00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include <stdio.h>
00022 #include <unistd.h>
00023 #include <errno.h>
00024 #include <strings.h>
00025 #include <string.h>
00026 #include <stdlib.h>
00027 #include <sys/time.h>
00028 #include <sys/stat.h>
00029 #include <fcntl.h>
00030 #include "dtn_api.h"
00031
00032 #define BUFSIZE 16
00033 #define BLOCKSIZE 8192
00034 #define COUNTER_MAX_DIGITS 9
00035
00036
00037 #ifdef __FreeBSD__
00038
00039 #include <sys/syslimits.h>
00040 #endif
00041
00042 #ifndef PATH_MAX
00043
00044 #define PATH_MAX 1024
00045 #endif
00046
00047 const char *progname;
00048
00049 int verbose = 0;
00050 int quiet = 0;
00051 char* endpoint = NULL;
00052 dtn_reg_id_t regid = DTN_REGID_NONE;
00053 int expiration = 30;
00054 int count = 0;
00055 int failure_action = DTN_REG_DEFER;
00056 char* failure_script = "";
00057 int register_only = 0;
00058 int change = 0;
00059 int unregister = 0;
00060 int recv_timeout = -1;
00061 int no_find_reg = 0;
00062 char filename[PATH_MAX];
00063 dtn_bundle_payload_location_t bundletype = DTN_PAYLOAD_MEM;
00064
00065 void
00066 usage()
00067 {
00068 fprintf(stderr, "usage: %s [opts] <endpoint> \n", progname);
00069 fprintf(stderr, "options:\n");
00070 fprintf(stderr, " -v verbose\n");
00071 fprintf(stderr, " -q quiet\n");
00072 fprintf(stderr, " -h help\n");
00073 fprintf(stderr, " -d <eid|demux_string> endpoint id\n");
00074 fprintf(stderr, " -r <regid> use existing registration regid\n");
00075 fprintf(stderr, " -n <count> exit after count bundles received\n");
00076 fprintf(stderr, " -e <time> registration expiration time in seconds "
00077 "(default: one hour)\n");
00078 fprintf(stderr, " -f <defer|drop|exec> failure action\n");
00079 fprintf(stderr, " -F <script> failure script for exec action\n");
00080 fprintf(stderr, " -x call dtn_register and immediately exit\n");
00081 fprintf(stderr, " -c call dtn_change_registration and immediately exit\n");
00082 fprintf(stderr, " -u call dtn_unregister and immediately exit\n");
00083 fprintf(stderr, " -N don't try to find an existing registration\n");
00084 fprintf(stderr, " -t <timeout> timeout value for call to dtn_recv\n");
00085 fprintf(stderr, " -o <template> Write out transfers to files using this template (# chars are\n"
00086 "replaced with a counter). Example: f##.bin goes to f00.bin, f01.bin, etc...\n");
00087 }
00088
00089 void
00090 parse_options(int argc, char**argv)
00091 {
00092 int c, done = 0;
00093
00094 progname = argv[0];
00095
00096 memset(filename, 0, sizeof(char) * PATH_MAX);
00097
00098 while (!done)
00099 {
00100 c = getopt(argc, argv, "vqhHd:r:e:f:F:xn:cuNt:o:");
00101 switch (c)
00102 {
00103 case 'v':
00104 verbose = 1;
00105 break;
00106 case 'q':
00107 quiet = 1;
00108 break;
00109 case 'h':
00110 case 'H':
00111 usage();
00112 exit(0);
00113 return;
00114 case 'r':
00115 regid = atoi(optarg);
00116 break;
00117 case 'e':
00118 expiration = atoi(optarg);
00119 break;
00120 case 'f':
00121 if (!strcasecmp(optarg, "defer")) {
00122 failure_action = DTN_REG_DEFER;
00123
00124 } else if (!strcasecmp(optarg, "drop")) {
00125 failure_action = DTN_REG_DROP;
00126
00127 } else if (!strcasecmp(optarg, "exec")) {
00128 failure_action = DTN_REG_EXEC;
00129
00130 } else {
00131 fprintf(stderr, "invalid failure action '%s'\n", optarg);
00132 usage();
00133 exit(1);
00134 }
00135 case 'F':
00136 failure_script = optarg;
00137 break;
00138 case 'x':
00139 register_only = 1;
00140 break;
00141 case 'n':
00142 count = atoi(optarg);
00143 break;
00144 case 'c':
00145 change = 1;
00146 break;
00147 case 'u':
00148 unregister = 1;
00149 break;
00150 case 'N':
00151 no_find_reg = 1;
00152 break;
00153 case 't':
00154 recv_timeout = atoi(optarg);
00155 break;
00156 case 'o':
00157 strncpy(filename, optarg, PATH_MAX);
00158 break;
00159 case -1:
00160 done = 1;
00161 break;
00162 default:
00163
00164
00165 usage();
00166 exit(1);
00167 }
00168 }
00169
00170 endpoint = argv[optind];
00171 if (!endpoint && (regid == DTN_REGID_NONE)) {
00172 fprintf(stderr, "must specify either an endpoint or a regid\n");
00173 usage();
00174 exit(1);
00175 }
00176
00177 if ((change || unregister) && (regid == DTN_REGID_NONE)) {
00178 fprintf(stderr, "must specify regid when using -%c option\n",
00179 change ? 'c' : 'u');
00180 usage();
00181 exit(1);
00182 }
00183
00184 if (failure_action == DTN_REG_EXEC && failure_script == NULL) {
00185 fprintf(stderr, "failure action EXEC must supply script\n");
00186 usage();
00187 exit(1);
00188 }
00189
00190
00191
00192 if ( filename[0] != '\0' )
00193 bundletype = DTN_PAYLOAD_FILE;
00194
00195 }
00196
00197
00198 static void
00199 print_data(char* buffer, u_int length)
00200 {
00201 u_int k;
00202 char s_buffer[BUFSIZE];
00203 for (k=0; k < length; k++)
00204 {
00205 if (buffer[k] >= ' ' && buffer[k] <= '~')
00206 s_buffer[k%BUFSIZE] = buffer[k];
00207 else
00208 s_buffer[k%BUFSIZE] = '.';
00209
00210 if (k%BUFSIZE == 0)
00211 {
00212 printf("%07x ", k);
00213 }
00214 else if (k%2 == 0)
00215 {
00216 printf(" ");
00217 }
00218
00219 printf("%02x", buffer[k] & 0xff);
00220
00221
00222 if (k%BUFSIZE == BUFSIZE-1)
00223 {
00224 printf(" | %.*s\n", BUFSIZE, s_buffer);
00225 }
00226 }
00227
00228
00229 if ((length % BUFSIZE) != 0) {
00230 while (k%BUFSIZE != BUFSIZE-1) {
00231 if (k%2 == 0) {
00232 printf(" ");
00233 }
00234 printf(" ");
00235 k++;
00236 }
00237 printf(" | %.*s\n",
00238 (int)length%BUFSIZE,
00239 s_buffer);
00240 }
00241 printf("\n");
00242 }
00243
00244
00245
00246
00247
00248 int buildfilename(char* template, char* newfilename, int counter )
00249 {
00250 char counterasstring[COUNTER_MAX_DIGITS];
00251 char formatstring[10];
00252 char* startloc;
00253 char* endloc;
00254 int templatelen;
00255
00256 strcpy(newfilename, template);
00257
00258 endloc = rindex(newfilename, '#');
00259
00260 if ( endloc == NULL )
00261 return 0;
00262
00263
00264 for ( startloc = endloc; *startloc == '#' && startloc != template;
00265 startloc -= 1 );
00266
00267 startloc += 1;
00268
00269 templatelen = endloc - startloc + 1;
00270 if ( templatelen > COUNTER_MAX_DIGITS )
00271 templatelen = COUNTER_MAX_DIGITS;
00272
00273 sprintf(formatstring, "%%0%dd", templatelen);
00274 sprintf(counterasstring, formatstring, counter);
00275
00276 if ( strlen(counterasstring) > (unsigned int)templatelen )
00277 fprintf(stderr, "Warning: Filename template not large enough "
00278 "to support counter value %d\n", counter);
00279
00280 memcpy(startloc, counterasstring, sizeof(char) * templatelen);
00281
00282 return 0;
00283 }
00284
00285
00286
00287
00288
00289
00290 int
00291 handle_file_transfer(dtn_bundle_spec_t spec, dtn_bundle_payload_t payload,
00292 int* total_bytes, int counter)
00293 {
00294 int tempdes;
00295 int destdes;
00296 char block[BLOCKSIZE];
00297 ssize_t bytesread;
00298 struct stat fileinfo;
00299 char currentfile[PATH_MAX];
00300
00301
00302
00303 buildfilename(filename, currentfile, counter);
00304
00305
00306 if (rename(filename, currentfile) == 0) {
00307
00308
00309 } else {
00310
00311 tempdes = open(payload.filename.filename_val, O_RDONLY);
00312
00313 if ( tempdes < 0 )
00314 {
00315 fprintf(stderr, "While opening the temporary file for reading '%s': %s\n",
00316 payload.filename.filename_val, strerror(errno));
00317 exit(1);
00318 }
00319
00320 destdes = creat(currentfile, 0644);
00321
00322 if ( destdes < 0 )
00323 {
00324 fprintf(stderr, "While opening output file for writing '%s': %s\n",
00325 filename, strerror(errno));
00326 exit(1);
00327 }
00328
00329
00330 while ( (bytesread = read(tempdes, block, sizeof(block))) > 0 )
00331 write(destdes, block, bytesread);
00332
00333 close(tempdes);
00334 close(destdes);
00335
00336 unlink(payload.filename.filename_val);
00337 }
00338
00339 if ( stat(currentfile, &fileinfo) == -1 )
00340 {
00341 fprintf(stderr, "Unable to stat destination file '%s': %s\n",
00342 currentfile, strerror(errno));
00343 return 1;
00344 }
00345
00346 printf("%d byte file from [%s]: transit time=%d ms, written to '%s'\n",
00347 (int)fileinfo.st_size, spec.source.uri, 0, currentfile);
00348
00349 *total_bytes += fileinfo.st_size;
00350
00351 return 0;
00352 }
00353
00354 int
00355 main(int argc, char** argv)
00356 {
00357 int i;
00358 u_int k;
00359 int ret;
00360 int total_bytes = 0;
00361 dtn_handle_t handle;
00362 dtn_endpoint_id_t local_eid;
00363 dtn_reg_info_t reginfo;
00364 dtn_bundle_spec_t spec;
00365 dtn_bundle_payload_t payload;
00366 int call_bind;
00367
00368
00369
00370 setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00371
00372 progname = argv[0];
00373
00374 parse_options(argc, argv);
00375
00376 if (count == 0) {
00377 printf("dtnrecv (pid %d) starting up\n", getpid());
00378 } else {
00379 printf("dtnrecv (pid %d) starting up -- count %u\n", getpid(), count);
00380 }
00381
00382
00383 if (verbose) printf("opening connection to dtn router...\n");
00384 int err = dtn_open(&handle);
00385 if (err != DTN_SUCCESS) {
00386 fprintf(stderr, "fatal error opening dtn handle: %s\n",
00387 dtn_strerror(err));
00388 exit(1);
00389 }
00390 if (verbose) printf("opened connection to dtn router...\n");
00391
00392
00393
00394 memset(®info, 0, sizeof(reginfo));
00395
00396 if ((regid == DTN_REGID_NONE) || change)
00397 {
00398
00399
00400
00401 if (endpoint[0] == '/') {
00402 if (verbose) printf("calling dtn_build_local_eid.\n");
00403 dtn_build_local_eid(handle, &local_eid, (char *) endpoint);
00404 if (verbose) printf("local_eid [%s]\n", local_eid.uri);
00405 } else {
00406 if (verbose) printf("calling parse_eid_string\n");
00407 if (dtn_parse_eid_string(&local_eid, endpoint)) {
00408 fprintf(stderr, "invalid destination endpoint '%s'\n",
00409 endpoint);
00410 goto err;
00411 }
00412 }
00413
00414
00415 dtn_copy_eid(®info.endpoint, &local_eid);
00416 reginfo.regid = regid;
00417 reginfo.expiration = expiration;
00418 reginfo.flags = failure_action;
00419 reginfo.script.script_val = failure_script;
00420 reginfo.script.script_len = strlen(failure_script) + 1;
00421 }
00422
00423 if (change) {
00424 if ((ret = dtn_change_registration(handle, regid, ®info)) != 0) {
00425 fprintf(stderr, "error changing registration: %d (%s)\n",
00426 ret, dtn_strerror(dtn_errno(handle)));
00427 goto err;
00428 }
00429 printf("change registration succeeded, regid %d\n", regid);
00430 goto done;
00431 }
00432
00433 if (unregister) {
00434 if (dtn_unregister(handle, regid) != 0) {
00435 fprintf(stderr, "error in unregister regid %d: %s\n",
00436 regid, dtn_strerror(dtn_errno(handle)));
00437 goto err;
00438 }
00439
00440 printf("unregister succeeded, regid %d\n", regid);
00441 goto done;
00442 }
00443
00444
00445
00446 if (regid == DTN_REGID_NONE && ! no_find_reg) {
00447 if (dtn_find_registration(handle, &local_eid, ®id) != 0) {
00448 if (dtn_errno(handle) != DTN_ENOTFOUND) {
00449 fprintf(stderr, "error in find_registration: %s\n",
00450 dtn_strerror(dtn_errno(handle)));
00451 goto err;
00452 }
00453 }
00454 printf("find registration succeeded, regid %d\n", regid);
00455 call_bind = 1;
00456 }
00457
00458
00459 if (regid == DTN_REGID_NONE) {
00460 if ((ret = dtn_register(handle, ®info, ®id)) != 0) {
00461 fprintf(stderr, "error creating registration: %d (%s)\n",
00462 ret, dtn_strerror(dtn_errno(handle)));
00463 goto err;
00464 }
00465
00466 printf("register succeeded, regid %d\n", regid);
00467 call_bind = 0;
00468 } else {
00469 call_bind = 1;
00470 }
00471
00472 if (register_only) {
00473 goto done;
00474 }
00475
00476 if (call_bind) {
00477
00478 printf("binding to regid %d\n", regid);
00479 if (dtn_bind(handle, regid) != 0) {
00480 fprintf(stderr, "error binding to registration: %s\n",
00481 dtn_strerror(dtn_errno(handle)));
00482 goto err;
00483 }
00484 }
00485
00486
00487 if (count == 0) {
00488 printf("looping forever to receive bundles\n");
00489 } else {
00490 printf("looping to receive %d bundles\n", count);
00491 }
00492 for (i = 0; (count == 0) || (i < count); ++i) {
00493 memset(&spec, 0, sizeof(spec));
00494 memset(&payload, 0, sizeof(payload));
00495
00496 if (!quiet) {
00497 printf("dtn_recv [%s]...\n", local_eid.uri);
00498 }
00499
00500 if ((ret = dtn_recv(handle, &spec, bundletype, &payload,
00501 recv_timeout)) < 0)
00502 {
00503 fprintf(stderr, "error getting recv reply: %d (%s)\n",
00504 ret, dtn_strerror(dtn_errno(handle)));
00505 goto err;
00506 }
00507
00508
00509 if ( bundletype == DTN_PAYLOAD_FILE )
00510 {
00511 handle_file_transfer(spec, payload, &total_bytes, i);
00512 dtn_free_payload(&payload);
00513 continue;
00514 }
00515
00516 total_bytes += payload.buf.buf_len;
00517
00518 if (quiet) {
00519 dtn_free_payload(&payload);
00520 if (spec.blocks.blocks_len > 0) {
00521 free(spec.blocks.blocks_val);
00522 spec.blocks.blocks_val = NULL;
00523 spec.blocks.blocks_len = 0;
00524 }
00525 if (spec.metadata.metadata_len > 0) {
00526 free(spec.metadata.metadata_val);
00527 spec.metadata.metadata_val = NULL;
00528 spec.metadata.metadata_len = 0;
00529 }
00530 continue;
00531 }
00532
00533 printf("\n%d extension blocks from [%s]: transit time=%d ms\n",
00534 spec.blocks.blocks_len, spec.source.uri, 0);
00535 dtn_extension_block_t *block = spec.blocks.blocks_val;
00536 for (k = 0; k < spec.blocks.blocks_len; k++) {
00537 printf("Extension Block %i:\n", k);
00538 printf("\ttype = %i\n\tflags = %i\n",
00539 block[k].type, block[k].flags);
00540 print_data(block[k].data.data_val, block[k].data.data_len);
00541 }
00542
00543 printf("\n%d metadata blocks from [%s]: transit time=%d ms\n",
00544 spec.metadata.metadata_len, spec.source.uri, 0);
00545 dtn_extension_block_t *meta = spec.metadata.metadata_val;
00546 for (k = 0; k < spec.metadata.metadata_len; k++) {
00547 printf("Metadata Extension Block %i:\n", k);
00548 printf("\ttype = %i\n\tflags = %i\n",
00549 meta[k].type, meta[k].flags);
00550 print_data(meta[k].data.data_val, meta[k].data.data_len);
00551 }
00552
00553 printf("%d payload bytes from [%s]: transit time=%d ms\n",
00554 payload.buf.buf_len,
00555 spec.source.uri, 0);
00556
00557 print_data(payload.buf.buf_val, payload.buf.buf_len);
00558 printf("\n");
00559
00560 dtn_free_payload(&payload);
00561 if (spec.blocks.blocks_len > 0) {
00562 free(spec.blocks.blocks_val);
00563 spec.blocks.blocks_val = NULL;
00564 spec.blocks.blocks_len = 0;
00565 }
00566 if (spec.metadata.metadata_len > 0) {
00567 free(spec.metadata.metadata_val);
00568 spec.metadata.metadata_val = NULL;
00569 spec.metadata.metadata_len = 0;
00570 }
00571 }
00572
00573 printf("dtnrecv (pid %d) exiting: %d bundles received, %d total bytes\n\n",
00574 getpid(), i, total_bytes);
00575
00576 done:
00577 dtn_close(handle);
00578 return 0;
00579
00580 err:
00581 dtn_close(handle);
00582 return 1;
00583 }