dtnperf-server.c

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

Generated on Thu Jun 7 16:56:49 2007 for DTN Reference Implementation by  doxygen 1.5.1