dtnsend.c

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-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 #include <stdio.h>
00019 #include <unistd.h>
00020 #include <errno.h>
00021 #include <strings.h>
00022 #include <stdlib.h>
00023 #include <sys/time.h>
00024 #include <time.h>
00025 
00026 #include "dtn_api.h"
00027 
00028 char *progname;
00029 
00030 // global options
00031 dtn_bundle_payload_location_t 
00032 payload_type    = 0;    // the type of data source for the bundle
00033 int copies              = 1;    // the number of copies to send
00034 int verbose             = 0;
00035 int sleep_time          = 0;
00036 
00037 // bundle options
00038 int expiration          = 3600; // expiration timer (default one hour)
00039 int delivery_receipts   = 0;    // request end to end delivery receipts
00040 int delete_receipts     = 0;    // request deletion receipts
00041 int forwarding_receipts = 0;    // request per hop departure
00042 int custody             = 0;    // request custody transfer
00043 int custody_receipts    = 0;    // request per custodian receipts
00044 int receive_receipts    = 0;    // request per hop arrival receipt
00045 int overwrite           = 0;    // queue overwrite option
00046 int wait_for_report     = 0;    // wait for bundle status reports
00047 
00048 char * data_source      = NULL; // filename or message, depending on type
00049 char date_buf[256];             // buffer for date payloads
00050 
00051 // extension block information
00052 int extension_block     = 0;
00053 u_int block_type        = 0;
00054 u_int block_flags       = BLOCK_FLAG_NONE;
00055 char * block_buf        = NULL;
00056 
00057 // specified options for bundle eids
00058 char * arg_replyto      = NULL;
00059 char * arg_source       = NULL;
00060 char * arg_dest         = NULL;
00061 
00062 dtn_reg_id_t regid      = DTN_REGID_NONE;
00063 
00064 
00065 void parse_options(int, char**);
00066 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle,
00067                               dtn_endpoint_id_t * eid,
00068                               char * str);
00069 void print_usage();
00070 void print_eid(char * label, dtn_endpoint_id_t * eid);
00071 void fill_payload(dtn_bundle_payload_t* payload);
00072 
00073 int
00074 main(int argc, char** argv)
00075 {
00076     int i;
00077     int ret;
00078     dtn_handle_t handle;
00079     dtn_reg_info_t reginfo;
00080     dtn_bundle_spec_t bundle_spec;
00081     dtn_bundle_spec_t reply_spec;
00082     dtn_bundle_id_t bundle_id;
00083     dtn_bundle_payload_t send_payload;
00084     dtn_bundle_payload_t reply_payload;
00085     dtn_extension_block_t block;
00086     struct timeval start, end;
00087     
00088     // force stdout to always be line buffered, even if output is
00089     // redirected to a pipe or file
00090     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00091     
00092     parse_options(argc, argv);
00093 
00094     // open the ipc handle
00095     if (verbose) fprintf(stdout, "Opening connection to local DTN daemon\n");
00096 
00097     int err = dtn_open(&handle);
00098     if (err != DTN_SUCCESS) {
00099         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00100                 dtn_strerror(err));
00101         exit(1);
00102     }
00103 
00104     // initialize bundle spec
00105     memset(&bundle_spec, 0, sizeof(bundle_spec));
00106 
00107     // initialize/parse bundle src/dest/replyto eids
00108     if (verbose) fprintf(stdout, "Destination: %s\n", arg_dest);
00109     parse_eid(handle, &bundle_spec.dest, arg_dest);
00110 
00111     if (verbose) fprintf(stdout, "Source: %s\n", arg_source);
00112     parse_eid(handle, &bundle_spec.source, arg_source);
00113     if (arg_replyto == NULL) 
00114     {
00115         if (verbose) fprintf(stdout, "Reply To: same as source\n");
00116         dtn_copy_eid(&bundle_spec.replyto, &bundle_spec.source);
00117     }
00118     else
00119     {
00120         if (verbose) fprintf(stdout, "Reply To: %s\n", arg_replyto);
00121         parse_eid(handle, &bundle_spec.replyto, arg_replyto);
00122     }
00123 
00124     if (verbose)
00125     {
00126         print_eid("source_eid", &bundle_spec.source);
00127         print_eid("replyto_eid", &bundle_spec.replyto);
00128         print_eid("dest_eid", &bundle_spec.dest);
00129     }
00130 
00131     if (wait_for_report)
00132     {
00133         // create a new dtn registration to receive bundle status reports
00134         memset(&reginfo, 0, sizeof(reginfo));
00135         dtn_copy_eid(&reginfo.endpoint, &bundle_spec.replyto);
00136         reginfo.failure_action = DTN_REG_DROP;
00137         reginfo.regid = regid;
00138         reginfo.expiration = 60 * 60;
00139         if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00140             fprintf(stderr, "error creating registration (id=%d): %d (%s)\n",
00141                     regid, ret, dtn_strerror(dtn_errno(handle)));
00142             exit(1);
00143         }
00144         
00145         if (verbose) printf("dtn_register succeeded, regid 0x%x\n", regid);
00146     }
00147     
00148     // set the dtn options
00149     bundle_spec.expiration = expiration;
00150     
00151     if (delivery_receipts)
00152     {
00153         // set the delivery receipt option
00154         bundle_spec.dopts |= DOPTS_DELIVERY_RCPT;
00155     }
00156 
00157     if (delete_receipts)
00158     {
00159         // set the delivery receipt option
00160         bundle_spec.dopts |= DOPTS_DELETE_RCPT;
00161     }
00162 
00163     if (forwarding_receipts)
00164     {
00165         // set the forward receipt option
00166         bundle_spec.dopts |= DOPTS_FORWARD_RCPT;
00167     }
00168 
00169     if (custody)
00170     {
00171         // request custody transfer
00172         bundle_spec.dopts |= DOPTS_CUSTODY;
00173     }
00174 
00175     if (custody_receipts)
00176     {
00177         // request custody transfer
00178         bundle_spec.dopts |= DOPTS_CUSTODY_RCPT;
00179     }
00180 
00181     if (receive_receipts)
00182     {
00183         // request receive receipt
00184         bundle_spec.dopts |= DOPTS_RECEIVE_RCPT;
00185     }
00186     
00187     // set extension block information
00188     memset(&block, 0, sizeof(block));
00189     if (extension_block == 1) {
00190         block.type = block_type;
00191         block.flags = block_flags;
00192         block.data.data_len = strlen(block_buf);
00193         block.data.data_val = block_buf;
00194 
00195         bundle_spec.blocks.blocks_len = 1;
00196         bundle_spec.blocks.blocks_val = &block;
00197     }
00198     
00199     // loop, sending sends and getting replies.
00200     for (i = 0; i < copies; ++i) {
00201         gettimeofday(&start, NULL);
00202 
00203         fill_payload(&send_payload);
00204         
00205         memset(&bundle_id, 0, sizeof(bundle_id));
00206         
00207         if ((ret = dtn_send(handle, &bundle_spec, &send_payload,
00208                             &bundle_id)) != 0)
00209         {
00210             fprintf(stderr, "error sending bundle: %d (%s)\n",
00211                     ret, dtn_strerror(dtn_errno(handle)));
00212             exit(1);
00213         }
00214 
00215         if (verbose) fprintf(stdout, "bundle sent successfully: id %s,%u.%u\n",
00216                              bundle_id.source.uri,
00217                              bundle_id.creation_ts.secs,
00218                              bundle_id.creation_ts.seqno);
00219 
00220         if (wait_for_report)
00221         {
00222             memset(&reply_spec, 0, sizeof(reply_spec));
00223             memset(&reply_payload, 0, sizeof(reply_payload));
00224             
00225             // now we block waiting for any replies
00226             if ((ret = dtn_recv(handle, &reply_spec,
00227                                 DTN_PAYLOAD_MEM, &reply_payload, -1)) < 0)
00228             {
00229                 fprintf(stderr, "error getting reply: %d (%s)\n",
00230                         ret, dtn_strerror(dtn_errno(handle)));
00231                 exit(1);
00232             }
00233             gettimeofday(&end, NULL);
00234 
00235             printf("got %d byte report from [%s]: time=%.1f ms\n",
00236                    reply_payload.buf.buf_len,
00237                    reply_spec.source.uri,
00238                    ((double)(end.tv_sec - start.tv_sec) * 1000.0 + 
00239                     (double)(end.tv_usec - start.tv_usec)/1000.0));
00240         }
00241 
00242         if (sleep_time != 0) {
00243             usleep(sleep_time * 1000);
00244         }
00245     }
00246 
00247     dtn_close(handle);
00248  
00249     if (block_buf != NULL) {
00250         free(block_buf);
00251         block_buf = NULL;
00252     }
00253     
00254     return 0;
00255 }
00256 
00257 void print_usage()
00258 {
00259     fprintf(stderr, "usage: %s [opts] "
00260             "-s <source_eid> -d <dest_eid> -t <type> -p <payload>\n",
00261             progname);
00262     fprintf(stderr, "options:\n");
00263     fprintf(stderr, " -v verbose\n");
00264     fprintf(stderr, " -h help\n");
00265     fprintf(stderr, " -s <eid|demux_string> source eid)\n");
00266     fprintf(stderr, " -d <eid|demux_string> destination eid)\n");
00267     fprintf(stderr, " -r <eid|demux_string> reply to eid)\n");
00268     fprintf(stderr, " -t <f|t|m|d> payload type: file, tmpfile, message, or date\n");
00269     fprintf(stderr, " -p <filename|string> payload data\n");
00270     fprintf(stderr, " -e <time> expiration time in seconds (default: one hour)\n");
00271     fprintf(stderr, " -i <regid> registration id for reply to\n");
00272     fprintf(stderr, " -n <int> copies of the bundle to send\n");
00273     fprintf(stderr, " -z <time> msecs to sleep between transmissions\n");
00274     fprintf(stderr, " -c request custody transfer\n");
00275     fprintf(stderr, " -C request custody transfer receipts\n");
00276     fprintf(stderr, " -D request for end-to-end delivery receipt\n");
00277     fprintf(stderr, " -X request for deletion receipt\n");
00278     fprintf(stderr, " -R request for bundle reception receipts\n");
00279     fprintf(stderr, " -F request for bundle forwarding receipts\n");
00280     fprintf(stderr, " -w wait for bundle status reports\n");
00281     fprintf(stderr, " -E <int> include extension block and specify type\n");
00282     fprintf(stderr, " -P <int> flag value(s) to include in extension block\n");
00283     fprintf(stderr, " -S <string> extension block content\n");
00284     
00285     exit(1);
00286 }
00287 
00288 void parse_options(int argc, char**argv)
00289 {
00290     char c, done = 0;
00291     char arg_type = 0;
00292 
00293     progname = argv[0];
00294 
00295     while (!done)
00296     {
00297         c = getopt(argc, argv, "vhHr:s:d:e:n:woDXFRcCt:p:i:z:E:P:S:");
00298         switch (c)
00299         {
00300         case 'v':
00301             verbose = 1;
00302             break;
00303         case 'h':
00304         case 'H':
00305             print_usage();
00306             exit(0);
00307             return;
00308         case 'r':
00309             arg_replyto = optarg;
00310             break;
00311         case 's':
00312             arg_source = optarg;
00313             break;
00314         case 'd':
00315             arg_dest = optarg;
00316             break;
00317         case 'e':
00318             expiration = atoi(optarg);
00319             break;
00320         case 'n':
00321             copies = atoi(optarg);
00322             break;
00323         case 'w':
00324             wait_for_report = 1;
00325             break;
00326         case 'D':
00327             delivery_receipts = 1;
00328             break;
00329         case 'X':
00330             delete_receipts = 1;
00331             break;
00332         case 'F':
00333             forwarding_receipts = 1;
00334             break;
00335         case 'R':
00336             receive_receipts = 1;
00337             break;
00338         case 'c':
00339             custody = 1;
00340             break;
00341         case 'C':
00342             custody_receipts = 1;
00343             break;
00344         case 't':
00345             arg_type = optarg[0];
00346             break;
00347         case 'p':
00348             data_source = strdup(optarg);
00349             break;
00350         case 'i':
00351             regid = atoi(optarg);
00352             break;
00353         case 'z':
00354             sleep_time = atoi(optarg);
00355             break;
00356         case 'E':
00357             extension_block = 1;
00358             block_type = atoi(optarg);
00359             break;
00360         case 'P':
00361             block_flags = atoi(optarg);
00362             break;
00363         case 'S':
00364             block_buf = strdup(optarg);
00365             break;
00366         case -1:
00367             done = 1;
00368             break;
00369         default:
00370             // getopt already prints an error message for unknown
00371             // option characters
00372             print_usage();
00373             exit(1);
00374         }
00375     }
00376 
00377 #define CHECK_SET(_arg, _what)                                          \
00378     if (_arg == 0) {                                                    \
00379         fprintf(stderr, "dtnsend: %s must be specified\n", _what);      \
00380         print_usage();                                                  \
00381         exit(1);                                                        \
00382     }
00383     
00384     CHECK_SET(arg_source,   "source eid");
00385     CHECK_SET(arg_dest,     "destination eid");
00386     CHECK_SET(arg_type,     "payload type");
00387     if (arg_type != 'd') {
00388         CHECK_SET(data_source,  "payload data");
00389     }
00390 
00391     switch (arg_type)
00392     {
00393     case 'f': payload_type = DTN_PAYLOAD_FILE; break;
00394     case 't': payload_type = DTN_PAYLOAD_TEMP_FILE; break;
00395     case 'm': payload_type = DTN_PAYLOAD_MEM; break;
00396     case 'd': 
00397         payload_type = DTN_PAYLOAD_MEM;
00398         data_source = date_buf;
00399         break;
00400     default:
00401         fprintf(stderr, "dtnsend: type argument '%d' invalid\n", arg_type);
00402         print_usage();
00403         exit(1);
00404     }
00405 
00406     if (extension_block == 1) {
00407         if (block_type > 255) {
00408             fprintf(stderr, "dtnsend: invalid block type %d\n", block_type);
00409             print_usage();
00410             exit(1);
00411         }
00412 
00413         if (block_flags > 255) {
00414             fprintf(stderr, "dtnsend: invalid block flags %d\n", block_flags);
00415             print_usage();
00416             exit(1);
00417         }
00418     }
00419 }
00420 
00421 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle, 
00422                               dtn_endpoint_id_t* eid, char * str)
00423 {
00424     // try the string as an actual dtn eid
00425     if (!dtn_parse_eid_string(eid, str)) 
00426     {
00427         if (verbose) fprintf(stdout, "%s (literal)\n", str);
00428         return eid;
00429     }
00430     // build a local eid based on the configuration of our dtn
00431     // router plus the str as demux string
00432     else if (!dtn_build_local_eid(handle, eid, str))
00433     {
00434         if (verbose) fprintf(stdout, "%s (local)\n", str);
00435         return eid;
00436     }
00437     else
00438     {
00439         fprintf(stderr, "invalid eid string '%s'\n", str);
00440         exit(1);
00441     }
00442 }
00443 
00444 void print_eid(char *  label, dtn_endpoint_id_t * eid)
00445 {
00446     printf("%s [%s]\n", label, eid->uri);
00447 }
00448 
00449 void fill_payload(dtn_bundle_payload_t* payload) {
00450 
00451     if (data_source == date_buf) {
00452         time_t current = time(NULL);
00453         strcpy(date_buf, ctime(&current));
00454     }
00455 
00456     memset(payload, 0, sizeof(*payload));
00457     dtn_set_payload(payload, payload_type, data_source, strlen(data_source));
00458 }

Generated on Sat Sep 8 08:36:16 2007 for DTN Reference Implementation by  doxygen 1.5.3