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