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