dtnrecv.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 <string.h>
00044 #include <stdlib.h>
00045 #include <sys/time.h>
00046 #include "dtn_api.h"
00047 
00048 #define BUFSIZE 16
00049 
00050 const char *progname;
00051 
00052 int   verbose           = 0;            // verbose output
00053 int   quiet             = 0;            // quiet output
00054 char* endpoint          = NULL;         // endpoint for registration
00055 dtn_reg_id_t regid      = DTN_REGID_NONE;// registration id
00056 int   expiration        = 30;           // registration expiration time
00057 int   count             = 0;            // exit after count bundles received
00058 int   failure_action    = DTN_REG_DEFER;// registration delivery failure action
00059 char* failure_script    = "";           // script to exec
00060 int   register_only     = 0;            // register and quit
00061 int   change            = 0;            // change existing registration 
00062 int   unregister        = 0;            // remove existing registration 
00063 int   recv_timeout      = -1;           // timeout to dtn_recv call
00064 int   no_find_reg       = 0;            // omit call to dtn_find_registration
00065 
00066 void
00067 usage()
00068 {
00069     fprintf(stderr, "usage: %s [opts] <endpoint> \n", progname);
00070     fprintf(stderr, "options:\n");
00071     fprintf(stderr, " -v verbose\n");
00072     fprintf(stderr, " -q quiet\n");
00073     fprintf(stderr, " -h help\n");
00074     fprintf(stderr, " -d <eid|demux_string> endpoint id\n");
00075     fprintf(stderr, " -r <regid> use existing registration regid\n");
00076     fprintf(stderr, " -n <count> exit after count bundles received\n");
00077     fprintf(stderr, " -e <time> registration expiration time in seconds "
00078             "(default: one hour)\n");
00079     fprintf(stderr, " -f <defer|drop|exec> failure action\n");
00080     fprintf(stderr, " -F <script> failure script for exec action\n");
00081     fprintf(stderr, " -x call dtn_register and immediately exit\n");
00082     fprintf(stderr, " -c call dtn_change_registration and immediately exit\n");
00083     fprintf(stderr, " -u call dtn_unregister and immediately exit\n");
00084     fprintf(stderr, " -N don't try to find an existing registration\n");
00085     fprintf(stderr, " -t <timeout> timeout value for call to dtn_recv\n");
00086 }
00087 
00088 void
00089 parse_options(int argc, char**argv)
00090 {
00091     char c, done = 0;
00092 
00093     progname = argv[0];
00094 
00095     while (!done)
00096     {
00097         c = getopt(argc, argv, "vqhHd:r:e:f:F:xn:cuNt:");
00098         switch (c)
00099         {
00100         case 'v':
00101             verbose = 1;
00102             break;
00103         case 'q':
00104             quiet = 1;
00105             break;
00106         case 'h':
00107         case 'H':
00108             usage();
00109             exit(0);
00110             return;
00111         case 'r':
00112             regid = atoi(optarg);
00113             break;
00114         case 'e':
00115             expiration = atoi(optarg);
00116             break;
00117         case 'f':
00118             if (!strcasecmp(optarg, "defer")) {
00119                 failure_action = DTN_REG_DEFER;
00120 
00121             } else if (!strcasecmp(optarg, "drop")) {
00122                 failure_action = DTN_REG_DROP;
00123 
00124             } else if (!strcasecmp(optarg, "exec")) {
00125                 failure_action = DTN_REG_EXEC;
00126 
00127             } else {
00128                 fprintf(stderr, "invalid failure action '%s'\n", optarg);
00129                 usage();
00130                 exit(1);
00131             }
00132         case 'F':
00133             failure_script = optarg;
00134             break;
00135         case 'x':
00136             register_only = 1;
00137             break;
00138         case 'n':
00139             count = atoi(optarg);
00140             break;
00141         case 'c':
00142             change = 1;
00143             break;
00144         case 'u':
00145             unregister = 1;
00146             break;
00147         case 'N':
00148             no_find_reg = 1;
00149             break;
00150         case 't':
00151             recv_timeout = atoi(optarg);
00152             break;
00153         case -1:
00154             done = 1;
00155             break;
00156         default:
00157             // getopt already prints an error message for unknown
00158             // option characters
00159             usage();
00160             exit(1);
00161         }
00162     }
00163 
00164     endpoint = argv[optind];
00165     if (!endpoint && (regid == DTN_REGID_NONE)) {
00166         fprintf(stderr, "must specify either an endpoint or a regid\n");
00167         usage();
00168         exit(1);
00169     }
00170 
00171     if ((change || unregister) && (regid == DTN_REGID_NONE)) {
00172         fprintf(stderr, "must specify regid when using -%c option\n",
00173                 change ? 'c' : 'u');
00174         usage();
00175         exit(1);
00176     }
00177 
00178     if (failure_action == DTN_REG_EXEC && failure_script == NULL) {
00179         fprintf(stderr, "failure action EXEC must supply script\n");
00180         usage();
00181         exit(1);
00182     }
00183 }
00184 
00185 
00186 int
00187 main(int argc, char** argv)
00188 {
00189     int i;
00190     u_int k;
00191     int ret;
00192     int total_bytes = 0;
00193     dtn_handle_t handle;
00194     dtn_endpoint_id_t local_eid;
00195     dtn_reg_info_t reginfo;
00196     dtn_bundle_spec_t spec;
00197     dtn_bundle_payload_t payload;
00198     unsigned char* buffer;
00199     char s_buffer[BUFSIZE];
00200     int call_bind;
00201 
00202     // force stdout to always be line buffered, even if output is
00203     // redirected to a pipe or file
00204     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00205     
00206     progname = argv[0];
00207 
00208     parse_options(argc, argv);
00209 
00210     if (count == 0) { 
00211         printf("dtnrecv (pid %d) starting up\n", getpid());
00212     } else {
00213         printf("dtnrecv (pid %d) starting up -- count %u\n", getpid(), count);
00214     }
00215 
00216     // open the ipc handle
00217     if (verbose) printf("opening connection to dtn router...\n");
00218     int err = dtn_open(&handle);
00219     if (err != DTN_SUCCESS) {
00220         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00221                 dtn_strerror(err));
00222         exit(1);
00223     }
00224     if (verbose) printf("opened connection to dtn router...\n");
00225 
00226     // if we're not given a regid, or we're in change mode, we need to
00227     // build up the reginfo
00228     memset(&reginfo, 0, sizeof(reginfo));
00229 
00230     if ((regid == DTN_REGID_NONE) || change)
00231     {
00232         // if the specified eid starts with '/', then build a local
00233         // eid based on the configuration of our dtn router plus the
00234         // demux string. otherwise make sure it's a valid one
00235         if (endpoint[0] == '/') {
00236             if (verbose) printf("calling dtn_build_local_eid.\n");
00237             dtn_build_local_eid(handle, &local_eid, (char *) endpoint);
00238             if (verbose) printf("local_eid [%s]\n", local_eid.uri);
00239         } else {
00240             if (verbose) printf("calling parse_eid_string\n");
00241             if (dtn_parse_eid_string(&local_eid, endpoint)) {
00242                 fprintf(stderr, "invalid destination endpoint '%s'\n",
00243                         endpoint);
00244                 goto err;
00245             }
00246         }
00247 
00248         // create a new registration based on this eid
00249         dtn_copy_eid(&reginfo.endpoint, &local_eid);
00250         reginfo.regid             = regid;
00251         reginfo.expiration        = expiration;
00252         reginfo.failure_action    = failure_action;
00253         reginfo.script.script_val = failure_script;
00254         reginfo.script.script_len = strlen(failure_script) + 1;
00255     }
00256 
00257     if (change) {
00258         if ((ret = dtn_change_registration(handle, regid, &reginfo)) != 0) {
00259             fprintf(stderr, "error changing registration: %d (%s)\n",
00260                     ret, dtn_strerror(dtn_errno(handle)));
00261             goto err;
00262         }
00263         printf("change registration succeeded, regid %d\n", regid);
00264         goto done;
00265     }
00266     
00267     if (unregister) {
00268         if (dtn_unregister(handle, regid) != 0) {
00269             fprintf(stderr, "error in unregister regid %d: %s\n",
00270                     regid, dtn_strerror(dtn_errno(handle)));
00271             goto err;
00272         }
00273         
00274         printf("unregister succeeded, regid %d\n", regid);
00275         goto done;
00276     }
00277     
00278     // try to see if there is an existing registration that matches
00279     // the given endpoint, in which case we'll use that one.
00280     if (regid == DTN_REGID_NONE && ! no_find_reg) {
00281         if (dtn_find_registration(handle, &local_eid, &regid) != 0) {
00282             if (dtn_errno(handle) != DTN_ENOTFOUND) {
00283                 fprintf(stderr, "error in find_registration: %s\n",
00284                         dtn_strerror(dtn_errno(handle)));
00285                 goto err;
00286             }
00287         }
00288         printf("find registration succeeded, regid %d\n", regid);
00289         call_bind = 1;
00290     }
00291     
00292     // if the user didn't give us a registration to use, get a new one
00293     if (regid == DTN_REGID_NONE) {
00294         if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00295             fprintf(stderr, "error creating registration: %d (%s)\n",
00296                     ret, dtn_strerror(dtn_errno(handle)));
00297             goto err;
00298         }
00299 
00300         printf("register succeeded, regid %d\n", regid);
00301         call_bind = 0;
00302     } else {
00303         call_bind = 1;
00304     }
00305     
00306     if (register_only) {
00307         goto done;
00308     }
00309 
00310     if (call_bind) {
00311         // bind the current handle to the found registration
00312         printf("binding to regid %d\n", regid);
00313         if (dtn_bind(handle, regid) != 0) {
00314             fprintf(stderr, "error binding to registration: %s\n",
00315                     dtn_strerror(dtn_errno(handle)));
00316             goto err;
00317         }
00318     }
00319 
00320     // loop waiting for bundles
00321     for (i = 0; (count == 0) || (i < count); ++i) {
00322         memset(&spec, 0, sizeof(spec));
00323         memset(&payload, 0, sizeof(payload));
00324 
00325         if (!quiet) {
00326             printf("dtn_recv [%s]...\n", local_eid.uri);
00327         }
00328     
00329         if ((ret = dtn_recv(handle, &spec,
00330                             DTN_PAYLOAD_MEM, &payload, recv_timeout)) < 0)
00331         {
00332             fprintf(stderr, "error getting recv reply: %d (%s)\n",
00333                     ret, dtn_strerror(dtn_errno(handle)));
00334             goto err;
00335         }
00336 
00337         total_bytes += payload.dtn_bundle_payload_t_u.buf.buf_len;
00338 
00339         if (quiet) {
00340             dtn_free_payload(&payload);
00341             continue;
00342         }
00343         
00344         printf("%d bytes from [%s]: transit time=%d ms\n",
00345                payload.dtn_bundle_payload_t_u.buf.buf_len,
00346                spec.source.uri, 0);
00347 
00348         buffer = (unsigned char *) payload.dtn_bundle_payload_t_u.buf.buf_val;
00349         for (k=0; k < payload.dtn_bundle_payload_t_u.buf.buf_len; k++)
00350         {
00351             if (buffer[k] >= ' ' && buffer[k] <= '~')
00352                 s_buffer[k%BUFSIZE] = buffer[k];
00353             else
00354                 s_buffer[k%BUFSIZE] = '.';
00355 
00356             if (k%BUFSIZE == 0) // new line every 16 bytes
00357             {
00358                 printf("%07x ", k);
00359             }
00360             else if (k%2 == 0)
00361             {
00362                 printf(" "); // space every 2 bytes
00363             }
00364                     
00365             printf("%02x", buffer[k] & 0xff);
00366                     
00367             // print character summary (a la emacs hexl-mode)
00368             if (k%BUFSIZE == BUFSIZE-1)
00369             {
00370                 printf(" |  %.*s\n", BUFSIZE, s_buffer);
00371             }
00372         }
00373 
00374         // print spaces to fill out the rest of the line
00375         if (k%BUFSIZE != BUFSIZE-1) {
00376             while (k%BUFSIZE != BUFSIZE-1) {
00377                 if (k%2 == 0) {
00378                     printf(" ");
00379                 }
00380                 printf("  ");
00381                 k++;
00382             }
00383             printf("   |  %.*s\n",
00384               (int)payload.dtn_bundle_payload_t_u.buf.buf_len%BUFSIZE, 
00385                    s_buffer);
00386         }
00387         printf("\n");
00388 
00389         dtn_free_payload(&payload);
00390     }
00391 
00392     printf("dtnrecv (pid %d) exiting: %d bundles received, %d total bytes\n\n",
00393            getpid(), i, total_bytes);
00394 
00395  done:
00396     dtn_close(handle);
00397     return 0;
00398 
00399  err:
00400     dtn_close(handle);
00401     return 1;
00402 }

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