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