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; }
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; }
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; }
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; }
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; }
// 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; }
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; }
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; }
/** * 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; }
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; }
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; }
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; }
// 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; }
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; }