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