apps/dtncat/dtncat.c
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2006 Intel Corporation
       
     3  * 
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  * 
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  * 
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 
       
    18 /*
       
    19  * dtncat: move stdin to bundles and vice-versa
       
    20  * resembles the nc (netcat) unix program
       
    21  * - kfall Apr 2006
       
    22  *
       
    23  *   Usage: dtncat [-options] -s EID -d EID
       
    24  *   dtncat -l -s EID -d EID
       
    25  */
       
    26 
       
    27 #ifdef HAVE_CONFIG_H
       
    28 #  include <dtn-config.h>
       
    29 #endif
       
    30 
       
    31 #include <stdio.h>
       
    32 #include <unistd.h>
       
    33 #include <errno.h>
       
    34 #include <strings.h>
       
    35 #include <string.h>
       
    36 #include <stdlib.h>
       
    37 #include <sys/time.h>
       
    38 #include <time.h>
       
    39 
       
    40 #include "dtn_api.h"
       
    41 
       
    42 char *progname;
       
    43 
       
    44 // global options
       
    45 int copies              = 1;    // the number of copies to send
       
    46 int verbose             = 0;
       
    47 
       
    48 // bundle options
       
    49 int expiration          = 3600; // expiration timer (default one hour)
       
    50 int delivery_receipts   = 0;    // request end to end delivery receipts
       
    51 int forwarding_receipts = 0;    // request per hop departure
       
    52 int custody             = 0;    // request custody transfer
       
    53 int custody_receipts    = 0;    // request per custodian receipts
       
    54 int receive_receipts    = 0;    // request per hop arrival receipt
       
    55 int wait_for_report     = 0;    // wait for bundle status reports
       
    56 int bundle_count	= -1;	// # bundles to receive (-l option)
       
    57 int session_flags       = 0;    // use pub/sub session flags
       
    58 char* sequence_id       = 0;    // use the given sequence id
       
    59 char* obsoletes_id      = 0;    // use the given obsoletes id
       
    60 
       
    61 #define DEFAULT_BUNDLE_COUNT	1
       
    62 #define FAILURE_SCRIPT ""
       
    63 
       
    64 #ifdef MIN
       
    65 #undef MIN
       
    66 #endif
       
    67 #define MIN(a, b) ((a) < (b) ? (a) : (b))
       
    68 
       
    69 // specified options for bundle eids
       
    70 char * arg_replyto      = NULL;
       
    71 char * arg_source       = NULL;
       
    72 char * arg_dest         = NULL;
       
    73 char * arg_receive         = NULL;
       
    74 
       
    75 dtn_reg_id_t regid      = DTN_REGID_NONE;
       
    76 
       
    77 void parse_options(int, char**);
       
    78 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle,
       
    79                               dtn_endpoint_id_t * eid,
       
    80                               char * str);
       
    81 void print_usage();
       
    82 void print_eid(FILE*, char * label, dtn_endpoint_id_t * eid);
       
    83 int fill_payload(dtn_bundle_payload_t* payload);
       
    84 
       
    85 FILE* info;	/* when -v option is used, write to here */
       
    86 #define REG_EXPIRE (60 * 60)
       
    87 char payload_buf[DTN_MAX_BUNDLE_MEM];
       
    88 
       
    89 int from_bundles_flag;
       
    90 
       
    91 void to_bundles();	// stdin -> bundles
       
    92 void from_bundles();	// bundles -> stdout
       
    93 void make_registration(dtn_reg_info_t*);
       
    94 
       
    95 dtn_handle_t handle;
       
    96 dtn_bundle_spec_t bundle_spec;
       
    97 dtn_bundle_spec_t reply_spec;
       
    98 dtn_bundle_payload_t primary_payload;
       
    99 dtn_bundle_payload_t reply_payload;
       
   100 dtn_bundle_id_t bundle_id;
       
   101 struct timeval start, end;
       
   102 
       
   103 
       
   104 int
       
   105 main(int argc, char** argv)
       
   106 {
       
   107 
       
   108     info = stderr;
       
   109     
       
   110     // force stdout to always be line buffered, even if output is
       
   111     // redirected to a pipe or file -- why? kf
       
   112     // setvbuf(stdout, (char *)NULL, _IOLBF, 0);
       
   113     
       
   114     parse_options(argc, argv);
       
   115 
       
   116     // open the ipc handle
       
   117     if (verbose)
       
   118 	fprintf(info, "Opening connection to local DTN daemon\n");
       
   119 
       
   120     int err = dtn_open(&handle);
       
   121     if (err != DTN_SUCCESS) {
       
   122         fprintf(stderr, "%s: fatal error opening dtn handle: %s\n",
       
   123                 progname, dtn_strerror(err));
       
   124         exit(EXIT_FAILURE);
       
   125     }
       
   126 
       
   127     if (gettimeofday(&start, NULL) < 0) {
       
   128 		fprintf(stderr, "%s: gettimeofday(start) returned error %s\n",
       
   129 			progname, strerror(errno));
       
   130 		exit(EXIT_FAILURE);
       
   131     }
       
   132 
       
   133     if (from_bundles_flag)
       
   134 	    from_bundles();
       
   135     else
       
   136 	    to_bundles();
       
   137 
       
   138     dtn_close(handle);
       
   139     return (EXIT_SUCCESS);
       
   140 }
       
   141 
       
   142 
       
   143 /*
       
   144  * [bundles] -> stdout
       
   145  */
       
   146 
       
   147 void
       
   148 from_bundles()
       
   149 {
       
   150     int total_bytes = 0, i, ret;
       
   151     char *buffer;
       
   152     char s_buffer[BUFSIZ];
       
   153 
       
   154     dtn_reg_info_t reg;
       
   155     dtn_endpoint_id_t local_eid;
       
   156     dtn_bundle_spec_t receive_spec;
       
   157 
       
   158     parse_eid(handle, &local_eid, arg_receive);
       
   159 
       
   160     memset(&reg, 0, sizeof(reg));
       
   161     dtn_copy_eid(&reg.endpoint, &local_eid);
       
   162 
       
   163     // when using the session flags, the registration expires
       
   164     // immediately, otherwise we give it a default expiration time
       
   165     if (session_flags) {
       
   166         reg.flags = DTN_REG_DROP | DTN_SESSION_SUBSCRIBE;
       
   167         reg.expiration = 0;
       
   168     } else {
       
   169         reg.flags = DTN_REG_DEFER;
       
   170         reg.expiration = REG_EXPIRE;
       
   171     }
       
   172     
       
   173     make_registration(&reg);
       
   174 
       
   175     if (verbose)
       
   176 	    fprintf(info, "waiting to receive %d bundles using reg >%s<\n",
       
   177 			    bundle_count, reg.endpoint.uri);
       
   178 
       
   179     // loop waiting for bundles
       
   180     for (i = 0; i < bundle_count; ++i) {
       
   181         size_t bytes = 0;
       
   182         u_int k;
       
   183         
       
   184 	// read from network
       
   185         if ((ret = dtn_recv(handle, &receive_spec,
       
   186 	        DTN_PAYLOAD_MEM, &primary_payload, -1)) < 0) {
       
   187             fprintf(stderr, "%s: error getting recv reply: %d (%s)\n",
       
   188                     progname, ret, dtn_strerror(dtn_errno(handle)));
       
   189             exit(EXIT_FAILURE);
       
   190         }
       
   191 
       
   192         bytes  = primary_payload.buf.buf_len;
       
   193         buffer = (char *) primary_payload.buf.buf_val;
       
   194         total_bytes += bytes;
       
   195 
       
   196 	// write to stdout
       
   197 	if (fwrite(buffer, 1, bytes, stdout) != bytes) {
       
   198             fprintf(stderr, "%s: error writing to stdout\n",
       
   199                     progname);
       
   200             exit(EXIT_FAILURE);
       
   201 	}
       
   202 
       
   203         if (!verbose) {
       
   204             continue;
       
   205         }
       
   206         
       
   207         fprintf(info, "%d bytes from [%s]: transit time=%d ms\n",
       
   208                primary_payload.buf.buf_len,
       
   209                receive_spec.source.uri, 0);
       
   210 
       
   211         for (k=0; k < primary_payload.buf.buf_len; k++) {
       
   212             if (buffer[k] >= ' ' && buffer[k] <= '~')
       
   213                 s_buffer[k%BUFSIZ] = buffer[k];
       
   214             else
       
   215                 s_buffer[k%BUFSIZ] = '.';
       
   216 
       
   217             if (k%BUFSIZ == 0) // new line every 16 bytes
       
   218             {
       
   219                 fprintf(info,"%07x ", k);
       
   220             }
       
   221             else if (k%2 == 0)
       
   222             {
       
   223                 fprintf(info," "); // space every 2 bytes
       
   224             }
       
   225                     
       
   226             fprintf(info,"%02x", buffer[k] & 0xff);
       
   227                     
       
   228             // print character summary (a la emacs hexl-mode)
       
   229             if (k%BUFSIZ == BUFSIZ-1)
       
   230             {
       
   231                 fprintf(info," |  %.*s\n", BUFSIZ, s_buffer);
       
   232             }
       
   233         }
       
   234 
       
   235         // print spaces to fill out the rest of the line
       
   236 	if (k%BUFSIZ != BUFSIZ-1) {
       
   237             while (k%BUFSIZ != BUFSIZ-1) {
       
   238                 if (k%2 == 0) {
       
   239                     fprintf(info," ");
       
   240                 }
       
   241                 fprintf(info,"  ");
       
   242                 k++;
       
   243             }
       
   244             fprintf(info,"   |  %.*s\n",
       
   245               (int)primary_payload.buf.buf_len%BUFSIZ, 
       
   246                    s_buffer);
       
   247         }
       
   248 	fprintf(info,"\n");
       
   249     }
       
   250 }
       
   251 
       
   252 /*
       
   253  * stdout -> [bundles]
       
   254  */
       
   255 
       
   256 void
       
   257 to_bundles()
       
   258 {
       
   259 
       
   260     int bytes, ret;
       
   261     dtn_reg_info_t reg_report; /* for reports, if reqd */
       
   262     dtn_reg_info_t reg_session; /* for session reg, if reqd */
       
   263 	
       
   264     // initialize bundle spec
       
   265     memset(&bundle_spec, 0, sizeof(bundle_spec));
       
   266     parse_eid(handle, &bundle_spec.dest, arg_dest);
       
   267     parse_eid(handle, &bundle_spec.source, arg_source);
       
   268 
       
   269     if (arg_replyto == NULL) {
       
   270         dtn_copy_eid(&bundle_spec.replyto, &bundle_spec.source);
       
   271     } else {
       
   272         parse_eid(handle, &bundle_spec.replyto, arg_replyto);
       
   273     }
       
   274 
       
   275     if (verbose) {
       
   276         print_eid(info, "source_eid", &bundle_spec.source);
       
   277         print_eid(info, "replyto_eid", &bundle_spec.replyto);
       
   278         print_eid(info, "dest_eid", &bundle_spec.dest);
       
   279     }
       
   280 
       
   281     if (wait_for_report) {
       
   282 	// if we're given a regid, bind to it, otherwise make a
       
   283 	// registration for incoming reports
       
   284         if (regid != DTN_REGID_NONE) {
       
   285             if (dtn_bind(handle, regid) != DTN_SUCCESS) {
       
   286                 fprintf(stderr, "%s: error in bind (id=0x%x): %d (%s)\n",
       
   287                         progname, regid, ret, dtn_strerror(dtn_errno(handle)));
       
   288                 exit(EXIT_FAILURE);
       
   289             }
       
   290         } else {
       
   291             memset(&reg_report, 0, sizeof(reg_report));
       
   292             dtn_copy_eid(&reg_report.endpoint, &bundle_spec.replyto);
       
   293             reg_report.flags = DTN_REG_DEFER;
       
   294             reg_report.expiration = REG_EXPIRE;
       
   295             make_registration(&reg_report);
       
   296         }
       
   297     }
       
   298 
       
   299     if (session_flags) {
       
   300         // make a publisher registration 
       
   301         memset(&reg_session, 0, sizeof(reg_session));
       
   302 	dtn_copy_eid(&reg_session.endpoint, &bundle_spec.dest);
       
   303         reg_session.flags = DTN_SESSION_PUBLISH;
       
   304         reg_session.expiration = 0;
       
   305 	make_registration(&reg_session);
       
   306     }
       
   307     
       
   308     // set the dtn options
       
   309     bundle_spec.expiration = expiration;
       
   310     
       
   311     if (delivery_receipts) {
       
   312         // set the delivery receipt option
       
   313         bundle_spec.dopts |= DOPTS_DELIVERY_RCPT;
       
   314     }
       
   315 
       
   316     if (forwarding_receipts) {
       
   317         // set the forward receipt option
       
   318         bundle_spec.dopts |= DOPTS_FORWARD_RCPT;
       
   319     }
       
   320 
       
   321     if (custody) {
       
   322         // request custody transfer
       
   323         bundle_spec.dopts |= DOPTS_CUSTODY;
       
   324     }
       
   325 
       
   326     if (custody_receipts) {
       
   327         // request custody transfer
       
   328         bundle_spec.dopts |= DOPTS_CUSTODY_RCPT;
       
   329     }
       
   330 
       
   331     if (receive_receipts) {
       
   332         // request receive receipt
       
   333         bundle_spec.dopts |= DOPTS_RECEIVE_RCPT;
       
   334     }
       
   335 
       
   336     if (sequence_id) {
       
   337         bundle_spec.sequence_id.data.data_val = sequence_id;
       
   338         bundle_spec.sequence_id.data.data_len = strlen(sequence_id);
       
   339     }
       
   340 
       
   341     if (obsoletes_id) {
       
   342         bundle_spec.obsoletes_id.data.data_val = obsoletes_id;
       
   343         bundle_spec.obsoletes_id.data.data_len = strlen(obsoletes_id);
       
   344     }
       
   345 
       
   346     if ((bytes = fill_payload(&primary_payload)) < 0) {
       
   347 	fprintf(stderr, "%s: error reading bundle data\n",
       
   348 	    progname);
       
   349 	exit(EXIT_FAILURE);
       
   350     }
       
   351 
       
   352     memset(&bundle_id, 0, sizeof(bundle_id));
       
   353     if ((ret = dtn_send(handle, regid, &bundle_spec, &primary_payload,
       
   354                         &bundle_id)) != 0) {
       
   355 	fprintf(stderr, "%s: error sending bundle: %d (%s)\n",
       
   356 	    progname, ret, dtn_strerror(dtn_errno(handle)));
       
   357 	exit(EXIT_FAILURE);
       
   358     }
       
   359 
       
   360     if (verbose)
       
   361         fprintf(info, "Read %d bytes from stdin and wrote to bundles\n",
       
   362 		bytes);
       
   363 
       
   364     if (wait_for_report) {
       
   365 	memset(&reply_spec, 0, sizeof(reply_spec));
       
   366 	memset(&reply_payload, 0, sizeof(reply_payload));
       
   367 	
       
   368 	// now we block waiting for any replies
       
   369 	if ((ret = dtn_recv(handle, &reply_spec,
       
   370 			    DTN_PAYLOAD_MEM, &reply_payload, -1)) < 0) {
       
   371 	    fprintf(stderr, "%s: error getting reply: %d (%s)\n",
       
   372 		    progname, ret, dtn_strerror(dtn_errno(handle)));
       
   373 	    exit(EXIT_FAILURE);
       
   374 	}
       
   375 	if (gettimeofday(&end, NULL) < 0) {
       
   376 	    fprintf(stderr, "%s: gettimeofday(end) returned error %s\n",
       
   377 		    progname, strerror(errno));
       
   378 	    exit(EXIT_FAILURE);
       
   379 	}
       
   380     
       
   381 	if (verbose)
       
   382 	    fprintf(info, "got %d byte report from [%s]: time=%.1f ms\n",
       
   383 	       reply_payload.buf.buf_len,
       
   384 	       reply_spec.source.uri,
       
   385 	       ((double)(end.tv_sec - start.tv_sec) * 1000.0 + 
       
   386 		(double)(end.tv_usec - start.tv_usec)/1000.0));
       
   387     }
       
   388 }
       
   389 
       
   390 
       
   391 void print_usage()
       
   392 {
       
   393     fprintf(stderr, "To source bundles from stdin:\n");
       
   394     fprintf(stderr, "    usage: %s [opts] -s <source_eid> -d <dest_eid>\n",
       
   395             progname);
       
   396     fprintf(stderr, "To receive bundles to stdout:\n");
       
   397     fprintf(stderr, "    usage: %s [opts] -l <receive_eid>\n", progname);
       
   398 
       
   399     fprintf(stderr, "common options:\n");
       
   400     fprintf(stderr, " -v verbose\n");
       
   401     fprintf(stderr, " -h/H help\n");
       
   402     fprintf(stderr, " -i <regid> registration id for listening\n");
       
   403     fprintf(stderr, "receive only options (-l option required):\n");
       
   404     fprintf(stderr, " -l <eid> receive bundles destined for eid (instead of sending)\n");
       
   405     fprintf(stderr, " -n <count> exit after count bundles received (-l option required)\n");
       
   406     fprintf(stderr, "send only options (-l option prohibited):\n");
       
   407     fprintf(stderr, " -s <eid|demux_string> source eid)\n");
       
   408     fprintf(stderr, " -d <eid|demux_string> destination eid)\n");
       
   409     fprintf(stderr, " -r <eid|demux_string> reply to eid)\n");
       
   410     fprintf(stderr, " -e <time> expiration time in seconds (default: one hour)\n");
       
   411     fprintf(stderr, " -c request custody transfer\n");
       
   412     fprintf(stderr, " -C request custody transfer receipts\n");
       
   413     fprintf(stderr, " -D request for end-to-end delivery receipt\n");
       
   414     fprintf(stderr, " -R request for bundle reception receipts\n");
       
   415     fprintf(stderr, " -F request for bundle forwarding receipts\n");
       
   416     fprintf(stderr, " -w wait for bundle status reports\n");
       
   417     fprintf(stderr, " -S <sequence_id> sequence id vector\n");
       
   418     fprintf(stderr, " -O <obsoletes_id> obsoletes id vector\n");
       
   419     
       
   420     return;
       
   421 }
       
   422 
       
   423 void
       
   424 parse_options(int argc, char**argv)
       
   425 {
       
   426     int c, done = 0;
       
   427     int lopts = 0, notlopts = 0;
       
   428 
       
   429     progname = argv[0];
       
   430 
       
   431     while (!done) {
       
   432         c = getopt(argc, argv, "l:vhHr:s:d:e:wDFRcCi:n:S:O:");
       
   433         switch (c) {
       
   434 	case 'l':
       
   435 	    from_bundles_flag = 1;
       
   436 	    arg_receive = optarg;
       
   437 	    break;
       
   438         case 'v':
       
   439             verbose = 1;
       
   440             break;
       
   441         case 'h':
       
   442         case 'H':
       
   443             print_usage();
       
   444             exit(EXIT_SUCCESS);
       
   445             return;
       
   446         case 'r':
       
   447             arg_replyto = optarg;
       
   448 	    lopts++;
       
   449             break;
       
   450         case 's':
       
   451             arg_source = optarg;
       
   452 	    notlopts++;
       
   453             break;
       
   454         case 'd':
       
   455             arg_dest = optarg;
       
   456 	    notlopts++;
       
   457             break;
       
   458         case 'e':
       
   459             expiration = atoi(optarg);
       
   460 	    notlopts++;
       
   461             break;
       
   462         case 'w':
       
   463             wait_for_report = 1;
       
   464 	    notlopts++;
       
   465             break;
       
   466         case 'D':
       
   467             delivery_receipts = 1;
       
   468 	    notlopts++;
       
   469             break;
       
   470         case 'F':
       
   471             forwarding_receipts = 1;
       
   472 	    notlopts++;
       
   473             break;
       
   474         case 'R':
       
   475             receive_receipts = 1;
       
   476 	    notlopts++;
       
   477             break;
       
   478         case 'c':
       
   479             custody = 1;
       
   480 	    notlopts++;
       
   481             break;
       
   482         case 'C':
       
   483             custody_receipts = 1;
       
   484 	    notlopts++;
       
   485             break;
       
   486         case 'i':
       
   487             regid = atoi(optarg);
       
   488 	    notlopts++;
       
   489             break;
       
   490 	case 'n':
       
   491 	    bundle_count = atoi(optarg);
       
   492 	    lopts++;
       
   493 	    break;
       
   494         case 'S':
       
   495             sequence_id = optarg;
       
   496             break;
       
   497         case 'O':
       
   498             obsoletes_id = optarg;
       
   499             break;
       
   500         case -1:
       
   501             done = 1;
       
   502             break;
       
   503         default:
       
   504             // getopt already prints an error message for unknown
       
   505             // option characters
       
   506             print_usage();
       
   507             exit(EXIT_FAILURE);
       
   508         }
       
   509     }
       
   510 
       
   511     if (from_bundles_flag && (notlopts > 0)) {
       
   512 	    fprintf(stderr, "%s: error: transmission options specified when using -l flag\n",
       
   513 			progname);
       
   514         print_usage();
       
   515         exit(EXIT_FAILURE);
       
   516     }
       
   517 
       
   518     if (!from_bundles_flag && (lopts > 0)) {
       
   519 	    fprintf(stderr, "%s: error: receive option specified but -l option not selected\n",
       
   520 			progname);
       
   521         print_usage();
       
   522         exit(EXIT_FAILURE);
       
   523     }
       
   524 
       
   525 
       
   526 #define CHECK_SET(_arg, _what)                                          \
       
   527     if (_arg == 0) {                                                    \
       
   528         fprintf(stderr, "%s: %s must be specified\n", progname, _what); \
       
   529         print_usage();                                                  \
       
   530         exit(EXIT_FAILURE);                                             \
       
   531     }
       
   532     
       
   533     if (!from_bundles_flag) {
       
   534     	    /* transmitting to bundles - no -l option */
       
   535 	    CHECK_SET(arg_source,   "source eid");
       
   536 	    CHECK_SET(arg_dest,     "destination eid");
       
   537     } else {
       
   538     	    /* receiving from bundles - -l option specified */
       
   539 	    CHECK_SET(arg_receive,  "receive eid");
       
   540 	    if (bundle_count == -1) {
       
   541 		    bundle_count = DEFAULT_BUNDLE_COUNT;
       
   542 	    }
       
   543     }
       
   544 }
       
   545 
       
   546 dtn_endpoint_id_t *
       
   547 parse_eid(dtn_handle_t handle, dtn_endpoint_id_t* eid, char * str)
       
   548 {
       
   549     // try the string as an actual dtn eid
       
   550     if (!dtn_parse_eid_string(eid, str)) {
       
   551         if (verbose)
       
   552 		fprintf(info, "%s (literal)\n", str);
       
   553         return eid;
       
   554     } else if (!dtn_build_local_eid(handle, eid, str)) {
       
   555         // build a local eid based on the configuration of our dtn
       
   556         // router plus the str as demux string
       
   557         if (verbose) fprintf(info, "%s (local)\n", str);
       
   558         return eid;
       
   559     } else {
       
   560         fprintf(stderr, "invalid eid string '%s'\n", str);
       
   561         exit(EXIT_FAILURE);
       
   562     }
       
   563 }
       
   564 
       
   565 void
       
   566 print_eid(FILE *dest, char *  label, dtn_endpoint_id_t * eid)
       
   567 {
       
   568     fprintf(dest, "%s [%s]\n", label, eid->uri);
       
   569 }
       
   570 
       
   571 /*
       
   572  * read from stdin to get the payload
       
   573  */
       
   574 
       
   575 int
       
   576 fill_payload(dtn_bundle_payload_t* payload)
       
   577 {
       
   578 
       
   579    unsigned char buf[BUFSIZ];
       
   580    unsigned char *p = (unsigned char*) payload_buf;
       
   581    unsigned char *endp = p + sizeof(payload_buf);
       
   582    size_t n, total = 0;
       
   583    size_t maxread = sizeof(buf);
       
   584 
       
   585    while (1) {
       
   586        maxread = MIN((int)sizeof(buf), (endp-p));
       
   587        if ((n = fread(buf, 1, maxread, stdin)) == 0)
       
   588 	       break;
       
   589        memcpy(p, buf, n);
       
   590        p += n;
       
   591        total += n;
       
   592    }
       
   593    if (ferror(stdin))
       
   594        return (-1); 
       
   595 
       
   596    if (dtn_set_payload(payload, DTN_PAYLOAD_MEM, payload_buf, total) == DTN_ESIZE)
       
   597 	   return (-1);
       
   598    return(total);
       
   599 }
       
   600 
       
   601 void
       
   602 make_registration(dtn_reg_info_t* reginfo)
       
   603 {
       
   604 	int ret;
       
   605 
       
   606         // try to find an existing registration to use (unless we're
       
   607         // using session flags, in which case we always create a new
       
   608         // registration)
       
   609         if (session_flags == 0) {
       
   610             ret = dtn_find_registration(handle, &reginfo->endpoint, &regid);
       
   611 
       
   612             if (ret == 0) {
       
   613                 
       
   614                 // found the registration, bind it to the handle
       
   615                 if (dtn_bind(handle, regid) != DTN_SUCCESS) {
       
   616                     fprintf(stderr, "%s: error in bind (id=0x%x): %d (%s)\n",
       
   617                             progname, regid, ret, dtn_strerror(dtn_errno(handle)));
       
   618                     exit(EXIT_FAILURE);
       
   619                 }
       
   620                 
       
   621                 return;
       
   622                 
       
   623             } else if (dtn_errno(handle) == DTN_ENOTFOUND) {
       
   624                 // fall through
       
   625                 
       
   626             } else {
       
   627                 fprintf(stderr, "%s: error in dtn_find_registration: %d (%s)\n",
       
   628                         progname, ret, dtn_strerror(dtn_errno(handle)));
       
   629                 exit(EXIT_FAILURE);
       
   630             }
       
   631         }
       
   632 
       
   633         // create a new dtn registration to receive bundles
       
   634 	if ((ret = dtn_register(handle, reginfo, &regid)) != 0) {
       
   635             fprintf(stderr, "%s: error creating registration (id=0x%x): %d (%s)\n",
       
   636                     progname, regid, ret, dtn_strerror(dtn_errno(handle)));
       
   637             exit(EXIT_FAILURE);
       
   638         }
       
   639     
       
   640         if (verbose)
       
   641             fprintf(info, "dtn_register succeeded, regid 0x%x\n", regid);
       
   642 }