Exemplo n.º 1
0
int
ccnl_interest_append_pending(struct ccnl_interest_s *i,
                             struct ccnl_face_s *from)
{
    struct ccnl_pendint_s *pi, *last = NULL;
    DEBUGMSG_CORE(TRACE, "ccnl_append_pending\n");

    for (pi = i->pending; pi; pi = pi->next) { // check whether already listed
        if (pi->face == from) {
            DEBUGMSG_CORE(DEBUG, "  we found a matching interest, updating time\n");
            pi->last_used = CCNL_NOW();
            return 0;
        }
        last = pi;
    }
    pi = (struct ccnl_pendint_s *) ccnl_calloc(1,sizeof(struct ccnl_pendint_s));
    if (!pi) {
        DEBUGMSG_CORE(DEBUG, "  no mem\n");
        return -1;
    }
    DEBUGMSG_CORE(DEBUG, "  appending a new pendint entry %p\n", (void *) pi);
    pi->face = from;
    pi->last_used = CCNL_NOW();
    if (last)
        last->next = pi;
    else
        i->pending = pi;
    return 0;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
struct ccnl_content_s*
ccnl_content_new(struct ccnl_relay_s *ccnl, struct ccnl_pkt_s **pkt)
{
    struct ccnl_content_s *c;

//    DEBUGMSG_CORE(TRACE, "ccnl_content_new %p <%s [%d]>\n",
//             (void*) *pkt, ccnl_prefix_to_path((*pkt)->pfx), ((*pkt)->pfx->chunknum)? *((*pkt)->pfx->chunknum) : -1);

    c = (struct ccnl_content_s *) ccnl_calloc(1, sizeof(struct ccnl_content_s));
    if (!c)
        return NULL;
    c->pkt = *pkt;
    *pkt = NULL;
    c->last_used = CCNL_NOW();
    c->recommended_cache_time = CCNL_NOW() + PUBLISHING_TIMEPERIOD;
    return c;
}
Exemplo n.º 4
0
void
ccnl_do_ageing(void *ptr, void *dummy)
{
    (void) dummy;
    struct ccnl_relay_s *relay = (struct ccnl_relay_s*) ptr;
    struct ccnl_content_s *c = relay->contents;
    struct ccnl_interest_s *i = relay->pit;
    struct ccnl_face_s *f = relay->faces;
    time_t t = CCNL_NOW();
    DEBUGMSG_CORE(TRACE, "ageing t=%d\n", (int)t);

    while (c) {
        if ((c->last_used + CCNL_CONTENT_TIMEOUT) <= t &&
                                !(c->flags & CCNL_CONTENT_FLAGS_STATIC)){
          DEBUGMSG_CORE(TRACE, "AGING: CONTENT REMOVE %p\n", (void*) c);
            c = ccnl_content_remove(relay, c);
        }
        else
            c = c->next;
    }
    while (i) { // CONFORM: "Entries in the PIT MUST timeout rather
                // than being held indefinitely."
        if ((i->last_used + CCNL_INTEREST_TIMEOUT) <= t ||
                                i->retries > CCNL_MAX_INTEREST_RETRANSMIT) {
            DEBUGMSG_CORE(TRACE, "AGING: INTEREST REMOVE %p\n", (void*) i);
            DEBUGMSG_CORE(DEBUG, " timeout: remove interest 0x%p <%s>\n",
                          (void*)i,
                     ccnl_prefix_to_path(i->pkt->pfx));
            i = ccnl_nfn_interest_remove(relay, i);
        } else {
            // CONFORM: "A node MUST retransmit Interest Messages
            // periodically for pending PIT entries."
            DEBUGMSG_CORE(DEBUG, " retransmit %d <%s>\n", i->retries,
                     ccnl_prefix_to_path(i->pkt->pfx));
#ifdef USE_NFN
            if (i->flags & CCNL_PIT_COREPROPAGATES){
#endif
                DEBUGMSG_CORE(TRACE, "AGING: PROPAGATING INTEREST %p\n", (void*) i);
                ccnl_interest_propagate(relay, i);
#ifdef USE_NFN
            }
#endif

            i->retries++;
            i = i->next;
        }
    }
    while (f) {
        if (!(f->flags & CCNL_FACE_FLAGS_STATIC) &&
                (f->last_used + CCNL_FACE_TIMEOUT) <= t){
            DEBUGMSG_CORE(TRACE, "AGING: FACE REMOVE %p\n", (void*) f);
            f = ccnl_face_remove(relay, f);
    }
        else
            f = f->next;
    }
}
Exemplo n.º 5
0
char*
timestamp(void)
{
    static char ts[30], *cp;

    sprintf(ts, "%.4g", CCNL_NOW());
    cp = strchr(ts, '.');
    if (!cp)
	strcat(ts, ".0000");
    else if (strlen(cp) > 5)
	cp[5] = '\0';
    else while (strlen(cp) < 5)
	strcat(cp, "0");
    return ts;
}
Exemplo n.º 6
0
struct ccnl_content_s*
ccnl_content_new(struct ccnl_relay_s *ccnl, struct ccnl_pkt_s **pkt)
{
    struct ccnl_content_s *c;

    DEBUGMSG_CORE(TRACE, "ccnl_content_new %p <%s [%d]>\n",
             (void*) *pkt, ccnl_prefix_to_path((*pkt)->pfx), ((*pkt)->pfx->chunknum)? *((*pkt)->pfx->chunknum) : -1);

    c = (struct ccnl_content_s *) ccnl_calloc(1, sizeof(struct ccnl_content_s));
    if (!c)
        return NULL;
    c->pkt = *pkt;
    *pkt = NULL;
    c->last_used = CCNL_NOW();

    return c;
}
Exemplo n.º 7
0
struct ccnl_content_s *
oldestCacheTimeExpiredContent(struct ccnl_relay_s *ccnl){
    struct ccnl_content_s *cit;
    struct ccnl_content_s *cacheTimeExpiredContent = NULL;
    double leastCacheTimeLeft = 10; // set initial value to anything greater than zero because of first time entry into the if condition below
    double cacheTimeLeft =0;
    for (cit = ccnl->contents; cit; cit = cit->next) {
        cacheTimeLeft = cit->recommended_cache_time - CCNL_NOW();
//        DEBUGMSG_CORE(DEBUG, " ICNIoT: RCT is %f, time now is %f cacheTimeLeft is %f\n",cit->recommended_cache_time, CCNL_NOW(), cacheTimeLeft);
        if ((cacheTimeLeft <= 0) && (leastCacheTimeLeft > cacheTimeLeft)){
           DEBUGMSG_CORE(DEBUG, " ICNIoT: RCT cacheTime expired\n");
           leastCacheTimeLeft = cacheTimeLeft;
           cacheTimeExpiredContent = cit;
        }
    }
    return cacheTimeExpiredContent;
}
Exemplo n.º 8
0
struct ccnl_interest_s*
ccnl_interest_new(struct ccnl_relay_s *ccnl, struct ccnl_face_s *from,
                  struct ccnl_pkt_s **pkt)
{
    struct ccnl_interest_s *i = (struct ccnl_interest_s *) ccnl_calloc(1,
                                            sizeof(struct ccnl_interest_s));
    DEBUGMSG_CORE(TRACE,
                  "ccnl_new_interest(prefix=%s, suite=%s)\n",
                  ccnl_prefix_to_path((*pkt)->pfx),
                  ccnl_suite2str((*pkt)->pfx->suite));

    if (!i)
        return NULL;
    i->pkt = *pkt;
    *pkt = NULL;
    i->flags |= CCNL_PIT_COREPROPAGATES;
    i->from = from;
    i->last_used = CCNL_NOW();
    DBL_LINKED_LIST_ADD(ccnl->pit, i);

    return i;
}
Exemplo n.º 9
0
struct ccnl_interest_s*
ccnl_interest_new(struct ccnl_relay_s *ccnl, struct ccnl_face_s *from,
                  struct ccnl_pkt_s **pkt)
{
    struct ccnl_interest_s *i = (struct ccnl_interest_s *) ccnl_calloc(1,
                                            sizeof(struct ccnl_interest_s));
    DEBUGMSG_CORE(TRACE, "ccnl_new_interest\n");
             //             ccnl_prefix_to_path((*pkt)->pfx),
             //             ccnl_suite2str((*pkt)->pfx->suite));

    if (!i)
        return NULL;
    i->pkt = *pkt;
    *pkt = NULL;
    i->flags |= CCNL_PIT_COREPROPAGATES;
    i->from = from;
    i->last_used = CCNL_NOW();
    DBL_LINKED_LIST_ADD(ccnl->pit, i);
//akhila 16-10-2015
    ccnl->pitcnt++;
    DEBUGMSG_CORE(TRACE, ": pit_entry_added:%d\n",ccnl->pitcnt);
    return i;
}
Exemplo n.º 10
0
struct ccnl_face_s*
ccnl_get_face_or_create(struct ccnl_relay_s *ccnl, int ifndx,
                       struct sockaddr *sa, int addrlen)
// sa==NULL means: local(=in memory) client, search for existing ifndx being -1
// sa!=NULL && ifndx==-1: search suitable interface for given sa_family
// sa!=NULL && ifndx!=-1: use this (incoming) interface for outgoing
{
    static int seqno;
    int i;
    struct ccnl_face_s *f;

    DEBUGMSG_CORE(TRACE, "ccnl_get_face_or_create src=%s\n",
             ccnl_addr2ascii((sockunion*)sa));

    for (f = ccnl->faces; f; f = f->next) {
        if (!sa) {
            if (f->ifndx == -1)
                return f;
            continue;
        }
        if (ifndx != -1 && !ccnl_addr_cmp(&f->peer, (sockunion*)sa)) {
            f->last_used = CCNL_NOW();
            return f;
        }
    }

    if (sa && ifndx == -1) {
        for (i = 0; i < ccnl->ifcount; i++) {
            if (sa->sa_family != ccnl->ifs[i].addr.sa.sa_family)
                continue;
            ifndx = i;
            break;
        }
        if (ifndx == -1) // no suitable interface found
            return NULL;
    }
    DEBUGMSG_CORE(VERBOSE, "  found suitable interface %d for %s\n", ifndx,
                ccnl_addr2ascii((sockunion*)sa));

    f = (struct ccnl_face_s *) ccnl_calloc(1, sizeof(struct ccnl_face_s));
    if (!f) {
        DEBUGMSG_CORE(VERBOSE, "  no memory for face\n");
        return NULL;
    }
    f->faceid = ++seqno;
    f->ifndx = ifndx;

    if (ifndx >= 0) {
        if (ccnl->defaultFaceScheduler)
            f->sched = ccnl->defaultFaceScheduler(ccnl,
                                          (void(*)(void*,void*))ccnl_face_CTS);
        if (ccnl->ifs[ifndx].reflect)   f->flags |= CCNL_FACE_FLAGS_REFLECT;
        if (ccnl->ifs[ifndx].fwdalli)   f->flags |= CCNL_FACE_FLAGS_FWDALLI;
    }

    if (sa)
        memcpy(&f->peer, sa, addrlen);
    else // local client
        f->ifndx = -1;
    f->last_used = CCNL_NOW();
    DBL_LINKED_LIST_ADD(ccnl->faces, f);

    TRACEOUT();
    return f;
}
Exemplo n.º 11
0
void
ccnl_do_ageing(void *ptr, void *dummy)
{
    struct ccnl_relay_s *relay = (struct ccnl_relay_s*) ptr;
    struct ccnl_content_s *c = relay->contents;
    struct ccnl_interest_s *i = relay->pit;
    struct ccnl_face_s *f = relay->faces;
    time_t t = CCNL_NOW();
    char *bufp = NULL;
    DEBUGMSG_CORE(INFO, " ICNIoT: ageing t=%d\n", (int)t);

    while (c) {
        if ((c->last_used + CCNL_CONTENT_TIMEOUT) <= t &&
                                !(c->flags & CCNL_CONTENT_FLAGS_STATIC)){
          DEBUGMSG_CORE(INFO, " ICNIoT: AGING: CONTENT REMOVE %p\n", (void*) c);
            c = ccnl_content_remove(relay, c);
        }
        else{
//akhila 29-10-2015
        // check if it is the n th time instant. If yes then save the content store 
             if ((((int)t)%CS_SAVE_PERIOD == 0) && !(c->flags & CCNL_CONTENT_FLAGS_STATIC)){
                 bufp = ccnl_prefix_to_path((c->pkt)->pfx);
                 DEBUGMSG_CORE(INFO, " ICNIoT: ContentStoreItem :%s\n",bufp);
                 ccnl_free(bufp);
             }
            c = c->next;
        }
    }
    if (((int)t)%CS_SAVE_PERIOD == 0){
    	DEBUGMSG_CORE(INFO, " ICNIoT: ContentStoreItem contentCount:%d\n",relay->contentcnt);
      }
    while (i) { // CONFORM: "Entries in the PIT MUST timeout rather
                // than being held indefinitely."
        if ((i->last_used + CCNL_INTEREST_TIMEOUT) <= t){ // if it has timed out either resend it or remove it based on MAX_RETRIES
                if(i->retries >= CCNL_MAX_INTEREST_RETRANSMIT){
            		DEBUGMSG_CORE(INFO, " ICNIoT: AGING: INTEREST REMOVE %p\n", (void*) i);
//            		DEBUGMSG_CORE(DEBUG, " timeout: remove interest 0x%p <%s>\n",(void*)i,ccnl_prefix_to_path(i->pkt->pfx));
            		i = ccnl_nfn_interest_remove(relay, i);
        	  }
        	else {
            		// CONFORM: "A node MUST retransmit Interest Messages
            		// periodically for pending PIT entries."
            		DEBUGMSG_CORE(INFO, " ICNIoT: retransmit %d \n", i->retries);
//                      ccnl_prefix_to_path(i->pkt->pfx));
#ifdef USE_NFN
            		if (i->flags & CCNL_PIT_COREPROPAGATES){
#endif
     		           DEBUGMSG_CORE(INFO, " ICNIoT: AGING: PROPAGATING INTEREST %p\n", (void*) i);
                	   ccnl_interest_propagate(relay, i);
#ifdef USE_NFN
                        }
#endif
            		i->retries++;
            		i = i->next;
        	}
         }
        else{ // The interest has not timed out yet, so leave it alone !
//		DEBUGMSG_CORE(INFO, " ICNIoT: AGING: DO NOTHING %p\n", (void*) i);
		i = i->next;
            } 
    }
//    DEBUGMSG_CORE(INFO, " ICNIoT: PITcount %d\n",relay->pitcnt);
    while (f) {
        if (!(f->flags & CCNL_FACE_FLAGS_STATIC) &&
                (f->last_used + CCNL_FACE_TIMEOUT) <= t){
            DEBUGMSG_CORE(TRACE, "AGING: FACE REMOVE %p\n", (void*) f);
            f = ccnl_face_remove(relay, f);
    }
        else
            f = f->next;
    }
}
Exemplo n.º 12
0
int drop_this_pkt(struct ccnl_relay_s *relay, struct ccnl_face_s *from){
        int drop = 0;
#ifdef USE_LOSSY_LINKS
	int from_nodeID = findIntFromStr(ccnl_addr2ascii(from ? &from->peer : NULL),"/") - 9000;	// NULL here means there is something wrong
        int my_nodeID = relay->nodeID;
//        DEBUGMSG_CORE(DEBUG, " ICNIoT: pkt received at node %d from node %d\n",my_nodeID, from_nodeID);

        int* ptr = relay->network_links_ptr;
        int j=0;
        int flag = 0;
        for(j=0;j<relay->num_of_links;j++){
            if(((*(ptr + 2*j) == from_nodeID) && (*(ptr + 2*j +1) == my_nodeID)) || ((*(ptr + 2*j) == my_nodeID) && (*(ptr + 2*j +1) == from_nodeID))){// this implies that we are checking bidirectional links
                flag =1;
                break;
             }
        }
        if(flag==0){
//           DEBUGMSG_CORE(DEBUG, " ICNIoT: This link is NOT a lossy link\n");
           return 0;
        }

//        DEBUGMSG_CORE(DEBUG, " ICNIoT: This link is a lossy link\n");

	double P[2][2];
	P[0][0] = (double)1-(double)ALPHA;
	P[0][1] = (double)ALPHA;
	P[1][0] = (double)BETA;
	P[1][1] = (double)1-(double)BETA;
	// 100 ms is one step 
	double val;
	int i=0;
        j=0;
//        int m=2;
	int n = (int)(((CCNL_NOW() - relay->last_pkt_recv_time)*(double)STEP_SCALE) + 1);
//        DEBUGMSG_CORE(DEBUG, " ICNIoT: number of steps passed since last pkt receive is %f - %f = %d\n",CCNL_NOW(),relay->last_pkt_recv_time,n);
	if (n > 20)// This 20 is because when n is large, due to loss of accuracy the P^n matrix either becomes all 0s or inf
		n=20;

	for(i=0;i<n;i++)
		squareOfMatrix(P);

//	printf("P^%d is \n",n);
//        for(i=0;i<m;i++){
//                for(j=0;j<m;j++){
//                        printf("%f ",P[i][j]);
//                }
//		printf("\n");
//        }

	val = P[relay->last_state][0];
//        DEBUGMSG_CORE(DEBUG, " ICNIoT: current state is %d\n",relay->last_state);
        double rnd = (double)rand() / (double)((unsigned)RAND_MAX + 1);  
        if(rnd < val)
		relay->last_state = 0; //update state
	else relay->last_state = 1; // update state


        rnd = (double)rand() / (double)((unsigned)RAND_MAX + 1);
//	DEBUGMSG_CORE(DEBUG, " ICNIoT: Next state is %d, using error rate = %f\n",relay->last_state, relay->linkErrProb[relay->last_state]);
	if(rnd < relay->linkErrProb[relay->last_state])
                drop =1;


	relay->last_pkt_recv_time = CCNL_NOW();
#endif
        return drop;
}
Exemplo n.º 13
0
int
ccnl_http_status(struct ccnl_relay_s *ccnl, struct ccnl_http_s *http)
{
    static char txt[64000];
    char *hdr =
        "HTTP/1.1 200 OK\n\r"
        "Content-Type: text/html; charset=utf-8\n\r"
        "Connection: close\n\r\n\r", *cp;
    int len = strlen(hdr), i, j, cnt;
    time_t t;
    struct utsname uts;
    struct ccnl_face_s *f;
    struct ccnl_forward_s *fwd;
    struct ccnl_interest_s *ipt;
    struct ccnl_buf_s *bpt;

    strcpy(txt, hdr);
    len += sprintf(txt+len,
                   "<html><head><title>ccn-lite-relay status</title>\n"
                   "<style type=\"text/css\">\n"
                   "body {font-family: sans-serif;}\n"
                   "</style>\n"
                   "</head><body>\n");
    len += sprintf(txt+len, "\n<table borders=0>\n<tr><td>"
                   "<a href=\"\">[refresh]</a>&nbsp;&nbsp;<td>"
                   "ccn-lite-relay Status Page &nbsp;&nbsp;");
    uname(&uts);
    len += sprintf(txt+len, "node <strong>%s (%d)</strong>\n",
                   uts.nodename, getpid());
    t = time(NULL);
    cp = ctime(&t);
    cp[strlen(cp)-1] = 0;
    len += sprintf(txt+len, "<tr><td><td><font size=-1>%s &nbsp;&nbsp;", cp);
    cp = ctime(&ccnl->startup_time);
    cp[strlen(cp)-1] = 0;
    len += sprintf(txt+len, " (started %s)</font>\n</table>\n", cp);

    len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>"
                   "<tr><td><em>Forwarding Table</em></table><ul>\n");
    for (fwd = ccnl->fib, cnt = 0; fwd; fwd = fwd->next, cnt++);
    if (cnt > 0) {
        struct ccnl_forward_s **fwda;
        fwda = (struct ccnl_forward_s**) ccnl_malloc(cnt * sizeof(fwd));
        for (fwd = ccnl->fib, i = 0; fwd; fwd = fwd->next, i++)
            fwda[i] = fwd;
        qsort(fwda, cnt, sizeof(fwd), ccnl_cmpfib);
        for (i = 0; i < cnt; i++) {
            char fname[10];
            sprintf(fname, "f%d", fwda[i]->face->faceid);
            len += sprintf(txt+len,
                           "<li>via %4s: <font face=courier>%s</font>\n",
                           fname, ccnl_prefix_to_path(fwda[i]->prefix));
        }
        ccnl_free(fwda);
    }
    len += sprintf(txt+len, "</ul>\n");

    len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>"
                   "<tr><td><em>Faces</em></table><ul>\n");
    for (f = ccnl->faces, cnt = 0; f; f = f->next, cnt++);
    if (cnt > 0) {
        struct ccnl_face_s **fa;
        fa = (struct ccnl_face_s**) ccnl_malloc(cnt * sizeof(f));
        for (f = ccnl->faces, i = 0; f; f = f->next, i++)
            fa[i] = f;
        qsort(fa, cnt, sizeof(f), ccnl_cmpfaceid);
        for (i = 0; i < cnt; i++) {
            len += sprintf(txt+len,
                           "<li><strong>f%d</strong> (via i%d) &nbsp;"
                           "peer=<font face=courier>%s</font> &nbsp;ttl=",
                           fa[i]->faceid, fa[i]->ifndx,
                           ccnl_addr2ascii(&(fa[i]->peer)));
            if (fa[i]->flags & CCNL_FACE_FLAGS_STATIC)
                len += sprintf(txt+len, "static");
            else
                len += sprintf(txt+len, "%.1fsec",
                        fa[i]->last_used + CCNL_FACE_TIMEOUT - CCNL_NOW());
            for (j = 0, bpt = fa[i]->outq; bpt; bpt = bpt->next, j++);
            len += sprintf(txt+len, " &nbsp;qlen=%d\n", j);
        }
        ccnl_free(fa);
    }
    len += sprintf(txt+len, "</ul>\n");

    len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>"
                   "<tr><td><em>Interfaces</em></table><ul>\n");
    for (i = 0; i < ccnl->ifcount; i++) {
        len += sprintf(txt+len, "<li><strong>i%d</strong>&nbsp;&nbsp;"
                       "addr=<font face=courier>%s</font>&nbsp;&nbsp;"
                       "qlen=%d/%d\n",
                       i, ccnl_addr2ascii(&ccnl->ifs[i].addr),
                       ccnl->ifs[i].qlen, CCNL_MAX_IF_QLEN);
    }
    len += sprintf(txt+len, "</ul>\n");

    len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>"
                   "<tr><td><em>Misc stats</em></table><ul>\n");
    for (cnt = 0, bpt = ccnl->nonces; bpt; bpt = bpt->next, cnt++);
    len += sprintf(txt+len, "<li>Nonces: %d\n", cnt);
    for (cnt = 0, ipt = ccnl->pit; ipt; ipt = ipt->next, cnt++);
    len += sprintf(txt+len, "<li>Pending interests: %d\n", cnt);
    len += sprintf(txt+len, "<li>Content chunks: %d (max=%d)\n",
                   ccnl->contentcnt, ccnl->max_cache_entries);
    len += sprintf(txt+len, "</ul>\n");

    len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>"
                   "<tr><td><em>Config</em></table><table borders=0>\n");
    len += sprintf(txt+len, "<tr><td>content.timeout:"
                   "<td align=right> %d<td>\n", CCNL_CONTENT_TIMEOUT);
    len += sprintf(txt+len, "<tr><td>face.timeout:"
                   "<td align=right> %d<td>\n", CCNL_FACE_TIMEOUT);
    len += sprintf(txt+len, "<tr><td>interest.maxretransmit:"
                   "<td align=right> %d<td>\n", CCNL_MAX_INTEREST_RETRANSMIT);
    len += sprintf(txt+len, "<tr><td>interest.timeout:"
                   "<td align=right> %d<td>\n", CCNL_INTEREST_TIMEOUT);
    len += sprintf(txt+len, "<tr><td>nonces.max:"
                   "<td align=right> %d<td>\n", CCNL_MAX_NONCES);

    len += sprintf(txt+len, "<tr><td>compile.featureset:<td><td> %s\n",
                   compile_string());
    len += sprintf(txt+len, "<tr><td>compile.time:"
                   "<td><td>%s %s\n", __DATE__, __TIME__);
    len += sprintf(txt+len, "<tr><td>compile.ccnl_core_version:"
                   "<td><td>%s\n", CCNL_VERSION);
    len += sprintf(txt+len, "</table>\n");

    len += sprintf(txt+len, "\n<p><hr></body></html>\n");

    http->out = (unsigned char*) txt;
    http->outoffs = 0;
    http->outlen = len;

    return 0;
}