void make_registration(dtn_reg_info_t* reginfo) { int ret; // try to find an existing registration to use (unless we're // using session flags, in which case we always create a new // registration) if (session_flags == 0) { ret = dtn_find_registration(handle, ®info->endpoint, ®id); if (ret == 0) { // found the registration, bind it to the handle if (dtn_bind(handle, regid) != DTN_SUCCESS) { fprintf(stderr, "%s: error in bind (id=0x%x): %d (%s)\n", progname, regid, ret, dtn_strerror(dtn_errno(handle))); exit(EXIT_FAILURE); } return; } else if (dtn_errno(handle) == DTN_ENOTFOUND) { // fall through } else { fprintf(stderr, "%s: error in dtn_find_registration: %d (%s)\n", progname, ret, dtn_strerror(dtn_errno(handle))); exit(EXIT_FAILURE); } } // create a new dtn registration to receive bundles if ((ret = dtn_register(handle, reginfo, ®id)) != 0) { fprintf(stderr, "%s: error creating registration (id=0x%x): %d (%s)\n", progname, regid, ret, dtn_strerror(dtn_errno(handle))); exit(EXIT_FAILURE); } if (verbose) fprintf(info, "dtn_register succeeded, regid 0x%x\n", regid); }
void to_bundles() { int bytes, ret; dtn_reg_info_t reg_report; /* for reports, if reqd */ dtn_reg_info_t reg_session; /* for session reg, if reqd */ // initialize bundle spec memset(&bundle_spec, 0, sizeof(bundle_spec)); parse_eid(handle, &bundle_spec.dest, arg_dest); parse_eid(handle, &bundle_spec.source, arg_source); if (arg_replyto == NULL) { dtn_copy_eid(&bundle_spec.replyto, &bundle_spec.source); } else { parse_eid(handle, &bundle_spec.replyto, arg_replyto); } if (verbose) { print_eid(info, "source_eid", &bundle_spec.source); print_eid(info, "replyto_eid", &bundle_spec.replyto); print_eid(info, "dest_eid", &bundle_spec.dest); } if (wait_for_report) { // if we're given a regid, bind to it, otherwise make a // registration for incoming reports if (regid != DTN_REGID_NONE) { if (dtn_bind(handle, regid) != DTN_SUCCESS) { fprintf(stderr, "%s: error in bind (id=0x%x): %d (%s)\n", progname, regid, ret, dtn_strerror(dtn_errno(handle))); exit(EXIT_FAILURE); } } else { memset(®_report, 0, sizeof(reg_report)); dtn_copy_eid(®_report.endpoint, &bundle_spec.replyto); reg_report.flags = DTN_REG_DEFER; reg_report.expiration = REG_EXPIRE; make_registration(®_report); } } if (session_flags) { // make a publisher registration memset(®_session, 0, sizeof(reg_session)); dtn_copy_eid(®_session.endpoint, &bundle_spec.dest); reg_session.flags = DTN_SESSION_PUBLISH; reg_session.expiration = 0; make_registration(®_session); } // set the dtn options bundle_spec.expiration = expiration; if (delivery_receipts) { // set the delivery receipt option bundle_spec.dopts |= DOPTS_DELIVERY_RCPT; } if (forwarding_receipts) { // set the forward receipt option bundle_spec.dopts |= DOPTS_FORWARD_RCPT; } if (custody) { // request custody transfer bundle_spec.dopts |= DOPTS_CUSTODY; } if (custody_receipts) { // request custody transfer bundle_spec.dopts |= DOPTS_CUSTODY_RCPT; } if (receive_receipts) { // request receive receipt bundle_spec.dopts |= DOPTS_RECEIVE_RCPT; } if (sequence_id) { bundle_spec.sequence_id.data.data_val = sequence_id; bundle_spec.sequence_id.data.data_len = strlen(sequence_id); } if (obsoletes_id) { bundle_spec.obsoletes_id.data.data_val = obsoletes_id; bundle_spec.obsoletes_id.data.data_len = strlen(obsoletes_id); } if ((bytes = fill_payload(&primary_payload)) < 0) { fprintf(stderr, "%s: error reading bundle data\n", progname); exit(EXIT_FAILURE); } memset(&bundle_id, 0, sizeof(bundle_id)); if ((ret = dtn_send(handle, regid, &bundle_spec, &primary_payload, &bundle_id)) != 0) { fprintf(stderr, "%s: error sending bundle: %d (%s)\n", progname, ret, dtn_strerror(dtn_errno(handle))); exit(EXIT_FAILURE); } if (verbose) fprintf(info, "Read %d bytes from stdin and wrote to bundles\n", bytes); if (wait_for_report) { memset(&reply_spec, 0, sizeof(reply_spec)); memset(&reply_payload, 0, sizeof(reply_payload)); // now we block waiting for any replies if ((ret = dtn_recv(handle, &reply_spec, DTN_PAYLOAD_MEM, &reply_payload, -1)) < 0) { fprintf(stderr, "%s: error getting reply: %d (%s)\n", progname, ret, dtn_strerror(dtn_errno(handle))); exit(EXIT_FAILURE); } if (gettimeofday(&end, NULL) < 0) { fprintf(stderr, "%s: gettimeofday(end) returned error %s\n", progname, strerror(errno)); exit(EXIT_FAILURE); } if (verbose) fprintf(info, "got %d byte report from [%s]: time=%.1f ms\n", reply_payload.buf.buf_len, reply_spec.source.uri, ((double)(end.tv_sec - start.tv_sec) * 1000.0 + (double)(end.tv_usec - start.tv_usec)/1000.0)); } }
int main(int argc, char** argv) { int i, errs; int ret; dtn_handle_t handle; dtn_endpoint_id_t local_eid; dtn_reg_info_t reginfo; dtn_bundle_spec_t spec; dtn_bundle_payload_t payload; int call_bind; time_t now; // force stdout to always be line buffered, even if output is // redirected to a pipe or file setvbuf(stdout, (char *)NULL, _IOLBF, 0); progname = argv[0]; parse_options(argc, argv); printf("dtnsink starting up -- waiting for %u bundles\n", count); // open the ipc handle if (verbose) printf("opening connection to dtn router...\n"); int err = dtn_open(&handle); if (err != DTN_SUCCESS) { fprintf(stderr, "fatal error opening dtn handle: %s\n", dtn_strerror(err)); exit(1); } if (verbose) printf("opened connection to dtn router...\n"); // if we're not given a regid, or we're in change mode, we need to // build up the reginfo memset(®info, 0, sizeof(reginfo)); if ((regid == DTN_REGID_NONE) || change) { // if the specified eid starts with '/', then build a local // eid based on the configuration of our dtn router plus the // demux string. otherwise make sure it's a valid one if (endpoint[0] == '/') { if (verbose) printf("calling dtn_build_local_eid.\n"); dtn_build_local_eid(handle, &local_eid, (char *) endpoint); if (verbose) printf("local_eid [%s]\n", local_eid.uri); } else { if (verbose) printf("calling parse_eid_string\n"); if (dtn_parse_eid_string(&local_eid, endpoint)) { fprintf(stderr, "invalid destination endpoint '%s'\n", endpoint); goto err; } } // create a new registration based on this eid dtn_copy_eid(®info.endpoint, &local_eid); reginfo.regid = regid; reginfo.expiration = expiration; reginfo.flags = failure_action; reginfo.script.script_val = failure_script; reginfo.script.script_len = strlen(failure_script) + 1; } if (change) { if ((ret = dtn_change_registration(handle, regid, ®info)) != 0) { fprintf(stderr, "error changing registration: %d (%s)\n", ret, dtn_strerror(dtn_errno(handle))); goto err; } printf("change registration succeeded, regid %d\n", regid); goto done; } if (unregister) { if (dtn_unregister(handle, regid) != 0) { fprintf(stderr, "error in unregister regid %d: %s\n", regid, dtn_strerror(dtn_errno(handle))); goto err; } printf("unregister succeeded, regid %d\n", regid); goto done; } // try to see if there is an existing registration that matches // the given endpoint, in which case we'll use that one. if (regid == DTN_REGID_NONE && ! no_find_reg) { if (dtn_find_registration(handle, &local_eid, ®id) != 0) { if (dtn_errno(handle) != DTN_ENOTFOUND) { fprintf(stderr, "error in find_registration: %s\n", dtn_strerror(dtn_errno(handle))); goto err; } } printf("find registration succeeded, regid %d\n", regid); call_bind = 1; } // if the user didn't give us a registration to use, get a new one if (regid == DTN_REGID_NONE) { if ((ret = dtn_register(handle, ®info, ®id)) != 0) { fprintf(stderr, "error creating registration: %d (%s)\n", ret, dtn_strerror(dtn_errno(handle))); goto err; } printf("register succeeded, regid %d\n", regid); call_bind = 0; } else { call_bind = 1; } if (register_only) { goto done; } if (call_bind) { // bind the current handle to the found registration printf("binding to regid %d\n", regid); if (dtn_bind(handle, regid) != 0) { fprintf(stderr, "error binding to registration: %s\n", dtn_strerror(dtn_errno(handle))); goto err; } } // keep track of what we've seen char *received = (char *)malloc(count + 1); memset(received, '\0', count); // loop waiting for bundles fprintf(stderr, "waiting %d seconds for first bundle...\n", (MAX_STARTUP_TRIES)*RECV_TIMEOUT/1000); for (i = 1; i <= count; ++i) { int tries; uint32_t which; uint32_t size; memset(&spec, 0, sizeof(spec)); memset(&payload, 0, sizeof(payload)); /* * this is a little tricky. We want dtn_recv to time out after * RECV_TIMEOUT ms, so we don't wait a long time for a bundle * if something is broken and no bundle is coming. But we * want to be friendly and wait patiently for the first * bundle, in case dtnsource is slow in getting off the mark. * * So we loop at most MAX_STARTUP_TRIES times */ tries = 0; while ((ret = dtn_recv(handle, &spec, bundletype, &payload, RECV_TIMEOUT)) < 0) { /* if waiting for the first bundle and we timed out be patient */ if (dtn_errno(handle) == DTN_ETIMEOUT) { if (i == 1 && ++tries < MAX_STARTUP_TRIES) { fprintf(stderr, "waiting %d seconds for first bundle...\n", (MAX_STARTUP_TRIES-tries)*RECV_TIMEOUT/1000); } else { /* timed out waiting, something got dropped */ fprintf(stderr, "timeout waiting for bundle %d\n", i); goto bail; } } else { /* a bad thing has happend in recv, or we've lost patience */ fprintf(stderr, "error in dtn_recv: %d (%d, %s)\n", ret, dtn_errno(handle), dtn_strerror(dtn_errno(handle))); goto bail; } } if (i == 1) { now = time(0); printf("received first bundle at %s\n", ctime(&now)); } if (verbose) { printf("bundle %d received successfully: id %s,%llu.%llu\n", i, spec.source.uri, spec.creation_ts.secs, spec.creation_ts.seqno); } if (!promiscuous) { /* check to see which bundle this is */ // Files need to be handled differently than memory transfers if (payload.location == DTN_PAYLOAD_FILE) { if (handle_file_transfer(payload, &size, &which) < 0) { dtn_free_payload(&payload); continue; } } else { which = ntohl(*(uint32_t *)payload.buf.buf_val); size = payload.buf.buf_len; } if (which > (uint32_t) count) { // note that the above cast is safe as count always >= 0 fprintf(stderr, "-- expecting %d bundles, saw bundle %u\n", count, which); } else if (which <= 0) { /* because I am paranoid -DJE */ fprintf(stderr, "-- didn't expect bundle %u\n", which); } else { ++received[which]; } } // XXX should verify size here... /* all done, get next one */ dtn_free_payload(&payload); } bail: for (i = 1; i <= count; ++i) { if (received[i] == 0) { int j = i + 1; while (j <= count && received[j] == 0) ++j; if (j == i + 1) printf("bundle %d: dropped\n", i); else printf("bundles %d-%d dropped\n", i, j - 1); errs += (j - i); i += (j - i - 1); } else if (received[i] > 1) { printf("bundle %d: received %d copies\n", i, received[i]); ++errs; } } if (errs == 0) { printf("all %d bundles received correctly\n", count); } free(received); now = time(0); printf("terminating at %s\n", ctime(&now)); done: dtn_close(handle); return 0; err: dtn_close(handle); return 1; }