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