Esempio n. 1
0
int
ccnl_i_prefixof_c(struct ccnl_prefix_s *prefix,
                  int minsuffix, int maxsuffix, struct ccnl_content_s *c)
{
    unsigned char *md;
#ifdef USE_LOGGING
    char prefixBuf1[CCNL_PREFIX_BUFSIZE], prefixBuf2[CCNL_PREFIX_BUFSIZE];
#endif
    struct ccnl_prefix_s *p = c->pkt->pfx;

    DEBUGMSG_CPFX(VERBOSE, "ccnl_i_prefixof_c prefix=<%s> content=<%s> min=%d max=%d\n",
             ccnl_prefix2path(prefixBuf1, CCNL_ARRAY_SIZE(prefixBuf1), prefix),
             ccnl_prefix2path(prefixBuf2, CCNL_ARRAY_SIZE(prefixBuf2), p),
             minsuffix, maxsuffix);
    if (!prefix || !p)
        return 0;
    // CONFORM: we do prefix match, honour min. and maxsuffix,

    // NON-CONFORM: "Note that to match a ContentObject must satisfy
    // all of the specifications given in the Interest Message."
    // >> CCNL does not honour the exclusion filtering

    if ( (prefix->compcnt + minsuffix) > (p->compcnt + 1) ||
         (prefix->compcnt + maxsuffix) < (p->compcnt + 1)) {
        DEBUGMSG_CPFX(TRACE, "  mismatch in # of components\n");
        return 0;
    }

    md = (prefix->compcnt - p->compcnt == 1) ? compute_ccnx_digest(c->pkt->buf) : NULL;
    return ccnl_prefix_cmp(p, md, prefix, CMP_MATCH) == prefix->compcnt;
}
Esempio n. 2
0
int ccnl_i_prefixof_c(struct ccnl_prefix_s *prefix, struct ccnl_buf_s *ppkd,
                      int minsuffix, int maxsuffix, struct ccnl_content_s *c)
{
    unsigned char *md;
    DEBUGMSG(99, "ccnl_i_prefixof_c prefix=%s min=%d max=%d\n",
             ccnl_prefix_to_path(prefix), minsuffix, maxsuffix);

    // CONFORM: we do prefix match, honour min. and maxsuffix,
    // and check the PublisherPublicKeyDigest if present

    // NON-CONFORM: "Note that to match a ContentObject must satisfy
    // all of the specifications given in the Interest Message."
    // >> CCNL does not honour the exclusion filtering

    if ((ppkd && !buf_equal(ppkd, c->ppkd))
        || (prefix->compcnt + minsuffix) > (c->name->compcnt + 1)
        || (prefix->compcnt + maxsuffix) < (c->name->compcnt + 1)) {
        return 0;
    }

    md = NULL;

    if ((prefix->compcnt - c->name->compcnt) == 1) {
        md = compute_ccnx_digest(c->pkt);
    }

    return ccnl_prefix_cmp(c->name, md, prefix, CMP_MATCH) == prefix->compcnt;
}
Esempio n. 3
0
int
ccnl_nfn_thunk_already_computing(struct ccnl_relay_s *ccnl,
                                 struct ccnl_prefix_s *prefix)
{
    int i = 0;
    struct ccnl_prefix_s *copy;

    DEBUGMSG(TRACE, "ccnl_nfn_thunk_already_computing()\n");

    copy = ccnl_prefix_dup(prefix);
    // ccnl_nfn_remove_thunk_from_prefix(copy);
    ccnl_nfnprefix_set(copy, CCNL_PREFIX_NFN | CCNL_PREFIX_THUNK);

    for (i = 0; i < -ccnl->km->configid; ++i) {
        struct configuration_s *config;

        config = ccnl_nfn_findConfig(ccnl->km->configuration_list, -i);
        if (!config)
            continue;
        if (!ccnl_prefix_cmp(config->prefix, NULL, copy, CMP_EXACT)) {
            free_prefix(copy);
            return 1;
        }  
    }
    free_prefix(copy);

    return 0;
}
Esempio n. 4
0
void 
ccnl_nfn_continue_computation(struct ccnl_relay_s *ccnl, int configid, int continue_from_remove){
    DEBUGMSG(TRACE, "ccnl_nfn_continue_computation()\n");
    struct configuration_s *config = ccnl_nfn_findConfig(ccnl->km->configuration_list, -configid);
    
    if(!config){
        DEBUGMSG(DEBUG, "nfn_continue_computation: %d not found\n", configid);
        return;
    }

    //update original interest prefix to stay longer...reenable if propagate=0 do not protect interests
    struct ccnl_interest_s *original_interest;
    for(original_interest = ccnl->pit; original_interest; original_interest = original_interest->next){
        if(!ccnl_prefix_cmp(config->prefix, 0, original_interest->prefix, CMP_EXACT)){
            original_interest->last_used = CCNL_NOW();
            original_interest->retries = 0;
            original_interest->from->last_used = CCNL_NOW();
            break;
        }
    }
    if(config->thunk && CCNL_NOW() > config->endtime){
        DEBUGMSG(INFO, "NFN: Exit computation: timeout when resolving thunk\n");
        DBL_LINKED_LIST_REMOVE(ccnl->km->configuration_list, config);
        //Reply error!
        //config->thunk = 0;
        return;
    }
    ccnl_nfn(ccnl, NULL, NULL, config, NULL, 0, 0);
}
// returns: 0=match, -1=otherwise
int
ccnl_iottlv_cMatch(struct ccnl_pkt_s *p, struct ccnl_content_s *c)
{
    assert(p);
    assert(p->suite == CCNL_SUITE_IOTTLV);

    if (ccnl_prefix_cmp(c->pkt->pfx, NULL, p->pfx, CMP_EXACT))
        return -1;
    return 0;
}
// returns: 0=match, -1=otherwise
int
ccnl_ccntlv_cMatch(struct ccnl_pkt_s *p, struct ccnl_content_s *c)
{
    assert(p);
    assert(p->suite == CCNL_SUITE_CCNTLV);

    if (ccnl_prefix_cmp(c->pkt->pfx, NULL, p->pfx, CMP_EXACT))
        return -1;
    // TODO: check keyid
    // TODO: check freshness, kind-of-reply
    return 0;
}
Esempio n. 7
0
int
ccnl_nfn_RX_result(struct ccnl_relay_s *relay, struct ccnl_face_s *from,
                   struct ccnl_content_s *c)
{
    struct ccnl_interest_s *i_it = NULL;
    int found = 0;

    DEBUGMSG(TRACE, "ccnl_nfn_RX_result()\n");
#ifdef USE_NACK
    if (ccnl_nfnprefix_contentIsNACK(c)) {
        ccnl_nfn_nack_local_computation(relay, c->pkt, c->name,
                                        from, c->name->suite);
        return -1;
    }
#endif // USE_NACK
    for (i_it = relay->pit; i_it;/* i_it = i_it->next*/) {
        //Check if prefix match and it is a nfn request
        DEBUGMSG(DEBUG, "CMP: %d (match if zero), faceid: %d \n", 
			ccnl_prefix_cmp(c->name, NULL, i_it->prefix, CMP_EXACT),
			i_it->from->faceid);
        if (!ccnl_prefix_cmp(c->name, NULL, i_it->prefix, CMP_EXACT) &&
                                                i_it->from->faceid < 0) {
            int faceid = -i_it->from->faceid;

            ccnl_content_add2cache(relay, c);
	    DEBUGMSG(DEBUG, "Continue configuration for configid: %d with prefix: %s\n",
                     -i_it->from->faceid, ccnl_prefix_to_path(c->name));
            i_it->flags |= CCNL_PIT_COREPROPAGATES;
            i_it = ccnl_interest_remove(relay, i_it);
            ccnl_nfn_continue_computation(relay, faceid, 0);
            ++found;
            //goto Done;
        }
        else
            i_it = i_it->next;
    }
    return found > 0;
}
Esempio n. 8
0
// returns: 0=match, -1=otherwise
int8_t
ccnl_ccntlv_cMatch(struct ccnl_pkt_s *p, struct ccnl_content_s *c)
{
#ifndef CCNL_LINUXKERNEL
    assert(p);
    assert(p->suite == CCNL_SUITE_CCNTLV);
#endif
    if (ccnl_prefix_cmp(c->pkt->pfx, NULL, p->pfx, CMP_EXACT)) {
        return -1;
    }
    // TODO: check keyid
    // TODO: check freshness, kind-of-reply
    return 0;
}
/**
 * @brief local callback to handle incoming content chunks
 *
 * @note  Gets called from CCNL thread context
 *
 * @returns 1   if chunk is handled and no further processing should happen
 * @returns 0   otherwise
 **/
int ccnlriot_consumer(struct ccnl_relay_s *relay, struct ccnl_face_s *from,
                      struct ccnl_pkt_s *pkt)
{
    (void) from;
    (void) relay;

    if (dow_state == DOW_STATE_STOPPED) {
        LOG_DEBUG("ccnl_helper: we're in stopped, do nothing\n");
        free_packet(pkt);
        return 1;
    }

    uint32_t cont_id = (uint32_t) strtol((char*)pkt->pfx->comp[2], NULL, 16);
    if (cont_id > dow_highest_id) {
        dow_highest_id = cont_id;
    }

    LOG_DEBUG("%" PRIu32 " ccnl_helper: local consumer for prefix: %s\n", xtimer_now().ticks32,
              ccnl_prefix_to_path_detailed(_prefix_str, pkt->pfx, 1, 0, 0));
    memset(_prefix_str, 0, CCNLRIOT_PFX_LEN);

#if DOW_DEPUTY
    /* XXX: might be unnecessary du to mutex now */
    /* if we're currently transferring our cache to the new deputy, we do not touch the content store */
    if (dow_state == DOW_STATE_HANDOVER) {
        LOG_DEBUG("ccnl_helper: we're in handover state, cannot touch content store right now\n");
        free_packet(pkt);
        return 1;
    }
#endif

    /* check if prefix is for ALL and contains an ACK */
    if ((ccnl_prefix_cmp(ccnl_helper_all_pfx, NULL, pkt->pfx, CMP_MATCH) >= 1) &&
        (strncmp((char*) pkt->content, CCNLRIOT_CONT_ACK, strlen(CCNLRIOT_CONT_ACK)) == 0)) {
        dow_content_t *cc = (dow_content_t*) pkt->content;
        LOG_DEBUG("ccnl_helper: content number is %i\n", cc->num);
        if (cc->num >= 0) {
            _remove_pit(relay, cc->num);
        }

        LOG_DEBUG("ccnl_helper: received ACK, flag the content\n");
        msg_t m = { .type = DOW_MSG_RECEIVED_ACK };
        msg_try_send(&m, dow_pid);
        free_packet(pkt);
        return 1;
    }
Esempio n. 10
0
void ccnl_interest_propagate(struct ccnl_relay_s *ccnl,
                             struct ccnl_interest_s *i)
{
    struct ccnl_forward_s *fwd;
    DEBUGMSG(99, "ccnl_interest_propagate\n");

    // CONFORM: "A node MUST implement some strategy rule, even if it is only to
    // transmit an Interest Message on all listed dest faces in sequence."
    // CCNL strategy: we forward on all FWD entries with a prefix match
    int forward_cnt = 0;
    for (fwd = ccnl->fib; fwd; fwd = fwd->next) {
        int rc = ccnl_prefix_cmp(fwd->prefix, NULL, i->prefix, CMP_LONGEST);
        DEBUGMSG(40, "  ccnl_interest_propagate, rc=%d/%d\n", rc,
                 fwd->prefix->compcnt);

        if (rc < fwd->prefix->compcnt) {
            continue;
        }

        DEBUGMSG(40, "  ccnl_interest_propagate, fwd==%p\n", (void *) fwd);

        // suppress forwarding to origin of interest, except wireless
        if (!i->from || fwd->face != i->from
            || (i->from->flags & CCNL_FACE_FLAGS_REFLECT)) {

            i->forwarded_over = fwd;
            fwd->face->stat.send_interest[i->retries]++;
            ccnl_get_timeval(&i->last_used);
            ccnl_face_enqueue(ccnl, fwd->face, buf_dup(i->pkt));
            ccnl_get_timeval(&fwd->last_used);
            forward_cnt++;
        }
    }

    if (forward_cnt == 0) {
        DEBUGMSG(40, "  ccnl_interest_propagate: using broadcast face!\n");
        ccnl->ifs[RIOT_TRANS_IDX].broadcast_face->stat.send_interest[i->retries]++;
        ccnl_get_timeval(&i->last_used);
        ccnl_face_enqueue(ccnl, ccnl->ifs[RIOT_TRANS_IDX].broadcast_face, buf_dup(i->pkt));
    }

    return;
}
Esempio n. 11
0
int
ccnl_nfn_RX_result(struct ccnl_relay_s *relay, struct ccnl_face_s *from,
                   struct ccnl_content_s *c)
{
    struct ccnl_interest_s *i_it = NULL;
    int found = 0;

    DEBUGMSG_CFWD(INFO, "data in rx result %.*s\n", c->pkt->contlen, c->pkt->content);
    TRACEIN();
#ifdef USE_NACK
    if (ccnl_nfnprefix_contentIsNACK(c)) {
        ccnl_nfn_nack_local_computation(relay, c->pkt->buf, c->pkt->pfx,
                                        from, c->pkt->pfx->suite);
        return -1;
    }
#endif // USE_NACK
    for (i_it = relay->pit; i_it;/* i_it = i_it->next*/) {
        //Check if prefix match and it is a nfn request
        if (!ccnl_prefix_cmp(c->pkt->pfx, NULL, i_it->pkt->pfx, CMP_EXACT) &&
                                        i_it->from && i_it->from->faceid < 0) {
            struct ccnl_face_s *from = i_it->from;
            int faceid = - from->faceid;

            DEBUGMSG(TRACE, "  interest faceid=%d\n", i_it->from->faceid);

            ccnl_content_add2cache(relay, c);
	    DEBUGMSG_CFWD(INFO, "data in rx resulti after add to cache %.*s\n", c->pkt->contlen, c->pkt->content);
            DEBUGMSG(DEBUG, "Continue configuration for configid: %d with prefix: %s\n",
                  faceid, ccnl_prefix_to_path(c->pkt->pfx));
            i_it->flags |= CCNL_PIT_COREPROPAGATES;
            i_it->from = NULL;
            ccnl_nfn_continue_computation(relay, faceid, 0);
            i_it = ccnl_interest_remove(relay, i_it);
            //ccnl_face_remove(relay, from);
            ++found;
            //goto Done;
        } else
            i_it = i_it->next;
    }
    TRACEOUT();
    return found > 0;
}
Esempio n. 12
0
/**
 * returns an entry from the fib which has a common prefix with p.
 * only returns that entry if it fullfils the aggregate threshold!
 */
struct ccnl_forward_s *ccn_forward_find_common_prefix_to_aggregate(struct ccnl_relay_s *ccnl, struct ccnl_prefix_s *p, int *match_len)
{
    if (!ccnl->fib) {
        DEBUGMSG(999, "ccn_forward_find_common_prefix: fib was empty\n");
        return NULL;
    }

    /* fib as at least one enty */
    struct ccnl_forward_s *fwd2 = ccnl->fib;
    while (fwd2) {
        DEBUGMSG(1, "ccn_forward_find_common_prefix: '%s' vs. '%s'\n", ccnl_prefix_to_path(p), ccnl_prefix_to_path(fwd2->prefix));
        *match_len = ccnl_prefix_cmp(fwd2->prefix, 0, p, CMP_LONGEST);

        /* check for threshold and never date up a static enty */
        if ((ccnl->fib_threshold_aggregate <= *match_len) && !(fwd2->flags & CCNL_FORWARD_FLAGS_STATIC)) {
            return fwd2;
        }

        fwd2 = fwd2->next;
    }

    return NULL;
}
Esempio n. 13
0
int
ccnl_interest_isSame(struct ccnl_interest_s *i, struct ccnl_pkt_s *pkt)
{
    if (i->pkt->pfx->suite != pkt->suite ||
                ccnl_prefix_cmp(i->pkt->pfx, NULL, pkt->pfx, CMP_EXACT))
        return 0;

    switch (i->pkt->pfx->suite) {
#ifdef USE_SUITE_CCNB
    case CCNL_SUITE_CCNB:
        return i->pkt->s.ccnb.minsuffix == pkt->s.ccnb.minsuffix &&
               i->pkt->s.ccnb.maxsuffix == pkt->s.ccnb.maxsuffix &&
               ((!i->pkt->s.ccnb.ppkd && !pkt->s.ccnb.ppkd) ||
                    buf_equal(i->pkt->s.ccnb.ppkd, pkt->s.ccnb.ppkd));
#endif
#ifdef USE_SUITE_NDNTLV
    case CCNL_SUITE_NDNTLV:
        return i->pkt->s.ndntlv.minsuffix == pkt->s.ndntlv.minsuffix &&
               i->pkt->s.ndntlv.maxsuffix == pkt->s.ndntlv.maxsuffix &&
               ((!i->pkt->s.ndntlv.ppkl && !pkt->s.ndntlv.ppkl) ||
                    buf_equal(i->pkt->s.ndntlv.ppkl, pkt->s.ndntlv.ppkl));
#endif
#ifdef USE_SUITE_CCNTLV
    case CCNL_SUITE_CCNTLV:
#endif
#ifdef USE_SUITE_CISTLV
    case CCNL_SUITE_CISTLV:
#endif
#ifdef USE_SUITE_IOTTLV
    case CCNL_SUITE_IOTTLV:
#endif
    default:
        break;
    }
    return 1;
}
Esempio n. 14
0
int
ccnl_ccnb_forwarder(struct ccnl_relay_s *relay, struct ccnl_face_s *from,
		    unsigned char **data, int *datalen)
{
    int rc= -1, scope=3, aok=3, minsfx=0, maxsfx=CCNL_MAX_NAME_COMP, contlen;
    struct ccnl_buf_s *buf = 0, *nonce=0, *ppkd=0;
    struct ccnl_interest_s *i = 0;
    struct ccnl_content_s *c = 0;
    struct ccnl_prefix_s *p = 0;
    unsigned char *content = 0;
    DEBUGMSG(99, "ccnl/ccnb forwarder (%d bytes left)\n", *datalen);

    buf = ccnl_ccnb_extract(data, datalen, &scope, &aok, &minsfx,
			    &maxsfx, &p, &nonce, &ppkd, &content, &contlen);
    if (!buf) {
	    DEBUGMSG(6, "  parsing error or no prefix\n"); goto Done;
    }
    if (nonce && ccnl_nonce_find_or_append(relay, nonce)) {
	DEBUGMSG(6, "  dropped because of duplicate nonce\n"); goto Skip;
    }
    if (buf->data[0] == 0x01 && buf->data[1] == 0xd2) { // interest
	DEBUGMSG(6, "  interest=<%s>\n", ccnl_prefix_to_path(p));
	ccnl_print_stats(relay, STAT_RCV_I); //log count recv_interest
	if (p->compcnt > 0 && p->comp[0][0] == (unsigned char) 0xc1) goto Skip;
	if (p->compcnt == 4 && !memcmp(p->comp[0], "ccnx", 4)) {
	    rc = ccnl_mgmt(relay, buf, p, from); goto Done;
	}
	// CONFORM: Step 1:
	if ( aok & 0x01 ) { // honor "answer-from-existing-content-store" flag
	    for (c = relay->contents; c; c = c->next) {
		if (c->suite != CCNL_SUITE_CCNB) continue;
		if (!ccnl_i_prefixof_c(p, minsfx, maxsfx, c)) continue;
		if (ppkd && !buf_equal(ppkd, c->details.ccnb.ppkd)) continue;
		// FIXME: should check stale bit in aok here
		DEBUGMSG(7, "  matching content for interest, content %p\n", (void *) c);
		ccnl_print_stats(relay, STAT_SND_C); //log sent_c
		if (from->ifndx >= 0)
		    ccnl_face_enqueue(relay, from, buf_dup(c->pkt));
		else
		    ccnl_app_RX(relay, c);
		goto Skip;
	    }
	}
	// CONFORM: Step 2: check whether interest is already known
	for (i = relay->pit; i; i = i->next) {
	    if (i->suite == CCNL_SUITE_CCNB &&
		!ccnl_prefix_cmp(i->prefix, NULL, p, CMP_EXACT) &&
		i->details.ccnb.minsuffix == minsfx &&
		i->details.ccnb.maxsuffix == maxsfx && 
		((!ppkd && !i->details.ccnb.ppkd) ||
		   buf_equal(ppkd, i->details.ccnb.ppkd)) )
		break;
	}
	if (!i) { // this is a new/unknown I request: create and propagate
	    i = ccnl_interest_new(relay, from, CCNL_SUITE_CCNB,
				  &buf, &p, minsfx, maxsfx);
	    if (ppkd)
		i->details.ccnb.ppkd = ppkd, ppkd = NULL;
	    if (i) { // CONFORM: Step 3 (and 4)
		DEBUGMSG(7, "  created new interest entry %p\n", (void *) i);
		if (scope > 2)
		    ccnl_interest_propagate(relay, i);
	    }
	} else if (scope > 2 && (from->flags & CCNL_FACE_FLAGS_FWDALLI)) {
	    DEBUGMSG(7, "  old interest, nevertheless propagated %p\n", (void *) i);
	    ccnl_interest_propagate(relay, i);
	}
	if (i) { // store the I request, for the incoming face (Step 3)
	    DEBUGMSG(7, "  appending interest entry %p\n", (void *) i);
	    ccnl_interest_append_pending(i, from);
	}
    } else { // content
	DEBUGMSG(6, "  content=<%s>\n", ccnl_prefix_to_path(p));
	ccnl_print_stats(relay, STAT_RCV_C); //log count recv_content
        
#ifdef USE_SIGNATURES
        if (p->compcnt == 2 && !memcmp(p->comp[0], "ccnx", 4)
                && !memcmp(p->comp[1], "crypto", 6) &&
                from == relay->crypto_face) {
	    rc = ccnl_crypto(relay, buf, p, from); goto Done;
	}
#endif /*USE_SIGNATURES*/
        
        // CONFORM: Step 1:
	for (c = relay->contents; c; c = c->next)
	    if (buf_equal(c->pkt, buf)) goto Skip; // content is dup
	c = ccnl_content_new(relay, CCNL_SUITE_CCNB,
			     &buf, &p, &ppkd, content, contlen);
	if (c) { // CONFORM: Step 2 (and 3)
	    if (!ccnl_content_serve_pending(relay, c)) { // unsolicited content
		// CONFORM: "A node MUST NOT forward unsolicited data [...]"
		DEBUGMSG(7, "  removed because no matching interest\n");
		free_content(c);
		goto Skip;
	    }
	    if (relay->max_cache_entries != 0) { // it's set to -1 or a limit
		DEBUGMSG(7, "  adding content to cache\n");
		ccnl_content_add2cache(relay, c);
	    } else {
		DEBUGMSG(7, "  content not added to cache\n");
		free_content(c);
	    }
	}
    }
Skip:
    rc = 0;
Done:
    free_prefix(p);
    free_3ptr_list(buf, nonce, ppkd);
    return rc;
}
Esempio n. 15
0
int ccnl_core_RX_i_or_c(struct ccnl_relay_s *relay, struct ccnl_face_s *from,
                        unsigned char **data, int *datalen)
{
    int rc = -1, scope = 3, aok = 3, minsfx = 0, maxsfx = CCNL_MAX_NAME_COMP,
        contlen;
    struct ccnl_buf_s *buf = 0, *nonce = 0, *ppkd = 0;
    struct ccnl_interest_s *i = 0;
    struct ccnl_content_s *c = 0;
    struct ccnl_prefix_s *p = 0;
    unsigned char *content = 0;
    DEBUGMSG(1, "ccnl_core_RX_i_or_c: (%d bytes left)\n", *datalen);

    buf = ccnl_extract_prefix_nonce_ppkd(data, datalen, &scope, &aok, &minsfx,
                                         &maxsfx, &p, &nonce, &ppkd, &content, &contlen);

    if (!buf) {
        DEBUGMSG(6, "  parsing error or no prefix\n");
        goto Done;
    }

    if (nonce && ccnl_nonce_find_or_append(relay, nonce)) {
        DEBUGMSG(6, "  dropped because of duplicate nonce\n");
        goto Skip;
    }

    if (buf->data[0] == 0x01 && buf->data[1] == 0xd2) { // interest
        DEBUGMSG(1, "ccnl_core_RX_i_or_c: interest=<%s>\n", ccnl_prefix_to_path(p));
        from->stat.received_interest++;

        if (p->compcnt > 0 && p->comp[0][0] == (unsigned char) 0xc1) {
            goto Skip;
        }

        if (p->compcnt == 4 && !memcmp(p->comp[0], "ccnx", 4)) {
            DEBUGMSG(1, "it's a mgnt msg!\n");
            rc = ccnl_mgmt(relay, buf, p, from);
            DEBUGMSG(1, "mgnt processing done!\n");
            goto Done;
        }

        // CONFORM: Step 1:
        if (aok & 0x01) { // honor "answer-from-existing-content-store" flag
            for (c = relay->contents; c; c = c->next) {
                if (!ccnl_i_prefixof_c(p, ppkd, minsfx, maxsfx, c)) {
                    continue;
                }

                // FIXME: should check stale bit in aok here
                DEBUGMSG(7, "  matching content for interest, content %p\n",
                         (void *) c);
                from->stat.send_content[c->served_cnt % CCNL_MAX_CONTENT_SERVED_STAT]++;
                c->served_cnt++;

                if (from->ifndx >= 0) {
                    ccnl_face_enqueue(relay, from, buf_dup(c->pkt));
                }

                goto Skip;
            }
        }

        // CONFORM: Step 2: check whether interest is already known
        for (i = relay->pit; i; i = i->next) {
            if (!ccnl_prefix_cmp(i->prefix, NULL, p, CMP_EXACT)
                && i->minsuffix == minsfx && i->maxsuffix == maxsfx
                && ((!ppkd && !i->ppkd) || buf_equal(ppkd, i->ppkd))) {
                break;
            }
        }

        if (!i) { // this is a new/unknown I request: create and propagate
            i = ccnl_interest_new(relay, from, &buf, &p, minsfx, maxsfx, &ppkd);

            if (i) { // CONFORM: Step 3 (and 4)
                DEBUGMSG(7, "  created new interest entry %p\n", (void *) i);

                if (scope > 2) {
                    ccnl_interest_propagate(relay, i);
                }
            }
        }
        else if (scope > 2 && (from->flags & CCNL_FACE_FLAGS_FWDALLI)) {
            DEBUGMSG(7, "  old interest, nevertheless propagated %p\n",
                     (void *) i);
            ccnl_interest_propagate(relay, i);
        }

        if (i) { // store the I request, for the incoming face (Step 3)
            DEBUGMSG(7, "  appending interest entry %p\n", (void *) i);
            ccnl_interest_append_pending(i, from);
        }
    }
    else {   // content
        DEBUGMSG(6, "  content=<%s>\n", ccnl_prefix_to_path(p));
        from->stat.received_content++;

        // CONFORM: Step 1:
        for (c = relay->contents; c; c = c->next) {
            if (buf_equal(c->pkt, buf)) {
                DEBUGMSG(1, "content is dup: skip\n");
                goto Skip;
            }
        }

        c = ccnl_content_new(relay, &buf, &p, &ppkd, content, contlen);

        if (c) { // CONFORM: Step 2 (and 3)
            if (!ccnl_content_serve_pending(relay, c, from)) { // unsolicited content
                // CONFORM: "A node MUST NOT forward unsolicited data [...]"
                DEBUGMSG(7, "  removed because no matching interest\n");
                free_content(c);
                goto Skip;
            }
#if CCNL_DYNAMIC_FIB
            else {
                /* content has matched an interest, we consider this name as available on this face */
                ccnl_content_learn_name_route(relay, c->name, from, relay->fib_threshold_prefix, 0);
            }
#endif

            if (relay->max_cache_entries != 0) { // it's set to -1 or a limit
                DEBUGMSG(7, "  adding content to cache\n");
                ccnl_content_add2cache(relay, c);
            }
            else {
                DEBUGMSG(7, "  content not added to cache\n");
                free_content(c);
            }
        }
    }

Skip:
    rc = 0;
Done:
    free_prefix(p);
    free_3ptr_list(buf, nonce, ppkd);
    DEBUGMSG(1, "leaving\n");
    return rc;
}
Esempio n. 16
0
// deliver new content c to all clients with (loosely) matching interest,
// but only one copy per face
// returns: number of forwards
int
ccnl_content_serve_pending(struct ccnl_relay_s *ccnl, struct ccnl_content_s *c)
{
    struct ccnl_interest_s *i;
    struct ccnl_face_s *f;
    int cnt = 0;
    DEBUGMSG_CORE(TRACE, "ccnl_content_serve_pending\n");

    for (f = ccnl->faces; f; f = f->next){
                f->flags &= ~CCNL_FACE_FLAGS_SERVED; // reply on a face only once
    }
    for (i = ccnl->pit; i;) {
        struct ccnl_pendint_s *pi;
        if (!i->pkt->pfx)
            continue;

        switch (i->pkt->pfx->suite) {
#ifdef USE_SUITE_CCNB
        case CCNL_SUITE_CCNB:
            if (!ccnl_i_prefixof_c(i->pkt->pfx, i->pkt->s.ccnb.minsuffix,
                       i->pkt->s.ccnb.maxsuffix, c)) {
                // XX must also check i->ppkd
                i = i->next;
                continue;
            }
            break;
#endif
#ifdef USE_SUITE_CCNTLV
        case CCNL_SUITE_CCNTLV:
            if (ccnl_prefix_cmp(c->pkt->pfx, NULL, i->pkt->pfx, CMP_EXACT)) {
                // XX must also check keyid
                i = i->next;
                continue;
            }
            break;
#endif
#ifdef USE_SUITE_CISTLV
        case CCNL_SUITE_CISTLV:
            if (ccnl_prefix_cmp(c->pkt->pfx, NULL, i->pkt->pfx, CMP_EXACT)) {
                // XX must also check keyid
                i = i->next;
                continue;
            }
            break;
#endif
#ifdef USE_SUITE_IOTTLV
        case CCNL_SUITE_IOTTLV:
          if (ccnl_prefix_cmp(c->pkt->pfx, NULL, i->pkt->pfx, CMP_EXACT)) {
                // XX must also check keyid
                i = i->next;
                continue;
            }
            break;
#endif
#ifdef USE_SUITE_NDNTLV
        case CCNL_SUITE_NDNTLV:
            if (!ccnl_i_prefixof_c(i->pkt->pfx, i->pkt->s.ndntlv.minsuffix,
                       i->pkt->s.ndntlv.maxsuffix, c)) {
                // XX must also check i->ppkl,
                i = i->next;
                continue;
            }
            break;
#endif
        default:
            i = i->next;
            continue;
        }

        //Hook for add content to cache by callback:
        if(i && ! i->pending){
            DEBUGMSG_CORE(WARNING, "releasing interest 0x%p OK?\n", (void*)i);
            c->flags |= CCNL_CONTENT_FLAGS_STATIC;
            i = ccnl_interest_remove(ccnl, i);
            return 1;
        }

        // CONFORM: "Data MUST only be transmitted in response to
        // an Interest that matches the Data."
        for (pi = i->pending; pi; pi = pi->next) {
            if (pi->face->flags & CCNL_FACE_FLAGS_SERVED)
            continue;
            pi->face->flags |= CCNL_FACE_FLAGS_SERVED;
            if (pi->face->ifndx >= 0) {
                DEBUGMSG_CFWD(INFO, "  outgoing data=<%s>%s to=%s\n",
                          ccnl_prefix_to_path(i->pkt->pfx),
                          ccnl_suite2str(i->pkt->pfx->suite),
                          ccnl_addr2ascii(&pi->face->peer));
                DEBUGMSG_CORE(VERBOSE, "    Serve to face: %d (pkt=%p)\n",
                         pi->face->faceid, (void*) c->pkt);
                ccnl_nfn_monitor(ccnl, pi->face, c->pkt->pfx,
                                 c->pkt->content, c->pkt->contlen);
                ccnl_face_enqueue(ccnl, pi->face, buf_dup(c->pkt->buf));
            } else {// upcall to deliver content to local client
                ccnl_app_RX(ccnl, c);
            }
            c->served_cnt++;
            cnt++;
        }
        i = ccnl_interest_remove(ccnl, i);
    }
    return cnt;
}
Esempio n. 17
0
void
ccnl_interest_propagate(struct ccnl_relay_s *ccnl, struct ccnl_interest_s *i)
{
    struct ccnl_forward_s *fwd;
    int rc = 0;
#ifdef USE_NACK
    int matching_face = 0;
#endif

    if (!i)
        return;
    DEBUGMSG_CORE(DEBUG, "ccnl_interest_propagate\n");

    // CONFORM: "A node MUST implement some strategy rule, even if it is only to
    // transmit an Interest Message on all listed dest faces in sequence."
    // CCNL strategy: we forward on all FWD entries with a prefix match

    for (fwd = ccnl->fib; fwd; fwd = fwd->next) {
        if (!fwd->prefix)
            continue;

        //Only for matching suite
        if (!i->pkt->pfx || fwd->suite != i->pkt->pfx->suite) {
            DEBUGMSG_CORE(VERBOSE, "  not same suite (%d/%d)\n",
                     fwd->suite, i->pkt->pfx ? i->pkt->pfx->suite : -1);
            continue;
        }

        rc = ccnl_prefix_cmp(fwd->prefix, NULL, i->pkt->pfx, CMP_LONGEST);

        DEBUGMSG_CORE(DEBUG, "  ccnl_interest_propagate, rc=%d/%d\n",
                 rc, fwd->prefix->compcnt);
        if (rc < fwd->prefix->compcnt)
            continue;

        DEBUGMSG_CORE(DEBUG, "  ccnl_interest_propagate, fwd==%p\n", (void*)fwd);
        // suppress forwarding to origin of interest, except wireless
        if (!i->from || fwd->face != i->from ||
                                (i->from->flags & CCNL_FACE_FLAGS_REFLECT)) {
            DEBUGMSG_CFWD(INFO, "  outgoing interest=<%s> to=%s\n",
                          ccnl_prefix_to_path(i->pkt->pfx),
                          fwd->face ? ccnl_addr2ascii(&fwd->face->peer)
                                    : "<tap>");
            ccnl_nfn_monitor(ccnl, fwd->face, i->pkt->pfx, NULL, 0);

            // DEBUGMSG(DEBUG, "%p %p %p\n", (void*)i, (void*)i->pkt, (void*)i->pkt->buf);
            if (fwd->tap)
                (fwd->tap)(ccnl, i->from, i->pkt->pfx, i->pkt->buf);
            if (fwd->face)
                ccnl_face_enqueue(ccnl, fwd->face, buf_dup(i->pkt->buf));
#ifdef USE_NACK
            matching_face = 1;
#endif
        } else {
            DEBUGMSG_CORE(DEBUG, "  not forwarded\n");
        }
    }

#ifdef USE_NACK
    if(!matching_face){
        ccnl_nack_reply(ccnl, i->pkt->pfx, i->from, i->pkt->pfx->suite);
        ccnl_interest_remove(ccnl, i);
    }
#endif

    return;
}