Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
/**
 * 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);
}