bool hash_store_insert(struct hash_store* self, ndnr_accession accession, struct ndn_charbuf* co, struct ndn_parsed_ContentObject* pco) { int res; // retrieve payload struct ndn_parsed_ContentObject pco2 = {0}; if (pco == NULL) { res = ndn_parse_ContentObject(co->buf, co->length, pco = &pco2, NULL); if (res != 0) return false; } const uint8_t* payload; size_t payloadsz; ndn_content_get_value(co->buf, co->length, pco, &payload, &payloadsz); // calculate hash uint8_t hash[SEGMENT_HASHSZ]; struct ndn_digest* digest = ndn_digest_create(NDN_DIGEST_SHA256); ndn_digest_init(digest); ndn_digest_update(digest, payload, payloadsz); ndn_digest_final(digest, hash, sizeof(hash)); ndn_digest_destroy(&digest); LOG("hash_store_insert(%" PRIx64 ") ", (uint64_t)ndnr_accession_encode(self->h, accession)); LOG_hash(hash, SEGMENT_HASHSZ); // find where to insert struct ndn_btree_node* leaf = NULL; res = ndn_btree_lookup(self->btree, hash, sizeof(hash), &leaf); int i = NDN_BT_SRCH_INDEX(res); if (NDN_BT_SRCH_FOUND(res)) { LOG(" duplicate(%u,%d)\n", leaf->nodeid, i); return true;// already have it } LOG(" insert(%u,%d)\n", leaf->nodeid, i); // prepare payload uint64_t accession_encoded = ndnr_accession_encode(self->h, accession); // insert index entry res = ndn_btree_prepare_for_update(self->btree, leaf); if (res < 0) return false; res = ndn_btree_insert_entry(leaf, i, hash, sizeof(hash), &accession_encoded, sizeof(accession_encoded)); if (res < 0) return false; // btree maintenance if (ndn_btree_oversize(self->btree, leaf)) { res = ndn_btree_split(self->btree, leaf); for (int limit = 100; res >= 0 && self->btree->nextsplit != 0; --limit) { if (limit == 0) abort(); struct ndn_btree_node* node = ndn_btree_getnode(self->btree, self->btree->nextsplit, 0); if (node == NULL) break; res = ndn_btree_split(self->btree, node); } } hash_store_clean(self); return true; }
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; }
/** * Handle the incoming content messages. Extracts the data, and * requests the next block in sequence if the received block was * not the final one. */ enum ndn_upcall_res incoming_content(struct ndn_closure *selfp, enum ndn_upcall_kind kind, struct ndn_upcall_info *info) { struct ndn_charbuf *name = NULL; struct ndn_charbuf *templ = NULL; const unsigned char *ndnb = NULL; size_t ndnb_size = 0; const unsigned char *data = NULL; size_t data_size = 0; size_t written; const unsigned char *ib = NULL; /* info->interest_ndnb */ struct ndn_indexbuf *ic = NULL; int res; struct mydata *md = selfp->data; if (kind == NDN_UPCALL_FINAL) { if (md != NULL) { selfp->data = NULL; free(md); md = NULL; } return(NDN_UPCALL_RESULT_OK); } if (kind == NDN_UPCALL_INTEREST_TIMED_OUT) return(NDN_UPCALL_RESULT_REEXPRESS); if (kind == NDN_UPCALL_CONTENT_UNVERIFIED) return(NDN_UPCALL_RESULT_VERIFY); if (kind != NDN_UPCALL_CONTENT) return(NDN_UPCALL_RESULT_ERR); if (md == NULL) selfp->data = md = calloc(1, sizeof(*md)); ndnb = info->content_ndnb; ndnb_size = info->pco->offset[NDN_PCO_E]; ib = info->interest_ndnb; ic = info->interest_comps; res = ndn_content_get_value(ndnb, ndnb_size, info->pco, &data, &data_size); if (res < 0) abort(); if (info->pco->type != NDN_CONTENT_DATA) { /* For us this is spam. For now, give up. */ fprintf(stderr, "*** spammed at block %d\n", (int)selfp->intdata); exit(1); } /* OK, we will accept this block. */ if (data_size == 0) *(md->done) = 1; else { written = fwrite(data, data_size, 1, stdout); if (written != 1) exit(1); } // XXX The test below should get refactored into the library if (info->pco->offset[NDN_PCO_B_FinalBlockID] != info->pco->offset[NDN_PCO_E_FinalBlockID]) { const unsigned char *finalid = NULL; size_t finalid_size = 0; const unsigned char *nameid = NULL; size_t nameid_size = 0; struct ndn_indexbuf *cc = info->content_comps; ndn_ref_tagged_BLOB(NDN_DTAG_FinalBlockID, ndnb, info->pco->offset[NDN_PCO_B_FinalBlockID], info->pco->offset[NDN_PCO_E_FinalBlockID], &finalid, &finalid_size); if (cc->n < 2) abort(); ndn_ref_tagged_BLOB(NDN_DTAG_Component, ndnb, cc->buf[cc->n - 2], cc->buf[cc->n - 1], &nameid, &nameid_size); if (finalid_size == nameid_size && 0 == memcmp(finalid, nameid, nameid_size)) *(md->done) = 1; } if (*(md->done)) { ndn_set_run_timeout(info->h, 0); return(NDN_UPCALL_RESULT_OK); } /* Ask for the next fragment */ name = ndn_charbuf_create(); ndn_name_init(name); if (ic->n < 2) abort(); res = ndn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]); if (res < 0) abort(); ndn_name_append_numeric(name, NDN_MARKER_SEQNUM, ++(selfp->intdata)); templ = make_template(md, info); res = ndn_express_interest(info->h, name, selfp, templ); if (res < 0) abort(); ndn_charbuf_destroy(&templ); ndn_charbuf_destroy(&name); return(NDN_UPCALL_RESULT_OK); }