00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include <stdio.h>
00049 #include <unistd.h>
00050 #include <errno.h>
00051 #include <strings.h>
00052 #include <string.h>
00053 #include <stdlib.h>
00054 #include <sys/time.h>
00055 #include <time.h>
00056
00057 #include "dtn_api.h"
00058
00059 char *progname;
00060
00061
00062 int copies = 1;
00063 int verbose = 0;
00064
00065
00066 int expiration = 3600;
00067 int delivery_receipts = 0;
00068 int forwarding_receipts = 0;
00069 int custody = 0;
00070 int custody_receipts = 0;
00071 int receive_receipts = 0;
00072 int wait_for_report = 0;
00073 int bundle_count = -1;
00074
00075 #define DEFAULT_BUNDLE_COUNT 1
00076 #define FAILURE_SCRIPT ""
00077
00078 #ifdef MIN
00079 #undef MIN
00080 #endif
00081 #define MIN(a, b) ((a) < (b) ? (a) : (b))
00082
00083
00084 char * arg_replyto = NULL;
00085 char * arg_source = NULL;
00086 char * arg_dest = NULL;
00087 char * arg_receive = NULL;
00088
00089 dtn_reg_id_t regid = DTN_REGID_NONE;
00090
00091 void parse_options(int, char**);
00092 dtn_endpoint_id_t * parse_eid(dtn_handle_t handle,
00093 dtn_endpoint_id_t * eid,
00094 char * str);
00095 void print_usage();
00096 void print_eid(FILE*, char * label, dtn_endpoint_id_t * eid);
00097 int fill_payload(dtn_bundle_payload_t* payload);
00098
00099 FILE* info;
00100 #define REG_EXPIRE (60 * 60)
00101 char payload_buf[DTN_MAX_BUNDLE_MEM];
00102
00103 int from_bundles_flag;
00104
00105 void to_bundles();
00106 void from_bundles();
00107 void make_registration(dtn_reg_info_t*);
00108
00109 dtn_handle_t handle;
00110 dtn_bundle_spec_t bundle_spec;
00111 dtn_bundle_spec_t reply_spec;
00112 dtn_bundle_payload_t primary_payload;
00113 dtn_bundle_payload_t reply_payload;
00114 dtn_bundle_id_t bundle_id;
00115 struct timeval start, end;
00116
00117
00118 int
00119 main(int argc, char** argv)
00120 {
00121
00122 info = stderr;
00123
00124
00125
00126
00127
00128 parse_options(argc, argv);
00129
00130
00131 if (verbose)
00132 fprintf(info, "Opening connection to local DTN daemon\n");
00133
00134 int err = dtn_open(&handle);
00135 if (err != DTN_SUCCESS) {
00136 fprintf(stderr, "%s: fatal error opening dtn handle: %s\n",
00137 progname, dtn_strerror(err));
00138 exit(EXIT_FAILURE);
00139 }
00140
00141 if (gettimeofday(&start, NULL) < 0) {
00142 fprintf(stderr, "%s: gettimeofday(start) returned error %s\n",
00143 progname, strerror(errno));
00144 exit(EXIT_FAILURE);
00145 }
00146
00147 if (from_bundles_flag)
00148 from_bundles();
00149 else
00150 to_bundles();
00151
00152 dtn_close(handle);
00153 return (EXIT_SUCCESS);
00154 }
00155
00156
00157
00158
00159
00160
00161 void
00162 from_bundles()
00163 {
00164 int total_bytes = 0, i, ret;
00165 char *buffer;
00166 char s_buffer[BUFSIZ];
00167
00168 dtn_reg_info_t reg;
00169 dtn_endpoint_id_t local_eid;
00170 dtn_bundle_spec_t receive_spec;
00171
00172 parse_eid(handle, &local_eid, arg_receive);
00173
00174 memset(®, 0, sizeof(reg));
00175 dtn_copy_eid(®.endpoint, &local_eid);
00176 make_registration(®);
00177
00178 if (verbose)
00179 fprintf(info, "waiting to receive %d bundles using reg >%s<\n",
00180 bundle_count, reg.endpoint.uri);
00181
00182
00183 for (i = 0; i < bundle_count; ++i) {
00184 size_t bytes = 0;
00185 u_int k;
00186
00187
00188 if ((ret = dtn_recv(handle, &receive_spec,
00189 DTN_PAYLOAD_MEM, &primary_payload, -1)) < 0) {
00190 fprintf(stderr, "%s: error getting recv reply: %d (%s)\n",
00191 progname, ret, dtn_strerror(dtn_errno(handle)));
00192 exit(EXIT_FAILURE);
00193 }
00194
00195 bytes = primary_payload.dtn_bundle_payload_t_u.buf.buf_len;
00196 buffer =
00197 (char *) primary_payload.dtn_bundle_payload_t_u.buf.buf_val;
00198 total_bytes += bytes;
00199
00200
00201 if (fwrite(buffer, 1, bytes, stdout) != bytes) {
00202 fprintf(stderr, "%s: error writing to stdout\n",
00203 progname);
00204 exit(EXIT_FAILURE);
00205 }
00206
00207 if (!verbose) {
00208 continue;
00209 }
00210
00211 fprintf(info, "%d bytes from [%s]: transit time=%d ms\n",
00212 primary_payload.dtn_bundle_payload_t_u.buf.buf_len,
00213 receive_spec.source.uri, 0);
00214
00215 for (k=0; k < primary_payload.dtn_bundle_payload_t_u.buf.buf_len; k++) {
00216 if (buffer[k] >= ' ' && buffer[k] <= '~')
00217 s_buffer[k%BUFSIZ] = buffer[k];
00218 else
00219 s_buffer[k%BUFSIZ] = '.';
00220
00221 if (k%BUFSIZ == 0)
00222 {
00223 fprintf(info,"%07x ", k);
00224 }
00225 else if (k%2 == 0)
00226 {
00227 fprintf(info," ");
00228 }
00229
00230 fprintf(info,"%02x", buffer[k] & 0xff);
00231
00232
00233 if (k%BUFSIZ == BUFSIZ-1)
00234 {
00235 fprintf(info," | %.*s\n", BUFSIZ, s_buffer);
00236 }
00237 }
00238
00239
00240 if (k%BUFSIZ != BUFSIZ-1) {
00241 while (k%BUFSIZ != BUFSIZ-1) {
00242 if (k%2 == 0) {
00243 fprintf(info," ");
00244 }
00245 fprintf(info," ");
00246 k++;
00247 }
00248 fprintf(info," | %.*s\n",
00249 (int)primary_payload.dtn_bundle_payload_t_u.buf.buf_len%BUFSIZ,
00250 s_buffer);
00251 }
00252 fprintf(info,"\n");
00253 }
00254 }
00255
00256
00257
00258
00259
00260 void
00261 to_bundles()
00262 {
00263
00264 int bytes, ret;
00265 dtn_reg_info_t reg_report;
00266
00267
00268 memset(&bundle_spec, 0, sizeof(bundle_spec));
00269 parse_eid(handle, &bundle_spec.dest, arg_dest);
00270 parse_eid(handle, &bundle_spec.source, arg_source);
00271
00272 if (arg_replyto == NULL) {
00273 dtn_copy_eid(&bundle_spec.replyto, &bundle_spec.source);
00274 } else {
00275 parse_eid(handle, &bundle_spec.replyto, arg_replyto);
00276 }
00277
00278 if (verbose) {
00279 print_eid(info, "source_eid", &bundle_spec.source);
00280 print_eid(info, "replyto_eid", &bundle_spec.replyto);
00281 print_eid(info, "dest_eid", &bundle_spec.dest);
00282 }
00283
00284 if (wait_for_report) {
00285
00286 memset(®_report, 0, sizeof(reg_report));
00287 dtn_copy_eid(®_report.endpoint, &bundle_spec.replyto);
00288 make_registration(®_report);
00289 }
00290
00291
00292 bundle_spec.expiration = expiration;
00293
00294 if (delivery_receipts) {
00295
00296 bundle_spec.dopts |= DOPTS_DELIVERY_RCPT;
00297 }
00298
00299 if (forwarding_receipts) {
00300
00301 bundle_spec.dopts |= DOPTS_FORWARD_RCPT;
00302 }
00303
00304 if (custody) {
00305
00306 bundle_spec.dopts |= DOPTS_CUSTODY;
00307 }
00308
00309 if (custody_receipts) {
00310
00311 bundle_spec.dopts |= DOPTS_CUSTODY_RCPT;
00312 }
00313
00314 if (receive_receipts) {
00315
00316 bundle_spec.dopts |= DOPTS_RECEIVE_RCPT;
00317 }
00318
00319
00320 if ((bytes = fill_payload(&primary_payload)) < 0) {
00321 fprintf(stderr, "%s: error reading bundle data\n",
00322 progname);
00323 exit(EXIT_FAILURE);
00324 }
00325
00326 memset(&bundle_id, 0, sizeof(bundle_id));
00327 if ((ret = dtn_send(handle, &bundle_spec, &primary_payload,
00328 &bundle_id)) != 0) {
00329 fprintf(stderr, "%s: error sending bundle: %d (%s)\n",
00330 progname, ret, dtn_strerror(dtn_errno(handle)));
00331 exit(EXIT_FAILURE);
00332 }
00333
00334 if (verbose)
00335 fprintf(info, "Read %d bytes from stdin and wrote to bundles\n",
00336 bytes);
00337
00338 if (wait_for_report) {
00339 memset(&reply_spec, 0, sizeof(reply_spec));
00340 memset(&reply_payload, 0, sizeof(reply_payload));
00341
00342
00343 if ((ret = dtn_recv(handle, &reply_spec,
00344 DTN_PAYLOAD_MEM, &reply_payload, -1)) < 0) {
00345 fprintf(stderr, "%s: error getting reply: %d (%s)\n",
00346 progname, ret, dtn_strerror(dtn_errno(handle)));
00347 exit(EXIT_FAILURE);
00348 }
00349 if (gettimeofday(&end, NULL) < 0) {
00350 fprintf(stderr, "%s: gettimeofday(end) returned error %s\n",
00351 progname, strerror(errno));
00352 exit(EXIT_FAILURE);
00353 }
00354
00355 if (verbose)
00356 fprintf(info, "got %d byte report from [%s]: time=%.1f ms\n",
00357 reply_payload.dtn_bundle_payload_t_u.buf.buf_len,
00358 reply_spec.source.uri,
00359 ((double)(end.tv_sec - start.tv_sec) * 1000.0 +
00360 (double)(end.tv_usec - start.tv_usec)/1000.0));
00361 }
00362 }
00363
00364
00365 void print_usage()
00366 {
00367 fprintf(stderr, "To source bundles from stdin:\n");
00368 fprintf(stderr, " usage: %s [opts] -s <source_eid> -d <dest_eid>\n",
00369 progname);
00370 fprintf(stderr, "To receive bundles to stdout:\n");
00371 fprintf(stderr, " usage: %s [opts] -l <receive_eid>\n", progname);
00372
00373 fprintf(stderr, "common options:\n");
00374 fprintf(stderr, " -v verbose\n");
00375 fprintf(stderr, " -h/H help\n");
00376 fprintf(stderr, "receive only options (-l option required):\n");
00377
00378 fprintf(stderr, " -l <eid> receive bundles destined for eid (instead of sending)\n");
00379 fprintf(stderr, " -n <count> exit after count bundles received (-l option required)\n");
00380 fprintf(stderr, "send only options (-l option prohibited):\n");
00381 fprintf(stderr, " -s <eid|demux_string> source eid)\n");
00382 fprintf(stderr, " -d <eid|demux_string> destination eid)\n");
00383 fprintf(stderr, " -r <eid|demux_string> reply to eid)\n");
00384 fprintf(stderr, " -e <time> expiration time in seconds (default: one hour)\n");
00385 fprintf(stderr, " -i <regid> registration id for reply to\n");
00386 fprintf(stderr, " -c request custody transfer\n");
00387 fprintf(stderr, " -C request custody transfer receipts\n");
00388 fprintf(stderr, " -D request for end-to-end delivery receipt\n");
00389 fprintf(stderr, " -R request for bundle reception receipts\n");
00390 fprintf(stderr, " -F request for bundle forwarding receipts\n");
00391 fprintf(stderr, " -w wait for bundle status reports\n");
00392
00393 return;
00394 }
00395
00396 void
00397 parse_options(int argc, char**argv)
00398 {
00399 char c, done = 0;
00400 int lopts = 0, notlopts = 0;
00401
00402 progname = argv[0];
00403
00404 while (!done) {
00405 c = getopt(argc, argv, "l:vhHr:s:d:e:wDFRcCi:n:");
00406 switch (c) {
00407 case 'l':
00408 from_bundles_flag = 1;
00409 arg_receive = optarg;
00410 break;
00411 case 'v':
00412 verbose = 1;
00413 break;
00414 case 'h':
00415 case 'H':
00416 print_usage();
00417 exit(EXIT_SUCCESS);
00418 return;
00419 case 'r':
00420 arg_replyto = optarg;
00421 lopts++;
00422 break;
00423 case 's':
00424 arg_source = optarg;
00425 notlopts++;
00426 break;
00427 case 'd':
00428 arg_dest = optarg;
00429 notlopts++;
00430 break;
00431 case 'e':
00432 expiration = atoi(optarg);
00433 notlopts++;
00434 break;
00435 case 'w':
00436 wait_for_report = 1;
00437 notlopts++;
00438 break;
00439 case 'D':
00440 delivery_receipts = 1;
00441 notlopts++;
00442 break;
00443 case 'F':
00444 forwarding_receipts = 1;
00445 notlopts++;
00446 break;
00447 case 'R':
00448 receive_receipts = 1;
00449 notlopts++;
00450 break;
00451 case 'c':
00452 custody = 1;
00453 notlopts++;
00454 break;
00455 case 'C':
00456 custody_receipts = 1;
00457 notlopts++;
00458 break;
00459 case 'i':
00460 regid = atoi(optarg);
00461 notlopts++;
00462 break;
00463 case 'n':
00464 bundle_count = atoi(optarg);
00465 lopts++;
00466 break;
00467 case -1:
00468 done = 1;
00469 break;
00470 default:
00471
00472
00473 print_usage();
00474 exit(EXIT_FAILURE);
00475 }
00476 }
00477
00478 if (from_bundles_flag && (notlopts > 0)) {
00479 fprintf(stderr, "%s: error: transmission options specified when using -l flag\n",
00480 progname);
00481 print_usage();
00482 exit(EXIT_FAILURE);
00483 }
00484
00485 if (!from_bundles_flag && (lopts > 0)) {
00486 fprintf(stderr, "%s: error: receive option specified but -l option not selected\n",
00487 progname);
00488 print_usage();
00489 exit(EXIT_FAILURE);
00490 }
00491
00492
00493 #define CHECK_SET(_arg, _what) \
00494 if (_arg == 0) { \
00495 fprintf(stderr, "%s: %s must be specified\n", progname, _what); \
00496 print_usage(); \
00497 exit(EXIT_FAILURE); \
00498 }
00499
00500 if (!from_bundles_flag) {
00501
00502 CHECK_SET(arg_source, "source eid");
00503 CHECK_SET(arg_dest, "destination eid");
00504 } else {
00505
00506 CHECK_SET(arg_receive, "receive eid");
00507 if (bundle_count == -1) {
00508 bundle_count = DEFAULT_BUNDLE_COUNT;
00509 }
00510 }
00511 }
00512
00513 dtn_endpoint_id_t *
00514 parse_eid(dtn_handle_t handle, dtn_endpoint_id_t* eid, char * str)
00515 {
00516
00517 if (!dtn_parse_eid_string(eid, str)) {
00518 if (verbose)
00519 fprintf(info, "%s (literal)\n", str);
00520 return eid;
00521 } else if (!dtn_build_local_eid(handle, eid, str)) {
00522
00523
00524 if (verbose) fprintf(info, "%s (local)\n", str);
00525 return eid;
00526 } else {
00527 fprintf(stderr, "invalid eid string '%s'\n", str);
00528 exit(EXIT_FAILURE);
00529 }
00530 }
00531
00532 void
00533 print_eid(FILE *dest, char * label, dtn_endpoint_id_t * eid)
00534 {
00535 fprintf(dest, "%s [%s]\n", label, eid->uri);
00536 }
00537
00538
00539
00540
00541
00542 int
00543 fill_payload(dtn_bundle_payload_t* payload)
00544 {
00545
00546 unsigned char buf[BUFSIZ];
00547 unsigned char *p = (unsigned char*) payload_buf;
00548 unsigned char *endp = p + sizeof(payload_buf);
00549 size_t n, total = 0;
00550 size_t maxread = sizeof(buf);
00551
00552 while (1) {
00553 maxread = MIN((int)sizeof(buf), (endp-p));
00554 if ((n = fread(buf, 1, maxread, stdin)) == 0)
00555 break;
00556 memcpy(p, buf, n);
00557 p += n;
00558 total += n;
00559 }
00560 if (ferror(stdin))
00561 return (-1);
00562
00563 if (dtn_set_payload(payload, DTN_PAYLOAD_MEM, payload_buf, total) == DTN_ESIZE)
00564 return (-1);
00565 return(total);
00566 }
00567
00568 void
00569 make_registration(dtn_reg_info_t* reginfo)
00570 {
00571 int ret;
00572
00573
00574 ret = dtn_find_registration(handle, ®info->endpoint, ®id);
00575
00576 if (ret == 0) {
00577
00578
00579 if (dtn_bind(handle, regid) != DTN_SUCCESS) {
00580 fprintf(stderr, "%s: error in bind (id=0x%x): %d (%s)\n",
00581 progname, regid, ret, dtn_strerror(dtn_errno(handle)));
00582 exit(EXIT_FAILURE);
00583 }
00584
00585 return;
00586
00587 } else if (dtn_errno(handle) == DTN_ENOTFOUND) {
00588
00589
00590 } else {
00591 fprintf(stderr, "%s: error in dtn_find_registration: %d (%s)\n",
00592 progname, ret, dtn_strerror(dtn_errno(handle)));
00593 exit(EXIT_FAILURE);
00594 }
00595
00596
00597 reginfo->regid = regid;
00598 reginfo->expiration = REG_EXPIRE;
00599 reginfo->failure_action = DTN_REG_DROP;
00600 reginfo->script.script_val = FAILURE_SCRIPT;
00601 reginfo->script.script_len = strlen(reginfo->script.script_val) + 1;
00602
00603 if ((ret = dtn_register(handle, reginfo, ®id)) != 0) {
00604 fprintf(stderr, "%s: error creating registration (id=0x%x): %d (%s)\n",
00605 progname, regid, ret, dtn_strerror(dtn_errno(handle)));
00606 exit(EXIT_FAILURE);
00607 }
00608
00609 if (verbose)
00610 fprintf(info, "dtn_register succeeded, regid 0x%x\n", regid);
00611 }