PUBLIC struct content_entry * process_incoming_content(struct ccnr_handle *h, struct fdholder *fdholder, unsigned char *msg, size_t size) { struct ccn_parsed_ContentObject obj = {0}; int res; struct content_entry *content = NULL; ccnr_accession accession = CCNR_NULL_ACCESSION; content = calloc(1, sizeof(*content)); if (content == NULL) goto Bail; content->cob = ccn_charbuf_create(); if (content->cob == NULL) goto Bail; res = ccn_charbuf_append(content->cob, msg, size); if (res < 0) goto Bail; content->size = size; res = r_store_set_flatname(h, content, &obj); if (res < 0) goto Bail; ccnr_meter_bump(h, fdholder->meter[FM_DATI], 1); content->accession = CCNR_NULL_ACCESSION; r_store_enroll_content(h, content); if (CCNSHOULDLOG(h, LM_4, CCNL_FINE)) ccnr_debug_content(h, __LINE__, "content_from", fdholder, content); res = r_store_content_btree_insert(h, content, &obj, &accession); if (res < 0) goto Bail; if (res == 0) { /* Content was there, with an accession */ if (CCNSHOULDLOG(h, LM_4, CCNL_FINER)) ccnr_debug_content(h, __LINE__, "content_duplicate", fdholder, content); h->content_dups_recvd++; r_store_forget_content(h, &content); content = r_store_content_from_accession(h, accession); if (content == NULL) goto Bail; } r_store_set_content_timer(h, content, &obj); r_match_match_interests(h, content, &obj, NULL, fdholder); return(content); Bail: r_store_forget_content(h, &content); return(content); }
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; }
PUBLIC struct content_entry * r_store_lookup(struct ccnr_handle *h, const unsigned char *msg, const struct ccn_parsed_interest *pi, struct ccn_indexbuf *comps) { struct content_entry *content = NULL; struct ccn_btree_node *leaf = NULL; ccnr_cookie last_match = 0; ccnr_accession last_match_acc = CCNR_NULL_ACCESSION; struct ccn_charbuf *scratch = NULL; size_t size = pi->offset[CCN_PI_E]; int ndx; int res; int try; content = r_store_find_first_match_candidate(h, msg, pi); if (content != NULL && CCNSHOULDLOG(h, LM_8, CCNL_FINER)) ccnr_debug_content(h, __LINE__, "first_candidate", NULL, content); if (content != NULL && !r_store_content_matches_interest_prefix(h, content, msg, size)) { if (CCNSHOULDLOG(h, LM_8, CCNL_FINER)) ccnr_debug_ccnb(h, __LINE__, "prefix_mismatch", NULL, msg, size); content = NULL; } scratch = ccn_charbuf_create(); for (try = 0; content != NULL; try++) { res = ccn_btree_lookup(h->btree, content->flatname->buf, content->flatname->length, &leaf); if (CCN_BT_SRCH_FOUND(res) == 0) { ccnr_debug_content(h, __LINE__, "impossible", NULL, content); content = NULL; break; } ndx = CCN_BT_SRCH_INDEX(res); res = ccn_btree_match_interest(leaf, ndx, msg, pi, scratch); if (res == -1) { ccnr_debug_ccnb(h, __LINE__, "match_error", NULL, msg, size); content = NULL; break; } if (res == 1) { if ((pi->orderpref & 1) == 0) // XXX - should be symbolic break; last_match = content->cookie; last_match_acc = content->accession; content = r_store_next_child_at_level(h, content, comps->n - 1); } else content = r_store_content_next(h, content); if (content != NULL && !r_store_content_matches_interest_prefix(h, content, msg, size)) content = NULL; } if (last_match != 0) { content = r_store_content_from_cookie(h, last_match); if (content == NULL) content = r_store_content_from_accession(h, last_match_acc); } ccn_charbuf_destroy(&scratch); return(content); } /** * Find the first content handle that matches the prefix given by the namish, * which may be a Name, Interest, ContentObject, ... * * Does not check the other parts of namish, in particular, does not generate * the digest component of a ContentObject. */ PUBLIC struct content_entry * r_store_lookup_ccnb(struct ccnr_handle *h, const unsigned char *namish, size_t size) { struct content_entry *content = NULL; struct ccn_charbuf *flatname = NULL; int res; flatname = ccn_charbuf_create(); if (flatname == NULL) goto Bail; res = ccn_flatname_from_ccnb(flatname, namish, size); if (res < 0) goto Bail; content = r_store_look(h, flatname->buf, flatname->length); if (content != NULL) { res = ccn_flatname_charbuf_compare(flatname, content->flatname); if (res == 0 || res == -9999) { /* prefix matches */ } else content = NULL; } Bail: ccn_charbuf_destroy(&flatname); return(content); } /** * Mark content as stale */ PUBLIC void r_store_mark_stale(struct ccnr_handle *h, struct content_entry *content) { ccnr_cookie cookie = content->cookie; if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0) return; if (CCNSHOULDLOG(h, LM_4, CCNL_FINE)) ccnr_debug_content(h, __LINE__, "stale", NULL, content); content->flags |= CCN_CONTENT_ENTRY_STALE; h->n_stale++; if (cookie < h->min_stale) h->min_stale = cookie; if (cookie > h->max_stale) h->max_stale = cookie; } /** * Scheduled event that makes content stale when its FreshnessSeconds * has expired. */ static int expire_content(struct ccn_schedule *sched, void *clienth, struct ccn_scheduled_event *ev, int flags) { struct ccnr_handle *h = clienth; ccnr_cookie cookie = ev->evint; struct content_entry *content = NULL; if ((flags & CCN_SCHEDULE_CANCEL) != 0) return(0); content = r_store_content_from_cookie(h, cookie); if (content != NULL) r_store_mark_stale(h, content); return(0); } /** * Schedules content expiration based on its FreshnessSeconds. * */ PUBLIC void r_store_set_content_timer(struct ccnr_handle *h, struct content_entry *content, struct ccn_parsed_ContentObject *pco) { int seconds = 0; int microseconds = 0; size_t start = pco->offset[CCN_PCO_B_FreshnessSeconds]; size_t stop = pco->offset[CCN_PCO_E_FreshnessSeconds]; const unsigned char *content_msg = NULL; if (start == stop) return; content_msg = r_store_content_base(h, content); seconds = ccn_fetch_tagged_nonNegativeInteger( CCN_DTAG_FreshnessSeconds, content_msg, start, stop); if (seconds <= 0) return; if (seconds > ((1U<<31) / 1000000)) { ccnr_debug_content(h, __LINE__, "FreshnessSeconds_too_large", NULL, content); return; } microseconds = seconds * 1000000; ccn_schedule_event(h->sched, microseconds, &expire_content, NULL, content->cookie); }