ccnd.c

Go to the documentation of this file.
00001 /*
00002  * ccnd/ccnd.c
00003  *
00004  * Main program of ccnd - the CCNx Daemon
00005  *
00006  * Copyright (C) 2008-2011 Palo Alto Research Center, Inc.
00007  *
00008  * This work is free software; you can redistribute it and/or modify it under
00009  * the terms of the GNU General Public License version 2 as published by the
00010  * Free Software Foundation.
00011  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00014  * for more details. You should have received a copy of the GNU General Public
00015  * License along with this program; if not, write to the
00016  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  */
00019 
00020 /**
00021  * Main program of ccnd - the CCNx Daemon
00022  */
00023 
00024 #include <errno.h>
00025 #include <fcntl.h>
00026 #include <limits.h>
00027 #include <netdb.h>
00028 #include <poll.h>
00029 #include <signal.h>
00030 #include <stddef.h>
00031 #include <stdint.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <time.h>
00036 #include <unistd.h>
00037 #include <arpa/inet.h>
00038 #include <sys/time.h>
00039 #include <sys/socket.h>
00040 #include <sys/stat.h>
00041 #include <sys/types.h>
00042 #include <sys/un.h>
00043 #include <netinet/in.h>
00044 
00045 #if defined(NEED_GETADDRINFO_COMPAT)
00046     #include "getaddrinfo.h"
00047     #include "dummyin6.h"
00048 #endif
00049 
00050 #include <ccn/bloom.h>
00051 #include <ccn/ccn.h>
00052 #include <ccn/ccn_private.h>
00053 #include <ccn/ccnd.h>
00054 #include <ccn/charbuf.h>
00055 #include <ccn/face_mgmt.h>
00056 #include <ccn/hashtb.h>
00057 #include <ccn/indexbuf.h>
00058 #include <ccn/schedule.h>
00059 #include <ccn/reg_mgmt.h>
00060 #include <ccn/uri.h>
00061 
00062 #include "ccnd_private.h"
00063 #define GOT_HERE ccnd_msg(h, "at ccnd.c:%d", __LINE__);
00064 
00065 static void cleanup_at_exit(void);
00066 static void unlink_at_exit(const char *path);
00067 static int create_local_listener(struct ccnd_handle *h, const char *sockname, int backlog);
00068 static struct face *record_connection(struct ccnd_handle *h,
00069                                       int fd,
00070                                       struct sockaddr *who,
00071                                       socklen_t wholen,
00072                                       int setflags);
00073 static void process_input_message(struct ccnd_handle *h, struct face *face,
00074                                   unsigned char *msg, size_t size, int pdu_ok);
00075 static void process_input(struct ccnd_handle *h, int fd);
00076 static int ccn_stuff_interest(struct ccnd_handle *h,
00077                               struct face *face, struct ccn_charbuf *c);
00078 static void do_deferred_write(struct ccnd_handle *h, int fd);
00079 static void clean_needed(struct ccnd_handle *h);
00080 static struct face *get_dgram_source(struct ccnd_handle *h, struct face *face,
00081                                      struct sockaddr *addr, socklen_t addrlen,
00082                                      int why);
00083 static void content_skiplist_insert(struct ccnd_handle *h,
00084                                     struct content_entry *content);
00085 static void content_skiplist_remove(struct ccnd_handle *h,
00086                                     struct content_entry *content);
00087 static void mark_stale(struct ccnd_handle *h,
00088                        struct content_entry *content);
00089 static ccn_accession_t content_skiplist_next(struct ccnd_handle *h,
00090                                              struct content_entry *content);
00091 static void reap_needed(struct ccnd_handle *h, int init_delay_usec);
00092 static void check_comm_file(struct ccnd_handle *h);
00093 static const char *unlink_this_at_exit = NULL;
00094 static struct nameprefix_entry *nameprefix_for_pe(struct ccnd_handle *h,
00095                                                   struct propagating_entry *pe);
00096 static int nameprefix_seek(struct ccnd_handle *h,
00097                            struct hashtb_enumerator *e,
00098                            const unsigned char *msg,
00099                            struct ccn_indexbuf *comps,
00100                            int ncomps);
00101 static void register_new_face(struct ccnd_handle *h, struct face *face);
00102 static void update_forward_to(struct ccnd_handle *h,
00103                               struct nameprefix_entry *npe);
00104 static void stuff_and_send(struct ccnd_handle *h, struct face *face,
00105                            const unsigned char *data1, size_t size1,
00106                            const unsigned char *data2, size_t size2);
00107 static void ccn_link_state_init(struct ccnd_handle *h, struct face *face);
00108 static void ccn_append_link_stuff(struct ccnd_handle *h,
00109                                   struct face *face,
00110                                   struct ccn_charbuf *c);
00111 static int process_incoming_link_message(struct ccnd_handle *h,
00112                                          struct face *face, enum ccn_dtag dtag,
00113                                          unsigned char *msg, size_t size);
00114 
00115 static void
00116 cleanup_at_exit(void)
00117 {
00118     if (unlink_this_at_exit != NULL) {
00119         unlink(unlink_this_at_exit);
00120         unlink_this_at_exit = NULL;
00121     }
00122 }
00123 
00124 static void
00125 handle_fatal_signal(int sig)
00126 {
00127     cleanup_at_exit();
00128     _exit(sig);
00129 }
00130 
00131 static void
00132 unlink_at_exit(const char *path)
00133 {
00134     if (unlink_this_at_exit == NULL) {
00135         static char namstor[sizeof(struct sockaddr_un)];
00136         strncpy(namstor, path, sizeof(namstor));
00137         unlink_this_at_exit = namstor;
00138         signal(SIGTERM, &handle_fatal_signal);
00139         signal(SIGINT, &handle_fatal_signal);
00140         signal(SIGHUP, &handle_fatal_signal);
00141         atexit(&cleanup_at_exit);
00142     }
00143 }
00144 
00145 static int
00146 comm_file_ok(void)
00147 {
00148     struct stat statbuf;
00149     int res;
00150     if (unlink_this_at_exit == NULL)
00151         return(1);
00152     res = stat(unlink_this_at_exit, &statbuf);
00153     if (res == -1)
00154         return(0);
00155     return(1);
00156 }
00157 
00158 static struct ccn_charbuf *
00159 charbuf_obtain(struct ccnd_handle *h)
00160 {
00161     struct ccn_charbuf *c = h->scratch_charbuf;
00162     if (c == NULL)
00163         return(ccn_charbuf_create());
00164     h->scratch_charbuf = NULL;
00165     c->length = 0;
00166     return(c);
00167 }
00168 
00169 static void
00170 charbuf_release(struct ccnd_handle *h, struct ccn_charbuf *c)
00171 {
00172     c->length = 0;
00173     if (h->scratch_charbuf == NULL)
00174         h->scratch_charbuf = c;
00175     else
00176         ccn_charbuf_destroy(&c);
00177 }
00178 
00179 static struct ccn_indexbuf *
00180 indexbuf_obtain(struct ccnd_handle *h)
00181 {
00182     struct ccn_indexbuf *c = h->scratch_indexbuf;
00183     if (c == NULL)
00184         return(ccn_indexbuf_create());
00185     h->scratch_indexbuf = NULL;
00186     c->n = 0;
00187     return(c);
00188 }
00189 
00190 static void
00191 indexbuf_release(struct ccnd_handle *h, struct ccn_indexbuf *c)
00192 {
00193     c->n = 0;
00194     if (h->scratch_indexbuf == NULL)
00195         h->scratch_indexbuf = c;
00196     else
00197         ccn_indexbuf_destroy(&c);
00198 }
00199 
00200 /**
00201  * Looks up a face based on its faceid (private).
00202  */
00203 static struct face *
00204 face_from_faceid(struct ccnd_handle *h, unsigned faceid)
00205 {
00206     unsigned slot = faceid & MAXFACES;
00207     struct face *face = NULL;
00208     if (slot < h->face_limit) {
00209         face = h->faces_by_faceid[slot];
00210         if (face != NULL && face->faceid != faceid)
00211             face = NULL;
00212     }
00213     return(face);
00214 }
00215 
00216 /**
00217  * Looks up a face based on its faceid.
00218  */
00219 struct face *
00220 ccnd_face_from_faceid(struct ccnd_handle *h, unsigned faceid)
00221 {
00222     return(face_from_faceid(h, faceid));
00223 }
00224 
00225 /**
00226  * Assigns the faceid for a nacent face,
00227  * calls register_new_face() if successful.
00228  */
00229 static int
00230 enroll_face(struct ccnd_handle *h, struct face *face)
00231 {
00232     unsigned i;
00233     unsigned n = h->face_limit;
00234     struct face **a = h->faces_by_faceid;
00235     for (i = h->face_rover; i < n; i++)
00236         if (a[i] == NULL) goto use_i;
00237     for (i = 0; i < n; i++)
00238         if (a[i] == NULL) {
00239             /* bump gen only if second pass succeeds */
00240             h->face_gen += MAXFACES + 1;
00241             goto use_i;
00242         }
00243     i = (n + 1) * 3 / 2;
00244     if (i > MAXFACES) i = MAXFACES;
00245     if (i <= n)
00246         return(-1); /* overflow */
00247     a = realloc(a, i * sizeof(struct face *));
00248     if (a == NULL)
00249         return(-1); /* ENOMEM */
00250     h->face_limit = i;
00251     while (--i > n)
00252         a[i] = NULL;
00253     h->faces_by_faceid = a;
00254 use_i:
00255     a[i] = face;
00256     h->face_rover = i + 1;
00257     face->faceid = i | h->face_gen;
00258     face->meter[FM_BYTI] = ccnd_meter_create(h, "bytein");
00259     face->meter[FM_BYTO] = ccnd_meter_create(h, "byteout");
00260     face->meter[FM_INTI] = ccnd_meter_create(h, "intrin");
00261     face->meter[FM_INTO] = ccnd_meter_create(h, "introut");
00262     face->meter[FM_DATI] = ccnd_meter_create(h, "datain");
00263     face->meter[FM_DATO] = ccnd_meter_create(h, "dataout");
00264     register_new_face(h, face);
00265     return (face->faceid);
00266 }
00267 
00268 static int
00269 choose_face_delay(struct ccnd_handle *h, struct face *face, enum cq_delay_class c)
00270 {
00271     int shift = (c == CCN_CQ_SLOW) ? 2 : 0;
00272     if (c == CCN_CQ_ASAP)
00273         return(1);
00274     if ((face->flags & CCN_FACE_LINK) != 0) /* udplink or such, delay more */
00275         return((h->data_pause_microsec) << shift);
00276     if ((face->flags & CCN_FACE_LOCAL) != 0)
00277         return(5); /* local stream, answer quickly */
00278     if ((face->flags & CCN_FACE_MCAST) != 0)
00279         return((h->data_pause_microsec) << shift); /* multicast, delay more */
00280     if ((face->flags & CCN_FACE_GG) != 0)
00281         return(100 << shift); /* localhost, delay just a little */
00282     if ((face->flags & CCN_FACE_DGRAM) != 0)
00283         return(500 << shift); /* udp, delay just a little */
00284     return(100); /* probably tcp to a different machine */
00285 }
00286 
00287 static struct content_queue *
00288 content_queue_create(struct ccnd_handle *h, struct face *face, enum cq_delay_class c)
00289 {
00290     struct content_queue *q;
00291     unsigned usec;
00292     q = calloc(1, sizeof(*q));
00293     if (q != NULL) {
00294         usec = choose_face_delay(h, face, c);
00295         q->burst_nsec = (usec <= 500 ? 500 : 150000); // XXX - needs a knob
00296         q->min_usec = usec;
00297         q->rand_usec = 2 * usec;
00298         q->nrun = 0;
00299         q->send_queue = ccn_indexbuf_create();
00300         if (q->send_queue == NULL) {
00301             free(q);
00302             return(NULL);
00303         }
00304         q->sender = NULL;
00305     }
00306     return(q);
00307 }
00308 
00309 static void
00310 content_queue_destroy(struct ccnd_handle *h, struct content_queue **pq)
00311 {
00312     struct content_queue *q;
00313     if (*pq != NULL) {
00314         q = *pq;
00315         ccn_indexbuf_destroy(&q->send_queue);
00316         if (q->sender != NULL) {
00317             ccn_schedule_cancel(h->sched, q->sender);
00318             q->sender = NULL;
00319         }
00320         free(q);
00321         *pq = NULL;
00322     }
00323 }
00324 
00325 /**
00326  * Close an open file descriptor quietly.
00327  */
00328 static void
00329 close_fd(int *pfd)
00330 {
00331     if (*pfd != -1) {
00332         close(*pfd);
00333         *pfd = -1;
00334     }
00335 }
00336 
00337 /**
00338  * Close an open file descriptor, and grumble about it.
00339  */
00340 static void
00341 ccnd_close_fd(struct ccnd_handle *h, unsigned faceid, int *pfd)
00342 {
00343     int res;
00344     
00345     if (*pfd != -1) {
00346         int linger = 0;
00347         setsockopt(*pfd, SOL_SOCKET, SO_LINGER,
00348                    &linger, sizeof(linger));
00349         res = close(*pfd);
00350         if (res == -1)
00351             ccnd_msg(h, "close failed for face %u fd=%d: %s (errno=%d)",
00352                      faceid, *pfd, strerror(errno), errno);
00353         else
00354             ccnd_msg(h, "closing fd %d while finalizing face %u", *pfd, faceid);
00355         *pfd = -1;
00356     }
00357 }
00358 
00359 static void
00360 finalize_face(struct hashtb_enumerator *e)
00361 {
00362     struct ccnd_handle *h = hashtb_get_param(e->ht, NULL);
00363     struct face *face = e->data;
00364     unsigned i = face->faceid & MAXFACES;
00365     enum cq_delay_class c;
00366     int recycle = 0;
00367     int m;
00368     
00369     if (i < h->face_limit && h->faces_by_faceid[i] == face) {
00370         if ((face->flags & CCN_FACE_UNDECIDED) == 0)
00371             ccnd_face_status_change(h, face->faceid);
00372         if (e->ht == h->faces_by_fd)
00373             ccnd_close_fd(h, face->faceid, &face->recv_fd);
00374         h->faces_by_faceid[i] = NULL;
00375         if ((face->flags & CCN_FACE_UNDECIDED) != 0 &&
00376               face->faceid == ((h->face_rover - 1) | h->face_gen)) {
00377             /* stream connection with no ccn traffic - safe to reuse */
00378             recycle = 1;
00379             h->face_rover--;
00380         }
00381         for (c = 0; c < CCN_CQ_N; c++)
00382             content_queue_destroy(h, &(face->q[c]));
00383         ccnd_msg(h, "%s face id %u (slot %u)",
00384             recycle ? "recycling" : "releasing",
00385             face->faceid, face->faceid & MAXFACES);
00386         /* Don't free face->addr; storage is managed by hash table */
00387     }
00388     else if (face->faceid != CCN_NOFACEID)
00389         ccnd_msg(h, "orphaned face %u", face->faceid);
00390     for (m = 0; m < CCND_FACE_METER_N; m++)
00391         ccnd_meter_destroy(&face->meter[m]);
00392 }
00393 
00394 static struct content_entry *
00395 content_from_accession(struct ccnd_handle *h, ccn_accession_t accession)
00396 {
00397     struct content_entry *ans = NULL;
00398     if (accession < h->accession_base) {
00399         struct sparse_straggler_entry *entry;
00400         entry = hashtb_lookup(h->sparse_straggler_tab,
00401                               &accession, sizeof(accession));
00402         if (entry != NULL)
00403             ans = entry->content;
00404     }
00405     else if (accession < h->accession_base + h->content_by_accession_window) {
00406         ans = h->content_by_accession[accession - h->accession_base];
00407         if (ans != NULL && ans->accession != accession)
00408             ans = NULL;
00409     }
00410     return(ans);
00411 }
00412 
00413 static void
00414 cleanout_stragglers(struct ccnd_handle *h)
00415 {
00416     ccn_accession_t accession;
00417     struct hashtb_enumerator ee;
00418     struct hashtb_enumerator *e = &ee;
00419     struct sparse_straggler_entry *entry = NULL;
00420     struct content_entry **a = h->content_by_accession;
00421     unsigned n_direct;
00422     unsigned n_occupied;
00423     unsigned window;
00424     unsigned i;
00425     if (h->accession <= h->accession_base || a[0] == NULL)
00426         return;
00427     n_direct = h->accession - h->accession_base;
00428     if (n_direct < 1000)
00429         return;
00430     n_occupied = hashtb_n(h->content_tab) - hashtb_n(h->sparse_straggler_tab);
00431     if (n_occupied >= (n_direct / 8))
00432         return;
00433     /* The direct lookup table is too sparse, so sweep stragglers */
00434     hashtb_start(h->sparse_straggler_tab, e);
00435     window = h->content_by_accession_window;
00436     for (i = 0; i < window; i++) {
00437         if (a[i] != NULL) {
00438             if (n_occupied >= ((window - i) / 8))
00439                 break;
00440             accession = h->accession_base + i;
00441             hashtb_seek(e, &accession, sizeof(accession), 0);
00442             entry = e->data;
00443             if (entry != NULL && entry->content == NULL) {
00444                 entry->content = a[i];
00445                 a[i] = NULL;
00446                 n_occupied -= 1;
00447             }
00448         }
00449     }
00450     hashtb_end(e);
00451 }
00452 
00453 static int
00454 cleanout_empties(struct ccnd_handle *h)
00455 {
00456     unsigned i = 0;
00457     unsigned j = 0;
00458     struct content_entry **a = h->content_by_accession;
00459     unsigned window = h->content_by_accession_window;
00460     if (a == NULL)
00461         return(-1);
00462     cleanout_stragglers(h);
00463     while (i < window && a[i] == NULL)
00464         i++;
00465     if (i == 0)
00466         return(-1);
00467     h->accession_base += i;
00468     while (i < window)
00469         a[j++] = a[i++];
00470     while (j < window)
00471         a[j++] = NULL;
00472     return(0);
00473 }
00474 
00475 static void
00476 enroll_content(struct ccnd_handle *h, struct content_entry *content)
00477 {
00478     unsigned new_window;
00479     struct content_entry **new_array;
00480     struct content_entry **old_array;
00481     unsigned i = 0;
00482     unsigned j = 0;
00483     unsigned window = h->content_by_accession_window;
00484     if ((content->accession - h->accession_base) >= window &&
00485           cleanout_empties(h) < 0) {
00486         if (content->accession < h->accession_base)
00487             return;
00488         window = h->content_by_accession_window;
00489         old_array = h->content_by_accession;
00490         new_window = ((window + 20) * 3 / 2);
00491         if (new_window < window)
00492             return;
00493         new_array = calloc(new_window, sizeof(new_array[0]));
00494         if (new_array == NULL)
00495             return;
00496         while (i < h->content_by_accession_window && old_array[i] == NULL)
00497             i++;
00498         h->accession_base += i;
00499         h->content_by_accession = new_array;
00500         while (i < h->content_by_accession_window)
00501             new_array[j++] = old_array[i++];
00502         h->content_by_accession_window = new_window;
00503     free(old_array);
00504     }
00505     h->content_by_accession[content->accession - h->accession_base] = content;
00506 }
00507 
00508 static void
00509 finalize_content(struct hashtb_enumerator *content_enumerator)
00510 {
00511     struct ccnd_handle *h = hashtb_get_param(content_enumerator->ht, NULL);
00512     struct content_entry *entry = content_enumerator->data;
00513     unsigned i = entry->accession - h->accession_base;
00514     if (i < h->content_by_accession_window &&
00515           h->content_by_accession[i] == entry) {
00516         content_skiplist_remove(h, entry);
00517         h->content_by_accession[i] = NULL;
00518     }
00519     else {
00520         struct hashtb_enumerator ee;
00521         struct hashtb_enumerator *e = &ee;
00522         hashtb_start(h->sparse_straggler_tab, e);
00523         if (hashtb_seek(e, &entry->accession, sizeof(entry->accession), 0) ==
00524               HT_NEW_ENTRY) {
00525             ccnd_msg(h, "orphaned content %llu",
00526                      (unsigned long long)(entry->accession));
00527             hashtb_delete(e);
00528             hashtb_end(e);
00529             return;
00530         }
00531         content_skiplist_remove(h, entry);
00532         hashtb_delete(e);
00533         hashtb_end(e);
00534     }
00535     if (entry->comps != NULL) {
00536         free(entry->comps);
00537         entry->comps = NULL;
00538     }
00539 }
00540 
00541 static int
00542 content_skiplist_findbefore(struct ccnd_handle *h,
00543                             const unsigned char *key,
00544                             size_t keysize,
00545                             struct content_entry *wanted_old,
00546                             struct ccn_indexbuf **ans)
00547 {
00548     int i;
00549     int n = h->skiplinks->n;
00550     struct ccn_indexbuf *c;
00551     struct content_entry *content;
00552     int order;
00553     size_t start;
00554     size_t end;
00555     
00556     c = h->skiplinks;
00557     for (i = n - 1; i >= 0; i--) {
00558         for (;;) {
00559             if (c->buf[i] == 0)
00560                 break;
00561             content = content_from_accession(h, c->buf[i]);
00562             if (content == NULL)
00563                 abort();
00564             start = content->comps[0];
00565             end = content->comps[content->ncomps - 1];
00566             order = ccn_compare_names(content->key + start - 1, end - start + 2,
00567                                       key, keysize);
00568             if (order > 0)
00569                 break;
00570             if (order == 0 && (wanted_old == content || wanted_old == NULL))
00571                 break;
00572             if (content->skiplinks == NULL || i >= content->skiplinks->n)
00573                 abort();
00574             c = content->skiplinks;
00575         }
00576         ans[i] = c;
00577     }
00578     return(n);
00579 }
00580 
00581 #define CCN_SKIPLIST_MAX_DEPTH 30
00582 static void
00583 content_skiplist_insert(struct ccnd_handle *h, struct content_entry *content)
00584 {
00585     int d;
00586     int i;
00587     size_t start;
00588     size_t end;
00589     struct ccn_indexbuf *pred[CCN_SKIPLIST_MAX_DEPTH] = {NULL};
00590     if (content->skiplinks != NULL) abort();
00591     for (d = 1; d < CCN_SKIPLIST_MAX_DEPTH - 1; d++)
00592         if ((nrand48(h->seed) & 3) != 0) break;
00593     while (h->skiplinks->n < d)
00594         ccn_indexbuf_append_element(h->skiplinks, 0);
00595     start = content->comps[0];
00596     end = content->comps[content->ncomps - 1];
00597     i = content_skiplist_findbefore(h,
00598                                     content->key + start - 1,
00599                                     end - start + 2, NULL, pred);
00600     if (i < d)
00601         d = i; /* just in case */
00602     content->skiplinks = ccn_indexbuf_create();
00603     for (i = 0; i < d; i++) {
00604         ccn_indexbuf_append_element(content->skiplinks, pred[i]->buf[i]);
00605         pred[i]->buf[i] = content->accession;
00606     }
00607 }
00608 
00609 static void
00610 content_skiplist_remove(struct ccnd_handle *h, struct content_entry *content)
00611 {
00612     int i;
00613     int d;
00614     size_t start;
00615     size_t end;
00616     struct ccn_indexbuf *pred[CCN_SKIPLIST_MAX_DEPTH] = {NULL};
00617     if (content->skiplinks == NULL) abort();
00618     start = content->comps[0];
00619     end = content->comps[content->ncomps - 1];
00620     d = content_skiplist_findbefore(h,
00621                                     content->key + start - 1,
00622                                     end - start + 2, content, pred);
00623     if (d > content->skiplinks->n)
00624         d = content->skiplinks->n;
00625     for (i = 0; i < d; i++) {
00626         pred[i]->buf[i] = content->skiplinks->buf[i];
00627     }
00628     ccn_indexbuf_destroy(&content->skiplinks);
00629 }
00630 
00631 static struct content_entry *
00632 find_first_match_candidate(struct ccnd_handle *h,
00633                            const unsigned char *interest_msg,
00634                            const struct ccn_parsed_interest *pi)
00635 {
00636     int res;
00637     struct ccn_indexbuf *pred[CCN_SKIPLIST_MAX_DEPTH] = {NULL};
00638     size_t start = pi->offset[CCN_PI_B_Name];
00639     size_t end = pi->offset[CCN_PI_E_Name];
00640     struct ccn_charbuf *namebuf = NULL;
00641     if (pi->offset[CCN_PI_B_Exclude] < pi->offset[CCN_PI_E_Exclude]) {
00642         /* Check for <Exclude><Any/><Component>... fast case */
00643         struct ccn_buf_decoder decoder;
00644         struct ccn_buf_decoder *d;
00645         size_t ex1start;
00646         size_t ex1end;
00647         d = ccn_buf_decoder_start(&decoder,
00648                                   interest_msg + pi->offset[CCN_PI_B_Exclude],
00649                                   pi->offset[CCN_PI_E_Exclude] -
00650                                   pi->offset[CCN_PI_B_Exclude]);
00651         ccn_buf_advance(d);
00652         if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) {
00653             ccn_buf_advance(d);
00654             ccn_buf_check_close(d);
00655             if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00656                 ex1start = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
00657                 ccn_buf_advance_past_element(d);
00658                 ex1end = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
00659                 if (d->decoder.state >= 0) {
00660                     namebuf = ccn_charbuf_create();
00661                     ccn_charbuf_append(namebuf,
00662                                        interest_msg + start,
00663                                        end - start);
00664                     namebuf->length--;
00665                     ccn_charbuf_append(namebuf,
00666                                        interest_msg + ex1start,
00667                                        ex1end - ex1start);
00668                     ccn_charbuf_append_closer(namebuf);
00669                     if (h->debug & 8)
00670                         ccnd_debug_ccnb(h, __LINE__, "fastex", NULL,
00671                                         namebuf->buf, namebuf->length);
00672                 }
00673             }
00674         }
00675     }
00676     if (namebuf == NULL) {
00677         res = content_skiplist_findbefore(h, interest_msg + start, end - start,
00678                                           NULL, pred);
00679     }
00680     else {
00681         res = content_skiplist_findbefore(h, namebuf->buf, namebuf->length,
00682                                           NULL, pred);
00683         ccn_charbuf_destroy(&namebuf);
00684     }
00685     if (res == 0)
00686         return(NULL);
00687     return(content_from_accession(h, pred[0]->buf[0]));
00688 }
00689 
00690 static int
00691 content_matches_interest_prefix(struct ccnd_handle *h,
00692                                 struct content_entry *content,
00693                                 const unsigned char *interest_msg,
00694                                 struct ccn_indexbuf *comps,
00695                                 int prefix_comps)
00696 {
00697     size_t prefixlen;
00698     if (prefix_comps < 0 || prefix_comps >= comps->n)
00699         abort();
00700     /* First verify the prefix match. */
00701     if (content->ncomps < prefix_comps + 1)
00702             return(0);
00703     prefixlen = comps->buf[prefix_comps] - comps->buf[0];
00704     if (content->comps[prefix_comps] - content->comps[0] != prefixlen)
00705         return(0);
00706     if (0 != memcmp(content->key + content->comps[0],
00707                     interest_msg + comps->buf[0],
00708                     prefixlen))
00709         return(0);
00710     return(1);
00711 }
00712 
00713 static ccn_accession_t
00714 content_skiplist_next(struct ccnd_handle *h, struct content_entry *content)
00715 {
00716     if (content == NULL)
00717         return(0);
00718     if (content->skiplinks == NULL || content->skiplinks->n < 1)
00719         return(0);
00720     return(content->skiplinks->buf[0]);
00721 }
00722 
00723 static void
00724 consume(struct ccnd_handle *h, struct propagating_entry *pe)
00725 {
00726     struct face *face = NULL;
00727     ccn_indexbuf_destroy(&pe->outbound);
00728     if (pe->interest_msg != NULL) {
00729         free(pe->interest_msg);
00730         pe->interest_msg = NULL;
00731         face = face_from_faceid(h, pe->faceid);
00732         if (face != NULL)
00733             face->pending_interests -= 1;
00734     }
00735     if (pe->next != NULL) {
00736         pe->next->prev = pe->prev;
00737         pe->prev->next = pe->next;
00738         pe->next = pe->prev = NULL;
00739     }
00740     pe->usec = 0;
00741 }
00742 
00743 static void
00744 finalize_nameprefix(struct hashtb_enumerator *e)
00745 {
00746     struct ccnd_handle *h = hashtb_get_param(e->ht, NULL);
00747     struct nameprefix_entry *npe = e->data;
00748     struct propagating_entry *head = &npe->pe_head;
00749     if (head->next != NULL) {
00750         while (head->next != head)
00751             consume(h, head->next);
00752     }
00753     ccn_indexbuf_destroy(&npe->forward_to);
00754     ccn_indexbuf_destroy(&npe->tap);
00755     while (npe->forwarding != NULL) {
00756         struct ccn_forwarding *f = npe->forwarding;
00757         npe->forwarding = f->next;
00758         free(f);
00759     }
00760 }
00761 
00762 static void
00763 link_propagating_interest_to_nameprefix(struct ccnd_handle *h,
00764     struct propagating_entry *pe, struct nameprefix_entry *npe)
00765 {
00766     struct propagating_entry *head = &npe->pe_head;
00767     pe->next = head;
00768     pe->prev = head->prev;
00769     pe->prev->next = pe->next->prev = pe;
00770 }
00771 
00772 static void
00773 finalize_propagating(struct hashtb_enumerator *e)
00774 {
00775     struct ccnd_handle *h = hashtb_get_param(e->ht, NULL);
00776     consume(h, e->data);
00777 }
00778 
00779 static int
00780 create_local_listener(struct ccnd_handle *h, const char *sockname, int backlog)
00781 {
00782     int res;
00783     int savedmask;
00784     int sock;
00785     struct sockaddr_un a = { 0 };
00786     res = unlink(sockname);
00787     if (res == 0) {
00788         ccnd_msg(NULL, "unlinked old %s, please wait", sockname);
00789         sleep(9); /* give old ccnd a chance to exit */
00790     }
00791     if (!(res == 0 || errno == ENOENT))
00792         ccnd_msg(NULL, "failed to unlink %s", sockname);
00793     a.sun_family = AF_UNIX;
00794     strncpy(a.sun_path, sockname, sizeof(a.sun_path));
00795     sock = socket(AF_UNIX, SOCK_STREAM, 0);
00796     if (sock == -1)
00797         return(sock);
00798     savedmask = umask(0111); /* socket should be R/W by anybody */
00799     res = bind(sock, (struct sockaddr *)&a, sizeof(a));
00800     umask(savedmask);
00801     if (res == -1) {
00802         close(sock);
00803         return(-1);
00804     }
00805     unlink_at_exit(sockname);
00806     res = listen(sock, backlog);
00807     if (res == -1) {
00808         close(sock);
00809         return(-1);
00810     }
00811     record_connection(h, sock, (struct sockaddr *)&a, sizeof(a),
00812                       (CCN_FACE_LOCAL | CCN_FACE_PASSIVE));
00813     return(sock);
00814 }
00815 
00816 static int
00817 establish_min_recv_bufsize(struct ccnd_handle *h, int fd, int minsize)
00818 {
00819     int res;
00820     int rcvbuf;
00821     socklen_t rcvbuf_sz;
00822 
00823     rcvbuf_sz = sizeof(rcvbuf);
00824     res = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_sz);
00825     if (res == -1)
00826         return (res);
00827     if (rcvbuf < minsize) {
00828         rcvbuf = minsize;
00829         res = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
00830         if (res == -1)
00831             return(res);
00832     }
00833     ccnd_msg(h, "SO_RCVBUF for fd %d is %d", fd, rcvbuf);
00834     return(rcvbuf);
00835 }
00836 
00837 /**
00838  * Initialize the face flags based upon the addr information
00839  * and the provided explicit setflags.
00840  */
00841 static void
00842 init_face_flags(struct ccnd_handle *h, struct face *face, int setflags)
00843 {
00844     const struct sockaddr *addr = face->addr;
00845     const unsigned char *rawaddr = NULL;
00846     
00847     if (addr->sa_family == AF_INET6) {
00848         const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
00849         face->flags |= CCN_FACE_INET6;
00850 #ifdef IN6_IS_ADDR_LOOPBACK
00851         if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr))
00852             face->flags |= CCN_FACE_LOOPBACK;
00853 #endif
00854     }
00855     else if (addr->sa_family == AF_INET) {
00856         const struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
00857         rawaddr = (const unsigned char *)&addr4->sin_addr.s_addr;
00858         face->flags |= CCN_FACE_INET;
00859         if (rawaddr[0] == 127)
00860             face->flags |= CCN_FACE_LOOPBACK;
00861         else {
00862             /* If our side and the peer have the same address, consider it loopback */
00863             /* This is the situation inside of FreeBSD jail. */
00864             struct sockaddr_in myaddr;
00865             socklen_t myaddrlen = sizeof(myaddr);
00866             if (0 == getsockname(face->recv_fd, (struct sockaddr *)&myaddr, &myaddrlen)) {
00867                 if (addr4->sin_addr.s_addr == myaddr.sin_addr.s_addr)
00868                     face->flags |= CCN_FACE_LOOPBACK;
00869             }
00870         }
00871     }
00872     else if (addr->sa_family == AF_UNIX)
00873         face->flags |= (CCN_FACE_GG | CCN_FACE_LOCAL);
00874     face->flags |= setflags;
00875 }
00876 
00877 /**
00878  * Make a new face entered in the faces_by_fd table.
00879  */
00880 static struct face *
00881 record_connection(struct ccnd_handle *h, int fd,
00882                   struct sockaddr *who, socklen_t wholen,
00883                   int setflags)
00884 {
00885     struct hashtb_enumerator ee;
00886     struct hashtb_enumerator *e = &ee;
00887     int res;
00888     struct face *face = NULL;
00889     unsigned char *addrspace;
00890     
00891     res = fcntl(fd, F_SETFL, O_NONBLOCK);
00892     if (res == -1)
00893         ccnd_msg(h, "fcntl: %s", strerror(errno));
00894     hashtb_start(h->faces_by_fd, e);
00895     if (hashtb_seek(e, &fd, sizeof(fd), wholen) == HT_NEW_ENTRY) {
00896         face = e->data;
00897         face->recv_fd = fd;
00898         face->sendface = CCN_NOFACEID;
00899         face->addrlen = e->extsize;
00900         addrspace = ((unsigned char *)e->key) + e->keysize;
00901         face->addr = (struct sockaddr *)addrspace;
00902         memcpy(addrspace, who, e->extsize);
00903         init_face_flags(h, face, setflags);
00904         res = enroll_face(h, face);
00905         if (res == -1) {
00906             hashtb_delete(e);
00907             face = NULL;
00908         }
00909     }
00910     hashtb_end(e);
00911     return(face);
00912 }
00913 
00914 /**
00915  * Accept an incoming DGRAM_STREAM connection, creating a new face.
00916  * @returns fd of new socket, or -1 for an error.
00917  */
00918 static int
00919 accept_connection(struct ccnd_handle *h, int listener_fd)
00920 {
00921     struct sockaddr_storage who;
00922     socklen_t wholen = sizeof(who);
00923     int fd;
00924     struct face *face;
00925 
00926     fd = accept(listener_fd, (struct sockaddr *)&who, &wholen);
00927     if (fd == -1) {
00928         ccnd_msg(h, "accept: %s", strerror(errno));
00929         return(-1);
00930     }
00931     face = record_connection(h, fd,
00932                             (struct sockaddr *)&who, wholen,
00933                             CCN_FACE_UNDECIDED);
00934     if (face == NULL)
00935         close_fd(&fd);
00936     else
00937         ccnd_msg(h, "accepted client fd=%d id=%u", fd, face->faceid);
00938     return(fd);
00939 }
00940 
00941 /**
00942  * Make an outbound stream connection.
00943  */
00944 static struct face *
00945 make_connection(struct ccnd_handle *h,
00946                 struct sockaddr *who, socklen_t wholen,
00947                 int setflags)
00948 {
00949     struct hashtb_enumerator ee;
00950     struct hashtb_enumerator *e = &ee;
00951     int fd;
00952     int res;
00953     struct face *face;
00954     const int checkflags = CCN_FACE_LINK | CCN_FACE_DGRAM | CCN_FACE_LOCAL |
00955                            CCN_FACE_NOSEND | CCN_FACE_UNDECIDED;
00956     const int wantflags = 0;
00957     
00958     /* Check for an existing usable connection */
00959     for (hashtb_start(h->faces_by_fd, e); e->data != NULL; hashtb_next(e)) {
00960         face = e->data;
00961         if (face->addr != NULL && face->addrlen == wholen &&
00962             ((face->flags & checkflags) == wantflags) &&
00963             0 == memcmp(face->addr, who, wholen)) {
00964             hashtb_end(e);
00965             return(face);
00966         }
00967     }
00968     face = NULL;
00969     hashtb_end(e);
00970     /* No existing connection, try to make a new one. */
00971     fd = socket(who->sa_family, SOCK_STREAM, 0);
00972     if (fd == -1) {
00973         ccnd_msg(h, "socket: %s", strerror(errno));
00974         return(NULL);
00975     }
00976     res = fcntl(fd, F_SETFL, O_NONBLOCK);
00977     if (res == -1)
00978         ccnd_msg(h, "connect fcntl: %s", strerror(errno));
00979     setflags &= ~CCN_FACE_CONNECTING;
00980     res = connect(fd, who, wholen);
00981     if (res == -1 && errno == EINPROGRESS) {
00982         res = 0;
00983         setflags |= CCN_FACE_CONNECTING;
00984     }
00985     if (res == -1) {
00986         ccnd_msg(h, "connect failed: %s (errno = %d)", strerror(errno), errno);
00987         close(fd);
00988         return(NULL);
00989     }
00990     face = record_connection(h, fd, who, wholen, setflags);
00991     if (face == NULL) {
00992         close(fd);
00993         return(NULL);
00994     }
00995     if ((face->flags & CCN_FACE_CONNECTING) != 0) {
00996         ccnd_msg(h, "connecting to client fd=%d id=%u", fd, face->faceid);
00997         face->outbufindex = 0;
00998         face->outbuf = ccn_charbuf_create();
00999     }
01000     else
01001         ccnd_msg(h, "connected client fd=%d id=%u", fd, face->faceid);
01002     return(face);
01003 }
01004 
01005 static int
01006 ccnd_getboundsocket(void *dat, struct sockaddr *who, socklen_t wholen)
01007 {
01008     struct ccnd_handle *h = dat;
01009     struct hashtb_enumerator ee;
01010     struct hashtb_enumerator *e = &ee;
01011     int yes = 1;
01012     int res;
01013     int ans = -1;
01014     int wantflags = (CCN_FACE_DGRAM | CCN_FACE_PASSIVE);
01015     for (hashtb_start(h->faces_by_fd, e); e->data != NULL; hashtb_next(e)) {
01016         struct face *face = e->data;
01017         if ((face->flags & wantflags) == wantflags &&
01018               wholen == face->addrlen &&
01019               0 == memcmp(who, face->addr, wholen)) {
01020             ans = face->recv_fd;
01021             break;
01022         }
01023     }
01024     hashtb_end(e);
01025     if (ans != -1)
01026         return(ans);
01027     ans = socket(who->sa_family, SOCK_DGRAM, 0);
01028     if (ans == -1)
01029         return(ans);
01030     setsockopt(ans, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
01031     res = bind(ans, who, wholen);
01032     if (res == -1) {
01033         ccnd_msg(h, "bind failed: %s (errno = %d)", strerror(errno), errno);
01034         close(ans);
01035         return(-1);
01036     }
01037     record_connection(h, ans, who, wholen,
01038                       CCN_FACE_DGRAM | CCN_FACE_PASSIVE | CCN_FACE_NORECV);
01039     return(ans);
01040 }
01041 
01042 static unsigned
01043 faceid_from_fd(struct ccnd_handle *h, int fd)
01044 {
01045     struct face *face = hashtb_lookup(h->faces_by_fd, &fd, sizeof(fd));
01046     if (face != NULL)
01047         return(face->faceid);
01048     return(CCN_NOFACEID);
01049 }
01050 
01051 typedef void (*loggerproc)(void *, const char *, ...);
01052 static struct face *
01053 setup_multicast(struct ccnd_handle *h, struct ccn_face_instance *face_instance,
01054                 struct sockaddr *who, socklen_t wholen)
01055 {
01056     struct hashtb_enumerator ee;
01057     struct hashtb_enumerator *e = &ee;
01058     struct ccn_sockets socks = { -1, -1 };
01059     int res;
01060     struct face *face = NULL;
01061     const int checkflags = CCN_FACE_LINK | CCN_FACE_DGRAM | CCN_FACE_MCAST |
01062                            CCN_FACE_LOCAL | CCN_FACE_NOSEND;
01063     const int wantflags = CCN_FACE_DGRAM | CCN_FACE_MCAST;
01064 
01065     /* See if one is already active */
01066     // XXX - should also compare and record additional mcast props.
01067     for (hashtb_start(h->faces_by_fd, e); e->data != NULL; hashtb_next(e)) {
01068         face = e->data;
01069         if (face->addr != NULL && face->addrlen == wholen &&
01070             ((face->flags & checkflags) == wantflags) &&
01071             0 == memcmp(face->addr, who, wholen)) {
01072             hashtb_end(e);
01073             return(face);
01074         }
01075     }
01076     face = NULL;
01077     hashtb_end(e);
01078     
01079     res = ccn_setup_socket(&face_instance->descr,
01080                            (loggerproc)&ccnd_msg, (void *)h,
01081                            &ccnd_getboundsocket, (void *)h,
01082                            &socks);
01083     if (res < 0)
01084         return(NULL);
01085     establish_min_recv_bufsize(h, socks.recving, 128*1024);
01086     face = record_connection(h, socks.recving, who, wholen,
01087                              (CCN_FACE_MCAST | CCN_FACE_DGRAM));
01088     if (face == NULL) {
01089         close(socks.recving);
01090         if (socks.sending != socks.recving)
01091             close(socks.sending); // XXX - could be problematic, but record_connection is unlikely to fail for other than ENOMEM
01092         return(NULL);
01093     }
01094     face->sendface = faceid_from_fd(h, socks.sending);
01095     ccnd_msg(h, "multicast on fd=%d id=%u, sending on face %u",
01096              face->recv_fd, face->faceid, face->sendface);
01097     return(face);
01098 }
01099 
01100 static void
01101 shutdown_client_fd(struct ccnd_handle *h, int fd)
01102 {
01103     struct hashtb_enumerator ee;
01104     struct hashtb_enumerator *e = &ee;
01105     struct face *face = NULL;
01106     unsigned faceid = CCN_NOFACEID;
01107     hashtb_start(h->faces_by_fd, e);
01108     if (hashtb_seek(e, &fd, sizeof(fd), 0) == HT_OLD_ENTRY) {
01109         face = e->data;
01110         if (face->recv_fd != fd) abort();
01111         faceid = face->faceid;
01112         if (faceid == CCN_NOFACEID) {
01113             ccnd_msg(h, "error indication on fd %d ignored", fd);
01114             hashtb_end(e);
01115             return;
01116         }
01117         close(fd);
01118         face->recv_fd = -1;
01119         ccnd_msg(h, "shutdown client fd=%d id=%u", fd, faceid);
01120         ccn_charbuf_destroy(&face->inbuf);
01121         ccn_charbuf_destroy(&face->outbuf);
01122         face = NULL;
01123     }
01124     hashtb_delete(e);
01125     hashtb_end(e);
01126     check_comm_file(h);
01127     reap_needed(h, 250000);
01128 }
01129 
01130 static void
01131 send_content(struct ccnd_handle *h, struct face *face, struct content_entry *content)
01132 {
01133     int n, a, b, size;
01134     if ((face->flags & CCN_FACE_NOSEND) != 0) {
01135         // XXX - should count this.
01136         return;
01137     }
01138     size = content->size;
01139     if (h->debug & 4)
01140         ccnd_debug_ccnb(h, __LINE__, "content_to", face,
01141                         content->key, size);
01142     /* Excise the message-digest name component */
01143     n = content->ncomps;
01144     if (n < 2) abort();
01145     a = content->comps[n - 2];
01146     b = content->comps[n - 1];
01147     if (b - a != 36)
01148         abort(); /* strange digest length */
01149     stuff_and_send(h, face, content->key, a, content->key + b, size - b);
01150     ccnd_meter_bump(h, face->meter[FM_DATO], 1);
01151     h->content_items_sent += 1;
01152 }
01153 
01154 static enum cq_delay_class
01155 choose_content_delay_class(struct ccnd_handle *h, unsigned faceid, int content_flags)
01156 {
01157     struct face *face = face_from_faceid(h, faceid);
01158     if (face == NULL)
01159         return(CCN_CQ_ASAP); /* Going nowhere, get it over with */
01160     if ((face->flags & (CCN_FACE_LINK | CCN_FACE_MCAST)) != 0) /* udplink or such, delay more */
01161         return((content_flags & CCN_CONTENT_ENTRY_SLOWSEND) ? CCN_CQ_SLOW : CCN_CQ_NORMAL);
01162     if ((face->flags & CCN_FACE_DGRAM) != 0)
01163         return(CCN_CQ_NORMAL); /* udp, delay just a little */
01164     if ((face->flags & (CCN_FACE_GG | CCN_FACE_LOCAL)) != 0)
01165         return(CCN_CQ_ASAP); /* localhost, answer quickly */
01166     return(CCN_CQ_NORMAL); /* default */
01167 }
01168 
01169 static unsigned
01170 randomize_content_delay(struct ccnd_handle *h, struct content_queue *q)
01171 {
01172     unsigned usec;
01173     
01174     usec = q->min_usec + q->rand_usec;
01175     if (usec < 2)
01176         return(1);
01177     if (usec <= 20 || q->rand_usec < 2) // XXX - what is a good value for this?
01178         return(usec); /* small value, don't bother to randomize */
01179     usec = q->min_usec + (nrand48(h->seed) % q->rand_usec);
01180     if (usec < 2)
01181         return(1);
01182     return(usec);
01183 }
01184 
01185 static int
01186 content_sender(struct ccn_schedule *sched,
01187     void *clienth,
01188     struct ccn_scheduled_event *ev,
01189     int flags)
01190 {
01191     int i, j;
01192     int delay;
01193     int nsec;
01194     int burst_nsec;
01195     int burst_max;
01196     struct ccnd_handle *h = clienth;
01197     struct content_entry *content = NULL;
01198     unsigned faceid = ev->evint;
01199     struct face *face = NULL;
01200     struct content_queue *q = ev->evdata;
01201     (void)sched;
01202     
01203     if ((flags & CCN_SCHEDULE_CANCEL) != 0)
01204         goto Bail;
01205     face = face_from_faceid(h, faceid);
01206     if (face == NULL)
01207         goto Bail;
01208     if (q->send_queue == NULL)
01209         goto Bail;
01210     if ((face->flags & CCN_FACE_NOSEND) != 0)
01211         goto Bail;
01212     /* Send the content at the head of the queue */
01213     if (q->ready > q->send_queue->n ||
01214         (q->ready == 0 && q->nrun >= 12 && q->nrun < 120))
01215         q->ready = q->send_queue->n;
01216     nsec = 0;
01217     burst_nsec = q->burst_nsec;
01218     burst_max = 2;
01219     if (q->ready < burst_max)
01220         burst_max = q->ready;
01221     if (burst_max == 0)
01222         q->nrun = 0;
01223     for (i = 0; i < burst_max && nsec < 1000000; i++) {
01224         content = content_from_accession(h, q->send_queue->buf[i]);
01225         if (content == NULL)
01226             q->nrun = 0;
01227         else {
01228             send_content(h, face, content);
01229             /* face may have vanished, bail out if it did */
01230             if (face_from_faceid(h, faceid) == NULL)
01231                 goto Bail;
01232             nsec += burst_nsec * (unsigned)((content->size + 1023) / 1024);
01233             q->nrun++;
01234         }
01235     }
01236     if (q->ready < i) abort();
01237     q->ready -= i;
01238     /* Update queue */
01239     for (j = 0; i < q->send_queue->n; i++, j++)
01240         q->send_queue->buf[j] = q->send_queue->buf[i];
01241     q->send_queue->n = j;
01242     /* Do a poll before going on to allow others to preempt send. */
01243     delay = (nsec + 499) / 1000 + 1;
01244     if (q->ready > 0) {
01245         if (h->debug & 8)
01246             ccnd_msg(h, "face %u ready %u delay %i nrun %u",
01247                      faceid, q->ready, delay, q->nrun, face->surplus);
01248         return(delay);
01249     }
01250     q->ready = j;
01251     if (q->nrun >= 12 && q->nrun < 120) {
01252         /* We seem to be a preferred provider, forgo the randomized delay */
01253         if (j == 0)
01254             delay += burst_nsec / 50;
01255         if (h->debug & 8)
01256             ccnd_msg(h, "face %u ready %u delay %i nrun %u surplus %u",
01257                     (unsigned)ev->evint, q->ready, delay, q->nrun, face->surplus);
01258         return(delay);
01259     }
01260     /* Determine when to run again */
01261     for (i = 0; i < q->send_queue->n; i++) {
01262         content = content_from_accession(h, q->send_queue->buf[i]);
01263         if (content != NULL) {
01264             q->nrun = 0;
01265             delay = randomize_content_delay(h, q);
01266             if (h->debug & 8)
01267                 ccnd_msg(h, "face %u queued %u delay %i",
01268                          (unsigned)ev->evint, q->ready, delay);
01269             return(delay);
01270         }
01271     }
01272     q->send_queue->n = q->ready = 0;
01273 Bail:
01274     q->sender = NULL;
01275     return(0);
01276 }
01277 
01278 static int
01279 face_send_queue_insert(struct ccnd_handle *h,
01280                        struct face *face, struct content_entry *content)
01281 {
01282     int ans;
01283     int delay;
01284     enum cq_delay_class c;
01285     enum cq_delay_class k;
01286     struct content_queue *q;
01287     if (face == NULL || content == NULL || (face->flags & CCN_FACE_NOSEND) != 0)
01288         return(-1);
01289     c = choose_content_delay_class(h, face->faceid, content->flags);
01290     if (face->q[c] == NULL)
01291         face->q[c] = content_queue_create(h, face, c);
01292     q = face->q[c];
01293     if (q == NULL)
01294         return(-1);
01295     /* Check the other queues first, it might be in one of them */
01296     for (k = 0; k < CCN_CQ_N; k++) {
01297         if (k != c && face->q[k] != NULL) {
01298             ans = ccn_indexbuf_member(face->q[k]->send_queue, content->accession);
01299             if (ans >= 0) {
01300                 if (h->debug & 8)
01301                     ccnd_debug_ccnb(h, __LINE__, "content_otherq", face,
01302                                     content->key, content->size);
01303                 return(ans);
01304             }
01305         }
01306     }
01307     ans = ccn_indexbuf_set_insert(q->send_queue, content->accession);
01308     if (q->sender == NULL) {
01309         delay = randomize_content_delay(h, q);
01310         q->ready = q->send_queue->n;
01311         q->sender = ccn_schedule_event(h->sched, delay,
01312                                        content_sender, q, face->faceid);
01313         if (h->debug & 8)
01314             ccnd_msg(h, "face %u q %d delay %d usec", face->faceid, c, delay);
01315     }
01316     return (ans);
01317 }
01318 
01319 /**
01320  * If the pe interest is slated to be sent to the given faceid,
01321  * promote the faceid to the front of the list, preserving the order
01322  * of the others.
01323  * @returns -1 if not found, or pe->sent if successful.
01324  */
01325 static int
01326 promote_outbound(struct propagating_entry *pe, unsigned faceid)
01327 {
01328     struct ccn_indexbuf *ob = pe->outbound;
01329     int lb = pe->sent;
01330     int i;
01331     if (ob == NULL || ob->n <= lb || lb < 0)
01332         return(-1);
01333     for (i = ob->n - 1; i >= lb; i--)
01334         if (ob->buf[i] == faceid)
01335             break;
01336     if (i < lb)
01337         return(-1);
01338     for (; i > lb; i--)
01339         ob->buf[i] = ob->buf[i-1];
01340     ob->buf[lb] = faceid;
01341     return(lb);
01342 }
01343 
01344 /**
01345  * Consume matching interests
01346  * given a nameprefix_entry and a piece of content.
01347  *
01348  * If face is not NULL, pay attention only to interests from that face.
01349  * It is allowed to pass NULL for pc, but if you have a (valid) one it
01350  * will avoid a re-parse.
01351  * @returns number of matches found.
01352  */
01353 static int
01354 consume_matching_interests(struct ccnd_handle *h,
01355                            struct nameprefix_entry *npe,
01356                            struct content_entry *content,
01357                            struct ccn_parsed_ContentObject *pc,
01358                            struct face *face)
01359 {
01360     int matches = 0;
01361     struct propagating_entry *head;
01362     struct propagating_entry *next;
01363     struct propagating_entry *p;
01364     const unsigned char *content_msg;
01365     size_t content_size;
01366     struct face *f;
01367     
01368     head = &npe->pe_head;
01369     content_msg = content->key;
01370     content_size = content->size;
01371     f = face;
01372     for (p = head->next; p != head; p = next) {
01373         next = p->next;
01374         if (p->interest_msg != NULL &&
01375             ((face == NULL && (f = face_from_faceid(h, p->faceid)) != NULL) ||
01376              (face != NULL && p->faceid == face->faceid))) {
01377             if (ccn_content_matches_interest(content_msg, content_size, 0, pc,
01378                                              p->interest_msg, p->size, NULL)) {
01379                 face_send_queue_insert(h, f, content);
01380                 if (h->debug & (32 | 8))
01381                     ccnd_debug_ccnb(h, __LINE__, "consume", f,
01382                                     p->interest_msg, p->size);
01383                 matches += 1;
01384                 consume(h, p);
01385             }
01386         }
01387     }
01388     return(matches);
01389 }
01390 
01391 static void
01392 adjust_npe_predicted_response(struct ccnd_handle *h,
01393                               struct nameprefix_entry *npe, int up)
01394 {
01395     unsigned t = npe->usec;
01396     if (up)
01397         t = t + (t >> 3);
01398     else
01399         t = t - (t >> 7);
01400     if (t < 127)
01401         t = 127;
01402     else if (t > 1000000)
01403         t = 1000000;
01404     npe->usec = t;
01405 }
01406 
01407 static void
01408 adjust_predicted_response(struct ccnd_handle *h,
01409                           struct propagating_entry *pe, int up)
01410 {
01411     struct nameprefix_entry *npe;
01412         
01413     npe = nameprefix_for_pe(h, pe);
01414     if (npe == NULL)
01415         return;
01416     adjust_npe_predicted_response(h, npe, up);
01417     if (npe->parent != NULL)
01418         adjust_npe_predicted_response(h, npe->parent, up);
01419 }
01420 
01421 /**
01422  * Keep a little history about where matching content comes from.
01423  */
01424 static void
01425 note_content_from(struct ccnd_handle *h,
01426                   struct nameprefix_entry *npe,
01427                   unsigned from_faceid,
01428                   int prefix_comps)
01429 {
01430     if (npe->src == from_faceid)
01431         adjust_npe_predicted_response(h, npe, 0);
01432     else if (npe->src == CCN_NOFACEID)
01433         npe->src = from_faceid;
01434     else {
01435         npe->osrc = npe->src;
01436         npe->src = from_faceid;
01437     }
01438     if (h->debug & 8)
01439         ccnd_msg(h, "sl.%d %u ci=%d osrc=%u src=%u usec=%d", __LINE__,
01440                  from_faceid, prefix_comps, npe->osrc, npe->src, npe->usec);
01441 }
01442 
01443 /**
01444  * Use the history to reorder the interest forwarding.
01445  *
01446  * @returns number of tap faces that are present.
01447  */
01448 static int
01449 reorder_outbound_using_history(struct ccnd_handle *h,
01450                                struct nameprefix_entry *npe,
01451                                struct propagating_entry *pe)
01452 {
01453     int ntap = 0;
01454     int i;
01455     
01456     if (npe->osrc != CCN_NOFACEID)
01457         promote_outbound(pe, npe->osrc);
01458     /* Process npe->src last so it will be tried first */
01459     if (npe->src != CCN_NOFACEID)
01460         promote_outbound(pe, npe->src);
01461     /* Tap are really first. */
01462     if (npe->tap != NULL) {
01463         ntap = npe->tap->n;
01464         for (i = 0; i < ntap; i++)
01465             promote_outbound(pe, npe->tap->buf[i]);
01466     }
01467     return(ntap);
01468 }
01469 
01470 /**
01471  * Find and consume interests that match given content.
01472  *
01473  * Schedules the sending of the content.
01474  * If face is not NULL, pay attention only to interests from that face.
01475  * It is allowed to pass NULL for pc, but if you have a (valid) one it
01476  * will avoid a re-parse.
01477  * For new content, from_face is the source; for old content, from_face is NULL.
01478  * @returns number of matches, or -1 if the new content should be dropped.
01479  */
01480 static int
01481 match_interests(struct ccnd_handle *h, struct content_entry *content,
01482                            struct ccn_parsed_ContentObject *pc,
01483                            struct face *face, struct face *from_face)
01484 {
01485     int n_matched = 0;
01486     int new_matches;
01487     int ci;
01488     int cm = 0;
01489     unsigned c0 = content->comps[0];
01490     const unsigned char *key = content->key + c0;
01491     struct nameprefix_entry *npe = NULL;
01492     for (ci = content->ncomps - 1; ci >= 0; ci--) {
01493         int size = content->comps[ci] - c0;
01494         npe = hashtb_lookup(h->nameprefix_tab, key, size);
01495         if (npe != NULL)
01496             break;
01497     }
01498     for (; npe != NULL; npe = npe->parent, ci--) {
01499         if (npe->fgen != h->forward_to_gen)
01500             update_forward_to(h, npe);
01501         if (from_face != NULL && (npe->flags & CCN_FORW_LOCAL) != 0 &&
01502             (from_face->flags & CCN_FACE_GG) == 0)
01503             return(-1);
01504         new_matches = consume_matching_interests(h, npe, content, pc, face);
01505         if (from_face != NULL && (new_matches != 0 || ci + 1 == cm))
01506             note_content_from(h, npe, from_face->faceid, ci);
01507         if (new_matches != 0) {
01508             cm = ci; /* update stats for this prefix and one shorter */
01509             n_matched += new_matches;
01510         }
01511     }
01512     return(n_matched);
01513 }
01514 
01515 /**
01516  * Send a message in a PDU, possibly stuffing other interest messages into it.
01517  * The message may be in two pieces.
01518  */
01519 static void
01520 stuff_and_send(struct ccnd_handle *h, struct face *face,
01521                const unsigned char *data1, size_t size1,
01522                const unsigned char *data2, size_t size2) {
01523     struct ccn_charbuf *c = NULL;
01524     
01525     if ((face->flags & CCN_FACE_LINK) != 0) {
01526         c = charbuf_obtain(h);
01527         ccn_charbuf_reserve(c, size1 + size2 + 5 + 8);
01528         ccn_charbuf_append_tt(c, CCN_DTAG_CCNProtocolDataUnit, CCN_DTAG);
01529         ccn_charbuf_append(c, data1, size1);
01530                 if (size2 != 0)
01531             ccn_charbuf_append(c, data2, size2);
01532         ccn_stuff_interest(h, face, c);
01533         ccn_append_link_stuff(h, face, c);
01534         ccn_charbuf_append_closer(c);
01535     }
01536     else if (size2 != 0 || h->mtu > size1 + size2 ||
01537              (face->flags & (CCN_FACE_SEQOK | CCN_FACE_SEQPROBE)) != 0) {
01538         c = charbuf_obtain(h);
01539         ccn_charbuf_append(c, data1, size1);
01540                 if (size2 != 0)
01541             ccn_charbuf_append(c, data2, size2);
01542         ccn_stuff_interest(h, face, c);
01543         ccn_append_link_stuff(h, face, c);
01544     }
01545     else {
01546         /* avoid a copy in this case */
01547         ccnd_send(h, face, data1, size1);
01548         return;
01549     }
01550     ccnd_send(h, face, c->buf, c->length);
01551     charbuf_release(h, c);
01552     return;
01553 }
01554 
01555 /**
01556  * Append a link-check interest if appropriate.
01557  *
01558  * @returns the number of messages that were stuffed.
01559  */
01560 static int
01561 stuff_link_check(struct ccnd_handle *h,
01562                    struct face *face, struct ccn_charbuf *c)
01563 {
01564     int checkflags = CCN_FACE_DGRAM | CCN_FACE_MCAST | CCN_FACE_GG;
01565     int wantflags = CCN_FACE_DGRAM;
01566     struct ccn_charbuf *name = NULL;
01567     struct ccn_charbuf *ibuf = NULL;
01568     int res;
01569     int ans = 0;
01570     if (face->recvcount > 0)
01571         return(0);
01572     if ((face->flags & checkflags) != wantflags)
01573         return(0);
01574     name = ccn_charbuf_create();
01575     if (name == NULL) goto Bail;
01576     ccn_name_init(name);
01577     res = ccn_name_from_uri(name, CCNDID_NEIGHBOR_URI);
01578     if (res < 0) goto Bail;
01579     ibuf = ccn_charbuf_create();
01580     if (ibuf == NULL) goto Bail;
01581     ccn_charbuf_append_tt(ibuf, CCN_DTAG_Interest, CCN_DTAG);
01582     ccn_charbuf_append(ibuf, name->buf, name->length);
01583     ccnb_tagged_putf(ibuf, CCN_DTAG_Scope, "2");
01584     // XXX - ought to generate a nonce
01585     ccn_charbuf_append_closer(ibuf);
01586     ccn_charbuf_append(c, ibuf->buf, ibuf->length);
01587     ccnd_meter_bump(h, face->meter[FM_INTO], 1);
01588     h->interests_stuffed++;
01589     if (h->debug & 2)
01590         ccnd_debug_ccnb(h, __LINE__, "stuff_interest_to", face,
01591                         ibuf->buf, ibuf->length);
01592     ans = 1;
01593 Bail:
01594     ccn_charbuf_destroy(&ibuf);
01595     ccn_charbuf_destroy(&name);
01596     return(ans);
01597 }
01598 
01599 /**
01600  * Stuff a PDU with interest messages that will fit.
01601  *
01602  * Note by default stuffing does not happen due to the setting of h->mtu.
01603  * @returns the number of messages that were stuffed.
01604  */
01605 static int
01606 ccn_stuff_interest(struct ccnd_handle *h,
01607                    struct face *face, struct ccn_charbuf *c)
01608 {
01609     struct hashtb_enumerator ee;
01610     struct hashtb_enumerator *e = &ee;
01611     int n_stuffed = 0;
01612     int remaining_space;
01613     if (stuff_link_check(h, face, c) > 0)
01614         n_stuffed++;
01615     remaining_space = h->mtu - c->length;
01616     if (remaining_space < 20 || face == h->face0)
01617         return(0);
01618     for (hashtb_start(h->nameprefix_tab, e);
01619          remaining_space >= 20 && e->data != NULL; hashtb_next(e)) {
01620         struct nameprefix_entry *npe = e->data;
01621         struct propagating_entry *head = &npe->pe_head;
01622         struct propagating_entry *p;
01623         for (p = head->prev; p != head; p = p->prev) {
01624             if (p->outbound != NULL &&
01625                 p->outbound->n > p->sent &&
01626                 p->size <= remaining_space &&
01627                 p->interest_msg != NULL &&
01628                 ((p->flags & (CCN_PR_STUFFED1 | CCN_PR_WAIT1)) == 0) &&
01629                 ((p->flags & CCN_PR_UNSENT) == 0 ||
01630                  p->outbound->buf[p->sent] == face->faceid) &&
01631                 promote_outbound(p, face->faceid) != -1) {
01632                 remaining_space -= p->size;
01633                 if ((p->flags & CCN_PR_UNSENT) != 0) {
01634                     p->flags &= ~CCN_PR_UNSENT;
01635                     p->flags |= CCN_PR_STUFFED1;
01636                 }
01637                 p->sent++;
01638                 n_stuffed++;
01639                 ccn_charbuf_append(c, p->interest_msg, p->size);
01640                 ccnd_meter_bump(h, face->meter[FM_INTO], 1);
01641                 h->interests_stuffed++;
01642                 if (h->debug & 2)
01643                     ccnd_debug_ccnb(h, __LINE__, "stuff_interest_to", face,
01644                                     p->interest_msg, p->size);
01645                 /*
01646                  * Don't stuff multiple interests with same prefix
01647                  * to avoid subverting attempts at redundancy.
01648                  */
01649                 break;
01650             }
01651         }
01652     }
01653     hashtb_end(e);
01654     return(n_stuffed);
01655 }
01656 
01657 static void
01658 ccn_link_state_init(struct ccnd_handle *h, struct face *face)
01659 {
01660     int checkflags;
01661     int matchflags;
01662     
01663     matchflags = CCN_FACE_DGRAM;
01664     checkflags = matchflags | CCN_FACE_MCAST | CCN_FACE_GG | CCN_FACE_SEQOK | \
01665                  CCN_FACE_PASSIVE;
01666     if ((face->flags & checkflags) != matchflags)
01667         return;
01668     /* Send one sequence number to see if the other side wants to play. */
01669     face->pktseq = nrand48(h->seed);
01670     face->flags |= CCN_FACE_SEQPROBE;
01671 }
01672 
01673 static void
01674 ccn_append_link_stuff(struct ccnd_handle *h,
01675                       struct face *face,
01676                       struct ccn_charbuf *c)
01677 {
01678     if ((face->flags & (CCN_FACE_SEQOK | CCN_FACE_SEQPROBE)) == 0)
01679         return;
01680     ccn_charbuf_append_tt(c, CCN_DTAG_SequenceNumber, CCN_DTAG);
01681     ccn_charbuf_append_tt(c, 2, CCN_BLOB);
01682     ccn_charbuf_append_value(c, face->pktseq, 2);
01683     ccnb_element_end(c);
01684     if (0)
01685         ccnd_msg(h, "debug.%d pkt_to %u seq %u",
01686                  __LINE__, face->faceid, (unsigned)face->pktseq);
01687     face->pktseq++;
01688     face->flags &= ~CCN_FACE_SEQPROBE;
01689 }
01690 
01691 static int
01692 process_incoming_link_message(struct ccnd_handle *h,
01693                               struct face *face, enum ccn_dtag dtag,
01694                               unsigned char *msg, size_t size)
01695 {
01696     uintmax_t s;
01697     int checkflags;
01698     int matchflags;
01699     struct ccn_buf_decoder decoder;
01700     struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
01701 
01702     switch (dtag) {
01703         case CCN_DTAG_SequenceNumber:
01704             s = ccn_parse_required_tagged_binary_number(d, dtag, 1, 6);
01705             if (d->decoder.state < 0)
01706                 return(d->decoder.state);
01707             /*
01708              * If the other side is unicast and sends sequence numbers,
01709              * then it is OK for us to send numbers as well.
01710              */
01711             matchflags = CCN_FACE_DGRAM;
01712             checkflags = matchflags | CCN_FACE_MCAST | CCN_FACE_SEQOK;
01713             if ((face->flags & checkflags) == matchflags)
01714                 face->flags |= CCN_FACE_SEQOK;
01715             if (face->rrun == 0) {
01716                 face->rseq = s;
01717                 face->rrun = 1;
01718                 return(0);
01719             }
01720             if (s == face->rseq + 1) {
01721                 face->rseq = s;
01722                 if (face->rrun < 255)
01723                     face->rrun++;
01724                 return(0);
01725             }
01726             if (s > face->rseq && s - face->rseq < 255) {
01727                 ccnd_msg(h, "seq_gap %u %ju to %ju",
01728                          face->faceid, face->rseq, s);
01729                 face->rseq = s;
01730                 face->rrun = 1;
01731                 return(0);
01732             }
01733             if (s <= face->rseq) {
01734                 if (face->rseq - s < face->rrun) {
01735                     ccnd_msg(h, "seq_dup %u %ju", face->faceid, s);
01736                     return(0);
01737                 }
01738                 if (face->rseq - s < 255) {
01739                     /* Received out of order */
01740                     ccnd_msg(h, "seq_ooo %u %ju", face->faceid, s);
01741                     if (s == face->rseq - face->rrun) {
01742                         face->rrun++;
01743                         return(0);
01744                     }
01745                 }
01746             }
01747             face->rseq = s;
01748             face->rrun = 1;
01749             break;
01750         default:
01751             return(-1);
01752     }
01753     return(0);
01754 }
01755 
01756 /**
01757  * Checks for inactivity on datagram faces.
01758  * @returns number of faces that have gone away.
01759  */
01760 static int
01761 check_dgram_faces(struct ccnd_handle *h)
01762 {
01763     struct hashtb_enumerator ee;
01764     struct hashtb_enumerator *e = &ee;
01765     int count = 0;
01766     int checkflags = CCN_FACE_DGRAM;
01767     int wantflags = CCN_FACE_DGRAM;
01768     
01769     hashtb_start(h->dgram_faces, e);
01770     while (e->data != NULL) {
01771         struct face *face = e->data;
01772         if (face->addr != NULL && (face->flags & checkflags) == wantflags) {
01773             if (face->recvcount == 0) {
01774                 if ((face->flags & CCN_FACE_PERMANENT) == 0) {
01775                     count += 1;
01776                     hashtb_delete(e);
01777                     continue;
01778                 }
01779             }
01780             else if (face->recvcount == 1) {
01781                 face->recvcount = 0;
01782             }
01783             else {
01784                 face->recvcount = 1; /* go around twice */
01785             }
01786         }
01787         hashtb_next(e);
01788     }
01789     hashtb_end(e);
01790     return(count);
01791 }
01792 
01793 /**
01794  * Destroys the face identified by faceid.
01795  * @returns 0 for success, -1 for failure.
01796  */
01797 int
01798 ccnd_destroy_face(struct ccnd_handle *h, unsigned faceid)
01799 {
01800     struct hashtb_enumerator ee;
01801     struct hashtb_enumerator *e = &ee;
01802     struct face *face;
01803     int dgram_chk = CCN_FACE_DGRAM | CCN_FACE_MCAST;
01804     int dgram_want = CCN_FACE_DGRAM;
01805     
01806     face = face_from_faceid(h, faceid);
01807     if (face == NULL)
01808         return(-1);
01809     if ((face->flags & dgram_chk) == dgram_want) {
01810         hashtb_start(h->dgram_faces, e);
01811         hashtb_seek(e, face->addr, face->addrlen, 0);
01812         if (e->data == face)
01813             face = NULL;
01814         hashtb_delete(e);
01815         hashtb_end(e);
01816         if (face == NULL)
01817             return(0);
01818     }
01819     shutdown_client_fd(h, face->recv_fd);
01820     face = NULL;
01821     return(0);
01822 }
01823 
01824 /**
01825  * Remove expired faces from npe->forward_to
01826  */
01827 static void
01828 check_forward_to(struct ccnd_handle *h, struct nameprefix_entry *npe)
01829 {
01830     struct ccn_indexbuf *ft = npe->forward_to;
01831     int i;
01832     int j;
01833     if (ft == NULL)
01834         return;
01835     for (i = 0; i < ft->n; i++)
01836         if (face_from_faceid(h, ft->buf[i]) == NULL)
01837             break;
01838     for (j = i + 1; j < ft->n; j++)
01839         if (face_from_faceid(h, ft->buf[j]) != NULL)
01840             ft->buf[i++] = ft->buf[j];
01841     if (i == 0)
01842         ccn_indexbuf_destroy(&npe->forward_to);
01843     else if (i < ft->n)
01844         ft->n = i;
01845 }
01846 
01847 /**
01848  * Check for expired propagating interests.
01849  * @returns number that have gone away.
01850  */
01851 static int
01852 check_propagating(struct ccnd_handle *h)
01853 {
01854     int count = 0;
01855     struct hashtb_enumerator ee;
01856     struct hashtb_enumerator *e = &ee;
01857     struct propagating_entry *pe;
01858     
01859     hashtb_start(h->propagating_tab, e);
01860     for (pe = e->data; pe != NULL; pe = e->data) {
01861         if (pe->interest_msg == NULL) {
01862             if (pe->size == 0) {
01863                 count += 1;
01864                 hashtb_delete(e);
01865                 continue;
01866             }
01867             pe->size = (pe->size > 1); /* go around twice */
01868             /* XXX - could use a flag bit instead of hacking size */
01869         }
01870         hashtb_next(e);
01871     }
01872     hashtb_end(e);
01873     return(count);
01874 }
01875 
01876 /**
01877  * Ages src info and retires unused nameprefix entries.
01878  * @returns number that have gone away.
01879  */
01880 static int
01881 check_nameprefix_entries(struct ccnd_handle *h)
01882 {
01883     int count = 0;
01884     struct hashtb_enumerator ee;
01885     struct hashtb_enumerator *e = &ee;
01886     struct propagating_entry *head;
01887     struct nameprefix_entry *npe;    
01888     
01889     hashtb_start(h->nameprefix_tab, e);
01890     for (npe = e->data; npe != NULL; npe = e->data) {
01891         if (npe->forward_to != NULL)
01892             check_forward_to(h, npe);
01893         if (  npe->src == CCN_NOFACEID &&
01894               npe->children == 0 &&
01895               npe->forwarding == NULL) {
01896             head = &npe->pe_head;
01897             if (head == head->next) {
01898                 count += 1;
01899                 if (npe->parent != NULL) {
01900                     npe->parent->children--;
01901                     npe->parent = NULL;
01902                 }
01903                 hashtb_delete(e);
01904                 continue;
01905             }
01906         }
01907         npe->osrc = npe->src;
01908         npe->src = CCN_NOFACEID;
01909         hashtb_next(e);
01910     }
01911     hashtb_end(e);
01912     return(count);
01913 }
01914 
01915 static void
01916 check_comm_file(struct ccnd_handle *h)
01917 {
01918     if (!comm_file_ok()) {
01919         ccnd_msg(h, "stopping (%s gone)", unlink_this_at_exit);
01920         unlink_this_at_exit = NULL;
01921         h->running = 0;
01922     }
01923 }
01924 
01925 /**
01926  * Scheduled reap event for retiring expired structures.
01927  */
01928 static int
01929 reap(
01930     struct ccn_schedule *sched,
01931     void *clienth,
01932     struct ccn_scheduled_event *ev,
01933     int flags)
01934 {
01935     struct ccnd_handle *h = clienth;
01936     (void)(sched);
01937     (void)(ev);
01938     if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
01939         h->reaper = NULL;
01940         return(0);
01941     }
01942     check_dgram_faces(h);
01943     check_propagating(h);
01944     check_nameprefix_entries(h);
01945     check_comm_file(h);
01946     return(2 * CCN_INTEREST_LIFETIME_MICROSEC);
01947 }
01948 
01949 static void
01950 reap_needed(struct ccnd_handle *h, int init_delay_usec)
01951 {
01952     if (h->reaper == NULL)
01953         h->reaper = ccn_schedule_event(h->sched, init_delay_usec, reap, NULL, 0);
01954 }
01955 
01956 static int
01957 remove_content(struct ccnd_handle *h, struct content_entry *content)
01958 {
01959     struct hashtb_enumerator ee;
01960     struct hashtb_enumerator *e = &ee;
01961     int res;
01962     if (content == NULL)
01963         return(-1);
01964     hashtb_start(h->content_tab, e);
01965     res = hashtb_seek(e, content->key,
01966                       content->key_size, content->size - content->key_size);
01967     if (res != HT_OLD_ENTRY)
01968         abort();
01969     if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0)
01970         h->n_stale--;
01971     if (h->debug & 4)
01972         ccnd_debug_ccnb(h, __LINE__, "remove", NULL,
01973                         content->key, content->size);
01974     hashtb_delete(e);
01975     hashtb_end(e);
01976     return(0);
01977 }
01978 
01979 /**
01980  * Periodic content cleaning
01981  */
01982 static int
01983 clean_deamon(struct ccn_schedule *sched,
01984              void *clienth,
01985              struct ccn_scheduled_event *ev,
01986              int flags)
01987 {
01988     struct ccnd_handle *h = clienth;
01989     (void)(sched);
01990     (void)(ev);
01991     unsigned long n;
01992     ccn_accession_t limit;
01993     ccn_accession_t a;
01994     ccn_accession_t min_stale;
01995     int check_limit = 500;  /* Do not run for too long at once */
01996     struct content_entry *content = NULL;
01997     int res = 0;
01998     int ignore;
01999     int i;
02000     
02001     /*
02002      * If we ran into our processing limit (check_limit) last time,
02003      * ev->evint tells us where to restart.
02004      */
02005     
02006     if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
02007         h->clean = NULL;
02008         return(0);
02009     }
02010     n = hashtb_n(h->content_tab);
02011     if (n <= h->capacity)
02012         return(15000000);
02013     /* Toss unsolicited content first */
02014     for (i = 0; i < h->unsol->n; i++) {
02015         if (i == check_limit) {
02016             for (i = check_limit; i < h->unsol->n; i++)
02017                 h->unsol->buf[i-check_limit] = h->unsol->buf[i];
02018             h->unsol->n -= check_limit;
02019             return(500);
02020         }
02021         a = h->unsol->buf[i];
02022         content = content_from_accession(h, a);
02023         if (content != NULL &&
02024             (content->flags & CCN_CONTENT_ENTRY_PRECIOUS) == 0)
02025             remove_content(h, content);
02026     }
02027     n = hashtb_n(h->content_tab);
02028     h->unsol->n = 0;
02029     if (h->min_stale <= h->max_stale) {
02030         /* clean out stale content next */
02031         limit = h->max_stale;
02032         if (limit > h->accession)
02033             limit = h->accession;
02034         min_stale = ~0;
02035         a = ev->evint;
02036         if (a <= h->min_stale || a > h->max_stale)
02037             a = h->min_stale;
02038         else
02039             min_stale = h->min_stale;
02040         for (; a <= limit && n > h->capacity; a++) {
02041             if (check_limit-- <= 0) {
02042                 ev->evint = a;
02043                 break;
02044             }
02045             content = content_from_accession(h, a);
02046             if (content != NULL &&
02047                   (content->flags & CCN_CONTENT_ENTRY_STALE) != 0) {
02048                 res = remove_content(h, content);
02049                 if (res < 0) {
02050                     if (a < min_stale)
02051                         min_stale = a;
02052                 }
02053                 else {
02054                     content = NULL;
02055                     n -= 1;
02056                 }
02057             }
02058         }
02059         if (min_stale < a)
02060             h->min_stale = min_stale;
02061         else if (a > limit) {
02062             h->min_stale = ~0;
02063             h->max_stale = 0;
02064         }
02065         else
02066             h->min_stale = a;
02067         if (check_limit <= 0)
02068             return(5000);
02069     }
02070     else {
02071         /* Make oldish content stale, for cleanup on next round */
02072         limit = h->accession;
02073         ignore = CCN_CONTENT_ENTRY_STALE | CCN_CONTENT_ENTRY_PRECIOUS;
02074         for (a = h->accession_base; a <= limit && n > h->capacity; a++) {
02075             content = content_from_accession(h, a);
02076             if (content != NULL && (content->flags & ignore) == 0) {
02077                 mark_stale(h, content);
02078                 n--;
02079             }
02080         }
02081         ev->evint = 0;
02082         return(1000000);
02083     }
02084     ev->evint = 0;
02085     return(15000000);
02086 }
02087 
02088 static void
02089 clean_needed(struct ccnd_handle *h)
02090 {
02091     if (h->clean == NULL)
02092         h->clean = ccn_schedule_event(h->sched, 1000000, clean_deamon, NULL, 0);
02093 }
02094 
02095 /**
02096  * Age out the old forwarding table entries
02097  */
02098 static int
02099 age_forwarding(struct ccn_schedule *sched,
02100              void *clienth,
02101              struct ccn_scheduled_event *ev,
02102              int flags)
02103 {
02104     struct ccnd_handle *h = clienth;
02105     struct hashtb_enumerator ee;
02106     struct hashtb_enumerator *e = &ee;
02107     struct ccn_forwarding *f;
02108     struct ccn_forwarding *next;
02109     struct ccn_forwarding **p;
02110     struct nameprefix_entry *npe;
02111     
02112     if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
02113         h->age_forwarding = NULL;
02114         return(0);
02115     }
02116     hashtb_start(h->nameprefix_tab, e);
02117     for (npe = e->data; npe != NULL; npe = e->data) {
02118         p = &npe->forwarding;
02119         for (f = npe->forwarding; f != NULL; f = next) {
02120             next = f->next;
02121             if ((f->flags & CCN_FORW_REFRESHED) == 0 ||
02122                   face_from_faceid(h, f->faceid) == NULL) {
02123                 if (h->debug & 2) {
02124                     struct face *face = face_from_faceid(h, f->faceid);
02125                     if (face != NULL) {
02126                         struct ccn_charbuf *prefix = ccn_charbuf_create();
02127                         ccn_name_init(prefix);
02128                         ccn_name_append_components(prefix, e->key, 0, e->keysize);
02129                         ccnd_debug_ccnb(h, __LINE__, "prefix_expiry", face,
02130                                 prefix->buf,
02131                                 prefix->length);
02132                         ccn_charbuf_destroy(&prefix);
02133                     }
02134                 }
02135                 *p = next;
02136                 free(f);
02137                 f = NULL;
02138                 continue;
02139             }
02140             f->expires -= CCN_FWU_SECS;
02141             if (f->expires <= 0)
02142                 f->flags &= ~CCN_FORW_REFRESHED;
02143             p = &(f->next);
02144         }
02145         hashtb_next(e);
02146     }
02147     hashtb_end(e);
02148     h->forward_to_gen += 1;
02149     return(CCN_FWU_SECS*1000000);
02150 }
02151 
02152 static void
02153 age_forwarding_needed(struct ccnd_handle *h)
02154 {
02155     if (h->age_forwarding == NULL)
02156         h->age_forwarding = ccn_schedule_event(h->sched,
02157                                                CCN_FWU_SECS*1000000,
02158                                                age_forwarding,
02159                                                NULL, 0);
02160 }
02161 
02162 static struct ccn_forwarding *
02163 seek_forwarding(struct ccnd_handle *h,
02164                 struct nameprefix_entry *npe, unsigned faceid)
02165 {
02166     struct ccn_forwarding *f;
02167     
02168     for (f = npe->forwarding; f != NULL; f = f->next)
02169         if (f->faceid == faceid)
02170             return(f);
02171     f = calloc(1, sizeof(*f));
02172     if (f != NULL) {
02173         f->faceid = faceid;
02174         f->flags = (CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE);
02175         f->expires = 0x7FFFFFFF;
02176         f->next = npe->forwarding;
02177         npe->forwarding = f;
02178     }
02179     return(f);
02180 }
02181 
02182 /**
02183  * Register or update a prefix in the forwarding table (FIB).
02184  *
02185  * @param h is the ccnd handle.
02186  * @param msg is a ccnb-encoded message containing the name prefix somewhere.
02187  * @param comps contains the delimiting offsets for the name components in msg.
02188  * @param ncomps is the number of relevant components.
02189  * @param faceid indicates which face to forward to.
02190  * @param flags are the forwarding entry flags (CCN_FORW_...), -1 for defaults.
02191  * @param expires tells the remaining lifetime, in seconds.
02192  * @returns -1 for error, or new flags upon success; the private flag
02193  *        CCN_FORW_REFRESHED indicates a previously existing entry.
02194  */
02195 static int
02196 ccnd_reg_prefix(struct ccnd_handle *h,
02197                 const unsigned char *msg,
02198                 struct ccn_indexbuf *comps,
02199                 int ncomps,
02200                 unsigned faceid,
02201                 int flags,
02202                 int expires)
02203 {
02204     struct hashtb_enumerator ee;
02205     struct hashtb_enumerator *e = &ee;
02206     struct ccn_forwarding *f = NULL;
02207     struct nameprefix_entry *npe = NULL;
02208     int res;
02209     struct face *face = NULL;
02210     
02211     if (flags >= 0 &&
02212         (flags & CCN_FORW_PUBMASK) != flags)
02213         return(-1);
02214     face = face_from_faceid(h, faceid);
02215     if (face == NULL)
02216         return(-1);
02217     /* This is a bit hacky, but it gives us a way to set CCN_FACE_DC */
02218     if (flags >= 0 && (flags & CCN_FORW_LAST) != 0)
02219         face->flags |= CCN_FACE_DC;
02220     hashtb_start(h->nameprefix_tab, e);
02221     res = nameprefix_seek(h, e, msg, comps, ncomps);
02222     if (res >= 0) {
02223         res = (res == HT_OLD_ENTRY) ? CCN_FORW_REFRESHED : 0;
02224         npe = e->data;
02225         f = seek_forwarding(h, npe, faceid);
02226         if (f != NULL) {
02227             h->forward_to_gen += 1; // XXX - too conservative, should check changes
02228             f->expires = expires;
02229             if (flags < 0)
02230                 flags = f->flags & CCN_FORW_PUBMASK;
02231             f->flags = (CCN_FORW_REFRESHED | flags);
02232             res |= flags;
02233             if (h->debug & (2 | 4)) {
02234                 struct ccn_charbuf *prefix = ccn_charbuf_create();
02235                 struct ccn_charbuf *debugtag = ccn_charbuf_create();
02236                 ccn_charbuf_putf(debugtag, "prefix,ff=%s%x",
02237                                  flags > 9 ? "0x" : "", flags);
02238                 if (f->expires < (1 << 30))
02239                     ccn_charbuf_putf(debugtag, ",sec=%d", expires);
02240                 ccn_name_init(prefix);
02241                 ccn_name_append_components(prefix, msg,
02242                                            comps->buf[0], comps->buf[ncomps]);
02243                 ccnd_debug_ccnb(h, __LINE__,
02244                                 ccn_charbuf_as_string(debugtag),
02245                                 face,
02246                                 prefix->buf,
02247                                 prefix->length);
02248                 ccn_charbuf_destroy(&prefix);
02249                 ccn_charbuf_destroy(&debugtag);
02250             }
02251         }
02252         else
02253             res = -1;
02254     }
02255     hashtb_end(e);
02256     return(res);
02257 }
02258 
02259 /**
02260  * Register a prefix, expressed in the form of a URI.
02261  * @returns negative value for error, or new face flags for success.
02262  */
02263 int
02264 ccnd_reg_uri(struct ccnd_handle *h,
02265              const char *uri,
02266              unsigned faceid,
02267              int flags,
02268              int expires)
02269 {
02270     struct ccn_charbuf *name;
02271     struct ccn_buf_decoder decoder;
02272     struct ccn_buf_decoder *d;
02273     struct ccn_indexbuf *comps;
02274     int res;
02275     
02276     name = ccn_charbuf_create();
02277     ccn_name_init(name);
02278     res = ccn_name_from_uri(name, uri);
02279     if (res < 0)
02280         goto Bail;
02281     comps = ccn_indexbuf_create();
02282     d = ccn_buf_decoder_start(&decoder, name->buf, name->length);
02283     res = ccn_parse_Name(d, comps);
02284     if (res < 0)
02285         goto Bail;
02286     res = ccnd_reg_prefix(h, name->buf, comps, comps->n - 1,
02287                           faceid, flags, expires);
02288 Bail:
02289     ccn_charbuf_destroy(&name);
02290     ccn_indexbuf_destroy(&comps);
02291     return(res);
02292 }
02293 
02294 /**
02295  * Register prefixes, expressed in the form of a list of URIs.
02296  * The URIs in the charbuf are each terminated by nul.
02297  */
02298 void
02299 ccnd_reg_uri_list(struct ccnd_handle *h,
02300              struct ccn_charbuf *uris,
02301              unsigned faceid,
02302              int flags,
02303              int expires)
02304 {
02305     size_t i;
02306     const char *s;
02307     s = ccn_charbuf_as_string(uris);
02308     for (i = 0; i + 1 < uris->length; i += strlen(s + i) + 1)
02309         ccnd_reg_uri(h, s + i, faceid, flags, expires);
02310 }
02311 
02312 /**
02313  * Called when a face is first created, and (perhaps) a second time in the case
02314  * that a face transitions from the undecided state.
02315  */
02316 static void
02317 register_new_face(struct ccnd_handle *h, struct face *face)
02318 {
02319     if (face->faceid != 0 && (face->flags & (CCN_FACE_UNDECIDED | CCN_FACE_PASSIVE)) == 0) {
02320         ccnd_face_status_change(h, face->faceid);
02321         if (h->flood && h->autoreg != NULL && (face->flags & CCN_FACE_GG) == 0)
02322             ccnd_reg_uri_list(h, h->autoreg, face->faceid,
02323                               CCN_FORW_CAPTURE_OK | CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE,
02324                               0x7FFFFFFF);
02325         ccn_link_state_init(h, face);
02326     }
02327 }
02328 
02329 /**
02330  * Replaces contents of reply_body with a ccnb-encoded StatusResponse.
02331  *
02332  * @returns CCN_CONTENT_NACK, or -1 in case of error.
02333  */
02334 static int
02335 ccnd_nack(struct ccnd_handle *h, struct ccn_charbuf *reply_body,
02336           int errcode, const char *errtext)
02337 {
02338     int res;
02339     reply_body->length = 0;
02340     res = ccn_encode_StatusResponse(reply_body, errcode, errtext);
02341     if (res == 0)
02342         res = CCN_CONTENT_NACK;
02343     return(res);
02344 }
02345 
02346 /**
02347  * Check that indicated ccndid matches ours.
02348  *
02349  * @returns 0 if OK, or CCN_CONTENT_NACK if not.
02350  */
02351 static int
02352 check_ccndid(struct ccnd_handle *h,
02353              const void *p, size_t sz, struct ccn_charbuf *reply_body)
02354 {
02355     if (sz != sizeof(h->ccnd_id) || memcmp(p, h->ccnd_id, sz) != 0)
02356         return(ccnd_nack(h, reply_body, 531, "missing or incorrect ccndid"));
02357     return(0);
02358 }
02359 
02360 static int
02361 check_face_instance_ccndid(struct ccnd_handle *h,
02362     struct ccn_face_instance *f, struct ccn_charbuf *reply_body)
02363 {
02364     return(check_ccndid(h, f->ccnd_id, f->ccnd_id_size, reply_body));
02365 }
02366 
02367 static int
02368 check_forwarding_entry_ccndid(struct ccnd_handle *h,
02369     struct ccn_forwarding_entry *f, struct ccn_charbuf *reply_body)
02370 {
02371     return(check_ccndid(h, f->ccnd_id, f->ccnd_id_size, reply_body));
02372 }
02373 
02374 /**
02375  * Process a newface request for the ccnd internal client.
02376  *
02377  * @param h is the ccnd handle
02378  * @param msg points to a ccnd-encoded ContentObject containing a
02379  *         FaceInstance in its Content.
02380  * @param size is its size in bytes
02381  * @param reply_body is a buffer to hold the Content of the reply, as a
02382  *         FaceInstance including faceid
02383  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02384  *         set the response type to NACK.
02385  *
02386  * Is is permitted for the face to already exist.
02387  * A newly created face will have no registered prefixes, and so will not
02388  * receive any traffic.
02389  */
02390 int
02391 ccnd_req_newface(struct ccnd_handle *h,
02392                  const unsigned char *msg, size_t size,
02393                  struct ccn_charbuf *reply_body)
02394 {
02395     struct ccn_parsed_ContentObject pco = {0};
02396     int res;
02397     const unsigned char *req;
02398     size_t req_size;
02399     struct ccn_face_instance *face_instance = NULL;
02400     struct addrinfo hints = {0};
02401     struct addrinfo *addrinfo = NULL;
02402     int fd = -1;
02403     int mcast;
02404     struct face *face = NULL;
02405     struct face *reqface = NULL;
02406     struct face *newface = NULL;
02407     int save;
02408     int nackallowed = 0;
02409 
02410     save = h->flood;
02411     h->flood = 0; /* never auto-register for these */
02412     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02413     if (res < 0)
02414         goto Finish;
02415     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02416     if (res < 0)
02417         goto Finish;
02418     res = -1;
02419     face_instance = ccn_face_instance_parse(req, req_size);
02420     if (face_instance == NULL || face_instance->action == NULL)
02421         goto Finish;
02422     if (strcmp(face_instance->action, "newface") != 0)
02423         goto Finish;
02424     /* consider the source ... */
02425     reqface = face_from_faceid(h, h->interest_faceid);
02426     if (reqface == NULL ||
02427         (reqface->flags & (CCN_FACE_LOOPBACK | CCN_FACE_LOCAL)) == 0)
02428         goto Finish;
02429     nackallowed = 1;
02430     res = check_face_instance_ccndid(h, face_instance, reply_body);
02431     if (res != 0)
02432         goto Finish;
02433     if (face_instance->descr.ipproto != IPPROTO_UDP &&
02434         face_instance->descr.ipproto != IPPROTO_TCP) {
02435         res = ccnd_nack(h, reply_body, 504, "parameter error");
02436         goto Finish;
02437     }
02438     if (face_instance->descr.address == NULL) {
02439         res = ccnd_nack(h, reply_body, 504, "parameter error");
02440         goto Finish;
02441     }
02442     if (face_instance->descr.port == NULL) {
02443         res = ccnd_nack(h, reply_body, 504, "parameter error");
02444         goto Finish;
02445     }
02446     if ((reqface->flags & CCN_FACE_GG) == 0) {
02447         res = ccnd_nack(h, reply_body, 430, "not authorized");
02448         goto Finish;
02449     }
02450     hints.ai_flags |= AI_NUMERICHOST;
02451     hints.ai_protocol = face_instance->descr.ipproto;
02452     hints.ai_socktype = (hints.ai_protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
02453     res = getaddrinfo(face_instance->descr.address,
02454                       face_instance->descr.port,
02455                       &hints,
02456                       &addrinfo);
02457     if (res != 0 || (h->debug & 128) != 0)
02458         ccnd_msg(h, "ccnd_req_newface from %u: getaddrinfo(%s, %s, ...) returned %d",
02459                  h->interest_faceid,
02460                  face_instance->descr.address,
02461                  face_instance->descr.port,
02462                  res);
02463     if (res != 0 || addrinfo == NULL) {
02464         res = ccnd_nack(h, reply_body, 501, "syntax error in address");
02465         goto Finish;
02466     }
02467     if (addrinfo->ai_next != NULL)
02468         ccnd_msg(h, "ccnd_req_newface: (addrinfo->ai_next != NULL) ? ?");
02469     if (face_instance->descr.ipproto == IPPROTO_UDP) {
02470         fd = -1;
02471         mcast = 0;
02472         if (addrinfo->ai_family == AF_INET) {
02473             face = face_from_faceid(h, h->ipv4_faceid);
02474             mcast = IN_MULTICAST(ntohl(((struct sockaddr_in *)(addrinfo->ai_addr))->sin_addr.s_addr));
02475         }
02476         else if (addrinfo->ai_family == AF_INET6) {
02477             face = face_from_faceid(h, h->ipv6_faceid);
02478             mcast = IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_addr);
02479         }
02480         if (mcast)
02481             face = setup_multicast(h, face_instance,
02482                                    addrinfo->ai_addr,
02483                                    addrinfo->ai_addrlen);
02484         if (face == NULL) {
02485             res = ccnd_nack(h, reply_body, 453, "could not setup multicast");
02486             goto Finish;
02487         }
02488         newface = get_dgram_source(h, face,
02489                                    addrinfo->ai_addr,
02490                                    addrinfo->ai_addrlen,
02491                                    0);
02492     }
02493     else if (addrinfo->ai_socktype == SOCK_STREAM) {
02494         newface = make_connection(h,
02495                                   addrinfo->ai_addr,
02496                                   addrinfo->ai_addrlen,
02497                                   0);
02498     }
02499     if (newface != NULL) {
02500         newface->flags |= CCN_FACE_PERMANENT;
02501         face_instance->action = NULL;
02502         face_instance->ccnd_id = h->ccnd_id;
02503         face_instance->ccnd_id_size = sizeof(h->ccnd_id);
02504         face_instance->faceid = newface->faceid;
02505         face_instance->lifetime = 0x7FFFFFFF;
02506         /*
02507          * A short lifetime is a clue to the client that
02508          * the connection has not been completed.
02509          */
02510         if ((newface->flags & CCN_FACE_CONNECTING) != 0)
02511             face_instance->lifetime = 1;
02512         res = ccnb_append_face_instance(reply_body, face_instance);
02513         if (res > 0)
02514             res = 0;
02515     }
02516     else
02517         res = ccnd_nack(h, reply_body, 450, "could not create face");
02518 Finish:
02519     h->flood = save; /* restore saved flood flag */
02520     ccn_face_instance_destroy(&face_instance);
02521     if (addrinfo != NULL)
02522         freeaddrinfo(addrinfo);
02523     return((nackallowed || res <= 0) ? res : -1);
02524 }
02525 
02526 /**
02527  * @brief Process a destroyface request for the ccnd internal client.
02528  * @param h is the ccnd handle
02529  * @param msg points to a ccnd-encoded ContentObject containing a FaceInstance
02530             in its Content.
02531  * @param size is its size in bytes
02532  * @param reply_body is a buffer to hold the Content of the reply, as a
02533  *         FaceInstance including faceid
02534  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02535  *         set the response type to NACK.
02536  *
02537  * Is is an error if the face does not exist.
02538  */
02539 int
02540 ccnd_req_destroyface(struct ccnd_handle *h,
02541                      const unsigned char *msg, size_t size,
02542                      struct ccn_charbuf *reply_body)
02543 {
02544     struct ccn_parsed_ContentObject pco = {0};
02545     int res;
02546     int at = 0;
02547     const unsigned char *req;
02548     size_t req_size;
02549     struct ccn_face_instance *face_instance = NULL;
02550     struct face *reqface = NULL;
02551     int nackallowed = 0;
02552 
02553     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02554     if (res < 0) { at = __LINE__; goto Finish; }
02555     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02556     if (res < 0) { at = __LINE__; goto Finish; }
02557     res = -1;
02558     face_instance = ccn_face_instance_parse(req, req_size);
02559     if (face_instance == NULL) { at = __LINE__; goto Finish; }
02560     if (face_instance->action == NULL) { at = __LINE__; goto Finish; }
02561     /* consider the source ... */
02562     reqface = face_from_faceid(h, h->interest_faceid);
02563     if (reqface == NULL) { at = __LINE__; goto Finish; }
02564     if ((reqface->flags & CCN_FACE_GG) == 0) { at = __LINE__; goto Finish; }
02565     nackallowed = 1;
02566     if (strcmp(face_instance->action, "destroyface") != 0)
02567         { at = __LINE__; goto Finish; }
02568     res = check_face_instance_ccndid(h, face_instance, reply_body);
02569     if (res != 0)
02570         { at = __LINE__; goto Finish; }
02571     if (face_instance->faceid == 0) { at = __LINE__; goto Finish; }
02572     res = ccnd_destroy_face(h, face_instance->faceid);
02573     if (res < 0) { at = __LINE__; goto Finish; }
02574     face_instance->action = NULL;
02575     face_instance->ccnd_id = h->ccnd_id;
02576     face_instance->ccnd_id_size = sizeof(h->ccnd_id);
02577     face_instance->lifetime = 0;
02578     res = ccnb_append_face_instance(reply_body, face_instance);
02579     if (res < 0) {
02580         at = __LINE__;
02581     }
02582 Finish:
02583     if (at != 0) {
02584         ccnd_msg(h, "ccnd_req_destroyface failed (line %d, res %d)", at, res);
02585         if (reqface == NULL || (reqface->flags & CCN_FACE_GG) == 0)
02586             res = -1;
02587         else
02588             res = ccnd_nack(h, reply_body, 450, "could not destroy face");
02589     }
02590     ccn_face_instance_destroy(&face_instance);
02591     return((nackallowed || res <= 0) ? res : -1);
02592 }
02593 
02594 /**
02595  * Worker bee for two very similar public functions.
02596  */
02597 static int
02598 ccnd_req_prefix_or_self_reg(struct ccnd_handle *h,
02599                             const unsigned char *msg, size_t size, int selfreg,
02600                             struct ccn_charbuf *reply_body)
02601 {
02602     struct ccn_parsed_ContentObject pco = {0};
02603     int res;
02604     const unsigned char *req;
02605     size_t req_size;
02606     struct ccn_forwarding_entry *forwarding_entry = NULL;
02607     struct face *face = NULL;
02608     struct face *reqface = NULL;
02609     struct ccn_indexbuf *comps = NULL;
02610     int nackallowed = 0;
02611 
02612     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02613     if (res < 0)
02614         goto Finish;
02615     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02616     if (res < 0)
02617         goto Finish;
02618     res = -1;
02619     forwarding_entry = ccn_forwarding_entry_parse(req, req_size);
02620     if (forwarding_entry == NULL || forwarding_entry->action == NULL)
02621         goto Finish;
02622     /* consider the source ... */
02623     reqface = face_from_faceid(h, h->interest_faceid);
02624     if (reqface == NULL)
02625         goto Finish;
02626     if ((reqface->flags & (CCN_FACE_GG | CCN_FACE_REGOK)) == 0)
02627         goto Finish;
02628     nackallowed = 1;
02629     if (selfreg) {
02630         if (strcmp(forwarding_entry->action, "selfreg") != 0)
02631             goto Finish;
02632         if (forwarding_entry->faceid == CCN_NOFACEID)
02633             forwarding_entry->faceid = h->interest_faceid;
02634         else if (forwarding_entry->faceid != h->interest_faceid)
02635             goto Finish;
02636     }
02637     else {
02638         if (strcmp(forwarding_entry->action, "prefixreg") != 0)
02639         goto Finish;
02640     }
02641     if (forwarding_entry->name_prefix == NULL)
02642         goto Finish;
02643     if (forwarding_entry->ccnd_id_size == sizeof(h->ccnd_id)) {
02644         if (memcmp(forwarding_entry->ccnd_id,
02645                    h->ccnd_id, sizeof(h->ccnd_id)) != 0)
02646             goto Finish;
02647     }
02648     else if (forwarding_entry->ccnd_id_size != 0)
02649         goto Finish;
02650     face = face_from_faceid(h, forwarding_entry->faceid);
02651     if (face == NULL)
02652         goto Finish;
02653     if (forwarding_entry->lifetime < 0)
02654         forwarding_entry->lifetime = 60;
02655     else if (forwarding_entry->lifetime > 3600 &&
02656              forwarding_entry->lifetime < (1 << 30))
02657         forwarding_entry->lifetime = 300;
02658     comps = ccn_indexbuf_create();
02659     res = ccn_name_split(forwarding_entry->name_prefix, comps);
02660     if (res < 0)
02661         goto Finish;
02662     res = ccnd_reg_prefix(h,
02663                           forwarding_entry->name_prefix->buf, comps, res,
02664                           face->faceid,
02665                           forwarding_entry->flags,
02666                           forwarding_entry->lifetime);
02667     if (res < 0)
02668         goto Finish;
02669     forwarding_entry->flags = res;
02670     forwarding_entry->action = NULL;
02671     forwarding_entry->ccnd_id = h->ccnd_id;
02672     forwarding_entry->ccnd_id_size = sizeof(h->ccnd_id);
02673     res = ccnb_append_forwarding_entry(reply_body, forwarding_entry);
02674     if (res > 0)
02675         res = 0;
02676 Finish:
02677     ccn_forwarding_entry_destroy(&forwarding_entry);
02678     ccn_indexbuf_destroy(&comps);
02679     if (nackallowed && res < 0)
02680         res = ccnd_nack(h, reply_body, 450, "could not register prefix");
02681     return((nackallowed || res <= 0) ? res : -1);
02682 }
02683 
02684 /**
02685  * @brief Process a prefixreg request for the ccnd internal client.
02686  * @param h is the ccnd handle
02687  * @param msg points to a ccnd-encoded ContentObject containing a
02688  *          ForwardingEntry in its Content.
02689  * @param size is its size in bytes
02690  * @param reply_body is a buffer to hold the Content of the reply, as a
02691  *         FaceInstance including faceid
02692  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02693  *         set the response type to NACK.
02694  *
02695  */
02696 int
02697 ccnd_req_prefixreg(struct ccnd_handle *h,
02698                    const unsigned char *msg, size_t size,
02699                    struct ccn_charbuf *reply_body)
02700 {
02701     return(ccnd_req_prefix_or_self_reg(h, msg, size, 0, reply_body));
02702 }
02703 
02704 /**
02705  * @brief Process a selfreg request for the ccnd internal client.
02706  * @param h is the ccnd handle
02707  * @param msg points to a ccnd-encoded ContentObject containing a
02708  *          ForwardingEntry in its Content.
02709  * @param size is its size in bytes
02710  * @param reply_body is a buffer to hold the Content of the reply, as a
02711  *         ccnb-encoded ForwardingEntry
02712  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02713  *         set the response type to NACK.
02714  *
02715  */
02716 int
02717 ccnd_req_selfreg(struct ccnd_handle *h,
02718                  const unsigned char *msg, size_t size,
02719                  struct ccn_charbuf *reply_body)
02720 {
02721     return(ccnd_req_prefix_or_self_reg(h, msg, size, 1, reply_body));
02722 }
02723 
02724 /**
02725  * @brief Process an unreg request for the ccnd internal client.
02726  * @param h is the ccnd handle
02727  * @param msg points to a ccnd-encoded ContentObject containing a
02728  *          ForwardingEntry in its Content.
02729  * @param size is its size in bytes
02730  * @param reply_body is a buffer to hold the Content of the reply, as a
02731  *         ccnb-encoded ForwardingEntry
02732  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02733  *         set the response type to NACK.
02734  *
02735  */
02736 int
02737 ccnd_req_unreg(struct ccnd_handle *h,
02738                const unsigned char *msg, size_t size,
02739                struct ccn_charbuf *reply_body)
02740 {
02741     struct ccn_parsed_ContentObject pco = {0};
02742     int n_name_comp = 0;
02743     int res;
02744     const unsigned char *req;
02745     size_t req_size;
02746     size_t start;
02747     size_t stop;
02748     int found;
02749     struct ccn_forwarding_entry *forwarding_entry = NULL;
02750     struct face *face = NULL;
02751     struct face *reqface = NULL;
02752     struct ccn_indexbuf *comps = NULL;
02753     struct ccn_forwarding **p = NULL;
02754     struct ccn_forwarding *f = NULL;
02755     struct nameprefix_entry *npe = NULL;
02756     int nackallowed = 0;
02757     
02758     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02759     if (res < 0)
02760         goto Finish;        
02761     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02762     if (res < 0)
02763         goto Finish;
02764     res = -1;
02765     forwarding_entry = ccn_forwarding_entry_parse(req, req_size);
02766     /* consider the source ... */
02767     reqface = face_from_faceid(h, h->interest_faceid);
02768     if (reqface == NULL || (reqface->flags & CCN_FACE_GG) == 0)
02769         goto Finish;
02770     nackallowed = 1;
02771     if (forwarding_entry == NULL || forwarding_entry->action == NULL)
02772         goto Finish;
02773     if (strcmp(forwarding_entry->action, "unreg") != 0)
02774         goto Finish;
02775     if (forwarding_entry->faceid == CCN_NOFACEID)
02776         goto Finish;
02777     if (forwarding_entry->name_prefix == NULL)
02778         goto Finish;
02779     res = check_forwarding_entry_ccndid(h, forwarding_entry, reply_body);
02780     if (res != 0)
02781         goto Finish;
02782     res = -1;
02783     face = face_from_faceid(h, forwarding_entry->faceid);
02784     if (face == NULL)
02785         goto Finish;
02786     comps = ccn_indexbuf_create();
02787     n_name_comp = ccn_name_split(forwarding_entry->name_prefix, comps);
02788     if (n_name_comp < 0)
02789         goto Finish;
02790     if (n_name_comp + 1 > comps->n)
02791         goto Finish;
02792     start = comps->buf[0];
02793     stop = comps->buf[n_name_comp];
02794     npe = hashtb_lookup(h->nameprefix_tab,
02795                         forwarding_entry->name_prefix->buf + start,
02796                         stop - start);
02797     if (npe == NULL)
02798         goto Finish;
02799     found = 0;
02800     p = &npe->forwarding;
02801     for (f = npe->forwarding; f != NULL; f = f->next) {
02802         if (f->faceid == forwarding_entry->faceid) {
02803             found = 1;
02804             if (h->debug & (2 | 4))
02805                 ccnd_debug_ccnb(h, __LINE__, "prefix_unreg", face,
02806                                 forwarding_entry->name_prefix->buf,
02807                                 forwarding_entry->name_prefix->length);
02808             *p = f->next;
02809             free(f);
02810             f = NULL;
02811             h->forward_to_gen += 1;
02812             break;
02813         }
02814         p = &(f->next);
02815     }
02816     if (!found)
02817         goto Finish;    
02818     forwarding_entry->action = NULL;
02819     forwarding_entry->ccnd_id = h->ccnd_id;
02820     forwarding_entry->ccnd_id_size = sizeof(h->ccnd_id);
02821     res = ccnb_append_forwarding_entry(reply_body, forwarding_entry);
02822     if (res > 0)
02823         res = 0;
02824 Finish:
02825     ccn_forwarding_entry_destroy(&forwarding_entry);
02826     ccn_indexbuf_destroy(&comps);
02827     if (nackallowed && res < 0)
02828         res = ccnd_nack(h, reply_body, 450, "could not unregister prefix");
02829     return((nackallowed || res <= 0) ? res : -1);
02830 }
02831 
02832 /**
02833  * Recompute the contents of npe->forward_to and npe->flags
02834  * from forwarding lists of npe and all of its ancestors.
02835  */
02836 static void
02837 update_forward_to(struct ccnd_handle *h, struct nameprefix_entry *npe)
02838 {
02839     struct ccn_indexbuf *x = NULL;
02840     struct ccn_indexbuf *tap = NULL;
02841     struct ccn_forwarding *f = NULL;
02842     struct nameprefix_entry *p = NULL;
02843     unsigned tflags;
02844     unsigned wantflags;
02845     unsigned moreflags;
02846     unsigned lastfaceid;
02847     unsigned namespace_flags;
02848 
02849     x = npe->forward_to;
02850     if (x == NULL)
02851         npe->forward_to = x = ccn_indexbuf_create();
02852     else
02853         x->n = 0;
02854     wantflags = CCN_FORW_ACTIVE;
02855     lastfaceid = CCN_NOFACEID;
02856     namespace_flags = 0;
02857     for (p = npe; p != NULL; p = p->parent) {
02858         moreflags = CCN_FORW_CHILD_INHERIT;
02859         for (f = p->forwarding; f != NULL; f = f->next) {
02860             if (face_from_faceid(h, f->faceid) == NULL)
02861                 continue;
02862             /* The sense of this flag needs to be inverted for this test */
02863             tflags = f->flags ^ CCN_FORW_CAPTURE_OK;
02864             if ((tflags & wantflags) == wantflags) {
02865                 if (h->debug & 32)
02866                     ccnd_msg(h, "fwd.%d adding %u", __LINE__, f->faceid);
02867                 ccn_indexbuf_set_insert(x, f->faceid);
02868                 if ((f->flags & CCN_FORW_TAP) != 0) {
02869                     if (tap == NULL)
02870                         tap = ccn_indexbuf_create();
02871                     ccn_indexbuf_set_insert(tap, f->faceid);
02872                 }
02873                 if ((f->flags & CCN_FORW_LAST) != 0)
02874                     lastfaceid = f->faceid;
02875             }
02876             namespace_flags |= f->flags;
02877             if ((f->flags & CCN_FORW_CAPTURE) != 0)
02878                 moreflags |= CCN_FORW_CAPTURE_OK;
02879         }
02880         wantflags |= moreflags;
02881     }
02882     if (lastfaceid != CCN_NOFACEID)
02883         ccn_indexbuf_move_to_end(x, lastfaceid);
02884     npe->flags = namespace_flags;
02885     npe->fgen = h->forward_to_gen;
02886     if (x->n == 0)
02887         ccn_indexbuf_destroy(&npe->forward_to);
02888     ccn_indexbuf_destroy(&npe->tap);
02889     npe->tap = tap;
02890 }
02891 
02892 /**
02893  * This is where we consult the interest forwarding table.
02894  * @param h is the ccnd handle
02895  * @param from is the handle for the originating face (may be NULL).
02896  * @param msg points to the ccnb-encoded interest message
02897  * @param pi must be the parse information for msg
02898  * @param npe should be the result of the prefix lookup
02899  * @result Newly allocated set of outgoing faceids (never NULL)
02900  */
02901 static struct ccn_indexbuf *
02902 get_outbound_faces(struct ccnd_handle *h,
02903     struct face *from,
02904     unsigned char *msg,
02905     struct ccn_parsed_interest *pi,
02906     struct nameprefix_entry *npe)
02907 {
02908     int checkmask = 0;
02909     int wantmask = 0;
02910     struct ccn_indexbuf *x;
02911     struct face *face;
02912     int i;
02913     int n;
02914     unsigned faceid;
02915     
02916     while (npe->parent != NULL && npe->forwarding == NULL)
02917         npe = npe->parent;
02918     if (npe->fgen != h->forward_to_gen)
02919         update_forward_to(h, npe);
02920     x = ccn_indexbuf_create();
02921     if (pi->scope == 0 || npe->forward_to == NULL || npe->forward_to->n == 0)
02922         return(x);
02923     if ((npe->flags & CCN_FORW_LOCAL) != 0)
02924         checkmask = (from != NULL && (from->flags & CCN_FACE_GG) != 0) ? CCN_FACE_GG : (~0);
02925     else if (pi->scope == 1)
02926         checkmask = CCN_FACE_GG;
02927     else if (pi->scope == 2)
02928         checkmask = from ? (CCN_FACE_GG & ~(from->flags)) : ~0;
02929     wantmask = checkmask;
02930     if (wantmask == CCN_FACE_GG)
02931         checkmask |= CCN_FACE_DC;
02932     for (n = npe->forward_to->n, i = 0; i < n; i++) {
02933         faceid = npe->forward_to->buf[i];
02934         face = face_from_faceid(h, faceid);
02935         if (face != NULL && face != from &&
02936             ((face->flags & checkmask) == wantmask)) {
02937             if (h->debug & 32)
02938                 ccnd_msg(h, "outbound.%d adding %u", __LINE__, face->faceid);
02939             ccn_indexbuf_append_element(x, face->faceid);
02940         }
02941     }
02942     return(x);
02943 }
02944 
02945 static int
02946 pe_next_usec(struct ccnd_handle *h,
02947              struct propagating_entry *pe, int next_delay, int lineno)
02948 {
02949     if (next_delay > pe->usec)
02950         next_delay = pe->usec;
02951     pe->usec -= next_delay;
02952     if (h->debug & 32) {
02953         struct ccn_charbuf *c = ccn_charbuf_create();
02954         ccn_charbuf_putf(c, "%p.%dof%d,usec=%d+%d",
02955                          (void *)pe,
02956                          pe->sent,
02957                          pe->outbound ? pe->outbound->n : -1,
02958                          next_delay, pe->usec);
02959         if (pe->interest_msg != NULL) {
02960             ccnd_debug_ccnb(h, lineno, ccn_charbuf_as_string(c),
02961                             face_from_faceid(h, pe->faceid),
02962                             pe->interest_msg, pe->size);
02963         }
02964         ccn_charbuf_destroy(&c);
02965     }
02966     return(next_delay);
02967 }
02968 
02969 static void replan_propagation(struct ccnd_handle *, struct propagating_entry *);
02970 
02971 static int
02972 do_propagate(struct ccn_schedule *sched,
02973              void *clienth,
02974              struct ccn_scheduled_event *ev,
02975              int flags)
02976 {
02977     struct ccnd_handle *h = clienth;
02978     struct propagating_entry *pe = ev->evdata;
02979     (void)(sched);
02980     int next_delay = 1;
02981     int special_delay = 0;
02982     if (pe->interest_msg == NULL)
02983         return(0);
02984     if (flags & CCN_SCHEDULE_CANCEL) {
02985         consume(h, pe);
02986         return(0);
02987     }
02988     if ((pe->flags & CCN_PR_WAIT1) != 0) {
02989         pe->flags &= ~CCN_PR_WAIT1;
02990         adjust_predicted_response(h, pe, 1);
02991     }
02992     if (pe->usec <= 0) {
02993         if (h->debug & 2)
02994             ccnd_debug_ccnb(h, __LINE__, "interest_expiry",
02995                             face_from_faceid(h, pe->faceid),
02996                             pe->interest_msg, pe->size);
02997         consume(h, pe);
02998         reap_needed(h, 0);
02999         return(0);        
03000     }
03001     if ((pe->flags & CCN_PR_STUFFED1) != 0) {
03002         pe->flags &= ~CCN_PR_STUFFED1;
03003         pe->flags |= CCN_PR_WAIT1;
03004         next_delay = special_delay = ev->evint;
03005     }
03006     else if (pe->outbound != NULL && pe->sent < pe->outbound->n) {
03007         unsigned faceid = pe->outbound->buf[pe->sent];
03008         struct face *face = face_from_faceid(h, faceid);
03009         if (face != NULL && (face->flags & CCN_FACE_NOSEND) == 0) {
03010             if (h->debug & 2)
03011                 ccnd_debug_ccnb(h, __LINE__, "interest_to", face,
03012                                 pe->interest_msg, pe->size);
03013             pe->sent++;
03014             h->interests_sent += 1;
03015             h->interest_faceid = pe->faceid;
03016             next_delay = nrand48(h->seed) % 8192 + 500;
03017             if (((pe->flags & CCN_PR_TAP) != 0) &&
03018                   ccn_indexbuf_member(nameprefix_for_pe(h, pe)->tap, pe->faceid)) {
03019                 next_delay = special_delay = 1;
03020             }
03021             else if ((pe->flags & CCN_PR_UNSENT) != 0) {
03022                 pe->flags &= ~CCN_PR_UNSENT;
03023                 pe->flags |= CCN_PR_WAIT1;
03024                 next_delay = special_delay = ev->evint;
03025             }
03026             stuff_and_send(h, face, pe->interest_msg, pe->size, NULL, 0);
03027             ccnd_meter_bump(h, face->meter[FM_INTO], 1);
03028         }
03029         else
03030             ccn_indexbuf_remove_first_match(pe->outbound, faceid);
03031     }
03032     /* The internal client may have already consumed the interest */
03033     if (pe->outbound == NULL)
03034         next_delay = CCN_INTEREST_LIFETIME_MICROSEC;
03035     else if (pe->sent == pe->outbound->n) {
03036         if (pe->usec <= CCN_INTEREST_LIFETIME_MICROSEC / 4)
03037             next_delay = CCN_INTEREST_LIFETIME_MICROSEC;
03038         else if (special_delay == 0)
03039             next_delay = CCN_INTEREST_LIFETIME_MICROSEC / 16;
03040         if (pe->fgen != h->forward_to_gen)
03041             replan_propagation(h, pe);
03042     }
03043     else {
03044         unsigned faceid = pe->outbound->buf[pe->sent];
03045         struct face *face = face_from_faceid(h, faceid);
03046         /* Wait longer before sending interest to ccndc */
03047         if (face != NULL && (face->flags & CCN_FACE_DC) != 0)
03048             next_delay += 60000;
03049     }
03050     next_delay = pe_next_usec(h, pe, next_delay, __LINE__);
03051     return(next_delay);
03052 }
03053 
03054 /**
03055  * Adjust the outbound face list for a new Interest, based upon
03056  * existing similar interests.
03057  * @result besides possibly updating the outbound set, returns
03058  *         an extra delay time before propagation.  A negative return value
03059  *         indicates the interest should be dropped.
03060  */
03061 // XXX - rearrange to allow dummied-up "sent" entries.
03062 // XXX - subtle point - when similar interests are present in the PIT, and a new dest appears due to prefix registration, only one of the set should get sent to the new dest.
03063 static int
03064 adjust_outbound_for_existing_interests(struct ccnd_handle *h, struct face *face,
03065                                        unsigned char *msg,
03066                                        struct ccn_parsed_interest *pi,
03067                                        struct nameprefix_entry *npe,
03068                                        struct ccn_indexbuf *outbound)
03069 {
03070     struct propagating_entry *head = &npe->pe_head;
03071     struct propagating_entry *p;
03072     size_t presize = pi->offset[CCN_PI_B_Nonce];
03073     size_t postsize = pi->offset[CCN_PI_E] - pi->offset[CCN_PI_E_Nonce];
03074     size_t minsize = presize + postsize;
03075     unsigned char *post = msg + pi->offset[CCN_PI_E_Nonce];
03076     int k = 0;
03077     int max_redundant = 3; /* Allow this many dups from same face */
03078     int i;
03079     int n;
03080     struct face *otherface;
03081     int extra_delay = 0;
03082 
03083     if ((face->flags & (CCN_FACE_MCAST | CCN_FACE_LINK)) != 0)
03084         max_redundant = 0;
03085     if (outbound != NULL) {
03086         for (p = head->next; p != head && outbound->n > 0; p = p->next) {
03087             if (p->size > minsize &&
03088                 p->interest_msg != NULL &&
03089                 p->usec > 0 &&
03090                 0 == memcmp(msg, p->interest_msg, presize) &&
03091                 0 == memcmp(post, p->interest_msg + p->size - postsize, postsize)) {
03092                 /* Matches everything but the Nonce */
03093                 otherface = face_from_faceid(h, p->faceid);
03094                 if (otherface == NULL)
03095                     continue;
03096                 /*
03097                  * If scope is 2, we can't treat these as similar if
03098                  * they did not originate on the same host
03099                  */
03100                 if (pi->scope == 2 &&
03101                     ((otherface->flags ^ face->flags) & CCN_FACE_GG) != 0)
03102                     continue;
03103                 if (h->debug & 32)
03104                     ccnd_debug_ccnb(h, __LINE__, "similar_interest",
03105                                     face_from_faceid(h, p->faceid),
03106                                     p->interest_msg, p->size);
03107                 if (face->faceid == p->faceid) {
03108                     /*
03109                      * This is one we've already seen before from the same face,
03110                      * but dropping it unconditionally would lose resiliency
03111                      * against dropped packets. Thus allow a few of them.
03112                      * Add some delay, though.
03113                      * XXX c.f. bug #13 // XXX - old bugid
03114                      */
03115                     extra_delay += npe->usec + 20000;
03116                     if ((++k) < max_redundant)
03117                         continue;
03118                     outbound->n = 0;
03119                     return(-1);
03120                 }
03121                 /*
03122                  * The existing interest from another face will serve for us,
03123                  * but we still need to send this interest there or we
03124                  * could miss an answer from that direction. Note that
03125                  * interests from two other faces could conspire to cover
03126                  * this one completely as far as propagation is concerned,
03127                  * but it is still necessary to keep it around for the sake
03128                  * of returning content.
03129                  * This assumes a unicast link.  If there are multiple
03130                  * parties on this face (broadcast or multicast), we
03131                  * do not want to send right away, because it is highly likely
03132                  * that we've seen an interest that one of the other parties
03133                  * is going to answer, and we'll see the answer, too.
03134                  */
03135                 n = outbound->n;
03136                 outbound->n = 0;
03137                 for (i = 0; i < n; i++) {
03138                     if (p->faceid == outbound->buf[i]) {
03139                         outbound->buf[0] = p->faceid;
03140                         outbound->n = 1;
03141                         if ((otherface->flags & (CCN_FACE_MCAST | CCN_FACE_LINK)) != 0)
03142                             extra_delay += npe->usec + 10000;
03143                         break;
03144                     }
03145                 }
03146                 p->flags |= CCN_PR_EQV; /* Don't add new faces */
03147                 // XXX - How robust is setting of CCN_PR_EQV?
03148                 /*
03149                  * XXX - We would like to avoid having to keep this
03150                  * interest around if we get here with (outbound->n == 0).
03151                  * However, we still need to remember to send the content
03152                  * back to this face, and the data structures are not
03153                  * there right now to represent this.  c.f. #100321.
03154                  */
03155             }
03156         }
03157     }
03158     return(extra_delay);
03159 }
03160 
03161 static void
03162 ccnd_append_debug_nonce(struct ccnd_handle *h, struct face *face, struct ccn_charbuf *cb) {
03163         unsigned char s[12];
03164         int i;
03165         
03166         for (i = 0; i < 3; i++)
03167             s[i] = h->ccnd_id[i];
03168         s[i++] = h->logpid >> 8;
03169         s[i++] = h->logpid;
03170         s[i++] = face->faceid >> 8;
03171         s[i++] = face->faceid;
03172         s[i++] = h->sec;
03173         s[i++] = h->usec * 256 / 1000000;
03174         for (; i < sizeof(s); i++)
03175             s[i] = nrand48(h->seed);
03176         ccnb_append_tagged_blob(cb, CCN_DTAG_Nonce, s, i);
03177 }
03178 
03179 static void
03180 ccnd_append_plain_nonce(struct ccnd_handle *h, struct face *face, struct ccn_charbuf *cb) {
03181         int noncebytes = 6;
03182         unsigned char *s = NULL;
03183         int i;
03184         
03185         ccn_charbuf_append_tt(cb, CCN_DTAG_Nonce, CCN_DTAG);
03186         ccn_charbuf_append_tt(cb, noncebytes, CCN_BLOB);
03187         s = ccn_charbuf_reserve(cb, noncebytes);
03188         for (i = 0; i < noncebytes; i++)
03189             s[i] = nrand48(h->seed) >> i;
03190         cb->length += noncebytes;
03191         ccn_charbuf_append_closer(cb);
03192 }
03193 
03194 /**
03195  * Schedules the propagation of an Interest message.
03196  */
03197 static int
03198 propagate_interest(struct ccnd_handle *h,
03199                    struct face *face,
03200                    unsigned char *msg,
03201                    struct ccn_parsed_interest *pi,
03202                    struct nameprefix_entry *npe)
03203 {
03204     struct hashtb_enumerator ee;
03205     struct hashtb_enumerator *e = &ee;
03206     unsigned char *nonce;
03207     size_t noncesize;
03208     struct ccn_charbuf *cb = NULL;
03209     int res;
03210     struct propagating_entry *pe = NULL;
03211     unsigned char *msg_out = msg;
03212     size_t msg_out_size = pi->offset[CCN_PI_E];
03213     int usec;
03214     int ntap;
03215     int delaymask;
03216     int extra_delay = 0;
03217     struct ccn_indexbuf *outbound = NULL;
03218     intmax_t lifetime;
03219     
03220     lifetime = ccn_interest_lifetime(msg, pi);
03221     outbound = get_outbound_faces(h, face, msg, pi, npe);
03222     if (outbound->n != 0) {
03223         extra_delay = adjust_outbound_for_existing_interests(h, face, msg, pi, npe, outbound);
03224         if (extra_delay < 0) {
03225             /*
03226              * Completely subsumed by other interests.
03227              * We do not have to worry about generating a nonce if it
03228              * does not have one yet.
03229              */
03230             if (h->debug & 16)
03231                 ccnd_debug_ccnb(h, __LINE__, "interest_subsumed", face,
03232                                 msg_out, msg_out_size);
03233             h->interests_dropped += 1;
03234             ccn_indexbuf_destroy(&outbound);
03235             return(0);
03236         }
03237     }
03238     if (pi->offset[CCN_PI_B_Nonce] == pi->offset[CCN_PI_E_Nonce]) {
03239         /* This interest has no nonce; add one before going on */
03240         size_t nonce_start = 0;
03241         cb = charbuf_obtain(h);
03242         ccn_charbuf_append(cb, msg, pi->offset[CCN_PI_B_Nonce]);
03243         nonce_start = cb->length;
03244         (h->appnonce)(h, face, cb);
03245         noncesize = cb->length - nonce_start;
03246         ccn_charbuf_append(cb, msg + pi->offset[CCN_PI_B_OTHER],
03247                                pi->offset[CCN_PI_E] - pi->offset[CCN_PI_B_OTHER]);
03248         nonce = cb->buf + nonce_start;
03249         msg_out = cb->buf;
03250         msg_out_size = cb->length;
03251     }
03252     else {
03253         nonce = msg + pi->offset[CCN_PI_B_Nonce];
03254         noncesize = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce];
03255     }
03256     hashtb_start(h->propagating_tab, e);
03257     res = hashtb_seek(e, nonce, noncesize, 0);
03258     pe = e->data;
03259     if (pe != NULL && pe->interest_msg == NULL) {
03260         unsigned char *m;
03261         m = calloc(1, msg_out_size);
03262         if (m == NULL) {
03263             res = -1;
03264             pe = NULL;
03265             hashtb_delete(e);
03266         }
03267         else {
03268             memcpy(m, msg_out, msg_out_size);
03269             pe->interest_msg = m;
03270             pe->size = msg_out_size;
03271             pe->faceid = face->faceid;
03272             face->pending_interests += 1;
03273             if (lifetime < INT_MAX / (1000000 >> 6) * (4096 >> 6))
03274                 pe->usec = lifetime * (1000000 >> 6) / (4096 >> 6);
03275             else
03276                 pe->usec = INT_MAX;
03277             delaymask = 0xFFF;
03278             pe->sent = 0;            
03279             pe->outbound = outbound;
03280             pe->flags = 0;
03281             if (pi->scope == 0)
03282                 pe->flags |= CCN_PR_SCOPE0;
03283             else if (pi->scope == 1)
03284                 pe->flags |= CCN_PR_SCOPE1;
03285             else if (pi->scope == 2)
03286                 pe->flags |= CCN_PR_SCOPE2;
03287             pe->fgen = h->forward_to_gen;
03288             link_propagating_interest_to_nameprefix(h, pe, npe);
03289             ntap = reorder_outbound_using_history(h, npe, pe);
03290             if (outbound->n > ntap &&
03291                   outbound->buf[ntap] == npe->src &&
03292                   extra_delay == 0) {
03293                 pe->flags = CCN_PR_UNSENT;
03294                 delaymask = 0xFF;
03295             }
03296             outbound = NULL;
03297             res = 0;
03298             if (ntap > 0)
03299                 (usec = 1, pe->flags |= CCN_PR_TAP);
03300             else
03301                 usec = (nrand48(h->seed) & delaymask) + 1 + extra_delay;
03302             usec = pe_next_usec(h, pe, usec, __LINE__);
03303             ccn_schedule_event(h->sched, usec, do_propagate, pe, npe->usec);
03304         }
03305     }
03306     else {
03307         ccnd_msg(h, "Interesting - this shouldn't happen much - ccnd.c:%d", __LINE__);
03308         /* We must have duplicated an existing nonce, or ENOMEM. */
03309         res = -1;
03310     }
03311     hashtb_end(e);
03312     if (cb != NULL)
03313         charbuf_release(h, cb);
03314     ccn_indexbuf_destroy(&outbound);
03315     return(res);
03316 }
03317 
03318 static struct nameprefix_entry *
03319 nameprefix_for_pe(struct ccnd_handle *h, struct propagating_entry *pe)
03320 {
03321     struct nameprefix_entry *npe;
03322     struct propagating_entry *p;
03323     
03324     /* If any significant time is spent here, a direct link is possible, but costs space. */
03325     for (p = pe->next; p->faceid != CCN_NOFACEID; p = p->next)
03326         continue;
03327     npe = (void *)(((char *)p) - offsetof(struct nameprefix_entry, pe_head));
03328     return(npe);
03329 }
03330 
03331 static void
03332 replan_propagation(struct ccnd_handle *h, struct propagating_entry *pe)
03333 {
03334     struct nameprefix_entry *npe = NULL;
03335     struct ccn_indexbuf *x = pe->outbound;
03336     struct face *face = NULL;
03337     struct face *from = NULL;
03338     int i;
03339     int k;
03340     int n;
03341     unsigned faceid;
03342     unsigned checkmask = 0;
03343     unsigned wantmask = 0;
03344     
03345     pe->fgen = h->forward_to_gen;
03346     if ((pe->flags & (CCN_PR_SCOPE0 | CCN_PR_EQV)) != 0)
03347         return;
03348     from = face_from_faceid(h, pe->faceid);
03349     if (from == NULL)
03350         return;
03351     npe = nameprefix_for_pe(h, pe);
03352     while (npe->parent != NULL && npe->forwarding == NULL)
03353         npe = npe->parent;
03354     if (npe->fgen != h->forward_to_gen)
03355         update_forward_to(h, npe);
03356     if (npe->forward_to == NULL || npe->forward_to->n == 0)
03357         return;
03358     if ((pe->flags & CCN_PR_SCOPE1) != 0)
03359         checkmask = CCN_FACE_GG;
03360     if ((pe->flags & CCN_PR_SCOPE2) != 0)
03361         checkmask = CCN_FACE_GG & ~(from->flags);
03362     if ((npe->flags & CCN_FORW_LOCAL) != 0)
03363         checkmask = ((from->flags & CCN_FACE_GG) != 0) ? CCN_FACE_GG : (~0);
03364     wantmask = checkmask;
03365     if (wantmask == CCN_FACE_GG)
03366         checkmask |= CCN_FACE_DC;
03367     for (n = npe->forward_to->n, i = 0; i < n; i++) {
03368         faceid = npe->forward_to->buf[i];
03369         face = face_from_faceid(h, faceid);
03370         if (face != NULL && faceid != pe->faceid &&
03371             ((face->flags & checkmask) == wantmask)) {
03372             k = x->n;
03373             ccn_indexbuf_set_insert(x, faceid);
03374             if (x->n > k && (h->debug & 32) != 0)
03375                 ccnd_msg(h, "at %d adding %u", __LINE__, faceid);
03376         }
03377     }
03378     // XXX - should account for similar interests, history, etc.
03379 }
03380 
03381 /**
03382  * Checks whether this Interest message has been seen before by using
03383  * its Nonce, recording it in the process.  Also, if it has been
03384  * seen and the original is still propagating, remove the face that
03385  * the duplicate arrived on from the outbound set of the original.
03386  */
03387 static int
03388 is_duplicate_flooded(struct ccnd_handle *h, unsigned char *msg,
03389                      struct ccn_parsed_interest *pi, unsigned faceid)
03390 {
03391     struct hashtb_enumerator ee;
03392     struct hashtb_enumerator *e = &ee;
03393     struct propagating_entry *pe = NULL;
03394     int res;
03395     size_t nonce_start = pi->offset[CCN_PI_B_Nonce];
03396     size_t nonce_size = pi->offset[CCN_PI_E_Nonce] - nonce_start;
03397     if (nonce_size == 0)
03398         return(0);
03399     hashtb_start(h->propagating_tab, e);
03400     res = hashtb_seek(e, msg + nonce_start, nonce_size, 0);
03401     if (res == HT_OLD_ENTRY) {
03402         pe = e->data;
03403         if (promote_outbound(pe, faceid) != -1)
03404             pe->sent++;
03405     }
03406     hashtb_end(e);
03407     return(res == HT_OLD_ENTRY);
03408 }
03409 
03410 /**
03411  * Finds the longest matching nameprefix, returns the component count or -1 for error.
03412  */
03413 /* UNUSED */ int
03414 nameprefix_longest_match(struct ccnd_handle *h, const unsigned char *msg,
03415                          struct ccn_indexbuf *comps, int ncomps)
03416 {
03417     int i;
03418     int base;
03419     int answer = 0;
03420     struct nameprefix_entry *npe = NULL;
03421 
03422     if (ncomps + 1 > comps->n)
03423         return(-1);
03424     base = comps->buf[0];
03425     for (i = 0; i <= ncomps; i++) {
03426         npe = hashtb_lookup(h->nameprefix_tab, msg + base, comps->buf[i] - base);
03427         if (npe == NULL)
03428             break;
03429         answer = i;
03430         if (npe->children == 0)
03431             break;
03432     }
03433     ccnd_msg(h, "nameprefix_longest_match returning %d", answer);
03434     return(answer);
03435 }
03436 
03437 /**
03438  * Creates a nameprefix entry if it does not already exist, together
03439  * with all of its parents.
03440  */
03441 static int
03442 nameprefix_seek(struct ccnd_handle *h, struct hashtb_enumerator *e,
03443                 const unsigned char *msg, struct ccn_indexbuf *comps, int ncomps)
03444 {
03445     int i;
03446     int base;
03447     int res = -1;
03448     struct nameprefix_entry *parent = NULL;
03449     struct nameprefix_entry *npe = NULL;
03450     struct propagating_entry *head = NULL;
03451 
03452     if (ncomps + 1 > comps->n)
03453         return(-1);
03454     base = comps->buf[0];
03455     for (i = 0; i <= ncomps; i++) {
03456         res = hashtb_seek(e, msg + base, comps->buf[i] - base, 0);
03457         if (res < 0)
03458             break;
03459         npe = e->data;
03460         if (res == HT_NEW_ENTRY) {
03461             head = &npe->pe_head;
03462             head->next = head;
03463             head->prev = head;
03464             head->faceid = CCN_NOFACEID;
03465             npe->parent = parent;
03466             npe->forwarding = NULL;
03467             npe->fgen = h->forward_to_gen - 1;
03468             npe->forward_to = NULL;
03469             if (parent != NULL) {
03470                 parent->children++;
03471                 npe->flags = parent->flags;
03472                 npe->src = parent->src;
03473                 npe->osrc = parent->osrc;
03474                 npe->usec = parent->usec;
03475             }
03476             else {
03477                 npe->src = npe->osrc = CCN_NOFACEID;
03478                 npe->usec = (nrand48(h->seed) % 4096U) + 8192;
03479             }
03480         }
03481         parent = npe;
03482     }
03483     return(res);
03484 }
03485 
03486 static struct content_entry *
03487 next_child_at_level(struct ccnd_handle *h,
03488                     struct content_entry *content, int level)
03489 {
03490     struct content_entry *next = NULL;
03491     struct ccn_charbuf *name;
03492     struct ccn_indexbuf *pred[CCN_SKIPLIST_MAX_DEPTH] = {NULL};
03493     int d;
03494     int res;
03495     
03496     if (content == NULL)
03497         return(NULL);
03498     if (content->ncomps <= level + 1)
03499         return(NULL);
03500     name = ccn_charbuf_create();
03501     ccn_name_init(name);
03502     res = ccn_name_append_components(name, content->key,
03503                                      content->comps[0],
03504                                      content->comps[level + 1]);
03505     if (res < 0) abort();
03506     res = ccn_name_next_sibling(name);
03507     if (res < 0) abort();
03508     if (h->debug & 8)
03509         ccnd_debug_ccnb(h, __LINE__, "child_successor", NULL,
03510                         name->buf, name->length);
03511     d = content_skiplist_findbefore(h, name->buf, name->length,
03512                                     NULL, pred);
03513     next = content_from_accession(h, pred[0]->buf[0]);
03514     if (next == content) {
03515         // XXX - I think this case should not occur, but just in case, avoid a loop.
03516         next = content_from_accession(h, content_skiplist_next(h, content));
03517         ccnd_debug_ccnb(h, __LINE__, "bump", NULL, next->key, next->size);
03518     }
03519     ccn_charbuf_destroy(&name);
03520     return(next);
03521 }
03522 
03523 static void
03524 process_incoming_interest(struct ccnd_handle *h, struct face *face,
03525                           unsigned char *msg, size_t size)
03526 {
03527     struct hashtb_enumerator ee;
03528     struct hashtb_enumerator *e = &ee;
03529     struct ccn_parsed_interest parsed_interest = {0};
03530     struct ccn_parsed_interest *pi = &parsed_interest;
03531     size_t namesize = 0;
03532     int k;
03533     int res;
03534     int try;
03535     int matched;
03536     int s_ok;
03537     struct nameprefix_entry *npe = NULL;
03538     struct content_entry *content = NULL;
03539     struct content_entry *last_match = NULL;
03540     struct ccn_indexbuf *comps = indexbuf_obtain(h);
03541     if (size > 65535)
03542         res = -__LINE__;
03543     else
03544         res = ccn_parse_interest(msg, size, pi, comps);
03545     if (res < 0) {
03546         ccnd_msg(h, "error parsing Interest - code %d", res);
03547         ccn_indexbuf_destroy(&comps);
03548         return;
03549     }
03550     ccnd_meter_bump(h, face->meter[FM_INTI], 1);
03551     if (pi->scope >= 0 && pi->scope < 2 &&
03552              (face->flags & CCN_FACE_GG) == 0) {
03553         ccnd_debug_ccnb(h, __LINE__, "interest_outofscope", face, msg, size);
03554         h->interests_dropped += 1;
03555     }
03556     else if (is_duplicate_flooded(h, msg, pi, face->faceid)) {
03557         if (h->debug & 16)
03558              ccnd_debug_ccnb(h, __LINE__, "interest_dup", face, msg, size);
03559         h->interests_dropped += 1;
03560     }
03561     else {
03562         if (h->debug & (16 | 8 | 2))
03563             ccnd_debug_ccnb(h, __LINE__, "interest_from", face, msg, size);
03564         if (h->debug & 16)
03565             ccnd_msg(h,
03566                      "version: %d, "
03567                      "prefix_comps: %d, "
03568                      "min_suffix_comps: %d, "
03569                      "max_suffix_comps: %d, "
03570                      "orderpref: %d, "
03571                      "answerfrom: %d, "
03572                      "scope: %d, "
03573                      "lifetime: %d.%04d, "
03574                      "excl: %d bytes, "
03575                      "etc: %d bytes",
03576                      pi->magic,
03577                      pi->prefix_comps,
03578                      pi->min_suffix_comps,
03579                      pi->max_suffix_comps,
03580                      pi->orderpref, pi->answerfrom, pi->scope,
03581                      ccn_interest_lifetime_seconds(msg, pi),
03582                      (int)(ccn_interest_lifetime(msg, pi) & 0xFFF) * 10000 / 4096,
03583                      pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude],
03584                      pi->offset[CCN_PI_E_OTHER] - pi->offset[CCN_PI_B_OTHER]);
03585         if (pi->magic < 20090701) {
03586             if (++(h->oldformatinterests) == h->oldformatinterestgrumble) {
03587                 h->oldformatinterestgrumble *= 2;
03588                 ccnd_msg(h, "downrev interests received: %d (%d)",
03589                          h->oldformatinterests,
03590                          pi->magic);
03591             }
03592         }
03593         namesize = comps->buf[pi->prefix_comps] - comps->buf[0];
03594         h->interests_accepted += 1;
03595         s_ok = (pi->answerfrom & CCN_AOK_STALE) != 0;
03596         matched = 0;
03597         hashtb_start(h->nameprefix_tab, e);
03598         res = nameprefix_seek(h, e, msg, comps, pi->prefix_comps);
03599         npe = e->data;
03600         if (npe == NULL)
03601             goto Bail;
03602         if ((npe->flags & CCN_FORW_LOCAL) != 0 &&
03603             (face->flags & CCN_FACE_GG) == 0) {
03604             ccnd_debug_ccnb(h, __LINE__, "interest_nonlocal", face, msg, size);
03605             h->interests_dropped += 1;
03606             goto Bail;
03607         }
03608         if ((pi->answerfrom & CCN_AOK_CS) != 0) {
03609             last_match = NULL;
03610             content = find_first_match_candidate(h, msg, pi);
03611             if (content != NULL && (h->debug & 8))
03612                 ccnd_debug_ccnb(h, __LINE__, "first_candidate", NULL,
03613                                 content->key,
03614                                 content->size);
03615             if (content != NULL &&
03616                 !content_matches_interest_prefix(h, content, msg, comps,
03617                                                  pi->prefix_comps)) {
03618                 if (h->debug & 8)
03619                     ccnd_debug_ccnb(h, __LINE__, "prefix_mismatch", NULL,
03620                                     msg, size);
03621                 content = NULL;
03622             }
03623             for (try = 0; content != NULL; try++) {
03624                 if ((s_ok || (content->flags & CCN_CONTENT_ENTRY_STALE) == 0) &&
03625                     ccn_content_matches_interest(content->key,
03626                                        content->size,
03627                                        0, NULL, msg, size, pi)) {
03628                     if ((pi->orderpref & 1) == 0 && // XXX - should be symbolic
03629                         pi->prefix_comps != comps->n - 1 &&
03630                         comps->n == content->ncomps &&
03631                         content_matches_interest_prefix(h, content, msg,
03632                                                         comps, comps->n - 1)) {
03633                         if (h->debug & 8)
03634                             ccnd_debug_ccnb(h, __LINE__, "skip_match", NULL,
03635                                             content->key,
03636                                             content->size);
03637                         goto move_along;
03638                     }
03639                     if (h->debug & 8)
03640                         ccnd_debug_ccnb(h, __LINE__, "matches", NULL,
03641                                         content->key,
03642                                         content->size);
03643                     if ((pi->orderpref & 1) == 0) // XXX - should be symbolic
03644                         break;
03645                     last_match = content;
03646                     content = next_child_at_level(h, content, comps->n - 1);
03647                     goto check_next_prefix;
03648                 }
03649             move_along:
03650                 content = content_from_accession(h, content_skiplist_next(h, content));
03651             check_next_prefix:
03652                 if (content != NULL &&
03653                     !content_matches_interest_prefix(h, content, msg,
03654                                                      comps, pi->prefix_comps)) {
03655                     if (h->debug & 8)
03656                         ccnd_debug_ccnb(h, __LINE__, "prefix_mismatch", NULL,
03657                                         content->key,
03658                                         content->size);
03659                     content = NULL;
03660                 }
03661             }
03662             if (last_match != NULL)
03663                 content = last_match;
03664             if (content != NULL) {
03665                 /* Check to see if we are planning to send already */
03666                 enum cq_delay_class c;
03667                 for (c = 0, k = -1; c < CCN_CQ_N && k == -1; c++)
03668                     if (face->q[c] != NULL)
03669                         k = ccn_indexbuf_member(face->q[c]->send_queue, content->accession);
03670                 if (k == -1) {
03671                     k = face_send_queue_insert(h, face, content);
03672                     if (k >= 0) {
03673                         if (h->debug & (32 | 8))
03674                             ccnd_debug_ccnb(h, __LINE__, "consume", face, msg, size);
03675                     }
03676                     /* Any other matched interests need to be consumed, too. */
03677                     match_interests(h, content, NULL, face, NULL);
03678                 }
03679                 if ((pi->answerfrom & CCN_AOK_EXPIRE) != 0)
03680                     mark_stale(h, content);
03681                 matched = 1;
03682             }
03683         }
03684         if (!matched && pi->scope != 0 && npe != NULL)
03685             propagate_interest(h, face, msg, pi, npe);
03686     Bail:
03687         hashtb_end(e);
03688     }
03689     indexbuf_release(h, comps);
03690 }
03691 
03692 /**
03693  * Mark content as stale
03694  */
03695 static void
03696 mark_stale(struct ccnd_handle *h, struct content_entry *content)
03697 {
03698     ccn_accession_t accession = content->accession;
03699     if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0)
03700         return;
03701     if (h->debug & 4)
03702             ccnd_debug_ccnb(h, __LINE__, "stale", NULL,
03703                             content->key, content->size);
03704     content->flags |= CCN_CONTENT_ENTRY_STALE;
03705     h->n_stale++;
03706     if (accession < h->min_stale)
03707         h->min_stale = accession;
03708     if (accession > h->max_stale)
03709         h->max_stale = accession;
03710 }
03711 
03712 /**
03713  * Scheduled event that makes content stale when its FreshnessSeconds
03714  * has exported.
03715  *
03716  * May actually remove the content if we are over quota.
03717  */
03718 static int
03719 expire_content(struct ccn_schedule *sched,
03720                void *clienth,
03721                struct ccn_scheduled_event *ev,
03722                int flags)
03723 {
03724     struct ccnd_handle *h = clienth;
03725     ccn_accession_t accession = ev->evint;
03726     struct content_entry *content = NULL;
03727     int res;
03728     unsigned n;
03729     if ((flags & CCN_SCHEDULE_CANCEL) != 0)
03730         return(0);
03731     content = content_from_accession(h, accession);
03732     if (content != NULL) {
03733         n = hashtb_n(h->content_tab);
03734         /* The fancy test here lets existing stale content go away, too. */
03735         if ((n - (n >> 3)) > h->capacity ||
03736             (n > h->capacity && h->min_stale > h->max_stale)) {
03737             res = remove_content(h, content);
03738             if (res == 0)
03739                 return(0);
03740         }
03741         mark_stale(h, content);
03742     }
03743     return(0);
03744 }
03745 
03746 /**
03747  * Schedules content expiration based on its FreshnessSeconds.
03748  *
03749  */
03750 static void
03751 set_content_timer(struct ccnd_handle *h, struct content_entry *content,
03752                   struct ccn_parsed_ContentObject *pco)
03753 {
03754     int seconds = 0;
03755     int microseconds = 0;
03756     size_t start = pco->offset[CCN_PCO_B_FreshnessSeconds];
03757     size_t stop  = pco->offset[CCN_PCO_E_FreshnessSeconds];
03758     if (h->force_zero_freshness) {
03759         /* Keep around for long enough to make it through the queues */
03760         microseconds = 8 * h->data_pause_microsec + 10000;
03761         goto Finish;
03762     }
03763     if (start == stop)
03764         return;
03765     seconds = ccn_fetch_tagged_nonNegativeInteger(
03766                 CCN_DTAG_FreshnessSeconds,
03767                 content->key,
03768                 start, stop);
03769     if (seconds <= 0)
03770         return;
03771     if (seconds > ((1U<<31) / 1000000)) {
03772         ccnd_debug_ccnb(h, __LINE__, "FreshnessSeconds_too_large", NULL,
03773             content->key, pco->offset[CCN_PCO_E]);
03774         return;
03775     }
03776     microseconds = seconds * 1000000;
03777 Finish:
03778     ccn_schedule_event(h->sched, microseconds,
03779                        &expire_content, NULL, content->accession);
03780 }
03781 
03782 static void
03783 process_incoming_content(struct ccnd_handle *h, struct face *face,
03784                          unsigned char *wire_msg, size_t wire_size)
03785 {
03786     unsigned char *msg;
03787     size_t size;
03788     struct hashtb_enumerator ee;
03789     struct hashtb_enumerator *e = &ee;
03790     struct ccn_parsed_ContentObject obj = {0};
03791     int res;
03792     size_t keysize = 0;
03793     size_t tailsize = 0;
03794     unsigned char *tail = NULL;
03795     struct content_entry *content = NULL;
03796     int i;
03797     struct ccn_indexbuf *comps = indexbuf_obtain(h);
03798     struct ccn_charbuf *cb = charbuf_obtain(h);
03799     
03800     msg = wire_msg;
03801     size = wire_size;
03802     
03803     res = ccn_parse_ContentObject(msg, size, &obj, comps);
03804     if (res < 0) {
03805         ccnd_msg(h, "error parsing ContentObject - code %d", res);
03806         goto Bail;
03807     }
03808     ccnd_meter_bump(h, face->meter[FM_DATI], 1);
03809     if (comps->n < 1 ||
03810         (keysize = comps->buf[comps->n - 1]) > 65535 - 36) {
03811         ccnd_msg(h, "ContentObject with keysize %lu discarded",
03812                  (unsigned long)keysize);
03813         ccnd_debug_ccnb(h, __LINE__, "oversize", face, msg, size);
03814         res = -__LINE__;
03815         goto Bail;
03816     }
03817     /* Make the ContentObject-digest name component explicit */
03818     ccn_digest_ContentObject(msg, &obj);
03819     if (obj.digest_bytes != 32) {
03820         ccnd_debug_ccnb(h, __LINE__, "indigestible", face, msg, size);
03821         goto Bail;
03822     }
03823     i = comps->buf[comps->n - 1];
03824     ccn_charbuf_append(cb, msg, i);
03825     ccn_charbuf_append_tt(cb, CCN_DTAG_Component, CCN_DTAG);
03826     ccn_charbuf_append_tt(cb, obj.digest_bytes, CCN_BLOB);
03827     ccn_charbuf_append(cb, obj.digest, obj.digest_bytes);
03828     ccn_charbuf_append_closer(cb);
03829     ccn_charbuf_append(cb, msg + i, size - i);
03830     msg = cb->buf;
03831     size = cb->length;
03832     res = ccn_parse_ContentObject(msg, size, &obj, comps);
03833     if (res < 0) abort(); /* must have just messed up */
03834     
03835     if (obj.magic != 20090415) {
03836         if (++(h->oldformatcontent) == h->oldformatcontentgrumble) {
03837             h->oldformatcontentgrumble *= 10;
03838             ccnd_msg(h, "downrev content items received: %d (%d)",
03839                      h->oldformatcontent,
03840                      obj.magic);
03841         }
03842     }
03843     if (h->debug & 4)
03844         ccnd_debug_ccnb(h, __LINE__, "content_from", face, msg, size);
03845     keysize = obj.offset[CCN_PCO_B_Content];
03846     tail = msg + keysize;
03847     tailsize = size - keysize;
03848     hashtb_start(h->content_tab, e);
03849     res = hashtb_seek(e, msg, keysize, tailsize);
03850     content = e->data;
03851     if (res == HT_OLD_ENTRY) {
03852         if (tailsize != e->extsize ||
03853               0 != memcmp(tail, ((unsigned char *)e->key) + keysize, tailsize)) {
03854             ccnd_msg(h, "ContentObject name collision!!!!!");
03855             ccnd_debug_ccnb(h, __LINE__, "new", face, msg, size);
03856             ccnd_debug_ccnb(h, __LINE__, "old", NULL, e->key, e->keysize + e->extsize);
03857             content = NULL;
03858             hashtb_delete(e); /* XXX - Mercilessly throw away both of them. */
03859             res = -__LINE__;
03860         }
03861         else if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0) {
03862             /* When old content arrives after it has gone stale, freshen it */
03863             // XXX - ought to do mischief checks before this
03864             content->flags &= ~CCN_CONTENT_ENTRY_STALE;
03865             h->n_stale--;
03866             set_content_timer(h, content, &obj);
03867             // XXX - no counter for this case
03868         }
03869         else {
03870             h->content_dups_recvd++;
03871             ccnd_msg(h, "received duplicate ContentObject from %u (accession %llu)",
03872                      face->faceid, (unsigned long long)content->accession);
03873             ccnd_debug_ccnb(h, __LINE__, "dup", face, msg, size);
03874         }
03875     }
03876     else if (res == HT_NEW_ENTRY) {
03877         content->accession = ++(h->accession);
03878         enroll_content(h, content);
03879         if (content == content_from_accession(h, content->accession)) {
03880             content->ncomps = comps->n;
03881             content->comps = calloc(comps->n, sizeof(comps[0]));
03882         }
03883         content->key_size = e->keysize;
03884         content->size = e->keysize + e->extsize;
03885         content->key = e->key;
03886         if (content->comps != NULL) {
03887             for (i = 0; i < comps->n; i++)
03888                 content->comps[i] = comps->buf[i];
03889             content_skiplist_insert(h, content);
03890             set_content_timer(h, content, &obj);
03891         }
03892         else {
03893             ccnd_msg(h, "could not enroll ContentObject (accession %llu)",
03894                 (unsigned long long)content->accession);
03895             hashtb_delete(e);
03896             res = -__LINE__;
03897             content = NULL;
03898         }
03899         /* Mark public keys supplied at startup as precious. */
03900         if (obj.type == CCN_CONTENT_KEY && content->accession <= (h->capacity + 7)/8)
03901             content->flags |= CCN_CONTENT_ENTRY_PRECIOUS;
03902     }
03903     hashtb_end(e);
03904 Bail:
03905     indexbuf_release(h, comps);
03906     charbuf_release(h, cb);
03907     cb = NULL;
03908     if (res >= 0 && content != NULL) {
03909         int n_matches;
03910         enum cq_delay_class c;
03911         struct content_queue *q;
03912         n_matches = match_interests(h, content, &obj, NULL, face);
03913         if (res == HT_NEW_ENTRY) {
03914             if (n_matches < 0) {
03915                 remove_content(h, content);
03916                 return;
03917             }
03918             if (n_matches == 0 && (face->flags & CCN_FACE_GG) == 0) {
03919                 content->flags |= CCN_CONTENT_ENTRY_SLOWSEND;
03920                 ccn_indexbuf_append_element(h->unsol, content->accession);
03921             }
03922         }
03923         for (c = 0; c < CCN_CQ_N; c++) {
03924             q = face->q[c];
03925             if (q != NULL) {
03926                 i = ccn_indexbuf_member(q->send_queue, content->accession);
03927                 if (i >= 0) {
03928                     /*
03929                      * In the case this consumed any interests from this source,
03930                      * don't send the content back
03931                      */
03932                     if (h->debug & 8)
03933                         ccnd_debug_ccnb(h, __LINE__, "content_nosend", face, msg, size);
03934                     q->send_queue->buf[i] = 0;
03935                 }
03936             }
03937         }
03938     }
03939 }
03940 
03941 static void
03942 process_input_message(struct ccnd_handle *h, struct face *face,
03943                       unsigned char *msg, size_t size, int pdu_ok)
03944 {
03945     struct ccn_skeleton_decoder decoder = {0};
03946     struct ccn_skeleton_decoder *d = &decoder;
03947     ssize_t dres;
03948     enum ccn_dtag dtag;
03949     
03950     if ((face->flags & CCN_FACE_UNDECIDED) != 0) {
03951         face->flags &= ~CCN_FACE_UNDECIDED;
03952         if ((face->flags & CCN_FACE_LOOPBACK) != 0)
03953             face->flags |= CCN_FACE_GG;
03954         /* YYY This is the first place that we know that an inbound stream face is speaking CCNx protocol. */
03955         register_new_face(h, face);
03956     }
03957     d->state |= CCN_DSTATE_PAUSE;
03958     dres = ccn_skeleton_decode(d, msg, size);
03959     if (d->state < 0)
03960         abort(); /* cannot happen because of checks in caller */
03961     if (CCN_GET_TT_FROM_DSTATE(d->state) != CCN_DTAG) {
03962         ccnd_msg(h, "discarding unknown message; size = %lu", (unsigned long)size);
03963         // XXX - keep a count?
03964         return;
03965     }
03966     dtag = d->numval;
03967     switch (dtag) {
03968         case CCN_DTAG_CCNProtocolDataUnit:
03969             if (!pdu_ok)
03970                 break;
03971             size -= d->index;
03972             if (size > 0)
03973                 size--;
03974             msg += d->index;
03975             face->flags |= CCN_FACE_LINK;
03976             face->flags &= ~CCN_FACE_GG;
03977             memset(d, 0, sizeof(*d));
03978             while (d->index < size) {
03979                 dres = ccn_skeleton_decode(d, msg + d->index, size - d->index);
03980                 if (d->state != 0)
03981                     abort(); /* cannot happen because of checks in caller */
03982                 /* The pdu_ok parameter limits the recursion depth */
03983                 process_input_message(h, face, msg + d->index - dres, dres, 0);
03984             }
03985             return;
03986         case CCN_DTAG_Interest:
03987             process_incoming_interest(h, face, msg, size);
03988             return;
03989         case CCN_DTAG_ContentObject:
03990             process_incoming_content(h, face, msg, size);
03991             return;
03992         case CCN_DTAG_SequenceNumber:
03993             process_incoming_link_message(h, face, dtag, msg, size);
03994             return;
03995         default:
03996             break;
03997     }
03998     ccnd_msg(h, "discarding unknown message; dtag=%u, size = %lu",
03999              (unsigned)dtag,
04000              (unsigned long)size);
04001 }
04002 
04003 static void
04004 ccnd_new_face_msg(struct ccnd_handle *h, struct face *face)
04005 {
04006     const struct sockaddr *addr = face->addr;
04007     int port = 0;
04008     const unsigned char *rawaddr = NULL;
04009     char printable[80];
04010     const char *peer = NULL;
04011     if (addr->sa_family == AF_INET6) {
04012         const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
04013         rawaddr = (const unsigned char *)&addr6->sin6_addr;
04014         port = htons(addr6->sin6_port);
04015     }
04016     else if (addr->sa_family == AF_INET) {
04017         const struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
04018         rawaddr = (const unsigned char *)&addr4->sin_addr.s_addr;
04019         port = htons(addr4->sin_port);
04020     }
04021     if (rawaddr != NULL)
04022         peer = inet_ntop(addr->sa_family, rawaddr, printable, sizeof(printable));
04023     if (peer == NULL)
04024         peer = "(unknown)";
04025     ccnd_msg(h,
04026              "accepted datagram client id=%d (flags=0x%x) %s port %d",
04027              face->faceid, face->flags, peer, port);
04028 }
04029 
04030 /**
04031  * Since struct sockaddr_in6 may contain fields that should not participate
04032  * in comparison / hash, ensure the undesired fields are zero.
04033  *
04034  * Per RFC 3493, sin6_flowinfo is zeroed.
04035  *
04036  * @param addr is the sockaddr (any family)
04037  * @param addrlen is its length
04038  * @param space points to a buffer that may be used for the result.
04039  * @returns either the original addr or a pointer to a scrubbed copy.
04040  *
04041  */
04042 static struct sockaddr *
04043 scrub_sockaddr(struct sockaddr *addr, socklen_t addrlen,
04044                struct sockaddr_in6 *space)
04045 {
04046     struct sockaddr_in6 *src;
04047     struct sockaddr_in6 *dst;
04048     if (addr->sa_family != AF_INET6 || addrlen != sizeof(*space))
04049         return(addr);
04050     dst = space;
04051     src = (void *)addr;
04052     memset(dst, 0, addrlen);
04053     /* Copy first byte case sin6_len is used. */
04054     ((uint8_t *)dst)[0] = ((uint8_t *)src)[0];
04055     dst->sin6_family   = src->sin6_family;
04056     dst->sin6_port     = src->sin6_port;
04057     dst->sin6_addr     = src->sin6_addr;
04058     dst->sin6_scope_id = src->sin6_scope_id;
04059     return((struct sockaddr *)dst);
04060 }
04061 
04062 static struct face *
04063 get_dgram_source(struct ccnd_handle *h, struct face *face,
04064                  struct sockaddr *addr, socklen_t addrlen, int why)
04065 {
04066     struct face *source = NULL;
04067     struct hashtb_enumerator ee;
04068     struct hashtb_enumerator *e = &ee;
04069     struct sockaddr_in6 space;
04070     int res;
04071     if ((face->flags & CCN_FACE_DGRAM) == 0)
04072         return(face);
04073     if ((face->flags & CCN_FACE_MCAST) != 0)
04074         return(face);
04075     hashtb_start(h->dgram_faces, e);
04076     res = hashtb_seek(e, scrub_sockaddr(addr, addrlen, &space), addrlen, 0);
04077     if (res >= 0) {
04078         source = e->data;
04079         source->recvcount++;
04080         if (source->addr == NULL) {
04081             source->addr = e->key;
04082             source->addrlen = e->keysize;
04083             source->recv_fd = face->recv_fd;
04084             source->sendface = face->faceid;
04085             init_face_flags(h, source, CCN_FACE_DGRAM);
04086             if (why == 1 && (source->flags & CCN_FACE_LOOPBACK) != 0)
04087                 source->flags |= CCN_FACE_GG;
04088             res = enroll_face(h, source);
04089             if (res == -1) {
04090                 hashtb_delete(e);
04091                 source = NULL;
04092             }
04093             else {
04094                 ccnd_new_face_msg(h, source);
04095                 reap_needed(h, CCN_INTEREST_LIFETIME_MICROSEC);
04096             }
04097         }
04098     }
04099     hashtb_end(e);
04100     return(source);
04101 }
04102 
04103 /**
04104  * Break up data in a face's input buffer buffer into individual messages,
04105  * and call process_input_message on each one.
04106  *
04107  * This is used to handle things originating from the internal client -
04108  * its output is input for face 0.
04109  */
04110 static void
04111 process_input_buffer(struct ccnd_handle *h, struct face *face)
04112 {
04113     unsigned char *msg;
04114     size_t size;
04115     ssize_t dres;
04116     struct ccn_skeleton_decoder *d;
04117 
04118     if (face == NULL || face->inbuf == NULL)
04119         return;
04120     d = &face->decoder;
04121     msg = face->inbuf->buf;
04122     size = face->inbuf->length;
04123     while (d->index < size) {
04124         dres = ccn_skeleton_decode(d, msg + d->index, size - d->index);
04125         if (d->state != 0)
04126             break;
04127         process_input_message(h, face, msg + d->index - dres, dres, 0);
04128     }
04129     if (d->index != size) {
04130         ccnd_msg(h, "protocol error on face %u (state %d), discarding %d bytes",
04131                      face->faceid, d->state, (int)(size - d->index));
04132         // XXX - perhaps this should be a fatal error.
04133     }
04134     face->inbuf->length = 0;
04135     memset(d, 0, sizeof(*d));
04136 }
04137 
04138 /**
04139  * Process the input from a socket.
04140  *
04141  * The socket has been found ready for input by the poll call.
04142  * Decide what face it corresponds to, and after checking for exceptional
04143  * cases, receive data, parse it into ccnb-encoded messages, and call
04144  * process_input_message for each one.
04145  */
04146 static void
04147 process_input(struct ccnd_handle *h, int fd)
04148 {
04149     struct face *face = NULL;
04150     struct face *source = NULL;
04151     ssize_t res;
04152     ssize_t dres;
04153     ssize_t msgstart;
04154     unsigned char *buf;
04155     struct ccn_skeleton_decoder *d;
04156     struct sockaddr_storage sstor;
04157     socklen_t addrlen = sizeof(sstor);
04158     struct sockaddr *addr = (struct sockaddr *)&sstor;
04159     int err = 0;
04160     socklen_t err_sz;
04161     
04162     face = hashtb_lookup(h->faces_by_fd, &fd, sizeof(fd));
04163     if (face == NULL)
04164         return;
04165     if ((face->flags & (CCN_FACE_DGRAM | CCN_FACE_PASSIVE)) == CCN_FACE_PASSIVE) {
04166         accept_connection(h, fd);
04167         check_comm_file(h);
04168         return;
04169     }
04170     err_sz = sizeof(err);
04171     res = getsockopt(face->recv_fd, SOL_SOCKET, SO_ERROR, &err, &err_sz);
04172     if (res >= 0 && err != 0) {
04173         ccnd_msg(h, "error on face %u: %s (%d)", face->faceid, strerror(err), err);
04174         if (err == ETIMEDOUT && (face->flags & CCN_FACE_CONNECTING) != 0) {
04175             shutdown_client_fd(h, fd);
04176             return;
04177         }
04178     }
04179     d = &face->decoder;
04180     if (face->inbuf == NULL)
04181         face->inbuf = ccn_charbuf_create();
04182     if (face->inbuf->length == 0)
04183         memset(d, 0, sizeof(*d));
04184     buf = ccn_charbuf_reserve(face->inbuf, 8800);
04185     memset(&sstor, 0, sizeof(sstor));
04186     res = recvfrom(face->recv_fd, buf, face->inbuf->limit - face->inbuf->length,
04187             /* flags */ 0, addr, &addrlen);
04188     if (res == -1)
04189         ccnd_msg(h, "recvfrom face %u :%s (errno = %d)",
04190                     face->faceid, strerror(errno), errno);
04191     else if (res == 0 && (face->flags & CCN_FACE_DGRAM) == 0)
04192         shutdown_client_fd(h, fd);
04193     else {
04194         source = get_dgram_source(h, face, addr, addrlen, (res == 1) ? 1 : 2);
04195         ccnd_meter_bump(h, source->meter[FM_BYTI], res);
04196         source->recvcount++;
04197         source->surplus = 0; // XXX - we don't actually use this, except for some obscure messages.
04198         if (res <= 1 && (source->flags & CCN_FACE_DGRAM) != 0) {
04199             // XXX - If the initial heartbeat gets missed, we don't realize the locality of the face.
04200             if (h->debug & 128)
04201                 ccnd_msg(h, "%d-byte heartbeat on %d", (int)res, source->faceid);
04202             return;
04203         }
04204         face->inbuf->length += res;
04205         msgstart = 0;
04206         if (((face->flags & CCN_FACE_UNDECIDED) != 0 &&
04207              face->inbuf->length >= 6 &&
04208              0 == memcmp(face->inbuf->buf, "GET ", 4))) {
04209             ccnd_stats_handle_http_connection(h, face);
04210             return;
04211         }
04212         dres = ccn_skeleton_decode(d, buf, res);
04213         while (d->state == 0) {
04214             process_input_message(h, source,
04215                                   face->inbuf->buf + msgstart,
04216                                   d->index - msgstart,
04217                                   (face->flags & CCN_FACE_LOCAL) != 0);
04218             msgstart = d->index;
04219             if (msgstart == face->inbuf->length) {
04220                 face->inbuf->length = 0;
04221                 return;
04222             }
04223             dres = ccn_skeleton_decode(d,
04224                     face->inbuf->buf + d->index, // XXX - msgstart and d->index are the same here - use msgstart
04225                     res = face->inbuf->length - d->index);  // XXX - why is res set here?
04226         }
04227         if ((face->flags & CCN_FACE_DGRAM) != 0) {
04228             ccnd_msg(h, "protocol error on face %u, discarding %u bytes",
04229                 source->faceid,
04230                 (unsigned)(face->inbuf->length));  // XXX - Should be face->inbuf->length - d->index (or msgstart)
04231             face->inbuf->length = 0;
04232             /* XXX - should probably ignore this source for a while */
04233             return;
04234         }
04235         else if (d->state < 0) {
04236             ccnd_msg(h, "protocol error on face %u", source->faceid);
04237             shutdown_client_fd(h, fd);
04238             return;
04239         }
04240         if (msgstart < face->inbuf->length && msgstart > 0) {
04241             /* move partial message to start of buffer */
04242             memmove(face->inbuf->buf, face->inbuf->buf + msgstart,
04243                 face->inbuf->length - msgstart);
04244             face->inbuf->length -= msgstart;
04245             d->index -= msgstart;
04246         }
04247     }
04248 }
04249 
04250 static void
04251 process_internal_client_buffer(struct ccnd_handle *h)
04252 {
04253     struct face *face = h->face0;
04254     if (face == NULL)
04255         return;
04256     face->inbuf = ccn_grab_buffered_output(h->internal_client);
04257     if (face->inbuf == NULL)
04258         return;
04259     ccnd_meter_bump(h, face->meter[FM_BYTI], face->inbuf->length);
04260     process_input_buffer(h, face);
04261     ccn_charbuf_destroy(&(face->inbuf));
04262 }
04263 
04264 /**
04265  * Handle errors after send() or sendto().
04266  * @returns -1 if error has been dealt with, or 0 to defer sending.
04267  */
04268 static int
04269 handle_send_error(struct ccnd_handle *h, int errnum, struct face *face,
04270                   const void *data, size_t size)
04271 {
04272     int res = -1;
04273     if (errnum == EAGAIN) {
04274         res = 0;
04275     }
04276     else if (errnum == EPIPE) {
04277         face->flags |= CCN_FACE_NOSEND;
04278         face->outbufindex = 0;
04279         ccn_charbuf_destroy(&face->outbuf);
04280     }
04281     else {
04282         ccnd_msg(h, "send to face %u failed: %s (errno = %d)",
04283                  face->faceid, strerror(errnum), errnum);
04284         if (errnum == EISCONN)
04285             res = 0;
04286     }
04287     return(res);
04288 }
04289 
04290 static int
04291 sending_fd(struct ccnd_handle *h, struct face *face)
04292 {
04293     struct face *out = NULL;
04294     if (face->sendface == face->faceid)
04295         return(face->recv_fd);
04296     out = face_from_faceid(h, face->sendface);
04297     if (out != NULL)
04298         return(out->recv_fd);
04299     face->sendface = CCN_NOFACEID;
04300     if (face->addr != NULL) {
04301         switch (face->addr->sa_family) {
04302             case AF_INET:
04303                 face->sendface = h->ipv4_faceid;
04304                 break;
04305             case AF_INET6:
04306                 face->sendface = h->ipv6_faceid;
04307                 break;
04308             default:
04309                 break;
04310         }
04311     }
04312     out = face_from_faceid(h, face->sendface);
04313     if (out != NULL)
04314         return(out->recv_fd);
04315     return(-1);
04316 }
04317 
04318 /**
04319  * Send data to the face.
04320  *
04321  * No direct error result is provided; the face state is updated as needed.
04322  */
04323 void
04324 ccnd_send(struct ccnd_handle *h,
04325           struct face *face,
04326           const void *data, size_t size)
04327 {
04328     ssize_t res;
04329     if ((face->flags & CCN_FACE_NOSEND) != 0)
04330         return;
04331     face->surplus++;
04332     if (face->outbuf != NULL) {
04333         ccn_charbuf_append(face->outbuf, data, size);
04334         return;
04335     }
04336     if (face == h->face0) {
04337         ccnd_meter_bump(h, face->meter[FM_BYTO], size);
04338         ccn_dispatch_message(h->internal_client, (void *)data, size);
04339         process_internal_client_buffer(h);
04340         return;
04341     }
04342     if ((face->flags & CCN_FACE_DGRAM) == 0)
04343         res = send(face->recv_fd, data, size, 0);
04344     else
04345         res = sendto(sending_fd(h, face), data, size, 0,
04346                      face->addr, face->addrlen);
04347     if (res > 0)
04348         ccnd_meter_bump(h, face->meter[FM_BYTO], res);
04349     if (res == size)
04350         return;
04351     if (res == -1) {
04352         res = handle_send_error(h, errno, face, data, size);
04353         if (res == -1)
04354             return;
04355     }
04356     if ((face->flags & CCN_FACE_DGRAM) != 0) {
04357         ccnd_msg(h, "sendto short");
04358         return;
04359     }
04360     face->outbufindex = 0;
04361     face->outbuf = ccn_charbuf_create();
04362     if (face->outbuf == NULL) {
04363         ccnd_msg(h, "do_write: %s", strerror(errno));
04364         return;
04365     }
04366     ccn_charbuf_append(face->outbuf,
04367                        ((const unsigned char *)data) + res, size - res);
04368 }
04369 
04370 static void
04371 do_deferred_write(struct ccnd_handle *h, int fd)
04372 {
04373     /* This only happens on connected sockets */
04374     ssize_t res;
04375     struct face *face = hashtb_lookup(h->faces_by_fd, &fd, sizeof(fd));
04376     if (face == NULL)
04377         return;
04378     if (face->outbuf != NULL) {
04379         ssize_t sendlen = face->outbuf->length - face->outbufindex;
04380         if (sendlen > 0) {
04381             res = send(fd, face->outbuf->buf + face->outbufindex, sendlen, 0);
04382             if (res == -1) {
04383                 if (errno == EPIPE) {
04384                     face->flags |= CCN_FACE_NOSEND;
04385                     face->outbufindex = 0;
04386                     ccn_charbuf_destroy(&face->outbuf);
04387                     return;
04388                 }
04389                 ccnd_msg(h, "send: %s (errno = %d)", strerror(errno), errno);
04390                 shutdown_client_fd(h, fd);
04391                 return;
04392             }
04393             if (res == sendlen) {
04394                 face->outbufindex = 0;
04395                 ccn_charbuf_destroy(&face->outbuf);
04396                 if ((face->flags & CCN_FACE_CLOSING) != 0)
04397                     shutdown_client_fd(h, fd);
04398                 return;
04399             }
04400             face->outbufindex += res;
04401             return;
04402         }
04403         face->outbufindex = 0;
04404         ccn_charbuf_destroy(&face->outbuf);
04405     }
04406     if ((face->flags & CCN_FACE_CLOSING) != 0)
04407         shutdown_client_fd(h, fd);
04408     else if ((face->flags & CCN_FACE_CONNECTING) != 0) {
04409         face->flags &= ~CCN_FACE_CONNECTING;
04410         ccnd_face_status_change(h, face->faceid);
04411     }
04412     else
04413         ccnd_msg(h, "ccnd:do_deferred_write: something fishy on %d", fd);
04414 }
04415 
04416 /**
04417  * Set up the array of fd descriptors for the poll(2) call.
04418  *
04419  * Arrange the array so that multicast receivers are early, so that
04420  * if the same packet arrives on both a multicast socket and a
04421  * normal socket, we will count is as multicast.
04422  */
04423 static void
04424 prepare_poll_fds(struct ccnd_handle *h)
04425 {
04426     struct hashtb_enumerator ee;
04427     struct hashtb_enumerator *e = &ee;
04428     int i, j, k;
04429     if (hashtb_n(h->faces_by_fd) != h->nfds) {
04430         h->nfds = hashtb_n(h->faces_by_fd);
04431         h->fds = realloc(h->fds, h->nfds * sizeof(h->fds[0]));
04432         memset(h->fds, 0, h->nfds * sizeof(h->fds[0]));
04433     }
04434     for (i = 0, k = h->nfds, hashtb_start(h->faces_by_fd, e);
04435          i < k && e->data != NULL; hashtb_next(e)) {
04436         struct face *face = e->data;
04437         if (face->flags & CCN_FACE_MCAST)
04438             j = i++;
04439         else
04440             j = --k;
04441         h->fds[j].fd = face->recv_fd;
04442         h->fds[j].events = ((face->flags & CCN_FACE_NORECV) == 0) ? POLLIN : 0;
04443         if ((face->outbuf != NULL || (face->flags & CCN_FACE_CLOSING) != 0))
04444             h->fds[j].events |= POLLOUT;
04445     }
04446     hashtb_end(e);
04447     if (i < k)
04448         abort();
04449 }
04450 
04451 /**
04452  * Run the main loop of the ccnd
04453  */
04454 void
04455 ccnd_run(struct ccnd_handle *h)
04456 {
04457     int i;
04458     int res;
04459     int timeout_ms = -1;
04460     int prev_timeout_ms = -1;
04461     int usec;
04462     for (h->running = 1; h->running;) {
04463         process_internal_client_buffer(h);
04464         usec = ccn_schedule_run(h->sched);
04465         timeout_ms = (usec < 0) ? -1 : ((usec + 960) / 1000);
04466         if (timeout_ms == 0 && prev_timeout_ms == 0)
04467             timeout_ms = 1;
04468         process_internal_client_buffer(h);
04469         prepare_poll_fds(h);
04470         if (0) ccnd_msg(h, "at ccnd.c:%d poll(h->fds, %d, %d)", __LINE__, h->nfds, timeout_ms);
04471         res = poll(h->fds, h->nfds, timeout_ms);
04472         prev_timeout_ms = ((res == 0) ? timeout_ms : 1);
04473         if (-1 == res) {
04474             ccnd_msg(h, "poll: %s (errno = %d)", strerror(errno), errno);
04475             sleep(1);
04476             continue;
04477         }
04478         for (i = 0; res > 0 && i < h->nfds; i++) {
04479             if (h->fds[i].revents != 0) {
04480                 res--;
04481                 if (h->fds[i].revents & (POLLERR | POLLNVAL | POLLHUP)) {
04482                     if (h->fds[i].revents & (POLLIN))
04483                         process_input(h, h->fds[i].fd);
04484                     else
04485                         shutdown_client_fd(h, h->fds[i].fd);
04486                     continue;
04487                 }
04488                 if (h->fds[i].revents & (POLLOUT))
04489                     do_deferred_write(h, h->fds[i].fd);
04490                 else if (h->fds[i].revents & (POLLIN))
04491                     process_input(h, h->fds[i].fd);
04492             }
04493         }
04494     }
04495 }
04496 
04497 static void
04498 ccnd_reseed(struct ccnd_handle *h)
04499 {
04500     int fd;
04501     ssize_t res;
04502     
04503     res = -1;
04504     fd = open("/dev/urandom", O_RDONLY);
04505     if (fd != -1) {
04506         res = read(fd, h->seed, sizeof(h->seed));
04507         close(fd);
04508     }
04509     if (res != sizeof(h->seed)) {
04510         h->seed[1] = (unsigned short)getpid(); /* better than no entropy */
04511         h->seed[2] = (unsigned short)time(NULL);
04512     }
04513     /*
04514      * The call to seed48 is needed by cygwin, and should be harmless
04515      * on other platforms.
04516      */
04517     seed48(h->seed);
04518 }
04519 
04520 static char *
04521 ccnd_get_local_sockname(void)
04522 {
04523     struct sockaddr_un sa;
04524     ccn_setup_sockaddr_un(NULL, &sa);
04525     return(strdup(sa.sun_path));
04526 }
04527 
04528 static void
04529 ccnd_gettime(const struct ccn_gettime *self, struct ccn_timeval *result)
04530 {
04531     struct ccnd_handle *h = self->data;
04532     struct timeval now = {0};
04533     gettimeofday(&now, 0);
04534     result->s = now.tv_sec;
04535     result->micros = now.tv_usec;
04536     h->sec = now.tv_sec;
04537     h->usec = now.tv_usec;
04538 }
04539 
04540 void
04541 ccnd_setsockopt_v6only(struct ccnd_handle *h, int fd)
04542 {
04543     int yes = 1;
04544     int res = 0;
04545 #ifdef IPV6_V6ONLY
04546     res = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes));
04547 #endif
04548     if (res == -1)
04549         ccnd_msg(h, "warning - could not set IPV6_V6ONLY on fd %d: %s",
04550                  fd, strerror(errno));
04551 }
04552 
04553 static const char *
04554 af_name(int family)
04555 {
04556     switch (family) {
04557         case AF_INET:
04558             return("ipv4");
04559         case AF_INET6:
04560             return("ipv6");
04561         default:
04562             return("");
04563     }
04564 }
04565 
04566 static int
04567 ccnd_listen_on_wildcards(struct ccnd_handle *h)
04568 {
04569     int fd;
04570     int res;
04571     int whichpf;
04572     struct addrinfo hints = {0};
04573     struct addrinfo *addrinfo = NULL;
04574     struct addrinfo *a;
04575     
04576     hints.ai_socktype = SOCK_DGRAM;
04577     hints.ai_flags = AI_PASSIVE;
04578     for (whichpf = 0; whichpf < 2; whichpf++) {
04579         hints.ai_family = whichpf ? PF_INET6 : PF_INET;
04580         res = getaddrinfo(NULL, h->portstr, &hints, &addrinfo);
04581         if (res == 0) {
04582             for (a = addrinfo; a != NULL; a = a->ai_next) {
04583                 fd = socket(a->ai_family, SOCK_DGRAM, 0);
04584                 if (fd != -1) {
04585                     struct face *face = NULL;
04586                     int yes = 1;
04587                     int rcvbuf = 0;
04588                     socklen_t rcvbuf_sz;
04589                     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04590                     rcvbuf_sz = sizeof(rcvbuf);
04591                     getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_sz);
04592                     if (a->ai_family == AF_INET6)
04593                         ccnd_setsockopt_v6only(h, fd);
04594                     res = bind(fd, a->ai_addr, a->ai_addrlen);
04595                     if (res != 0) {
04596                         close(fd);
04597                         continue;
04598                     }
04599                     face = record_connection(h, fd,
04600                                              a->ai_addr, a->ai_addrlen,
04601                                              CCN_FACE_DGRAM | CCN_FACE_PASSIVE);
04602                     if (face == NULL) {
04603                         close(fd);
04604                         continue;
04605                     }
04606                     if (a->ai_family == AF_INET)
04607                         h->ipv4_faceid = face->faceid;
04608                     else
04609                         h->ipv6_faceid = face->faceid;
04610                     ccnd_msg(h, "accepting %s datagrams on fd %d rcvbuf %d",
04611                              af_name(a->ai_family), fd, rcvbuf);
04612                 }
04613             }
04614             for (a = addrinfo; a != NULL; a = a->ai_next) {
04615                 fd = socket(a->ai_family, SOCK_STREAM, 0);
04616                 if (fd != -1) {
04617                     int yes = 1;
04618                     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04619                     if (a->ai_family == AF_INET6)
04620                         ccnd_setsockopt_v6only(h, fd);
04621                     res = bind(fd, a->ai_addr, a->ai_addrlen);
04622                     if (res != 0) {
04623                         close(fd);
04624                         continue;
04625                     }
04626                     res = listen(fd, 30);
04627                     if (res == -1) {
04628                         close(fd);
04629                         continue;
04630                     }
04631                     record_connection(h, fd,
04632                                       a->ai_addr, a->ai_addrlen,
04633                                       CCN_FACE_PASSIVE);
04634                     ccnd_msg(h, "accepting %s connections on fd %d",
04635                              af_name(a->ai_family), fd);
04636                 }
04637             }
04638             freeaddrinfo(addrinfo);
04639         }
04640     }
04641     return(0);
04642 }
04643 
04644 static int
04645 ccnd_listen_on_address(struct ccnd_handle *h, const char *addr)
04646 {
04647     int fd;
04648     int res;
04649     struct addrinfo hints = {0};
04650     struct addrinfo *addrinfo = NULL;
04651     struct addrinfo *a;
04652     int ok = 0;
04653     
04654     ccnd_msg(h, "listen_on %s", addr);
04655     hints.ai_socktype = SOCK_DGRAM;
04656     hints.ai_flags = AI_PASSIVE;
04657     res = getaddrinfo(addr, h->portstr, &hints, &addrinfo);
04658     if (res == 0) {
04659         for (a = addrinfo; a != NULL; a = a->ai_next) {
04660             fd = socket(a->ai_family, SOCK_DGRAM, 0);
04661             if (fd != -1) {
04662                 struct face *face = NULL;
04663                 int yes = 1;
04664                 int rcvbuf = 0;
04665                 socklen_t rcvbuf_sz;
04666                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04667                 rcvbuf_sz = sizeof(rcvbuf);
04668                 getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_sz);
04669                 if (a->ai_family == AF_INET6)
04670                     ccnd_setsockopt_v6only(h, fd);
04671                 res = bind(fd, a->ai_addr, a->ai_addrlen);
04672                 if (res != 0) {
04673                     close(fd);
04674                     continue;
04675                 }
04676                 face = record_connection(h, fd,
04677                                          a->ai_addr, a->ai_addrlen,
04678                                          CCN_FACE_DGRAM | CCN_FACE_PASSIVE);
04679                 if (face == NULL) {
04680                     close(fd);
04681                     continue;
04682                 }
04683                 if (a->ai_family == AF_INET)
04684                     h->ipv4_faceid = face->faceid;
04685                 else
04686                     h->ipv6_faceid = face->faceid;
04687                 ccnd_msg(h, "accepting %s datagrams on fd %d rcvbuf %d",
04688                              af_name(a->ai_family), fd, rcvbuf);
04689                 ok++;
04690             }
04691         }
04692         for (a = addrinfo; a != NULL; a = a->ai_next) {
04693             fd = socket(a->ai_family, SOCK_STREAM, 0);
04694             if (fd != -1) {
04695                 int yes = 1;
04696                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04697                 if (a->ai_family == AF_INET6)
04698                     ccnd_setsockopt_v6only(h, fd);
04699                 res = bind(fd, a->ai_addr, a->ai_addrlen);
04700                 if (res != 0) {
04701                     close(fd);
04702                     continue;
04703                 }
04704                 res = listen(fd, 30);
04705                 if (res == -1) {
04706                     close(fd);
04707                     continue;
04708                 }
04709                 record_connection(h, fd,
04710                                   a->ai_addr, a->ai_addrlen,
04711                                   CCN_FACE_PASSIVE);
04712                 ccnd_msg(h, "accepting %s connections on fd %d",
04713                          af_name(a->ai_family), fd);
04714                 ok++;
04715             }
04716         }
04717         freeaddrinfo(addrinfo);
04718     }
04719     return(ok > 0 ? 0 : -1);
04720 }
04721 
04722 static int
04723 ccnd_listen_on(struct ccnd_handle *h, const char *addrs)
04724 {
04725     unsigned char ch;
04726     unsigned char dlm;
04727     int res = 0;
04728     int i;
04729     struct ccn_charbuf *addr = NULL;
04730     
04731     if (addrs == NULL || !*addrs || 0 == strcmp(addrs, "*"))
04732         return(ccnd_listen_on_wildcards(h));
04733     addr = ccn_charbuf_create();
04734     for (i = 0, ch = addrs[i]; addrs[i] != 0;) {
04735         addr->length = 0;
04736         dlm = 0;
04737         if (ch == '[') {
04738             dlm = ']';
04739             ch = addrs[++i];
04740         }
04741         for (; ch > ' ' && ch != ',' && ch != ';' && ch != dlm; ch = addrs[++i])
04742             ccn_charbuf_append_value(addr, ch, 1);
04743         if (ch && ch == dlm)
04744             ch = addrs[++i];
04745         if (addr->length > 0) {
04746             res |= ccnd_listen_on_address(h, ccn_charbuf_as_string(addr));
04747         }
04748         while ((0 < ch && ch <= ' ') || ch == ',' || ch == ';')
04749             ch = addrs[++i];
04750     }
04751     ccn_charbuf_destroy(&addr);
04752     return(res);
04753 }
04754 
04755 static struct ccn_charbuf *
04756 ccnd_parse_uri_list(struct ccnd_handle *h, const char *what, const char *uris)
04757 {
04758     struct ccn_charbuf *ans;
04759     struct ccn_charbuf *name;
04760     int i;
04761     size_t j;
04762     int res;
04763     unsigned char ch;
04764     const char *uri;
04765 
04766     if (uris == NULL)
04767         return(NULL);
04768     ans = ccn_charbuf_create();
04769     name = ccn_charbuf_create();
04770     for (i = 0, ch = uris[0]; ch != 0;) {
04771         while ((0 < ch && ch <= ' ') || ch == ',' || ch == ';')
04772             ch = uris[++i];
04773         j = ans->length;
04774         while (ch > ' ' && ch != ',' && ch != ';') {
04775             ccn_charbuf_append_value(ans, ch, 1);
04776             ch = uris[++i];
04777         }
04778         if (j < ans->length) {
04779             ccn_charbuf_append_value(ans, 0, 1);
04780             uri = (const char *)ans->buf + j;
04781             name->length = 0;
04782             res = ccn_name_from_uri(name, uri);
04783             if (res < 0) {
04784                 ccnd_msg(h, "%s: invalid ccnx URI: %s", what, uri);
04785                 ans->length = j;
04786             }
04787         }
04788     }
04789     ccn_charbuf_destroy(&name);
04790     if (ans->length == 0)
04791         ccn_charbuf_destroy(&ans);
04792     return(ans);
04793 }
04794 
04795 /**
04796  * Start a new ccnd instance
04797  * @param progname - name of program binary, used for locating helpers
04798  * @param logger - logger function
04799  * @param loggerdata - data to pass to logger function
04800  */
04801 struct ccnd_handle *
04802 ccnd_create(const char *progname, ccnd_logger logger, void *loggerdata)
04803 {
04804     char *sockname;
04805     const char *portstr;
04806     const char *debugstr;
04807     const char *entrylimit;
04808     const char *mtu;
04809     const char *data_pause;
04810     const char *autoreg;
04811     const char *listen_on;
04812     int fd;
04813     struct ccnd_handle *h;
04814     struct hashtb_param param = {0};
04815     
04816     sockname = ccnd_get_local_sockname();
04817     h = calloc(1, sizeof(*h));
04818     if (h == NULL)
04819         return(h);
04820     h->logger = logger;
04821     h->loggerdata = loggerdata;
04822     h->appnonce = &ccnd_append_plain_nonce;
04823     h->logpid = (int)getpid();
04824     h->progname = progname;
04825     h->debug = -1;
04826     h->skiplinks = ccn_indexbuf_create();
04827     param.finalize_data = h;
04828     h->face_limit = 1024; /* soft limit */
04829     h->faces_by_faceid = calloc(h->face_limit, sizeof(h->faces_by_faceid[0]));
04830     param.finalize = &finalize_face;
04831     h->faces_by_fd = hashtb_create(sizeof(struct face), &param);
04832     h->dgram_faces = hashtb_create(sizeof(struct face), &param);
04833     param.finalize = &finalize_content;
04834     h->content_tab = hashtb_create(sizeof(struct content_entry), &param);
04835     param.finalize = &finalize_nameprefix;
04836     h->nameprefix_tab = hashtb_create(sizeof(struct nameprefix_entry), &param);
04837     param.finalize = &finalize_propagating;
04838     h->propagating_tab = hashtb_create(sizeof(struct propagating_entry), &param);
04839     param.finalize = 0;
04840     h->sparse_straggler_tab = hashtb_create(sizeof(struct sparse_straggler_entry), NULL);
04841     h->min_stale = ~0;
04842     h->max_stale = 0;
04843     h->unsol = ccn_indexbuf_create();
04844     h->ticktock.descr[0] = 'C';
04845     h->ticktock.micros_per_base = 1000000;
04846     h->ticktock.gettime = &ccnd_gettime;
04847     h->ticktock.data = h;
04848     h->sched = ccn_schedule_create(h, &h->ticktock);
04849     h->starttime = h->sec;
04850     h->starttime_usec = h->usec;
04851     h->oldformatcontentgrumble = 1;
04852     h->oldformatinterestgrumble = 1;
04853     h->data_pause_microsec = 10000;
04854     debugstr = getenv("CCND_DEBUG");
04855     if (debugstr != NULL && debugstr[0] != 0) {
04856         h->debug = atoi(debugstr);
04857         if (h->debug == 0 && debugstr[0] != '0')
04858             h->debug = 1;
04859     }
04860     else
04861         h->debug = 1;
04862     portstr = getenv(CCN_LOCAL_PORT_ENVNAME);
04863     if (portstr == NULL || portstr[0] == 0 || strlen(portstr) > 10)
04864         portstr = CCN_DEFAULT_UNICAST_PORT;
04865     h->portstr = portstr;
04866     entrylimit = getenv("CCND_CAP");
04867     h->capacity = ~0;
04868     if (entrylimit != NULL && entrylimit[0] != 0) {
04869         h->capacity = atol(entrylimit);
04870         if (h->capacity == 0)
04871             h->force_zero_freshness = 1;
04872         if (h->capacity <= 0)
04873             h->capacity = 10;
04874     }
04875     h->mtu = 0;
04876     mtu = getenv("CCND_MTU");
04877     if (mtu != NULL && mtu[0] != 0) {
04878         h->mtu = atol(mtu);
04879         if (h->mtu < 0)
04880             h->mtu = 0;
04881         if (h->mtu > 8800)
04882             h->mtu = 8800;
04883     }
04884     data_pause = getenv("CCND_DATA_PAUSE_MICROSEC");
04885     if (data_pause != NULL && data_pause[0] != 0) {
04886         h->data_pause_microsec = atol(data_pause);
04887         if (h->data_pause_microsec == 0)
04888             h->data_pause_microsec = 1;
04889         if (h->data_pause_microsec > 1000000)
04890             h->data_pause_microsec = 1000000;
04891     }
04892     listen_on = getenv("CCND_LISTEN_ON");
04893     autoreg = getenv("CCND_AUTOREG");
04894     ccnd_msg(h, "CCND_DEBUG=%d CCND_CAP=%lu", h->debug, h->capacity);
04895     if (autoreg != NULL && autoreg[0] != 0) {
04896         h->autoreg = ccnd_parse_uri_list(h, "CCND_AUTOREG", autoreg);
04897         if (h->autoreg != NULL)
04898             ccnd_msg(h, "CCND_AUTOREG=%s", autoreg);
04899     }
04900     if (listen_on != NULL && listen_on[0] != 0)
04901         ccnd_msg(h, "CCND_LISTEN_ON=%s", listen_on);
04902     // if (h->debug & 256)
04903         h->appnonce = &ccnd_append_debug_nonce;
04904     /* Do keystore setup early, it takes a while the first time */
04905     ccnd_init_internal_keystore(h);
04906     ccnd_reseed(h);
04907     if (h->face0 == NULL) {
04908         struct face *face;
04909         face = calloc(1, sizeof(*face));
04910         face->recv_fd = -1;
04911         face->sendface = 0;
04912         face->flags = (CCN_FACE_GG | CCN_FACE_LOCAL);
04913         h->face0 = face;
04914     }
04915     enroll_face(h, h->face0);
04916     fd = create_local_listener(h, sockname, 42);
04917     if (fd == -1)
04918         ccnd_msg(h, "%s: %s", sockname, strerror(errno));
04919     else
04920         ccnd_msg(h, "listening on %s", sockname);
04921     h->flood = (h->autoreg != NULL);
04922     h->ipv4_faceid = h->ipv6_faceid = CCN_NOFACEID;
04923     ccnd_listen_on(h, listen_on);
04924     clean_needed(h);
04925     age_forwarding_needed(h);
04926     ccnd_internal_client_start(h);
04927     free(sockname);
04928     sockname = NULL;
04929     return(h);
04930 }
04931 
04932 /**
04933  * Shutdown listeners and bound datagram sockets, leaving connected streams.
04934  */
04935 static void
04936 ccnd_shutdown_listeners(struct ccnd_handle *h)
04937 {
04938     struct hashtb_enumerator ee;
04939     struct hashtb_enumerator *e = &ee;
04940     for (hashtb_start(h->faces_by_fd, e); e->data != NULL;) {
04941         struct face *face = e->data;
04942         if ((face->flags & (CCN_FACE_MCAST | CCN_FACE_PASSIVE)) != 0)
04943             hashtb_delete(e);
04944         else
04945             hashtb_next(e);
04946     }
04947     hashtb_end(e);
04948 }
04949 
04950 /**
04951  * Destroy the ccnd instance, releasing all associated resources.
04952  */
04953 void
04954 ccnd_destroy(struct ccnd_handle **pccnd)
04955 {
04956     struct ccnd_handle *h = *pccnd;
04957     if (h == NULL)
04958         return;
04959     ccnd_shutdown_listeners(h);
04960     ccnd_internal_client_stop(h);
04961     ccn_schedule_destroy(&h->sched);
04962     hashtb_destroy(&h->dgram_faces);
04963     hashtb_destroy(&h->faces_by_fd);
04964     hashtb_destroy(&h->content_tab);
04965     hashtb_destroy(&h->propagating_tab);
04966     hashtb_destroy(&h->nameprefix_tab);
04967     hashtb_destroy(&h->sparse_straggler_tab);
04968     if (h->fds != NULL) {
04969         free(h->fds);
04970         h->fds = NULL;
04971         h->nfds = 0;
04972     }
04973     if (h->faces_by_faceid != NULL) {
04974         free(h->faces_by_faceid);
04975         h->faces_by_faceid = NULL;
04976         h->face_limit = h->face_gen = 0;
04977     }
04978     if (h->content_by_accession != NULL) {
04979         free(h->content_by_accession);
04980         h->content_by_accession = NULL;
04981         h->content_by_accession_window = 0;
04982     }
04983     ccn_charbuf_destroy(&h->scratch_charbuf);
04984     ccn_charbuf_destroy(&h->autoreg);
04985     ccn_indexbuf_destroy(&h->skiplinks);
04986     ccn_indexbuf_destroy(&h->scratch_indexbuf);
04987     ccn_indexbuf_destroy(&h->unsol);
04988     if (h->face0 != NULL) {
04989         ccn_charbuf_destroy(&h->face0->inbuf);
04990         ccn_charbuf_destroy(&h->face0->outbuf);
04991         free(h->face0);
04992         h->face0 = NULL;
04993     }
04994     free(h);
04995     *pccnd = NULL;
04996 }
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3