/* * Append Scope=0 to partially constructed Interest, meaning * to address only the local ndnd. */ static void local_scope(struct ndn_charbuf *templ) { ndn_charbuf_append_tt(templ, NDN_DTAG_Scope, NDN_DTAG); ndn_charbuf_append_tt(templ, 1, NDN_UDATA); ndn_charbuf_append(templ, "0", 1); ndn_charbuf_append_closer(templ); /* </Scope> */ }
/** * Append AnswerOriginKind=1 to partially constructed Interest, meaning * do not generate new content. */ static void answer_passive(struct ndn_charbuf *templ) { ndn_charbuf_append_tt(templ, NDN_DTAG_AnswerOriginKind, NDN_DTAG); ndn_charbuf_append_tt(templ, 1, NDN_UDATA); ndn_charbuf_append(templ, "1", 1); ndn_charbuf_append_closer(templ); /* </AnswerOriginKind> */ }
static void append_future_vcomp(struct ndn_charbuf *templ) { /* One beyond a distant future version stamp */ unsigned char b[7] = {NDN_MARKER_VERSION + 1, 0, 0, 0, 0, 0, 0}; ndn_charbuf_append_tt(templ, NDN_DTAG_Component, NDN_DTAG); ndn_charbuf_append_tt(templ, sizeof(b), NDN_BLOB); ndn_charbuf_append(templ, b, sizeof(b)); ndn_charbuf_append_closer(templ); /* </Component> */ }
struct ndn_charbuf *make_template(int allow_caching) { if (NDN_API_VERSION >= 8000 && !allow_caching) { struct ndn_charbuf *templ = ndn_charbuf_create(); ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG); ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG); ndn_charbuf_append_closer(templ); // </Name> ndn_charbuf_append_tt(templ, NDN_DTAG_AnswerOriginKind, NDN_DTAG); ndnb_append_number(templ, NDN_AOK_NEW); ndn_charbuf_append_closer(templ); // </AnswerOriginKind> ndn_charbuf_append_closer(templ); // </Interest> return(templ); } return NULL; }
PyObject * _pyndn_cmd_KeyLocator_to_ndn(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { static char *kwlist[] = {"name", "digest", "key", "cert", NULL}; PyObject *py_name = Py_None, *py_digest = Py_None, *py_key = Py_None, *py_cert = Py_None; struct ndn_charbuf *keylocator; int r; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &py_name, &py_digest, &py_key, &py_cert)) return NULL; keylocator = ndn_charbuf_create(); JUMP_IF_NULL_MEM(keylocator, error); r = ndn_charbuf_append_tt(keylocator, NDN_DTAG_KeyLocator, NDN_DTAG); JUMP_IF_NEG_MEM(r, error); if (py_name != Py_None) { //TODO: add digest as well r = KeyLocator_name_to_ndn(keylocator, py_name); JUMP_IF_NEG(r, error); } else if (py_key != Py_None) { r = KeyLocator_key_to_ndn(keylocator, py_key); JUMP_IF_NEG(r, error); } else if (py_cert != Py_None) { #if 0 ndn_charbuf_append_tt(keylocator, NDN_DTAG_Certificate, NDN_DTAG); // TODO: How to handle certificate? ** Not supported here ndn_charbuf_append_closer(keylocator); /* </Certificate> */ #endif PyErr_SetString(PyExc_NotImplementedError, "Certificate key locator is" " not implemented"); goto error; } r = ndn_charbuf_append_closer(keylocator); /* </KeyLocator> */ JUMP_IF_NEG_MEM(r, error); return NDNObject_New(KEY_LOCATOR, keylocator); error: ndn_charbuf_destroy(&keylocator); return NULL; }
static int KeyLocator_name_to_ndn(struct ndn_charbuf *keylocator, PyObject *py_name) { struct ndn_charbuf *name; int r; if (!NDNObject_IsValid(NAME, py_name)) { PyErr_SetString(PyExc_TypeError, "Argument needs to be of type NDN Name"); return -1; } name = NDNObject_Get(NAME, py_name); r = ndn_charbuf_append_tt(keylocator, NDN_DTAG_KeyName, NDN_DTAG); JUMP_IF_NEG_MEM(r, error); // Looks like name already has all necessary tags // r = ndnb_append_tagged_blob(keylocator, NDN_DTAG_Name, name->buf, name->length); // check r = ndn_charbuf_append_charbuf(keylocator, name); JUMP_IF_NEG_MEM(r, error); r = ndn_charbuf_append_closer(keylocator); /* </KeyName> */ JUMP_IF_NEG_MEM(r, error); r = 0; error: return r; }
static int KeyLocator_key_to_ndn(struct ndn_charbuf *keylocator, PyObject *py_key) { struct ndn_pkey *key; int r; if (!NDNObject_IsValid(PKEY_PUB, py_key)) { PyErr_SetString(PyExc_TypeError, "Argument needs to be of type NDN Key"); return -1; } key = NDNObject_Get(PKEY_PUB, py_key); r = ndn_charbuf_append_tt(keylocator, NDN_DTAG_Key, NDN_DTAG); JUMP_IF_NEG_MEM(r, error); r = ndn_append_pubkey_blob(keylocator, key); JUMP_IF_NEG_MEM(r, error); r = ndn_charbuf_append_closer(keylocator); /* </Key> */ JUMP_IF_NEG_MEM(r, error); r = 0; error: return r; }
int build_keylocator_from_key(struct ndn_charbuf** keylocator, struct ndn_pkey* key) { int res = 0; *keylocator = ndn_charbuf_create(); ndn_charbuf_append_tt(*keylocator, NDN_DTAG_KeyLocator, NDN_DTAG); ndn_charbuf_append_tt(*keylocator, NDN_DTAG_Key, NDN_DTAG); res = ndn_append_pubkey_blob(*keylocator, key); ndn_charbuf_append_closer(*keylocator); /* </Key> */ ndn_charbuf_append_closer(*keylocator); /* </KeyLocator> */ return(res); }
/** * Add a Component to a Name. * * The component is an arbitrary string of n octets, no escaping required. * @returns 0, or -1 for error. */ int ndn_name_append(struct ndn_charbuf *c, const void *component, size_t n) { int res; const unsigned char closer[2] = {NDN_CLOSE, NDN_CLOSE}; if (c->length < 2 || c->buf[c->length-1] != closer[1]) return(-1); c->length -= 1; ndn_charbuf_reserve(c, n + 8); res = ndn_charbuf_append_tt(c, NDN_DTAG_Component, NDN_DTAG); if (res == -1) return(res); res = ndn_charbuf_append_tt(c, n, NDN_BLOB); if (res == -1) return(res); res = ndn_charbuf_append(c, component, n); if (res == -1) return(res); res = ndn_charbuf_append(c, closer, sizeof(closer)); return(res); }
/* * Construct and send a new interest that uses the exclusion list. * Return -1 if not sent because of packet size, 0 for success. */ static int express_my_interest(struct ndn *h, struct ndn_closure *selfp, struct ndn_charbuf *name) { int ans; struct ndn_charbuf *templ = NULL; int i; struct ndn_traversal *data = get_my_data(selfp); templ = ndn_charbuf_create(); ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG); ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG); ndn_charbuf_append_closer(templ); /* </Name> */ if (data->n_excl != 0) { ndn_charbuf_append_tt(templ, NDN_DTAG_Exclude, NDN_DTAG); if ((data->flags & EXCLUDE_LOW) != 0) append_Any_filter(templ); for (i = 0; i < data->n_excl; i++) { struct ndn_charbuf *comp = data->excl[i]; if (comp->length < 4) abort(); ndn_charbuf_append(templ, comp->buf + 1, comp->length - 2); } if ((data->flags & EXCLUDE_HIGH) != 0) append_Any_filter(templ); ndn_charbuf_append_closer(templ); /* </Exclude> */ } answer_passive(templ, (data->flags & ALLOW_STALE) != 0); if ((data->flags & LOCAL_SCOPE) != 0) local_scope(templ); ndn_charbuf_append_closer(templ); /* </Interest> */ if (templ->length + name->length > data->warn + 2) { fprintf(stderr, "*** Interest packet is %d bytes\n", (int)templ->length); data->warn = data->warn * 8 / 5; } if (templ->length + name->length > 1450 && data->n_excl > 3) ans = -1; else { ndn_express_interest(h, name, selfp, templ); ans = 0; } ndn_charbuf_destroy(&templ); return(ans); }
/** * Construct a template suitable for use with ndn_express_interest * indicating at least one suffix component, and stale data if so * requested. */ struct ndn_charbuf * make_template(struct mydata *md, struct ndn_upcall_info *info) { struct ndn_charbuf *templ = ndn_charbuf_create(); ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG); ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG); ndn_charbuf_append_closer(templ); /* </Name> */ // XXX - use pubid if possible ndn_charbuf_append_tt(templ, NDN_DTAG_MinSuffixComponents, NDN_DTAG); ndnb_append_number(templ, 1); ndn_charbuf_append_closer(templ); /* </MinSuffixComponents> */ if (md->allow_stale) { ndn_charbuf_append_tt(templ, NDN_DTAG_AnswerOriginKind, NDN_DTAG); ndnb_append_number(templ, NDN_AOK_DEFAULT | NDN_AOK_STALE); ndn_charbuf_append_closer(templ); /* </AnswerOriginKind> */ } ndn_charbuf_append_closer(templ); /* </Interest> */ return(templ); }
/** * Reset charbuf to represent an empty Name in binary format. * 重置charbuf来代表一个空的*二进制*名字 * @returns 0, or -1 for error. */ int ndn_name_init(struct ndn_charbuf *c) { int res; c->length = 0; res = ndn_charbuf_append_tt(c, NDN_DTAG_Name, NDN_DTAG); if (res == -1) return(res); res = ndn_charbuf_append_closer(c); return(res); }
static struct ndn_charbuf * resolve_templ(struct ndn_charbuf *templ, unsigned const char *vcomp, int size, int lifetime, int versioning_flags) { if (templ == NULL) templ = ndn_charbuf_create(); if (size < 3 || size > 16) { ndn_charbuf_destroy(&templ); return(NULL); } templ->length = 0; ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG); ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG); ndn_charbuf_append_closer(templ); /* </Name> */ ndn_charbuf_append_tt(templ, NDN_DTAG_Exclude, NDN_DTAG); append_filter_all(templ); ndn_charbuf_append_tt(templ, NDN_DTAG_Component, NDN_DTAG); ndn_charbuf_append_tt(templ, size, NDN_BLOB); ndn_charbuf_append(templ, vcomp, size); ndn_charbuf_append_closer(templ); /* </Component> */ append_future_vcomp(templ); append_filter_all(templ); ndn_charbuf_append_closer(templ); /* </Exclude> */ answer_highest(templ); answer_passive(templ); if ((versioning_flags & NDN_V_SCOPE2) != 0) ndnb_tagged_putf(templ, NDN_DTAG_Scope, "%d", 2); else if ((versioning_flags & NDN_V_SCOPE1) != 0) ndnb_tagged_putf(templ, NDN_DTAG_Scope, "%d", 1); else if ((versioning_flags & NDN_V_SCOPE0) != 0) ndnb_tagged_putf(templ, NDN_DTAG_Scope, "%d", 0); if (lifetime > 0) ndnb_append_tagged_binary_number(templ, NDN_DTAG_InterestLifetime, lifetime); ndn_charbuf_append_closer(templ); /* </Interest> */ return(templ); }
static void express_bulkdata_interest(struct ndn *h, struct pending *p) { int res; struct bulkdata *b = NULL; struct ndn_charbuf *name = NULL; struct ndn_charbuf *templ = NULL; struct ndn_charbuf *seq = NULL; b = p->parent; if (b == NULL) return; name = ndn_charbuf_create(); templ = ndn_charbuf_create(); seq = ndn_charbuf_create(); ndn_charbuf_append(name, b->name_prefix->buf, b->name_prefix->length); seq->length = 0; (*b->seqfunc)(p->x, b->seqfunc_param, seq); ndn_name_append(name, seq->buf, seq->length); ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG); ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG); ndn_charbuf_append_closer(templ); /* </Name> */ // XXX - may want to set Min/MaxSuffixComponents ndn_charbuf_append_closer(templ); /* </Interest> */ res = ndn_express_interest(h, name, &p->closure, templ); assert(res >= 0); // XXX - handle this better ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&templ); ndn_charbuf_destroy(&seq); }
int ndn_append_pubkey_blob(struct ndn_charbuf *c, const struct ndn_pkey *i_pubkey) { int res; size_t bytes; unsigned char *p = NULL; res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, NULL); if (res < 0) return(-1); bytes = res; res = ndn_charbuf_append_tt(c, bytes, NDN_BLOB); if (res < 0) return(-1); p = ndn_charbuf_reserve(c, bytes); if (p == NULL) return(-1); res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, &p); if (res != (int)bytes) return(-1); c->length += bytes; return(bytes); }
/** * Extend a Name with a new version stamp * @param h is the the ndn handle. * May be NULL. This procedure does not use the connection. * @param name is a ndnb-encoded Name prefix. By default it gets extended * in-place with one additional Component that conforms to the * versioning profile and is based on the supplied time, unless a * version component is already present. * @param versioning_flags modifies the default behavior: * NDN_V_REPLACE causes the last component to be replaced if it * appears to be a version stamp. If NDN_V_HIGH is set as well, an * attempt will be made to generate a new version stamp that is * later than the existing one, or to return an error. * NDN_V_NOW bases the version on the current time rather than the * supplied time. * NDN_V_NESTOK will allow the new version component to be appended * even if there is one there (this makes no difference if NDN_V_REPLACE * is also set). * @param secs is the desired time, in seconds since epoch * (ignored if NDN_V_NOW is set). * @param nsecs is the number of nanoseconds. * @returns -1 for error, 0 for success. */ int ndn_create_version(struct ndn *h, struct ndn_charbuf *name, int versioning_flags, intmax_t secs, int nsecs) { size_t i; size_t j; size_t lc = 0; size_t oc = 0; int n; struct ndn_indexbuf *nix = NULL; int myres = -1; int already_versioned = 0; int ok_flags = (NDN_V_REPLACE | NDN_V_HIGH | NDN_V_NOW | NDN_V_NESTOK); // XXX - right now we ignore h, but in the future we may use it to try to avoid non-monotonicies in the versions. nix = ndn_indexbuf_create(); n = ndn_name_split(name, nix); if (n < 0) goto Finish; if ((versioning_flags & ~ok_flags) != 0) goto Finish; /* Check for existing version component */ if (n >= 1) { oc = nix->buf[n-1]; lc = nix->buf[n] - oc; if (lc <= 11 && lc >= 6 && name->buf[oc + 2] == NDN_MARKER_VERSION) already_versioned = 1; } myres = 0; if (already_versioned && (versioning_flags & (NDN_V_REPLACE | NDN_V_NESTOK)) == 0) goto Finish; name->length -= 1; /* Strip name closer */ i = name->length; myres |= ndn_charbuf_append_tt(name, NDN_DTAG_Component, NDN_DTAG); if ((versioning_flags & NDN_V_NOW) != 0) myres |= ndnb_append_now_blob(name, NDN_MARKER_VERSION); else { myres |= ndnb_append_timestamp_blob(name, NDN_MARKER_VERSION, secs, nsecs); } myres |= ndn_charbuf_append_closer(name); /* </Component> */ if (myres < 0) { name->length = i; goto CloseName; } j = name->length; if (already_versioned && (versioning_flags & NDN_V_REPLACE) != 0) { oc = nix->buf[n-1]; lc = nix->buf[n] - oc; if ((versioning_flags & NDN_V_HIGH) != 0 && memcmp(name->buf + oc, name->buf + i, j - i) > 0) { /* Supplied version is in the future. */ name->length = i; // XXX - we could try harder to make this work, for now just error out myres = -1; goto CloseName; } memmove(name->buf + oc, name->buf + i, j - i); name->length -= lc; } CloseName: myres |= ndn_charbuf_append_closer(name); /* </Name> */ Finish: myres = (myres < 0) ? -1 : 0; ndn_indexbuf_destroy(&nix); return(myres); }
/** * This appends a filter useful for * excluding everything between two 'fenceposts' in an Exclude construct. */ static void append_filter_all(struct ndn_charbuf *c) { ndn_charbuf_append_tt(c, NDN_DTAG_Any, NDN_DTAG); ndn_charbuf_append_closer(c); }
int main(int argc, char **argv) { const char *progname = argv[0]; struct ndn *ndn = NULL; struct ndn_charbuf *name = NULL; struct ndn_charbuf *pname = NULL; struct ndn_charbuf *temp = NULL; struct ndn_charbuf *extopt = NULL; long expire = -1; int versioned = 0; size_t blocksize = 8*1024; int status = 0; int res; ssize_t read_res; unsigned char *buf = NULL; enum ndn_content_type content_type = NDN_CONTENT_DATA; struct ndn_closure in_interest = {.p=&incoming_interest}; const char *postver = NULL; const char *key_uri = NULL; int force = 0; int verbose = 0; int timeout = -1; int setfinal = 0; int prefixcomps = -1; int fd; struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT; while ((res = getopt(argc, argv, "e:fhk:lvV:p:t:w:x:")) != -1) { switch (res) { case 'e': if (extopt == NULL) extopt = ndn_charbuf_create(); fd = open(optarg, O_RDONLY); if (fd < 0) { perror(optarg); exit(1); } for (;;) { read_res = read(fd, ndn_charbuf_reserve(extopt, 64), 64); if (read_res <= 0) break; extopt->length += read_res; } if (read_res < 0) perror(optarg); close(fd); break; case 'f': force = 1; break; case 'l': setfinal = 1; // set FinalBlockID to last comp of name break; case 'k': key_uri = optarg; break; case 'p': prefixcomps = atoi(optarg); if (prefixcomps < 0) usage(progname); break; case 'x': expire = atol(optarg); if (expire <= 0) usage(progname); break; case 'v': verbose = 1; break; case 'V': versioned = 1; postver = optarg; if (0 == memcmp(postver, "%00", 3)) setfinal = 1; break; case 'w': timeout = atol(optarg); if (timeout <= 0) usage(progname); timeout *= 1000; break; case 't': if (0 == strcasecmp(optarg, "DATA")) { content_type = NDN_CONTENT_DATA; break; } if (0 == strcasecmp(optarg, "ENCR")) { content_type = NDN_CONTENT_ENCR; break; } if (0 == strcasecmp(optarg, "GONE")) { content_type = NDN_CONTENT_GONE; break; } if (0 == strcasecmp(optarg, "KEY")) { content_type = NDN_CONTENT_KEY; break; } if (0 == strcasecmp(optarg, "LINK")) { content_type = NDN_CONTENT_LINK; break; } if (0 == strcasecmp(optarg, "NACK")) { content_type = NDN_CONTENT_NACK; break; } content_type = atoi(optarg); if (content_type > 0 && content_type <= 0xffffff) break; fprintf(stderr, "Unknown content type %s\n", optarg); /* FALLTHRU */ default: case 'h': usage(progname); break; } } argc -= optind; argv += optind; if (argv[0] == NULL) usage(progname); name = ndn_charbuf_create(); res = ndn_name_from_uri(name, argv[0]); if (res < 0) { fprintf(stderr, "%s: bad ndn URI: %s\n", progname, argv[0]); exit(1); } if (argv[1] != NULL) fprintf(stderr, "%s warning: extra arguments ignored\n", progname); /* Preserve the original prefix, in case we add versioning, * but trim it down if requested for the interest filter registration */ pname = ndn_charbuf_create(); ndn_charbuf_append(pname, name->buf, name->length); if (prefixcomps >= 0) { res = ndn_name_chop(pname, NULL, prefixcomps); if (res < 0) { fprintf(stderr, "%s: unable to trim name to %d component%s.\n", progname, prefixcomps, prefixcomps == 1 ? "" : "s"); exit(1); } } /* Connect to ndnd */ ndn = ndn_create(); if (ndn_connect(ndn, NULL) == -1) { perror("Could not connect to ndnd"); exit(1); } /* Read the actual user data from standard input */ buf = calloc(1, blocksize); read_res = read_full(0, buf, blocksize); if (read_res < 0) { perror("read"); read_res = 0; status = 1; } /* Tack on the version component if requested */ if (versioned) { res = ndn_create_version(ndn, name, NDN_V_REPLACE | NDN_V_NOW | NDN_V_HIGH, 0, 0); if (res < 0) { fprintf(stderr, "%s: ndn_create_version() failed\n", progname); exit(1); } if (postver != NULL) { res = ndn_name_from_uri(name, postver); if (res < 0) { fprintf(stderr, "-V %s: invalid name suffix\n", postver); exit(0); } } } temp = ndn_charbuf_create(); /* Ask for a FinalBlockID if appropriate. */ if (setfinal) sp.sp_flags |= NDN_SP_FINAL_BLOCK; if (res < 0) { fprintf(stderr, "Failed to create signed_info (res == %d)\n", res); exit(1); } /* Set content type */ sp.type = content_type; /* Set freshness */ if (expire >= 0) { if (sp.template_ndnb == NULL) { sp.template_ndnb = ndn_charbuf_create(); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_SignedInfo, NDN_DTAG); } else if (sp.template_ndnb->length > 0) { sp.template_ndnb->length--; } ndnb_tagged_putf(sp.template_ndnb, NDN_DTAG_FreshnessSeconds, "%ld", expire); sp.sp_flags |= NDN_SP_TEMPL_FRESHNESS; ndn_charbuf_append_closer(sp.template_ndnb); } /* Set key locator, if supplied */ if (key_uri != NULL) { struct ndn_charbuf *c = ndn_charbuf_create(); res = ndn_name_from_uri(c, key_uri); if (res < 0) { fprintf(stderr, "%s is not a valid ndnx URI\n", key_uri); exit(1); } if (sp.template_ndnb == NULL) { sp.template_ndnb = ndn_charbuf_create(); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_SignedInfo, NDN_DTAG); } else if (sp.template_ndnb->length > 0) { sp.template_ndnb->length--; } ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_KeyLocator, NDN_DTAG); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_KeyName, NDN_DTAG); ndn_charbuf_append(sp.template_ndnb, c->buf, c->length); ndn_charbuf_append_closer(sp.template_ndnb); ndn_charbuf_append_closer(sp.template_ndnb); sp.sp_flags |= NDN_SP_TEMPL_KEY_LOCATOR; ndn_charbuf_append_closer(sp.template_ndnb); ndn_charbuf_destroy(&c); } if (extopt != NULL && extopt->length > 0) { if (sp.template_ndnb == NULL) { sp.template_ndnb = ndn_charbuf_create(); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_SignedInfo, NDN_DTAG); } else if (sp.template_ndnb->length > 0) { sp.template_ndnb->length--; } ndnb_append_tagged_blob(sp.template_ndnb, NDN_DTAG_ExtOpt, extopt->buf, extopt->length); sp.sp_flags |= NDN_SP_TEMPL_EXT_OPT; ndn_charbuf_append_closer(sp.template_ndnb); } /* Create the signed content object, ready to go */ temp->length = 0; res = ndn_sign_content(ndn, temp, name, &sp, buf, read_res); if (res != 0) { fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res); exit(1); } if (read_res == blocksize) { read_res = read_full(0, buf, 1); if (read_res == 1) { fprintf(stderr, "%s: warning - truncated data\n", argv[0]); status = 1; } } free(buf); buf = NULL; if (force) { /* At user request, send without waiting to see an interest */ res = ndn_put(ndn, temp->buf, temp->length); if (res < 0) { fprintf(stderr, "ndn_put failed (res == %d)\n", res); exit(1); } } else { in_interest.data = temp; /* Set up a handler for interests */ res = ndn_set_interest_filter(ndn, pname, &in_interest); if (res < 0) { fprintf(stderr, "Failed to register interest (res == %d)\n", res); exit(1); } res = ndn_run(ndn, timeout); if (in_interest.intdata == 0) { if (verbose) fprintf(stderr, "Nobody's interested\n"); exit(1); } } if (verbose) { struct ndn_charbuf *uri = ndn_charbuf_create(); uri->length = 0; ndn_uri_append(uri, name->buf, name->length, 1); printf("wrote %s\n", ndn_charbuf_as_string(uri)); ndn_charbuf_destroy(&uri); } ndn_destroy(&ndn); ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&pname); ndn_charbuf_destroy(&temp); ndn_charbuf_destroy(&sp.template_ndnb); ndn_charbuf_destroy(&extopt); exit(status); }