dtnsend.c

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include <stdio.h>
00040 #include <unistd.h>
00041 #include <errno.h>
00042 #include <strings.h>
00043 #include <stdlib.h>
00044 #include <sys/time.h>
00045 #include <time.h>
00046 
00047 #include "dtn_api.h"
00048 
00049 char *progname;
00050 
00051 // global options
00052 dtn_bundle_payload_location_t 
00053 payload_type    = 0;    // the type of data source for the bundle
00054 int copies              = 1;    // the number of copies to send
00055 int verbose             = 0;
00056 int sleep_time          = 0;
00057 
00058 // bundle options
00059 int expiration          = 3600; // expiration timer (default one hour)
00060 int delivery_receipts   = 0;    // request end to end delivery receipts
00061 int forwarding_receipts = 0;    // request per hop departure
00062 int custody             = 0;    // request custody transfer
00063 int custody_receipts    = 0;    // request per custodian receipts
00064 int receive_receipts    = 0;    // request per hop arrival receipt
00065 int overwrite           = 0;    // queue overwrite option
00066 int wait_for_report     = 0;    // wait for bundle status reports
00067 
00068 char * data_source      = NULL; // filename or message, depending on type
00069 char date_buf[256];             // buffer for date payloads
00070 
00071 // specified options for bundle eids
00072 char * arg_replyto      = NULL;
00073 char * arg_source       = NULL;
00074 char * arg_dest         = NULL;
00075 
00076 dtn_reg_id_t regid      = DTN_REGID_NONE;
00077 
00078 
00079 void parse_options(int, char**);
00080 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle,
00081                               dtn_endpoint_id_t * eid,
00082                               char * str);
00083 void print_usage();
00084 void print_eid(char * label, dtn_endpoint_id_t * eid);
00085 void fill_payload(dtn_bundle_payload_t* payload);
00086 
00087 int
00088 main(int argc, char** argv)
00089 {
00090     int i;
00091     int ret;
00092     dtn_handle_t handle;
00093     dtn_reg_info_t reginfo;
00094     dtn_bundle_spec_t bundle_spec;
00095     dtn_bundle_spec_t reply_spec;
00096     dtn_bundle_id_t bundle_id;
00097     dtn_bundle_payload_t send_payload;
00098     dtn_bundle_payload_t reply_payload;
00099     struct timeval start, end;
00100     
00101     // force stdout to always be line buffered, even if output is
00102     // redirected to a pipe or file
00103     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00104     
00105     parse_options(argc, argv);
00106 
00107     // open the ipc handle
00108     if (verbose) fprintf(stdout, "Opening connection to local DTN daemon\n");
00109 
00110     int err = dtn_open(&handle);
00111     if (err != DTN_SUCCESS) {
00112         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00113                 dtn_strerror(err));
00114         exit(1);
00115     }
00116 
00117     // initialize bundle spec
00118     memset(&bundle_spec, 0, sizeof(bundle_spec));
00119 
00120     // initialize/parse bundle src/dest/replyto eids
00121     if (verbose) fprintf(stdout, "Destination: %s\n", arg_dest);
00122     parse_eid(handle, &bundle_spec.dest, arg_dest);
00123 
00124     if (verbose) fprintf(stdout, "Source: %s\n", arg_source);
00125     parse_eid(handle, &bundle_spec.source, arg_source);
00126     if (arg_replyto == NULL) 
00127     {
00128         if (verbose) fprintf(stdout, "Reply To: same as source\n");
00129         dtn_copy_eid(&bundle_spec.replyto, &bundle_spec.source);
00130     }
00131     else
00132     {
00133         if (verbose) fprintf(stdout, "Reply To: %s\n", arg_replyto);
00134         parse_eid(handle, &bundle_spec.replyto, arg_replyto);
00135     }
00136 
00137     if (verbose)
00138     {
00139         print_eid("source_eid", &bundle_spec.source);
00140         print_eid("replyto_eid", &bundle_spec.replyto);
00141         print_eid("dest_eid", &bundle_spec.dest);
00142     }
00143 
00144     if (wait_for_report)
00145     {
00146         // create a new dtn registration to receive bundle status reports
00147         memset(&reginfo, 0, sizeof(reginfo));
00148         dtn_copy_eid(&reginfo.endpoint, &bundle_spec.replyto);
00149         reginfo.failure_action = DTN_REG_DROP;
00150         reginfo.regid = regid;
00151         reginfo.expiration = 60 * 60;
00152         if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00153             fprintf(stderr, "error creating registration (id=%d): %d (%s)\n",
00154                     regid, ret, dtn_strerror(dtn_errno(handle)));
00155             exit(1);
00156         }
00157         
00158         if (verbose) printf("dtn_register succeeded, regid 0x%x\n", regid);
00159     }
00160     
00161     // set the dtn options
00162     bundle_spec.expiration = expiration;
00163     
00164     if (delivery_receipts)
00165     {
00166         // set the delivery receipt option
00167         bundle_spec.dopts |= DOPTS_DELIVERY_RCPT;
00168     }
00169 
00170     if (forwarding_receipts)
00171     {
00172         // set the forward receipt option
00173         bundle_spec.dopts |= DOPTS_FORWARD_RCPT;
00174     }
00175 
00176     if (custody)
00177     {
00178         // request custody transfer
00179         bundle_spec.dopts |= DOPTS_CUSTODY;
00180     }
00181 
00182     if (custody_receipts)
00183     {
00184         // request custody transfer
00185         bundle_spec.dopts |= DOPTS_CUSTODY_RCPT;
00186     }
00187 
00188     if (receive_receipts)
00189     {
00190         // request receive receipt
00191         bundle_spec.dopts |= DOPTS_RECEIVE_RCPT;
00192     }
00193     
00194     // loop, sending sends and getting replies.
00195     for (i = 0; i < copies; ++i) {
00196         gettimeofday(&start, NULL);
00197 
00198         fill_payload(&send_payload);
00199         
00200         memset(&bundle_id, 0, sizeof(bundle_id));
00201         
00202         if ((ret = dtn_send(handle, &bundle_spec, &send_payload,
00203                             &bundle_id)) != 0)
00204         {
00205             fprintf(stderr, "error sending bundle: %d (%s)\n",
00206                     ret, dtn_strerror(dtn_errno(handle)));
00207             exit(1);
00208         }
00209 
00210         if (verbose) fprintf(stdout, "bundle sent successfully: id %s,%u.%u\n",
00211                              bundle_id.source.uri,
00212                              bundle_id.creation_secs,
00213                              bundle_id.creation_subsecs);
00214 
00215         if (wait_for_report)
00216         {
00217             memset(&reply_spec, 0, sizeof(reply_spec));
00218             memset(&reply_payload, 0, sizeof(reply_payload));
00219             
00220             // now we block waiting for any replies
00221             if ((ret = dtn_recv(handle, &reply_spec,
00222                                 DTN_PAYLOAD_MEM, &reply_payload, -1)) < 0)
00223             {
00224                 fprintf(stderr, "error getting reply: %d (%s)\n",
00225                         ret, dtn_strerror(dtn_errno(handle)));
00226                 exit(1);
00227             }
00228             gettimeofday(&end, NULL);
00229 
00230             printf("got %d byte report from [%s]: time=%.1f ms\n",
00231                    reply_payload.dtn_bundle_payload_t_u.buf.buf_len,
00232                    reply_spec.source.uri,
00233                    ((double)(end.tv_sec - start.tv_sec) * 1000.0 + 
00234                     (double)(end.tv_usec - start.tv_usec)/1000.0));
00235         }
00236 
00237         if (sleep_time != 0) {
00238             usleep(sleep_time * 1000);
00239         }
00240     }
00241 
00242     dtn_close(handle);
00243     
00244     return 0;
00245 }
00246 
00247 void print_usage()
00248 {
00249     fprintf(stderr, "usage: %s [opts] "
00250             "-s <source_eid> -d <dest_eid> -t <type> -p <payload>\n",
00251             progname);
00252     fprintf(stderr, "options:\n");
00253     fprintf(stderr, " -v verbose\n");
00254     fprintf(stderr, " -h help\n");
00255     fprintf(stderr, " -s <eid|demux_string> source eid)\n");
00256     fprintf(stderr, " -d <eid|demux_string> destination eid)\n");
00257     fprintf(stderr, " -r <eid|demux_string> reply to eid)\n");
00258     fprintf(stderr, " -t <f|m|d> payload type: file, message, or date\n");
00259     fprintf(stderr, " -p <filename|string> payload data\n");
00260     fprintf(stderr, " -e <time> expiration time in seconds (default: one hour)\n");
00261     fprintf(stderr, " -i <regid> registration id for reply to\n");
00262     fprintf(stderr, " -n <int> copies of the bundle to send\n");
00263     fprintf(stderr, " -z <time> msecs to sleep between transmissions\n");
00264     fprintf(stderr, " -c request custody transfer\n");
00265     fprintf(stderr, " -C request custody transfer receipts\n");
00266     fprintf(stderr, " -D request for end-to-end delivery receipt\n");
00267     fprintf(stderr, " -R request for bundle reception receipts\n");
00268     fprintf(stderr, " -F request for bundle forwarding receipts\n");
00269     fprintf(stderr, " -w wait for bundle status reports\n");
00270     
00271     exit(1);
00272 }
00273 
00274 void parse_options(int argc, char**argv)
00275 {
00276     char c, done = 0;
00277     char arg_type = 0;
00278 
00279     progname = argv[0];
00280 
00281     while (!done)
00282     {
00283         c = getopt(argc, argv, "vhHr:s:d:e:n:woDFRcCt:p:i:z:");
00284         switch (c)
00285         {
00286         case 'v':
00287             verbose = 1;
00288             break;
00289         case 'h':
00290         case 'H':
00291             print_usage();
00292             exit(0);
00293             return;
00294         case 'r':
00295             arg_replyto = optarg;
00296             break;
00297         case 's':
00298             arg_source = optarg;
00299             break;
00300         case 'd':
00301             arg_dest = optarg;
00302             break;
00303         case 'e':
00304             expiration = atoi(optarg);
00305             break;
00306         case 'n':
00307             copies = atoi(optarg);
00308             break;
00309         case 'w':
00310             wait_for_report = 1;
00311             break;
00312         case 'D':
00313             delivery_receipts = 1;
00314             break;
00315         case 'F':
00316             forwarding_receipts = 1;
00317             break;
00318         case 'R':
00319             receive_receipts = 1;
00320             break;
00321         case 'c':
00322             custody = 1;
00323             break;
00324         case 'C':
00325             custody_receipts = 1;
00326             break;
00327         case 't':
00328             arg_type = optarg[0];
00329             break;
00330         case 'p':
00331             data_source = strdup(optarg);
00332             break;
00333         case 'i':
00334             regid = atoi(optarg);
00335             break;
00336         case 'z':
00337             sleep_time = atoi(optarg);
00338             break;
00339         case -1:
00340             done = 1;
00341             break;
00342         default:
00343             // getopt already prints an error message for unknown
00344             // option characters
00345             print_usage();
00346             exit(1);
00347         }
00348     }
00349 
00350 #define CHECK_SET(_arg, _what)                                          \
00351     if (_arg == 0) {                                                    \
00352         fprintf(stderr, "dtnsend: %s must be specified\n", _what);      \
00353         print_usage();                                                  \
00354         exit(1);                                                        \
00355     }
00356     
00357     CHECK_SET(arg_source,   "source eid");
00358     CHECK_SET(arg_dest,     "destination eid");
00359     CHECK_SET(arg_type,     "payload type");
00360     if (arg_type != 'd') {
00361         CHECK_SET(data_source,  "payload data");
00362     }
00363 
00364     switch (arg_type)
00365     {
00366     case 'f': payload_type = DTN_PAYLOAD_FILE; break;
00367     case 'm': payload_type = DTN_PAYLOAD_MEM; break;
00368     case 'd': 
00369         payload_type = DTN_PAYLOAD_MEM;
00370         data_source = date_buf;
00371         break;
00372     default:
00373         fprintf(stderr, "dtnsend: type argument '%d' invalid\n", arg_type);
00374         print_usage();
00375         exit(1);
00376     }
00377 }
00378 
00379 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle, 
00380                               dtn_endpoint_id_t* eid, char * str)
00381 {
00382     // try the string as an actual dtn eid
00383     if (!dtn_parse_eid_string(eid, str)) 
00384     {
00385         if (verbose) fprintf(stdout, "%s (literal)\n", str);
00386         return eid;
00387     }
00388     // build a local eid based on the configuration of our dtn
00389     // router plus the str as demux string
00390     else if (!dtn_build_local_eid(handle, eid, str))
00391     {
00392         if (verbose) fprintf(stdout, "%s (local)\n", str);
00393         return eid;
00394     }
00395     else
00396     {
00397         fprintf(stderr, "invalid eid string '%s'\n", str);
00398         exit(1);
00399     }
00400 }
00401 
00402 void print_eid(char *  label, dtn_endpoint_id_t * eid)
00403 {
00404     printf("%s [%s]\n", label, eid->uri);
00405 }
00406 
00407 void fill_payload(dtn_bundle_payload_t* payload) {
00408 
00409     if (data_source == date_buf) {
00410         time_t current = time(NULL);
00411         strcpy(date_buf, ctime(&current));
00412     }
00413 
00414     memset(payload, 0, sizeof(*payload));
00415     dtn_set_payload(payload, payload_type, data_source, strlen(data_source));
00416 }

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