dtnperf-server.c

Go to the documentation of this file.
00001 /* ----------------------
00002  *    dtnperf-server.c
00003  * ---------------------- */
00004 
00005 /* -----------------------------------------------------------
00006  *  PLEASE NOTE: this software was developed
00007  *    by Piero Cornice <piero.cornice@gmail.com>
00008  *    at DEIS - University of Bologna, Italy.
00009  *  If you want to modify it, please contact me
00010  *  at piero.cornice(at)gmail.com. Thanks =)
00011  * -----------------------------------------------------------
00012  */
00013 
00014 /* version 1.6.0 - 23/06/06
00015  *
00016  * - compatible with DTN 2.2.0 reference implementation
00017  */
00018 
00019 #include <stdio.h>
00020 #include <unistd.h>
00021 #include <errno.h>
00022 #include <strings.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <time.h>
00026 #include "dtn_api.h"
00027 
00028 #define BUFSIZE 16
00029 #define BUNDLE_DIR_DEFAULT "/var/lib/dtn/dtnperf"
00030 #define OUTFILE "dtnbuffer.rcv"
00031 
00032 /* ------------------------------
00033  *  Global variables and options
00034  * ------------------------------ */
00035 
00036 // values between [square braces] are default
00037 const char *progname   ;
00038 int use_file        = 1;        // if set to 0, memorize received bundles into memory (max 50000 bytes)
00039                                 // if set to 1, memorize received bundles into a file (-f) [0]
00040 int verbose         = 0;        // if set to 1, show verbose messages [0]
00041 int aggregate       = 0;        // if > 0, print after aggregate arrivals
00042 int debug           = 0;        // if set to 1, show debug messages [1]
00043 char * endpoint     = "/dtnperf:/dest";     // endpoint (-e) ["/dtnperf:/dest"]
00044 char * bundle_dir   = BUNDLE_DIR_DEFAULT;   // destination directory (-d)
00045 
00046 /* ------------------------
00047  *  Function Prototypes
00048  * ------------------------ */
00049 void print_usage(char*);
00050 void parse_options(int, char**);
00051 dtn_endpoint_id_t* parse_eid(dtn_handle_t, dtn_endpoint_id_t*, char*);
00052 
00053 
00054 /* -------------------------------------------------
00055  * main
00056  * ------------------------------------------------- */
00057 int main(int argc, char** argv)
00058 {
00059 
00060     /* -----------------------
00061      *  variables declaration
00062      * ----------------------- */
00063     int k;
00064     int ret;
00065     dtn_handle_t        handle;
00066     dtn_endpoint_id_t   local_eid;
00067     dtn_reg_info_t      reginfo;
00068     dtn_reg_id_t        regid;
00069     dtn_bundle_spec_t   spec;
00070     dtn_bundle_payload_t payload;
00071     char *buffer;                   // buffer used for shell commands
00072     char s_buffer[BUFSIZE];
00073     time_t current;
00074     dtn_bundle_payload_location_t pl_type = DTN_PAYLOAD_FILE; // payload saved into memory or into file
00075 //    char * source_region, dest_region;
00076     int source_eid_len, dest_eid_len;
00077     char *source_eid, *dest_eid;
00078     char * filepath;
00079     char * filename = OUTFILE;      // source filename [OUTFILE]
00080     int bufsize;
00081     int count = 0;
00082     int total = 0;
00083 
00084     /* -------
00085      *  begin
00086      * ------- */
00087 
00088     // print information header
00089     printf("\nDTNperf - SERVER - v 1.6.0");
00090     printf("\nwritten by Piero Cornice <piero.cornice@gmail.com>");
00091     printf("\nDEIS - University of Bologna, Italy");
00092     printf("\n");
00093 
00094     // parse command-line options
00095     parse_options(argc, argv);
00096     if (debug) printf("[debug] parsed command-line options\n");
00097 
00098     // show requested options (verbose)
00099     if (verbose) {
00100         printf("\nOptions:\n");
00101         printf("\tendpoint       : %s\n", endpoint);
00102         printf("\tsave bundles to: %s\n", use_file ? "file" : "memory");
00103         printf("\tdestination dir: %s\n", bundle_dir);
00104         printf("\n");
00105     }
00106 
00107     // initialize buffer with shell command ("mkdir -p " + bundle_dir)
00108     if (debug) printf("[debug] initializing buffer with shell command...");
00109     buffer = malloc(sizeof(char) * (strlen(bundle_dir) + 10));
00110     sprintf(buffer, "mkdir -p %s", bundle_dir);
00111     if (debug) printf(" done. Shell command = %s\n", buffer);
00112 
00113     // execute shell command
00114     if (debug) printf("[debug] executing shell command \"%s\"...", buffer);
00115     if (system(buffer) == -1)
00116     {
00117         fprintf(stderr, "Error opening bundle directory: %s\n", bundle_dir);
00118         exit(1);
00119     }
00120     free(buffer);
00121     if (debug) printf(" done\n");
00122 
00123     // open the ipc handle
00124     if (debug) printf("[debug] opening connection to dtn router...");
00125     int err = dtn_open(&handle);
00126     if (err != DTN_SUCCESS) {
00127         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00128                 dtn_strerror(err));
00129         exit(1);
00130     }
00131     if (debug) printf(" done\n");
00132 
00133     // build a local tuple based on the configuration of local dtn router
00134     if (debug) printf("[debug] building local eid...");
00135     dtn_build_local_eid(handle, &local_eid, endpoint);
00136     if (debug) printf(" done\n");
00137     if (verbose) printf("local_eid = %s\n", local_eid.uri);
00138 
00139     // create a new registration based on this eid
00140     if (debug) printf("[debug] registering to local daemon...");
00141     memset(&reginfo, 0, sizeof(reginfo));
00142     dtn_copy_eid(&reginfo.endpoint, &local_eid);
00143     reginfo.failure_action = DTN_REG_DEFER;
00144     reginfo.regid = DTN_REGID_NONE;
00145     reginfo.expiration = 0;
00146     if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00147         fprintf(stderr, "error creating registration: %d (%s)\n",
00148                 ret, dtn_strerror(dtn_errno(handle)));
00149         exit(1);
00150     }
00151     if (debug) printf(" done\n");
00152     if (verbose) printf("regid 0x%x\n", regid);
00153 
00154     // set bundle destination type
00155     if (debug) printf("[debug] choosing bundle destination type...");
00156     if (use_file)
00157         pl_type = DTN_PAYLOAD_FILE;
00158     else
00159         pl_type = DTN_PAYLOAD_MEM;
00160     if (debug) printf(" done. Bundles will be saved into %s\n", use_file ? "file" : "memory");
00161 
00162     if (debug) printf("[debug] entering infinite loop...\n");
00163 
00164     // infinite loop, waiting for bundles
00165     while (1) {
00166 
00167         // wait until receive a bundle
00168         memset(&spec, 0, sizeof(spec));
00169         memset(&payload, 0, sizeof(payload));
00170 
00171         if (debug) printf("[debug] waiting for bundles...");
00172         if ((ret = dtn_recv(handle, &spec, pl_type, &payload, -1)) < 0)
00173         {
00174             fprintf(stderr, "error getting recv reply: %d (%s)\n",
00175                     ret, dtn_strerror(dtn_errno(handle)));
00176             exit(1);
00177         }
00178         if (debug) printf(" bundle received\n");
00179         count++;
00180         total += payload.dtn_bundle_payload_t_u.buf.buf_len;
00181 
00182         // mark current time
00183         if (debug) printf("[debug] marking time...");
00184         current = time(NULL);
00185         if (debug) printf(" done\n");
00186 
00187         if (aggregate == 0) {
00188             printf("%s : %d bytes from %s\n",
00189                    ctime(&current),
00190                    payload.dtn_bundle_payload_t_u.buf.buf_len,
00191                    spec.source.uri);
00192         } else if (count % aggregate == 0) {
00193             printf("%s : %d bundles, total length %d bytes\n",
00194                    ctime(&current), count, total);
00195         }
00196 
00197         /* ---------------------------------------------------
00198          *  parse admin string to select file target location
00199          * --------------------------------------------------- */   
00200 
00201         // copy SOURCE eid
00202         if (debug) printf("[debug]\tcopying source eid...");
00203         source_eid_len = sizeof(spec.source.uri);
00204         source_eid = malloc(sizeof(char) * source_eid_len+1);
00205         memcpy(source_eid, spec.source.uri, source_eid_len);
00206         source_eid[source_eid_len] = '\0';
00207         if (debug) {
00208             printf(" done:\n");
00209             printf("\tsource_eid = %s\n", source_eid);
00210             printf("\n");
00211         }
00212 
00213         // copy DEST eid
00214         if (debug) printf("[debug]\tcopying dest eid...");
00215         dest_eid_len = sizeof(spec.dest.uri);
00216         dest_eid = malloc(sizeof(char) * dest_eid_len+1);
00217         memcpy(dest_eid, spec.dest.uri, dest_eid_len);
00218         dest_eid[dest_eid_len] = '\0';
00219         if (debug) {
00220             printf(" done:\n");
00221             printf("\tdest_eid = %s\n", dest_eid);
00222             printf("\n");
00223         }
00224 
00225         // recursively create full directory path
00226         filepath = malloc(sizeof(char) * dest_eid_len + 10);
00227         sprintf(filepath, "mkdir -p %s", bundle_dir);
00228         if (debug) printf("[debug] filepath = %s\n", filepath);
00229         system(filepath);
00230 
00231         // create file name
00232         sprintf(filepath, "%s/%s", bundle_dir, filename);
00233         if (debug) printf("[debug] filepath = %s\n", filepath);
00234 
00235         // bundle name is the name of the bundle payload file
00236         buffer = payload.dtn_bundle_payload_t_u.buf.buf_val;
00237         bufsize = payload.dtn_bundle_payload_t_u.buf.buf_len;
00238 
00239         if (debug) {
00240             printf ("======================================\n");
00241             printf (" Bundle received at %s\n", ctime(&current));
00242             printf ("  source: %s\n", spec.source.uri);
00243             if (use_file) {
00244                 printf ("  saved into    : %s\n", filepath);
00245             }
00246 
00247             printf ("--------------------------------------\n");
00248         }
00249 
00250         if (pl_type == DTN_PAYLOAD_FILE) { // if bundle was saved into file
00251 
00252             if (debug) printf("[debug] renaming file %s -> %s...", buffer, filepath);
00253             if (rename(buffer, filepath) != 0) {
00254                 printf("[ERROR] Couldn't rename %s -> %s: %s", buffer, filepath, strerror(errno));
00255             }
00256 
00257         } else { // if bundle was saved into memory
00258 
00259             if (debug) {
00260                 for (k=0; k < (int)payload.dtn_bundle_payload_t_u.buf.buf_len; k++)
00261                 {
00262                     if (buffer[k] >= ' ' && buffer[k] <= '~')
00263                         s_buffer[k%BUFSIZE] = buffer[k];
00264                     else
00265                         s_buffer[k%BUFSIZE] = '.';
00266 
00267                     if (k%BUFSIZE == 0) // new line every 16 bytes
00268                     {
00269                         printf("%07x ", k);
00270                     }
00271                     else if (k%2 == 0)
00272                     {
00273                         printf(" "); // space every 2 bytes
00274                     }
00275 
00276                     printf("%02x", buffer[k] & 0xff);
00277 
00278                     // print character summary (a la emacs hexl-mode)
00279                     if (k%BUFSIZE == BUFSIZE-1)
00280                     {
00281                         printf(" |  %.*s\n", BUFSIZE, s_buffer);
00282                     }
00283                 } // for
00284 
00285             // print spaces to fill out the rest of the line
00286             if (k%BUFSIZE != BUFSIZE-1) {
00287                     while (k%BUFSIZE != BUFSIZE-1) {
00288                         if (k%2 == 0) {
00289                             printf(" ");
00290                         }
00291                         printf("  ");
00292                         k++;
00293                     }
00294                     printf("   |  %.*s\n",
00295                            (int)payload.dtn_bundle_payload_t_u.buf.buf_len%BUFSIZE, s_buffer);
00296                 } // if
00297 
00298                 printf ("======================================\n");
00299  
00300             } // if (debug) 
00301 
00302             free(filepath);
00303             free(source_eid);
00304             free(dest_eid);
00305 
00306         }
00307 
00308         fflush(stdout);
00309 
00310     } // while(1)
00311 
00312     // if this was ever changed to gracefully shutdown, it would be good to call:
00313     dtn_close(handle);
00314 
00315     return 0;
00316 
00317 } //main
00318 
00319 /* -------------------------------
00320  *        Utility Functions
00321  * ------------------------------- */
00322 
00323 /* -------------
00324  *  print_usage
00325  * ------------- */
00326 void print_usage(char* progname)
00327 {
00328     fprintf(stderr, "\n");
00329     fprintf(stderr, "SYNTAX: %s [options]\n", progname);
00330     fprintf(stderr, "\n");
00331     fprintf(stderr, "options:\n");
00332     fprintf(stderr, " -d <dir>: destination directory (if using -f) \n");
00333     fprintf(stderr, "           [default destination dir: %s]\n", BUNDLE_DIR_DEFAULT);
00334     fprintf(stderr, " -D: many debug messages are shown\n");
00335     fprintf(stderr, " -m: save received bundles into memory\n");
00336     fprintf(stderr, " -h: shows this help\n");
00337     fprintf(stderr, " -v: verbose\n");
00338     fprintf(stderr, " -a <n>: print message every n arrivals\n");
00339     fprintf(stderr, "\n");
00340     exit(1);
00341 }
00342 
00343 /* ---------------
00344  *  parse_options
00345  * --------------- */
00346 void parse_options (int argc, char** argv) {
00347     char c, done = 0;
00348 
00349     while (!done) {
00350         c = getopt(argc, argv, "hvDfmd:e:a:");
00351 
00352         switch(c) {
00353             case 'h':           // show help
00354                 print_usage(argv[0]);
00355                 exit(1);
00356                 return;
00357             case 'v':           // verbose mode
00358                 verbose = 1;
00359                 break;
00360             case 'D':           // debug messages
00361                 debug = 1;
00362                 break;
00363             case 'm':           // save received bundles into memory
00364                 use_file = 0;
00365                 break;
00366             case 'd':           // destination directory
00367                 bundle_dir = optarg;
00368                 break;
00369 
00370             case 'e':           // destination endpoint
00371                 endpoint = optarg;
00372                 break;
00373 
00374             case 'a':           // aggregate
00375                 aggregate = atoi(optarg);
00376                 break;
00377 
00378             case -1:
00379                 done = 1;
00380                 break;
00381             default:
00382                 print_usage(argv[0]);
00383                 exit(1);
00384         }
00385     }
00386 
00387 #define CHECK_SET(_arg, _what)                                          \
00388     if (_arg == 0) {                                                    \
00389         fprintf(stderr, "\nSYNTAX ERROR: %s must be specified\n", _what);      \
00390         print_usage(argv[0]);                                                  \
00391         exit(1);                                                        \
00392     }
00393 
00394 }
00395 
00396 /* ----------------------------
00397  * parse_tuple
00398  * ---------------------------- */
00399 dtn_endpoint_id_t* parse_eid(dtn_handle_t handle, dtn_endpoint_id_t* eid, char * str)
00400 {
00401     // try the string as an actual dtn tuple
00402     if (!dtn_parse_eid_string(eid, str)) 
00403     {
00404         return eid;
00405     }
00406     // build a local tuple based on the configuration of our dtn
00407     // router plus the str as demux string
00408     else if (!dtn_build_local_eid(handle, eid, str))
00409     {
00410         if (verbose) fprintf(stdout, "%s (local)\n", str);
00411         return eid;
00412     }
00413     else
00414     {
00415         fprintf(stderr, "invalid eid string '%s'\n", str);
00416         exit(1);
00417     }
00418 } // end parse_tuple

Generated on Fri Dec 22 14:47:58 2006 for DTN Reference Implementation by  doxygen 1.5.1