/** * Write a file named index/stable that contains the size of * repoFile1 when the repository is shut down. */ static int r_store_write_stable_point(struct ccnr_handle *h) { struct ccn_charbuf *path = NULL; struct ccn_charbuf *cb = NULL; int fd; path = ccn_charbuf_create(); cb = ccn_charbuf_create(); ccn_charbuf_putf(path, "%s/index/stable", h->directory); unlink(ccn_charbuf_as_string(path)); /* Should not exist, but just in case. */ fd = open(ccn_charbuf_as_string(path), O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, 0666); if (fd == -1) { ccnr_msg(h, "cannot write stable mark %s: %s", ccn_charbuf_as_string(path), strerror(errno)); unlink(ccn_charbuf_as_string(path)); } else { ccn_charbuf_putf(cb, "%ju", (uintmax_t)(h->stable)); write(fd, cb->buf, cb->length); close(fd); if (CCNSHOULDLOG(h, dfsdf, CCNL_INFO)) ccnr_msg(h, "Index marked stable - %s", ccn_charbuf_as_string(cb)); } ccn_charbuf_destroy(&path); ccn_charbuf_destroy(&cb); return(0); }
char * get_orig_router_from_info_content_name(struct ccn_charbuf * content_name) { int start,end; start=0; struct ccn_indexbuf *comps=ccn_indexbuf_create(); ccn_name_split (content_name, comps); end=check_for_name_component_in_name(content_name,comps,"nlsr"); struct ccn_charbuf *temp=ccn_charbuf_create(); ccn_name_init(temp); ccn_name_append_components( temp, content_name->buf, comps->buf[start], comps->buf[end]); struct ccn_charbuf *temp1=ccn_charbuf_create(); ccn_uri_append(temp1, temp->buf, temp->length, 0); char *orig_router=(char *)calloc(strlen(ccn_charbuf_as_string(temp1))+1, sizeof(char)); memcpy(orig_router,ccn_charbuf_as_string(temp1), strlen(ccn_charbuf_as_string(temp1))); orig_router[strlen(orig_router)]='\0'; ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&temp1); ccn_indexbuf_destroy(&comps); return orig_router; }
char * get_orig_router_from_lsa_name(struct ccn_charbuf * content_name) { int start=0; size_t comp_size; const unsigned char *second_last_comp; char *second_comp_type; char *sep="."; char *rem; struct ccn_indexbuf *components=ccn_indexbuf_create(); struct ccn_charbuf *name=ccn_charbuf_create(); ccn_name_from_uri(name,nlsr->slice_prefix); ccn_name_split (name, components); start=components->n-2; ccn_charbuf_destroy(&name); ccn_indexbuf_destroy(&components); struct ccn_indexbuf *comps=ccn_indexbuf_create(); ccn_name_split (content_name, comps); ccn_name_comp_get( content_name->buf, comps, comps->n-1-2, &second_last_comp, &comp_size); second_comp_type=strtok_r((char *)second_last_comp, sep, &rem); if ( strcmp( second_comp_type, "lsId" ) == 0 ){ ccn_name_chop(content_name,comps,-3); } else{ ccn_name_chop(content_name,comps,-2); } struct ccn_charbuf *temp=ccn_charbuf_create(); ccn_name_init(temp); ccn_name_append_components( temp, content_name->buf, comps->buf[start+1], comps->buf[comps->n - 1]); struct ccn_charbuf *temp1=ccn_charbuf_create(); ccn_uri_append(temp1, temp->buf, temp->length, 0); char *orig_router=(char *)calloc(strlen(ccn_charbuf_as_string(temp1))+1, sizeof(char)); memcpy(orig_router,ccn_charbuf_as_string(temp1), strlen(ccn_charbuf_as_string(temp1))); orig_router[strlen(orig_router)]='\0'; ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&temp1); ccn_indexbuf_destroy(&comps); return orig_router; }
/** * Basic tests of ccn_btree_io_from_directory() and its methods. * * Assumes TEST_DIRECTORY has been set. */ static int test_btree_io(void) { int res; struct ccn_btree_node nodespace = {0}; struct ccn_btree_node *node = &nodespace; struct ccn_btree_io *io = NULL; /* Open it up. */ io = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL); CHKPTR(io); node->buf = ccn_charbuf_create(); CHKPTR(node->buf); node->nodeid = 12345; res = io->btopen(io, node); CHKSYS(res); FAILIF(node->iodata == NULL); ccn_charbuf_putf(node->buf, "smoke"); res = io->btwrite(io, node); CHKSYS(res); node->buf->length = 0; ccn_charbuf_putf(node->buf, "garbage"); res = io->btread(io, node, 500000); CHKSYS(res); FAILIF(node->buf->length != 5); FAILIF(node->buf->limit > 10000); node->clean = 5; ccn_charbuf_putf(node->buf, "r"); res = io->btwrite(io, node); CHKSYS(res); node->buf->length--; ccn_charbuf_putf(node->buf, "d"); res = io->btread(io, node, 1000); CHKSYS(res); FAILIF(0 != strcmp("smoker", ccn_charbuf_as_string(node->buf))); node->buf->length--; res = io->btwrite(io, node); CHKSYS(res); node->buf->length = 0; ccn_charbuf_putf(node->buf, "garbage"); node->clean = 0; res = io->btread(io, node, 1000); CHKSYS(res); res = io->btclose(io, node); CHKSYS(res); FAILIF(node->iodata != NULL); FAILIF(0 != strcmp("smoke", ccn_charbuf_as_string(node->buf))); res = io->btdestroy(&io); CHKSYS(res); ccn_charbuf_destroy(&node->buf); return(res); }
/** * Produce ccnr debug output. * Output is produced via h->logger under the control of h->debug; * prepends decimal timestamp and process identification. * Caller should not supply newlines. * @param h the ccnr handle * @param fmt printf-like format string */ void ccnr_msg(struct ccnr_handle *h, const char *fmt, ...) { struct timeval t; va_list ap; struct ccn_charbuf *b; int res; if (h == NULL || h->debug == 0 || h->logger == 0) return; b = ccn_charbuf_create(); if (b == NULL) return; gettimeofday(&t, NULL); if ((h->debug >= CCNL_FINE) && ((h->logbreak-- < 0 && t.tv_sec != h->logtime) || t.tv_sec >= h->logtime + 30)) { ccn_charbuf_putf(b, "%ld.000000 ccnr[%d]: %s ____________________ %s", (long)t.tv_sec, h->logpid, h->portstr ? h->portstr : "", ctime(&t.tv_sec)); h->logtime = t.tv_sec; h->logbreak = 30; } ccn_charbuf_putf(b, "%ld.%06u ccnr[%d]: %s\n", (long)t.tv_sec, (unsigned)t.tv_usec, h->logpid, fmt); va_start(ap, fmt); /* b should already have null termination, but use call for cleanliness */ res = (*h->logger)(h->loggerdata, ccn_charbuf_as_string(b), ap); va_end(ap); ccn_charbuf_destroy(&b); /* if there's no one to hear, don't make a sound */ if (res < 0) h->debug = 0; }
int sync_cb(struct ccns_handle *h, struct ccn_charbuf *lhash, struct ccn_charbuf *rhash, struct ccn_charbuf *name) { char *hexL; char *hexR; struct ccn_charbuf *uri = ccn_charbuf_create(); ccn_uri_append(uri, name->buf, name->length, 1); if (lhash == NULL || lhash->length == 0) { hexL = strdup("none"); } else hexL = hex_string(lhash->buf, lhash->length); if (rhash == NULL || rhash->length == 0) { hexR = strdup("none"); } else hexR = hex_string(rhash->buf, rhash->length); printf("%s %s %s\n", ccn_charbuf_as_string(uri), hexL, hexR); fflush(stdout); free(hexL); free(hexR); ccn_charbuf_destroy(&uri); return(0); }
int main(int argc, char **argv) { struct ccn *ccn = NULL; struct ccn_charbuf *name = NULL; int opt; int res; while ((opt = getopt(argc, argv, "h")) != -1) { switch (opt) { case 'h': default: usage(argv[0]); } } ccn = ccn_create(); if (ccn_connect(ccn, NULL) == -1) { perror("Could not connect to ccnd"); exit(1); } name = ccn_charbuf_create(); res = ccn_guest_prefix(ccn, name, 500); if (res < 0) exit(1); printf("%s\n", ccn_charbuf_as_string(name)); exit(0); }
/** * Read the contents of the repository config file * * Calls r_init_fail and returns NULL in case of error. * @returns unparsed content of config file in a newly allocated charbuf */ struct ccn_charbuf * r_init_read_config(struct ccnr_handle *h) { struct ccn_charbuf *path = NULL; struct ccn_charbuf *contents = NULL; size_t sz = 800; ssize_t sres = -1; int fd; h->directory = getenv("CCNR_DIRECTORY"); if (h->directory == NULL || h->directory[0] == 0) h->directory = "."; path = ccn_charbuf_create(); contents = ccn_charbuf_create(); if (path == NULL || contents == NULL) return(NULL); ccn_charbuf_putf(path, "%s/config", h->directory); fd = open(ccn_charbuf_as_string(path), O_RDONLY); if (fd == -1) { if (errno == ENOENT) sres = 0; else r_init_fail(h, __LINE__, ccn_charbuf_as_string(path), errno); } else { for (;;) { sres = read(fd, ccn_charbuf_reserve(contents, sz), sz); if (sres == 0) break; if (sres < 0) { r_init_fail(h, __LINE__, "Read failed reading config", errno); break; } contents->length += sres; if (contents->length > 999999) { r_init_fail(h, __LINE__, "config file too large", 0); sres = -1; break; } } close(fd); } ccn_charbuf_destroy(&path); if (sres < 0) ccn_charbuf_destroy(&contents); return(contents); }
static void init_cached_keystore() { ccn_keystore *keystore = cached_keystore; int res; if (keystore == NULL) { ccn_charbuf *temp = ccn_charbuf_create(); keystore = ccn_keystore_create(); ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME")); res = ccn_keystore_init(keystore, ccn_charbuf_as_string(temp), (char *)"Th1s1sn0t8g00dp8ssw0rd."); if (res != 0) { printf("Failed to initialize keystore %s\n", ccn_charbuf_as_string(temp)); exit(1); } ccn_charbuf_destroy(&temp); cached_keystore = keystore; } }
PUBLIC struct content_entry * r_store_content_next(struct ccnr_handle *h, struct content_entry *content) { if (content == NULL) return(0); /* We need to go past the current name, so make sure there is a 0 byte */ ccn_charbuf_as_string(content->flatname); content = r_store_look(h, content->flatname->buf, content->flatname->length + 1); return(content); }
void NdnlpSvc_link2ccn(NdnlpSvc self) { NdnlpPkt pkt; while (NULL != (pkt = Link_read(self->link))) { if (D) printf("===== link2ccn ===== \n"); if (NdnlpPkt_isData(pkt)) { printf("pkt: %s\n", ccn_charbuf_as_string(pkt)); FILE *dumpfile; dumpfile = fopen("dumpfile.txt", "a"); fprintf(dumpfile, "%s\n", ccn_charbuf_as_string(pkt)); fclose(dumpfile); NdnlpSvc_data(self, NdnlpPkt_asData(pkt)); } else if (NdnlpPkt_isAck(pkt)) { NdnlpSvc_ack(self, NdnlpPkt_asAck(pkt)); } else { NdnlpPkt_dtor(pkt); } } }
/** * Read the former size of repoFile1 from index/stable, and remove * the latter. */ static void r_store_read_stable_point(struct ccnr_handle *h) { struct ccn_charbuf *path = NULL; struct ccn_charbuf *cb = NULL; int fd; int i; ssize_t rres; uintmax_t val; unsigned char c; path = ccn_charbuf_create(); cb = ccn_charbuf_create(); ccn_charbuf_putf(path, "%s/index/stable", h->directory); fd = open(ccn_charbuf_as_string(path), O_RDONLY, 0666); if (fd != -1) { rres = read(fd, ccn_charbuf_reserve(cb, 80), 80); if (rres > 0) cb->length = rres; close(fd); if (CCNSHOULDLOG(h, dfsdf, CCNL_INFO)) ccnr_msg(h, "Last stable at %s", ccn_charbuf_as_string(cb)); } for (val = 0, i = 0; i < cb->length; i++) { c = cb->buf[i]; if ('0' <= c && c <= '9') val = val * 10 + (c - '0'); else break; } if (i == 0 || i < cb->length) { ccnr_msg(h, "Bad stable mark - %s", ccn_charbuf_as_string(cb)); h->stable = 0; } else { h->stable = val; unlink(ccn_charbuf_as_string(path)); } ccn_charbuf_destroy(&path); ccn_charbuf_destroy(&cb); }
static int merge_files(struct ccnr_handle *h) { int i, last_file; int res; struct ccn_charbuf *filename = ccn_charbuf_create(); // first parse the file(s) making sure there are no errors for (i = 2;; i++) { filename->length = 0; ccn_charbuf_putf(filename, "repoFile%d", i); res = r_init_map_and_process_file(h, filename, 0); if (res == 1) break; if (res < 0) { ccnr_msg(h, "Error parsing repository file %s", ccn_charbuf_as_string(filename)); return (-1); } } last_file = i - 1; for (i = 2; i <= last_file; i++) { filename->length = 0; ccn_charbuf_putf(filename, "repoFile%d", i); res = r_init_map_and_process_file(h, filename, 1); if (res < 0) { ccnr_msg(h, "Error in phase 2 incorporating repository file %s", ccn_charbuf_as_string(filename)); return (-1); } } for (i = last_file; i > 1; --i) { filename->length = 0; ccn_charbuf_putf(filename, "%s/repoFile%d", h->directory, i); if (CCNSHOULDLOG(h, LM_128, CCNL_INFO)) ccnr_msg(h, "unlinking %s", ccn_charbuf_as_string(filename)); unlink(ccn_charbuf_as_string(filename)); } ccn_charbuf_destroy(&filename); return (0); }
/** * Base loop for the background CCN task * * This is the main execution loop for the background task responsible for * interacting with the CCN network. It is from this point that many of the above methods are * called to work the inbound messages from ccnx as well as sending out the data messages. * * \param data the task context information setup by the parent sink element thread */ static void ccn_event_thread (void *data) { Gstccnxsink *me = (Gstccnxsink *) data; struct ccn_charbuf *filtName; struct ccn_charbuf *temp; int res = 0; GST_DEBUG ("CCNxSink event: *** event thread starting"); temp = ccn_charbuf_create (); filtName = ccn_charbuf_create (); /* A closure is what defines what to do when an inbound interest arrives */ if ((me->ccn_closure = calloc (1, sizeof (struct ccn_closure))) == NULL) { GST_ELEMENT_ERROR (me, RESOURCE, READ, (NULL), ("closure alloc failed")); return; } /* We setup the closure to contain the sink element context reference, and also tell it what function to call */ me->ccn_closure->data = me; me->ccn_closure->p = new_interests; me->timeouts = 0; ccn_charbuf_append (filtName, me->name->buf, me->name->length); /* This call will set up a handler for interests we expect to get from clients */ // hDump(DUMP_ADDR(filtName->buf), DUMP_SIZE(filtName->length)); ccn_set_interest_filter (me->ccn, filtName, me->ccn_closure); GST_DEBUG ("CCNxSink event: interest filter registered\n"); /* Some debugging information */ temp->length = 0; ccn_uri_append (temp, me->name->buf, me->name->length, TRUE); GST_DEBUG ("CCNxSink event: using uri: %s\n", ccn_charbuf_as_string (temp)); /* Now that the interest is registered, we loop around waiting for something to do */ /* We pass control to ccnx for a while so it can work with any incoming or outgoing data */ /* and then we check our fifo queue for work to do. That's about it! */ /* We check to see if any problems have caused our ccnd connection to fail, and we reconnect */ while (res >= 0) { GST_DEBUG ("CCNxSink event: *** looping"); res = ccn_run (me->ccn, 50); check_fifo (me); if (res < 0 && ccn_get_connection_fd (me->ccn) == -1) { GST_DEBUG ("CCNxSink event: need to reconnect..."); /* Try reconnecting, after a bit of delay */ msleep ((30 + (getpid () % 30)) * 1000); res = ccn_connect (me->ccn, ccndHost ()); } } GST_DEBUG ("CCNxSink event: *** event thread ending"); }
/** * Use standard mkdtemp() to create a subdirectory of the * current working directory, and set the TEST_DIRECTORY environment * variable with its name. */ static int test_directory_creation(void) { int res; struct ccn_charbuf *dirbuf; char *temp; dirbuf = ccn_charbuf_create(); CHKPTR(dirbuf); res = ccn_charbuf_putf(dirbuf, "./%s", "_bt_XXXXXX"); CHKSYS(res); temp = mkdtemp(ccn_charbuf_as_string(dirbuf)); CHKPTR(temp); res = ccn_charbuf_putf(dirbuf, "/%s", "_test"); CHKSYS(res); res = mkdir(ccn_charbuf_as_string(dirbuf), 0777); CHKSYS(res); printf("Created directory %s\n", ccn_charbuf_as_string(dirbuf)); setenv("TEST_DIRECTORY", ccn_charbuf_as_string(dirbuf), 1); ccn_charbuf_destroy(&dirbuf); return(res); }
static void collect_faces_html(struct ccnd_handle *h, struct ccn_charbuf *b) { int i; struct ccn_charbuf *nodebuf; int port; nodebuf = ccn_charbuf_create(); ccn_charbuf_putf(b, "<h4>Faces</h4>" NL); ccn_charbuf_putf(b, "<ul>"); for (i = 0; i < h->face_limit; i++) { struct face *face = h->faces_by_faceid[i]; if (face != NULL && (face->flags & CCN_FACE_UNDECIDED) == 0) { ccn_charbuf_putf(b, " <li>"); ccn_charbuf_putf(b, "<b>face:</b> %u <b>flags:</b> 0x%x", face->faceid, face->flags); ccn_charbuf_putf(b, " <b>pending:</b> %d", face->pending_interests); if (face->recvcount != 0) ccn_charbuf_putf(b, " <b>activity:</b> %d", face->recvcount); nodebuf->length = 0; port = ccn_charbuf_append_sockaddr(nodebuf, face->addr); if (port > 0) { const char *node = ccn_charbuf_as_string(nodebuf); int chk = CCN_FACE_MCAST | CCN_FACE_UNDECIDED | CCN_FACE_NOSEND | CCN_FACE_GG | CCN_FACE_PASSIVE; if ((face->flags & chk) == 0) ccn_charbuf_putf(b, " <b>remote:</b> " "<a href='http://%s:%s/'>" "%s:%d</a>", node, CCN_DEFAULT_UNICAST_PORT, node, port); else if ((face->flags & CCN_FACE_PASSIVE) == 0) ccn_charbuf_putf(b, " <b>remote:</b> %s:%d", node, port); else ccn_charbuf_putf(b, " <b>local:</b> %s:%d", node, port); if (face->sendface != face->faceid && face->sendface != CCN_NOFACEID) ccn_charbuf_putf(b, " <b>via:</b> %u", face->sendface); } ccn_charbuf_putf(b, "</li>" NL); } } ccn_charbuf_putf(b, "</ul>"); ccn_charbuf_destroy(&nodebuf); }
void NdnlpSvc_msg(NdnlpSvc self, CcnbMsg msg) { NdnlpPktA pkts = MsgSlicer_slice(self->msgSlicer, msg); for (int i = 0, len = NdnlpPktA_length(pkts); i < len; ++i) { NdnlpPkt pkt = NdnlpPktA_get(pkts, i); if (NdnlpSvc_RLAPolicy(self, msg, pkt)) { DataPkt_setFlags(pkt, DataPkt_getFlags(pkt) | DataPktFlag_RLA); SentPkts_insert(self->sentPkts, pkt); } printf("pkt: %s\n", ccn_charbuf_as_string(pkt)); Link_write(self->link, pkt); } NdnlpPktA_dtor(pkts, false); CcnbMsg_dtor(msg); }
PUBLIC int r_io_open_repo_data_file(struct ccnr_handle *h, const char *name, int output) { struct ccn_charbuf *temp = NULL; int fd = -1; struct fdholder *fdholder = NULL; temp = ccn_charbuf_create(); ccn_charbuf_putf(temp, "%s/%s", h->directory, name); fd = open(ccn_charbuf_as_string(temp), output ? (O_CREAT | O_WRONLY | O_APPEND) : O_RDONLY, 0666); if (fd == -1) { if (CCNSHOULDLOG(h, sdf, CCNL_FINE)) ccnr_msg(h, "open(%s): %s", ccn_charbuf_as_string(temp), strerror(errno)); ccn_charbuf_destroy(&temp); return(-1); } fdholder = r_io_record_fd(h, fd, temp->buf, temp->length, CCNR_FACE_REPODATA | (output ? CCNR_FACE_NORECV : CCNR_FACE_NOSEND)); if (fdholder == NULL) close_fd(&fd); else { if (!output) { /* Use a larger buffer for indexing an existing repo file */ if (fdholder->inbuf == NULL) { fdholder->inbuf = ccn_charbuf_create(); fdholder->bufoffset = 0; } if (fdholder->inbuf != NULL) ccn_charbuf_reserve(fdholder->inbuf, 256 * 1024); } if (CCNSHOULDLOG(h, sdf, CCNL_INFO)) ccnr_msg(h, "opened fd=%d file=%s", fd, ccn_charbuf_as_string(temp)); } ccn_charbuf_destroy(&temp); return(fd); }
void get_name_part(struct name_prefix *name_part,struct ccn_charbuf * interest_ccnb, struct ccn_indexbuf *interest_comps, int offset) { int lsa_position=0; struct ccn_indexbuf *components=ccn_indexbuf_create(); struct ccn_charbuf *name=ccn_charbuf_create(); ccn_name_from_uri(name,nlsr->slice_prefix); ccn_name_split (name, components); lsa_position=components->n-2; ccn_charbuf_destroy(&name); struct ccn_charbuf *temp=ccn_charbuf_create(); ccn_name_init(temp); ccn_name_append_components( temp, interest_ccnb->buf, interest_comps->buf[lsa_position+1], interest_comps->buf[interest_comps->n - 1]); struct ccn_charbuf *temp1=ccn_charbuf_create(); ccn_uri_append(temp1, temp->buf, temp->length, 0); name_part->name=(char *)calloc(strlen(ccn_charbuf_as_string(temp1))+1, sizeof(char)); memcpy(name_part->name,ccn_charbuf_as_string(temp1), strlen(ccn_charbuf_as_string(temp1))); name_part->name[strlen(ccn_charbuf_as_string(temp1))]='\0'; name_part->length=strlen(ccn_charbuf_as_string(temp1))+1; ccn_charbuf_destroy(&temp1); ccn_charbuf_destroy(&temp); ccn_indexbuf_destroy(&components); if ( nlsr->debugging ) printf("Name Part: %s \n",name_part->name); }
static void collect_faces_xml(struct ccnd_handle *h, struct ccn_charbuf *b) { int i; int m; int port; struct ccn_charbuf *nodebuf; nodebuf = ccn_charbuf_create(); ccn_charbuf_putf(b, "<faces>"); for (i = 0; i < h->face_limit; i++) { struct face *face = h->faces_by_faceid[i]; if (face != NULL && (face->flags & CCN_FACE_UNDECIDED) == 0) { ccn_charbuf_putf(b, "<face>"); ccn_charbuf_putf(b, "<faceid>%u</faceid>" "<faceflags>%04x</faceflags>", face->faceid, face->flags); ccn_charbuf_putf(b, "<pending>%d</pending>", face->pending_interests); ccn_charbuf_putf(b, "<recvcount>%d</recvcount>", face->recvcount); nodebuf->length = 0; port = ccn_charbuf_append_sockaddr(nodebuf, face->addr); if (port > 0) { const char *node = ccn_charbuf_as_string(nodebuf); ccn_charbuf_putf(b, "<ip>%s:%d</ip>", node, port); } if (face->sendface != face->faceid && face->sendface != CCN_NOFACEID) ccn_charbuf_putf(b, "<via>%u</via>", face->sendface); if (face != NULL && (face->flags & CCN_FACE_PASSIVE) == 0) { ccn_charbuf_putf(b, "<meters>"); for (m = 0; m < CCND_FACE_METER_N; m++) collect_meter_xml(h, b, face->meter[m]); ccn_charbuf_putf(b, "</meters>"); } ccn_charbuf_putf(b, "</face>" NL); } } ccn_charbuf_putf(b, "</faces>"); ccn_charbuf_destroy(&nodebuf); }
/** * Produce a ccnd debug trace entry. * Output is produced by calling ccnd_msg. * @param h the ccnd handle * @param lineno caller's source line number (usually __LINE__) * @param msg a short text tag to identify the entry * @param face handle of associated face; may be NULL * @param ccnb points to ccnb-encoded Interest or ContentObject * @param ccnb_size is in bytes */ void ccnd_debug_ccnb(struct ccnd_handle *h, int lineno, const char *msg, struct face *face, const unsigned char *ccnb, size_t ccnb_size) { struct ccn_charbuf *c; struct ccn_parsed_interest pi; const unsigned char *nonce = NULL; size_t nonce_size = 0; size_t i; if (h != NULL && h->debug == 0) return; c = ccn_charbuf_create(); ccn_charbuf_putf(c, "debug.%d %s ", lineno, msg); if (face != NULL) ccn_charbuf_putf(c, "%u ", face->faceid); ccn_uri_append(c, ccnb, ccnb_size, 1); ccn_charbuf_putf(c, " (%u bytes)", (unsigned)ccnb_size); if (ccn_parse_interest(ccnb, ccnb_size, &pi, NULL) >= 0) { const char *p = ""; ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, ccnb, pi.offset[CCN_PI_B_Nonce], pi.offset[CCN_PI_E_Nonce], &nonce, &nonce_size); if (nonce_size > 0) { ccn_charbuf_putf(c, " "); if (nonce_size == 12) p = "CCC-P-F-T-NN"; for (i = 0; i < nonce_size; i++) ccn_charbuf_putf(c, "%s%02X", (*p) && (*p++)=='-' ? "-" : "", nonce[i]); } } ccnd_msg(h, "%s", ccn_charbuf_as_string(c)); ccn_charbuf_destroy(&c); }
PUBLIC void ccnr_debug_content(struct ccnr_handle *h, int lineno, const char *msg, struct fdholder *fdholder, struct content_entry *content) { struct ccn_charbuf *c = ccn_charbuf_create(); struct ccn_charbuf *flat = content->flatname; if (c == NULL) return; ccn_charbuf_putf(c, "debug.%d %s ", lineno, msg); if (fdholder != NULL) ccn_charbuf_putf(c, "%u ", fdholder->filedesc); if (flat != NULL) ccn_uri_append_flatname(c, flat->buf, flat->length, 1); ccn_charbuf_putf(c, " (%d bytes)", content->size); ccnr_msg(h, "%s", ccn_charbuf_as_string(c)); ccn_charbuf_destroy(&c); }
// my_response is used to handle a reply static enum ccn_upcall_res my_response(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { static char *here = "sync_track.my_response"; enum ccn_upcall_res ret = CCN_UPCALL_RESULT_ERR; switch (kind) { case CCN_UPCALL_FINAL: free(selfp); ret = CCN_UPCALL_RESULT_OK; break; case CCN_UPCALL_CONTENT_UNVERIFIED: ret = CCN_UPCALL_RESULT_VERIFY; break; case CCN_UPCALL_CONTENT_KEYMISSING: ret = CCN_UPCALL_RESULT_FETCHKEY; break; case CCN_UPCALL_INTEREST_TIMED_OUT: { struct sync_diff_fetch_data *fd = selfp->data; //enum local_flags flags = selfp->intdata; if (fd == NULL) break; struct sync_diff_data *diff_data = fd->diff_data; if (diff_data == NULL) break; struct ccns_handle *ch = diff_data->client_data; free_fetch_data(ch, fd); start_round(ch, 10); ret = CCN_UPCALL_RESULT_OK; break; } case CCN_UPCALL_CONTENT_RAW: case CCN_UPCALL_CONTENT: { struct sync_diff_fetch_data *fd = selfp->data; enum local_flags flags = selfp->intdata; if (fd == NULL) break; struct sync_diff_data *diff_data = fd->diff_data; if (diff_data == NULL) break; struct SyncRootStruct *root = diff_data->root; if (root == NULL) break; struct ccns_handle *ch = diff_data->client_data; struct SyncNodeComposite *nc = extractNode(root, info); if (ch->debug >= CCNL_FINE) { char fs[1024]; int pos = 0; switch (flags) { case LF_NULL: pos += snprintf(fs+pos, sizeof(fs)-pos, "null"); break; case LF_ADVISE: pos += snprintf(fs+pos, sizeof(fs)-pos, "advise"); break; case LF_NODE: pos += snprintf(fs+pos, sizeof(fs)-pos, "node"); break; default: pos += snprintf(fs+pos, sizeof(fs)-pos, "??%d", flags); break; } if (nc != NULL) pos += snprintf(fs+pos, sizeof(fs)-pos, ", nc OK"); struct ccn_charbuf *nm = SyncNameForIndexbuf(info->content_ccnb, info->content_comps); struct ccn_charbuf *uri = SyncUriForName(nm); pos += snprintf(fs+pos, sizeof(fs)-pos, ", %s", ccn_charbuf_as_string(uri)); SyncNoteSimple(diff_data->root, here, fs); ccn_charbuf_destroy(&nm); ccn_charbuf_destroy(&uri); } if (nc != NULL) { // the node exists, so store it // TBD: check the hash? struct ccns_handle *ch = diff_data->client_data; struct SyncHashCacheEntry *ce = SyncHashEnter(root->ch, nc->hash->buf, nc->hash->length, SyncHashState_remote); if (flags == LF_ADVISE) { ch->hashSeen = SyncNoteHash(ch->hashSeen, ce); if (ch->next_ce == NULL) // have to have an initial place to start ch->next_ce = ce; } if (ce->ncR == NULL) { // store the node ce->ncR = nc; SyncNodeIncRC(nc); } else { // flush the node SyncNodeDecRC(nc); nc = NULL; } if (flags != LF_NULL) { // from start_interest start_round(ch, 10); } else { // from sync_diff sync_diff_note_node(diff_data, ce); } ret = CCN_UPCALL_RESULT_OK; } free_fetch_data(ch, fd); break; default: // SHOULD NOT HAPPEN break; } } return ret; }
int ccndc_srv(struct ccndc_data *self, const unsigned char *domain, size_t domain_size) { char *proto = NULL; char *host = NULL; int port = 0; char port_str[10]; struct ccn_charbuf *uri; struct ccn_charbuf *uri_auto; struct ccn_face_instance *face; struct ccn_face_instance *newface; struct ccn_forwarding_entry *prefix; struct ccn_forwarding_entry *prefix_auto; int res; res = ccndc_query_srv(domain, domain_size, &host, &port, &proto); if (res < 0) { return -1; } uri = ccn_charbuf_create(); ccn_charbuf_append_string(uri, "ccnx:/"); if (domain_size != 0) { ccn_uri_append_percentescaped(uri, domain, domain_size); } snprintf (port_str, sizeof(port_str), "%d", port); /* now process the results */ /* pflhead, lineno=0, "add" "ccnx:/asdfasdf.com/" "tcp|udp", host, portstring, NULL NULL NULL */ ccndc_note(__LINE__, " >>> trying: add %s %s %s %s <<<\n", ccn_charbuf_as_string(uri), proto, host, port_str); face = parse_ccn_face_instance(self, proto, host, port_str, NULL, NULL, (~0U) >> 1); prefix = parse_ccn_forwarding_entry(self, ccn_charbuf_as_string(uri), NULL, self->lifetime); if (face == NULL || prefix == NULL) { res = -1; goto Cleanup; } // crazy operation // First. "Create" face, which will do nothing if face already exists // Second. Destroy the face // Third. Create face for real newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); res = -1; goto Cleanup; } face->faceid = newface->faceid; ccn_face_instance_destroy(&newface); newface = ccndc_do_face_action(self, "destroyface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot destroy face"); } else { ccn_face_instance_destroy(&newface); } newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); res = -1; goto Cleanup; } prefix->faceid = newface->faceid; ccn_face_instance_destroy(&newface); res = ccndc_do_prefix_action(self, "prefixreg", prefix); if (res < 0) { ccndc_warn(__LINE__, "Cannot register prefix [%s]\n", ccn_charbuf_as_string(uri)); } uri_auto = ccn_charbuf_create(); ccn_charbuf_append_string(uri_auto, "ccnx:/autoconf-route"); prefix_auto = parse_ccn_forwarding_entry(self, ccn_charbuf_as_string(uri_auto), NULL, self->lifetime); if (prefix_auto == NULL) { res = -1; goto Cleanup; } prefix_auto->faceid = prefix->faceid; res = ccndc_do_prefix_action(self, "prefixreg", prefix_auto); if (res < 0) { ccndc_warn(__LINE__, "Cannot register prefix_auto [%s]\n", ccn_charbuf_as_string(uri_auto)); } Cleanup: free(host); ccn_charbuf_destroy(&uri); ccn_charbuf_destroy(&uri_auto); ccn_face_instance_destroy(&face); ccn_forwarding_entry_destroy(&prefix); ccn_forwarding_entry_destroy(&prefix_auto); return res; }
int main(int argc, char **argv) { int opt; int res; char *prog = argv[0]; struct ccn *h; struct ccns_slice *slice; struct ccn_charbuf *prefix = ccn_charbuf_create(); struct ccn_charbuf *topo = ccn_charbuf_create(); struct ccn_charbuf *clause = ccn_charbuf_create(); struct ccn_charbuf *slice_name = ccn_charbuf_create(); struct ccn_charbuf *slice_uri = ccn_charbuf_create(); enum { CREATE = 0, DELETE = 1 } cmd = CREATE; unsigned verbose = 0; unsigned i; if (prefix == NULL || topo == NULL || clause == NULL || slice_name == NULL || slice_uri == NULL) { fprintf(stderr, "Unable to allocate required memory.\n"); exit(1); } while ((opt = getopt(argc, argv, "vh")) != -1) { switch (opt) { case 'v': verbose = 1; break; default: case 'h': usage(prog); break; } } argc -= optind; argv += optind; if (argc < 3) usage(prog); if (strcmp(argv[0], "create") == 0) cmd = CREATE; else if (strcmp(argv[0], "delete") == 0) cmd = DELETE; else usage(prog); slice = ccns_slice_create(); ccn_charbuf_reset(topo); if (0 > ccn_name_from_uri(topo, argv[1])) usage(prog); ccn_charbuf_reset(prefix); if (0 > ccn_name_from_uri(prefix, argv[2])) usage(prog); if (0 > ccns_slice_set_topo_prefix(slice, topo, prefix)) usage(prog); for (i = 3; i < argc; i++) { ccn_charbuf_reset(clause); if (0 > ccn_name_from_uri(clause, argv[i])) usage(prog); else if (0 > ccns_slice_add_clause(slice, clause)) usage(prog); } h = ccn_create(); res = ccn_connect(h, NULL); if (0 > res) { fprintf(stderr, "Unable to connect to ccnd.\n"); exit(1); } switch(cmd) { case CREATE: res = ccns_write_slice(h, slice, slice_name); break; case DELETE: ccns_slice_name(slice_name, slice); res = ccns_delete_slice(h, slice_name); break; } if (verbose || res < 0) { ccn_uri_append(slice_uri, slice_name->buf, slice_name->length, 1); printf("%s slice %s %s\n", cmd == CREATE ? "create" : "delete", ccn_charbuf_as_string(slice_uri), (res < 0) ? "failed" : "succeeded"); } ccns_slice_destroy(&slice); ccn_destroy(&h); ccn_charbuf_destroy(&prefix); ccn_charbuf_destroy(&topo); ccn_charbuf_destroy(&clause); ccn_charbuf_destroy(&slice_name); ccn_charbuf_destroy(&slice_uri); exit(res); }
/* * This upcall gets called for each piece of incoming content that * matches one of our interests. We need to issue a new interest that * excludes another component at the current level, and perhaps also * and interest to start exploring the next level. Thus if the matched * interest is * /a/b/c exclude {d,e,f,i,j,k} * and we get * /a/b/c/g/h * we would issue a new interest * /a/b/c exclude {d,e,f,g,i,j,k} * to continue exploring the current level, plus a simple interest * /a/b/c/g * to start exploring the next level as well. * * This does end up fetching each piece of content multiple times, once for * each level in the name. The repeated requests will be answered from the local * content store, though, and so should not generate extra network traffic. * There is a lot of unanswerable interest generated, though. * * To prevent the interests from becoming too huge, we may need to split them. * Thus if the first new interest above were deemed too large, we could instead * issue the two interests * /a/b/c exclude {d,e,f,g,*} * /a/b/c exclude {*,g,i,j,k} * where * stands for a Bloom filter that excludes anything. Note the * repetition of g to ensure that these two interests cover disjoint portions * of the hierarchy. We need to keep track of the endpoint conditions * as well as the excluded set in our upcall data. * When a split happens, we need a new closure to track it, as we do when * we start exploring a new level. */ static enum ccn_upcall_res incoming_content( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { struct ccn_charbuf *c = NULL; struct ccn_charbuf *comp = NULL; struct ccn_charbuf *uri = NULL; const unsigned char *ccnb = NULL; size_t ccnb_size = 0; struct ccn_indexbuf *comps = NULL; int matched_comps = 0; int res; int i; struct ccn_traversal *data = get_my_data(selfp); if (kind == CCN_UPCALL_FINAL) { for (i = 0; i < data->n_excl; i++) ccn_charbuf_destroy(&(data->excl[i])); if (data->excl != NULL) free(data->excl); free(data); free(selfp); return(0); } if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) return(0); if (kind == CCN_UPCALL_CONTENT_BAD) return(0); if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) { if ((data->flags & MUST_VERIFY) != 0) return(CCN_UPCALL_RESULT_VERIFY); } if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED) abort(); ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; comps = info->content_comps; matched_comps = info->pi->prefix_comps; c = ccn_charbuf_create(); uri = ccn_charbuf_create(); if (matched_comps + 1 > comps->n) { ccn_uri_append(c, ccnb, ccnb_size, 1); fprintf(stderr, "How did this happen? %s\n", ccn_charbuf_as_string(uri)); exit(1); } data->counter[0]++; /* Tell main that something new came in */ /* Recover the same prefix as before */ ccn_name_init(c); ccn_name_append_components(c, ccnb, comps->buf[0], comps->buf[matched_comps]); comp = ccn_charbuf_create(); ccn_name_init(comp); if (matched_comps + 1 == comps->n) { /* Reconstruct the implicit content digest component */ ccn_digest_ContentObject(ccnb, info->pco); ccn_name_append(comp, info->pco->digest, info->pco->digest_bytes); } else { ccn_name_append_components(comp, ccnb, comps->buf[matched_comps], comps->buf[matched_comps + 1]); } data->excl = realloc(data->excl, (data->n_excl + 1) * sizeof(data->excl[0])); data->excl[data->n_excl++] = comp; comp = NULL; qsort(data->excl, data->n_excl, sizeof(data->excl[0]), &namecompare); res = express_my_interest(info->h, selfp, c); if (res == -1) { struct ccn_closure *high = split_my_excludes(selfp); if (high == NULL) abort(); express_my_interest(info->h, selfp, c); express_my_interest(info->h, high, c); } /* Explore the next level, if there is one. */ if (matched_comps + 2 < comps->n) { struct ccn_traversal *newdat = NULL; struct ccn_closure *cl; newdat = calloc(1, sizeof(*newdat)); newdat->magic = 68955871; newdat->warn = 1492; newdat->counter = data->counter; newdat->flags = data->flags & ~(EXCLUDE_LOW | EXCLUDE_HIGH); newdat->n_excl = 0; newdat->excl = NULL; cl = calloc(1, sizeof(*cl)); cl->p = &incoming_content; cl->data = newdat; ccn_name_init(c); ccn_name_append_components(c, ccnb, comps->buf[0], comps->buf[matched_comps + 1]); express_my_interest(info->h, cl, c); } else { res = ccn_uri_append(uri, info->content_ccnb, info->pco->offset[CCN_PCO_E], 1); if (res < 0) fprintf(stderr, "*** Error: ccn_traverse line %d res=%d\n", __LINE__, res); else printf("%s\n", ccn_charbuf_as_string(uri)); } ccn_charbuf_destroy(&c); ccn_charbuf_destroy(&uri); return(0); }
static int dissect_ccn_contentobject(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *signature_tree; proto_tree *name_tree; proto_tree *signedinfo_tree; proto_tree *content_tree; proto_item *titem; struct ccn_parsed_ContentObject co; struct ccn_parsed_ContentObject *pco = &co; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; size_t blob_size; const unsigned char *blob; int l; unsigned int i; double dt; nstime_t timestamp; int res; comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnb, ccnb_size, pco, comps); if (res < 0) return (-1); /* Signature */ l = pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]; titem = proto_tree_add_item(tree, hf_ccn_signature, tvb, pco->offset[CCN_PCO_B_Signature], l, FALSE); signature_tree = proto_item_add_subtree(titem, ett_signature); /* DigestAlgorithm */ l = pco->offset[CCN_PCO_E_DigestAlgorithm] - pco->offset[CCN_PCO_B_DigestAlgorithm]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, ccnb, pco->offset[CCN_PCO_B_DigestAlgorithm], pco->offset[CCN_PCO_E_DigestAlgorithm], &blob, &blob_size); titem = proto_tree_add_item(signature_tree, hf_ccn_signaturedigestalg, tvb, blob - ccnb, blob_size, FALSE); } /* Witness */ l = pco->offset[CCN_PCO_E_Witness] - pco->offset[CCN_PCO_B_Witness]; if (l > 0) { /* add the witness item to the signature tree */ } /* Signature bits */ l = pco->offset[CCN_PCO_E_SignatureBits] - pco->offset[CCN_PCO_B_SignatureBits]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, ccnb, pco->offset[CCN_PCO_B_SignatureBits], pco->offset[CCN_PCO_E_SignatureBits], &blob, &blob_size); titem = proto_tree_add_bytes(signature_tree, hf_ccn_signaturebits, tvb, blob - ccnb, blob_size, blob); } /* /Signature */ /* Name */ l = pco->offset[CCN_PCO_E_Name] - pco->offset[CCN_PCO_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pco->offset[CCN_PCO_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); /* Name Components */ for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* /Name */ /* SignedInfo */ l = pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]; titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_SignedInfo], l, "SignedInfo"); signedinfo_tree = proto_item_add_subtree(titem, ett_signedinfo); /* PublisherPublicKeyDigest */ l = pco->offset[CCN_PCO_E_PublisherPublicKeyDigest] - pco->offset[CCN_PCO_B_PublisherPublicKeyDigest]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, ccnb, pco->offset[CCN_PCO_B_PublisherPublicKeyDigest], pco->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); titem = proto_tree_add_bytes(signedinfo_tree, hf_ccn_publisherpublickeydigest, tvb, blob - ccnb, blob_size, blob); } /* Timestamp */ l = pco->offset[CCN_PCO_E_Timestamp] - pco->offset[CCN_PCO_B_Timestamp]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, ccnb, pco->offset[CCN_PCO_B_Timestamp], pco->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); dt = 0.0; for (i = 0; i < blob_size; i++) dt = dt * 256.0 + (double)blob[i]; dt /= 4096.0; timestamp.secs = dt; /* truncates */ timestamp.nsecs = (dt - (double) timestamp.secs) * 1000000000.0; titem = proto_tree_add_time(signedinfo_tree, hf_ccn_timestamp, tvb, blob - ccnb, blob_size, ×tamp); } /* Type */ l = pco->offset[CCN_PCO_E_Type] - pco->offset[CCN_PCO_B_Type]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Type, ccnb, pco->offset[CCN_PCO_B_Type], pco->offset[CCN_PCO_E_Type], &blob, &blob_size); titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, tvb, blob - ccnb, blob_size, pco->type); } else { titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, NULL, 0, 0, pco->type); } /* FreshnessSeconds */ l = pco->offset[CCN_PCO_E_FreshnessSeconds] - pco->offset[CCN_PCO_B_FreshnessSeconds]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds], &blob, &blob_size); i = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds]); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_freshnessseconds, tvb, blob - ccnb, blob_size, i); } /* FinalBlockID */ l = pco->offset[CCN_PCO_E_FinalBlockID] - pco->offset[CCN_PCO_B_FinalBlockID]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, pco->offset[CCN_PCO_B_FinalBlockID], pco->offset[CCN_PCO_E_FinalBlockID], &blob, &blob_size); titem = proto_tree_add_item(signedinfo_tree, hf_ccn_finalblockid, tvb, blob - ccnb, blob_size, FALSE); } /* TODO: KeyLocator */ /* /SignedInfo */ /* Content */ l = pco->offset[CCN_PCO_E_Content] - pco->offset[CCN_PCO_B_Content]; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnb, pco->offset[CCN_PCO_B_Content], pco->offset[CCN_PCO_E_Content], &blob, &blob_size); titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_Content], l, "Content: %d bytes", blob_size); if (blob_size > 0) { content_tree = proto_item_add_subtree(titem, ett_content); titem = proto_tree_add_item(content_tree, hf_ccn_contentdata, tvb, blob - ccnb, blob_size, FALSE); } return (ccnb_size); }
static int dissect_ccn_interest(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *name_tree; proto_tree *exclude_tree; proto_item *titem; struct ccn_parsed_interest interest; struct ccn_parsed_interest *pi = &interest; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; const unsigned char *blob; size_t blob_size; ssize_t l; unsigned int i; int res; comps = ccn_indexbuf_create(); res = ccn_parse_interest(ccnb, ccnb_size, pi, comps); /* Name */ l = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pi->offset[CCN_PI_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* MinSuffixComponents */ l = pi->offset[CCN_PI_E_MinSuffixComponents] - pi->offset[CCN_PI_B_MinSuffixComponents]; if (l > 0) { i = pi->min_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_minsuffixcomponents, tvb, pi->offset[CCN_PI_B_MinSuffixComponents], l, i); } /* MaxSuffixComponents */ l = pi->offset[CCN_PI_E_MaxSuffixComponents] - pi->offset[CCN_PI_B_MaxSuffixComponents]; if (l > 0) { i = pi->max_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_maxsuffixcomponents, tvb, pi->offset[CCN_PI_B_MaxSuffixComponents], l, i); } /* PublisherIDKeyDigest? */ /* Exclude */ l = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]; if (l > 0) { titem = proto_tree_add_text(tree, tvb, pi->offset[CCN_PI_B_Exclude], l, "Exclude"); exclude_tree = proto_item_add_subtree(titem, ett_exclude); } /* ChildSelector */ l = pi->offset[CCN_PI_E_ChildSelector] - pi->offset[CCN_PI_B_ChildSelector]; if (l > 0) { i = pi->orderpref; titem = proto_tree_add_uint(tree, hf_ccn_childselector, tvb, pi->offset[CCN_PI_B_ChildSelector], l, i); proto_item_append_text(titem, ", %s", val_to_str(i & 1, VALS(childselectordirection_vals), "")); } /* AnswerOriginKind */ l = pi->offset[CCN_PI_E_AnswerOriginKind] - pi->offset[CCN_PI_B_AnswerOriginKind]; if (l > 0) { i = pi->answerfrom; titem = proto_tree_add_uint(tree, hf_ccn_answeroriginkind, tvb, pi->offset[CCN_PI_B_AnswerOriginKind], l, i); } /* Scope */ l = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope]; if (l > 0) { i = pi->scope; titem = proto_tree_add_uint(tree, hf_ccn_scope, tvb, pi->offset[CCN_PI_B_Scope], l, i); } /* Nonce */ /* Nonce */ l = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce]; if (l > 0) { i = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, ccnb, pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob, &blob_size); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_str(pinfo->cinfo, COL_INFO, ", <"); for (i = 0; i < blob_size; i++) col_append_fstr(pinfo->cinfo, COL_INFO, "%02x", blob[i]); col_append_str(pinfo->cinfo, COL_INFO, ">"); } titem = proto_tree_add_item(tree, hf_ccn_nonce, tvb, blob - ccnb, blob_size, FALSE); } return (1); }
/* * Dissector that returns: * * The amount of data in the protocol's PDU, if it was able to * dissect all the data; * * 0, if the tvbuff doesn't contain a PDU for that protocol; * * The negative of the amount of additional data needed, if * we need more data (e.g., from subsequent TCP segments) to * dissect the entire PDU. */ static int dissect_ccn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint tvb_size = 0; proto_tree *ccn_tree; proto_item *ti = NULL; const unsigned char *ccnb; struct ccn_skeleton_decoder skel_decoder; struct ccn_skeleton_decoder *sd; struct ccn_charbuf *c; int packet_type = 0; int packet_type_length = 0; /* a couple of basic checks to rule out packets that are definitely not ours */ tvb_size = tvb_length(tvb); if (tvb_size < CCN_MIN_PACKET_SIZE || tvb_get_guint8(tvb, 0) == 0) return (0); sd = &skel_decoder; memset(sd, 0, sizeof(*sd)); sd->state |= CCN_DSTATE_PAUSE; ccnb = ep_tvb_memdup(tvb, 0, tvb_size); ccn_skeleton_decode(sd, ccnb, tvb_size); if (sd->state < 0) return (0); if (CCN_GET_TT_FROM_DSTATE(sd->state) == CCN_DTAG) { packet_type = sd->numval; packet_type_length = sd->index; } else { return (0); } memset(sd, 0, sizeof(*sd)); ccn_skeleton_decode(sd, ccnb, tvb_size); if (!CCN_FINAL_DSTATE(sd->state)) { pinfo->desegment_offset = 0; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return (-1); /* what should this be? */ } /* Make it visible that we're taking this packet */ if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "CCN"); } /* Clear out stuff in the info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); } c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, tvb_size, 1); /* Add the packet type and CCN URI to the info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, VALS(ccn_dtag_dict.dict), "Unknown (0x%02x")); col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, ccn_charbuf_as_string(c)); } if (tree == NULL) { ccn_charbuf_destroy(&c); return (sd->index); } ti = proto_tree_add_protocol_format(tree, proto_ccn, tvb, 0, -1, "Content-centric Networking Protocol, %s, %s", val_to_str(packet_type, VALS(ccn_dtag_dict.dict), "Unknown (0x%02x"), ccn_charbuf_as_string(c)); ccn_tree = proto_item_add_subtree(ti, ett_ccn); ccn_charbuf_destroy(&c); ti = proto_tree_add_uint(ccn_tree, hf_ccn_type, tvb, 0, packet_type_length, packet_type); switch (packet_type) { case CCN_DTAG_ContentObject: if (0 > dissect_ccn_contentobject(ccnb, sd->index, tvb, pinfo, ccn_tree)) return (0); break; case CCN_DTAG_Interest: if (0 > dissect_ccn_interest(ccnb, sd->index, tvb, pinfo, ccn_tree)) return (0); break; } return (sd->index); }
/** * Call-back from the CCN network that something has arrived * * We get notified that a client has interests in things we are producing. * This function will do some basic checking to see what exactly the client has * an interest in, and will produce what is appropriate. * Currently the things we produce are: * \li last block - we resend the last block we have published for a given name * \li last segment - we produce a data message that only contains the latest segment number we used * * \param selfp -> a context structure we created when registering this call-back * \param kind specifies the type of call-back being processed, see the \b switch statement * \param info context information about the call-back itself; interests, data, etc. * \return a response as to how successful we were in processing the call-back * \retval CCN_UPCALL_RESULT_OK things went well * \retval CCN_UPCALL_RESULT_VERIFY need to verify the contents of what we received * \retval CCN_UPCALL_RESULT_REEXPRESS an interest timedout waiting for data, so we try again * \retval CCN_UPCALL_RESULT_ERR some error was encountered */ static enum ccn_upcall_res new_interests (struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { Gstccnxsink *me = GST_CCNXSINK (selfp->data); struct ccn_charbuf *cb; struct ccn_charbuf *sname = NULL; const unsigned char *cp1, *cp2; size_t sz1; size_t sz2; long lastSeq; struct ccn_signing_params myparams; unsigned int i; int rc; GST_DEBUG ("something has arrived!"); GST_DEBUG ("matched is: %d", info->matched_comps); // number of filter components that were matched by the interest cb = interestAsUri (info); GST_DEBUG ("as URI: %s", ccn_charbuf_as_string (cb)); ccn_charbuf_destroy (&cb); myparams = me->sp; /* Some debugging stuff */ for (i = 0; i < 10; ++i) { const unsigned char *cp; size_t sz; GST_DEBUG ("%3d: ", i); if (0 > ccn_name_comp_get (info->interest_ccnb, info->interest_comps, i, &cp, &sz)) { // fprintf(stderr, "could not get comp\n"); break; } else { // hDump( DUMP_ADDR( cp ), DUMP_SIZE( sz ) ); } } switch (kind) { case CCN_UPCALL_FINAL: GST_LOG_OBJECT (me, "CCN upcall final %p", selfp); return (0); case CCN_UPCALL_INTEREST_TIMED_OUT: if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN Interest timed out on dead closure %p", selfp); return (0); } GST_LOG_OBJECT (me, "CCN upcall reexpress -- timed out"); if (me->timeouts > 5) { GST_LOG_OBJECT (me, "CCN upcall reexpress -- too many reexpressions"); return (0); } me->timeouts++; return (CCN_UPCALL_RESULT_REEXPRESS); case CCN_UPCALL_CONTENT_UNVERIFIED: if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN unverified content on dead closure %p", selfp); return (0); } return (CCN_UPCALL_RESULT_VERIFY); case CCN_UPCALL_CONTENT: if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN content on dead closure %p", selfp); return (0); } break; case CCN_UPCALL_CONTENT_BAD: GST_LOG_OBJECT (me, "Content signature verification failed! Discarding.\n"); return (CCN_UPCALL_RESULT_ERR); case CCN_UPCALL_CONSUMED_INTEREST: GST_LOG_OBJECT (me, "Upcall consumed interest\n"); return (CCN_UPCALL_RESULT_ERR); /* no data */ /* Here is the most interesting case...when an interest arrives */ case CCN_UPCALL_INTEREST: GST_INFO ("We got an interest\n"); myparams.freshness = 1; /* meta data is old very quickly */ /* See if any meta information is sought */ for (i = 0;; ++i) { if (0 > ccn_name_comp_get (info->interest_ccnb, info->interest_comps, i, &cp1, &sz1)) { cp1 = NULL; break; } else { if (!strncmp ((const char *) cp1, "_meta_", 6)) { // OK, found meta, now which one is needed? if (0 > ccn_name_comp_get (info->interest_ccnb, info->interest_comps, i + 1, &cp2, &sz2)) { GST_LOG_OBJECT (me, "CCN interest received with invalid meta request"); cp1 = NULL; } break; } // Component not meta, keep looking } } // At this point, i is left pointing at '_meta_' or at the end of component list if (cp1) { // hDump( DUMP_ADDR(cp1), DUMP_SIZE(sz1) ); // hDump( DUMP_ADDR(cp2), DUMP_SIZE(sz2) ); if (strncmp ((const char *) cp2, ".segment", 8)) goto Exit_Interest; /* not a match */ /* publish what segment we are up to in reply to the meta request */ lastSeq = me->segment - 1; GST_INFO ("sending meta data....segment: %d", lastSeq); sname = ccn_charbuf_create (); ccn_name_init (sname); rc = ccn_name_append_components (sname, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[i + 2]); if (rc < 0) goto Error_Interest; // rc = ccn_create_version(me->ccn, sname, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0); // if (rc < 0) goto Error_Interest; me->temp->length = 0; rc = ccn_sign_content (me->ccn, me->temp, sname, &myparams, &lastSeq, sizeof (lastSeq)); // hDump(DUMP_ADDR(sname->buf), DUMP_SIZE(sname->length)); if (rc != 0) { GST_LOG_OBJECT (me, "Failed to encode ContentObject (rc == %d)\n", rc); goto Error_Interest; } GST_INFO ("sending meta data..."); // hDump(DUMP_ADDR(me->temp->buf), DUMP_SIZE(me->temp->length)); rc = ccn_put (me->ccn, me->temp->buf, me->temp->length); me->temp->length = 0; if (rc < 0) { GST_LOG_OBJECT (me, "ccn_put failed (res == %d)\n", rc); goto Error_Interest; } GST_INFO ("meta data sent"); } else goto Exit_Interest; /* do not have _meta_ */ Exit_Interest: ccn_charbuf_destroy (&sname); break; Error_Interest: ccn_charbuf_destroy (&sname); return CCN_UPCALL_RESULT_ERR; default: GST_LOG_OBJECT (me, "CCN upcall result error"); return (CCN_UPCALL_RESULT_ERR); } me->timeouts = 0; return (CCN_UPCALL_RESULT_OK); }