Ejemplo n.º 1
0
/**
 * Parses content object and sets content->flatname
 */
static int
r_store_set_flatname(struct ccnr_handle *h, struct content_entry *content,
                     struct ccn_parsed_ContentObject *pco)
{
    int res;
    struct ccn_charbuf *flatname = NULL;
    const unsigned char *msg = NULL;
    size_t size;
    
    msg = r_store_content_base(h, content);
    size = content->size;
    if (msg == NULL)
        goto Bail;
    flatname = ccn_charbuf_create();
    if (flatname == NULL)
        goto Bail;    
    res = ccn_parse_ContentObject(msg, size, pco, NULL);
    if (res < 0) {
        ccnr_msg(h, "error parsing ContentObject - code %d", res);
        goto Bail;
    }
    ccn_digest_ContentObject(msg, pco);
    if (pco->digest_bytes != 32)
        goto Bail;
    res = ccn_flatname_from_ccnb(flatname, msg, size);
    if (res < 0) goto Bail;
    res = ccn_flatname_append_component(flatname, pco->digest, pco->digest_bytes);
    if (res < 0) goto Bail;
    content->flatname = flatname;
    flatname = NULL;
    return(0);
Bail:
    ccn_charbuf_destroy(&flatname);
    return(-1);
}
Ejemplo n.º 2
0
/** @returns 2 if content was added to index, 1 if it was there but had no accession, 0 if it was already there, -1 for error */
static int
r_store_content_btree_insert(struct ccnr_handle *h,
                             struct content_entry *content,
                             struct ccn_parsed_ContentObject *pco,
                             ccnr_accession *accp)
{
    const unsigned char *content_base = NULL;
    struct ccn_btree *btree = NULL;
    struct ccn_btree_node *leaf = NULL;
    struct ccn_btree_node *node = NULL;
    struct ccn_charbuf *flat = NULL;
    int i;
    int limit;
    int res;

    btree = h->btree;
    if (btree == NULL)
        return(-1);
    flat = content->flatname;
    if (flat == NULL)
        return(-1);
    res = ccn_btree_lookup(h->btree, flat->buf, flat->length, &leaf);
    if (res < 0)
        return(-1);
    i = CCN_BT_SRCH_INDEX(res);
    if (CCN_BT_SRCH_FOUND(res)) {
        *accp = ccnr_accession_decode(h, ccn_btree_content_cobid(leaf, i));
        return(*accp == CCNR_NULL_ACCESSION);
    }
    else {
        content_base = r_store_content_base(h, content);
        if (content_base == NULL)
            return(-1);
        res = ccn_btree_prepare_for_update(h->btree, leaf);
        if (res < 0)
            return(-1);
        res = ccn_btree_insert_content(leaf, i,
                                       ccnr_accession_encode(h, content->accession),
                                       content_base,
                                       pco,
                                       content->flatname);
        if (res < 0)
            return(-1);
        if (ccn_btree_oversize(btree, leaf)) {
            res = ccn_btree_split(btree, leaf);
            for (limit = 100; res >= 0 && btree->nextsplit != 0; limit--) {
                if (limit == 0) abort();
                node = ccn_btree_getnode(btree, btree->nextsplit, 0);
                if (node == NULL)
                    return(-1);
                res = ccn_btree_split(btree, node);
            }
        }
        r_store_index_needs_cleaning(h);
        
        *accp = content->accession;
        return(2);
    }
}
Ejemplo n.º 3
0
PUBLIC struct content_entry *
r_store_content_from_accession(struct ccnr_handle *h, ccnr_accession accession)
{
    struct ccn_parsed_ContentObject obj = {0};
    struct content_entry *content = NULL;
    struct content_by_accession_entry *entry;
    const unsigned char *content_base = NULL;
    int res;
    ccnr_accession acc;
    
    if (accession == CCNR_NULL_ACCESSION)
        return(NULL);
    entry = hashtb_lookup(h->content_by_accession_tab,
                          &accession, sizeof(accession));
    if (entry != NULL) {
        h->content_from_accession_hits++;
        return(entry->content);
    }
    h->content_from_accession_misses++;
    content = calloc(1, sizeof(*content));
    CHKPTR(content);
    content->cookie = 0;
    content->accession = accession;
    content->cob = NULL;
    content->size = 0;
    content_base = r_store_content_base(h, content);
    if (content_base == NULL || content->size == 0)
        goto Bail;
    res = r_store_set_flatname(h, content, &obj);
    if (res < 0) goto Bail;
    r_store_enroll_content(h, content);
    res = r_store_content_btree_insert(h, content, &obj, &acc);
    if (res < 0) goto Bail;
    if (res == 1 || CCNSHOULDLOG(h, sdf, CCNL_FINEST))
        ccnr_debug_content(h, __LINE__, "content/accession", NULL, content);
    return(content);
Bail:
    ccnr_msg(h, "r_store_content_from_accession.%d failed 0x%jx",
             __LINE__, ccnr_accession_encode(h, accession));
    r_store_forget_content(h, &content);
    return(content);
}
Ejemplo n.º 4
0
PUBLIC void
r_store_send_content(struct ccnr_handle *h, struct fdholder *fdholder, struct content_entry *content)
{
    const unsigned char *content_msg = NULL;
    off_t offset;

    if (CCNSHOULDLOG(h, LM_4, CCNL_FINE))
        ccnr_debug_content(h, __LINE__, "content_to", fdholder, content);
    content_msg = r_store_content_base(h, content);
    r_link_stuff_and_send(h, fdholder, content_msg, content->size, NULL, 0, &offset);
    if (offset != (off_t)-1 && content->accession == CCNR_NULL_ACCESSION) {
        int res;
        res = r_store_set_accession_from_offset(h, content, fdholder, offset);
        if (res == 0)
            if (CCNSHOULDLOG(h, LM_4, CCNL_FINE))
                ccnr_debug_content(h, __LINE__, "content_stored",
                                   r_io_fdholder_from_fd(h, h->active_out_fd),
                                   content);
    }
}
Ejemplo n.º 5
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.º 6
0
/**
 * Consume matching interests
 * given a nameprefix_entry and a piece of content.
 *
 * If fdholder is not NULL, pay attention only to interests from that fdholder.
 * It is allowed to pass NULL for pc, but if you have a (valid) one it
 * will avoid a re-parse.
 * @returns number of matches found.
 */
PUBLIC int
r_match_consume_matching_interests(struct ccnr_handle *h,
                           struct nameprefix_entry *npe,
                           struct content_entry *content,
                           struct ccn_parsed_ContentObject *pc,
                           struct fdholder *fdholder)
{
    int matches = 0;
    struct propagating_entry *head;
    struct propagating_entry *next;
    struct propagating_entry *p;
    const unsigned char *content_msg;
    size_t content_size;
    struct fdholder *f;
    
    head = &npe->pe_head;
    // XXX - i do not think this is called in practice
    content_msg = r_store_content_base(h, content);
    content_size = r_store_content_size(h, content);
    f = fdholder;
    for (p = head->next; p != head; p = next) {
        next = p->next;
        if (p->interest_msg != NULL &&
            ((fdholder == NULL && (f = r_io_fdholder_from_fd(h, p->filedesc)) != NULL) ||
             (fdholder != NULL && p->filedesc == fdholder->filedesc))) {
            if (ccn_content_matches_interest(content_msg, content_size, 1, pc,
                                             p->interest_msg, p->size, NULL)) {
                r_sendq_face_send_queue_insert(h, f, content);
                if (CCNSHOULDLOG(h, (32 | 8), CCNL_FINE))
                    ccnr_debug_ccnb(h, __LINE__, "consume", f,
                                    p->interest_msg, p->size);
                matches += 1;
                r_match_consume_interest(h, p);
            }
        }
    }
    return(matches);
}
Ejemplo n.º 7
0
PUBLIC int
r_store_content_field_access(struct ccnr_handle *h,
                             struct content_entry *content,
                             enum ccn_dtag dtag,
                             const unsigned char **bufp, size_t *sizep)
{
    int res = -1;
    const unsigned char *content_msg;
    struct ccn_parsed_ContentObject pco = {0};
    
    content_msg = r_store_content_base(h, content);
    if (content_msg == NULL)
        return(-1);
    res = ccn_parse_ContentObject(content_msg, content->size, &pco, NULL);
    if (res < 0)
        return(-1);
    if (dtag == CCN_DTAG_Content)
        res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg,
                                  pco.offset[CCN_PCO_B_Content],
                                  pco.offset[CCN_PCO_E_Content],
                                  bufp, sizep);
    return(res);
}
Ejemplo n.º 8
0
/**
 * 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);
Ejemplo n.º 9
0
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);
}