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