void ccnl_core_cleanup(struct ccnl_relay_s *ccnl) { int k; DEBUGMSG_CORE(TRACE, "ccnl_core_cleanup %p\n", (void *) ccnl); while (ccnl->pit) ccnl_interest_remove(ccnl, ccnl->pit); while (ccnl->faces) ccnl_face_remove(ccnl, ccnl->faces); // removes allmost all FWD entries while (ccnl->fib) { struct ccnl_forward_s *fwd = ccnl->fib->next; ccnl_prefix_free(ccnl->fib->prefix); ccnl_free(ccnl->fib); ccnl->fib = fwd; } while (ccnl->contents) ccnl_content_remove(ccnl, ccnl->contents); while (ccnl->nonces) { struct ccnl_buf_s *tmp = ccnl->nonces->next; ccnl_free(ccnl->nonces); ccnl->nonces = tmp; } for (k = 0; k < ccnl->ifcount; k++) ccnl_interface_cleanup(ccnl->ifs + k); }
void ccnl_core_cleanup(struct ccnl_relay_s *ccnl) { int k; DEBUGMSG(99, "ccnl_core_cleanup %p\n", (void *) ccnl); while (ccnl->pit) { ccnl_interest_remove(ccnl, ccnl->pit); } while (ccnl->faces) { ccnl_face_remove(ccnl, ccnl->faces); // also removes all FWD entries } while (ccnl->contents) { ccnl_content_remove(ccnl, ccnl->contents); } while (ccnl->nonces) { ccnl_nonce_remove(ccnl, ccnl->nonces); } for (k = 0; k < ccnl->ifcount; k++) { ccnl_interface_cleanup(ccnl->ifs + k); } }
void ccnl_do_ageing(void *ptr, void *dummy) { (void) dummy; /* unused */ struct ccnl_relay_s *relay = (struct ccnl_relay_s *) ptr; struct ccnl_interest_s *i = relay->pit; struct ccnl_content_s *c = relay->contents; struct ccnl_face_s *f = relay->faces; struct timeval now; ccnl_get_timeval(&now); //DEBUGMSG(999, "ccnl_do_ageing %ld:%ld\n", now.tv_sec, now.tv_usec); while (i) { if (ccnl_is_timed_out(&now, &i->last_used, CCNL_INTEREST_TIMEOUT_SEC, CCNL_INTEREST_TIMEOUT_USEC)) { if (i->from->ifndx == RIOT_MSG_IDX) { /* this interest was requested by an app from this node */ /* inform this app about this problem */ riot_send_nack(i->from->faceid); } i = ccnl_interest_remove(relay, i); } else { i = i->next; } } while (c) { if (ccnl_is_timed_out(&now, &c->last_used, CCNL_CONTENT_TIMEOUT_SEC, CCNL_CONTENT_TIMEOUT_USEC) && !(c->flags & CCNL_CONTENT_FLAGS_STATIC)) { c = ccnl_content_remove(relay, c); } else { c = c->next; } } while (f) { if (!(f->flags & CCNL_FACE_FLAGS_STATIC) && ccnl_is_timed_out(&now, &f->last_used, CCNL_FACE_TIMEOUT_SEC, CCNL_FACE_TIMEOUT_USEC)) { f = ccnl_face_remove(relay, f); } else { f = f->next; } } struct ccnl_forward_s *fwd = relay->fib; while (fwd) { if (!(fwd->flags & CCNL_FORWARD_FLAGS_STATIC) && ccnl_is_timed_out(&now, &fwd->last_used, CCNL_FWD_TIMEOUT_SEC, CCNL_FWD_TIMEOUT_USEC)) { fwd = ccnl_forward_remove(relay, fwd); } else { fwd = fwd->next; } } }
// 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_face_s *from) { struct ccnl_interest_s *i; struct ccnl_face_s *f; int cnt = 0; DEBUGMSG(99, "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 (!ccnl_i_prefixof_c(i->prefix, i->ppkd, i->minsuffix, i->maxsuffix, c)) { i = i->next; continue; } // 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; } if (pi->face == from) { // the existing pending interest is from the same face // as the newly arrived content is...no need to send content back DEBUGMSG(1, " detected looping content, before loop could happen\n"); continue; } pi->face->flags |= CCNL_FACE_FLAGS_SERVED; DEBUGMSG(6, " forwarding content <%s>\n", ccnl_prefix_to_path(c->name)); pi->face->stat.send_content[c->served_cnt % CCNL_MAX_CONTENT_SERVED_STAT]++; ccnl_face_enqueue(ccnl, pi->face, buf_dup(c->pkt)); c->served_cnt++; ccnl_get_timeval(&c->last_used); cnt++; } i = ccnl_interest_remove(ccnl, i); } return cnt; }
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; }
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; }
// 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; }
struct ccnl_face_s * ccnl_face_remove(struct ccnl_relay_s *ccnl, struct ccnl_face_s *f) { struct ccnl_face_s *f2; struct ccnl_interest_s *pit; struct ccnl_forward_s **ppfwd; DEBUGMSG(1, "ccnl_face_remove relay=%p face=%p\n", (void *) ccnl, (void *) f); ccnl_sched_destroy(f->sched); ccnl_frag_destroy(f->frag); for (pit = ccnl->pit; pit;) { struct ccnl_pendint_s **ppend, *pend; if (pit->from == f) { pit->from = NULL; } for (ppend = &pit->pending; *ppend;) { if ((*ppend)->face == f) { pend = *ppend; *ppend = pend->next; ccnl_free(pend); } else { ppend = &(*ppend)->next; } } if (pit->pending) { pit = pit->next; } else { pit = ccnl_interest_remove(ccnl, pit); } } for (ppfwd = &ccnl->fib; *ppfwd;) { if ((*ppfwd)->face == f) { struct ccnl_forward_s *pfwd = *ppfwd; *ppfwd = pfwd->next; ccnl_forward_remove(ccnl, pfwd); } else { ppfwd = &(*ppfwd)->next; } } while (f->outq) { struct ccnl_buf_s *tmp = f->outq->next; ccnl_free(f->outq); f->outq = tmp; } #if ENABLE_DEBUG ccnl_face_print_stat(f); #endif f2 = f->next; DBL_LINKED_LIST_REMOVE(ccnl->faces, f); ccnl_free(f); return f2; }