int ndn_name_comp_strcmp(const unsigned char *data, const struct ndn_indexbuf *indexbuf, unsigned int i, const char *val) { const unsigned char *comp_ptr; size_t comp_size; // XXX - We probably want somewhat different semantics in the API - // comparing a string against a longer string with a 0 byte should // not claim equality. if (ndn_name_comp_get(data, indexbuf, i, &comp_ptr, &comp_size) == 0) return(strncmp(val, (const char *)comp_ptr, comp_size)); /* Probably no such component, say query is greater-than */ return(1); }
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; }
/** * 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); }