/** * Destroy the ndnr instance, releasing all associated resources. */ PUBLIC void r_init_destroy(struct ndnr_handle **pndnr) { struct ndnr_handle *h = *pndnr; int stable; if (h == NULL) return; stable = h->active_in_fd == -1 ? 1 : 0; r_io_shutdown_all(h); ndnr_direct_client_stop(h); ndn_schedule_destroy(&h->sched); hashtb_destroy(&h->propagating_tab); hashtb_destroy(&h->nameprefix_tab); hashtb_destroy(&h->enum_state_tab); hashtb_destroy(&h->content_by_accession_tab); // SyncActions sync_stop method should be shutting down heartbeat if (h->sync_plumbing) { h->sync_plumbing->sync_methods->sync_stop(h->sync_plumbing, NULL); free(h->sync_plumbing); h->sync_plumbing = NULL; h->sync_base = NULL; // freed by sync_stop ? } r_store_final(h, stable); if (h->fds != NULL) { free(h->fds); h->fds = NULL; h->nfds = 0; } if (h->fdholder_by_fd != NULL) { free(h->fdholder_by_fd); h->fdholder_by_fd = NULL; h->face_limit = h->face_gen = 0; } if (h->content_by_cookie != NULL) { free(h->content_by_cookie); h->content_by_cookie = NULL; h->cookie_limit = 1; } ndn_charbuf_destroy(&h->scratch_charbuf); ndn_indexbuf_destroy(&h->skiplinks); ndn_indexbuf_destroy(&h->scratch_indexbuf); ndn_indexbuf_destroy(&h->unsol); if (h->parsed_policy != NULL) { ndn_indexbuf_destroy(&h->parsed_policy->namespaces); ndn_charbuf_destroy(&h->parsed_policy->store); free(h->parsed_policy); h->parsed_policy = NULL; } ndn_charbuf_destroy(&h->policy_name); ndn_charbuf_destroy(&h->policy_link_cob); ndn_charbuf_destroy(&h->ndnr_keyid); free(h); *pndnr = NULL; }
/* * Destroy the result of a ndn_header_parse or ndn_get_header */ void ndn_header_destroy(struct ndn_header **ph) { if (*ph == NULL) return; ndn_charbuf_destroy(&(*ph)->root_digest); ndn_charbuf_destroy(&(*ph)->content_digest); free(*ph); *ph = NULL; }
/** * Read the contents of the repository config file * * Calls r_init_fail and returns NULL in case of error. * @returns unparsed content of config file in a newly allocated charbuf */ struct ndn_charbuf * r_init_read_config(struct ndnr_handle *h) { struct ndn_charbuf *path = NULL; struct ndn_charbuf *contents = NULL; size_t sz = 800; ssize_t sres = -1; int fd; h->directory = getenv("NDNR_DIRECTORY"); if (h->directory == NULL || h->directory[0] == 0) h->directory = "."; path = ndn_charbuf_create(); contents = ndn_charbuf_create(); if (path == NULL || contents == NULL) return(NULL); ndn_charbuf_putf(path, "%s/config", h->directory); fd = open(ndn_charbuf_as_string(path), O_RDONLY); if (fd == -1) { if (errno == ENOENT) sres = 0; else r_init_fail(h, __LINE__, ndn_charbuf_as_string(path), errno); } else { for (;;) { sres = read(fd, ndn_charbuf_reserve(contents, sz), sz); if (sres == 0) break; if (sres < 0) { r_init_fail(h, __LINE__, "Read failed reading config", errno); break; } contents->length += sres; if (contents->length > 999999) { r_init_fail(h, __LINE__, "config file too large", 0); sres = -1; break; } } close(fd); } ndn_charbuf_destroy(&path); if (sres < 0) ndn_charbuf_destroy(&contents); return(contents); }
enum ndn_upcall_res outgoing_content(struct ndn_closure *selfp, enum ndn_upcall_kind kind, struct ndn_upcall_info *info) { struct mini_store *md; struct ndn_charbuf *cob = NULL; int i; int res = 0; int which; md = selfp->data; which = md->me.intdata; if (kind == NDN_UPCALL_FINAL) { fprintf(stderr, "NDN_UPCALL_FINAL for store %d\n", which); for (i = 0; i < MINI_STORE_LIMIT; i++) ndn_charbuf_destroy(&md->cob[i]); return(NDN_UPCALL_RESULT_OK); } printf("Store %d got interest matching %d components, kind = %d", which, info->matched_comps, kind); /* Look through our little pile of content and send one that matches */ if (kind == NDN_UPCALL_INTEREST) { for (i = 0; i < MINI_STORE_LIMIT; i++) { cob = md->cob[i]; if (cob != NULL && cob_matches(info, cob)) { res = ndn_put(info->h, cob->buf, cob->length); if (res == -1) { fprintf(stderr, "... error sending data\n"); return(NDN_UPCALL_RESULT_ERR); } else { printf("... sent my content:\n"); printraw(cob->buf, cob->length); ndn_charbuf_destroy(&md->cob[i]); return(NDN_UPCALL_RESULT_INTEREST_CONSUMED); } } } printf("... no match\n"); } else printf("\n"); return(NDN_UPCALL_RESULT_ERR); }
/** * Destroy the result of ndn_face_instance_parse(). */ void ndn_face_instance_destroy(struct ndn_face_instance **pfi) { if (*pfi == NULL) return; ndn_charbuf_destroy(&(*pfi)->store); free(*pfi); *pfi = NULL; }
/** * Destroy the result of ndn_forwarding_entry_parse(). */ void ndn_forwarding_entry_destroy(struct ndn_forwarding_entry **pfe) { if (*pfe == NULL) return; ndn_charbuf_destroy(&(*pfe)->name_prefix); free(*pfe); *pfe = NULL; }
struct ndn_header * ndn_get_header(struct ndn *h, struct ndn_charbuf *name, int timeout) { struct ndn_charbuf *hn; struct ndn_header *result = NULL; int res; hn = ndn_charbuf_create(); ndn_charbuf_append_charbuf(hn, name); /* * Requires consistency with metadata profile in * javasrc/src/main/org/ndnx/ndn-tlv/profiles/metadata/MetadataProfile.java */ ndn_name_append(hn, meta, sizeof(meta)); ndn_name_append_str(hn, ".header"); res = ndn_resolve_version(h, hn, NDN_V_HIGHEST, timeout); if (res <= 0) { /* Version not found: try old header name from prior to 04/2010 */ ndn_charbuf_reset(hn); ndn_charbuf_append_charbuf(hn, name); ndn_name_append_str(hn, "_meta_"); ndn_name_append_str(hn, ".header"); res = ndn_resolve_version(h, hn, NDN_V_HIGHEST, timeout); } /* headers must be versioned */ if (res > 0) { struct ndn_charbuf *ho = ndn_charbuf_create(); struct ndn_parsed_ContentObject pcobuf = { 0 }; const unsigned char *hc; size_t hcs; res = ndn_get(h, hn, NULL, timeout, ho, &pcobuf, NULL, 0); if (res == 0) { hc = ho->buf; hcs = ho->length; ndn_content_get_value(hc, hcs, &pcobuf, &hc, &hcs); result = ndn_header_parse(hc, hcs); } ndn_charbuf_destroy(&ho); } ndn_charbuf_destroy(&hn); return (result); }
enum ndn_upcall_res hash_store_handle_proto_sha256(struct hash_store* self, struct ndn_upcall_info* info) { int res; // extract hash const uint8_t* hash; size_t hashsz; res = ndn_name_comp_get(info->interest_ndnb, info->interest_comps, 1, &hash, &hashsz); if (res != 0 || hashsz != SEGMENT_HASHSZ) return NDN_UPCALL_RESULT_ERR; LOG("hash_store_handle_proto_sha256("); LOG_hash(hash, hashsz); LOG(") "); // find content ndnr_accession accession = hash_store_find(self, hash); if (accession == NDNR_NULL_ACCESSION) { LOG("MISS\n"); return NDN_UPCALL_RESULT_OK; } struct content_entry* orig_content = r_store_content_from_accession(self->h, accession); if (orig_content == NULL) { LOG("LOST\n"); return NDN_UPCALL_RESULT_OK; } if (orig_content->cob == NULL && r_store_content_base(self->h, orig_content) == NULL) { LOG("LOST\n"); return NDN_UPCALL_RESULT_OK; } LOG("HIT %" PRIx64 ", ", (uint64_t)ndnr_accession_encode(self->h, accession)); // extract payload struct ndn_parsed_ContentObject orig_pco = {0}; res = ndn_parse_ContentObject(orig_content->cob->buf, orig_content->cob->length, &orig_pco, NULL); if (res != 0) { LOG("cannot parse\n"); return NDN_UPCALL_RESULT_OK; } const uint8_t* payload; size_t payloadsz; res = ndn_content_get_value(orig_content->cob->buf, orig_content->cob->length, &orig_pco, &payload, &payloadsz); if (res != 0) { LOG("cannot extract payload\n"); return NDN_UPCALL_RESULT_OK; } // verify hash if (!hash_store_verify_hash(self, payload, payloadsz, hash)) { LOG("hash mismatch\n"); return NDN_UPCALL_RESULT_OK; } // build reply struct ndn_charbuf* reply = ndn_charbuf_create(); hash_store_build_reply(self, reply, hash, payload, payloadsz); // send reply TODO use queues res = ndn_put(info->h, reply->buf, reply->length); if (res != 0) { LOG("cannot send\n"); ndn_charbuf_destroy(&reply); return NDN_UPCALL_RESULT_OK; } ndn_charbuf_destroy(&reply); LOG("OK\n"); return NDN_UPCALL_RESULT_INTEREST_CONSUMED; }
/** * Basic tests of ndn_btree_io_from_directory() and its methods. * * Assumes TEST_DIRECTORY has been set. */ static int test_btree_io(void) { int res; struct ndn_btree_node nodespace = {0}; struct ndn_btree_node *node = &nodespace; struct ndn_btree_io *io = NULL; /* Open it up. */ io = ndn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL); CHKPTR(io); node->buf = ndn_charbuf_create(); CHKPTR(node->buf); node->nodeid = 12345; res = io->btopen(io, node); CHKSYS(res); FAILIF(node->iodata == NULL); ndn_charbuf_putf(node->buf, "smoke"); res = io->btwrite(io, node); CHKSYS(res); node->buf->length = 0; ndn_charbuf_putf(node->buf, "garbage"); res = io->btread(io, node, 500000); CHKSYS(res); FAILIF(node->buf->length != 5); FAILIF(node->buf->limit > 10000); node->clean = 5; ndn_charbuf_putf(node->buf, "r"); res = io->btwrite(io, node); CHKSYS(res); node->buf->length--; ndn_charbuf_putf(node->buf, "d"); res = io->btread(io, node, 1000); CHKSYS(res); FAILIF(0 != strcmp("smoker", ndn_charbuf_as_string(node->buf))); node->buf->length--; res = io->btwrite(io, node); CHKSYS(res); node->buf->length = 0; ndn_charbuf_putf(node->buf, "garbage"); node->clean = 0; res = io->btread(io, node, 1000); CHKSYS(res); res = io->btclose(io, node); CHKSYS(res); FAILIF(node->iodata != NULL); FAILIF(0 != strcmp("smoke", ndn_charbuf_as_string(node->buf))); res = io->btdestroy(&io); CHKSYS(res); ndn_charbuf_destroy(&node->buf); return(res); }
PUBLIC void ndnr_parsed_policy_destroy(struct ndnr_parsed_policy **ppp) { struct ndnr_parsed_policy *pp; if (*ppp == NULL) return; pp = *ppp; ndn_charbuf_destroy(&pp->store); ndn_indexbuf_destroy(&pp->namespaces); free(pp); *ppp = NULL; }
static int do_ping(struct ndn_schedule *sched, void *clienth, struct ndn_scheduled_event *ev, int flags) { struct ndn_ping_client *client = clienth; if (client->total >= 0 && client->sent >= client->total) return 0; struct ndn_charbuf *name = ndn_charbuf_create(); struct ndn_charbuf *templ = NULL; long int rnum; char rnumstr[20]; int res; ndn_charbuf_append(name, client->prefix->buf, client->prefix->length); if (client->number < 0) rnum = random(); else { rnum = client->number; client->number ++; } memset(&rnumstr, 0, 20); sprintf(rnumstr, "%ld", rnum); ndn_name_append_str(name, rnumstr); templ = make_template(client->allow_caching); res = ndn_express_interest(client->h, name, client->closure, templ); add_ndn_ping_entry(client, name, rnum); client->sent ++; sta.sent ++; ndn_charbuf_destroy(&templ); ndn_charbuf_destroy(&name); if (res < 0) print_log(client->print_timestamp, "failed to express Interest to %s: number = %ld\n", client->original_prefix, rnum); return client->interval * 1000000; }
static struct ndn_charbuf * ndnr_init_policy_cob(struct ndnr_handle *ndnr, struct ndn *h, struct ndn_charbuf *basename, int freshness, struct ndn_charbuf *content) { struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT; struct ndn_charbuf *name = ndn_charbuf_create(); struct ndn_charbuf *pubid = ndn_charbuf_create(); struct ndn_charbuf *pubkey = ndn_charbuf_create(); struct ndn_charbuf *keyid = ndn_charbuf_create(); struct ndn_charbuf *tcob = ndn_charbuf_create(); struct ndn_charbuf *cob = NULL; // result int res; res = ndn_get_public_key(h, NULL, pubid, pubkey); if (res < 0) goto Leave; res = ndn_charbuf_append_charbuf(name, basename); if (ndn_name_from_uri(name, "%00") < 0) goto Leave; sp.sp_flags |= NDN_SP_FINAL_BLOCK; sp.type = NDN_CONTENT_DATA; sp.freshness = freshness; res |= ndn_sign_content(h, tcob, name, &sp, content->buf, content->length); if (res == 0) { cob = tcob; tcob = NULL; } Leave: ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&pubid); ndn_charbuf_destroy(&pubkey); ndn_charbuf_destroy(&keyid); ndn_charbuf_destroy(&tcob); return (cob); }
struct hash_store* hash_store_ctor(struct ndnr_handle* h) { struct hash_store* self = calloc(1, sizeof(*self)); self->h = h; h->hashstore = self; // open btree with disk IO struct ndn_charbuf* path = ndn_charbuf_create(); ndn_charbuf_putf(path, "%s/hashstore", h->directory); int res = mkdir(ndn_charbuf_as_string(path), 0700); if (res != 0 && errno != EEXIST) { free(self); ndn_charbuf_destroy(&path); return NULL; } self->btree = ndn_btree_create(); self->btree->io = ndn_btree_io_from_directory(ndn_charbuf_as_string(path), NULL); if (self->btree->io == NULL) { free(self); ndn_charbuf_destroy(&path); ndn_btree_destroy(&self->btree); return NULL; } ndn_charbuf_destroy(&path); struct ndn_btree_node* node = ndn_btree_getnode(self->btree, 1, 0); self->btree->nextnodeid = self->btree->io->maxnodeid + 1; if (node->buf->length == 0) { res = ndn_btree_init_node(node, 0, 'R', 0); } LOG("hash_store_ctor\n"); return self; }
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); }
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; }
/* * 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); }
static int merge_files(struct ndnr_handle *h) { int i, last_file; int res; struct ndn_charbuf *filename = ndn_charbuf_create(); // first parse the file(s) making sure there are no errors for (i = 2;; i++) { filename->length = 0; ndn_charbuf_putf(filename, "repoFile%d", i); res = r_init_map_and_process_file(h, filename, 0); if (res == 1) break; if (res < 0) { ndnr_msg(h, "Error parsing repository file %s", ndn_charbuf_as_string(filename)); return (-1); } } last_file = i - 1; for (i = 2; i <= last_file; i++) { filename->length = 0; ndn_charbuf_putf(filename, "repoFile%d", i); res = r_init_map_and_process_file(h, filename, 1); if (res < 0) { ndnr_msg(h, "Error in phase 2 incorporating repository file %s", ndn_charbuf_as_string(filename)); return (-1); } } for (i = last_file; i > 1; --i) { filename->length = 0; ndn_charbuf_putf(filename, "%s/repoFile%d", h->directory, i); if (NDNSHOULDLOG(h, LM_128, NDNL_INFO)) ndnr_msg(h, "unlinking %s", ndn_charbuf_as_string(filename)); unlink(ndn_charbuf_as_string(filename)); } ndn_charbuf_destroy(&filename); return (0); }
/** * Advance the last Component of a Name to the next possible value. * @param c contains a ndnb-encoded Name to be updated. * @returns -1 for error, otherwise the number of Components */ int ndn_name_next_sibling(struct ndn_charbuf *c) { int res = -1; struct ndn_indexbuf *ndx; unsigned char *lastcomp = NULL; size_t lastcompsize = 0; size_t i; int carry; struct ndn_charbuf *newcomp; ndx = ndn_indexbuf_create(); if (ndx == NULL) goto Finish; res = ndn_name_split(c, ndx); if (res <= 0) { res = -1; goto Finish; } res = ndn_ref_tagged_BLOB(NDN_DTAG_Component, c->buf, ndx->buf[res-1], ndx->buf[res], (const unsigned char **)&lastcomp, &lastcompsize); if (res < 0) goto Finish; for (carry = 1, i = lastcompsize; carry && i > 0; i--) { carry = (((++lastcomp[i-1]) & 0xFF) == 0x00); } if (carry) { newcomp = ndn_charbuf_create(); res |= ndn_charbuf_append_value(newcomp, 0, 1); res |= ndn_charbuf_append(newcomp, lastcomp, lastcompsize); res |= ndn_name_chop(c, ndx, ndx->n - 2); res |= ndn_name_append(c, newcomp->buf, newcomp->length); ndn_charbuf_destroy(&newcomp); if (res < 0) goto Finish; } res = ndx->n - 1; Finish: ndn_indexbuf_destroy(&ndx); return(res); }
/** * should probably return a new cob, rather than reusing one. * should publish link as: * NDNRID_POLICY_URI("ndn:/%C1.M.S.localhost/%C1.M.SRV/repository/POLICY)/%C1.M.K--pubid--/--version--/%00 * should have key locator which is the key name of the repository */ PUBLIC struct ndn_charbuf * ndnr_init_policy_link_cob(struct ndnr_handle *ndnr, struct ndn *h, struct ndn_charbuf *targetname) { struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT; struct ndn_charbuf *name = ndn_charbuf_create(); struct ndn_charbuf *pubid = ndn_charbuf_create(); struct ndn_charbuf *pubkey = ndn_charbuf_create(); struct ndn_charbuf *keyid = ndn_charbuf_create(); struct ndn_charbuf *content = ndn_charbuf_create(); struct ndn_charbuf *cob = ndn_charbuf_create(); struct ndn_charbuf *answer = NULL; int res; res = ndn_get_public_key(h, NULL, pubid, pubkey); if (res < 0) goto Bail; if (ndn_name_from_uri(name, NDNRID_POLICY_URI) < 0) goto Bail; res |= ndn_charbuf_append_value(keyid, NDN_MARKER_CONTROL, 1); res |= ndn_charbuf_append_string(keyid, ".M.K"); res |= ndn_charbuf_append_value(keyid, 0, 1); res |= ndn_charbuf_append_charbuf(keyid, pubid); res |= ndn_name_append(name, keyid->buf, keyid->length); res |= ndn_create_version(h, name, NDN_V_NOW, 0, 0); if (ndn_name_from_uri(name, "%00") < 0) goto Bail; sp.sp_flags |= NDN_SP_FINAL_BLOCK; sp.type = NDN_CONTENT_LINK; res |= ndnb_append_Link(content, targetname, "Repository Policy", NULL); if (res != 0) goto Bail; res |= ndn_sign_content(h, cob, name, &sp, content->buf, content->length); if (res != 0) goto Bail; answer = cob; cob = NULL; Bail: ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&pubid); ndn_charbuf_destroy(&pubkey); ndn_charbuf_destroy(&keyid); ndn_charbuf_destroy(&content); ndn_charbuf_destroy(&cob); return (answer); }
/** * Use standard mkdtemp() to create a subdirectory of the * current working directory, and set the TEST_DIRECTORY environment * variable with its name. */ static int test_directory_creation(void) { int res; struct ndn_charbuf *dirbuf; char *temp; dirbuf = ndn_charbuf_create(); CHKPTR(dirbuf); res = ndn_charbuf_putf(dirbuf, "./%s", "_bt_XXXXXX"); CHKSYS(res); temp = mkdtemp(ndn_charbuf_as_string(dirbuf)); CHKPTR(temp); res = ndn_charbuf_putf(dirbuf, "/%s", "_test"); CHKSYS(res); res = mkdir(ndn_charbuf_as_string(dirbuf), 0777); CHKSYS(res); printf("Created directory %s\n", ndn_charbuf_as_string(dirbuf)); setenv("TEST_DIRECTORY", ndn_charbuf_as_string(dirbuf), 1); ndn_charbuf_destroy(&dirbuf); 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); }
struct ndn_forwarding_entry * ndn_forwarding_entry_parse(const unsigned char *p, size_t size) { struct ndn_buf_decoder decoder; struct ndn_buf_decoder *d = ndn_buf_decoder_start(&decoder, p, size); struct ndn_charbuf *store = ndn_charbuf_create(); struct ndn_forwarding_entry *result; const unsigned char *val; size_t sz; size_t start; size_t end; int action_off = -1; int ndnd_id_off = -1; if (store == NULL) return(NULL); result = calloc(1, sizeof(*result)); if (result == NULL) { ndn_charbuf_destroy(&store); return(NULL); } if (ndn_buf_match_dtag(d, NDN_DTAG_ForwardingEntry)) { ndn_buf_advance(d); action_off = ndn_parse_tagged_string(d, NDN_DTAG_Action, store); if (ndn_buf_match_dtag(d, NDN_DTAG_Name)) { result->name_prefix = ndn_charbuf_create(); start = d->decoder.token_index; ndn_parse_Name(d, NULL); end = d->decoder.token_index; ndn_charbuf_append(result->name_prefix, p + start, end - start); } else result->name_prefix = NULL; if (ndn_buf_match_dtag(d, NDN_DTAG_PublisherPublicKeyDigest)) { ndn_buf_advance(d); if (ndn_buf_match_blob(d, &val, &sz)) { ndn_buf_advance(d); if (sz != 32) d->decoder.state = -__LINE__; } ndn_buf_check_close(d); if (d->decoder.state >= 0) { ndnd_id_off = store->length; ndn_charbuf_append(store, val, sz); result->ndnd_id_size = sz; } } result->faceid = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FaceID); result->flags = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_ForwardingFlags); result->lifetime = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FreshnessSeconds); ndn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !NDN_FINAL_DSTATE(d->decoder.state) || store->length > sizeof(result->store)) ndn_forwarding_entry_destroy(&result); else { char *b = (char *)result->store; memcpy(b, store->buf, store->length); result->action = (action_off == -1) ? NULL : b + action_off; result->ndnd_id = (ndnd_id_off == -1) ? NULL : result->store + ndnd_id_off; } ndn_charbuf_destroy(&store); return(result); }
/** * Convert a ndnx-scheme URI to a ndnb-encoded Name. * The converted result is placed in c. * On input, c may contain a base name, in which case relative URIs are allowed. * Otherwise c should start out empty, and the URI must be absolute. * @returns -1 if an error is found, otherwise returns the number of characters * that were processed. */ int ndn_name_from_uri(struct ndn_charbuf *c, const char *uri) { int res = 0; struct ndn_charbuf *compbuf = NULL; const char *stop = uri + strlen(uri); const char *s = uri; size_t cont = 0; compbuf = ndn_charbuf_create(); if (compbuf == NULL) return(-1); if (s[0] != '/') { res = ndn_append_uri_component(compbuf, s, stop - s, &cont); if (res < -2) goto Done; ndn_charbuf_reserve(compbuf, 1)[0] = 0; if (s[cont-1] == ':') { if ((0 == strcasecmp((const char *)(compbuf->buf), "ndn:") || 0 == strcasecmp((const char *)(compbuf->buf), "ndn:"))) { s += cont; cont = 0; } else return (-1); } } if (s[0] == '/') { ndn_name_init(c); if (s[1] == '/') { /* Skip over hostname part - not used in ndnx scheme */ s += 2; compbuf->length = 0; res = ndn_append_uri_component(compbuf, s, stop - s, &cont); if (res < 0 && res != -2) goto Done; s += cont; cont = 0; } } while (s[0] != 0 && s[0] != '?' && s[0] != '#') { if (s[0] == '/') s++; compbuf->length = 0; res = ndn_append_uri_component(compbuf, s, stop - s, &cont); s += cont; cont = 0; if (res < -2) goto Done; if (res == -2) { res = 0; /* process . or equiv in URI */ continue; } if (res == -1) { /* process .. in URI - discard last name component */ res = ndn_name_last_component_offset(c->buf, c->length); if (res < 0) goto Done; c->length = res; ndn_charbuf_append_closer(c); continue; } res = ndn_name_append(c, compbuf->buf, compbuf->length); if (res < 0) goto Done; } Done: ndn_charbuf_destroy(&compbuf); if (res < 0) return(-1); if (c->length < 2 || c->buf[c->length-1] != NDN_CLOSE) return(-1); return(s - uri); }
/* * This upcall gets called for each piece of incoming content that * matches one of our interests. We need to issue a new interest that * excludes another component at the current level, and perhaps also * and interest to start exploring the next level. Thus if the matched * interest is * /a/b/c exclude {d,e,f,i,j,k} * and we get * /a/b/c/g/h * we would issue a new interest * /a/b/c exclude {d,e,f,g,i,j,k} * to continue exploring the current level, plus a simple interest * /a/b/c/g * to start exploring the next level as well. * * This does end up fetching each piece of content multiple times, once for * each level in the name. The repeated requests will be answered from the local * content store, though, and so should not generate extra network traffic. * There is a lot of unanswerable interest generated, though. * * To prevent the interests from becoming too huge, we may need to split them. * Thus if the first new interest above were deemed too large, we could instead * issue the two interests * /a/b/c exclude {d,e,f,g,*} * /a/b/c exclude {*,g,i,j,k} * where * stands for a Bloom filter that excludes anything. Note the * repetition of g to ensure that these two interests cover disjoint portions * of the hierarchy. We need to keep track of the endpoint conditions * as well as the excluded set in our upcall data. * When a split happens, we need a new closure to track it, as we do when * we start exploring a new level. */ static enum ndn_upcall_res incoming_content( struct ndn_closure *selfp, enum ndn_upcall_kind kind, struct ndn_upcall_info *info) { struct ndn_charbuf *c = NULL; struct ndn_charbuf *comp = NULL; struct ndn_charbuf *uri = NULL; const unsigned char *ndnb = NULL; size_t ndnb_size = 0; struct ndn_indexbuf *comps = NULL; int matched_comps = 0; int res; int i; struct ndn_traversal *data = get_my_data(selfp); if (kind == NDN_UPCALL_FINAL) { for (i = 0; i < data->n_excl; i++) ndn_charbuf_destroy(&(data->excl[i])); if (data->excl != NULL) free(data->excl); free(data); free(selfp); return(0); } if (kind == NDN_UPCALL_INTEREST_TIMED_OUT) return(0); if (kind == NDN_UPCALL_CONTENT_BAD) return(0); if (kind == NDN_UPCALL_CONTENT_UNVERIFIED) { if ((data->flags & MUST_VERIFY) != 0) return(NDN_UPCALL_RESULT_VERIFY); } if (kind != NDN_UPCALL_CONTENT && kind != NDN_UPCALL_CONTENT_UNVERIFIED) abort(); ndnb = info->content_ndnb; ndnb_size = info->pco->offset[NDN_PCO_E]; comps = info->content_comps; matched_comps = info->pi->prefix_comps; c = ndn_charbuf_create(); uri = ndn_charbuf_create(); if (matched_comps + 1 > comps->n) { ndn_uri_append(c, ndnb, ndnb_size, 1); fprintf(stderr, "How did this happen? %s\n", ndn_charbuf_as_string(uri)); exit(1); } data->counter[0]++; /* Tell main that something new came in */ /* Recover the same prefix as before */ ndn_name_init(c); ndn_name_append_components(c, ndnb, comps->buf[0], comps->buf[matched_comps]); comp = ndn_charbuf_create(); ndn_name_init(comp); if (matched_comps + 1 == comps->n) { /* Reconstruct the implicit content digest component */ ndn_digest_ContentObject(ndnb, info->pco); ndn_name_append(comp, info->pco->digest, info->pco->digest_bytes); } else { ndn_name_append_components(comp, ndnb, comps->buf[matched_comps], comps->buf[matched_comps + 1]); } data->excl = realloc(data->excl, (data->n_excl + 1) * sizeof(data->excl[0])); data->excl[data->n_excl++] = comp; comp = NULL; qsort(data->excl, data->n_excl, sizeof(data->excl[0]), &namecompare); res = express_my_interest(info->h, selfp, c); if (res == -1) { struct ndn_closure *high = split_my_excludes(selfp); if (high == NULL) abort(); express_my_interest(info->h, selfp, c); express_my_interest(info->h, high, c); } /* Explore the next level, if there is one. */ if (matched_comps + 2 < comps->n) { struct ndn_traversal *newdat = NULL; struct ndn_closure *cl; newdat = calloc(1, sizeof(*newdat)); newdat->magic = 68955871; newdat->warn = 1492; newdat->counter = data->counter; newdat->flags = data->flags & ~(EXCLUDE_LOW | EXCLUDE_HIGH); newdat->n_excl = 0; newdat->excl = NULL; cl = calloc(1, sizeof(*cl)); cl->p = &incoming_content; cl->data = newdat; ndn_name_init(c); ndn_name_append_components(c, ndnb, comps->buf[0], comps->buf[matched_comps + 1]); express_my_interest(info->h, cl, c); } else { res = ndn_uri_append(uri, info->content_ndnb, info->pco->offset[NDN_PCO_E], 1); if (res < 0) fprintf(stderr, "*** Error: ndn_traverse line %d res=%d\n", __LINE__, res); else printf("%s\n", ndn_charbuf_as_string(uri)); } ndn_charbuf_destroy(&c); ndn_charbuf_destroy(&uri); return(0); }
/** * Parse the buffered configuration found in config * * The pass argument controls what is done with the result: * 0 - silent check for syntax errors; * 1 - check for syntax errors and warnings, logging the results, * 2 - incorporate settings into environ. * * @returns -1 if an error is found, otherwise the count of warnings. */ int r_init_parse_config(struct ndnr_handle *h, struct ndn_charbuf *config, int pass) { struct ndn_charbuf *key = NULL; struct ndn_charbuf *value = NULL; const unsigned char *b; int line; size_t i; size_t sol; /* start of line */ size_t len; /* config->len */ size_t ndx; /* temp for column report*/ int ch; int warns = 0; int errors = 0; int use_it = 0; static const char pclegal[] = "~@%-+=:,./[]" "abcdefghijklmnopqrstuvwxyz" "0123456789" "_" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *klegal = strchr(pclegal, 'a'); int flags; /* for reporting */ b = config->buf; len = config->length; if (len == 0) return(0); ndn_charbuf_as_string(config); key = ndn_charbuf_create(); value = ndn_charbuf_create(); if (key == NULL || value == NULL) return(-1); /* Ensure there is null termination in the buffered config */ if (ndn_charbuf_as_string(config) == NULL) return(-1); for (line = 1, i = 0, ch = b[0], sol = 0; i < len;) { flags = pass; use_it = 0; if (ch > ' ' && ch != '#') { key->length = value->length = 0; /* parse key */ while (i < len && ch != '\n' && ch != '=') { ndn_charbuf_append_value(key, ch, 1); ch = b[++i]; } if (ch == '=') ch = b[++i]; else { r_init_config_msg(h, flags, line, key->length, "missing '='"); flags |= NDNR_CONFIG_IGNORELINE; warns++; ch = '\n'; } /* parse value */ while (i < len && ch > ' ') { ndn_charbuf_append_value(value, ch, 1); ch = b[++i]; } /* See if it might be one of ours */ if (key->length < 5 || (memcmp(key->buf, "NDNR_", 5) != 0 && memcmp(key->buf, "NDNS_", 5) != 0)) { r_init_config_msg(h, flags, line, 0, "ignoring unrecognized key"); flags |= NDNR_CONFIG_IGNORELINE; warns++; use_it = 0; } else use_it = 1; /* Check charset of key */ ndx = strspn(ndn_charbuf_as_string(key), klegal); if (ndx != key->length) { errors += use_it; r_init_config_msg(h, (flags | NDNR_CONFIG_ERR), line, ndx, "unexpected character in key"); flags |= NDNR_CONFIG_IGNORELINE; warns++; } /* Check charset of value */ ndx = strspn(ndn_charbuf_as_string(value), pclegal); if (ndx != value->length) { errors += use_it; r_init_config_msg(h, (flags | NDNR_CONFIG_ERR), line, key->length + 1 + ndx, "unexpected character in value"); flags |= NDNR_CONFIG_IGNORELINE; warns++; } } if (ch == '#') { /* a comment line or error recovery. */ while (i < len && ch != '\n') ch = b[++i]; } while (i < len && ch <= ' ') { if (ch == '\n') { line++; sol = i; break; } if (memchr("\r\t ", ch, 3) == NULL) { r_init_config_msg(h, pass, line, i - sol, "non-whitespace control char at end of line"); warns++; } ch = b[++i]; } if (i == len) { r_init_config_msg(h, flags, line, i - sol, "missing newline at end of file"); warns++; ch = '\n'; } else if (ch == '\n') ch = b[++i]; else { r_init_config_msg(h, flags, line, i - sol, "junk at end of line"); flags |= NDNR_CONFIG_IGNORELINE; warns++; ch = '#'; } if (flags == 0 && strcmp(ndn_charbuf_as_string(key), "NDNR_DEBUG") == 0) { /* Set this on pass 0 so that it takes effect sooner. */ h->debug = 1; setenv("NDNR_DEBUG", ndn_charbuf_as_string(value), 1); h->debug = r_init_debug_getenv(h, "NDNR_DEBUG"); } if (pass == 2 && use_it) { if (NDNSHOULDLOG(h, mmm, NDNL_FINEST)) ndnr_msg(h, "config: %s=%s", ndn_charbuf_as_string(key), ndn_charbuf_as_string(value)); setenv(ndn_charbuf_as_string(key), ndn_charbuf_as_string(value), 1); } } ndn_charbuf_destroy(&key); ndn_charbuf_destroy(&value); return(errors ? -1 : warns); }
/** * Resolve the version, based on existing ndn content. * @param h is the the ndn handle; it may be NULL, but it is preferable to * use the handle that the client probably already has. * @param name is a ndnb-encoded Name prefix. It gets extended in-place with * one additional Component such that it names highest extant * version that can be found, subject to the supplied timeout. * @param versioning_flags presently must be NDN_V_HIGH or NDN_V_HIGHEST, * possibly combined with NDN_V_NESTOK. If NDN_V_NESTOK is not present * and the ending component appears to be a version, the routine * returns 0 immediately, on the assumption that an explicit * version has already been provided. * @param timeout_ms is a time value in milliseconds. This is the total time * that the caller can wait. * @returns -1 for error, 0 if name was not extended, 1 if was. */ int ndn_resolve_version(struct ndn *h, struct ndn_charbuf *name, int versioning_flags, int timeout_ms) { int res; int myres = -1; struct ndn_parsed_ContentObject pco_space = { 0 }; struct ndn_charbuf *templ = NULL; struct ndn_charbuf *prefix = ndn_charbuf_create(); struct ndn_charbuf *cobj = ndn_charbuf_create(); struct ndn_parsed_ContentObject *pco = &pco_space; struct ndn_indexbuf *ndx = ndn_indexbuf_create(); const unsigned char *vers = NULL; size_t vers_size = 0; struct timeval start, prev, now; int n; int rtt_max = 0; int rtt; int ttimeout; struct ndn_indexbuf *nix = ndn_indexbuf_create(); unsigned char lowtime[7] = {NDN_MARKER_VERSION, 0, FF, FF, FF, FF, FF}; if ((versioning_flags & ~NDN_V_NESTOK & ~NDN_V_EST) != NDN_V_HIGH) { ndn_seterror(h, EINVAL); ndn_perror(h, "ndn_resolve_version is only implemented for versioning_flags = NDN_V_HIGH(EST)"); goto Finish; } n = ndn_name_split(name, nix); if (n < 0) goto Finish; if ((versioning_flags & NDN_V_NESTOK) == 0) { res = ndn_name_comp_get(name->buf, nix, n - 1, &vers, &vers_size); if (res >= 0 && vers_size == 7 && vers[0] == NDN_MARKER_VERSION) { myres = 0; goto Finish; } } templ = resolve_templ(templ, lowtime, sizeof(lowtime), ms_to_tu(timeout_ms) * 7 / 8, versioning_flags); ndn_charbuf_append(prefix, name->buf, name->length); /* our copy */ cobj->length = 0; gettimeofday(&start, NULL); prev = start; /* * the algorithm for NDN_V_HIGHEST is to send the initial Interest with * a lifetime that will ensure 1 resend before the timeout, and to keep * keep sending an Interest, excluding earlier versions, tracking the * maximum round trip time and using a timeout of 4*RTT, and an interest * lifetime that should get a retransmit. If there is no response, * return the highest version found so far. */ myres = 0; res = ndn_get(h, prefix, templ, timeout_ms, cobj, pco, ndx, 0); while (cobj->length != 0) { if (pco->type == NDN_CONTENT_NACK) // XXX - also check for number of components break; res = ndn_name_comp_get(cobj->buf, ndx, n, &vers, &vers_size); if (res < 0) break; if (vers_size == 7 && vers[0] == NDN_MARKER_VERSION) { /* Looks like we have versions. */ name->length = 0; ndn_charbuf_append(name, prefix->buf, prefix->length); ndn_name_append(name, vers, vers_size); myres = 1; if ((versioning_flags & NDN_V_EST) == 0) break; gettimeofday(&now, NULL); rtt = (now.tv_sec - prev.tv_sec) * 1000000 + (now.tv_usec - prev.tv_usec); if (rtt > rtt_max) rtt_max = rtt; prev = now; timeout_ms -= (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000; if (timeout_ms <= 0) break; ttimeout = timeout_ms < (rtt_max/250) ? timeout_ms : (rtt_max/250); templ = resolve_templ(templ, vers, vers_size, ms_to_tu(ttimeout) * 7 / 8, versioning_flags); if (templ == NULL) break; cobj->length = 0; res = ndn_get(h, prefix, templ, ttimeout, cobj, pco, ndx, NDN_GET_NOKEYWAIT); } else break; } Finish: ndn_charbuf_destroy(&prefix); ndn_charbuf_destroy(&cobj); ndn_indexbuf_destroy(&ndx); ndn_indexbuf_destroy(&nix); ndn_charbuf_destroy(&templ); return(myres); }
int main(int argc, char **argv) { const char *progname = argv[0]; struct ndn *ndn = NULL; struct ndn_charbuf *root = NULL; struct ndn_charbuf *name = NULL; struct ndn_charbuf *temp = NULL; struct ndn_charbuf *templ = NULL; struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT; long expire = -1; long blocksize = 1024; int i; int status = 0; int res; ssize_t read_res; unsigned char *buf = NULL; struct mydata mydata = { 0 }; struct ndn_closure in_content = {.p=&incoming_content, .data=&mydata}; struct ndn_closure in_interest = {.p=&incoming_interest, .data=&mydata}; while ((res = getopt(argc, argv, "hx:b:")) != -1) { switch (res) { case 'x': expire = atol(optarg); if (expire <= 0) usage(progname); break; case 'b': blocksize = atol(optarg); break; default: case 'h': usage(progname); break; } } argc -= optind; argv += optind; if (argc != 1) 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); } ndn = ndn_create(); if (ndn_connect(ndn, NULL) == -1) { perror("Could not connect to ndnd"); exit(1); } buf = calloc(1, blocksize); root = name; name = ndn_charbuf_create(); temp = ndn_charbuf_create(); templ = ndn_charbuf_create(); /* Set up a handler for interests */ ndn_charbuf_append(name, root->buf, root->length); ndn_set_interest_filter(ndn, name, &in_interest); /* Initiate check to see whether there is already something there. */ ndn_charbuf_reset(temp); ndn_charbuf_putf(temp, "%d", 0); ndn_name_append(name, temp->buf, temp->length); ndn_charbuf_reset(templ); ndnb_element_begin(templ, NDN_DTAG_Interest); ndnb_element_begin(templ, NDN_DTAG_Name); ndnb_element_end(templ); /* </Name> */ ndnb_tagged_putf(templ, NDN_DTAG_MaxSuffixComponents, "%d", 1); // XXX - use pubid ndnb_element_end(templ); /* </Interest> */ res = ndn_express_interest(ndn, name, &in_content, templ); if (res < 0) abort(); sp.freshness = expire; for (i = 0;; i++) { read_res = read_full(0, buf, blocksize); if (read_res < 0) { perror("read"); read_res = 0; status = 1; } if (read_res < blocksize) { sp.sp_flags |= NDN_SP_FINAL_BLOCK; } ndn_charbuf_reset(name); ndn_charbuf_append(name, root->buf, root->length); ndn_charbuf_reset(temp); ndn_charbuf_putf(temp, "%d", i); ndn_name_append(name, temp->buf, temp->length); ndn_charbuf_reset(temp); ndn_charbuf_append(temp, buf, read_res); ndn_charbuf_reset(temp); res = ndn_sign_content(ndn, temp, name, &sp, buf, read_res); if (res != 0) { fprintf(stderr, "Failed to sign ContentObject (res == %d)\n", res); exit(1); } /* Put the keylocator in the first block only. */ sp.sp_flags |= NDN_SP_OMIT_KEY_LOCATOR; if (i == 0) { /* Finish check for old content */ if (mydata.content_received == 0) ndn_run(ndn, 100); if (mydata.content_received > 0) { fprintf(stderr, "%s: name is in use: %s\n", progname, argv[0]); exit(1); } mydata.outstanding++; /* the first one is free... */ } res = ndn_put(ndn, temp->buf, temp->length); if (res < 0) { fprintf(stderr, "ndn_put failed (res == %d)\n", res); exit(1); } if (read_res < blocksize) break; if (mydata.outstanding > 0) mydata.outstanding--; else res = 10; res = ndn_run(ndn, res * 100); if (res < 0) { status = 1; break; } } free(buf); buf = NULL; ndn_charbuf_destroy(&root); ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&temp); ndn_destroy(&ndn); exit(status); }
/** * Load a link to the repo policy from the repoPolicy file and load the link * target to extract the actual policy. * If a policy file does not exist a new one is created, with a link to a policy * based either on the environment variable NDNR_GLOBAL_PREFIX or the system * default value of ndn:/named-data.net/ndn/Repos, plus the system defaults for * other fields. * This routine must be called after the btree code is initialized and capable * of returning content objects. * Sets the parsed_policy field of the handle to be the new policy. */ static int load_policy(struct ndnr_handle *ndnr) { int fd; ssize_t res; struct content_entry *content = NULL; const unsigned char *content_msg = NULL; struct ndn_parsed_ContentObject pco = {0}; struct ndn_parsed_Link pl = {0}; struct ndn_indexbuf *nc = NULL; struct ndn_charbuf *basename = NULL; struct ndn_charbuf *policy = NULL; struct ndn_charbuf *policy_cob = NULL; struct ndn_charbuf *policyFileName; const char *global_prefix; const unsigned char *buf = NULL; size_t length = 0; int segment = 0; int final = 0; struct ndn_buf_decoder decoder; struct ndn_buf_decoder *d; policyFileName = ndn_charbuf_create(); ndn_charbuf_putf(policyFileName, "%s/repoPolicy", ndnr->directory); ndnr->parsed_policy = ndnr_parsed_policy_create(); fd = open(ndn_charbuf_as_string(policyFileName), O_RDONLY); if (fd >= 0) { ndnr->policy_link_cob = ndn_charbuf_create(); ndn_charbuf_reserve(ndnr->policy_link_cob, 4096); // limits the size of the policy link ndnr->policy_link_cob->length = 0; // clear the buffer res = read(fd, ndnr->policy_link_cob->buf, ndnr->policy_link_cob->limit - ndnr->policy_link_cob->length); close(fd); if (res == -1) { r_init_fail(ndnr, __LINE__, "Error reading repoPolicy file.", errno); ndn_charbuf_destroy(&ndnr->policy_link_cob); ndn_charbuf_destroy(&policyFileName); return(-1); } ndnr->policy_link_cob->length = res; nc = ndn_indexbuf_create(); res = ndn_parse_ContentObject(ndnr->policy_link_cob->buf, ndnr->policy_link_cob->length, &pco, nc); res = ndn_ref_tagged_BLOB(NDN_DTAG_Content, ndnr->policy_link_cob->buf, pco.offset[NDN_PCO_B_Content], pco.offset[NDN_PCO_E_Content], &buf, &length); d = ndn_buf_decoder_start(&decoder, buf, length); res = ndn_parse_Link(d, &pl, NULL); if (res <= 0) { ndnr_msg(ndnr, "Policy link is malformed."); goto CreateNewPolicy; } basename = ndn_charbuf_create(); ndn_charbuf_append(basename, buf + pl.offset[NDN_PL_B_Name], pl.offset[NDN_PL_E_Name] - pl.offset[NDN_PL_B_Name]); ndnr->policy_name = ndn_charbuf_create(); // to detect writes to this name ndn_charbuf_append_charbuf(ndnr->policy_name, basename); // has version ndn_name_chop(ndnr->policy_name, NULL, -1); // get rid of version policy = ndn_charbuf_create(); // if we fail to retrieve the link target, report and then create a new one do { ndn_name_append_numeric(basename, NDN_MARKER_SEQNUM, segment++); content = r_store_lookup_ndnb(ndnr, basename->buf, basename->length); if (content == NULL) { ndnr_debug_ndnb(ndnr, __LINE__, "policy lookup failed for", NULL, basename->buf, basename->length); break; } ndn_name_chop(basename, NULL, -1); content_msg = r_store_content_base(ndnr, content); if (content_msg == NULL) { ndnr_debug_ndnb(ndnr, __LINE__, "Unable to read policy object", NULL, basename->buf, basename->length); break; } res = ndn_parse_ContentObject(content_msg, r_store_content_size(ndnr, content), &pco, nc); res = ndn_ref_tagged_BLOB(NDN_DTAG_Content, content_msg, pco.offset[NDN_PCO_B_Content], pco.offset[NDN_PCO_E_Content], &buf, &length); ndn_charbuf_append(policy, buf, length); final = ndn_is_final_pco(content_msg, &pco, nc); } while (!final && segment < 100);
/** * Parse a ndnb-ecoded FaceInstance into an internal representation * * The space used for the various strings is held by the charbuf. * A client may replace the strings with other pointers, but then * assumes responsibilty for managing those pointers. * @returns pointer to newly allocated structure describing the face, or * NULL if there is an error. */ struct ndn_face_instance * ndn_face_instance_parse(const unsigned char *p, size_t size) { struct ndn_buf_decoder decoder; struct ndn_buf_decoder *d = ndn_buf_decoder_start(&decoder, p, size); struct ndn_charbuf *store = ndn_charbuf_create(); struct ndn_face_instance *result; const unsigned char *val; size_t sz; int action_off = -1; int ndnd_id_off = -1; int host_off = -1; int port_off = -1; int mcast_off = -1; if (store == NULL) return(NULL); result = calloc(1, sizeof(*result)); if (result == NULL) { ndn_charbuf_destroy(&store); return(NULL); } result->store = store; if (ndn_buf_match_dtag(d, NDN_DTAG_FaceInstance)) { ndn_buf_advance(d); action_off = ndn_parse_tagged_string(d, NDN_DTAG_Action, store); if (ndn_buf_match_dtag(d, NDN_DTAG_PublisherPublicKeyDigest)) { ndn_buf_advance(d); if (ndn_buf_match_blob(d, &val, &sz)) { ndn_buf_advance(d); if (sz != 32) d->decoder.state = -__LINE__; } ndn_buf_check_close(d); if (d->decoder.state >= 0) { ndnd_id_off = store->length; ndn_charbuf_append(store, val, sz); result->ndnd_id_size = sz; } } result->faceid = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FaceID); result->descr.ipproto = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_IPProto); host_off = ndn_parse_tagged_string(d, NDN_DTAG_Host, store); port_off = ndn_parse_tagged_string(d, NDN_DTAG_Port, store); mcast_off = ndn_parse_tagged_string(d, NDN_DTAG_MulticastInterface, store); result->descr.mcast_ttl = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_MulticastTTL); result->lifetime = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FreshnessSeconds); ndn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !NDN_FINAL_DSTATE(d->decoder.state)) ndn_face_instance_destroy(&result); else { char *b = (char *)store->buf; result->action = (action_off == -1) ? NULL : b + action_off; result->ndnd_id = (ndnd_id_off == -1) ? NULL : store->buf + ndnd_id_off; result->descr.address = (host_off == -1) ? NULL : b + host_off; result->descr.port = (port_off == -1) ? NULL : b + port_off; result->descr.source_address = (mcast_off == -1) ? NULL : b + mcast_off; } return(result); }
/** * Create a new ndnr instance * @param progname - name of program binary, used for locating helpers * @param logger - logger function * @param loggerdata - data to pass to logger function */ PUBLIC struct ndnr_handle * r_init_create(const char *progname, ndnr_logger logger, void *loggerdata) { char *sockname = NULL; const char *portstr = NULL; const char *listen_on = NULL; const char *d = NULL; struct ndnr_handle *h = NULL; struct hashtb_param param = {0}; struct ndn_charbuf *config = NULL; int res; h = calloc(1, sizeof(*h)); if (h == NULL) return(h); h->notify_after = 0; //NDNR_MAX_ACCESSION; h->logger = logger; h->loggerdata = loggerdata; h->logpid = (int)getpid(); h->progname = progname; h->debug = -1; config = r_init_read_config(h); if (config == NULL) goto Bail; r_init_parse_config(h, config, 0); /* silent pass to pick up NDNR_DEBUG */ h->debug = 1; /* so that we see any complaints */ h->debug = r_init_debug_getenv(h, "NDNR_DEBUG"); res = r_init_parse_config(h, config, 1); if (res < 0) { h->running = -1; goto Bail; } r_init_parse_config(h, config, 2); sockname = r_net_get_local_sockname(); h->skiplinks = ndn_indexbuf_create(); h->face_limit = 10; /* soft limit */ h->fdholder_by_fd = calloc(h->face_limit, sizeof(h->fdholder_by_fd[0])); param.finalize_data = h; param.finalize = &r_fwd_finalize_nameprefix; h->nameprefix_tab = hashtb_create(sizeof(struct nameprefix_entry), ¶m); param.finalize = 0; // PRUNED &r_fwd_finalize_propagating; h->propagating_tab = hashtb_create(sizeof(struct propagating_entry), ¶m); param.finalize = &r_proto_finalize_enum_state; h->enum_state_tab = hashtb_create(sizeof(struct enum_state), ¶m); h->min_stale = ~0; h->max_stale = 0; h->unsol = ndn_indexbuf_create(); h->ticktock.descr[0] = 'C'; h->ticktock.micros_per_base = 1000000; h->ticktock.gettime = &r_util_gettime; h->ticktock.data = h; h->sched = ndn_schedule_create(h, &h->ticktock); h->starttime = h->sec; h->starttime_usec = h->usec; h->oldformatcontentgrumble = 1; h->oldformatinterestgrumble = 1; h->cob_limit = 4201; h->start_write_scope_limit = r_init_confval(h, "NDNR_START_WRITE_SCOPE_LIMIT", 0, 3, 3); h->debug = 1; /* so that we see any complaints */ h->debug = r_init_debug_getenv(h, "NDNR_DEBUG"); h->syncdebug = r_init_debug_getenv(h, "NDNS_DEBUG"); portstr = getenv("NDNR_STATUS_PORT"); if (portstr == NULL || portstr[0] == 0 || strlen(portstr) > 10) portstr = ""; h->portstr = portstr; ndnr_msg(h, "NDNR_DEBUG=%d NDNR_DIRECTORY=%s NDNR_STATUS_PORT=%s", h->debug, h->directory, h->portstr); listen_on = getenv("NDNR_LISTEN_ON"); if (listen_on != NULL && listen_on[0] != 0) ndnr_msg(h, "NDNR_LISTEN_ON=%s", listen_on); if (ndnr_init_repo_keystore(h, NULL) < 0) { h->running = -1; goto Bail; } r_util_reseed(h); r_store_init(h); if (h->running == -1) goto Bail; while (h->active_in_fd >= 0) { r_dispatch_process_input(h, h->active_in_fd); r_store_trim(h, h->cob_limit); ndn_schedule_run(h->sched); } ndnr_msg(h, "Repository file is indexed"); if (h->face0 == NULL) { struct fdholder *fdholder; fdholder = calloc(1, sizeof(*fdholder)); if (dup2(open("/dev/null", O_RDONLY), 0) == -1) ndnr_msg(h, "stdin: %s", strerror(errno)); fdholder->filedesc = 0; fdholder->flags = (NDNR_FACE_GG | NDNR_FACE_NORECV); r_io_enroll_face(h, fdholder); } ndnr_direct_client_start(h); d = getenv("NDNR_SKIP_VERIFY"); #if (NDN_API_VERSION >= 4004) if (d != NULL && strcmp(d, "1") == 0) { ndnr_msg(h, "NDNR_SKIP_VERIFY=%s", d); ndn_defer_verification(h->direct_client, 1); } #endif if (ndn_connect(h->direct_client, NULL) != -1) { int af = 0; int bufsize; int flags; int fd; struct fdholder *fdholder; fd = ndn_get_connection_fd(h->direct_client); // Play a dirty trick here - if this wins, we can fix it right in the c lib later on... af = try_tcp_instead(fd); flags = NDNR_FACE_NDND; if (af == AF_INET) flags |= NDNR_FACE_INET; else if (af == AF_INET6) flags |= NDNR_FACE_INET6; else flags |= NDNR_FACE_LOCAL; fdholder = r_io_record_fd(h, fd, "NDND", 5, flags); if (fdholder == NULL) abort(); ndnr_uri_listen(h, h->direct_client, "ndn:/%C1.M.S.localhost/%C1.M.SRV/repository", &ndnr_answer_req, OP_SERVICE); ndnr_uri_listen(h, h->direct_client, "ndn:/%C1.M.S.neighborhood/%C1.M.SRV/repository", &ndnr_answer_req, OP_SERVICE); bufsize = r_init_confval(h, "NDNR_MIN_SEND_BUFSIZE", 1, 2097152, 16384); establish_min_send_bufsize(h, fd, bufsize); } else ndn_disconnect(h->direct_client); // Apparently ndn_connect error case needs work. if (1 == r_init_confval(h, "NDNS_ENABLE", 0, 1, 1)) { h->sync_plumbing = calloc(1, sizeof(struct sync_plumbing)); h->sync_plumbing->ndn = h->direct_client; h->sync_plumbing->sched = h->sched; h->sync_plumbing->client_methods = &sync_client_methods; h->sync_plumbing->client_data = h; h->sync_base = SyncNewBaseForActions(h->sync_plumbing); } if (-1 == load_policy(h)) goto Bail; r_net_listen_on(h, listen_on); ndnr_internal_client_start(h); r_proto_init(h); r_proto_activate_policy(h, h->parsed_policy); if (merge_files(h) == -1) r_init_fail(h, __LINE__, "Unable to merge additional repository data files.", errno); if (h->running == -1) goto Bail; if (h->sync_plumbing) { // Start sync running // returns < 0 if a failure occurred // returns 0 if the name updates should fully restart // returns > 0 if the name updates should restart at last fence res = h->sync_plumbing->sync_methods->sync_start(h->sync_plumbing, NULL); if (res < 0) { r_init_fail(h, __LINE__, "starting sync", res); abort(); } else if (res > 0) { // XXX: need to work out details of starting from last fence. // By examination of code, SyncActions won't take this path } } Bail: if (sockname) free(sockname); sockname = NULL; ndn_charbuf_destroy(&config); if (h->running == -1) r_init_destroy(&h); return(h); }