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-2012 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              face->recvcount == 0) {
01539         c = charbuf_obtain(h);
01540         ccn_charbuf_append(c, data1, size1);
01541                 if (size2 != 0)
01542             ccn_charbuf_append(c, data2, size2);
01543         ccn_stuff_interest(h, face, c);
01544         ccn_append_link_stuff(h, face, c);
01545     }
01546     else {
01547         /* avoid a copy in this case */
01548         ccnd_send(h, face, data1, size1);
01549         return;
01550     }
01551     ccnd_send(h, face, c->buf, c->length);
01552     charbuf_release(h, c);
01553     return;
01554 }
01555 
01556 /**
01557  * Append a link-check interest if appropriate.
01558  *
01559  * @returns the number of messages that were stuffed.
01560  */
01561 static int
01562 stuff_link_check(struct ccnd_handle *h,
01563                    struct face *face, struct ccn_charbuf *c)
01564 {
01565     int checkflags = CCN_FACE_DGRAM | CCN_FACE_MCAST | CCN_FACE_GG | CCN_FACE_LC;
01566     int wantflags = CCN_FACE_DGRAM;
01567     struct ccn_charbuf *name = NULL;
01568     struct ccn_charbuf *ibuf = NULL;
01569     int res;
01570     int ans = 0;
01571     if (face->recvcount > 0)
01572         return(0);
01573     if ((face->flags & checkflags) != wantflags)
01574         return(0);
01575     name = ccn_charbuf_create();
01576     if (name == NULL) goto Bail;
01577     ccn_name_init(name);
01578     res = ccn_name_from_uri(name, CCNDID_NEIGHBOR_URI);
01579     if (res < 0) goto Bail;
01580     ibuf = ccn_charbuf_create();
01581     if (ibuf == NULL) goto Bail;
01582     ccn_charbuf_append_tt(ibuf, CCN_DTAG_Interest, CCN_DTAG);
01583     ccn_charbuf_append(ibuf, name->buf, name->length);
01584     ccnb_tagged_putf(ibuf, CCN_DTAG_Scope, "2");
01585     // XXX - ought to generate a nonce
01586     ccn_charbuf_append_closer(ibuf);
01587     ccn_charbuf_append(c, ibuf->buf, ibuf->length);
01588     ccnd_meter_bump(h, face->meter[FM_INTO], 1);
01589     h->interests_stuffed++;
01590     face->flags |= CCN_FACE_LC;
01591     if (h->debug & 2)
01592         ccnd_debug_ccnb(h, __LINE__, "stuff_interest_to", face,
01593                         ibuf->buf, ibuf->length);
01594     ans = 1;
01595 Bail:
01596     ccn_charbuf_destroy(&ibuf);
01597     ccn_charbuf_destroy(&name);
01598     return(ans);
01599 }
01600 
01601 /**
01602  * Stuff a PDU with interest messages that will fit.
01603  *
01604  * Note by default stuffing does not happen due to the setting of h->mtu.
01605  * @returns the number of messages that were stuffed.
01606  */
01607 static int
01608 ccn_stuff_interest(struct ccnd_handle *h,
01609                    struct face *face, struct ccn_charbuf *c)
01610 {
01611     struct hashtb_enumerator ee;
01612     struct hashtb_enumerator *e = &ee;
01613     int n_stuffed = 0;
01614     int remaining_space;
01615     if (stuff_link_check(h, face, c) > 0)
01616         n_stuffed++;
01617     remaining_space = h->mtu - c->length;
01618     if (remaining_space < 20 || face == h->face0)
01619         return(0);
01620     for (hashtb_start(h->nameprefix_tab, e);
01621          remaining_space >= 20 && e->data != NULL; hashtb_next(e)) {
01622         struct nameprefix_entry *npe = e->data;
01623         struct propagating_entry *head = &npe->pe_head;
01624         struct propagating_entry *p;
01625         for (p = head->next; p != head; p = p->next) {
01626             if (p->outbound != NULL &&
01627                 p->outbound->n > p->sent &&
01628                 p->size <= remaining_space &&
01629                 p->interest_msg != NULL &&
01630                 ((p->flags & (CCN_PR_STUFFED1 | CCN_PR_WAIT1)) == 0) &&
01631                 ((p->flags & CCN_PR_UNSENT) == 0 ||
01632                  p->outbound->buf[p->sent] == face->faceid) &&
01633                 promote_outbound(p, face->faceid) != -1) {
01634                 remaining_space -= p->size;
01635                 if ((p->flags & CCN_PR_UNSENT) != 0) {
01636                     p->flags &= ~CCN_PR_UNSENT;
01637                     p->flags |= CCN_PR_STUFFED1;
01638                 }
01639                 p->sent++;
01640                 n_stuffed++;
01641                 ccn_charbuf_append(c, p->interest_msg, p->size);
01642                 ccnd_meter_bump(h, face->meter[FM_INTO], 1);
01643                 h->interests_stuffed++;
01644                 if (h->debug & 2)
01645                     ccnd_debug_ccnb(h, __LINE__, "stuff_interest_to", face,
01646                                     p->interest_msg, p->size);
01647                 /*
01648                  * Don't stuff multiple interests with same prefix
01649                  * to avoid subverting attempts at redundancy.
01650                  */
01651                 break;
01652             }
01653         }
01654     }
01655     hashtb_end(e);
01656     return(n_stuffed);
01657 }
01658 
01659 static void
01660 ccn_link_state_init(struct ccnd_handle *h, struct face *face)
01661 {
01662     int checkflags;
01663     int matchflags;
01664     
01665     matchflags = CCN_FACE_DGRAM;
01666     checkflags = matchflags | CCN_FACE_MCAST | CCN_FACE_GG | CCN_FACE_SEQOK | \
01667                  CCN_FACE_PASSIVE;
01668     if ((face->flags & checkflags) != matchflags)
01669         return;
01670     /* Send one sequence number to see if the other side wants to play. */
01671     face->pktseq = nrand48(h->seed);
01672     face->flags |= CCN_FACE_SEQPROBE;
01673 }
01674 
01675 static void
01676 ccn_append_link_stuff(struct ccnd_handle *h,
01677                       struct face *face,
01678                       struct ccn_charbuf *c)
01679 {
01680     if ((face->flags & (CCN_FACE_SEQOK | CCN_FACE_SEQPROBE)) == 0)
01681         return;
01682     ccn_charbuf_append_tt(c, CCN_DTAG_SequenceNumber, CCN_DTAG);
01683     ccn_charbuf_append_tt(c, 2, CCN_BLOB);
01684     ccn_charbuf_append_value(c, face->pktseq, 2);
01685     ccnb_element_end(c);
01686     if (0)
01687         ccnd_msg(h, "debug.%d pkt_to %u seq %u",
01688                  __LINE__, face->faceid, (unsigned)face->pktseq);
01689     face->pktseq++;
01690     face->flags &= ~CCN_FACE_SEQPROBE;
01691 }
01692 
01693 static int
01694 process_incoming_link_message(struct ccnd_handle *h,
01695                               struct face *face, enum ccn_dtag dtag,
01696                               unsigned char *msg, size_t size)
01697 {
01698     uintmax_t s;
01699     int checkflags;
01700     int matchflags;
01701     struct ccn_buf_decoder decoder;
01702     struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
01703 
01704     switch (dtag) {
01705         case CCN_DTAG_SequenceNumber:
01706             s = ccn_parse_required_tagged_binary_number(d, dtag, 1, 6);
01707             if (d->decoder.state < 0)
01708                 return(d->decoder.state);
01709             /*
01710              * If the other side is unicast and sends sequence numbers,
01711              * then it is OK for us to send numbers as well.
01712              */
01713             matchflags = CCN_FACE_DGRAM;
01714             checkflags = matchflags | CCN_FACE_MCAST | CCN_FACE_SEQOK;
01715             if ((face->flags & checkflags) == matchflags)
01716                 face->flags |= CCN_FACE_SEQOK;
01717             if (face->rrun == 0) {
01718                 face->rseq = s;
01719                 face->rrun = 1;
01720                 return(0);
01721             }
01722             if (s == face->rseq + 1) {
01723                 face->rseq = s;
01724                 if (face->rrun < 255)
01725                     face->rrun++;
01726                 return(0);
01727             }
01728             if (s > face->rseq && s - face->rseq < 255) {
01729                 ccnd_msg(h, "seq_gap %u %ju to %ju",
01730                          face->faceid, face->rseq, s);
01731                 face->rseq = s;
01732                 face->rrun = 1;
01733                 return(0);
01734             }
01735             if (s <= face->rseq) {
01736                 if (face->rseq - s < face->rrun) {
01737                     ccnd_msg(h, "seq_dup %u %ju", face->faceid, s);
01738                     return(0);
01739                 }
01740                 if (face->rseq - s < 255) {
01741                     /* Received out of order */
01742                     ccnd_msg(h, "seq_ooo %u %ju", face->faceid, s);
01743                     if (s == face->rseq - face->rrun) {
01744                         face->rrun++;
01745                         return(0);
01746                     }
01747                 }
01748             }
01749             face->rseq = s;
01750             face->rrun = 1;
01751             break;
01752         default:
01753             return(-1);
01754     }
01755     return(0);
01756 }
01757 
01758 /**
01759  * Checks for inactivity on datagram faces.
01760  * @returns number of faces that have gone away.
01761  */
01762 static int
01763 check_dgram_faces(struct ccnd_handle *h)
01764 {
01765     struct hashtb_enumerator ee;
01766     struct hashtb_enumerator *e = &ee;
01767     int count = 0;
01768     int checkflags = CCN_FACE_DGRAM;
01769     int wantflags = CCN_FACE_DGRAM;
01770     
01771     hashtb_start(h->dgram_faces, e);
01772     while (e->data != NULL) {
01773         struct face *face = e->data;
01774         if (face->addr != NULL && (face->flags & checkflags) == wantflags) {
01775             face->flags &= ~CCN_FACE_LC; /* Rate limit link check interests */
01776             if (face->recvcount == 0) {
01777                 if ((face->flags & CCN_FACE_PERMANENT) == 0) {
01778                     count += 1;
01779                     hashtb_delete(e);
01780                     continue;
01781                 }
01782             }
01783             else if (face->recvcount == 1) {
01784                 face->recvcount = 0;
01785             }
01786             else {
01787                 face->recvcount = 1; /* go around twice */
01788             }
01789         }
01790         hashtb_next(e);
01791     }
01792     hashtb_end(e);
01793     return(count);
01794 }
01795 
01796 /**
01797  * Destroys the face identified by faceid.
01798  * @returns 0 for success, -1 for failure.
01799  */
01800 int
01801 ccnd_destroy_face(struct ccnd_handle *h, unsigned faceid)
01802 {
01803     struct hashtb_enumerator ee;
01804     struct hashtb_enumerator *e = &ee;
01805     struct face *face;
01806     int dgram_chk = CCN_FACE_DGRAM | CCN_FACE_MCAST;
01807     int dgram_want = CCN_FACE_DGRAM;
01808     
01809     face = face_from_faceid(h, faceid);
01810     if (face == NULL)
01811         return(-1);
01812     if ((face->flags & dgram_chk) == dgram_want) {
01813         hashtb_start(h->dgram_faces, e);
01814         hashtb_seek(e, face->addr, face->addrlen, 0);
01815         if (e->data == face)
01816             face = NULL;
01817         hashtb_delete(e);
01818         hashtb_end(e);
01819         if (face == NULL)
01820             return(0);
01821     }
01822     shutdown_client_fd(h, face->recv_fd);
01823     face = NULL;
01824     return(0);
01825 }
01826 
01827 /**
01828  * Remove expired faces from npe->forward_to
01829  */
01830 static void
01831 check_forward_to(struct ccnd_handle *h, struct nameprefix_entry *npe)
01832 {
01833     struct ccn_indexbuf *ft = npe->forward_to;
01834     int i;
01835     int j;
01836     if (ft == NULL)
01837         return;
01838     for (i = 0; i < ft->n; i++)
01839         if (face_from_faceid(h, ft->buf[i]) == NULL)
01840             break;
01841     for (j = i + 1; j < ft->n; j++)
01842         if (face_from_faceid(h, ft->buf[j]) != NULL)
01843             ft->buf[i++] = ft->buf[j];
01844     if (i == 0)
01845         ccn_indexbuf_destroy(&npe->forward_to);
01846     else if (i < ft->n)
01847         ft->n = i;
01848 }
01849 
01850 /**
01851  * Check for expired propagating interests.
01852  * @returns number that have gone away.
01853  */
01854 static int
01855 check_propagating(struct ccnd_handle *h)
01856 {
01857     int count = 0;
01858     struct hashtb_enumerator ee;
01859     struct hashtb_enumerator *e = &ee;
01860     struct propagating_entry *pe;
01861     
01862     hashtb_start(h->propagating_tab, e);
01863     for (pe = e->data; pe != NULL; pe = e->data) {
01864         if (pe->interest_msg == NULL) {
01865             if (pe->size == 0) {
01866                 count += 1;
01867                 hashtb_delete(e);
01868                 continue;
01869             }
01870             pe->size = (pe->size > 1); /* go around twice */
01871             /* XXX - could use a flag bit instead of hacking size */
01872         }
01873         hashtb_next(e);
01874     }
01875     hashtb_end(e);
01876     return(count);
01877 }
01878 
01879 /**
01880  * Ages src info and retires unused nameprefix entries.
01881  * @returns number that have gone away.
01882  */
01883 static int
01884 check_nameprefix_entries(struct ccnd_handle *h)
01885 {
01886     int count = 0;
01887     struct hashtb_enumerator ee;
01888     struct hashtb_enumerator *e = &ee;
01889     struct propagating_entry *head;
01890     struct nameprefix_entry *npe;    
01891     
01892     hashtb_start(h->nameprefix_tab, e);
01893     for (npe = e->data; npe != NULL; npe = e->data) {
01894         if (npe->forward_to != NULL)
01895             check_forward_to(h, npe);
01896         if (  npe->src == CCN_NOFACEID &&
01897               npe->children == 0 &&
01898               npe->forwarding == NULL) {
01899             head = &npe->pe_head;
01900             if (head == head->next) {
01901                 count += 1;
01902                 if (npe->parent != NULL) {
01903                     npe->parent->children--;
01904                     npe->parent = NULL;
01905                 }
01906                 hashtb_delete(e);
01907                 continue;
01908             }
01909         }
01910         npe->osrc = npe->src;
01911         npe->src = CCN_NOFACEID;
01912         hashtb_next(e);
01913     }
01914     hashtb_end(e);
01915     return(count);
01916 }
01917 
01918 static void
01919 check_comm_file(struct ccnd_handle *h)
01920 {
01921     if (!comm_file_ok()) {
01922         ccnd_msg(h, "stopping (%s gone)", unlink_this_at_exit);
01923         unlink_this_at_exit = NULL;
01924         h->running = 0;
01925     }
01926 }
01927 
01928 /**
01929  * Scheduled reap event for retiring expired structures.
01930  */
01931 static int
01932 reap(
01933     struct ccn_schedule *sched,
01934     void *clienth,
01935     struct ccn_scheduled_event *ev,
01936     int flags)
01937 {
01938     struct ccnd_handle *h = clienth;
01939     (void)(sched);
01940     (void)(ev);
01941     if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
01942         h->reaper = NULL;
01943         return(0);
01944     }
01945     check_dgram_faces(h);
01946     check_propagating(h);
01947     check_nameprefix_entries(h);
01948     check_comm_file(h);
01949     return(2 * CCN_INTEREST_LIFETIME_MICROSEC);
01950 }
01951 
01952 static void
01953 reap_needed(struct ccnd_handle *h, int init_delay_usec)
01954 {
01955     if (h->reaper == NULL)
01956         h->reaper = ccn_schedule_event(h->sched, init_delay_usec, reap, NULL, 0);
01957 }
01958 
01959 static int
01960 remove_content(struct ccnd_handle *h, struct content_entry *content)
01961 {
01962     struct hashtb_enumerator ee;
01963     struct hashtb_enumerator *e = &ee;
01964     int res;
01965     if (content == NULL)
01966         return(-1);
01967     hashtb_start(h->content_tab, e);
01968     res = hashtb_seek(e, content->key,
01969                       content->key_size, content->size - content->key_size);
01970     if (res != HT_OLD_ENTRY)
01971         abort();
01972     if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0)
01973         h->n_stale--;
01974     if (h->debug & 4)
01975         ccnd_debug_ccnb(h, __LINE__, "remove", NULL,
01976                         content->key, content->size);
01977     hashtb_delete(e);
01978     hashtb_end(e);
01979     return(0);
01980 }
01981 
01982 /**
01983  * Periodic content cleaning
01984  */
01985 static int
01986 clean_deamon(struct ccn_schedule *sched,
01987              void *clienth,
01988              struct ccn_scheduled_event *ev,
01989              int flags)
01990 {
01991     struct ccnd_handle *h = clienth;
01992     (void)(sched);
01993     (void)(ev);
01994     unsigned long n;
01995     ccn_accession_t limit;
01996     ccn_accession_t a;
01997     ccn_accession_t min_stale;
01998     int check_limit = 500;  /* Do not run for too long at once */
01999     struct content_entry *content = NULL;
02000     int res = 0;
02001     int ignore;
02002     int i;
02003     
02004     /*
02005      * If we ran into our processing limit (check_limit) last time,
02006      * ev->evint tells us where to restart.
02007      */
02008     
02009     if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
02010         h->clean = NULL;
02011         return(0);
02012     }
02013     n = hashtb_n(h->content_tab);
02014     if (n <= h->capacity)
02015         return(15000000);
02016     /* Toss unsolicited content first */
02017     for (i = 0; i < h->unsol->n; i++) {
02018         if (i == check_limit) {
02019             for (i = check_limit; i < h->unsol->n; i++)
02020                 h->unsol->buf[i-check_limit] = h->unsol->buf[i];
02021             h->unsol->n -= check_limit;
02022             return(500);
02023         }
02024         a = h->unsol->buf[i];
02025         content = content_from_accession(h, a);
02026         if (content != NULL &&
02027             (content->flags & CCN_CONTENT_ENTRY_PRECIOUS) == 0)
02028             remove_content(h, content);
02029     }
02030     n = hashtb_n(h->content_tab);
02031     h->unsol->n = 0;
02032     if (h->min_stale <= h->max_stale) {
02033         /* clean out stale content next */
02034         limit = h->max_stale;
02035         if (limit > h->accession)
02036             limit = h->accession;
02037         min_stale = ~0;
02038         a = ev->evint;
02039         if (a <= h->min_stale || a > h->max_stale)
02040             a = h->min_stale;
02041         else
02042             min_stale = h->min_stale;
02043         for (; a <= limit && n > h->capacity; a++) {
02044             if (check_limit-- <= 0) {
02045                 ev->evint = a;
02046                 break;
02047             }
02048             content = content_from_accession(h, a);
02049             if (content != NULL &&
02050                   (content->flags & CCN_CONTENT_ENTRY_STALE) != 0) {
02051                 res = remove_content(h, content);
02052                 if (res < 0) {
02053                     if (a < min_stale)
02054                         min_stale = a;
02055                 }
02056                 else {
02057                     content = NULL;
02058                     n -= 1;
02059                 }
02060             }
02061         }
02062         if (min_stale < a)
02063             h->min_stale = min_stale;
02064         else if (a > limit) {
02065             h->min_stale = ~0;
02066             h->max_stale = 0;
02067         }
02068         else
02069             h->min_stale = a;
02070         if (check_limit <= 0)
02071             return(5000);
02072     }
02073     else {
02074         /* Make oldish content stale, for cleanup on next round */
02075         limit = h->accession;
02076         ignore = CCN_CONTENT_ENTRY_STALE | CCN_CONTENT_ENTRY_PRECIOUS;
02077         for (a = h->accession_base; a <= limit && n > h->capacity; a++) {
02078             content = content_from_accession(h, a);
02079             if (content != NULL && (content->flags & ignore) == 0) {
02080                 mark_stale(h, content);
02081                 n--;
02082             }
02083         }
02084         ev->evint = 0;
02085         return(1000000);
02086     }
02087     ev->evint = 0;
02088     return(15000000);
02089 }
02090 
02091 static void
02092 clean_needed(struct ccnd_handle *h)
02093 {
02094     if (h->clean == NULL)
02095         h->clean = ccn_schedule_event(h->sched, 1000000, clean_deamon, NULL, 0);
02096 }
02097 
02098 /**
02099  * Age out the old forwarding table entries
02100  */
02101 static int
02102 age_forwarding(struct ccn_schedule *sched,
02103              void *clienth,
02104              struct ccn_scheduled_event *ev,
02105              int flags)
02106 {
02107     struct ccnd_handle *h = clienth;
02108     struct hashtb_enumerator ee;
02109     struct hashtb_enumerator *e = &ee;
02110     struct ccn_forwarding *f;
02111     struct ccn_forwarding *next;
02112     struct ccn_forwarding **p;
02113     struct nameprefix_entry *npe;
02114     
02115     if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
02116         h->age_forwarding = NULL;
02117         return(0);
02118     }
02119     hashtb_start(h->nameprefix_tab, e);
02120     for (npe = e->data; npe != NULL; npe = e->data) {
02121         p = &npe->forwarding;
02122         for (f = npe->forwarding; f != NULL; f = next) {
02123             next = f->next;
02124             if ((f->flags & CCN_FORW_REFRESHED) == 0 ||
02125                   face_from_faceid(h, f->faceid) == NULL) {
02126                 if (h->debug & 2) {
02127                     struct face *face = face_from_faceid(h, f->faceid);
02128                     if (face != NULL) {
02129                         struct ccn_charbuf *prefix = ccn_charbuf_create();
02130                         ccn_name_init(prefix);
02131                         ccn_name_append_components(prefix, e->key, 0, e->keysize);
02132                         ccnd_debug_ccnb(h, __LINE__, "prefix_expiry", face,
02133                                 prefix->buf,
02134                                 prefix->length);
02135                         ccn_charbuf_destroy(&prefix);
02136                     }
02137                 }
02138                 *p = next;
02139                 free(f);
02140                 f = NULL;
02141                 continue;
02142             }
02143             f->expires -= CCN_FWU_SECS;
02144             if (f->expires <= 0)
02145                 f->flags &= ~CCN_FORW_REFRESHED;
02146             p = &(f->next);
02147         }
02148         hashtb_next(e);
02149     }
02150     hashtb_end(e);
02151     h->forward_to_gen += 1;
02152     return(CCN_FWU_SECS*1000000);
02153 }
02154 
02155 static void
02156 age_forwarding_needed(struct ccnd_handle *h)
02157 {
02158     if (h->age_forwarding == NULL)
02159         h->age_forwarding = ccn_schedule_event(h->sched,
02160                                                CCN_FWU_SECS*1000000,
02161                                                age_forwarding,
02162                                                NULL, 0);
02163 }
02164 
02165 static struct ccn_forwarding *
02166 seek_forwarding(struct ccnd_handle *h,
02167                 struct nameprefix_entry *npe, unsigned faceid)
02168 {
02169     struct ccn_forwarding *f;
02170     
02171     for (f = npe->forwarding; f != NULL; f = f->next)
02172         if (f->faceid == faceid)
02173             return(f);
02174     f = calloc(1, sizeof(*f));
02175     if (f != NULL) {
02176         f->faceid = faceid;
02177         f->flags = (CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE);
02178         f->expires = 0x7FFFFFFF;
02179         f->next = npe->forwarding;
02180         npe->forwarding = f;
02181     }
02182     return(f);
02183 }
02184 
02185 /**
02186  * Register or update a prefix in the forwarding table (FIB).
02187  *
02188  * @param h is the ccnd handle.
02189  * @param msg is a ccnb-encoded message containing the name prefix somewhere.
02190  * @param comps contains the delimiting offsets for the name components in msg.
02191  * @param ncomps is the number of relevant components.
02192  * @param faceid indicates which face to forward to.
02193  * @param flags are the forwarding entry flags (CCN_FORW_...), -1 for defaults.
02194  * @param expires tells the remaining lifetime, in seconds.
02195  * @returns -1 for error, or new flags upon success; the private flag
02196  *        CCN_FORW_REFRESHED indicates a previously existing entry.
02197  */
02198 static int
02199 ccnd_reg_prefix(struct ccnd_handle *h,
02200                 const unsigned char *msg,
02201                 struct ccn_indexbuf *comps,
02202                 int ncomps,
02203                 unsigned faceid,
02204                 int flags,
02205                 int expires)
02206 {
02207     struct hashtb_enumerator ee;
02208     struct hashtb_enumerator *e = &ee;
02209     struct ccn_forwarding *f = NULL;
02210     struct nameprefix_entry *npe = NULL;
02211     int res;
02212     struct face *face = NULL;
02213     
02214     if (flags >= 0 &&
02215         (flags & CCN_FORW_PUBMASK) != flags)
02216         return(-1);
02217     face = face_from_faceid(h, faceid);
02218     if (face == NULL)
02219         return(-1);
02220     /* This is a bit hacky, but it gives us a way to set CCN_FACE_DC */
02221     if (flags >= 0 && (flags & CCN_FORW_LAST) != 0)
02222         face->flags |= CCN_FACE_DC;
02223     hashtb_start(h->nameprefix_tab, e);
02224     res = nameprefix_seek(h, e, msg, comps, ncomps);
02225     if (res >= 0) {
02226         res = (res == HT_OLD_ENTRY) ? CCN_FORW_REFRESHED : 0;
02227         npe = e->data;
02228         f = seek_forwarding(h, npe, faceid);
02229         if (f != NULL) {
02230             h->forward_to_gen += 1; // XXX - too conservative, should check changes
02231             f->expires = expires;
02232             if (flags < 0)
02233                 flags = f->flags & CCN_FORW_PUBMASK;
02234             f->flags = (CCN_FORW_REFRESHED | flags);
02235             res |= flags;
02236             if (h->debug & (2 | 4)) {
02237                 struct ccn_charbuf *prefix = ccn_charbuf_create();
02238                 struct ccn_charbuf *debugtag = ccn_charbuf_create();
02239                 ccn_charbuf_putf(debugtag, "prefix,ff=%s%x",
02240                                  flags > 9 ? "0x" : "", flags);
02241                 if (f->expires < (1 << 30))
02242                     ccn_charbuf_putf(debugtag, ",sec=%d", expires);
02243                 ccn_name_init(prefix);
02244                 ccn_name_append_components(prefix, msg,
02245                                            comps->buf[0], comps->buf[ncomps]);
02246                 ccnd_debug_ccnb(h, __LINE__,
02247                                 ccn_charbuf_as_string(debugtag),
02248                                 face,
02249                                 prefix->buf,
02250                                 prefix->length);
02251                 ccn_charbuf_destroy(&prefix);
02252                 ccn_charbuf_destroy(&debugtag);
02253             }
02254         }
02255         else
02256             res = -1;
02257     }
02258     hashtb_end(e);
02259     return(res);
02260 }
02261 
02262 /**
02263  * Register a prefix, expressed in the form of a URI.
02264  * @returns negative value for error, or new face flags for success.
02265  */
02266 int
02267 ccnd_reg_uri(struct ccnd_handle *h,
02268              const char *uri,
02269              unsigned faceid,
02270              int flags,
02271              int expires)
02272 {
02273     struct ccn_charbuf *name;
02274     struct ccn_buf_decoder decoder;
02275     struct ccn_buf_decoder *d;
02276     struct ccn_indexbuf *comps;
02277     int res;
02278     
02279     name = ccn_charbuf_create();
02280     ccn_name_init(name);
02281     res = ccn_name_from_uri(name, uri);
02282     if (res < 0)
02283         goto Bail;
02284     comps = ccn_indexbuf_create();
02285     d = ccn_buf_decoder_start(&decoder, name->buf, name->length);
02286     res = ccn_parse_Name(d, comps);
02287     if (res < 0)
02288         goto Bail;
02289     res = ccnd_reg_prefix(h, name->buf, comps, comps->n - 1,
02290                           faceid, flags, expires);
02291 Bail:
02292     ccn_charbuf_destroy(&name);
02293     ccn_indexbuf_destroy(&comps);
02294     return(res);
02295 }
02296 
02297 /**
02298  * Register prefixes, expressed in the form of a list of URIs.
02299  * The URIs in the charbuf are each terminated by nul.
02300  */
02301 void
02302 ccnd_reg_uri_list(struct ccnd_handle *h,
02303              struct ccn_charbuf *uris,
02304              unsigned faceid,
02305              int flags,
02306              int expires)
02307 {
02308     size_t i;
02309     const char *s;
02310     s = ccn_charbuf_as_string(uris);
02311     for (i = 0; i + 1 < uris->length; i += strlen(s + i) + 1)
02312         ccnd_reg_uri(h, s + i, faceid, flags, expires);
02313 }
02314 
02315 /**
02316  * Called when a face is first created, and (perhaps) a second time in the case
02317  * that a face transitions from the undecided state.
02318  */
02319 static void
02320 register_new_face(struct ccnd_handle *h, struct face *face)
02321 {
02322     if (face->faceid != 0 && (face->flags & (CCN_FACE_UNDECIDED | CCN_FACE_PASSIVE)) == 0) {
02323         ccnd_face_status_change(h, face->faceid);
02324         if (h->flood && h->autoreg != NULL && (face->flags & CCN_FACE_GG) == 0)
02325             ccnd_reg_uri_list(h, h->autoreg, face->faceid,
02326                               CCN_FORW_CAPTURE_OK | CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE,
02327                               0x7FFFFFFF);
02328         ccn_link_state_init(h, face);
02329     }
02330 }
02331 
02332 /**
02333  * Replaces contents of reply_body with a ccnb-encoded StatusResponse.
02334  *
02335  * @returns CCN_CONTENT_NACK, or -1 in case of error.
02336  */
02337 static int
02338 ccnd_nack(struct ccnd_handle *h, struct ccn_charbuf *reply_body,
02339           int errcode, const char *errtext)
02340 {
02341     int res;
02342     reply_body->length = 0;
02343     res = ccn_encode_StatusResponse(reply_body, errcode, errtext);
02344     if (res == 0)
02345         res = CCN_CONTENT_NACK;
02346     return(res);
02347 }
02348 
02349 /**
02350  * Check that indicated ccndid matches ours.
02351  *
02352  * @returns 0 if OK, or CCN_CONTENT_NACK if not.
02353  */
02354 static int
02355 check_ccndid(struct ccnd_handle *h,
02356              const void *p, size_t sz, struct ccn_charbuf *reply_body)
02357 {
02358     if (sz != sizeof(h->ccnd_id) || memcmp(p, h->ccnd_id, sz) != 0)
02359         return(ccnd_nack(h, reply_body, 531, "missing or incorrect ccndid"));
02360     return(0);
02361 }
02362 
02363 static int
02364 check_face_instance_ccndid(struct ccnd_handle *h,
02365     struct ccn_face_instance *f, struct ccn_charbuf *reply_body)
02366 {
02367     return(check_ccndid(h, f->ccnd_id, f->ccnd_id_size, reply_body));
02368 }
02369 
02370 static int
02371 check_forwarding_entry_ccndid(struct ccnd_handle *h,
02372     struct ccn_forwarding_entry *f, struct ccn_charbuf *reply_body)
02373 {
02374     return(check_ccndid(h, f->ccnd_id, f->ccnd_id_size, reply_body));
02375 }
02376 
02377 /**
02378  * Process a newface request for the ccnd internal client.
02379  *
02380  * @param h is the ccnd handle
02381  * @param msg points to a ccnd-encoded ContentObject containing a
02382  *         FaceInstance in its Content.
02383  * @param size is its size in bytes
02384  * @param reply_body is a buffer to hold the Content of the reply, as a
02385  *         FaceInstance including faceid
02386  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02387  *         set the response type to NACK.
02388  *
02389  * Is is permitted for the face to already exist.
02390  * A newly created face will have no registered prefixes, and so will not
02391  * receive any traffic.
02392  */
02393 int
02394 ccnd_req_newface(struct ccnd_handle *h,
02395                  const unsigned char *msg, size_t size,
02396                  struct ccn_charbuf *reply_body)
02397 {
02398     struct ccn_parsed_ContentObject pco = {0};
02399     int res;
02400     const unsigned char *req;
02401     size_t req_size;
02402     struct ccn_face_instance *face_instance = NULL;
02403     struct addrinfo hints = {0};
02404     struct addrinfo *addrinfo = NULL;
02405     int mcast;
02406     struct face *face = NULL;
02407     struct face *reqface = NULL;
02408     struct face *newface = NULL;
02409     int save;
02410     int nackallowed = 0;
02411 
02412     save = h->flood;
02413     h->flood = 0; /* never auto-register for these */
02414     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02415     if (res < 0)
02416         goto Finish;
02417     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02418     if (res < 0)
02419         goto Finish;
02420     res = -1;
02421     face_instance = ccn_face_instance_parse(req, req_size);
02422     if (face_instance == NULL || face_instance->action == NULL)
02423         goto Finish;
02424     if (strcmp(face_instance->action, "newface") != 0)
02425         goto Finish;
02426     /* consider the source ... */
02427     reqface = face_from_faceid(h, h->interest_faceid);
02428     if (reqface == NULL ||
02429         (reqface->flags & (CCN_FACE_LOOPBACK | CCN_FACE_LOCAL)) == 0)
02430         goto Finish;
02431     nackallowed = 1;
02432     res = check_face_instance_ccndid(h, face_instance, reply_body);
02433     if (res != 0)
02434         goto Finish;
02435     if (face_instance->descr.ipproto != IPPROTO_UDP &&
02436         face_instance->descr.ipproto != IPPROTO_TCP) {
02437         res = ccnd_nack(h, reply_body, 504, "parameter error");
02438         goto Finish;
02439     }
02440     if (face_instance->descr.address == NULL) {
02441         res = ccnd_nack(h, reply_body, 504, "parameter error");
02442         goto Finish;
02443     }
02444     if (face_instance->descr.port == NULL) {
02445         res = ccnd_nack(h, reply_body, 504, "parameter error");
02446         goto Finish;
02447     }
02448     if ((reqface->flags & CCN_FACE_GG) == 0) {
02449         res = ccnd_nack(h, reply_body, 430, "not authorized");
02450         goto Finish;
02451     }
02452     hints.ai_flags |= AI_NUMERICHOST;
02453     hints.ai_protocol = face_instance->descr.ipproto;
02454     hints.ai_socktype = (hints.ai_protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
02455     res = getaddrinfo(face_instance->descr.address,
02456                       face_instance->descr.port,
02457                       &hints,
02458                       &addrinfo);
02459     if (res != 0 || (h->debug & 128) != 0)
02460         ccnd_msg(h, "ccnd_req_newface from %u: getaddrinfo(%s, %s, ...) returned %d",
02461                  h->interest_faceid,
02462                  face_instance->descr.address,
02463                  face_instance->descr.port,
02464                  res);
02465     if (res != 0 || addrinfo == NULL) {
02466         res = ccnd_nack(h, reply_body, 501, "syntax error in address");
02467         goto Finish;
02468     }
02469     if (addrinfo->ai_next != NULL)
02470         ccnd_msg(h, "ccnd_req_newface: (addrinfo->ai_next != NULL) ? ?");
02471     if (face_instance->descr.ipproto == IPPROTO_UDP) {
02472         mcast = 0;
02473         if (addrinfo->ai_family == AF_INET) {
02474             face = face_from_faceid(h, h->ipv4_faceid);
02475             mcast = IN_MULTICAST(ntohl(((struct sockaddr_in *)(addrinfo->ai_addr))->sin_addr.s_addr));
02476         }
02477         else if (addrinfo->ai_family == AF_INET6) {
02478             face = face_from_faceid(h, h->ipv6_faceid);
02479             mcast = IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_addr);
02480         }
02481         if (mcast)
02482             face = setup_multicast(h, face_instance,
02483                                    addrinfo->ai_addr,
02484                                    addrinfo->ai_addrlen);
02485         if (face == NULL) {
02486             res = ccnd_nack(h, reply_body, 453, "could not setup multicast");
02487             goto Finish;
02488         }
02489         newface = get_dgram_source(h, face,
02490                                    addrinfo->ai_addr,
02491                                    addrinfo->ai_addrlen,
02492                                    0);
02493     }
02494     else if (addrinfo->ai_socktype == SOCK_STREAM) {
02495         newface = make_connection(h,
02496                                   addrinfo->ai_addr,
02497                                   addrinfo->ai_addrlen,
02498                                   0);
02499     }
02500     if (newface != NULL) {
02501         newface->flags |= CCN_FACE_PERMANENT;
02502         face_instance->action = NULL;
02503         face_instance->ccnd_id = h->ccnd_id;
02504         face_instance->ccnd_id_size = sizeof(h->ccnd_id);
02505         face_instance->faceid = newface->faceid;
02506         face_instance->lifetime = 0x7FFFFFFF;
02507         /*
02508          * A short lifetime is a clue to the client that
02509          * the connection has not been completed.
02510          */
02511         if ((newface->flags & CCN_FACE_CONNECTING) != 0)
02512             face_instance->lifetime = 1;
02513         res = ccnb_append_face_instance(reply_body, face_instance);
02514         if (res > 0)
02515             res = 0;
02516     }
02517     else
02518         res = ccnd_nack(h, reply_body, 450, "could not create face");
02519 Finish:
02520     h->flood = save; /* restore saved flood flag */
02521     ccn_face_instance_destroy(&face_instance);
02522     if (addrinfo != NULL)
02523         freeaddrinfo(addrinfo);
02524     return((nackallowed || res <= 0) ? res : -1);
02525 }
02526 
02527 /**
02528  * @brief Process a destroyface request for the ccnd internal client.
02529  * @param h is the ccnd handle
02530  * @param msg points to a ccnd-encoded ContentObject containing a FaceInstance
02531             in its Content.
02532  * @param size is its size in bytes
02533  * @param reply_body is a buffer to hold the Content of the reply, as a
02534  *         FaceInstance including faceid
02535  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02536  *         set the response type to NACK.
02537  *
02538  * Is is an error if the face does not exist.
02539  */
02540 int
02541 ccnd_req_destroyface(struct ccnd_handle *h,
02542                      const unsigned char *msg, size_t size,
02543                      struct ccn_charbuf *reply_body)
02544 {
02545     struct ccn_parsed_ContentObject pco = {0};
02546     int res;
02547     int at = 0;
02548     const unsigned char *req;
02549     size_t req_size;
02550     struct ccn_face_instance *face_instance = NULL;
02551     struct face *reqface = NULL;
02552     int nackallowed = 0;
02553 
02554     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02555     if (res < 0) { at = __LINE__; goto Finish; }
02556     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02557     if (res < 0) { at = __LINE__; goto Finish; }
02558     res = -1;
02559     face_instance = ccn_face_instance_parse(req, req_size);
02560     if (face_instance == NULL) { at = __LINE__; goto Finish; }
02561     if (face_instance->action == NULL) { at = __LINE__; goto Finish; }
02562     /* consider the source ... */
02563     reqface = face_from_faceid(h, h->interest_faceid);
02564     if (reqface == NULL) { at = __LINE__; goto Finish; }
02565     if ((reqface->flags & CCN_FACE_GG) == 0) { at = __LINE__; goto Finish; }
02566     nackallowed = 1;
02567     if (strcmp(face_instance->action, "destroyface") != 0)
02568         { at = __LINE__; goto Finish; }
02569     res = check_face_instance_ccndid(h, face_instance, reply_body);
02570     if (res != 0)
02571         { at = __LINE__; goto Finish; }
02572     if (face_instance->faceid == 0) { at = __LINE__; goto Finish; }
02573     res = ccnd_destroy_face(h, face_instance->faceid);
02574     if (res < 0) { at = __LINE__; goto Finish; }
02575     face_instance->action = NULL;
02576     face_instance->ccnd_id = h->ccnd_id;
02577     face_instance->ccnd_id_size = sizeof(h->ccnd_id);
02578     face_instance->lifetime = 0;
02579     res = ccnb_append_face_instance(reply_body, face_instance);
02580     if (res < 0) {
02581         at = __LINE__;
02582     }
02583 Finish:
02584     if (at != 0) {
02585         ccnd_msg(h, "ccnd_req_destroyface failed (line %d, res %d)", at, res);
02586         if (reqface == NULL || (reqface->flags & CCN_FACE_GG) == 0)
02587             res = -1;
02588         else
02589             res = ccnd_nack(h, reply_body, 450, "could not destroy face");
02590     }
02591     ccn_face_instance_destroy(&face_instance);
02592     return((nackallowed || res <= 0) ? res : -1);
02593 }
02594 
02595 /**
02596  * Worker bee for two very similar public functions.
02597  */
02598 static int
02599 ccnd_req_prefix_or_self_reg(struct ccnd_handle *h,
02600                             const unsigned char *msg, size_t size, int selfreg,
02601                             struct ccn_charbuf *reply_body)
02602 {
02603     struct ccn_parsed_ContentObject pco = {0};
02604     int res;
02605     const unsigned char *req;
02606     size_t req_size;
02607     struct ccn_forwarding_entry *forwarding_entry = NULL;
02608     struct face *face = NULL;
02609     struct face *reqface = NULL;
02610     struct ccn_indexbuf *comps = NULL;
02611     int nackallowed = 0;
02612 
02613     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02614     if (res < 0)
02615         goto Finish;
02616     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02617     if (res < 0)
02618         goto Finish;
02619     res = -1;
02620     forwarding_entry = ccn_forwarding_entry_parse(req, req_size);
02621     if (forwarding_entry == NULL || forwarding_entry->action == NULL)
02622         goto Finish;
02623     /* consider the source ... */
02624     reqface = face_from_faceid(h, h->interest_faceid);
02625     if (reqface == NULL)
02626         goto Finish;
02627     if ((reqface->flags & (CCN_FACE_GG | CCN_FACE_REGOK)) == 0)
02628         goto Finish;
02629     nackallowed = 1;
02630     if (selfreg) {
02631         if (strcmp(forwarding_entry->action, "selfreg") != 0)
02632             goto Finish;
02633         if (forwarding_entry->faceid == CCN_NOFACEID)
02634             forwarding_entry->faceid = h->interest_faceid;
02635         else if (forwarding_entry->faceid != h->interest_faceid)
02636             goto Finish;
02637     }
02638     else {
02639         if (strcmp(forwarding_entry->action, "prefixreg") != 0)
02640         goto Finish;
02641     }
02642     if (forwarding_entry->name_prefix == NULL)
02643         goto Finish;
02644     if (forwarding_entry->ccnd_id_size == sizeof(h->ccnd_id)) {
02645         if (memcmp(forwarding_entry->ccnd_id,
02646                    h->ccnd_id, sizeof(h->ccnd_id)) != 0)
02647             goto Finish;
02648     }
02649     else if (forwarding_entry->ccnd_id_size != 0)
02650         goto Finish;
02651     face = face_from_faceid(h, forwarding_entry->faceid);
02652     if (face == NULL)
02653         goto Finish;
02654     if (forwarding_entry->lifetime < 0)
02655         forwarding_entry->lifetime = 2000000000;
02656     else if (forwarding_entry->lifetime > 3600 &&
02657              forwarding_entry->lifetime < (1 << 30))
02658         forwarding_entry->lifetime = 300;
02659     comps = ccn_indexbuf_create();
02660     res = ccn_name_split(forwarding_entry->name_prefix, comps);
02661     if (res < 0)
02662         goto Finish;
02663     res = ccnd_reg_prefix(h,
02664                           forwarding_entry->name_prefix->buf, comps, res,
02665                           face->faceid,
02666                           forwarding_entry->flags,
02667                           forwarding_entry->lifetime);
02668     if (res < 0)
02669         goto Finish;
02670     forwarding_entry->flags = res;
02671     forwarding_entry->action = NULL;
02672     forwarding_entry->ccnd_id = h->ccnd_id;
02673     forwarding_entry->ccnd_id_size = sizeof(h->ccnd_id);
02674     res = ccnb_append_forwarding_entry(reply_body, forwarding_entry);
02675     if (res > 0)
02676         res = 0;
02677 Finish:
02678     ccn_forwarding_entry_destroy(&forwarding_entry);
02679     ccn_indexbuf_destroy(&comps);
02680     if (nackallowed && res < 0)
02681         res = ccnd_nack(h, reply_body, 450, "could not register prefix");
02682     return((nackallowed || res <= 0) ? res : -1);
02683 }
02684 
02685 /**
02686  * @brief Process a prefixreg request for the ccnd internal client.
02687  * @param h is the ccnd handle
02688  * @param msg points to a ccnd-encoded ContentObject containing a
02689  *          ForwardingEntry in its Content.
02690  * @param size is its size in bytes
02691  * @param reply_body is a buffer to hold the Content of the reply, as a
02692  *         FaceInstance including faceid
02693  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02694  *         set the response type to NACK.
02695  *
02696  */
02697 int
02698 ccnd_req_prefixreg(struct ccnd_handle *h,
02699                    const unsigned char *msg, size_t size,
02700                    struct ccn_charbuf *reply_body)
02701 {
02702     return(ccnd_req_prefix_or_self_reg(h, msg, size, 0, reply_body));
02703 }
02704 
02705 /**
02706  * @brief Process a selfreg request for the ccnd internal client.
02707  * @param h is the ccnd handle
02708  * @param msg points to a ccnd-encoded ContentObject containing a
02709  *          ForwardingEntry in its Content.
02710  * @param size is its size in bytes
02711  * @param reply_body is a buffer to hold the Content of the reply, as a
02712  *         ccnb-encoded ForwardingEntry
02713  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02714  *         set the response type to NACK.
02715  *
02716  */
02717 int
02718 ccnd_req_selfreg(struct ccnd_handle *h,
02719                  const unsigned char *msg, size_t size,
02720                  struct ccn_charbuf *reply_body)
02721 {
02722     return(ccnd_req_prefix_or_self_reg(h, msg, size, 1, reply_body));
02723 }
02724 
02725 /**
02726  * @brief Process an unreg request for the ccnd internal client.
02727  * @param h is the ccnd handle
02728  * @param msg points to a ccnd-encoded ContentObject containing a
02729  *          ForwardingEntry in its Content.
02730  * @param size is its size in bytes
02731  * @param reply_body is a buffer to hold the Content of the reply, as a
02732  *         ccnb-encoded ForwardingEntry
02733  * @returns 0 for success, negative for no response, or CCN_CONTENT_NACK to
02734  *         set the response type to NACK.
02735  *
02736  */
02737 int
02738 ccnd_req_unreg(struct ccnd_handle *h,
02739                const unsigned char *msg, size_t size,
02740                struct ccn_charbuf *reply_body)
02741 {
02742     struct ccn_parsed_ContentObject pco = {0};
02743     int n_name_comp = 0;
02744     int res;
02745     const unsigned char *req;
02746     size_t req_size;
02747     size_t start;
02748     size_t stop;
02749     int found;
02750     struct ccn_forwarding_entry *forwarding_entry = NULL;
02751     struct face *face = NULL;
02752     struct face *reqface = NULL;
02753     struct ccn_indexbuf *comps = NULL;
02754     struct ccn_forwarding **p = NULL;
02755     struct ccn_forwarding *f = NULL;
02756     struct nameprefix_entry *npe = NULL;
02757     int nackallowed = 0;
02758     
02759     res = ccn_parse_ContentObject(msg, size, &pco, NULL);
02760     if (res < 0)
02761         goto Finish;        
02762     res = ccn_content_get_value(msg, size, &pco, &req, &req_size);
02763     if (res < 0)
02764         goto Finish;
02765     res = -1;
02766     forwarding_entry = ccn_forwarding_entry_parse(req, req_size);
02767     /* consider the source ... */
02768     reqface = face_from_faceid(h, h->interest_faceid);
02769     if (reqface == NULL || (reqface->flags & CCN_FACE_GG) == 0)
02770         goto Finish;
02771     nackallowed = 1;
02772     if (forwarding_entry == NULL || forwarding_entry->action == NULL)
02773         goto Finish;
02774     if (strcmp(forwarding_entry->action, "unreg") != 0)
02775         goto Finish;
02776     if (forwarding_entry->faceid == CCN_NOFACEID)
02777         goto Finish;
02778     if (forwarding_entry->name_prefix == NULL)
02779         goto Finish;
02780     res = check_forwarding_entry_ccndid(h, forwarding_entry, reply_body);
02781     if (res != 0)
02782         goto Finish;
02783     res = -1;
02784     face = face_from_faceid(h, forwarding_entry->faceid);
02785     if (face == NULL)
02786         goto Finish;
02787     comps = ccn_indexbuf_create();
02788     n_name_comp = ccn_name_split(forwarding_entry->name_prefix, comps);
02789     if (n_name_comp < 0)
02790         goto Finish;
02791     if (n_name_comp + 1 > comps->n)
02792         goto Finish;
02793     start = comps->buf[0];
02794     stop = comps->buf[n_name_comp];
02795     npe = hashtb_lookup(h->nameprefix_tab,
02796                         forwarding_entry->name_prefix->buf + start,
02797                         stop - start);
02798     if (npe == NULL)
02799         goto Finish;
02800     found = 0;
02801     p = &npe->forwarding;
02802     for (f = npe->forwarding; f != NULL; f = f->next) {
02803         if (f->faceid == forwarding_entry->faceid) {
02804             found = 1;
02805             if (h->debug & (2 | 4))
02806                 ccnd_debug_ccnb(h, __LINE__, "prefix_unreg", face,
02807                                 forwarding_entry->name_prefix->buf,
02808                                 forwarding_entry->name_prefix->length);
02809             *p = f->next;
02810             free(f);
02811             f = NULL;
02812             h->forward_to_gen += 1;
02813             break;
02814         }
02815         p = &(f->next);
02816     }
02817     if (!found)
02818         goto Finish;    
02819     forwarding_entry->action = NULL;
02820     forwarding_entry->ccnd_id = h->ccnd_id;
02821     forwarding_entry->ccnd_id_size = sizeof(h->ccnd_id);
02822     res = ccnb_append_forwarding_entry(reply_body, forwarding_entry);
02823     if (res > 0)
02824         res = 0;
02825 Finish:
02826     ccn_forwarding_entry_destroy(&forwarding_entry);
02827     ccn_indexbuf_destroy(&comps);
02828     if (nackallowed && res < 0)
02829         res = ccnd_nack(h, reply_body, 450, "could not unregister prefix");
02830     return((nackallowed || res <= 0) ? res : -1);
02831 }
02832 
02833 /**
02834  * Recompute the contents of npe->forward_to and npe->flags
02835  * from forwarding lists of npe and all of its ancestors.
02836  */
02837 static void
02838 update_forward_to(struct ccnd_handle *h, struct nameprefix_entry *npe)
02839 {
02840     struct ccn_indexbuf *x = NULL;
02841     struct ccn_indexbuf *tap = NULL;
02842     struct ccn_forwarding *f = NULL;
02843     struct nameprefix_entry *p = NULL;
02844     unsigned tflags;
02845     unsigned wantflags;
02846     unsigned moreflags;
02847     unsigned lastfaceid;
02848     unsigned namespace_flags;
02849 
02850     x = npe->forward_to;
02851     if (x == NULL)
02852         npe->forward_to = x = ccn_indexbuf_create();
02853     else
02854         x->n = 0;
02855     wantflags = CCN_FORW_ACTIVE;
02856     lastfaceid = CCN_NOFACEID;
02857     namespace_flags = 0;
02858     for (p = npe; p != NULL; p = p->parent) {
02859         moreflags = CCN_FORW_CHILD_INHERIT;
02860         for (f = p->forwarding; f != NULL; f = f->next) {
02861             if (face_from_faceid(h, f->faceid) == NULL)
02862                 continue;
02863             /* The sense of this flag needs to be inverted for this test */
02864             tflags = f->flags ^ CCN_FORW_CAPTURE_OK;
02865             if ((tflags & wantflags) == wantflags) {
02866                 if (h->debug & 32)
02867                     ccnd_msg(h, "fwd.%d adding %u", __LINE__, f->faceid);
02868                 ccn_indexbuf_set_insert(x, f->faceid);
02869                 if ((f->flags & CCN_FORW_TAP) != 0) {
02870                     if (tap == NULL)
02871                         tap = ccn_indexbuf_create();
02872                     ccn_indexbuf_set_insert(tap, f->faceid);
02873                 }
02874                 if ((f->flags & CCN_FORW_LAST) != 0)
02875                     lastfaceid = f->faceid;
02876             }
02877             namespace_flags |= f->flags;
02878             if ((f->flags & CCN_FORW_CAPTURE) != 0)
02879                 moreflags |= CCN_FORW_CAPTURE_OK;
02880         }
02881         wantflags |= moreflags;
02882     }
02883     if (lastfaceid != CCN_NOFACEID)
02884         ccn_indexbuf_move_to_end(x, lastfaceid);
02885     npe->flags = namespace_flags;
02886     npe->fgen = h->forward_to_gen;
02887     if (x->n == 0)
02888         ccn_indexbuf_destroy(&npe->forward_to);
02889     ccn_indexbuf_destroy(&npe->tap);
02890     npe->tap = tap;
02891 }
02892 
02893 /**
02894  * This is where we consult the interest forwarding table.
02895  * @param h is the ccnd handle
02896  * @param from is the handle for the originating face (may be NULL).
02897  * @param msg points to the ccnb-encoded interest message
02898  * @param pi must be the parse information for msg
02899  * @param npe should be the result of the prefix lookup
02900  * @result Newly allocated set of outgoing faceids (never NULL)
02901  */
02902 static struct ccn_indexbuf *
02903 get_outbound_faces(struct ccnd_handle *h,
02904     struct face *from,
02905     unsigned char *msg,
02906     struct ccn_parsed_interest *pi,
02907     struct nameprefix_entry *npe)
02908 {
02909     int checkmask = 0;
02910     int wantmask = 0;
02911     struct ccn_indexbuf *x;
02912     struct face *face;
02913     int i;
02914     int n;
02915     unsigned faceid;
02916     
02917     while (npe->parent != NULL && npe->forwarding == NULL)
02918         npe = npe->parent;
02919     if (npe->fgen != h->forward_to_gen)
02920         update_forward_to(h, npe);
02921     x = ccn_indexbuf_create();
02922     if (pi->scope == 0 || npe->forward_to == NULL || npe->forward_to->n == 0)
02923         return(x);
02924     if ((npe->flags & CCN_FORW_LOCAL) != 0)
02925         checkmask = (from != NULL && (from->flags & CCN_FACE_GG) != 0) ? CCN_FACE_GG : (~0);
02926     else if (pi->scope == 1)
02927         checkmask = CCN_FACE_GG;
02928     else if (pi->scope == 2)
02929         checkmask = from ? (CCN_FACE_GG & ~(from->flags)) : ~0;
02930     wantmask = checkmask;
02931     if (wantmask == CCN_FACE_GG)
02932         checkmask |= CCN_FACE_DC;
02933     for (n = npe->forward_to->n, i = 0; i < n; i++) {
02934         faceid = npe->forward_to->buf[i];
02935         face = face_from_faceid(h, faceid);
02936         if (face != NULL && face != from &&
02937             ((face->flags & checkmask) == wantmask)) {
02938             if (h->debug & 32)
02939                 ccnd_msg(h, "outbound.%d adding %u", __LINE__, face->faceid);
02940             ccn_indexbuf_append_element(x, face->faceid);
02941         }
02942     }
02943     return(x);
02944 }
02945 
02946 static int
02947 pe_next_usec(struct ccnd_handle *h,
02948              struct propagating_entry *pe, int next_delay, int lineno)
02949 {
02950     if (next_delay > pe->usec)
02951         next_delay = pe->usec;
02952     pe->usec -= next_delay;
02953     if (h->debug & 32) {
02954         struct ccn_charbuf *c = ccn_charbuf_create();
02955         ccn_charbuf_putf(c, "%p.%dof%d,usec=%d+%d",
02956                          (void *)pe,
02957                          pe->sent,
02958                          pe->outbound ? pe->outbound->n : -1,
02959                          next_delay, pe->usec);
02960         if (pe->interest_msg != NULL) {
02961             ccnd_debug_ccnb(h, lineno, ccn_charbuf_as_string(c),
02962                             face_from_faceid(h, pe->faceid),
02963                             pe->interest_msg, pe->size);
02964         }
02965         ccn_charbuf_destroy(&c);
02966     }
02967     return(next_delay);
02968 }
02969 
02970 static void replan_propagation(struct ccnd_handle *, struct propagating_entry *);
02971 
02972 static int
02973 do_propagate(struct ccn_schedule *sched,
02974              void *clienth,
02975              struct ccn_scheduled_event *ev,
02976              int flags)
02977 {
02978     struct ccnd_handle *h = clienth;
02979     struct propagating_entry *pe = ev->evdata;
02980     (void)(sched);
02981     int next_delay = 1;
02982     int special_delay = 0;
02983     if (pe->interest_msg == NULL)
02984         return(0);
02985     if (flags & CCN_SCHEDULE_CANCEL) {
02986         consume(h, pe);
02987         return(0);
02988     }
02989     if ((pe->flags & CCN_PR_WAIT1) != 0) {
02990         pe->flags &= ~CCN_PR_WAIT1;
02991         adjust_predicted_response(h, pe, 1);
02992     }
02993     if (pe->usec <= 0) {
02994         if (h->debug & 2)
02995             ccnd_debug_ccnb(h, __LINE__, "interest_expiry",
02996                             face_from_faceid(h, pe->faceid),
02997                             pe->interest_msg, pe->size);
02998         consume(h, pe);
02999         reap_needed(h, 0);
03000         return(0);        
03001     }
03002     if ((pe->flags & CCN_PR_STUFFED1) != 0) {
03003         pe->flags &= ~CCN_PR_STUFFED1;
03004         pe->flags |= CCN_PR_WAIT1;
03005         next_delay = special_delay = ev->evint;
03006     }
03007     else if (pe->outbound != NULL && pe->sent < pe->outbound->n) {
03008         unsigned faceid = pe->outbound->buf[pe->sent];
03009         struct face *face = face_from_faceid(h, faceid);
03010         if (face != NULL && (face->flags & CCN_FACE_NOSEND) == 0) {
03011             if (h->debug & 2)
03012                 ccnd_debug_ccnb(h, __LINE__, "interest_to", face,
03013                                 pe->interest_msg, pe->size);
03014             pe->sent++;
03015             h->interests_sent += 1;
03016             h->interest_faceid = pe->faceid;
03017             next_delay = nrand48(h->seed) % 8192 + 500;
03018             if (((pe->flags & CCN_PR_TAP) != 0) &&
03019                   ccn_indexbuf_member(nameprefix_for_pe(h, pe)->tap, pe->faceid)) {
03020                 next_delay = special_delay = 1;
03021             }
03022             else if ((pe->flags & CCN_PR_UNSENT) != 0) {
03023                 pe->flags &= ~CCN_PR_UNSENT;
03024                 pe->flags |= CCN_PR_WAIT1;
03025                 next_delay = special_delay = ev->evint;
03026             }
03027             stuff_and_send(h, face, pe->interest_msg, pe->size, NULL, 0);
03028             ccnd_meter_bump(h, face->meter[FM_INTO], 1);
03029         }
03030         else
03031             ccn_indexbuf_remove_first_match(pe->outbound, faceid);
03032     }
03033     /* The internal client may have already consumed the interest */
03034     if (pe->outbound == NULL)
03035         next_delay = CCN_INTEREST_LIFETIME_MICROSEC;
03036     else if (pe->sent == pe->outbound->n) {
03037         if (pe->usec <= CCN_INTEREST_LIFETIME_MICROSEC / 4)
03038             next_delay = CCN_INTEREST_LIFETIME_MICROSEC;
03039         else if (special_delay == 0)
03040             next_delay = CCN_INTEREST_LIFETIME_MICROSEC / 16;
03041         if (pe->fgen != h->forward_to_gen)
03042             replan_propagation(h, pe);
03043     }
03044     else {
03045         unsigned faceid = pe->outbound->buf[pe->sent];
03046         struct face *face = face_from_faceid(h, faceid);
03047         /* Wait longer before sending interest to ccndc */
03048         if (face != NULL && (face->flags & CCN_FACE_DC) != 0)
03049             next_delay += 60000;
03050     }
03051     next_delay = pe_next_usec(h, pe, next_delay, __LINE__);
03052     return(next_delay);
03053 }
03054 
03055 /**
03056  * Adjust the outbound face list for a new Interest, based upon
03057  * existing similar interests.
03058  * @result besides possibly updating the outbound set, returns
03059  *         an extra delay time before propagation.  A negative return value
03060  *         indicates the interest should be dropped.
03061  */
03062 // XXX - rearrange to allow dummied-up "sent" entries.
03063 // 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.
03064 static int
03065 adjust_outbound_for_existing_interests(struct ccnd_handle *h, struct face *face,
03066                                        unsigned char *msg,
03067                                        struct ccn_parsed_interest *pi,
03068                                        struct nameprefix_entry *npe,
03069                                        struct ccn_indexbuf *outbound)
03070 {
03071     struct propagating_entry *head = &npe->pe_head;
03072     struct propagating_entry *p;
03073     size_t presize = pi->offset[CCN_PI_B_Nonce];
03074     size_t postsize = pi->offset[CCN_PI_E] - pi->offset[CCN_PI_E_Nonce];
03075     size_t minsize = presize + postsize;
03076     unsigned char *post = msg + pi->offset[CCN_PI_E_Nonce];
03077     int k = 0;
03078     int max_redundant = 3; /* Allow this many dups from same face */
03079     int i;
03080     int n;
03081     struct face *otherface;
03082     int extra_delay = 0;
03083 
03084     if ((face->flags & (CCN_FACE_MCAST | CCN_FACE_LINK)) != 0)
03085         max_redundant = 0;
03086     if (outbound != NULL) {
03087         for (p = head->prev; p != head && outbound->n > 0; p = p->prev) {
03088             if (p->size > minsize &&
03089                 p->interest_msg != NULL &&
03090                 p->usec > 0 &&
03091                 0 == memcmp(msg, p->interest_msg, presize) &&
03092                 0 == memcmp(post, p->interest_msg + p->size - postsize, postsize)) {
03093                 /* Matches everything but the Nonce */
03094                 otherface = face_from_faceid(h, p->faceid);
03095                 if (otherface == NULL)
03096                     continue;
03097                 /*
03098                  * If scope is 2, we can't treat these as similar if
03099                  * they did not originate on the same host
03100                  */
03101                 if (pi->scope == 2 &&
03102                     ((otherface->flags ^ face->flags) & CCN_FACE_GG) != 0)
03103                     continue;
03104                 if (h->debug & 32)
03105                     ccnd_debug_ccnb(h, __LINE__, "similar_interest",
03106                                     face_from_faceid(h, p->faceid),
03107                                     p->interest_msg, p->size);
03108                 if (face->faceid == p->faceid) {
03109                     /*
03110                      * This is one we've already seen before from the same face,
03111                      * but dropping it unconditionally would lose resiliency
03112                      * against dropped packets. Thus allow a few of them.
03113                      * Add some delay, though.
03114                      * XXX c.f. bug #13 // XXX - old bugid
03115                      */
03116                     extra_delay += npe->usec + 20000;
03117                     if ((++k) < max_redundant)
03118                         continue;
03119                     outbound->n = 0;
03120                     return(-1);
03121                 }
03122                 /*
03123                  * The existing interest from another face will serve for us,
03124                  * but we still need to send this interest there or we
03125                  * could miss an answer from that direction. Note that
03126                  * interests from two other faces could conspire to cover
03127                  * this one completely as far as propagation is concerned,
03128                  * but it is still necessary to keep it around for the sake
03129                  * of returning content.
03130                  * This assumes a unicast link.  If there are multiple
03131                  * parties on this face (broadcast or multicast), we
03132                  * do not want to send right away, because it is highly likely
03133                  * that we've seen an interest that one of the other parties
03134                  * is going to answer, and we'll see the answer, too.
03135                  */
03136                 n = outbound->n;
03137                 outbound->n = 0;
03138                 for (i = 0; i < n; i++) {
03139                     if (p->faceid == outbound->buf[i]) {
03140                         outbound->buf[0] = p->faceid;
03141                         outbound->n = 1;
03142                         if ((otherface->flags & (CCN_FACE_MCAST | CCN_FACE_LINK)) != 0)
03143                             extra_delay += npe->usec + 10000;
03144                         break;
03145                     }
03146                 }
03147                 p->flags |= CCN_PR_EQV; /* Don't add new faces */
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     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             if (content->comps == NULL) {
03883                 ccnd_msg(h, "could not enroll ContentObject (accession %llu)",
03884                          (unsigned long long)content->accession);
03885                 content = NULL;
03886                 hashtb_delete(e);
03887                 res = -__LINE__;
03888                 hashtb_end(e);
03889                 goto Bail;
03890                 
03891             }
03892         }
03893         content->key_size = e->keysize;
03894         content->size = e->keysize + e->extsize;
03895         content->key = e->key;
03896         for (i = 0; i < comps->n; i++)
03897             content->comps[i] = comps->buf[i];
03898         content_skiplist_insert(h, content);
03899         set_content_timer(h, content, &obj);
03900         /* Mark public keys supplied at startup as precious. */
03901         if (obj.type == CCN_CONTENT_KEY && content->accession <= (h->capacity + 7)/8)
03902             content->flags |= CCN_CONTENT_ENTRY_PRECIOUS;
03903     }
03904     hashtb_end(e);
03905 Bail:
03906     indexbuf_release(h, comps);
03907     charbuf_release(h, cb);
03908     cb = NULL;
03909     if (res >= 0 && content != NULL) {
03910         int n_matches;
03911         enum cq_delay_class c;
03912         struct content_queue *q;
03913         n_matches = match_interests(h, content, &obj, NULL, face);
03914         if (res == HT_NEW_ENTRY) {
03915             if (n_matches < 0) {
03916                 remove_content(h, content);
03917                 return;
03918             }
03919             if (n_matches == 0 && (face->flags & CCN_FACE_GG) == 0) {
03920                 content->flags |= CCN_CONTENT_ENTRY_SLOWSEND;
03921                 ccn_indexbuf_append_element(h->unsol, content->accession);
03922             }
03923         }
03924         for (c = 0; c < CCN_CQ_N; c++) {
03925             q = face->q[c];
03926             if (q != NULL) {
03927                 i = ccn_indexbuf_member(q->send_queue, content->accession);
03928                 if (i >= 0) {
03929                     /*
03930                      * In the case this consumed any interests from this source,
03931                      * don't send the content back
03932                      */
03933                     if (h->debug & 8)
03934                         ccnd_debug_ccnb(h, __LINE__, "content_nosend", face, msg, size);
03935                     q->send_queue->buf[i] = 0;
03936                 }
03937             }
03938         }
03939     }
03940 }
03941 
03942 static void
03943 process_input_message(struct ccnd_handle *h, struct face *face,
03944                       unsigned char *msg, size_t size, int pdu_ok)
03945 {
03946     struct ccn_skeleton_decoder decoder = {0};
03947     struct ccn_skeleton_decoder *d = &decoder;
03948     ssize_t dres;
03949     enum ccn_dtag dtag;
03950     
03951     if ((face->flags & CCN_FACE_UNDECIDED) != 0) {
03952         face->flags &= ~CCN_FACE_UNDECIDED;
03953         if ((face->flags & CCN_FACE_LOOPBACK) != 0)
03954             face->flags |= CCN_FACE_GG;
03955         /* YYY This is the first place that we know that an inbound stream face is speaking CCNx protocol. */
03956         register_new_face(h, face);
03957     }
03958     d->state |= CCN_DSTATE_PAUSE;
03959     dres = ccn_skeleton_decode(d, msg, size);
03960     if (d->state < 0)
03961         abort(); /* cannot happen because of checks in caller */
03962     if (CCN_GET_TT_FROM_DSTATE(d->state) != CCN_DTAG) {
03963         ccnd_msg(h, "discarding unknown message; size = %lu", (unsigned long)size);
03964         // XXX - keep a count?
03965         return;
03966     }
03967     dtag = d->numval;
03968     switch (dtag) {
03969         case CCN_DTAG_CCNProtocolDataUnit:
03970             if (!pdu_ok)
03971                 break;
03972             size -= d->index;
03973             if (size > 0)
03974                 size--;
03975             msg += d->index;
03976             face->flags |= CCN_FACE_LINK;
03977             face->flags &= ~CCN_FACE_GG;
03978             memset(d, 0, sizeof(*d));
03979             while (d->index < size) {
03980                 dres = ccn_skeleton_decode(d, msg + d->index, size - d->index);
03981                 if (d->state != 0)
03982                     abort(); /* cannot happen because of checks in caller */
03983                 /* The pdu_ok parameter limits the recursion depth */
03984                 process_input_message(h, face, msg + d->index - dres, dres, 0);
03985             }
03986             return;
03987         case CCN_DTAG_Interest:
03988             process_incoming_interest(h, face, msg, size);
03989             return;
03990         case CCN_DTAG_ContentObject:
03991             process_incoming_content(h, face, msg, size);
03992             return;
03993         case CCN_DTAG_SequenceNumber:
03994             process_incoming_link_message(h, face, dtag, msg, size);
03995             return;
03996         default:
03997             break;
03998     }
03999     ccnd_msg(h, "discarding unknown message; dtag=%u, size = %lu",
04000              (unsigned)dtag,
04001              (unsigned long)size);
04002 }
04003 
04004 static void
04005 ccnd_new_face_msg(struct ccnd_handle *h, struct face *face)
04006 {
04007     const struct sockaddr *addr = face->addr;
04008     int port = 0;
04009     const unsigned char *rawaddr = NULL;
04010     char printable[80];
04011     const char *peer = NULL;
04012     if (addr->sa_family == AF_INET6) {
04013         const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
04014         rawaddr = (const unsigned char *)&addr6->sin6_addr;
04015         port = htons(addr6->sin6_port);
04016     }
04017     else if (addr->sa_family == AF_INET) {
04018         const struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
04019         rawaddr = (const unsigned char *)&addr4->sin_addr.s_addr;
04020         port = htons(addr4->sin_port);
04021     }
04022     if (rawaddr != NULL)
04023         peer = inet_ntop(addr->sa_family, rawaddr, printable, sizeof(printable));
04024     if (peer == NULL)
04025         peer = "(unknown)";
04026     ccnd_msg(h,
04027              "accepted datagram client id=%d (flags=0x%x) %s port %d",
04028              face->faceid, face->flags, peer, port);
04029 }
04030 
04031 /**
04032  * Since struct sockaddr_in6 may contain fields that should not participate
04033  * in comparison / hash, ensure the undesired fields are zero.
04034  *
04035  * Per RFC 3493, sin6_flowinfo is zeroed.
04036  *
04037  * @param addr is the sockaddr (any family)
04038  * @param addrlen is its length
04039  * @param space points to a buffer that may be used for the result.
04040  * @returns either the original addr or a pointer to a scrubbed copy.
04041  *
04042  */
04043 static struct sockaddr *
04044 scrub_sockaddr(struct sockaddr *addr, socklen_t addrlen,
04045                struct sockaddr_in6 *space)
04046 {
04047     struct sockaddr_in6 *src;
04048     struct sockaddr_in6 *dst;
04049     if (addr->sa_family != AF_INET6 || addrlen != sizeof(*space))
04050         return(addr);
04051     dst = space;
04052     src = (void *)addr;
04053     memset(dst, 0, addrlen);
04054     /* Copy first byte case sin6_len is used. */
04055     ((uint8_t *)dst)[0] = ((uint8_t *)src)[0];
04056     dst->sin6_family   = src->sin6_family;
04057     dst->sin6_port     = src->sin6_port;
04058     dst->sin6_addr     = src->sin6_addr;
04059     dst->sin6_scope_id = src->sin6_scope_id;
04060     return((struct sockaddr *)dst);
04061 }
04062 
04063 static struct face *
04064 get_dgram_source(struct ccnd_handle *h, struct face *face,
04065                  struct sockaddr *addr, socklen_t addrlen, int why)
04066 {
04067     struct face *source = NULL;
04068     struct hashtb_enumerator ee;
04069     struct hashtb_enumerator *e = &ee;
04070     struct sockaddr_in6 space;
04071     int res;
04072     if ((face->flags & CCN_FACE_DGRAM) == 0)
04073         return(face);
04074     if ((face->flags & CCN_FACE_MCAST) != 0)
04075         return(face);
04076     hashtb_start(h->dgram_faces, e);
04077     res = hashtb_seek(e, scrub_sockaddr(addr, addrlen, &space), addrlen, 0);
04078     if (res >= 0) {
04079         source = e->data;
04080         source->recvcount++;
04081         if (source->addr == NULL) {
04082             source->addr = e->key;
04083             source->addrlen = e->keysize;
04084             source->recv_fd = face->recv_fd;
04085             source->sendface = face->faceid;
04086             init_face_flags(h, source, CCN_FACE_DGRAM);
04087             if (why == 1 && (source->flags & CCN_FACE_LOOPBACK) != 0)
04088                 source->flags |= CCN_FACE_GG;
04089             res = enroll_face(h, source);
04090             if (res == -1) {
04091                 hashtb_delete(e);
04092                 source = NULL;
04093             }
04094             else {
04095                 ccnd_new_face_msg(h, source);
04096                 reap_needed(h, CCN_INTEREST_LIFETIME_MICROSEC);
04097             }
04098         }
04099     }
04100     hashtb_end(e);
04101     return(source);
04102 }
04103 
04104 /**
04105  * Break up data in a face's input buffer buffer into individual messages,
04106  * and call process_input_message on each one.
04107  *
04108  * This is used to handle things originating from the internal client -
04109  * its output is input for face 0.
04110  */
04111 static void
04112 process_input_buffer(struct ccnd_handle *h, struct face *face)
04113 {
04114     unsigned char *msg;
04115     size_t size;
04116     ssize_t dres;
04117     struct ccn_skeleton_decoder *d;
04118 
04119     if (face == NULL || face->inbuf == NULL)
04120         return;
04121     d = &face->decoder;
04122     msg = face->inbuf->buf;
04123     size = face->inbuf->length;
04124     while (d->index < size) {
04125         dres = ccn_skeleton_decode(d, msg + d->index, size - d->index);
04126         if (d->state != 0)
04127             break;
04128         process_input_message(h, face, msg + d->index - dres, dres, 0);
04129     }
04130     if (d->index != size) {
04131         ccnd_msg(h, "protocol error on face %u (state %d), discarding %d bytes",
04132                      face->faceid, d->state, (int)(size - d->index));
04133         // XXX - perhaps this should be a fatal error.
04134     }
04135     face->inbuf->length = 0;
04136     memset(d, 0, sizeof(*d));
04137 }
04138 
04139 /**
04140  * Process the input from a socket.
04141  *
04142  * The socket has been found ready for input by the poll call.
04143  * Decide what face it corresponds to, and after checking for exceptional
04144  * cases, receive data, parse it into ccnb-encoded messages, and call
04145  * process_input_message for each one.
04146  */
04147 static void
04148 process_input(struct ccnd_handle *h, int fd)
04149 {
04150     struct face *face = NULL;
04151     struct face *source = NULL;
04152     ssize_t res;
04153     ssize_t dres;
04154     ssize_t msgstart;
04155     unsigned char *buf;
04156     struct ccn_skeleton_decoder *d;
04157     struct sockaddr_storage sstor;
04158     socklen_t addrlen = sizeof(sstor);
04159     struct sockaddr *addr = (struct sockaddr *)&sstor;
04160     int err = 0;
04161     socklen_t err_sz;
04162     
04163     face = hashtb_lookup(h->faces_by_fd, &fd, sizeof(fd));
04164     if (face == NULL)
04165         return;
04166     if ((face->flags & (CCN_FACE_DGRAM | CCN_FACE_PASSIVE)) == CCN_FACE_PASSIVE) {
04167         accept_connection(h, fd);
04168         check_comm_file(h);
04169         return;
04170     }
04171     err_sz = sizeof(err);
04172     res = getsockopt(face->recv_fd, SOL_SOCKET, SO_ERROR, &err, &err_sz);
04173     if (res >= 0 && err != 0) {
04174         ccnd_msg(h, "error on face %u: %s (%d)", face->faceid, strerror(err), err);
04175         if (err == ETIMEDOUT && (face->flags & CCN_FACE_CONNECTING) != 0) {
04176             shutdown_client_fd(h, fd);
04177             return;
04178         }
04179     }
04180     d = &face->decoder;
04181     if (face->inbuf == NULL)
04182         face->inbuf = ccn_charbuf_create();
04183     if (face->inbuf->length == 0)
04184         memset(d, 0, sizeof(*d));
04185     buf = ccn_charbuf_reserve(face->inbuf, 8800);
04186     memset(&sstor, 0, sizeof(sstor));
04187     res = recvfrom(face->recv_fd, buf, face->inbuf->limit - face->inbuf->length,
04188             /* flags */ 0, addr, &addrlen);
04189     if (res == -1)
04190         ccnd_msg(h, "recvfrom face %u :%s (errno = %d)",
04191                     face->faceid, strerror(errno), errno);
04192     else if (res == 0 && (face->flags & CCN_FACE_DGRAM) == 0)
04193         shutdown_client_fd(h, fd);
04194     else {
04195         source = get_dgram_source(h, face, addr, addrlen, (res == 1) ? 1 : 2);
04196         ccnd_meter_bump(h, source->meter[FM_BYTI], res);
04197         source->recvcount++;
04198         source->surplus = 0; // XXX - we don't actually use this, except for some obscure messages.
04199         if (res <= 1 && (source->flags & CCN_FACE_DGRAM) != 0) {
04200             // XXX - If the initial heartbeat gets missed, we don't realize the locality of the face.
04201             if (h->debug & 128)
04202                 ccnd_msg(h, "%d-byte heartbeat on %d", (int)res, source->faceid);
04203             return;
04204         }
04205         face->inbuf->length += res;
04206         msgstart = 0;
04207         if (((face->flags & CCN_FACE_UNDECIDED) != 0 &&
04208              face->inbuf->length >= 6 &&
04209              0 == memcmp(face->inbuf->buf, "GET ", 4))) {
04210             ccnd_stats_handle_http_connection(h, face);
04211             return;
04212         }
04213         dres = ccn_skeleton_decode(d, buf, res);
04214         while (d->state == 0) {
04215             process_input_message(h, source,
04216                                   face->inbuf->buf + msgstart,
04217                                   d->index - msgstart,
04218                                   (face->flags & CCN_FACE_LOCAL) != 0);
04219             msgstart = d->index;
04220             if (msgstart == face->inbuf->length) {
04221                 face->inbuf->length = 0;
04222                 return;
04223             }
04224             dres = ccn_skeleton_decode(d,
04225                     face->inbuf->buf + d->index, // XXX - msgstart and d->index are the same here - use msgstart
04226                     res = face->inbuf->length - d->index);  // XXX - why is res set here?
04227         }
04228         if ((face->flags & CCN_FACE_DGRAM) != 0) {
04229             ccnd_msg(h, "protocol error on face %u, discarding %u bytes",
04230                 source->faceid,
04231                 (unsigned)(face->inbuf->length));  // XXX - Should be face->inbuf->length - d->index (or msgstart)
04232             face->inbuf->length = 0;
04233             /* XXX - should probably ignore this source for a while */
04234             return;
04235         }
04236         else if (d->state < 0) {
04237             ccnd_msg(h, "protocol error on face %u", source->faceid);
04238             shutdown_client_fd(h, fd);
04239             return;
04240         }
04241         if (msgstart < face->inbuf->length && msgstart > 0) {
04242             /* move partial message to start of buffer */
04243             memmove(face->inbuf->buf, face->inbuf->buf + msgstart,
04244                 face->inbuf->length - msgstart);
04245             face->inbuf->length -= msgstart;
04246             d->index -= msgstart;
04247         }
04248     }
04249 }
04250 
04251 static void
04252 process_internal_client_buffer(struct ccnd_handle *h)
04253 {
04254     struct face *face = h->face0;
04255     if (face == NULL)
04256         return;
04257     face->inbuf = ccn_grab_buffered_output(h->internal_client);
04258     if (face->inbuf == NULL)
04259         return;
04260     ccnd_meter_bump(h, face->meter[FM_BYTI], face->inbuf->length);
04261     process_input_buffer(h, face);
04262     ccn_charbuf_destroy(&(face->inbuf));
04263 }
04264 
04265 /**
04266  * Handle errors after send() or sendto().
04267  * @returns -1 if error has been dealt with, or 0 to defer sending.
04268  */
04269 static int
04270 handle_send_error(struct ccnd_handle *h, int errnum, struct face *face,
04271                   const void *data, size_t size)
04272 {
04273     int res = -1;
04274     if (errnum == EAGAIN) {
04275         res = 0;
04276     }
04277     else if (errnum == EPIPE) {
04278         face->flags |= CCN_FACE_NOSEND;
04279         face->outbufindex = 0;
04280         ccn_charbuf_destroy(&face->outbuf);
04281     }
04282     else {
04283         ccnd_msg(h, "send to face %u failed: %s (errno = %d)",
04284                  face->faceid, strerror(errnum), errnum);
04285         if (errnum == EISCONN)
04286             res = 0;
04287     }
04288     return(res);
04289 }
04290 
04291 static int
04292 sending_fd(struct ccnd_handle *h, struct face *face)
04293 {
04294     struct face *out = NULL;
04295     if (face->sendface == face->faceid)
04296         return(face->recv_fd);
04297     out = face_from_faceid(h, face->sendface);
04298     if (out != NULL)
04299         return(out->recv_fd);
04300     face->sendface = CCN_NOFACEID;
04301     if (face->addr != NULL) {
04302         switch (face->addr->sa_family) {
04303             case AF_INET:
04304                 face->sendface = h->ipv4_faceid;
04305                 break;
04306             case AF_INET6:
04307                 face->sendface = h->ipv6_faceid;
04308                 break;
04309             default:
04310                 break;
04311         }
04312     }
04313     out = face_from_faceid(h, face->sendface);
04314     if (out != NULL)
04315         return(out->recv_fd);
04316     return(-1);
04317 }
04318 
04319 /**
04320  * Send data to the face.
04321  *
04322  * No direct error result is provided; the face state is updated as needed.
04323  */
04324 void
04325 ccnd_send(struct ccnd_handle *h,
04326           struct face *face,
04327           const void *data, size_t size)
04328 {
04329     ssize_t res;
04330     if ((face->flags & CCN_FACE_NOSEND) != 0)
04331         return;
04332     face->surplus++;
04333     if (face->outbuf != NULL) {
04334         ccn_charbuf_append(face->outbuf, data, size);
04335         return;
04336     }
04337     if (face == h->face0) {
04338         ccnd_meter_bump(h, face->meter[FM_BYTO], size);
04339         ccn_dispatch_message(h->internal_client, (void *)data, size);
04340         process_internal_client_buffer(h);
04341         return;
04342     }
04343     if ((face->flags & CCN_FACE_DGRAM) == 0)
04344         res = send(face->recv_fd, data, size, 0);
04345     else
04346         res = sendto(sending_fd(h, face), data, size, 0,
04347                      face->addr, face->addrlen);
04348     if (res > 0)
04349         ccnd_meter_bump(h, face->meter[FM_BYTO], res);
04350     if (res == size)
04351         return;
04352     if (res == -1) {
04353         res = handle_send_error(h, errno, face, data, size);
04354         if (res == -1)
04355             return;
04356     }
04357     if ((face->flags & CCN_FACE_DGRAM) != 0) {
04358         ccnd_msg(h, "sendto short");
04359         return;
04360     }
04361     face->outbufindex = 0;
04362     face->outbuf = ccn_charbuf_create();
04363     if (face->outbuf == NULL) {
04364         ccnd_msg(h, "do_write: %s", strerror(errno));
04365         return;
04366     }
04367     ccn_charbuf_append(face->outbuf,
04368                        ((const unsigned char *)data) + res, size - res);
04369 }
04370 
04371 static void
04372 do_deferred_write(struct ccnd_handle *h, int fd)
04373 {
04374     /* This only happens on connected sockets */
04375     ssize_t res;
04376     struct face *face = hashtb_lookup(h->faces_by_fd, &fd, sizeof(fd));
04377     if (face == NULL)
04378         return;
04379     if (face->outbuf != NULL) {
04380         ssize_t sendlen = face->outbuf->length - face->outbufindex;
04381         if (sendlen > 0) {
04382             res = send(fd, face->outbuf->buf + face->outbufindex, sendlen, 0);
04383             if (res == -1) {
04384                 if (errno == EPIPE) {
04385                     face->flags |= CCN_FACE_NOSEND;
04386                     face->outbufindex = 0;
04387                     ccn_charbuf_destroy(&face->outbuf);
04388                     return;
04389                 }
04390                 ccnd_msg(h, "send: %s (errno = %d)", strerror(errno), errno);
04391                 shutdown_client_fd(h, fd);
04392                 return;
04393             }
04394             if (res == sendlen) {
04395                 face->outbufindex = 0;
04396                 ccn_charbuf_destroy(&face->outbuf);
04397                 if ((face->flags & CCN_FACE_CLOSING) != 0)
04398                     shutdown_client_fd(h, fd);
04399                 return;
04400             }
04401             face->outbufindex += res;
04402             return;
04403         }
04404         face->outbufindex = 0;
04405         ccn_charbuf_destroy(&face->outbuf);
04406     }
04407     if ((face->flags & CCN_FACE_CLOSING) != 0)
04408         shutdown_client_fd(h, fd);
04409     else if ((face->flags & CCN_FACE_CONNECTING) != 0) {
04410         face->flags &= ~CCN_FACE_CONNECTING;
04411         ccnd_face_status_change(h, face->faceid);
04412     }
04413     else
04414         ccnd_msg(h, "ccnd:do_deferred_write: something fishy on %d", fd);
04415 }
04416 
04417 /**
04418  * Set up the array of fd descriptors for the poll(2) call.
04419  *
04420  * Arrange the array so that multicast receivers are early, so that
04421  * if the same packet arrives on both a multicast socket and a
04422  * normal socket, we will count is as multicast.
04423  */
04424 static void
04425 prepare_poll_fds(struct ccnd_handle *h)
04426 {
04427     struct hashtb_enumerator ee;
04428     struct hashtb_enumerator *e = &ee;
04429     int i, j, k;
04430     if (hashtb_n(h->faces_by_fd) != h->nfds) {
04431         h->nfds = hashtb_n(h->faces_by_fd);
04432         h->fds = realloc(h->fds, h->nfds * sizeof(h->fds[0]));
04433         memset(h->fds, 0, h->nfds * sizeof(h->fds[0]));
04434     }
04435     for (i = 0, k = h->nfds, hashtb_start(h->faces_by_fd, e);
04436          i < k && e->data != NULL; hashtb_next(e)) {
04437         struct face *face = e->data;
04438         if (face->flags & CCN_FACE_MCAST)
04439             j = i++;
04440         else
04441             j = --k;
04442         h->fds[j].fd = face->recv_fd;
04443         h->fds[j].events = ((face->flags & CCN_FACE_NORECV) == 0) ? POLLIN : 0;
04444         if ((face->outbuf != NULL || (face->flags & CCN_FACE_CLOSING) != 0))
04445             h->fds[j].events |= POLLOUT;
04446     }
04447     hashtb_end(e);
04448     if (i < k)
04449         abort();
04450 }
04451 
04452 /**
04453  * Run the main loop of the ccnd
04454  */
04455 void
04456 ccnd_run(struct ccnd_handle *h)
04457 {
04458     int i;
04459     int res;
04460     int timeout_ms = -1;
04461     int prev_timeout_ms = -1;
04462     int usec;
04463     for (h->running = 1; h->running;) {
04464         process_internal_client_buffer(h);
04465         usec = ccn_schedule_run(h->sched);
04466         timeout_ms = (usec < 0) ? -1 : ((usec + 960) / 1000);
04467         if (timeout_ms == 0 && prev_timeout_ms == 0)
04468             timeout_ms = 1;
04469         process_internal_client_buffer(h);
04470         prepare_poll_fds(h);
04471         if (0) ccnd_msg(h, "at ccnd.c:%d poll(h->fds, %d, %d)", __LINE__, h->nfds, timeout_ms);
04472         res = poll(h->fds, h->nfds, timeout_ms);
04473         prev_timeout_ms = ((res == 0) ? timeout_ms : 1);
04474         if (-1 == res) {
04475             ccnd_msg(h, "poll: %s (errno = %d)", strerror(errno), errno);
04476             sleep(1);
04477             continue;
04478         }
04479         for (i = 0; res > 0 && i < h->nfds; i++) {
04480             if (h->fds[i].revents != 0) {
04481                 res--;
04482                 if (h->fds[i].revents & (POLLERR | POLLNVAL | POLLHUP)) {
04483                     if (h->fds[i].revents & (POLLIN))
04484                         process_input(h, h->fds[i].fd);
04485                     else
04486                         shutdown_client_fd(h, h->fds[i].fd);
04487                     continue;
04488                 }
04489                 if (h->fds[i].revents & (POLLOUT))
04490                     do_deferred_write(h, h->fds[i].fd);
04491                 else if (h->fds[i].revents & (POLLIN))
04492                     process_input(h, h->fds[i].fd);
04493             }
04494         }
04495     }
04496 }
04497 
04498 static void
04499 ccnd_reseed(struct ccnd_handle *h)
04500 {
04501     int fd;
04502     ssize_t res;
04503     
04504     res = -1;
04505     fd = open("/dev/urandom", O_RDONLY);
04506     if (fd != -1) {
04507         res = read(fd, h->seed, sizeof(h->seed));
04508         close(fd);
04509     }
04510     if (res != sizeof(h->seed)) {
04511         h->seed[1] = (unsigned short)getpid(); /* better than no entropy */
04512         h->seed[2] = (unsigned short)time(NULL);
04513     }
04514     /*
04515      * The call to seed48 is needed by cygwin, and should be harmless
04516      * on other platforms.
04517      */
04518     seed48(h->seed);
04519 }
04520 
04521 static char *
04522 ccnd_get_local_sockname(void)
04523 {
04524     struct sockaddr_un sa;
04525     ccn_setup_sockaddr_un(NULL, &sa);
04526     return(strdup(sa.sun_path));
04527 }
04528 
04529 static void
04530 ccnd_gettime(const struct ccn_gettime *self, struct ccn_timeval *result)
04531 {
04532     struct ccnd_handle *h = self->data;
04533     struct timeval now = {0};
04534     gettimeofday(&now, 0);
04535     result->s = now.tv_sec;
04536     result->micros = now.tv_usec;
04537     h->sec = now.tv_sec;
04538     h->usec = now.tv_usec;
04539 }
04540 
04541 void
04542 ccnd_setsockopt_v6only(struct ccnd_handle *h, int fd)
04543 {
04544     int yes = 1;
04545     int res = 0;
04546 #ifdef IPV6_V6ONLY
04547     res = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes));
04548 #endif
04549     if (res == -1)
04550         ccnd_msg(h, "warning - could not set IPV6_V6ONLY on fd %d: %s",
04551                  fd, strerror(errno));
04552 }
04553 
04554 static const char *
04555 af_name(int family)
04556 {
04557     switch (family) {
04558         case AF_INET:
04559             return("ipv4");
04560         case AF_INET6:
04561             return("ipv6");
04562         default:
04563             return("");
04564     }
04565 }
04566 
04567 static int
04568 ccnd_listen_on_wildcards(struct ccnd_handle *h)
04569 {
04570     int fd;
04571     int res;
04572     int whichpf;
04573     struct addrinfo hints = {0};
04574     struct addrinfo *addrinfo = NULL;
04575     struct addrinfo *a;
04576     
04577     hints.ai_socktype = SOCK_DGRAM;
04578     hints.ai_flags = AI_PASSIVE;
04579     for (whichpf = 0; whichpf < 2; whichpf++) {
04580         hints.ai_family = whichpf ? PF_INET6 : PF_INET;
04581         res = getaddrinfo(NULL, h->portstr, &hints, &addrinfo);
04582         if (res == 0) {
04583             for (a = addrinfo; a != NULL; a = a->ai_next) {
04584                 fd = socket(a->ai_family, SOCK_DGRAM, 0);
04585                 if (fd != -1) {
04586                     struct face *face = NULL;
04587                     int yes = 1;
04588                     int rcvbuf = 0;
04589                     socklen_t rcvbuf_sz;
04590                     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04591                     rcvbuf_sz = sizeof(rcvbuf);
04592                     getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_sz);
04593                     if (a->ai_family == AF_INET6)
04594                         ccnd_setsockopt_v6only(h, fd);
04595                     res = bind(fd, a->ai_addr, a->ai_addrlen);
04596                     if (res != 0) {
04597                         close(fd);
04598                         continue;
04599                     }
04600                     face = record_connection(h, fd,
04601                                              a->ai_addr, a->ai_addrlen,
04602                                              CCN_FACE_DGRAM | CCN_FACE_PASSIVE);
04603                     if (face == NULL) {
04604                         close(fd);
04605                         continue;
04606                     }
04607                     if (a->ai_family == AF_INET)
04608                         h->ipv4_faceid = face->faceid;
04609                     else
04610                         h->ipv6_faceid = face->faceid;
04611                     ccnd_msg(h, "accepting %s datagrams on fd %d rcvbuf %d",
04612                              af_name(a->ai_family), fd, rcvbuf);
04613                 }
04614             }
04615             for (a = addrinfo; a != NULL; a = a->ai_next) {
04616                 fd = socket(a->ai_family, SOCK_STREAM, 0);
04617                 if (fd != -1) {
04618                     int yes = 1;
04619                     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04620                     if (a->ai_family == AF_INET6)
04621                         ccnd_setsockopt_v6only(h, fd);
04622                     res = bind(fd, a->ai_addr, a->ai_addrlen);
04623                     if (res != 0) {
04624                         close(fd);
04625                         continue;
04626                     }
04627                     res = listen(fd, 30);
04628                     if (res == -1) {
04629                         close(fd);
04630                         continue;
04631                     }
04632                     record_connection(h, fd,
04633                                       a->ai_addr, a->ai_addrlen,
04634                                       CCN_FACE_PASSIVE);
04635                     ccnd_msg(h, "accepting %s connections on fd %d",
04636                              af_name(a->ai_family), fd);
04637                 }
04638             }
04639             freeaddrinfo(addrinfo);
04640         }
04641     }
04642     return(0);
04643 }
04644 
04645 static int
04646 ccnd_listen_on_address(struct ccnd_handle *h, const char *addr)
04647 {
04648     int fd;
04649     int res;
04650     struct addrinfo hints = {0};
04651     struct addrinfo *addrinfo = NULL;
04652     struct addrinfo *a;
04653     int ok = 0;
04654     
04655     ccnd_msg(h, "listen_on %s", addr);
04656     hints.ai_socktype = SOCK_DGRAM;
04657     hints.ai_flags = AI_PASSIVE;
04658     res = getaddrinfo(addr, h->portstr, &hints, &addrinfo);
04659     if (res == 0) {
04660         for (a = addrinfo; a != NULL; a = a->ai_next) {
04661             fd = socket(a->ai_family, SOCK_DGRAM, 0);
04662             if (fd != -1) {
04663                 struct face *face = NULL;
04664                 int yes = 1;
04665                 int rcvbuf = 0;
04666                 socklen_t rcvbuf_sz;
04667                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04668                 rcvbuf_sz = sizeof(rcvbuf);
04669                 getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_sz);
04670                 if (a->ai_family == AF_INET6)
04671                     ccnd_setsockopt_v6only(h, fd);
04672                 res = bind(fd, a->ai_addr, a->ai_addrlen);
04673                 if (res != 0) {
04674                     close(fd);
04675                     continue;
04676                 }
04677                 face = record_connection(h, fd,
04678                                          a->ai_addr, a->ai_addrlen,
04679                                          CCN_FACE_DGRAM | CCN_FACE_PASSIVE);
04680                 if (face == NULL) {
04681                     close(fd);
04682                     continue;
04683                 }
04684                 if (a->ai_family == AF_INET)
04685                     h->ipv4_faceid = face->faceid;
04686                 else
04687                     h->ipv6_faceid = face->faceid;
04688                 ccnd_msg(h, "accepting %s datagrams on fd %d rcvbuf %d",
04689                              af_name(a->ai_family), fd, rcvbuf);
04690                 ok++;
04691             }
04692         }
04693         for (a = addrinfo; a != NULL; a = a->ai_next) {
04694             fd = socket(a->ai_family, SOCK_STREAM, 0);
04695             if (fd != -1) {
04696                 int yes = 1;
04697                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
04698                 if (a->ai_family == AF_INET6)
04699                     ccnd_setsockopt_v6only(h, fd);
04700                 res = bind(fd, a->ai_addr, a->ai_addrlen);
04701                 if (res != 0) {
04702                     close(fd);
04703                     continue;
04704                 }
04705                 res = listen(fd, 30);
04706                 if (res == -1) {
04707                     close(fd);
04708                     continue;
04709                 }
04710                 record_connection(h, fd,
04711                                   a->ai_addr, a->ai_addrlen,
04712                                   CCN_FACE_PASSIVE);
04713                 ccnd_msg(h, "accepting %s connections on fd %d",
04714                          af_name(a->ai_family), fd);
04715                 ok++;
04716             }
04717         }
04718         freeaddrinfo(addrinfo);
04719     }
04720     return(ok > 0 ? 0 : -1);
04721 }
04722 
04723 static int
04724 ccnd_listen_on(struct ccnd_handle *h, const char *addrs)
04725 {
04726     unsigned char ch;
04727     unsigned char dlm;
04728     int res = 0;
04729     int i;
04730     struct ccn_charbuf *addr = NULL;
04731     
04732     if (addrs == NULL || !*addrs || 0 == strcmp(addrs, "*"))
04733         return(ccnd_listen_on_wildcards(h));
04734     addr = ccn_charbuf_create();
04735     for (i = 0, ch = addrs[i]; addrs[i] != 0;) {
04736         addr->length = 0;
04737         dlm = 0;
04738         if (ch == '[') {
04739             dlm = ']';
04740             ch = addrs[++i];
04741         }
04742         for (; ch > ' ' && ch != ',' && ch != ';' && ch != dlm; ch = addrs[++i])
04743             ccn_charbuf_append_value(addr, ch, 1);
04744         if (ch && ch == dlm)
04745             ch = addrs[++i];
04746         if (addr->length > 0) {
04747             res |= ccnd_listen_on_address(h, ccn_charbuf_as_string(addr));
04748         }
04749         while ((0 < ch && ch <= ' ') || ch == ',' || ch == ';')
04750             ch = addrs[++i];
04751     }
04752     ccn_charbuf_destroy(&addr);
04753     return(res);
04754 }
04755 
04756 static struct ccn_charbuf *
04757 ccnd_parse_uri_list(struct ccnd_handle *h, const char *what, const char *uris)
04758 {
04759     struct ccn_charbuf *ans;
04760     struct ccn_charbuf *name;
04761     int i;
04762     size_t j;
04763     int res;
04764     unsigned char ch;
04765     const char *uri;
04766 
04767     if (uris == NULL)
04768         return(NULL);
04769     ans = ccn_charbuf_create();
04770     name = ccn_charbuf_create();
04771     for (i = 0, ch = uris[0]; ch != 0;) {
04772         while ((0 < ch && ch <= ' ') || ch == ',' || ch == ';')
04773             ch = uris[++i];
04774         j = ans->length;
04775         while (ch > ' ' && ch != ',' && ch != ';') {
04776             ccn_charbuf_append_value(ans, ch, 1);
04777             ch = uris[++i];
04778         }
04779         if (j < ans->length) {
04780             ccn_charbuf_append_value(ans, 0, 1);
04781             uri = (const char *)ans->buf + j;
04782             name->length = 0;
04783             res = ccn_name_from_uri(name, uri);
04784             if (res < 0) {
04785                 ccnd_msg(h, "%s: invalid ccnx URI: %s", what, uri);
04786                 ans->length = j;
04787             }
04788         }
04789     }
04790     ccn_charbuf_destroy(&name);
04791     if (ans->length == 0)
04792         ccn_charbuf_destroy(&ans);
04793     return(ans);
04794 }
04795 
04796 /**
04797  * Start a new ccnd instance
04798  * @param progname - name of program binary, used for locating helpers
04799  * @param logger - logger function
04800  * @param loggerdata - data to pass to logger function
04801  */
04802 struct ccnd_handle *
04803 ccnd_create(const char *progname, ccnd_logger logger, void *loggerdata)
04804 {
04805     char *sockname;
04806     const char *portstr;
04807     const char *debugstr;
04808     const char *entrylimit;
04809     const char *mtu;
04810     const char *data_pause;
04811     const char *autoreg;
04812     const char *listen_on;
04813     int fd;
04814     struct ccnd_handle *h;
04815     struct hashtb_param param = {0};
04816     
04817     sockname = ccnd_get_local_sockname();
04818     h = calloc(1, sizeof(*h));
04819     if (h == NULL)
04820         return(h);
04821     h->logger = logger;
04822     h->loggerdata = loggerdata;
04823     h->appnonce = &ccnd_append_plain_nonce;
04824     h->logpid = (int)getpid();
04825     h->progname = progname;
04826     h->debug = -1;
04827     h->skiplinks = ccn_indexbuf_create();
04828     param.finalize_data = h;
04829     h->face_limit = 1024; /* soft limit */
04830     h->faces_by_faceid = calloc(h->face_limit, sizeof(h->faces_by_faceid[0]));
04831     param.finalize = &finalize_face;
04832     h->faces_by_fd = hashtb_create(sizeof(struct face), &param);
04833     h->dgram_faces = hashtb_create(sizeof(struct face), &param);
04834     param.finalize = &finalize_content;
04835     h->content_tab = hashtb_create(sizeof(struct content_entry), &param);
04836     param.finalize = &finalize_nameprefix;
04837     h->nameprefix_tab = hashtb_create(sizeof(struct nameprefix_entry), &param);
04838     param.finalize = &finalize_propagating;
04839     h->propagating_tab = hashtb_create(sizeof(struct propagating_entry), &param);
04840     param.finalize = 0;
04841     h->sparse_straggler_tab = hashtb_create(sizeof(struct sparse_straggler_entry), NULL);
04842     h->min_stale = ~0;
04843     h->max_stale = 0;
04844     h->unsol = ccn_indexbuf_create();
04845     h->ticktock.descr[0] = 'C';
04846     h->ticktock.micros_per_base = 1000000;
04847     h->ticktock.gettime = &ccnd_gettime;
04848     h->ticktock.data = h;
04849     h->sched = ccn_schedule_create(h, &h->ticktock);
04850     h->starttime = h->sec;
04851     h->starttime_usec = h->usec;
04852     h->oldformatcontentgrumble = 1;
04853     h->oldformatinterestgrumble = 1;
04854     h->data_pause_microsec = 10000;
04855     debugstr = getenv("CCND_DEBUG");
04856     if (debugstr != NULL && debugstr[0] != 0) {
04857         h->debug = atoi(debugstr);
04858         if (h->debug == 0 && debugstr[0] != '0')
04859             h->debug = 1;
04860     }
04861     else
04862         h->debug = 1;
04863     portstr = getenv(CCN_LOCAL_PORT_ENVNAME);
04864     if (portstr == NULL || portstr[0] == 0 || strlen(portstr) > 10)
04865         portstr = CCN_DEFAULT_UNICAST_PORT;
04866     h->portstr = portstr;
04867     entrylimit = getenv("CCND_CAP");
04868     h->capacity = ~0;
04869     if (entrylimit != NULL && entrylimit[0] != 0) {
04870         h->capacity = atol(entrylimit);
04871         if (h->capacity == 0)
04872             h->force_zero_freshness = 1;
04873         if (h->capacity <= 0)
04874             h->capacity = 10;
04875     }
04876     h->mtu = 0;
04877     mtu = getenv("CCND_MTU");
04878     if (mtu != NULL && mtu[0] != 0) {
04879         h->mtu = atol(mtu);
04880         if (h->mtu < 0)
04881             h->mtu = 0;
04882         if (h->mtu > 8800)
04883             h->mtu = 8800;
04884     }
04885     data_pause = getenv("CCND_DATA_PAUSE_MICROSEC");
04886     if (data_pause != NULL && data_pause[0] != 0) {
04887         h->data_pause_microsec = atol(data_pause);
04888         if (h->data_pause_microsec == 0)
04889             h->data_pause_microsec = 1;
04890         if (h->data_pause_microsec > 1000000)
04891             h->data_pause_microsec = 1000000;
04892     }
04893     listen_on = getenv("CCND_LISTEN_ON");
04894     autoreg = getenv("CCND_AUTOREG");
04895     ccnd_msg(h, "CCND_DEBUG=%d CCND_CAP=%lu", h->debug, h->capacity);
04896     if (autoreg != NULL && autoreg[0] != 0) {
04897         h->autoreg = ccnd_parse_uri_list(h, "CCND_AUTOREG", autoreg);
04898         if (h->autoreg != NULL)
04899             ccnd_msg(h, "CCND_AUTOREG=%s", autoreg);
04900     }
04901     if (listen_on != NULL && listen_on[0] != 0)
04902         ccnd_msg(h, "CCND_LISTEN_ON=%s", listen_on);
04903     // if (h->debug & 256)
04904         h->appnonce = &ccnd_append_debug_nonce;
04905     /* Do keystore setup early, it takes a while the first time */
04906     ccnd_init_internal_keystore(h);
04907     ccnd_reseed(h);
04908     if (h->face0 == NULL) {
04909         struct face *face;
04910         face = calloc(1, sizeof(*face));
04911         face->recv_fd = -1;
04912         face->sendface = 0;
04913         face->flags = (CCN_FACE_GG | CCN_FACE_LOCAL);
04914         h->face0 = face;
04915     }
04916     enroll_face(h, h->face0);
04917     fd = create_local_listener(h, sockname, 42);
04918     if (fd == -1)
04919         ccnd_msg(h, "%s: %s", sockname, strerror(errno));
04920     else
04921         ccnd_msg(h, "listening on %s", sockname);
04922     h->flood = (h->autoreg != NULL);
04923     h->ipv4_faceid = h->ipv6_faceid = CCN_NOFACEID;
04924     ccnd_listen_on(h, listen_on);
04925     clean_needed(h);
04926     age_forwarding_needed(h);
04927     ccnd_internal_client_start(h);
04928     free(sockname);
04929     sockname = NULL;
04930     return(h);
04931 }
04932 
04933 /**
04934  * Shutdown listeners and bound datagram sockets, leaving connected streams.
04935  */
04936 static void
04937 ccnd_shutdown_listeners(struct ccnd_handle *h)
04938 {
04939     struct hashtb_enumerator ee;
04940     struct hashtb_enumerator *e = &ee;
04941     for (hashtb_start(h->faces_by_fd, e); e->data != NULL;) {
04942         struct face *face = e->data;
04943         if ((face->flags & (CCN_FACE_MCAST | CCN_FACE_PASSIVE)) != 0)
04944             hashtb_delete(e);
04945         else
04946             hashtb_next(e);
04947     }
04948     hashtb_end(e);
04949 }
04950 
04951 /**
04952  * Destroy the ccnd instance, releasing all associated resources.
04953  */
04954 void
04955 ccnd_destroy(struct ccnd_handle **pccnd)
04956 {
04957     struct ccnd_handle *h = *pccnd;
04958     if (h == NULL)
04959         return;
04960     ccnd_shutdown_listeners(h);
04961     ccnd_internal_client_stop(h);
04962     ccn_schedule_destroy(&h->sched);
04963     hashtb_destroy(&h->dgram_faces);
04964     hashtb_destroy(&h->faces_by_fd);
04965     hashtb_destroy(&h->content_tab);
04966     hashtb_destroy(&h->propagating_tab);
04967     hashtb_destroy(&h->nameprefix_tab);
04968     hashtb_destroy(&h->sparse_straggler_tab);
04969     if (h->fds != NULL) {
04970         free(h->fds);
04971         h->fds = NULL;
04972         h->nfds = 0;
04973     }
04974     if (h->faces_by_faceid != NULL) {
04975         free(h->faces_by_faceid);
04976         h->faces_by_faceid = NULL;
04977         h->face_limit = h->face_gen = 0;
04978     }
04979     if (h->content_by_accession != NULL) {
04980         free(h->content_by_accession);
04981         h->content_by_accession = NULL;
04982         h->content_by_accession_window = 0;
04983     }
04984     ccn_charbuf_destroy(&h->scratch_charbuf);
04985     ccn_charbuf_destroy(&h->autoreg);
04986     ccn_indexbuf_destroy(&h->skiplinks);
04987     ccn_indexbuf_destroy(&h->scratch_indexbuf);
04988     ccn_indexbuf_destroy(&h->unsol);
04989     if (h->face0 != NULL) {
04990         ccn_charbuf_destroy(&h->face0->inbuf);
04991         ccn_charbuf_destroy(&h->face0->outbuf);
04992         free(h->face0);
04993         h->face0 = NULL;
04994     }
04995     free(h);
04996     *pccnd = NULL;
04997 }

Generated on Thu Feb 16 00:43:58 2012 for Content-Centric Networking in C by  doxygen 1.5.6