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