ccn_client.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_client.c
00003  * @brief Support for ccn clients.
00004  * 
00005  * Part of the CCNx C Library.
00006  *
00007  * Copyright (C) 2008-2012 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 #include <arpa/inet.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <poll.h>
00024 #include <signal.h>
00025 #include <stdint.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/socket.h>
00030 #include <sys/stat.h>
00031 #include <sys/time.h>
00032 #include <sys/types.h>
00033 #include <sys/un.h>
00034 #include <unistd.h>
00035 #include <openssl/evp.h>
00036 
00037 #include <ccn/ccn.h>
00038 #include <ccn/ccn_private.h>
00039 #include <ccn/ccnd.h>
00040 #include <ccn/charbuf.h>
00041 #include <ccn/coding.h>
00042 #include <ccn/digest.h>
00043 #include <ccn/hashtb.h>
00044 #include <ccn/reg_mgmt.h>
00045 #include <ccn/schedule.h>
00046 #include <ccn/signing.h>
00047 #include <ccn/keystore.h>
00048 #include <ccn/uri.h>
00049 
00050 /* Forward struct declarations */
00051 struct interests_by_prefix;
00052 struct expressed_interest;
00053 struct interest_filter;
00054 struct ccn_reg_closure;
00055 
00056 /**
00057  * Handle representing a connection to ccnd
00058  */
00059 struct ccn {
00060     int sock;
00061     size_t outbufindex;
00062     struct ccn_charbuf *interestbuf;
00063     struct ccn_charbuf *inbuf;
00064     struct ccn_charbuf *outbuf;
00065     struct ccn_charbuf *ccndid;
00066     struct hashtb *interests_by_prefix;
00067     struct hashtb *interest_filters;
00068     struct ccn_skeleton_decoder decoder;
00069     struct ccn_indexbuf *scratch_indexbuf;
00070     struct hashtb *keys;    /* public keys, by pubid */
00071     struct hashtb *keystores;   /* unlocked private keys */
00072     struct ccn_charbuf *default_pubid;
00073     struct ccn_schedule *schedule;
00074     struct timeval now;
00075     int timeout;
00076     int refresh_us;
00077     int err;                    /* pos => errno value, neg => other */
00078     int errline;
00079     int verbose_error;
00080     int tap;
00081     int running;
00082     int defer_verification;     /* Client wants to do its own verification */
00083 };
00084 
00085 struct interests_by_prefix { /* keyed by components of name prefix */
00086     struct expressed_interest *list;
00087 };
00088 
00089 struct expressed_interest {
00090     int magic;                   /* for sanity checking */
00091     struct timeval lasttime;     /* time most recently expressed */
00092     struct ccn_closure *action;  /* handler for incoming content */
00093     unsigned char *interest_msg; /* the interest message as sent */
00094     size_t size;                 /* its size in bytes */
00095     int target;                  /* how many we want outstanding (0 or 1) */
00096     int outstanding;             /* number currently outstanding (0 or 1) */
00097     int lifetime_us;             /* interest lifetime in microseconds */
00098     struct ccn_charbuf *wanted_pub; /* waiting for this pub to arrive */
00099     struct expressed_interest *next; /* link to next in list */
00100 };
00101 
00102 /**
00103  * Data field for entries in the interest_filters hash table
00104  */
00105 struct interest_filter { /* keyed by components of name */
00106     struct ccn_closure *action;
00107     struct ccn_reg_closure *ccn_reg_closure;
00108     struct timeval expiry;       /* Time that refresh will be needed */
00109     int flags;
00110 };
00111 #define CCN_FORW_WAITING_CCNDID (1<<30)
00112 
00113 struct ccn_reg_closure {
00114     struct ccn_closure action;
00115     struct interest_filter *interest_filter; /* Backlink */
00116 };
00117 
00118 /* Macros */
00119 
00120 #define NOTE_ERR(h, e) (h->err = (e), h->errline = __LINE__, ccn_note_err(h))
00121 #define NOTE_ERRNO(h) NOTE_ERR(h, errno)
00122 
00123 #define THIS_CANNOT_HAPPEN(h) \
00124     do { NOTE_ERR(h, -73); ccn_perror(h, "Can't happen");} while (0)
00125 
00126 #define XXX \
00127     do { NOTE_ERR(h, -76); ccn_perror(h, "Please write some more code here"); } while (0)
00128 
00129 /* Prototypes */
00130 
00131 static void ccn_refresh_interest(struct ccn *, struct expressed_interest *);
00132 static void ccn_initiate_prefix_reg(struct ccn *,
00133                                     const void *, size_t,
00134                                     struct interest_filter *);
00135 static void finalize_pkey(struct hashtb_enumerator *e);
00136 static void finalize_keystore(struct hashtb_enumerator *e);
00137 static int ccn_pushout(struct ccn *h);
00138 static void update_ifilt_flags(struct ccn *, struct interest_filter *, int);
00139 static int update_multifilt(struct ccn *,
00140                             struct interest_filter *,
00141                             struct ccn_closure *,
00142                             int);
00143 /**
00144  * Compare two timvals
00145  */
00146 static int
00147 tv_earlier(const struct timeval *a, const struct timeval *b)
00148 {
00149     if (a->tv_sec > b->tv_sec)
00150         return(0);
00151     if (a->tv_sec < b->tv_sec)
00152         return(1);
00153     return(a->tv_usec < b->tv_usec);
00154 }
00155 
00156 /**
00157  * Produce message on standard error output describing the last
00158  * error encountered during a call using the given handle.
00159  * @param h is the ccn handle - may not be NULL.
00160  * @param s is a client-supplied message; if NULL a message will be supplied
00161  *        where available.
00162  */
00163 void
00164 ccn_perror(struct ccn *h, const char *s)
00165 {
00166     const char *dlm = ": ";
00167     if (s == NULL) {
00168         if (h->err > 0)
00169             s = strerror(h->err);
00170         else
00171             dlm = s = "";
00172     }
00173     // XXX - time stamp
00174     fprintf(stderr, "ccn_client.c:%d[%d] - error %d%s%s\n",
00175                         h->errline, (int)getpid(), h->err, dlm, s);
00176 }
00177 
00178 static int
00179 ccn_note_err(struct ccn *h)
00180 {
00181     if (h->verbose_error)
00182         ccn_perror(h, NULL);
00183     return(-1);
00184 }
00185 
00186 /**
00187  * Set the error code in a ccn handle.
00188  * @param h is the ccn handle - may be NULL.
00189  * @param error_code is the code to set.
00190  * @returns -1 in all cases.
00191  */
00192 int
00193 ccn_seterror(struct ccn *h, int error_code)
00194 {
00195     if (h == NULL)
00196         return(-1);
00197     h->err = error_code;
00198     h->errline = 0;
00199     if (error_code != 0)
00200         ccn_note_err(h);
00201     return(-1);
00202 }
00203 
00204 /**
00205  * Recover last error code.
00206  * @param h is the ccn handle - may be NULL.
00207  * @returns the most recently set error code, or 0 if h is NULL.
00208  */
00209 int
00210 ccn_geterror(struct ccn *h)
00211 {
00212     if (h == NULL)
00213         return(0);
00214     return(h->err);
00215 }
00216 
00217 static struct ccn_indexbuf *
00218 ccn_indexbuf_obtain(struct ccn *h)
00219 {
00220     struct ccn_indexbuf *c = h->scratch_indexbuf;
00221     if (c == NULL)
00222         return(ccn_indexbuf_create());
00223     h->scratch_indexbuf = NULL;
00224     c->n = 0;
00225     return(c);
00226 }
00227 
00228 static void
00229 ccn_indexbuf_release(struct ccn *h, struct ccn_indexbuf *c)
00230 {
00231     c->n = 0;
00232     if (h->scratch_indexbuf == NULL)
00233         h->scratch_indexbuf = c;
00234     else
00235         ccn_indexbuf_destroy(&c);
00236 }
00237 
00238 /**
00239  * Do the refcount updating for closure instances on assignment
00240  *
00241  * When the refcount drops to 0, the closure is told to finalize itself.
00242  */
00243 static void
00244 ccn_replace_handler(struct ccn *h,
00245                     struct ccn_closure **dstp,
00246                     struct ccn_closure *src)
00247 {
00248     struct ccn_closure *old = *dstp;
00249     if (src == old)
00250         return;
00251     if (src != NULL)
00252         src->refcount++;
00253     *dstp = src;
00254     if (old != NULL && (--(old->refcount)) == 0) {
00255         struct ccn_upcall_info info = { 0 };
00256         info.h = h;
00257         (old->p)(old, CCN_UPCALL_FINAL, &info);
00258     }
00259 }
00260 
00261 /**
00262  * Create a client handle.
00263  * The new handle is not yet connected.
00264  * On error, returns NULL and sets errno.
00265  * Errors: ENOMEM
00266  */ 
00267 struct ccn *
00268 ccn_create(void)
00269 {
00270     struct ccn *h;
00271     const char *s;
00272     struct hashtb_param param = {0};
00273 
00274     h = calloc(1, sizeof(*h));
00275     if (h == NULL)
00276         return(h);
00277     param.finalize_data = h;
00278     h->sock = -1;
00279     h->interestbuf = ccn_charbuf_create();
00280     param.finalize = &finalize_pkey;
00281     h->keys = hashtb_create(sizeof(struct ccn_pkey *), &param);
00282     param.finalize = &finalize_keystore;
00283     h->keystores = hashtb_create(sizeof(struct ccn_keystore *), &param);
00284     s = getenv("CCN_DEBUG");
00285     h->verbose_error = (s != NULL && s[0] != 0);
00286     s = getenv("CCN_TAP");
00287     if (s != NULL && s[0] != 0) {
00288     char tap_name[255];
00289     struct timeval tv;
00290     gettimeofday(&tv, NULL);
00291         if (snprintf(tap_name, 255, "%s-%d-%d-%d", s, (int)getpid(),
00292                      (int)tv.tv_sec, (int)tv.tv_usec) >= 255) {
00293             fprintf(stderr, "CCN_TAP path is too long: %s\n", s);
00294         } else {
00295             h->tap = open(tap_name, O_WRONLY|O_APPEND|O_CREAT, S_IRWXU);
00296             if (h->tap == -1) {
00297                 NOTE_ERRNO(h);
00298                 ccn_perror(h, "Unable to open CCN_TAP file");
00299             }
00300             else
00301                 fprintf(stderr, "CCN_TAP writing to %s\n", tap_name);
00302         }
00303     } else
00304         h->tap = -1;
00305     h->defer_verification = 0;
00306     OpenSSL_add_all_algorithms();
00307     return(h);
00308 }
00309 
00310 /**
00311  * Tell the library to defer verification.
00312  *
00313  * For some specialized applications (performance testing being an example),
00314  * the normal verification done within the library may be undesirable.
00315  * Setting the "defer validation" flag will cause the library to pass content
00316  * to the application without attempting to verify it. In this case,
00317  * the CCN_UPCALL_CONTENT_RAW upcall kind will be passed instead of
00318  * CCN_UPCALL_CONTENT, and CCN_UPCALL_CONTENT_KEYMISSING instead of
00319  * CCN_UPCALL_CONTENT_UNVERIFIED.  If the application wants do still do
00320  * key fetches, it may use the CCN_UPCALL_RESULT_FETCHKEY response instead
00321  * of CCN_UPCALL_RESULT_VERIFY.
00322  *
00323  * Calling this while there are interests outstanding is not recommended.
00324  * 
00325  * This call is available beginning with CCN_API_VERSION 4004.
00326  *
00327  * @param defer is 0 to verify, 1 to defer, -1 to leave unchanged.
00328  * @returns previous value, or -1 in case of error.
00329  */
00330 int
00331 ccn_defer_verification(struct ccn *h, int defer)
00332 {
00333     int old;
00334 
00335     if (h == NULL || defer > 1 || defer < -1)
00336         return(-1);
00337     old = h->defer_verification;
00338     if (defer >= 0)
00339         h->defer_verification = defer;
00340     return(old);
00341 }
00342 
00343 /**
00344  * Connect to local ccnd.
00345  * @param h is a ccn library handle
00346  * @param name is the name of the unix-domain socket to connect to;
00347  *             use NULL to get the default.
00348  * @returns the fd for the connection, or -1 for error.
00349  */ 
00350 int
00351 ccn_connect(struct ccn *h, const char *name)
00352 {
00353     struct sockaddr_un addr = {0};
00354     int res;
00355     if (h == NULL)
00356         return(-1);
00357     h->err = 0;
00358     if (h->sock != -1)
00359         return(NOTE_ERR(h, EINVAL));
00360     addr.sun_family = AF_UNIX;
00361     if (name == NULL || name[0] == 0)
00362         ccn_setup_sockaddr_un(NULL, &addr);
00363     else {
00364         addr.sun_family = AF_UNIX;
00365         strncpy(addr.sun_path, name, sizeof(addr.sun_path));
00366     }
00367     h->sock = socket(AF_UNIX, SOCK_STREAM, 0);
00368     if (h->sock == -1)
00369         return(NOTE_ERRNO(h));
00370     res = connect(h->sock, (struct sockaddr *)&addr, sizeof(addr));
00371     if (res == -1)
00372         return(NOTE_ERRNO(h));
00373     res = fcntl(h->sock, F_SETFL, O_NONBLOCK);
00374     if (res == -1)
00375         return(NOTE_ERRNO(h));
00376     return(h->sock);
00377 }
00378 
00379 int
00380 ccn_get_connection_fd(struct ccn *h)
00381 {
00382     return(h->sock);
00383 }
00384 
00385 int
00386 ccn_disconnect(struct ccn *h)
00387 {
00388     int res;
00389     res = ccn_pushout(h);
00390     if (res == 1) {
00391         res = fcntl(h->sock, F_SETFL, 0); /* clear O_NONBLOCK */
00392         if (res == 0)
00393             ccn_pushout(h);
00394     }
00395     ccn_charbuf_destroy(&h->inbuf);
00396     ccn_charbuf_destroy(&h->outbuf);
00397     res = close(h->sock);
00398     h->sock = -1;
00399     if (res == -1)
00400         return(NOTE_ERRNO(h));
00401     return(0);
00402 }
00403 
00404 static void
00405 ccn_gripe(struct expressed_interest *i)
00406 {
00407     fprintf(stderr, "BOTCH - (struct expressed_interest *)%p has bad magic value\n", (void *)i);
00408 }
00409 
00410 static void
00411 replace_interest_msg(struct expressed_interest *interest,
00412                      struct ccn_charbuf *cb)
00413 {
00414     if (interest->magic != 0x7059e5f4) {
00415         ccn_gripe(interest);
00416         return;
00417     }
00418     if (interest->interest_msg != NULL)
00419         free(interest->interest_msg);
00420     interest->interest_msg = NULL;
00421     interest->size = 0;
00422     if (cb != NULL && cb->length > 0) {
00423         interest->interest_msg = calloc(1, cb->length);
00424         if (interest->interest_msg != NULL) {
00425             memcpy(interest->interest_msg, cb->buf, cb->length);
00426             interest->size = cb->length;
00427         }
00428     }
00429 }
00430 
00431 static struct expressed_interest *
00432 ccn_destroy_interest(struct ccn *h, struct expressed_interest *i)
00433 {
00434     struct expressed_interest *ans = i->next;
00435     if (i->magic != 0x7059e5f4) {
00436         ccn_gripe(i);
00437         return(NULL);
00438     }
00439     ccn_replace_handler(h, &(i->action), NULL);
00440     replace_interest_msg(i, NULL);
00441     ccn_charbuf_destroy(&i->wanted_pub);
00442     i->magic = -1;
00443     free(i);
00444     return(ans);
00445 }
00446 
00447 void
00448 ccn_check_interests(struct expressed_interest *list)
00449 {
00450     struct expressed_interest *ie;
00451     for (ie = list; ie != NULL; ie = ie->next) {
00452         if (ie->magic != 0x7059e5f4) {
00453             ccn_gripe(ie);
00454             abort();
00455         }
00456     }
00457 }
00458 
00459 void
00460 ccn_clean_interests_by_prefix(struct ccn *h, struct interests_by_prefix *entry)
00461 {
00462     struct expressed_interest *ie;
00463     struct expressed_interest *next;
00464     struct expressed_interest **ip;
00465     ccn_check_interests(entry->list);
00466     ip = &(entry->list);
00467     for (ie = entry->list; ie != NULL; ie = next) {
00468         next = ie->next;
00469         if (ie->action == NULL)
00470             ccn_destroy_interest(h, ie);
00471         else {
00472             (*ip) = ie;
00473             ip = &(ie->next);
00474         }
00475     }
00476     (*ip) = NULL;
00477     ccn_check_interests(entry->list);
00478 }
00479 
00480 void
00481 ccn_destroy(struct ccn **hp)
00482 {
00483     struct hashtb_enumerator ee;
00484     struct hashtb_enumerator *e = &ee;
00485     struct ccn *h = *hp;
00486     if (h == NULL)
00487         return;
00488     ccn_schedule_destroy(&h->schedule);
00489     ccn_disconnect(h);
00490     if (h->interests_by_prefix != NULL) {
00491         for (hashtb_start(h->interests_by_prefix, e); e->data != NULL; hashtb_next(e)) {
00492             struct interests_by_prefix *entry = e->data;
00493             while (entry->list != NULL)
00494                 entry->list = ccn_destroy_interest(h, entry->list);
00495         }
00496         hashtb_end(e);
00497         hashtb_destroy(&(h->interests_by_prefix));
00498     }
00499     if (h->interest_filters != NULL) {
00500         for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
00501             struct interest_filter *i = e->data;
00502             ccn_replace_handler(h, &(i->action), NULL);
00503         }
00504         hashtb_end(e);
00505         hashtb_destroy(&(h->interest_filters));
00506     }
00507     hashtb_destroy(&(h->keys));
00508     hashtb_destroy(&(h->keystores));
00509     ccn_charbuf_destroy(&h->interestbuf);
00510     ccn_charbuf_destroy(&h->inbuf);
00511     ccn_charbuf_destroy(&h->outbuf);
00512     ccn_indexbuf_destroy(&h->scratch_indexbuf);
00513     ccn_charbuf_destroy(&h->default_pubid);
00514     ccn_charbuf_destroy(&h->ccndid);
00515     if (h->tap != -1)
00516         close(h->tap);
00517     free(h);
00518     *hp = NULL;
00519     EVP_cleanup();
00520 }
00521 
00522 /*
00523  * ccn_check_namebuf: check that name is valid
00524  * Returns the byte offset of the end of prefix portion,
00525  * as given by prefix_comps, or -1 for error.
00526  * prefix_comps = -1 means the whole name is the prefix.
00527  * If omit_possible_digest, chops off a potential digest name at the end
00528  */
00529 static int
00530 ccn_check_namebuf(struct ccn *h, struct ccn_charbuf *namebuf, int prefix_comps,
00531                   int omit_possible_digest)
00532 {
00533     struct ccn_buf_decoder decoder;
00534     struct ccn_buf_decoder *d;
00535     int i = 0;
00536     int ans = 0;
00537     int prev_ans = 0;
00538     if (namebuf == NULL || namebuf->length < 2)
00539         return(-1);
00540     d = ccn_buf_decoder_start(&decoder, namebuf->buf, namebuf->length);
00541     if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00542         ccn_buf_advance(d);
00543         prev_ans = ans = d->decoder.token_index;
00544         while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00545             ccn_buf_advance(d);
00546             if (ccn_buf_match_blob(d, NULL, NULL)) {
00547                 ccn_buf_advance(d);
00548             }
00549             ccn_buf_check_close(d);
00550             i += 1;
00551             if (prefix_comps < 0 || i <= prefix_comps) {
00552                 prev_ans = ans;
00553                 ans = d->decoder.token_index;
00554             }
00555         }
00556         ccn_buf_check_close(d);
00557     }
00558     if (d->decoder.state < 0 || ans < prefix_comps)
00559         return(-1);
00560     if (omit_possible_digest && ans == prev_ans + 36 && ans == namebuf->length - 1)
00561         return(prev_ans);
00562     return(ans);
00563 }
00564 
00565 static void
00566 ccn_construct_interest(struct ccn *h,
00567                        struct ccn_charbuf *name_prefix,
00568                        struct ccn_charbuf *interest_template,
00569                        struct expressed_interest *dest)
00570 {
00571     struct ccn_charbuf *c = h->interestbuf;
00572     size_t start;
00573     size_t size;
00574     int res;
00575     
00576     dest->lifetime_us = CCN_INTEREST_LIFETIME_MICROSEC;
00577     c->length = 0;
00578     ccn_charbuf_append_tt(c, CCN_DTAG_Interest, CCN_DTAG);
00579     ccn_charbuf_append(c, name_prefix->buf, name_prefix->length);
00580     res = 0;
00581     if (interest_template != NULL) {
00582         struct ccn_parsed_interest pi = { 0 };
00583         res = ccn_parse_interest(interest_template->buf,
00584                                  interest_template->length, &pi, NULL);
00585         if (res >= 0) {
00586             intmax_t lifetime = ccn_interest_lifetime(interest_template->buf, &pi);
00587             // XXX - for now, don't try to handle lifetimes over 30 seconds.
00588             if (lifetime < 1 || lifetime > (30 << 12))
00589                 NOTE_ERR(h, EINVAL);
00590             else
00591                 dest->lifetime_us = (lifetime * 1000000) >> 12;
00592             start = pi.offset[CCN_PI_E_Name];
00593             size = pi.offset[CCN_PI_B_Nonce] - start;
00594             ccn_charbuf_append(c, interest_template->buf + start, size);
00595             start = pi.offset[CCN_PI_B_OTHER];
00596             size = pi.offset[CCN_PI_E_OTHER] - start;
00597             if (size != 0)
00598                 ccn_charbuf_append(c, interest_template->buf + start, size);
00599         }
00600         else
00601             NOTE_ERR(h, EINVAL);
00602     }
00603     ccn_charbuf_append_closer(c);
00604     replace_interest_msg(dest, (res >= 0 ? c : NULL));
00605 }
00606 
00607 int
00608 ccn_express_interest(struct ccn *h,
00609                      struct ccn_charbuf *namebuf,
00610                      struct ccn_closure *action,
00611                      struct ccn_charbuf *interest_template)
00612 {
00613     struct hashtb_enumerator ee;
00614     struct hashtb_enumerator *e = &ee;
00615     int res;
00616     int prefixend;
00617     struct expressed_interest *interest = NULL;
00618     struct interests_by_prefix *entry = NULL;
00619     if (h->interests_by_prefix == NULL) {
00620         h->interests_by_prefix = hashtb_create(sizeof(struct interests_by_prefix), NULL);
00621         if (h->interests_by_prefix == NULL)
00622             return(NOTE_ERRNO(h));
00623     }
00624     prefixend = ccn_check_namebuf(h, namebuf, -1, 1);
00625     if (prefixend < 0)
00626         return(prefixend);
00627     /*
00628      * To make it easy to lookup prefixes of names, we keep only
00629      * the prefix name components as the key in the hash table.
00630      */
00631     hashtb_start(h->interests_by_prefix, e);
00632     res = hashtb_seek(e, namebuf->buf + 1, prefixend - 1, 0);
00633     entry = e->data;
00634     if (entry == NULL) {
00635         NOTE_ERRNO(h);
00636         hashtb_end(e);
00637         return(res);
00638     }
00639     if (res == HT_NEW_ENTRY)
00640         entry->list = NULL;
00641     interest = calloc(1, sizeof(*interest));
00642     if (interest == NULL) {
00643         NOTE_ERRNO(h);
00644         hashtb_end(e);
00645         return(-1);
00646     }
00647     interest->magic = 0x7059e5f4;
00648     ccn_construct_interest(h, namebuf, interest_template, interest);
00649     if (interest->interest_msg == NULL) {
00650         free(interest);
00651         hashtb_end(e);
00652         return(-1);
00653     }
00654     ccn_replace_handler(h, &(interest->action), action);
00655     interest->target = 1;
00656     interest->next = entry->list;
00657     entry->list = interest;
00658     hashtb_end(e);
00659     /* Actually send the interest out right away */
00660     ccn_refresh_interest(h, interest);
00661     return(0);
00662 }
00663 
00664 static void
00665 finalize_interest_filter(struct hashtb_enumerator *e)
00666 {
00667     struct interest_filter *i = e->data;
00668     if (i->ccn_reg_closure != NULL) {
00669         i->ccn_reg_closure->interest_filter = NULL;
00670         i->ccn_reg_closure = NULL;
00671     }
00672 }
00673 
00674 /**
00675  * Register to receive interests on a prefix, with forwarding flags
00676  *
00677  * See ccn_set_interest_filter for a description of the basic operation.
00678  *
00679  * The additional forw_flags argument offers finer control of which
00680  * interests are forward to the application.
00681  * Refer to doc/technical/Registration for details.
00682  *
00683  * There may be multiple actions associated with the prefix.  They will be
00684  * called in an unspecified order.  The flags passed to ccnd will be
00685  * the inclusive-or of the flags associated with each action.
00686  *
00687  * Passing a value of 0 for forw_flags will unregister just this specific action,
00688  * leaving other actions untouched.
00689  *
00690  * @returns -1 in case of error, non-negative for success.
00691  */
00692 int
00693 ccn_set_interest_filter_with_flags(struct ccn *h, struct ccn_charbuf *namebuf,
00694                         struct ccn_closure *action, int forw_flags)
00695 {
00696     struct hashtb_enumerator ee;
00697     struct hashtb_enumerator *e = &ee;
00698     int res;
00699     struct interest_filter *entry;
00700     
00701     if (h->interest_filters == NULL) {
00702         struct hashtb_param param = {0};
00703         param.finalize = &finalize_interest_filter;
00704         h->interest_filters = hashtb_create(sizeof(struct interest_filter), &param);
00705         if (h->interest_filters == NULL)
00706             return(NOTE_ERRNO(h));
00707     }
00708     res = ccn_check_namebuf(h, namebuf, -1, 0);
00709     if (res < 0)
00710         return(res);
00711     hashtb_start(h->interest_filters, e);
00712     res = hashtb_seek(e, namebuf->buf + 1, namebuf->length - 2, 0);
00713     if (res >= 0) {
00714         entry = e->data;
00715         if (entry->action != NULL && action != NULL && action != entry->action)
00716             res = update_multifilt(h, entry, action, forw_flags);
00717         else {
00718             update_ifilt_flags(h, entry, forw_flags);
00719             ccn_replace_handler(h, &(entry->action), action);
00720         }
00721         if (entry->action == NULL)
00722             hashtb_delete(e);
00723     }
00724     hashtb_end(e);
00725     return(res);
00726 }
00727 
00728 /**
00729  * Register to receive interests on a prefix
00730  *
00731  * The action will be called upon the arrival of an interest that
00732  * has the given name as a prefix.
00733  *
00734  * If action is NULL, any existing filter for the prefix is removed.
00735  * Note that this may have undesirable effects in applications that share
00736  * the same handle for independently operating subcomponents.
00737  * See ccn_set_interest_filter_with_flags() for a way to deal with this.
00738  * 
00739  * The contents of namebuf are copied as needed.
00740  *
00741  * The handler should return CCN_UPCALL_RESULT_INTEREST_CONSUMED as a
00742  * promise that it has produced, or will soon produce, a matching content
00743  * object.
00744  *
00745  * The upcall kind passed to the handler will be CCN_UPCALL_INTEREST
00746  * if no other handler has claimed to produce content, or else
00747  * CCN_UPCALL_CONSUMED_INTEREST.
00748  *
00749  * This call is equivalent to a call to ccn_set_interest_filter_with_flags,
00750  * passing the forwarding flags (CCN_FORW_ACTIVE | CCN_FORW_CHILD_INHERIT).
00751  *
00752  * @returns -1 in case of error, non-negative for success.
00753  */
00754 int
00755 ccn_set_interest_filter(struct ccn *h, struct ccn_charbuf *namebuf,
00756                         struct ccn_closure *action)
00757 {
00758     int forw_flags = CCN_FORW_ACTIVE | CCN_FORW_CHILD_INHERIT;
00759     return(ccn_set_interest_filter_with_flags(h, namebuf, action, forw_flags));
00760 }
00761 
00762 /**
00763  * Change forwarding flags, triggering a refresh as needed.
00764  */
00765 static void
00766 update_ifilt_flags(struct ccn *h, struct interest_filter *f, int forw_flags)
00767 {
00768     if (f->flags != forw_flags) {
00769         memset(&f->expiry, 0, sizeof(f->expiry));
00770         f->flags = forw_flags;
00771     }
00772 }
00773 
00774 /* * * multifilt * * */
00775 
00776 /**
00777  * Item in the array of interest filters associated with one prefix
00778  */
00779 struct multifilt_item {
00780     struct ccn_closure *action;
00781     int forw_flags;
00782 };
00783 
00784 /**
00785  * Data for the multifilt case
00786  *
00787  * This wraps multiple interest filters up as a single one, so they
00788  * can share the single slot in a struct interest_filter.
00789  */
00790 struct multifilt {
00791     struct ccn_closure me;
00792     int n;                      /**< Number of elements in a */
00793     struct multifilt_item *a;   /**< The filters that are to be combined */
00794 };
00795 
00796 /* Prototypes */
00797 static enum ccn_upcall_res handle_multifilt(struct ccn_closure *selfp,
00798                                             enum ccn_upcall_kind kind,
00799                                             struct ccn_upcall_info *info);
00800 static int build_multifilt_array(struct ccn *h,
00801                                  struct multifilt_item **ap,
00802                                  int n,
00803                                  struct ccn_closure *action,
00804                                  int forw_flags);
00805 static void destroy_multifilt_array(struct ccn *h,
00806                                     struct multifilt_item **ap,
00807                                     int n);
00808 
00809 /**
00810  * Take care of the case of multiple filters registered on one prefix
00811  *
00812  * Avoid calling when either action or f->action is NULL.
00813  */
00814 static int
00815 update_multifilt(struct ccn *h,
00816                  struct interest_filter *f,
00817                  struct ccn_closure *action,
00818                  int forw_flags)
00819 {
00820     struct multifilt *md = NULL;
00821     struct multifilt_item *a = NULL;
00822     int flags;
00823     int i;
00824     int n = 0;
00825     
00826     if (action->p == &handle_multifilt) {
00827         /* This should never happen. */
00828         abort();
00829     }
00830     if (f->action->p == &handle_multifilt) {
00831         /* Already have a multifilt */
00832         md = f->action->data;
00833         if (md->me.data != md)
00834             abort();
00835         a = md->a;
00836     }
00837     else {
00838         /* Make a new multifilt, with 2 slots */
00839         a = calloc(2, sizeof(*a));
00840         if (a == NULL)
00841             return(NOTE_ERRNO(h));
00842         md = calloc(1, sizeof(*md));
00843         if (md == NULL) {
00844             free(a);
00845             return(NOTE_ERRNO(h));
00846         }
00847         md->me.p = &handle_multifilt;
00848         md->me.data = md;
00849         md->n = 2;
00850         md->a = a;
00851         ccn_replace_handler(h, &(a[0].action), f->action);
00852         a[0].forw_flags = f->flags;
00853         ccn_replace_handler(h, &(a[1].action), action);
00854         a[1].forw_flags = 0; /* Actually set these below */
00855         ccn_replace_handler(h, &f->action, &md->me);
00856     }
00857     /* Search for the action */
00858     for (i = 0; i < n; i++) {
00859         if (a[i].action == action) {
00860             a[i].forw_flags = forw_flags;
00861             if (forw_flags == 0) {
00862                 ccn_replace_handler(h, &(a[i].action), NULL);
00863                 action = NULL;
00864             }
00865             goto Finish;
00866         }
00867     }
00868     /* Not there, but if the flags are 0 we do not need to remember action */
00869     if (forw_flags == 0) {
00870         action->refcount++;
00871         ccn_replace_handler(h, &action, NULL);
00872         goto Finish;
00873     }
00874     /* Need to build a new array */
00875     n = build_multifilt_array(h, &a, n, action, forw_flags);
00876     if (n < 0)
00877         return(n);
00878     destroy_multifilt_array(h, &md->a, md->n);
00879     md->a = a;
00880     md->n = n;
00881 Finish:
00882     /* The only thing left to do is to combine the forwarding flags */
00883     for (i = 0, flags = 0; i < n; i++)
00884         flags |= a[i].forw_flags;
00885     update_ifilt_flags(h, f, flags);
00886     return(0);
00887 }
00888 
00889 /**
00890  * Replace *ap with a copy, perhaps with one additional element
00891  *
00892  * The old array is not modified.  Empty slots are not copied.
00893  *
00894  * @returns new count, or -1 in case of an error.
00895  */
00896 static int
00897 build_multifilt_array(struct ccn *h,
00898                       struct multifilt_item **ap,
00899                       int n,
00900                       struct ccn_closure *action,
00901                       int forw_flags)
00902 {
00903     struct multifilt_item *a = NULL; /* old array */
00904     struct multifilt_item *c = NULL; /* new array */
00905     int i, j, m;
00906     
00907     a = *ap;
00908     /* Determine how many slots we will need */
00909     for (m = 0, i = 0; i < n; i++) {
00910         if (a[i].action != NULL)
00911             m++;
00912     }
00913     if (action != NULL)
00914         m++;
00915     if (m == 0) {
00916         *ap = NULL;
00917         return(0);
00918     }
00919     c = calloc(m, sizeof(*c));
00920     if (c == NULL)
00921         return(NOTE_ERRNO(h));
00922     for (i = 0, j = 0; i < n; i++) {
00923         if (a[i].action != NULL) {
00924             ccn_replace_handler(h, &(c[j].action), a[i].action);
00925             c[j].forw_flags = a[i].forw_flags;
00926             j++;
00927         }
00928     }
00929     if (j < m) {
00930         ccn_replace_handler(h, &(c[j].action), action);
00931         c[j].forw_flags = forw_flags;
00932     }
00933     *ap = c;
00934     return(m);
00935 }
00936 
00937 /**
00938  * Destroy a multifilt_array
00939  */
00940 static void
00941 destroy_multifilt_array(struct ccn *h, struct multifilt_item **ap, int n)
00942 {
00943     struct multifilt_item *a;
00944     int i;
00945     
00946     a = *ap;
00947     if (a != NULL) {
00948         for (i = 0; i < n; i++)
00949             ccn_replace_handler(h, &(a[i].action), NULL);
00950         free(a);
00951         *ap = NULL;
00952     }
00953 }
00954 
00955 /**
00956  * Upcall to handle multifilt
00957  */
00958 static enum ccn_upcall_res
00959 handle_multifilt(struct ccn_closure *selfp,
00960                  enum ccn_upcall_kind kind,
00961                  struct ccn_upcall_info *info)
00962 {
00963     struct multifilt *md;
00964     struct multifilt_item *a;
00965     enum ccn_upcall_res ans;
00966     enum ccn_upcall_res res;
00967     int i, n;
00968     
00969     md = selfp->data;
00970     if (kind == CCN_UPCALL_FINAL) {
00971         destroy_multifilt_array(info->h, &md->a, md->n);
00972         free(md);
00973         return(CCN_UPCALL_RESULT_OK);
00974     }
00975     /*
00976      * Since the upcalls might be changing registrations on the fly,
00977      * we need to make a copy of the array (updating the refcounts).
00978      * Forget md and selfp, since they could go away during upcalls.
00979      */
00980     a = md->a;
00981     n = build_multifilt_array(info->h, &a, md->n, NULL, 0);
00982     ans = CCN_UPCALL_RESULT_OK;
00983     md = NULL;
00984     selfp = NULL;
00985     for (i = 0; i < n; i++) {
00986         if ((a[i].forw_flags & CCN_FORW_ACTIVE) != 0) {
00987             res = (a[i].action->p)(a[i].action, kind, info);
00988             if (res == CCN_UPCALL_RESULT_INTEREST_CONSUMED) {
00989                 ans = res;
00990                 if (kind == CCN_UPCALL_INTEREST)
00991                     kind = CCN_UPCALL_CONSUMED_INTEREST;
00992             }
00993         }
00994     }
00995     destroy_multifilt_array(info->h, &a, n);
00996     return(ans);
00997 }
00998 
00999 /* end of multifilt */
01000 
01001 static int
01002 ccn_pushout(struct ccn *h)
01003 {
01004     ssize_t res;
01005     size_t size;
01006     if (h->outbuf != NULL && h->outbufindex < h->outbuf->length) {
01007         if (h->sock < 0)
01008             return(1);
01009         size = h->outbuf->length - h->outbufindex;
01010         res = write(h->sock, h->outbuf->buf + h->outbufindex, size);
01011         if (res == size) {
01012             h->outbuf->length = h->outbufindex = 0;
01013             return(0);
01014         }
01015         if (res == -1)
01016             return ((errno == EAGAIN) ? 1 : NOTE_ERRNO(h));
01017         h->outbufindex += res;
01018         return(1);
01019     }
01020     return(0);
01021 }
01022 
01023 int
01024 ccn_put(struct ccn *h, const void *p, size_t length)
01025 {
01026     struct ccn_skeleton_decoder dd = {0};
01027     ssize_t res;
01028     if (h == NULL)
01029         return(-1);
01030     if (p == NULL || length == 0)
01031         return(NOTE_ERR(h, EINVAL));
01032     res = ccn_skeleton_decode(&dd, p, length);
01033     if (!(res == length && dd.state == 0))
01034         return(NOTE_ERR(h, EINVAL));
01035     if (h->tap != -1) {
01036         res = write(h->tap, p, length);
01037         if (res == -1) {
01038             NOTE_ERRNO(h);
01039             (void)close(h->tap);
01040             h->tap = -1;
01041         }
01042     }
01043     if (h->outbuf != NULL && h->outbufindex < h->outbuf->length) {
01044         // XXX - should limit unbounded growth of h->outbuf
01045         ccn_charbuf_append(h->outbuf, p, length); // XXX - check res
01046         return (ccn_pushout(h));
01047     }
01048     if (h->sock == -1)
01049         res = 0;
01050     else
01051         res = write(h->sock, p, length);
01052     if (res == length)
01053         return(0);
01054     if (res == -1) {
01055         if (errno != EAGAIN)
01056             return(NOTE_ERRNO(h));
01057         res = 0;
01058     }
01059     if (h->outbuf == NULL) {
01060         h->outbuf = ccn_charbuf_create();
01061         h->outbufindex = 0;
01062     }
01063     ccn_charbuf_append(h->outbuf, ((const unsigned char *)p)+res, length-res);
01064     return(1);
01065 }
01066 
01067 int
01068 ccn_output_is_pending(struct ccn *h)
01069 {
01070     return(h != NULL && h->outbuf != NULL && h->outbufindex < h->outbuf->length);
01071 }
01072 
01073 struct ccn_charbuf *
01074 ccn_grab_buffered_output(struct ccn *h)
01075 {
01076     if (ccn_output_is_pending(h) && h->outbufindex == 0) {
01077         struct ccn_charbuf *ans = h->outbuf;
01078         h->outbuf = NULL;
01079         return(ans);
01080     }
01081     return(NULL);
01082 }
01083 
01084 static void
01085 ccn_refresh_interest(struct ccn *h, struct expressed_interest *interest)
01086 {
01087     int res;
01088     if (interest->magic != 0x7059e5f4) {
01089         ccn_gripe(interest);
01090         return;
01091     }
01092     if (interest->outstanding < interest->target) {
01093         res = ccn_put(h, interest->interest_msg, interest->size);
01094         if (res >= 0) {
01095             interest->outstanding += 1;
01096             if (h->now.tv_sec == 0)
01097                 gettimeofday(&h->now, NULL);
01098             interest->lasttime = h->now;
01099         }
01100     }
01101 }
01102 
01103 static int
01104 ccn_get_content_type(const unsigned char *ccnb,
01105                      const struct ccn_parsed_ContentObject *pco)
01106 {
01107     enum ccn_content_type type = pco->type;
01108     (void)ccnb; // XXX - don't need now
01109     switch (type) {
01110         case CCN_CONTENT_DATA:
01111         case CCN_CONTENT_ENCR:
01112         case CCN_CONTENT_GONE:
01113         case CCN_CONTENT_KEY:
01114         case CCN_CONTENT_LINK:
01115         case CCN_CONTENT_NACK:
01116             return (type);
01117         default:
01118             return (-1);
01119     }
01120 }
01121 
01122 /**
01123  * Compute the digest of just the Content portion of content_object.
01124  */
01125 static void
01126 ccn_digest_Content(const unsigned char *content_object,
01127                    struct ccn_parsed_ContentObject *pc,
01128                    unsigned char *digest,
01129                    size_t digest_bytes)
01130 {
01131     int res;
01132     struct ccn_digest *d = NULL;
01133     const unsigned char *content = NULL;
01134     size_t content_bytes = 0;
01135     
01136     if (pc->magic < 20080000) abort();
01137     if (digest_bytes == sizeof(digest))
01138         return;
01139     d = ccn_digest_create(CCN_DIGEST_SHA256);
01140     ccn_digest_init(d);
01141     res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_object,
01142                               pc->offset[CCN_PCO_B_Content],
01143                               pc->offset[CCN_PCO_E_Content],
01144                               &content, &content_bytes);
01145     if (res < 0) abort();
01146     res = ccn_digest_update(d, content, content_bytes);
01147     if (res < 0) abort();
01148     res = ccn_digest_final(d, digest, digest_bytes);
01149     if (res < 0) abort();
01150     ccn_digest_destroy(&d);
01151 }
01152 
01153 static int
01154 ccn_cache_key(struct ccn *h,
01155               const unsigned char *ccnb, size_t size,
01156               struct ccn_parsed_ContentObject *pco)
01157 {
01158     int type;
01159     struct ccn_pkey **entry;
01160     struct hashtb_enumerator ee;
01161     struct hashtb_enumerator *e = &ee;
01162     int res;
01163     unsigned char digest[32];
01164 
01165     type = ccn_get_content_type(ccnb, pco);
01166     if (type != CCN_CONTENT_KEY) {
01167         return (0);
01168     }
01169 
01170     ccn_digest_Content(ccnb, pco, digest, sizeof(digest));
01171 
01172     hashtb_start(h->keys, e);
01173     res = hashtb_seek(e, (void *)digest, sizeof(digest), 0);
01174     if (res < 0) {
01175         hashtb_end(e);
01176         return(NOTE_ERRNO(h));
01177     }
01178     entry = e->data;
01179     if (res == HT_NEW_ENTRY) {
01180         struct ccn_pkey *pkey;
01181         const unsigned char *data = NULL;
01182         size_t data_size = 0;
01183 
01184         res = ccn_content_get_value(ccnb, size, pco, &data, &data_size);
01185         if (res < 0) {
01186             hashtb_delete(e);
01187             hashtb_end(e);
01188             return(NOTE_ERRNO(h));
01189         }
01190         pkey = ccn_d2i_pubkey(data, data_size);
01191         if (pkey == NULL) {
01192             hashtb_delete(e);
01193             hashtb_end(e);
01194             return(NOTE_ERRNO(h));
01195         }
01196         *entry = pkey;
01197     }
01198     hashtb_end(e);
01199     return (0);
01200 }
01201 
01202 static void
01203 finalize_pkey(struct hashtb_enumerator *e)
01204 {
01205     struct ccn_pkey **entry = e->data;
01206     if (*entry != NULL)
01207         ccn_pubkey_free(*entry);
01208 }
01209 
01210 /**
01211  * Examine a ContentObject and try to find the public key needed to
01212  * verify it.  It might be present in our cache of keys, or in the
01213  * object itself; in either of these cases, we can satisfy the request
01214  * right away. Or there may be an indirection (a KeyName), in which case
01215  * return without the key. The final possibility is that there is no key
01216  * locator we can make sense of.
01217  * @returns negative for error, 0 when pubkey is filled in,
01218  *         or 1 if the key needs to be requested.
01219  */
01220 static int
01221 ccn_locate_key(struct ccn *h,
01222                const unsigned char *msg,
01223                struct ccn_parsed_ContentObject *pco,
01224                struct ccn_pkey **pubkey)
01225 {
01226     int res;
01227     const unsigned char *pkeyid;
01228     size_t pkeyid_size;
01229     struct ccn_pkey **entry;
01230     struct ccn_buf_decoder decoder;
01231     struct ccn_buf_decoder *d;
01232 
01233     if (h->keys == NULL) {
01234         return (NOTE_ERR(h, EINVAL));
01235     }
01236 
01237     res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, msg,
01238                               pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
01239                               pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
01240                               &pkeyid, &pkeyid_size);
01241     if (res < 0)
01242         return (NOTE_ERR(h, res));
01243     entry = hashtb_lookup(h->keys, pkeyid, pkeyid_size);
01244     if (entry != NULL) {
01245         *pubkey = *entry;
01246         return (0);
01247     }
01248     /* Is a key locator present? */
01249     if (pco->offset[CCN_PCO_B_KeyLocator] == pco->offset[CCN_PCO_E_KeyLocator])
01250         return (-1);
01251     /* Use the key locator */
01252     d = ccn_buf_decoder_start(&decoder, msg + pco->offset[CCN_PCO_B_Key_Certificate_KeyName],
01253                               pco->offset[CCN_PCO_E_Key_Certificate_KeyName] -
01254                               pco->offset[CCN_PCO_B_Key_Certificate_KeyName]);
01255     if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) {
01256         return(1);
01257     }
01258     else if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
01259         const unsigned char *dkey;
01260         size_t dkey_size;
01261         struct ccn_digest *digest = NULL;
01262         unsigned char *key_digest = NULL;
01263         size_t key_digest_size;
01264         struct hashtb_enumerator ee;
01265         struct hashtb_enumerator *e = &ee;
01266 
01267         res = ccn_ref_tagged_BLOB(CCN_DTAG_Key, msg,
01268                                   pco->offset[CCN_PCO_B_Key_Certificate_KeyName],
01269                                   pco->offset[CCN_PCO_E_Key_Certificate_KeyName],
01270                                   &dkey, &dkey_size);
01271         *pubkey = ccn_d2i_pubkey(dkey, dkey_size);
01272         digest = ccn_digest_create(CCN_DIGEST_SHA256);
01273         ccn_digest_init(digest);
01274         key_digest_size = ccn_digest_size(digest);
01275         key_digest = calloc(1, key_digest_size);
01276         if (key_digest == NULL) abort();
01277         res = ccn_digest_update(digest, dkey, dkey_size);
01278         if (res < 0) abort();
01279         res = ccn_digest_final(digest, key_digest, key_digest_size);
01280         if (res < 0) abort();
01281         ccn_digest_destroy(&digest);
01282         hashtb_start(h->keys, e);
01283         res = hashtb_seek(e, (void *)key_digest, key_digest_size, 0);
01284         free(key_digest);
01285         key_digest = NULL;
01286         if (res < 0) {
01287             hashtb_end(e);
01288             return(NOTE_ERRNO(h));
01289         }
01290         entry = e->data;
01291         if (res == HT_NEW_ENTRY) {
01292             *entry = *pubkey;
01293         }
01294         else
01295             THIS_CANNOT_HAPPEN(h);
01296         hashtb_end(e);
01297         return (0);
01298     }
01299     else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
01300         XXX; // what should we really do in this case?
01301     }
01302 
01303     return (-1);
01304 }
01305 
01306 /**
01307  * Get the name out of a Link.
01308  *
01309  * XXX - this needs a better home.
01310  */
01311 static int
01312 ccn_append_link_name(struct ccn_charbuf *name, const unsigned char *data, size_t data_size)
01313 {
01314     struct ccn_buf_decoder decoder;
01315     struct ccn_buf_decoder *d;
01316     size_t start = 0;
01317     size_t end = 0;
01318     
01319     d = ccn_buf_decoder_start(&decoder, data, data_size);
01320     if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
01321         ccn_buf_advance(d);
01322         start = d->decoder.token_index;
01323         ccn_parse_Name(d, NULL);
01324         end = d->decoder.token_index;
01325         ccn_buf_check_close(d);
01326         if (d->decoder.state < 0)
01327             return (d->decoder.state);
01328         ccn_charbuf_append(name, data + start, end - start);
01329         return(0);
01330         }
01331     return(-1);
01332 }
01333 
01334 /**
01335  * Called when we get an answer to a KeyLocator fetch issued by
01336  * ccn_initiate_key_fetch.  This does not really have to do much,
01337  * since the main content handling logic picks up the keys as they
01338  * go by.
01339  */
01340 static enum ccn_upcall_res
01341 handle_key(struct ccn_closure *selfp,
01342            enum ccn_upcall_kind kind,
01343            struct ccn_upcall_info *info)
01344 {
01345     struct ccn *h = info->h;
01346     (void)h;
01347     int type = 0;
01348     const unsigned char *msg = NULL;
01349     const unsigned char *data = NULL;
01350     size_t size;
01351     size_t data_size;
01352     int res;
01353     struct ccn_charbuf *name = NULL;
01354     struct ccn_charbuf *templ = NULL;
01355     
01356     switch(kind) {
01357         case CCN_UPCALL_FINAL:
01358             free(selfp);
01359             return(CCN_UPCALL_RESULT_OK);
01360         case CCN_UPCALL_INTEREST_TIMED_OUT:
01361             /* Don't keep trying */
01362             return(CCN_UPCALL_RESULT_OK);
01363         case CCN_UPCALL_CONTENT_UNVERIFIED:
01364             /* This is not exactly right, but trying to follow the KeyLocator could be worse trouble. */
01365         case CCN_UPCALL_CONTENT_KEYMISSING:
01366         case CCN_UPCALL_CONTENT_RAW:
01367         case CCN_UPCALL_CONTENT:
01368             type = ccn_get_content_type(msg, info->pco);
01369             if (type == CCN_CONTENT_KEY)
01370                 return(CCN_UPCALL_RESULT_OK);
01371             if (type == CCN_CONTENT_LINK) {
01372                 /* resolve the link */
01373                 /* Limit how much we work at this. */
01374                 if (selfp->intdata <= 0)
01375                     return(NOTE_ERR(h, ELOOP));
01376                 selfp->intdata -= 1;
01377                 msg = info->content_ccnb;
01378                 size = info->pco->offset[CCN_PCO_E];
01379                 res = ccn_content_get_value(info->content_ccnb, size, info->pco,
01380                                             &data, &data_size);
01381                 if (res < 0)
01382                     return (CCN_UPCALL_RESULT_ERR);
01383                 templ = ccn_charbuf_create();
01384                 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01385                 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
01386                 ccn_charbuf_append_closer(templ); /* </Name> */
01387                 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01388                 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01389                 ccn_charbuf_append_closer(templ); /* </Interest> */
01390                 name = ccn_charbuf_create();
01391                 res = ccn_append_link_name(name, data, data_size);
01392                 if (res < 0) {
01393                     NOTE_ERR(h, EINVAL);
01394                     res = CCN_UPCALL_RESULT_ERR;
01395                 }
01396                 else
01397                     res = ccn_express_interest(h, name, selfp, templ);
01398                 ccn_charbuf_destroy(&name);
01399                 ccn_charbuf_destroy(&templ);
01400                 return(res);
01401             }
01402             return (CCN_UPCALL_RESULT_ERR);
01403         default:
01404             return (CCN_UPCALL_RESULT_ERR);
01405     }
01406 }
01407 
01408 /**
01409  * This is the maximum number of links in we are willing to traverse
01410  * when resolving a key locator.
01411  */
01412 #ifndef CCN_MAX_KEY_LINK_CHAIN
01413 #define CCN_MAX_KEY_LINK_CHAIN 7
01414 #endif
01415 
01416 static int
01417 ccn_initiate_key_fetch(struct ccn *h,
01418                        unsigned char *msg,
01419                        struct ccn_parsed_ContentObject *pco,
01420                        struct expressed_interest *trigger_interest)
01421 {
01422     /* 
01423      * Create a new interest in the key name, set up a callback that will
01424      * insert the key into the h->keys hashtb for the calling handle and
01425      * cause the trigger_interest to be re-expressed.
01426      */
01427     int res;
01428     int namelen;
01429     struct ccn_charbuf *key_name = NULL;
01430     struct ccn_closure *key_closure = NULL;
01431     const unsigned char *pkeyid = NULL;
01432     size_t pkeyid_size = 0;
01433     struct ccn_charbuf *templ = NULL;
01434     
01435     if (trigger_interest != NULL) {
01436         /* Arrange a wakeup when the key arrives */
01437         if (trigger_interest->wanted_pub == NULL)
01438             trigger_interest->wanted_pub = ccn_charbuf_create();
01439         res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, msg,
01440                                   pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
01441                                   pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
01442                                   &pkeyid, &pkeyid_size);
01443         if (trigger_interest->wanted_pub != NULL && res >= 0) {
01444             trigger_interest->wanted_pub->length = 0;
01445             ccn_charbuf_append(trigger_interest->wanted_pub, pkeyid, pkeyid_size);
01446         }
01447         trigger_interest->target = 0;
01448     }
01449 
01450     namelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01451                pco->offset[CCN_PCO_B_KeyName_Name]);
01452     /*
01453      * If there is no KeyName provided, we can't ask, but we might win if the
01454      * key arrives along with some other content.
01455      */
01456     if (namelen == 0)
01457         return(-1);
01458     key_closure = calloc(1, sizeof(*key_closure));
01459     if (key_closure == NULL)
01460         return (NOTE_ERRNO(h));
01461     key_closure->p = &handle_key;
01462     key_closure->intdata = CCN_MAX_KEY_LINK_CHAIN; /* to limit how many links we will resolve */
01463     
01464     key_name = ccn_charbuf_create();
01465     res = ccn_charbuf_append(key_name,
01466                              msg + pco->offset[CCN_PCO_B_KeyName_Name],
01467                              namelen);
01468     templ = ccn_charbuf_create();
01469     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01470     ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
01471     ccn_charbuf_append_closer(templ); /* </Name> */
01472     ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01473     ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01474     if (pco->offset[CCN_PCO_B_KeyName_Pub] < pco->offset[CCN_PCO_E_KeyName_Pub]) {
01475         ccn_charbuf_append(templ,
01476                            msg + pco->offset[CCN_PCO_B_KeyName_Pub],
01477                            (pco->offset[CCN_PCO_E_KeyName_Pub] - 
01478                             pco->offset[CCN_PCO_B_KeyName_Pub]));
01479     }
01480     ccn_charbuf_append_closer(templ); /* </Interest> */
01481     res = ccn_express_interest(h, key_name, key_closure, templ);
01482     ccn_charbuf_destroy(&key_name);
01483     ccn_charbuf_destroy(&templ);
01484     return(res);
01485 }
01486 
01487 /**
01488  * If we were waiting for a key and it has arrived,
01489  * refresh the interest.
01490  */
01491 static void
01492 ccn_check_pub_arrival(struct ccn *h, struct expressed_interest *interest)
01493 {
01494     struct ccn_charbuf *want = interest->wanted_pub;
01495     if (want == NULL)
01496         return;
01497     if (hashtb_lookup(h->keys, want->buf, want->length) != NULL) {
01498         ccn_charbuf_destroy(&interest->wanted_pub);
01499         interest->target = 1;
01500         ccn_refresh_interest(h, interest);
01501     }
01502 }
01503 
01504 /**
01505  * Dispatch a message through the registered upcalls.
01506  * This is not used by normal ccn clients, but is made available for use when
01507  * ccnd needs to communicate with its internal client.
01508  * @param h is the ccn handle.
01509  * @param msg is the ccnb-encoded Interest or ContentObject.
01510  * @param size is its size in bytes.
01511  */
01512 void
01513 ccn_dispatch_message(struct ccn *h, unsigned char *msg, size_t size)
01514 {
01515     struct ccn_parsed_interest pi = {0};
01516     struct ccn_upcall_info info = {0};
01517     int i;
01518     int res;
01519     enum ccn_upcall_res ures;
01520     
01521     h->running++;
01522     info.h = h;
01523     info.pi = &pi;
01524     info.interest_comps = ccn_indexbuf_obtain(h);
01525     res = ccn_parse_interest(msg, size, &pi, info.interest_comps);
01526     if (res >= 0) {
01527         /* This message is an Interest */
01528         enum ccn_upcall_kind upcall_kind = CCN_UPCALL_INTEREST;
01529         info.interest_ccnb = msg;
01530         if (h->interest_filters != NULL && info.interest_comps->n > 0) {
01531             struct ccn_indexbuf *comps = info.interest_comps;
01532             size_t keystart = comps->buf[0];
01533             unsigned char *key = msg + keystart;
01534             struct interest_filter *entry;
01535             for (i = comps->n - 1; i >= 0; i--) {
01536                 entry = hashtb_lookup(h->interest_filters, key, comps->buf[i] - keystart);
01537                 if (entry != NULL) {
01538                     info.matched_comps = i;
01539                     ures = (entry->action->p)(entry->action, upcall_kind, &info);
01540                     if (ures == CCN_UPCALL_RESULT_INTEREST_CONSUMED)
01541                         upcall_kind = CCN_UPCALL_CONSUMED_INTEREST;
01542                 }
01543             }
01544         }
01545     }
01546     else {
01547         /* This message should be a ContentObject. */
01548         struct ccn_parsed_ContentObject obj = {0};
01549         info.pco = &obj;
01550         info.content_comps = ccn_indexbuf_create();
01551         res = ccn_parse_ContentObject(msg, size, &obj, info.content_comps);
01552         if (res >= 0) {
01553             info.content_ccnb = msg;
01554             if (h->interests_by_prefix != NULL) {
01555                 struct ccn_indexbuf *comps = info.content_comps;
01556                 size_t keystart = comps->buf[0];
01557                 unsigned char *key = msg + keystart;
01558                 struct expressed_interest *interest = NULL;
01559                 struct interests_by_prefix *entry = NULL;
01560                 for (i = comps->n - 1; i >= 0; i--) {
01561                     entry = hashtb_lookup(h->interests_by_prefix, key, comps->buf[i] - keystart);
01562                     if (entry != NULL) {
01563                         for (interest = entry->list; interest != NULL; interest = interest->next) {
01564                             if (interest->magic != 0x7059e5f4) {
01565                                 ccn_gripe(interest);
01566                             }
01567                             if (interest->target > 0 && interest->outstanding > 0) {
01568                                 res = ccn_parse_interest(interest->interest_msg,
01569                                                          interest->size,
01570                                                          info.pi,
01571                                                          info.interest_comps);
01572                                 if (res >= 0 &&
01573                                     ccn_content_matches_interest(msg, size,
01574                                                                  1, info.pco,
01575                                                                  interest->interest_msg,
01576                                                                  interest->size,
01577                                                                  info.pi)) {
01578                                     enum ccn_upcall_kind upcall_kind = CCN_UPCALL_CONTENT;
01579                                     struct ccn_pkey *pubkey = NULL;
01580                                     int type = ccn_get_content_type(msg, info.pco);
01581                                     if (type == CCN_CONTENT_KEY)
01582                                         res = ccn_cache_key(h, msg, size, info.pco);
01583                                     res = ccn_locate_key(h, msg, info.pco, &pubkey);
01584                                     if (h->defer_verification) {
01585                                         if (res == 0)
01586                                             upcall_kind = CCN_UPCALL_CONTENT_RAW;
01587                                         else
01588                                             upcall_kind = CCN_UPCALL_CONTENT_KEYMISSING;
01589                                     }
01590                                     else if (res == 0) {
01591                                         /* we have the pubkey, use it to verify the msg */
01592                                         res = ccn_verify_signature(msg, size, info.pco, pubkey);
01593                                         upcall_kind = (res == 1) ? CCN_UPCALL_CONTENT : CCN_UPCALL_CONTENT_BAD;
01594                                     } else
01595                                         upcall_kind = CCN_UPCALL_CONTENT_UNVERIFIED;
01596                                     interest->outstanding -= 1;
01597                                     info.interest_ccnb = interest->interest_msg;
01598                                     info.matched_comps = i;
01599                                     ures = (interest->action->p)(interest->action,
01600                                                                  upcall_kind,
01601                                                                  &info);
01602                                     if (interest->magic != 0x7059e5f4)
01603                                         ccn_gripe(interest);
01604                                     if (ures == CCN_UPCALL_RESULT_REEXPRESS)
01605                                         ccn_refresh_interest(h, interest);
01606                                     else if ((ures == CCN_UPCALL_RESULT_VERIFY ||
01607                                               ures == CCN_UPCALL_RESULT_FETCHKEY) &&
01608                                              (upcall_kind == CCN_UPCALL_CONTENT_UNVERIFIED ||
01609                                               upcall_kind == CCN_UPCALL_CONTENT_KEYMISSING)) { /* KEYS */
01610                                         ccn_initiate_key_fetch(h, msg, info.pco, interest);
01611                                     }
01612                                     else if (ures == CCN_UPCALL_RESULT_VERIFY &&
01613                                              upcall_kind == CCN_UPCALL_CONTENT_RAW) {
01614                                         /* For now, call this a client bug. */
01615                                         abort();
01616                                     }
01617                                     else {
01618                                         interest->target = 0;
01619                                         replace_interest_msg(interest, NULL);
01620                                         ccn_replace_handler(h, &(interest->action), NULL);
01621                                     }
01622                                 }
01623                             }
01624                         }
01625                     }
01626                 }
01627             }
01628         }
01629     } // XXX whew, what a lot of right braces!
01630     ccn_indexbuf_release(h, info.interest_comps);
01631     ccn_indexbuf_destroy(&info.content_comps);
01632     h->running--;
01633 }
01634 
01635 static int
01636 ccn_process_input(struct ccn *h)
01637 {
01638     ssize_t res;
01639     ssize_t msgstart;
01640     unsigned char *buf;
01641     struct ccn_skeleton_decoder *d = &h->decoder;
01642     struct ccn_charbuf *inbuf = h->inbuf;
01643     if (inbuf == NULL)
01644         h->inbuf = inbuf = ccn_charbuf_create();
01645     if (inbuf->length == 0)
01646         memset(d, 0, sizeof(*d));
01647     buf = ccn_charbuf_reserve(inbuf, 8800);
01648     res = read(h->sock, buf, inbuf->limit - inbuf->length);
01649     if (res == 0) {
01650         ccn_disconnect(h);
01651         return(-1);
01652     }
01653     if (res == -1) {
01654         if (errno == EAGAIN)
01655             res = 0;
01656         else
01657             return(NOTE_ERRNO(h));
01658     }
01659     inbuf->length += res;
01660     msgstart = 0;
01661     ccn_skeleton_decode(d, buf, res);
01662     while (d->state == 0) {
01663         ccn_dispatch_message(h, inbuf->buf + msgstart, 
01664                               d->index - msgstart);
01665         msgstart = d->index;
01666         if (msgstart == inbuf->length) {
01667             inbuf->length = 0;
01668             return(0);
01669         }
01670         ccn_skeleton_decode(d, inbuf->buf + d->index,
01671                             inbuf->length - d->index);
01672     }
01673     if (msgstart < inbuf->length && msgstart > 0) {
01674         /* move partial message to start of buffer */
01675         memmove(inbuf->buf, inbuf->buf + msgstart,
01676                 inbuf->length - msgstart);
01677         inbuf->length -= msgstart;
01678         d->index -= msgstart;
01679     }
01680     return(0);
01681 }
01682 
01683 static void
01684 ccn_update_refresh_us(struct ccn *h, struct timeval *tv)
01685 {
01686     int delta;
01687     if (tv->tv_sec < h->now.tv_sec)
01688         return;
01689     if (tv->tv_sec > h->now.tv_sec + CCN_INTEREST_LIFETIME_SEC)
01690         return;
01691     delta = (tv->tv_sec  - h->now.tv_sec)*1000000 +
01692             (tv->tv_usec - h->now.tv_usec);
01693     if (delta < 0)
01694         delta = 0;
01695     if (delta < h->refresh_us)
01696         h->refresh_us = delta;
01697 }
01698 
01699 static void
01700 ccn_age_interest(struct ccn *h,
01701                  struct expressed_interest *interest,
01702                  const unsigned char *key, size_t keysize)
01703 {
01704     struct ccn_parsed_interest pi = {0};
01705     struct ccn_upcall_info info = {0};
01706     int delta;
01707     int res;
01708     enum ccn_upcall_res ures;
01709     int firstcall;
01710     if (interest->magic != 0x7059e5f4)
01711         ccn_gripe(interest);
01712     info.h = h;
01713     info.pi = &pi;
01714     firstcall = (interest->lasttime.tv_sec == 0);
01715     if (interest->lasttime.tv_sec + 30 < h->now.tv_sec) {
01716         /* fixup so that delta does not overflow */
01717         interest->outstanding = 0;
01718         interest->lasttime = h->now;
01719         interest->lasttime.tv_sec -= 30;
01720     }
01721     delta = (h->now.tv_sec  - interest->lasttime.tv_sec)*1000000 +
01722             (h->now.tv_usec - interest->lasttime.tv_usec);
01723     if (delta >= interest->lifetime_us) {
01724         interest->outstanding = 0;
01725         delta = 0;
01726     }
01727     else if (delta < 0)
01728         delta = 0;
01729     if (interest->lifetime_us - delta < h->refresh_us)
01730         h->refresh_us = interest->lifetime_us - delta;
01731     interest->lasttime = h->now;
01732     while (delta > interest->lasttime.tv_usec) {
01733         delta -= 1000000;
01734         interest->lasttime.tv_sec -= 1;
01735     }
01736     interest->lasttime.tv_usec -= delta;
01737     if (interest->target > 0 && interest->outstanding == 0) {
01738         ures = CCN_UPCALL_RESULT_REEXPRESS;
01739         if (!firstcall) {
01740             info.interest_ccnb = interest->interest_msg;
01741             info.interest_comps = ccn_indexbuf_obtain(h);
01742             res = ccn_parse_interest(interest->interest_msg,
01743                                      interest->size,
01744                                      info.pi,
01745                                      info.interest_comps);
01746             if (res >= 0) {
01747                 ures = (interest->action->p)(interest->action,
01748                                              CCN_UPCALL_INTEREST_TIMED_OUT,
01749                                              &info);
01750                 if (interest->magic != 0x7059e5f4)
01751                     ccn_gripe(interest);
01752             }
01753             else {
01754                 int i;
01755                 fprintf(stderr, "URP!! interest has been corrupted ccn_client.c:%d\n", __LINE__);
01756                 for (i = 0; i < 120; i++)
01757                     sleep(1);
01758                 ures = CCN_UPCALL_RESULT_ERR;
01759             }
01760             ccn_indexbuf_release(h, info.interest_comps);
01761         }
01762         if (ures == CCN_UPCALL_RESULT_REEXPRESS)
01763             ccn_refresh_interest(h, interest);
01764         else
01765             interest->target = 0;
01766     }
01767 }
01768 
01769 static void
01770 ccn_clean_all_interests(struct ccn *h)
01771 {
01772     struct hashtb_enumerator ee;
01773     struct hashtb_enumerator *e = &ee;
01774     struct interests_by_prefix *entry;
01775     for (hashtb_start(h->interests_by_prefix, e); e->data != NULL;) {
01776         entry = e->data;
01777         ccn_clean_interests_by_prefix(h, entry);
01778         if (entry->list == NULL)
01779             hashtb_delete(e);
01780         else
01781             hashtb_next(e);
01782     }
01783     hashtb_end(e);
01784 }
01785 
01786 static void
01787 ccn_notify_ccndid_changed(struct ccn *h)
01788 {
01789     struct hashtb_enumerator ee;
01790     struct hashtb_enumerator *e = &ee;
01791     if (h->interest_filters != NULL) {
01792         for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
01793             struct interest_filter *i = e->data;
01794             if ((i->flags & CCN_FORW_WAITING_CCNDID) != 0) {
01795                 i->expiry = h->now;
01796                 i->flags &= ~CCN_FORW_WAITING_CCNDID;
01797             }
01798         }
01799         hashtb_end(e);
01800     }
01801 }
01802 
01803 /**
01804  * Get the previously set event schedule from a ccn handle
01805  * @param h is the ccn handle
01806  * @returns pointer to the event schedule
01807  */
01808 struct ccn_schedule *
01809 ccn_get_schedule(struct ccn *h)
01810 {
01811     return(h->schedule);
01812 }
01813 
01814 /**
01815  * Set the event schedule in a ccn handle
01816  * @param h is the ccn handle
01817  * @param schedule is the new event schedule to be set in the handle
01818  * @returns pointer to the previous event schedule (or NULL)
01819  */
01820 struct ccn_schedule *
01821 ccn_set_schedule(struct ccn *h, struct ccn_schedule *schedule)
01822 {
01823     struct ccn_schedule *old = h->schedule;
01824     h->schedule = schedule;
01825     return(old);
01826 }
01827 
01828 /**
01829  * Process any scheduled operations that are due.
01830  * This is not used by normal ccn clients, but is made available for use
01831  * by ccnd to run its internal client.
01832  * @param h is the ccn handle.
01833  * @returns the number of microseconds until the next thing needs to happen.
01834  */
01835 int
01836 ccn_process_scheduled_operations(struct ccn *h)
01837 {
01838     struct hashtb_enumerator ee;
01839     struct hashtb_enumerator *e = &ee;
01840     struct interests_by_prefix *entry;
01841     struct expressed_interest *ie;
01842     int need_clean = 0;
01843     h->refresh_us = 5 * CCN_INTEREST_LIFETIME_MICROSEC;
01844     gettimeofday(&h->now, NULL);
01845     if (ccn_output_is_pending(h))
01846         return(h->refresh_us);
01847     h->running++;
01848     if (h->interest_filters != NULL) {
01849         for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
01850             struct interest_filter *i = e->data;
01851             if (tv_earlier(&i->expiry, &h->now)) {
01852                 /* registration is expiring, refresh it */
01853                 ccn_initiate_prefix_reg(h, e->key, e->keysize, i);
01854             }
01855             else
01856                 ccn_update_refresh_us(h, &i->expiry);
01857         }
01858         hashtb_end(e);
01859     }
01860     if (h->interests_by_prefix != NULL) {
01861         for (hashtb_start(h->interests_by_prefix, e); e->data != NULL; hashtb_next(e)) {
01862             entry = e->data;
01863             ccn_check_interests(entry->list);
01864             if (entry->list == NULL)
01865                 need_clean = 1;
01866             else {
01867                 for (ie = entry->list; ie != NULL; ie = ie->next) {
01868                     ccn_check_pub_arrival(h, ie);
01869                     if (ie->target != 0)
01870                         ccn_age_interest(h, ie, e->key, e->keysize);
01871                     if (ie->target == 0 && ie->wanted_pub == NULL) {
01872                         ccn_replace_handler(h, &(ie->action), NULL);
01873                         replace_interest_msg(ie, NULL);
01874                         need_clean = 1;
01875                     }
01876                 }
01877             }
01878         }
01879         hashtb_end(e);
01880         if (need_clean)
01881             ccn_clean_all_interests(h);
01882     }
01883     h->running--;
01884     return(h->refresh_us);
01885 }
01886 
01887 /**
01888  * Modify ccn_run timeout.
01889  *
01890  * This may be called from an upcall to change the timeout value.
01891  * Most often this will be used to set the timeout to zero so that
01892  * ccn_run() will return control to the client.
01893  * @param h is the ccn handle.
01894  * @param timeout is in milliseconds.
01895  * @returns old timeout value.
01896  */
01897 int
01898 ccn_set_run_timeout(struct ccn *h, int timeout)
01899 {
01900     int ans = h->timeout;
01901     h->timeout = timeout;
01902     return(ans);
01903 }
01904 
01905 /**
01906  * Run the ccn client event loop.
01907  * This may serve as the main event loop for simple apps by passing 
01908  * a timeout value of -1.
01909  * @param h is the ccn handle.
01910  * @param timeout is in milliseconds.
01911  * @returns a negative value for error, zero for success.
01912  */
01913 int
01914 ccn_run(struct ccn *h, int timeout)
01915 {
01916     struct timeval start;
01917     struct pollfd fds[1];
01918     int microsec;
01919     int s_microsec = -1;
01920     int millisec;
01921     int res = -1;
01922     if (h->running != 0)
01923         return(NOTE_ERR(h, EBUSY));
01924     memset(fds, 0, sizeof(fds));
01925     memset(&start, 0, sizeof(start));
01926     h->timeout = timeout;
01927     for (;;) {
01928         if (h->sock == -1) {
01929             res = -1;
01930             break;
01931         }
01932         if (h->schedule != NULL) {
01933             s_microsec = ccn_schedule_run(h->schedule);
01934         }
01935         microsec = ccn_process_scheduled_operations(h);
01936         if (s_microsec >= 0 && s_microsec < microsec)
01937             microsec = s_microsec;
01938         timeout = h->timeout;
01939         if (start.tv_sec == 0)
01940             start = h->now;
01941         else if (timeout >= 0) {
01942             millisec = (h->now.tv_sec  - start.tv_sec) *1000 +
01943             (h->now.tv_usec - start.tv_usec)/1000;
01944             if (millisec >= timeout) {
01945                 res = 0;
01946                 break;
01947             }
01948         }
01949         fds[0].fd = h->sock;
01950         fds[0].events = POLLIN;
01951         if (ccn_output_is_pending(h))
01952             fds[0].events |= POLLOUT;
01953         millisec = microsec / 1000;
01954         if (timeout >= 0 && timeout < millisec)
01955             millisec = timeout;
01956         res = poll(fds, 1, millisec);
01957         if (res < 0 && errno != EINTR) {
01958             res = NOTE_ERRNO(h);
01959             break;
01960         }
01961         if (res > 0) {
01962             if ((fds[0].revents | POLLOUT) != 0)
01963                 ccn_pushout(h);
01964             if ((fds[0].revents | POLLIN) != 0)
01965                 ccn_process_input(h);
01966         }
01967         if (h->err == ENOTCONN)
01968             ccn_disconnect(h);
01969         if (h->timeout == 0)
01970             break;
01971     }
01972     if (h->running != 0)
01973         abort();
01974     return((res < 0) ? res : 0);
01975 }
01976 
01977 /**
01978  * Instance data associated with handle_simple_incoming_content()
01979  */
01980 struct simple_get_data {
01981     struct ccn_closure closure;
01982     struct ccn_charbuf *resultbuf;
01983     struct ccn_parsed_ContentObject *pcobuf;
01984     struct ccn_indexbuf *compsbuf;
01985     int flags;
01986     int res;
01987 };
01988 
01989 /**
01990  * Upcall for implementing ccn_get()
01991  */
01992 static enum ccn_upcall_res
01993 handle_simple_incoming_content(
01994     struct ccn_closure *selfp,
01995     enum ccn_upcall_kind kind,
01996     struct ccn_upcall_info *info)
01997 {
01998     struct simple_get_data *md = selfp->data;
01999     struct ccn *h = info->h;
02000     
02001     if (kind == CCN_UPCALL_FINAL) {
02002         if (selfp != &md->closure)
02003             abort();
02004         free(md);
02005         return(CCN_UPCALL_RESULT_OK);
02006     }
02007     if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
02008         return(selfp->intdata ? CCN_UPCALL_RESULT_REEXPRESS : CCN_UPCALL_RESULT_OK);
02009     if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) {
02010         if ((md->flags & CCN_GET_NOKEYWAIT) == 0)
02011             return(CCN_UPCALL_RESULT_VERIFY);
02012     }
02013     if (kind == CCN_UPCALL_CONTENT_KEYMISSING) {
02014         if ((md->flags & CCN_GET_NOKEYWAIT) == 0)
02015             return(CCN_UPCALL_RESULT_FETCHKEY);
02016     }
02017     else if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_RAW)
02018         return(CCN_UPCALL_RESULT_ERR);
02019     if (md->resultbuf != NULL) {
02020         md->resultbuf->length = 0;
02021         ccn_charbuf_append(md->resultbuf,
02022                            info->content_ccnb, info->pco->offset[CCN_PCO_E]);
02023     }
02024     if (md->pcobuf != NULL)
02025         memcpy(md->pcobuf, info->pco, sizeof(*md->pcobuf));
02026     if (md->compsbuf != NULL) {
02027         md->compsbuf->n = 0;
02028         ccn_indexbuf_append(md->compsbuf,
02029                             info->content_comps->buf, info->content_comps->n);
02030     }
02031     md->res = 0;
02032     ccn_set_run_timeout(h, 0);
02033     return(CCN_UPCALL_RESULT_OK);
02034 }
02035 
02036 /**
02037  * Get a single matching ContentObject
02038  * This is a convenience for getting a single matching ContentObject.
02039  * Blocks until a matching ContentObject arrives or there is a timeout.
02040  * @param h is the ccn handle. If NULL or ccn_get is called from inside
02041  *        an upcall, a new connection will be used and upcalls from other
02042  *        requests will not be processed while ccn_get is active.
02043  * @param name holds a ccnb-encoded Name
02044  * @param interest_template conveys other fields to be used in the interest
02045  *        (may be NULL).
02046  * @param timeout_ms limits the time spent waiting for an answer (milliseconds).
02047  * @param resultbuf is updated to contain the ccnb-encoded ContentObject.
02048  * @param pcobuf may be supplied to save the client the work of re-parsing the
02049  *        ContentObject; may be NULL if this information is not actually needed.
02050  * @param compsbuf works similarly.
02051  * @param flags - CCN_GET_NOKEYWAIT means that it is permitted to return
02052  *        unverified data.
02053  * @returns 0 for success, -1 for an error.
02054  */
02055 int
02056 ccn_get(struct ccn *h,
02057         struct ccn_charbuf *name,
02058         struct ccn_charbuf *interest_template,
02059         int timeout_ms,
02060         struct ccn_charbuf *resultbuf,
02061         struct ccn_parsed_ContentObject *pcobuf,
02062         struct ccn_indexbuf *compsbuf,
02063         int flags)
02064 {
02065     struct ccn *orig_h = h;
02066     struct hashtb *saved_keys = NULL;
02067     int res;
02068     struct simple_get_data *md;
02069     
02070     if ((flags & ~((int)CCN_GET_NOKEYWAIT)) != 0)
02071         return(-1);
02072     if (h == NULL || h->running) {
02073         h = ccn_create();
02074         if (h == NULL)
02075             return(-1);
02076         if (orig_h != NULL) { /* Dad, can I borrow the keys? */
02077             saved_keys = h->keys;
02078             h->keys = orig_h->keys;
02079         }
02080         res = ccn_connect(h, NULL);
02081         if (res < 0) {
02082             ccn_destroy(&h);
02083             return(-1);
02084         }
02085     }
02086     md = calloc(1, sizeof(*md));
02087     md->resultbuf = resultbuf;
02088     md->pcobuf = pcobuf;
02089     md->compsbuf = compsbuf;
02090     md->flags = flags;
02091     md->res = -1;
02092     md->closure.p = &handle_simple_incoming_content;
02093     md->closure.data = md;
02094     md->closure.intdata = 1; /* tell upcall to re-express if needed */
02095     md->closure.refcount = 1;
02096     res = ccn_express_interest(h, name, &md->closure, interest_template);
02097     if (res >= 0)
02098         res = ccn_run(h, timeout_ms);
02099     if (res >= 0)
02100         res = md->res;
02101     md->resultbuf = NULL;
02102     md->pcobuf = NULL;
02103     md->compsbuf = NULL;
02104     md->closure.intdata = 0;
02105     md->closure.refcount--;
02106     if (md->closure.refcount == 0)
02107         free(md);
02108     if (h != orig_h) {
02109         if (saved_keys != NULL)
02110             h->keys = saved_keys;
02111         ccn_destroy(&h);
02112     }
02113     return(res);
02114 }
02115 
02116 /**
02117  * Upcall to handle response to fetch a ccndid
02118  */
02119 static enum ccn_upcall_res
02120 handle_ccndid_response(struct ccn_closure *selfp,
02121                      enum ccn_upcall_kind kind,
02122                      struct ccn_upcall_info *info)
02123 {
02124     int res;
02125     const unsigned char *ccndid = NULL;
02126     size_t size = 0;
02127     struct ccn *h = info->h;
02128     
02129     if (kind == CCN_UPCALL_FINAL) {
02130         free(selfp);
02131         return(CCN_UPCALL_RESULT_OK);
02132     }
02133     if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
02134         return(CCN_UPCALL_RESULT_VERIFY);
02135     if (kind == CCN_UPCALL_CONTENT_KEYMISSING)
02136         return(CCN_UPCALL_RESULT_FETCHKEY);
02137     if (kind == CCN_UPCALL_CONTENT_RAW) {
02138         if (ccn_verify_content(h, info->content_ccnb, info->pco) == 0)
02139             kind = CCN_UPCALL_CONTENT;
02140     }
02141     if (kind != CCN_UPCALL_CONTENT) {
02142         NOTE_ERR(h, -1000 - kind);
02143         return(CCN_UPCALL_RESULT_ERR);
02144     }
02145     res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
02146                               info->content_ccnb,
02147                               info->pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
02148                               info->pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
02149                               &ccndid,
02150                               &size);
02151     if (res < 0) {
02152         NOTE_ERR(h, -1);
02153         return(CCN_UPCALL_RESULT_ERR);
02154     }
02155     if (h->ccndid == NULL) {
02156         h->ccndid = ccn_charbuf_create_n(size);
02157         if (h->ccndid == NULL)
02158             return(NOTE_ERRNO(h));
02159     }
02160     ccn_charbuf_reset(h->ccndid);
02161     ccn_charbuf_append(h->ccndid, ccndid, size);
02162     ccn_notify_ccndid_changed(h);
02163     return(CCN_UPCALL_RESULT_OK);
02164 }
02165 
02166 static void
02167 ccn_initiate_ccndid_fetch(struct ccn *h)
02168 {
02169     struct ccn_charbuf *name = NULL;
02170     struct ccn_closure *action = NULL;
02171     
02172     name = ccn_charbuf_create();
02173     ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY");
02174     action = calloc(1, sizeof(*action));
02175     action->p = &handle_ccndid_response;
02176     ccn_express_interest(h, name, action, NULL);
02177     ccn_charbuf_destroy(&name);
02178 }
02179 
02180 /**
02181  * Handle reply to a prefix registration request
02182  */
02183 static enum ccn_upcall_res
02184 handle_prefix_reg_reply(
02185     struct ccn_closure *selfp,
02186     enum ccn_upcall_kind kind,
02187     struct ccn_upcall_info *info)
02188 {
02189     struct ccn_reg_closure *md = selfp->data;
02190     struct ccn *h = info->h;
02191     int lifetime = 10;
02192     struct ccn_forwarding_entry *fe = NULL;
02193     int res;
02194     const unsigned char *fe_ccnb = NULL;
02195     size_t fe_ccnb_size = 0;
02196 
02197     if (kind == CCN_UPCALL_FINAL) {
02198         // fprintf(stderr, "GOT TO handle_prefix_reg_reply FINAL\n");
02199         if (selfp != &md->action)
02200             abort();
02201         if (md->interest_filter != NULL)
02202             md->interest_filter->ccn_reg_closure = NULL;
02203         selfp->data = NULL;
02204         free(md);
02205         return(CCN_UPCALL_RESULT_OK);
02206     }
02207     if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
02208         return(CCN_UPCALL_RESULT_REEXPRESS);
02209     if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
02210         return(CCN_UPCALL_RESULT_VERIFY);
02211     if (kind == CCN_UPCALL_CONTENT_KEYMISSING)
02212         return(CCN_UPCALL_RESULT_FETCHKEY);
02213     if (kind == CCN_UPCALL_CONTENT_RAW) {
02214         if (ccn_verify_content(h, info->content_ccnb, info->pco) == 0)
02215             kind = CCN_UPCALL_CONTENT;
02216     }
02217     if (kind != CCN_UPCALL_CONTENT) {
02218         NOTE_ERR(h, -1000 - kind);
02219         return(CCN_UPCALL_RESULT_ERR);
02220     }
02221     res = ccn_content_get_value(info->content_ccnb,
02222                                 info->pco->offset[CCN_PCO_E],
02223                                 info->pco,
02224                                 &fe_ccnb, &fe_ccnb_size);
02225     if (res == 0)
02226         fe = ccn_forwarding_entry_parse(fe_ccnb, fe_ccnb_size);
02227     if (fe == NULL) {
02228         XXX;
02229         lifetime = 30;
02230     }
02231     else
02232         lifetime = fe->lifetime;
02233     if (lifetime < 0)
02234         lifetime = 0;
02235     else if (lifetime > 3600)
02236         lifetime = 3600;
02237     if (md->interest_filter != NULL) {
02238         md->interest_filter->expiry = h->now;
02239         md->interest_filter->expiry.tv_sec += lifetime;
02240     }
02241     ccn_forwarding_entry_destroy(&fe);
02242     return(CCN_UPCALL_RESULT_OK);
02243 }
02244 
02245 static void
02246 ccn_initiate_prefix_reg(struct ccn *h,
02247                         const void *prefix, size_t prefix_size,
02248                         struct interest_filter *i)
02249 {
02250     struct ccn_reg_closure *p = NULL;
02251     struct ccn_charbuf *reqname = NULL;
02252     struct ccn_charbuf *templ = NULL;
02253     struct ccn_forwarding_entry fe_store = { 0 };
02254     struct ccn_forwarding_entry *fe = &fe_store;
02255     struct ccn_charbuf *reg_request = NULL;
02256     struct ccn_charbuf *signed_reg_request = NULL;
02257     struct ccn_charbuf *empty = NULL;
02258 
02259     i->expiry = h->now;
02260     i->expiry.tv_sec += 60;
02261     /* This test is mainly for the benefit of the ccnd internal client */
02262     if (h->sock == -1)
02263         return;
02264     // fprintf(stderr, "GOT TO STUB ccn_initiate_prefix_reg()\n");
02265     if (h->ccndid == NULL) {
02266         ccn_initiate_ccndid_fetch(h);
02267         i->flags |= CCN_FORW_WAITING_CCNDID;
02268         return;
02269     }
02270     if (i->ccn_reg_closure != NULL)
02271         return;
02272     p = calloc(1, sizeof(*p));
02273     if (p == NULL) {
02274         NOTE_ERRNO(h);
02275         return;
02276     }
02277     p->action.data = p;
02278     p->action.p = &handle_prefix_reg_reply;
02279     p->interest_filter = i;
02280     i->ccn_reg_closure = p;
02281     reqname = ccn_charbuf_create();
02282     ccn_name_from_uri(reqname, "ccnx:/ccnx");
02283     ccn_name_append(reqname, h->ccndid->buf, h->ccndid->length);
02284     ccn_name_append_str(reqname, "selfreg");
02285     fe->action = "selfreg";
02286     fe->ccnd_id = h->ccndid->buf;
02287     fe->ccnd_id_size = h->ccndid->length;
02288     fe->faceid = ~0; // XXX - someday explicit faceid may be required
02289     fe->name_prefix = ccn_charbuf_create();
02290     fe->flags = i->flags & 0xFF;
02291     fe->lifetime = -1; /* Let ccnd decide */
02292     ccn_name_init(fe->name_prefix);
02293     ccn_name_append_components(fe->name_prefix, prefix, 0, prefix_size);
02294     reg_request = ccn_charbuf_create();
02295     ccnb_append_forwarding_entry(reg_request, fe);
02296     empty = ccn_charbuf_create();
02297     ccn_name_init(empty);
02298     signed_reg_request = ccn_charbuf_create();
02299     ccn_sign_content(h, signed_reg_request, empty, NULL,
02300                      reg_request->buf, reg_request->length);
02301     ccn_name_append(reqname,
02302                     signed_reg_request->buf, signed_reg_request->length);
02303     // XXX - should set up templ for scope 1
02304     ccn_express_interest(h, reqname, &p->action, templ);
02305     ccn_charbuf_destroy(&fe->name_prefix);
02306     ccn_charbuf_destroy(&reqname);
02307     ccn_charbuf_destroy(&templ);
02308     ccn_charbuf_destroy(&reg_request);
02309     ccn_charbuf_destroy(&signed_reg_request);
02310     ccn_charbuf_destroy(&empty);
02311 }
02312 
02313 /**
02314  * Verify a ContentObject using the public key from either the object
02315  * itself or our cache of keys.
02316  *
02317  * This routine does not attempt to fetch the public key if it is not
02318  * at hand.
02319  * @returns negative for error, 0 verification success,
02320  *         or 1 if the key needs to be requested.
02321  */
02322 int
02323 ccn_verify_content(struct ccn *h,
02324                    const unsigned char *msg,
02325                    struct ccn_parsed_ContentObject *pco)
02326 {
02327     struct ccn_pkey *pubkey = NULL;
02328     int res;
02329     unsigned char *buf = (unsigned char *)msg; /* XXX - discard const */
02330     
02331     res = ccn_locate_key(h, msg, pco, &pubkey);
02332     if (res == 0) {
02333         /* we have the pubkey, use it to verify the msg */
02334         res = ccn_verify_signature(buf, pco->offset[CCN_PCO_E], pco, pubkey);
02335         res = (res == 1) ? 0 : -1;
02336     }
02337     return(res);
02338 }
02339 
02340 /**
02341  * Load a private key from a keystore file.
02342  *
02343  * This call is only required for applications that use something other
02344  * than the user's default signing key.
02345  * @param h is the ccn handle
02346  * @param keystore_path is the pathname of the keystore file
02347  * @param keystore_passphrase is the passphase needed to unlock the keystore
02348  * @param pubid_out, if not NULL, is loaded with the digest of the public key
02349  * @result is 0 for success, negative for error.
02350  */
02351 int
02352 ccn_load_private_key(struct ccn *h,
02353                      const char *keystore_path,
02354                      const char *keystore_passphrase,
02355                      struct ccn_charbuf *pubid_out)
02356 {
02357     struct ccn_keystore *keystore = NULL;
02358     int res = 0;
02359     struct ccn_charbuf *pubid = pubid_out;
02360     struct ccn_charbuf *pubid_store = NULL;
02361     struct hashtb_enumerator ee;
02362     struct hashtb_enumerator *e = &ee;
02363     
02364     if (pubid == NULL)
02365         pubid = pubid_store = ccn_charbuf_create();
02366     if (pubid == NULL) {
02367         res = NOTE_ERRNO(h);
02368         goto Cleanup;
02369     }
02370     keystore = ccn_keystore_create();
02371     if (keystore == NULL) {
02372         res = NOTE_ERRNO(h);
02373         goto Cleanup;
02374     }
02375     res = ccn_keystore_init(keystore,
02376                            (char *)keystore_path,
02377                            (char *)keystore_passphrase);
02378     if (res != 0) {
02379         res = NOTE_ERRNO(h);
02380         goto Cleanup;
02381     }
02382     pubid->length = 0;
02383     ccn_charbuf_append(pubid,
02384                        ccn_keystore_public_key_digest(keystore),
02385                        ccn_keystore_public_key_digest_length(keystore));
02386     hashtb_start(h->keystores, e);
02387     res = hashtb_seek(e, pubid->buf, pubid->length, 0);
02388     if (res == HT_NEW_ENTRY) {
02389         struct ccn_keystore **p = e->data;
02390         *p = keystore;
02391         keystore = NULL;
02392         res = 0;
02393     }
02394     else if (res == HT_OLD_ENTRY)
02395         res = 0;
02396     else
02397         res = NOTE_ERRNO(h);
02398     hashtb_end(e);
02399 Cleanup:
02400     ccn_charbuf_destroy(&pubid_store);
02401     ccn_keystore_destroy(&keystore);
02402     return(res);
02403 }
02404 
02405 /**
02406  * Load the handle's default signing key from a keystore.
02407  *
02408  * This call is only required for applications that use something other
02409  * than the user's default signing key as the handle's default.  It should
02410  * be called early and at most once.
02411  * @param h is the ccn handle
02412  * @param keystore_path is the pathname of the keystore file
02413  * @param keystore_passphrase is the passphase needed to unlock the keystore
02414  * @result is 0 for success, negative for error.
02415  */
02416 int
02417 ccn_load_default_key(struct ccn *h,
02418                      const char *keystore_path,
02419                      const char *keystore_passphrase)
02420 {
02421     struct ccn_charbuf *default_pubid = NULL;
02422     int res;
02423     
02424     if (h->default_pubid != NULL)
02425         return(NOTE_ERR(h, EINVAL));
02426     default_pubid = ccn_charbuf_create();
02427     res = ccn_load_private_key(h,
02428                                keystore_path,
02429                                keystore_passphrase,
02430                                default_pubid);
02431     if (res == 0)
02432         h->default_pubid = default_pubid;
02433     else
02434         ccn_charbuf_destroy(&default_pubid);
02435     return(res);
02436 }
02437 
02438 static void
02439 finalize_keystore(struct hashtb_enumerator *e)
02440 {
02441     struct ccn_keystore **p = e->data;
02442     ccn_keystore_destroy(p);
02443 }
02444 
02445 /**
02446  * Place the public key associated with the params into result
02447  * buffer, and its digest into digest_result.
02448  *
02449  * This is for one of our signing keys, not just any key.
02450  * Result buffers may be NULL if the corresponding result is not wanted.
02451  *
02452  * @returns 0 for success, negative for error
02453  */
02454 int
02455 ccn_get_public_key(struct ccn *h,
02456                    const struct ccn_signing_params *params,
02457                    struct ccn_charbuf *digest_result,
02458                    struct ccn_charbuf *result)
02459 {
02460     struct hashtb_enumerator ee;
02461     struct hashtb_enumerator *e = &ee;
02462     struct ccn_keystore *keystore = NULL;
02463     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
02464     int res;
02465     res = ccn_chk_signing_params(h, params, &sp, NULL, NULL, NULL);
02466     if (res < 0)
02467         return(res);
02468     hashtb_start(h->keystores, e);
02469     if (hashtb_seek(e, sp.pubid, sizeof(sp.pubid), 0) == HT_OLD_ENTRY) {
02470         struct ccn_keystore **pk = e->data;
02471         keystore = *pk;
02472         if (digest_result != NULL) {
02473             digest_result->length = 0;
02474             ccn_charbuf_append(digest_result,
02475                                ccn_keystore_public_key_digest(keystore),
02476                                ccn_keystore_public_key_digest_length(keystore));
02477         }
02478         if (result != NULL) {
02479             struct ccn_buf_decoder decoder;
02480             struct ccn_buf_decoder *d;
02481             const unsigned char *p;
02482             size_t size;
02483             result->length = 0;
02484             ccn_append_pubkey_blob(result, ccn_keystore_public_key(keystore));
02485             d = ccn_buf_decoder_start(&decoder, result->buf, result->length);
02486             res = ccn_buf_match_blob(d, &p, &size);
02487             if (res >= 0) {
02488                 memmove(result->buf, p, size);
02489                 result->length = size;
02490                 res = 0;
02491             }
02492         }
02493     }
02494     else {
02495         res = NOTE_ERR(h, -1);
02496         hashtb_delete(e);
02497     }
02498     hashtb_end(e);
02499     return(res);
02500 }
02501 
02502 /**
02503  * This is mostly for use within the library,
02504  * but may be useful for some clients.
02505  */
02506 int
02507 ccn_chk_signing_params(struct ccn *h,
02508                        const struct ccn_signing_params *params,
02509                        struct ccn_signing_params *result,
02510                        struct ccn_charbuf **ptimestamp,
02511                        struct ccn_charbuf **pfinalblockid,
02512                        struct ccn_charbuf **pkeylocator)
02513 {
02514     struct ccn_charbuf *default_pubid = NULL;
02515     struct ccn_charbuf *temp = NULL;
02516     const char *home = NULL;
02517     const char *ccnx_dir = NULL;
02518     int res = 0;
02519     int i;
02520     int conflicting;
02521     int needed;
02522     
02523     if (params != NULL)
02524         *result = *params;
02525     if ((result->sp_flags & ~(CCN_SP_TEMPL_TIMESTAMP      |
02526                               CCN_SP_TEMPL_FINAL_BLOCK_ID |
02527                               CCN_SP_TEMPL_FRESHNESS      |
02528                               CCN_SP_TEMPL_KEY_LOCATOR    |
02529                               CCN_SP_FINAL_BLOCK          |
02530                               CCN_SP_OMIT_KEY_LOCATOR
02531                               )) != 0)
02532         return(NOTE_ERR(h, EINVAL));
02533     conflicting = CCN_SP_TEMPL_FINAL_BLOCK_ID | CCN_SP_FINAL_BLOCK;
02534     if ((result->sp_flags & conflicting) == conflicting)
02535         return(NOTE_ERR(h, EINVAL));
02536     conflicting = CCN_SP_TEMPL_KEY_LOCATOR | CCN_SP_OMIT_KEY_LOCATOR;
02537         if ((result->sp_flags & conflicting) == conflicting)
02538         return(NOTE_ERR(h, EINVAL));
02539     for (i = 0; i < sizeof(result->pubid) && result->pubid[i] == 0; i++)
02540         continue;
02541     if (i == sizeof(result->pubid)) {
02542         if (h->default_pubid == NULL) {
02543             default_pubid = ccn_charbuf_create();
02544             temp = ccn_charbuf_create();
02545             if (default_pubid == NULL || temp == NULL)
02546                 return(NOTE_ERRNO(h));
02547             ccnx_dir = getenv("CCNX_DIR");
02548             if (ccnx_dir == NULL || ccnx_dir[0] == 0) {
02549                 home = getenv("HOME");
02550                 if (home == NULL)
02551                     home = "";
02552                 ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", home);
02553             }
02554             else
02555                 ccn_charbuf_putf(temp, "%s/.ccnx_keystore", ccnx_dir);
02556             res = ccn_load_private_key(h,
02557                                        ccn_charbuf_as_string(temp),
02558                                        "Th1s1sn0t8g00dp8ssw0rd.",
02559                                        default_pubid);
02560             if (res == 0 && default_pubid->length == sizeof(result->pubid)) {
02561                 h->default_pubid = default_pubid;
02562                 default_pubid = NULL;
02563             }
02564         }
02565         if (h->default_pubid == NULL)
02566             res = NOTE_ERRNO(h);
02567         else
02568             memcpy(result->pubid, h->default_pubid->buf, sizeof(result->pubid));
02569     }
02570     ccn_charbuf_destroy(&default_pubid);
02571     ccn_charbuf_destroy(&temp);
02572     needed = result->sp_flags & (CCN_SP_TEMPL_TIMESTAMP      |
02573                                  CCN_SP_TEMPL_FINAL_BLOCK_ID |
02574                                  CCN_SP_TEMPL_FRESHNESS      |
02575                                  CCN_SP_TEMPL_KEY_LOCATOR    );
02576     if (result->template_ccnb != NULL) {
02577         struct ccn_buf_decoder decoder;
02578         struct ccn_buf_decoder *d;
02579         size_t start;
02580         size_t stop;
02581         size_t size;
02582         const unsigned char *ptr = NULL;
02583         d = ccn_buf_decoder_start(&decoder,
02584                                   result->template_ccnb->buf,
02585                                   result->template_ccnb->length);
02586         if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
02587             ccn_buf_advance(d);
02588             if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest))
02589                 ccn_parse_required_tagged_BLOB(d,
02590                     CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
02591             start = d->decoder.token_index;
02592             ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Timestamp, 1, -1);
02593             stop = d->decoder.token_index;
02594             if ((needed & CCN_SP_TEMPL_TIMESTAMP) != 0) {
02595                 i = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp,
02596                                         d->buf,
02597                                         start, stop,
02598                                         &ptr, &size);
02599                 if (i == 0) {
02600                     if (ptimestamp != NULL) {
02601                         *ptimestamp = ccn_charbuf_create();
02602                         ccn_charbuf_append(*ptimestamp, ptr, size);
02603                     }
02604                     needed &= ~CCN_SP_TEMPL_TIMESTAMP;
02605                 }
02606             }
02607             ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Type, 1, -1);
02608             i = ccn_parse_optional_tagged_nonNegativeInteger(d,
02609                     CCN_DTAG_FreshnessSeconds);
02610             if ((needed & CCN_SP_TEMPL_FRESHNESS) != 0 && i >= 0) {
02611                 result->freshness = i;
02612                 needed &= ~CCN_SP_TEMPL_FRESHNESS;
02613             }
02614             if (ccn_buf_match_dtag(d, CCN_DTAG_FinalBlockID)) {
02615                 ccn_buf_advance(d);
02616                 start = d->decoder.token_index;
02617                 if (ccn_buf_match_some_blob(d))
02618                     ccn_buf_advance(d);
02619                 stop = d->decoder.token_index;
02620                 ccn_buf_check_close(d);
02621                 if ((needed & CCN_SP_TEMPL_FINAL_BLOCK_ID) != 0 && 
02622                     d->decoder.state >= 0 && stop > start) {
02623                     if (pfinalblockid != NULL) {
02624                         *pfinalblockid = ccn_charbuf_create();
02625                         ccn_charbuf_append(*pfinalblockid,
02626                                            d->buf + start, stop - start);
02627                     }
02628                     needed &= ~CCN_SP_TEMPL_FINAL_BLOCK_ID;
02629                 }
02630             }
02631             start = d->decoder.token_index;
02632             if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator))
02633                 ccn_buf_advance_past_element(d);
02634             stop = d->decoder.token_index;
02635             if ((needed & CCN_SP_TEMPL_KEY_LOCATOR) != 0 && 
02636                 d->decoder.state >= 0 && stop > start) {
02637                 if (pkeylocator != NULL) {
02638                     *pkeylocator = ccn_charbuf_create();
02639                     ccn_charbuf_append(*pkeylocator,
02640                                        d->buf + start, stop - start);
02641                 }
02642                 needed &= ~CCN_SP_TEMPL_KEY_LOCATOR;
02643             }
02644             ccn_buf_check_close(d);
02645         }
02646         if (d->decoder.state < 0)
02647             res = NOTE_ERR(h, EINVAL);
02648     }
02649     if (needed != 0)
02650         res = NOTE_ERR(h, EINVAL);
02651     return(res);
02652 }
02653 
02654 /**
02655  * Create a signed ContentObject.
02656  *
02657  * @param h is the ccn handle
02658  * @param resultbuf - result buffer to which the ContentObject will be appended
02659  * @param name_prefix contains the ccnb-encoded name
02660  * @param params describe the ancillary information needed
02661  * @param data points to the raw content
02662  * @param size is the size of the raw content, in bytes
02663  * @returns 0 for success, -1 for error
02664  */
02665 int
02666 ccn_sign_content(struct ccn *h,
02667                  struct ccn_charbuf *resultbuf,
02668                  const struct ccn_charbuf *name_prefix,
02669                  const struct ccn_signing_params *params,
02670                  const void *data, size_t size)
02671 {
02672     struct hashtb_enumerator ee;
02673     struct hashtb_enumerator *e = &ee;
02674     struct ccn_signing_params p = CCN_SIGNING_PARAMS_INIT;
02675     struct ccn_charbuf *signed_info = NULL;
02676     struct ccn_keystore *keystore = NULL;
02677     struct ccn_charbuf *timestamp = NULL;
02678     struct ccn_charbuf *finalblockid = NULL;
02679     struct ccn_charbuf *keylocator = NULL;
02680     int res;
02681     
02682     res = ccn_chk_signing_params(h, params, &p,
02683                                  &timestamp, &finalblockid, &keylocator);
02684     if (res < 0)
02685         return(res);
02686     hashtb_start(h->keystores, e);
02687     if (hashtb_seek(e, p.pubid, sizeof(p.pubid), 0) == HT_OLD_ENTRY) {
02688         struct ccn_keystore **pk = e->data;
02689         keystore = *pk;
02690         signed_info = ccn_charbuf_create();
02691         if (keylocator == NULL && (p.sp_flags & CCN_SP_OMIT_KEY_LOCATOR) == 0) {
02692             /* Construct a key locator containing the key itself */
02693             keylocator = ccn_charbuf_create();
02694             ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
02695             ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
02696             res = ccn_append_pubkey_blob(keylocator,
02697                                          ccn_keystore_public_key(keystore));
02698             ccn_charbuf_append_closer(keylocator); /* </Key> */
02699             ccn_charbuf_append_closer(keylocator); /* </KeyLocator> */
02700         }
02701         if (res >= 0 && (p.sp_flags & CCN_SP_FINAL_BLOCK) != 0) {
02702             int ncomp;
02703             struct ccn_indexbuf *ndx;
02704             const unsigned char *comp = NULL;
02705             size_t size = 0;
02706             
02707             ndx = ccn_indexbuf_create();
02708             ncomp = ccn_name_split(name_prefix, ndx);
02709             if (ncomp < 0)
02710                 res = NOTE_ERR(h, EINVAL);
02711             else {
02712                 finalblockid = ccn_charbuf_create();
02713                 ccn_name_comp_get(name_prefix->buf,
02714                                   ndx, ncomp - 1, &comp, &size);
02715                 ccn_charbuf_append_tt(finalblockid, size, CCN_BLOB);
02716                 ccn_charbuf_append(finalblockid, comp, size);
02717             }
02718             ccn_indexbuf_destroy(&ndx);
02719         }
02720         if (res >= 0)
02721             res = ccn_signed_info_create(signed_info,
02722                                          ccn_keystore_public_key_digest(keystore),
02723                                          ccn_keystore_public_key_digest_length(keystore),
02724                                          timestamp,
02725                                          p.type,
02726                                          p.freshness,
02727                                          finalblockid,
02728                                          keylocator);
02729         if (res >= 0)
02730             res = ccn_encode_ContentObject(resultbuf,
02731                                            name_prefix,
02732                                            signed_info,
02733                                            data,
02734                                            size,
02735                                            ccn_keystore_digest_algorithm(keystore),
02736                                            ccn_keystore_private_key(keystore));
02737     }
02738     else {
02739         res = NOTE_ERR(h, -1);
02740         hashtb_delete(e);
02741     }
02742     hashtb_end(e);
02743     ccn_charbuf_destroy(&timestamp);
02744     ccn_charbuf_destroy(&keylocator);
02745     ccn_charbuf_destroy(&finalblockid);
02746     ccn_charbuf_destroy(&signed_info);
02747     return(res);
02748 }
02749 /**
02750  * Check whether content described by info is final block.
02751  *
02752  * @param info - the ccn_upcall_info describing the ContentObject
02753  * @returns 1 for final block, 0 for not final, -1 if an error occurs
02754  */
02755 int
02756 ccn_is_final_block(struct ccn_upcall_info *info)
02757 {
02758     const unsigned char *ccnb;
02759     size_t ccnb_size;
02760     int res;
02761     ccnb = info->content_ccnb;
02762     if (ccnb == NULL || info->pco == NULL)
02763         return(0);
02764     ccnb_size = info->pco->offset[CCN_PCO_E];
02765     if (info->pco->offset[CCN_PCO_B_FinalBlockID] !=
02766         info->pco->offset[CCN_PCO_E_FinalBlockID]) {
02767         const unsigned char *finalid = NULL;
02768         size_t finalid_size = 0;
02769         const unsigned char *nameid = NULL;
02770         size_t nameid_size = 0;
02771         struct ccn_indexbuf *cc = info->content_comps;
02772         if (cc->n < 2) return(-1);
02773         res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb,
02774                             info->pco->offset[CCN_PCO_B_FinalBlockID],
02775                             info->pco->offset[CCN_PCO_E_FinalBlockID],
02776                             &finalid,
02777                             &finalid_size);
02778         if (res < 0) return(-1);
02779         res = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb,
02780                             cc->buf[cc->n - 2],
02781                             cc->buf[cc->n - 1],
02782                             &nameid,
02783                             &nameid_size);
02784         if (res < 0) return(-1);
02785         if (finalid_size == nameid_size &&
02786             0 == memcmp(finalid, nameid, nameid_size))
02787             return(1);
02788     }
02789     return(0);
02790 }
Generated on Sun Apr 22 23:31:56 2012 for Content-Centric Networking in C by  doxygen 1.6.3