void content_received(struct ccn_upcall_info *info, struct ccn_closure *selfp) { UserDataBuf *userBuf = (UserDataBuf *)selfp->data; struct data_buffer *buffer = &userBuf->data_buf; const unsigned char *content_value; NDNState *state = buffer->state; const unsigned char *ccnb = info->content_ccnb; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; struct ccn_indexbuf *comps = info->content_comps; /* Append it to the queue */ struct buf_list *b; b = (struct buf_list *)calloc(1, sizeof(*b)); b->link = NULL; ccn_content_get_value(ccnb, ccnb_size, info->pco, &content_value, &b->len); b->buf = malloc(b->len); memcpy(b->buf, content_value, b->len); if (buffer->buflist == NULL) buffer->buflist = b; else { struct buf_list *p = buffer->buflist; while (p->link != NULL) p = p->link; p->link = b; } /*emit the signal for get the data out of the buffer*/ state->emitSignal(userBuf->user_name); }
extern int SyncCacheEntryFetch(struct SyncHashCacheEntry *ce) { // causes the cache entry to fetched from the repo char *here = "Sync.SyncCacheEntryFetch"; int res = 0; if (ce == NULL) { // not an entry res = -1; } else if (ce->ncL != NULL) { // it's already here res = 0; } else if ((ce->state & SyncHashState_stored) == 0) { // it's never been stored, fail quietly res = -1; } else { // at this point we try to fetch it from the local repo // a failure should complain struct SyncRootStruct *root = ce->head->root; struct SyncBaseStruct *base = root->base; struct ccn_charbuf *name = SyncNameForLocalNode(root, ce->hash); struct ccn_charbuf *content = ccn_charbuf_create(); char *why = "no fetch"; struct ccn_parsed_ContentObject pcos; res = SyncLocalRepoFetch(base, name, content, &pcos); if (res >= 0) { // parse the object const unsigned char *xp = NULL; size_t xs = 0; // get the encoded node res = ccn_content_get_value(content->buf, content->length, &pcos, &xp, &xs); if (res < 0) why = "ccn_content_get_value failed"; else { struct ccn_buf_decoder ds; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, xp, xs); struct SyncNodeComposite *nc = SyncAllocComposite(root->base); res |= SyncParseComposite(nc, d); if (res < 0) { // failed, so back out of the allocations why = "bad parse"; SyncFreeComposite(nc); nc = NULL; } else { res = 1; SyncNodeIncRC(nc); ce->ncL = nc; ce->state |= SyncHashState_stored; } } } if (res < 0) if (root->base->debug >= CCNL_ERROR) SyncNoteUri(root, here, why, name); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&content); } return res; }
// extractNode parses and creates a sync tree node from an upcall info // returns NULL if there was any kind of error static struct SyncNodeComposite * extractNode(struct SyncRootStruct *root, struct ccn_upcall_info *info) { // first, find the content char *here = "sync_track.extractNode"; const unsigned char *cp = NULL; size_t cs = 0; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; const unsigned char *ccnb = info->content_ccnb; int res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &cp, &cs); if (res < 0 || cs < DEFAULT_HASH_BYTES) { SyncNoteFailed(root, here, "ccn_content_get_value", __LINE__); return NULL; } // second, parse the object struct SyncNodeComposite *nc = SyncAllocComposite(root->base); struct ccn_buf_decoder ds; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, cp, cs); res |= SyncParseComposite(nc, d); if (res < 0) { // failed, so back out of the allocations SyncNoteFailed(root, here, "bad parse", -res); SyncFreeComposite(nc); nc = NULL; } return nc; }
/** * * Create new face by sending out a request Interest * The actual new face instance is returned * */ static struct ccn_face_instance *create_face(struct ccn *h, struct ccn_charbuf *local_scope_template, struct ccn_charbuf *no_name, struct ccn_face_instance *face_instance) { struct ccn_charbuf *newface = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance *new_face_instance = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res = 0; /* Encode the given face instance */ newface = ccn_charbuf_create(); ccnb_append_face_instance(newface, face_instance); temp = ccn_charbuf_create(); res = ccn_sign_content(h, temp, no_name, NULL, newface->buf, newface->length); resultbuf = ccn_charbuf_create(); /* Construct the Interest name that will create the face */ name = ccn_charbuf_create(); ccn_name_init(name); ccn_name_append_str(name, "ccnx"); ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size); ccn_name_append_str(name, face_instance->action); ccn_name_append(name, temp->buf, temp->length); /* send Interest to retrieve Data that contains the newly created face */ res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); /* decode Data to get the actual face instance */ res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); ON_ERROR_CLEANUP(res); new_face_instance = ccn_face_instance_parse(ptr, length); ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return new_face_instance; cleanup: ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return NULL; }
/* * newServerHandler * * Expecting a string containing the URI for the client */ static enum ccn_upcall_res newServerHandler(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { dropbear_log(LOG_WARNING,"Enter newServerHandler"); dropbear_log(LOG_WARNING,"Got interest matching %d components, kind = %d\n", info->matched_comps, kind); int result; const unsigned char *ccnb = NULL; size_t ccnb_size; void *data = NULL; size_t data_size = 0; switch (kind) { case CCN_UPCALL_CONTENT: break; case CCN_UPCALL_INTEREST_TIMED_OUT: return CCN_UPCALL_RESULT_REEXPRESS; case CCN_UPCALL_CONTENT_UNVERIFIED: // TODO: fix verification break; default: return CCN_UPCALL_RESULT_ERR; } dropbear_log(LOG_WARNING,"Interest to"); print_ccnb_name(info); ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; result = ccn_content_get_value(ccnb, ccnb_size, info->pco, (const unsigned char **)&data, &data_size); if( result < 0 ) dropbear_exit("Could not parse reply message"); dropbear_log(LOG_WARNING,"newServerHandler: parsing contents"); if( strncmp((char *)data,"ccnx:/",6) == 0 ) { cli_opts.remote_name_str = (char *)data; dropbear_log(LOG_WARNING,"newServerHandler: matches: %s (%d)",data,data_size); ses.remote_name = ccn_charbuf_create(); result = ccn_name_from_uri(ses.remote_name,cli_opts.remote_name_str); if( result < 0 ) dropbear_exit("Did not find expected uri in server response"); // Start a new session dropbear_log(LOG_WARNING,"Connected to server at"); print_ccnb_charbuf(ses.remote_name); cli_session(cli_opts.ccnxdomain,cli_opts.remote_name_str); return CCN_UPCALL_RESULT_OK; } else { dropbear_log(LOG_WARNING,"newServerHandler: doesn't match"); return CCN_UPCALL_RESULT_ERR; } }
BytesPtr ParsedContentObject::contentPtr() const { const unsigned char *content; size_t len; int res = ccn_content_get_value(head(m_bytes), m_pco.offset[CCN_PCO_E], &m_pco, &content, &len); if (res < 0) { boost::throw_exception(MisformedContentObjectException()); } return readRawPtr (content, len); }
int decode_message(struct ccn_charbuf *message, struct path * name_path, char *data, size_t len, const void *verkey) { struct ccn_parsed_ContentObject content; struct ccn_indexbuf *comps = ccn_indexbuf_create(); const unsigned char * content_value; size_t content_length; int res = 0; int i; memset(&content, 0x33, sizeof(content)); if (ccn_parse_ContentObject(message->buf, message->length, &content, comps) != 0) { printf("Decode failed to parse object\n"); res = -1; } if (comps->n-1 != name_path->count) { printf("Decode got wrong number of path components: %d vs. %d\n", (int)(comps->n-1), name_path->count); res = -1; } for (i=0; i<name_path->count; i++) { if (ccn_name_comp_strcmp(message->buf, comps, i, name_path->comps[i]) != 0) { printf("Decode mismatch on path component %d\n", i); res = -1; } } if (ccn_content_get_value(message->buf, message->length, &content, &content_value, &content_length) != 0) { printf("Cannot retrieve content value\n"); res = -1; } else if (content_length != len) { printf("Decode mismatch on content length %d vs. %d\n", (int)content_length, (int)len); res = -1; } else if (memcmp(content_value, data, len) != 0) { printf("Decode mismatch of content\n"); res = -1; } if (ccn_verify_signature(message->buf, message->length, &content, verkey) != 1) { printf("Signature did not verify\n"); res = -1; } ccn_indexbuf_destroy(&comps); return res; }
void GroupManager::incomingContent(ccn_upcall_info *info) { size_t len = 0; unsigned char *valuep = NULL; ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, (const unsigned char **)&valuep, &len); if (-1 == parseXmlUserList(valuep, len)) { debug("Invalid user list format received"); } if (valuep != NULL) { valuep = NULL; } // already have the lock enumerate(); }
static enum ccn_upcall_res incoming_handler( struct ccn_closure* selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info* info) { unsigned int i; int res; const unsigned char *ptr; size_t length; printf("Received response (kind: %d)\n", kind); switch(kind) { case CCN_UPCALL_FINAL: printf("deregistering handler\n"); return CCN_UPCALL_RESULT_OK; case CCN_UPCALL_CONTENT: printf("received content\n"); res = ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, &ptr, &length); printf("Output: "); for (i = 0; i < length; i++) { putchar(ptr[i]); } break; case CCN_UPCALL_INTEREST_TIMED_OUT: printf("request timed out - retrying\n"); return CCN_UPCALL_RESULT_REEXPRESS; case CCN_UPCALL_CONTENT_UNVERIFIED: case CCN_UPCALL_CONTENT_BAD: printf("error\n"); return CCN_UPCALL_RESULT_ERR; default: printf("Unexpected response\n"); return CCN_UPCALL_RESULT_ERR; } return CCN_UPCALL_RESULT_OK; }
/** * Request the current segment number from the ccnx data producer * * This is a request for meta data for the media stream the user has named with their URI. * We assume that they want to join the media broadcast from what is currently being published * and \em not want to start from the beginning...although there is good reason for that too. * * Getting this data is done by expressing interests in the meta data. The producer of the * media stream will catch this through one of its ccnx filters and produce this meta data * back through the network to us. * * \param h ccnx context handle * \param name the content name for which we desire the meta data * \param timeout how long to wait around * \return the segment number to ask for first, 0 on timeout */ static uintmax_t * get_segment (struct ccn *h, struct ccn_charbuf *name, int timeout) { struct ccn_charbuf *hn; uintmax_t *result = NULL; int res = 0; GST_INFO ("get_segment step 1"); hn = ccn_charbuf_create (); // ccn_name_append_components(hn, name->buf, 0, name->length ); ccn_charbuf_append_charbuf (hn, name); ccn_name_from_uri (hn, "_meta_/.segment"); // ccn_name_append_str(hn, "_meta_"); // ccn_name_append_str(hn, ".segment"); GST_INFO ("get_segment step 2"); // res = ccn_resolve_version(h, hn, CCN_V_HIGHEST, timeout); GST_INFO ("get_segment step 3, res: %d", res); if (res == 0) { struct ccn_charbuf *ho = ccn_charbuf_create (); struct ccn_parsed_ContentObject pcobuf = { 0 }; const unsigned char *hc; size_t hcs; // hDump(DUMP_ADDR(hn->buf), DUMP_SIZE(hn->length)); GST_INFO ("get_segment step 10"); res = ccn_get (h, hn, NULL, timeout, ho, &pcobuf, NULL, 0); GST_INFO ("get_segment step 11, res: %d", res); if (res >= 0) { hc = ho->buf; hcs = ho->length; // hDump( DUMP_ADDR(hc), DUMP_SIZE(hcs)); ccn_content_get_value (hc, hcs, &pcobuf, &hc, &hcs); // hDump( DUMP_ADDR(hc), DUMP_SIZE(hcs)); result = calloc (1, sizeof (uintmax_t)); memcpy (result, hc, sizeof (uintmax_t)); } ccn_charbuf_destroy (&ho); } GST_INFO ("get_segment step 9"); ccn_charbuf_destroy (&hn); return (result); }
/** * Read a slice (from a repository) given the name. * @param h is the ccn_handle on which to read. * @param name is the charbuf containing the name of the sync slice to be read. * @param slice is a pointer to a ccns_slice object which will be filled in * on successful return. * @returns 0 on success, -1 otherwise. */ int ccns_read_slice(struct ccn *h, struct ccn_charbuf *name, struct ccns_slice *slice) { struct ccn_parsed_ContentObject pco_space = { 0 }; struct ccn_parsed_ContentObject *pco = &pco_space; struct ccn_charbuf *nc = ccn_charbuf_create_n(name->length); struct ccn_charbuf *cob = ccn_charbuf_create(); const unsigned char *content; size_t content_length; int res = -1; if (nc == NULL || cob == NULL) goto Cleanup; ccn_charbuf_append_charbuf(nc, name); res = ccn_resolve_version(h, nc, CCN_V_HIGHEST, 100); // XXX: timeout if (res < 0) goto Cleanup; if (res == 0) { // TODO: check if the last component is a segment number, chop it off, try again. } res = ccn_get(h, nc, NULL, 100, cob, pco, NULL, 0); if (res < 0) goto Cleanup; if (pco->type != CCN_CONTENT_DATA) { res = -1; goto Cleanup; } res = ccn_content_get_value(cob->buf, cob->length, pco, &content, &content_length); if (res < 0) goto Cleanup; res = slice_parse(slice, content, content_length); Cleanup: ccn_charbuf_destroy(&nc); ccn_charbuf_destroy(&cob); return (res); }
static PyObject * Content_from_ccn_parsed(struct ccn_charbuf *content_object, struct ccn_parsed_ContentObject *parsed_content_object) { const char *value; size_t size; PyObject *py_content; int r; r = ccn_content_get_value(content_object->buf, content_object->length, parsed_content_object, (const unsigned char **) &value, &size); if (r < 0) { PyErr_Format(g_PyExc_CCNError, "ccn_content_get_value() returned" " %d", r); return NULL; } py_content = PyBytes_FromStringAndSize(value, size); if (!py_content) return NULL; return py_content; }
enum ccn_upcall_res CcnLAC_fetchFaceidCb(struct ccn_closure* selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info* info) { CcnLAC self = (CcnLAC)selfp->data; switch (kind) { case CCN_UPCALL_FINAL: { free(selfp); return CCN_UPCALL_RESULT_OK; } case CCN_UPCALL_INTEREST_TIMED_OUT: { return CCN_UPCALL_RESULT_REEXPRESS; } case CCN_UPCALL_CONTENT_UNVERIFIED: case CCN_UPCALL_CONTENT_KEYMISSING: case CCN_UPCALL_CONTENT_RAW: case CCN_UPCALL_CONTENT: { struct ccn_forwarding_entry* fe = NULL; const unsigned char* fe_ccnb = NULL; size_t fe_ccnb_size = 0; int res = ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, &fe_ccnb, &fe_ccnb_size); if (res == 0) fe = ccn_forwarding_entry_parse(fe_ccnb, fe_ccnb_size); if (fe != NULL) { self->faceid = fe->faceid; ccn_forwarding_entry_destroy(&fe); } else { self->error = true; } PollMgr_detach(self->pm, ccn_get_connection_fd(self->ccnh), &CcnLAC_initPollCb, self); void* emptyPDU = malloc(CCN_EMPTY_PDU_LENGTH); memcpy(emptyPDU, CCN_EMPTY_PDU, CCN_EMPTY_PDU_LENGTH); NBS_write(self->nbs, emptyPDU, 0, CCN_EMPTY_PDU_LENGTH, NULL); NBS_pollAttach(self->nbs, self->pm); return CCN_UPCALL_RESULT_OK; } default: { return CCN_UPCALL_RESULT_ERR; } } }
// creates a full structure without action, if proto == "face" only the // faceid (from cmd_host parameter) and lifetime will be filled in. struct ccn_face_instance * parse_ccn_face_instance(struct ccndc_data *self, const char *cmd_proto, const char *cmd_host, const char *cmd_port, const char *cmd_mcastttl, const char *cmd_mcastif, int freshness) { struct ccn_face_instance *entry; struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG)}; struct addrinfo mcasthints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG | AI_NUMERICHOST)}; struct addrinfo *raddrinfo = NULL; struct addrinfo *mcastifaddrinfo = NULL; char rhostnamebuf [NI_MAXHOST]; char rhostportbuf [NI_MAXSERV]; int off_address = -1, off_port = -1, off_source_address = -1; int res; int socktype; entry = calloc(1, sizeof(*entry)); if (entry == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // allocate storage for Face data entry->store = ccn_charbuf_create(); if (entry->store == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; if (cmd_proto == NULL) { ccndc_warn(__LINE__, "command error, missing address type\n"); goto ExitOnError; } if (strcasecmp(cmd_proto, "udp") == 0) { entry->descr.ipproto = IPPROTO_UDP; socktype = SOCK_DGRAM; } else if (strcasecmp(cmd_proto, "tcp") == 0) { entry->descr.ipproto = IPPROTO_TCP; socktype = SOCK_STREAM; } else if (strcasecmp(cmd_proto, "face") == 0) { errno = 0; unsigned long faceid = strtoul(cmd_host, (char **)NULL, 10); if (errno == ERANGE || errno == EINVAL || faceid > UINT_MAX || faceid == 0) { ccndc_warn(__LINE__, "command error, face number invalid or out of range '%s'\n", cmd_host); goto ExitOnError; } entry->faceid = (unsigned) faceid; entry->lifetime = freshness; return (entry); } else { ccndc_warn(__LINE__, "command error, unrecognized address type '%s'\n", cmd_proto); goto ExitOnError; } if (cmd_host == NULL) { ccndc_warn(__LINE__, "command error, missing hostname\n"); goto ExitOnError; } if (cmd_port == NULL || cmd_port[0] == 0) cmd_port = CCN_DEFAULT_UNICAST_PORT; hints.ai_socktype = socktype; res = getaddrinfo(cmd_host, cmd_port, &hints, &raddrinfo); if (res != 0 || raddrinfo == NULL) { ccndc_warn(__LINE__, "command error, getaddrinfo for host [%s] port [%s]: %s\n", cmd_host, cmd_port, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), rhostportbuf, sizeof(rhostportbuf), NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(raddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } off_port = entry->store->length; res = ccn_charbuf_append(entry->store, rhostportbuf, strlen(rhostportbuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } entry->descr.mcast_ttl = -1; if (cmd_mcastttl != NULL) { char *endptr; entry->descr.mcast_ttl = strtol(cmd_mcastttl, &endptr, 10); if ((endptr != &cmd_mcastttl[strlen(cmd_mcastttl)]) || entry->descr.mcast_ttl < 0 || entry->descr.mcast_ttl > 255) { ccndc_warn(__LINE__, "command error, invalid multicast ttl: %s\n", cmd_mcastttl); goto ExitOnError; } } if (cmd_mcastif != NULL) { res = getaddrinfo(cmd_mcastif, NULL, &mcasthints, &mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, incorrect multicat interface [%s]: " "mcastifaddr getaddrinfo: %s\n", cmd_mcastif, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(mcastifaddrinfo->ai_addr, mcastifaddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_source_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } } entry->descr.address = (const char *)(entry->store->buf + off_address); entry->descr.port = (const char *)(entry->store->buf + off_port); if (off_source_address >= 0) { entry->descr.source_address = (const char *)(entry->store->buf + off_source_address); } entry->lifetime = freshness; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } struct ccn_face_instance * parse_ccn_face_instance_from_face(struct ccndc_data *self, const char *cmd_faceid) { struct ccn_face_instance *entry = calloc(1, sizeof(*entry)); // allocate storage for Face data entry->store = ccn_charbuf_create(); // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; /* destroy a face - the URI field will hold the face number */ if (cmd_faceid == NULL) { ccndc_warn(__LINE__, "command error, missing face number for destroyface\n"); goto ExitOnError; } char *endptr; int facenumber = strtol(cmd_faceid, &endptr, 10); if ((endptr != &cmd_faceid[strlen(cmd_faceid)]) || facenumber < 0) { ccndc_warn(__LINE__, "command error invalid face number for destroyface: %d\n", facenumber); goto ExitOnError; } entry->faceid = facenumber; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // "private section /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ccndc_get_ccnd_id(struct ccndc_data *self) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"; const unsigned char *ccndid_result; int res = 0; name = ccn_charbuf_create(); if (name == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for service locator name charbuf\n"); return -1; } resultbuf = ccn_charbuf_create(); if (resultbuf == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for result charbuf"); res = -1; goto Cleanup; } res = ccn_name_from_uri(name, ccndid_uri); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse service locator URI for ccnd key"); goto Cleanup; } res = ccn_get(self->ccn_handle, name, self->local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0); if (res < 0) { ccndc_warn(__LINE__, "Unable to get key from ccnd"); goto Cleanup; } res = ccn_ref_tagged_BLOB (CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid_result, &self->ccnd_id_size); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse ccnd response for ccnd id"); goto Cleanup; } if (self->ccnd_id_size > sizeof (self->ccnd_id)) { ccndc_warn(__LINE__, "Incorrect size for ccnd id in response"); goto Cleanup; } memcpy(self->ccnd_id, ccndid_result, self->ccnd_id_size); Cleanup: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&resultbuf); return (res); } struct ccn_face_instance * ccndc_do_face_action(struct ccndc_data *self, const char *action, struct ccn_face_instance *face_instance) { struct ccn_charbuf *newface = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance *new_face_instance = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res = 0; face_instance->action = action; /* Encode the given face instance */ newface = ccn_charbuf_create(); ON_NULL_CLEANUP(newface); ON_ERROR_CLEANUP(ccnb_append_face_instance(newface, face_instance)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, newface->buf, newface->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); /* Construct the Interest name that will create the face */ name = ccn_charbuf_create(); ON_NULL_CLEANUP(name); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, face_instance->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_face_instance = ccn_face_instance_parse(ptr, length); ON_NULL_CLEANUP(new_face_instance); ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return (new_face_instance); Cleanup: ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_face_instance_destroy(&new_face_instance); return (NULL); } int ccndc_do_prefix_action(struct ccndc_data *self, const char *action, struct ccn_forwarding_entry *forwarding_entry) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry *new_forwarding_entry = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res; forwarding_entry->action = action; prefixreg = ccn_charbuf_create(); ON_NULL_CLEANUP(prefixreg); ON_ERROR_CLEANUP(ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, prefixreg->buf, prefixreg->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); name = ccn_charbuf_create(); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, forwarding_entry->ccnd_id, forwarding_entry->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, forwarding_entry->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (res); /* This is where ON_ERROR_CLEANUP sends us in case of an error * and we must free any storage we allocated before returning. */ Cleanup: ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (-1); }
/** * * Bind a prefix to a face * */ static int register_unregister_prefix(struct ccn *h, struct ccn_charbuf *local_scope_template, struct ccn_charbuf *no_name, struct ccn_charbuf *name_prefix, struct ccn_face_instance *face_instance, int operation) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry forwarding_entry_storage = {0}; struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage; struct ccn_forwarding_entry *new_forwarding_entry; const unsigned char *ptr = NULL; size_t length = 0; int res; /* Register or unregister the prefix */ forwarding_entry->action = (operation == OP_REG) ? "prefixreg" : "unreg"; forwarding_entry->name_prefix = name_prefix; forwarding_entry->ccnd_id = face_instance->ccnd_id; forwarding_entry->ccnd_id_size = face_instance->ccnd_id_size; forwarding_entry->faceid = face_instance->faceid; forwarding_entry->flags = -1; forwarding_entry->lifetime = 2100; prefixreg = ccn_charbuf_create(); ccnb_append_forwarding_entry(prefixreg, forwarding_entry); temp = ccn_charbuf_create(); res = ccn_sign_content(h, temp, no_name, NULL, prefixreg->buf, prefixreg->length); resultbuf = ccn_charbuf_create(); /* construct Interest containing prefixreg request */ name = ccn_charbuf_create(); ccn_name_init(name); ccn_name_append_str(name, "ccnx"); ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size); ccn_name_append_str(name, (operation == OP_REG) ? "prefixreg" : "unreg"); ccn_name_append(name, temp->buf, temp->length); /* send Interest, get Data */ res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); ON_ERROR_CLEANUP(res); /* extract new forwarding entry from Data */ new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return res; cleanup: ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return -1; }
/** * Main working loop for stuff coming in from the CCNx network * * The only kind of content we work with are data messages. They are in response to the * interest messages we send out. The work involves 2 pieces: packing the data from ccn message * sizes into buffer sizes we use internally, and detecting when the stream of data is done. * * The first is fairly simple. Each internal buffer we 'fill' is placed onto the fifo queue * so the main thread can take it off and reply to the pipeline request for more data. * * Determining the end of stream at the moment is a bit of a hack and could use some work. * \todo volunteers? 8-) * * \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 incoming_content (struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { Gstccnxsrc *me = GST_CCNXSRC (selfp->data); const unsigned char *ccnb = NULL; size_t ccnb_size = 0; const unsigned char *ib = NULL; /* info->interest_ccnb */ struct ccn_indexbuf *ic = NULL; unsigned int i; uintmax_t segment; CcnxInterestState *istate = NULL; gint res; const unsigned char *cp; size_t sz; const unsigned char *data = NULL; size_t data_size = 0; gboolean b_last = FALSE; GST_INFO ("content has arrived!"); /* Do some basic sanity and type checks to see if we want to process this data */ if (CCN_UPCALL_FINAL == kind) { GST_LOG_OBJECT (me, "CCN upcall final %p", selfp); if (me->i_bufoffset > 0) { GST_BUFFER_SIZE (me->buf) = me->i_bufoffset; fifo_put (me, me->buf); me->buf = gst_buffer_new_and_alloc (CCN_FIFO_BLOCK_SIZE); me->i_bufoffset = 0; } /* * Should emit an eos here instead of the empty buffer */ GST_BUFFER_SIZE (me->buf) = 0; fifo_put (me, me->buf); me->i_bufoffset = 0; return (CCN_UPCALL_RESULT_OK); } if (!info) return CCN_UPCALL_RESULT_ERR; // Now why would this happen? // show_comps( info->content_ccnb, info->content_comps); if (CCN_UPCALL_INTEREST_TIMED_OUT == kind) { if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN Interest timed out on dead closure %p", selfp); return (CCN_UPCALL_RESULT_OK); } segment = ccn_ccnb_fetch_segment (info->interest_ccnb, info->interest_comps); GST_INFO ("...looks to be for segment: %d", segment); GST_LOG_OBJECT (me, "CCN upcall reexpress -- timed out"); istate = fetchSegmentInterest (me, segment); if (istate) { if (istate->timeouts > 5) { GST_LOG_OBJECT (me, "CCN upcall reexpress -- too many reexpressions"); if (segment == me->post_seg) // We have been waiting for this one...process as an empty block to trigger other activity process_or_queue (me, me->post_seg, NULL, 0, FALSE); else freeInterestState (me, istate); post_next_interest (me); // make sure to ask for new stuff if needed, or else we stall waiting for nothing return (CCN_UPCALL_RESULT_OK); } else { istate->timeouts++; return (CCN_UPCALL_RESULT_REEXPRESS); } } else { GST_LOG_OBJECT (me, "segment not found in cache: %d", segment); return (CCN_UPCALL_RESULT_OK); } } else if (CCN_UPCALL_CONTENT_UNVERIFIED == kind) { if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN unverified content on dead closure %p", selfp); return (CCN_UPCALL_RESULT_OK); } return (CCN_UPCALL_RESULT_VERIFY); } else if (CCN_UPCALL_CONTENT != kind) { GST_LOG_OBJECT (me, "CCN upcall result error"); return (CCN_UPCALL_RESULT_ERR); } segment = ccn_ccnb_fetch_segment (info->content_ccnb, info->content_comps); GST_INFO ("...looks to be for segment: %d", segment); if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN content on dead closure %p", selfp); return (CCN_UPCALL_RESULT_OK); } /* At this point it seems we have a data message we want to process */ ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; /* spit out some debug information */ for (i = 0; i < 5; ++i) { GST_DEBUG ("%3d: ", i); if (0 > ccn_name_comp_get (info->content_ccnb, info->content_comps, i, &cp, &sz)) { // fprintf(stderr, "could not get comp\n"); } else { // hDump( DUMP_ADDR( cp ), DUMP_SIZE( sz ) ); } } /* go get the data and process it...note that the data pointer here is only temporary, a copy is needed to keep the data */ ib = info->interest_ccnb; ic = info->interest_comps; res = ccn_content_get_value (ccnb, ccnb_size, info->pco, &data, &data_size); if (res < 0) { GST_LOG_OBJECT (me, "CCN error on get value of size"); process_or_queue (me, segment, NULL, 0, FALSE); // process null block to adjust interest array queue post_next_interest (me); // Keep the data flowing return (CCN_UPCALL_RESULT_ERR); } /* was this the last block? [code taken from a ccnx tool */ /* \todo the test below should get refactored into the library */ if (info->pco->offset[CCN_PCO_B_FinalBlockID] != info->pco->offset[CCN_PCO_E_FinalBlockID]) { const unsigned char *finalid = NULL; size_t finalid_size = 0; const unsigned char *nameid = NULL; size_t nameid_size = 0; struct ccn_indexbuf *cc = info->content_comps; ccn_ref_tagged_BLOB (CCN_DTAG_FinalBlockID, ccnb, info->pco->offset[CCN_PCO_B_FinalBlockID], info->pco->offset[CCN_PCO_E_FinalBlockID], &finalid, &finalid_size); if (cc->n < 2) abort (); // \todo we need to behave better than this ccn_ref_tagged_BLOB (CCN_DTAG_Component, ccnb, cc->buf[cc->n - 2], cc->buf[cc->n - 1], &nameid, &nameid_size); if (finalid_size == nameid_size && 0 == memcmp (finalid, nameid, nameid_size)) { b_last = TRUE; } } /* a short block can also indicate the end, if the client isn't using FinalBlockID */ if (data_size < CCN_CHUNK_SIZE) b_last = TRUE; /* something to process */ process_or_queue (me, segment, data, data_size, b_last); post_next_interest (me); if (!b_last) return post_next_interest (me); return (CCN_UPCALL_RESULT_OK); }
enum ccn_upcall_res incoming_content( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *templ = NULL; struct ccn_charbuf *temp = NULL; const unsigned char *ccnb = NULL; size_t ccnb_size = 0; const unsigned char *data = NULL; size_t data_size = 0; size_t written; const unsigned char *ib = NULL; /* info->interest_ccnb */ struct ccn_indexbuf *ic = NULL; int res; struct mydata *md = selfp->data; if (kind == CCN_UPCALL_FINAL) { if (md != NULL) { selfp->data = NULL; free(md); md = NULL; } return(CCN_UPCALL_RESULT_OK); } if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) return(CCN_UPCALL_RESULT_REEXPRESS); if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED) return(CCN_UPCALL_RESULT_ERR); if (md == NULL) selfp->data = md = calloc(1, sizeof(*md)); ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; ib = info->interest_ccnb; ic = info->interest_comps; /* XXX - must verify sig, and make sure it is LEAF content */ res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size); if (res < 0) abort(); if (data_size > CHUNK_SIZE) { /* For us this is spam. Give up now. */ fprintf(stderr, "*** Segment %d found with a data size of %d." " This program only works with segments of 1024 bytes." " Try ccncatchunks2 instead.\n", (int)selfp->intdata, (int)data_size); exit(1); } /* OK, we will accept this block. */ written = fwrite(data, data_size, 1, stdout); if (written != 1) exit(1); /* A short block signals EOF for us. */ if (data_size < CHUNK_SIZE) exit(0); /* Ask for the next one */ name = ccn_charbuf_create(); ccn_name_init(name); if (ic->n < 2) abort(); res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]); if (res < 0) abort(); temp = ccn_charbuf_create(); ccn_charbuf_putf(temp, "%d", ++(selfp->intdata)); ccn_name_append(name, temp->buf, temp->length); ccn_charbuf_destroy(&temp); templ = make_template(md, info); res = ccn_express_interest(info->h, name, selfp, templ); if (res < 0) abort(); ccn_charbuf_destroy(&templ); ccn_charbuf_destroy(&name); return(CCN_UPCALL_RESULT_OK); }
static enum ccn_upcall_res CallMe(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { // CallMe is the callback routine invoked by ccn_run when a registered // interest has something interesting happen. struct localClosure *req = (struct localClosure *)selfp->data; seg_t thisSeg = req->reqSeg; struct ccn_fetch_stream *fs = (struct ccn_fetch_stream *) req->fs; if (fs == NULL) { if (kind == CCN_UPCALL_FINAL) { // orphaned, so just get rid of it free(req); free(selfp); } return(CCN_UPCALL_RESULT_OK); } FILE *debug = fs->parent->debug; seg_t finalSeg = fs->finalSeg; ccn_fetch_flags flags = fs->parent->debugFlags; if (finalSeg < 0) { // worth a try to find the last segment finalSeg = GetFinalSegment(info); fs->finalSeg = finalSeg; } switch (kind) { case CCN_UPCALL_FINAL: // this is the cleanup for an expressed interest req = RemSegRequest(fs, req); if (fs->reqBusy > 0) fs->reqBusy--; free(selfp); return(CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST_TIMED_OUT: { if (finalSeg >= 0 && thisSeg > finalSeg) // ignore this timeout quickly return(CCN_UPCALL_RESULT_OK); intmax_t dt = DeltaTime(req->startClock, GetCurrentTimeUSecs()); if (dt >= fs->timeoutUSecs) { // timed out, too many retries // assume that this interest will never produce seg_t timeoutSeg = fs->timeoutSeg; fs->timeoutsSeen++; fs->segsAhead = 0; if (timeoutSeg < 0 || thisSeg < timeoutSeg) { // we can infer a new timeoutSeg fs->timeoutSeg = thisSeg; } if (debug != NULL && (flags & ccn_fetch_flags_NoteTimeout)) { fprintf(debug, "** ccn_fetch timeout, %s, seg %jd", fs->id, thisSeg); fprintf(debug, ", dt %jd us, timeoutUSecs %jd\n", dt, fs->timeoutUSecs); fflush(debug); } return(CCN_UPCALL_RESULT_OK); } // TBD: may need to reseed bloom filter? who to ask? return(CCN_UPCALL_RESULT_REEXPRESS); } case CCN_UPCALL_CONTENT_UNVERIFIED: return (CCN_UPCALL_RESULT_VERIFY); case CCN_UPCALL_CONTENT: if (fs->timeoutSeg >= 0 && fs->timeoutSeg <= thisSeg) // we will ignore this, since we are blocked return(CCN_UPCALL_RESULT_OK); break; default: // SHOULD NOT HAPPEN return(CCN_UPCALL_RESULT_ERR); } struct ccn_fetch_buffer *fb = FindBufferForSeg(fs, thisSeg); if (fb == NULL) { // we don't already have the data yet const unsigned char *data = NULL; size_t dataLen = 0; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; const unsigned char *ccnb = info->content_ccnb; int res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &dataLen); if (res < 0 || (thisSeg != finalSeg && dataLen == 0)) { // we got a bogus result, no data in this content! if (debug != NULL && (flags & ccn_fetch_flags_NoteAddRem)) { fprintf(debug, "-- ccn_fetch no data, %s, seg %jd, final %jd", fs->id, thisSeg, finalSeg); ShowDelta(debug, req->startClock); } if (fs->zeroLenSeg < 0 || thisSeg < fs->zeroLenSeg) // note this problem for future reporting fs->zeroLenSeg = thisSeg; } else if (thisSeg == finalSeg && dataLen == 0) { // EOF, but no buffer needed if (fs->fileSize < 0) fs->fileSize = InferPosition(fs, thisSeg); fs->finalSeg = finalSeg-1; if (debug != NULL && (flags & ccn_fetch_flags_NoteFinal)) { fprintf(debug, "-- ccn_fetch EOF, %s, seg %jd, len %d, fs %jd", fs->id, thisSeg, (int) dataLen, fs->fileSize); ShowDelta(debug, req->startClock); } } else { // alloc a buffer and transfer the data if (fs->segSize == 0) { // assuming fixed size segments, so any should do // EXCEPT for an incomplete final segment if (thisSeg == 0 || thisSeg < finalSeg) fs->segSize = dataLen; } if (thisSeg == finalSeg) fs->finalSegLen = dataLen; struct ccn_fetch_buffer *fb = NewBufferForSeg(fs, thisSeg, dataLen); memcpy(fb->buf, data, dataLen); if (debug != NULL && (flags & ccn_fetch_flags_NoteFill)) { fprintf(debug, "-- ccn_fetch FillSeg, %s, seg %jd, len %d, nbuf %d", fs->id, thisSeg, (int) dataLen, (int) fs->nBufs); ShowDelta(debug, req->startClock); } if (thisSeg == finalSeg) { // the file size is known in segments if (fs->segSize <= 0) { // variable or unknown segment size if (fb->pos >= 0) { fs->fileSize = fb->pos + dataLen; } } else { // fixed segment size, so file size is now known fs->fileSize = thisSeg * fs->segSize + dataLen; } if (debug != NULL && (flags & ccn_fetch_flags_NoteFinal)) { fprintf(debug, "-- ccn_fetch EOF, %s, seg %jd, len %d, fs %jd", fs->id, thisSeg, (int) dataLen, fs->fileSize); ShowDelta(debug, req->startClock); } } fs->segsRead++; } } ccn_set_run_timeout(fs->parent->h, 0); return(CCN_UPCALL_RESULT_OK); }
int main (int argc, char **argv) { int res; //check if user supplied uri to trace if(argv[1] == NULL) { printf("Usage: trace URI\n"); exit(1); } //get the length of user provided URI int argv_length = strlen(argv[1]); //check first six chars for ccnx:/, if present, skip them int skip = 0; res = strncmp("ccnx:/", argv[1], 6); if(res == 0) { skip = 5; } //if URI does not begins with /, exit if (argv[1][skip] != '/') { printf("URI must begin with /\n"); exit(1); } //check if uri ends with slash, append if missing char *slash = ""; if (argv[1][argv_length-1] != '/') { slash = "/"; } //allocate memory for trace URI = /trace/user_input/random_number char *URI = (char *) malloc(sizeof(char)* argv_length+1); //find size of rand if(URI == NULL) { fprintf(stderr, "Can not allocate memory for URI\n"); exit(1); } //put together the trace URI, add a random number to end of URI srand ((unsigned int)time (NULL)*getpid()); sprintf(URI, "%s%s", argv[1]+skip, slash); //allocate memory for interest struct ccn_charbuf *ccnb = ccn_charbuf_create(); if(ccnb == NULL) { fprintf(stderr, "Can not allocate memory for interest\n"); exit(1); } //adding name to interest res = ccn_name_from_uri(ccnb, URI); if(res == -1) { fprintf(stderr, "Failed to assign name to interest"); exit(1); } //create the ccn handle struct ccn *ccn = ccn_create(); if(ccn == NULL) { fprintf(stderr, "Can not create ccn handle\n"); exit(1); } //connect to ccnd res = ccn_connect(ccn, NULL); if (res == -1) { fprintf(stderr, "Could not connect to ccnd... exiting\n"); exit(1); } #ifdef DEBUG printf("Connected to CCND, return code: %d\n", res); #endif //allocate buffer for response struct ccn_charbuf *resultbuf = ccn_charbuf_create(); if(resultbuf == NULL) { fprintf(stderr, "Can not allocate memory for URI\n"); exit(1); } //setting the parameters for ccn_get struct ccn_parsed_ContentObject pcobuf = { 0 }; int timeout_ms = 6000; //express interest //res = ccn_get(ccn, ccnb, NULL, timeout_ms, resultbuf, &pcobuf, NULL, 0); //if cached answer is not allowed, set the template //make sure AnswerOriginKind is 0x0 if(!ALLOW_CACHE) { struct ccn_charbuf *templ = ccn_charbuf_create(); ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG); ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG); ccn_charbuf_append_closer(templ); /* </Name> */ ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG); ccnb_append_number(templ,0x0); ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */ ccn_charbuf_append_closer(templ); //send out the interest res = ccn_get(ccn, ccnb, templ, timeout_ms, resultbuf, &pcobuf, NULL, 0); } //cached answer is allowed, don't set template else { res = ccn_get(ccn, ccnb, NULL, timeout_ms, resultbuf, &pcobuf, NULL, 0); } if (res == -1) { fprintf(stderr, "Did not receive answer for trace to %s\n", argv[1]); #ifdef DEBUG fprintf(stderr, "Did not receive answer for trace to URI: %s\n", URI); #endif exit(1); } //extract data from the response const unsigned char *ptr; size_t length; ptr = resultbuf->buf; length = resultbuf->length; ccn_content_get_value(ptr, length, &pcobuf, &ptr, &length); //check if received some data if(length == 0) { fprintf(stderr, "Received empty answer for trace to %s\n", argv[1]); #ifdef DEBUG fprintf(stderr, "Received empty answer for trace to URI: %s\n", URI); #endif exit(1); } //print the data printf("Reply: %s\n", ptr); printf("Length of data: %Zu\n", length); exit(0); }
int main(int argc, char **argv) { struct ccn *h = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *null_name = NULL; struct ccn_charbuf *name_prefix = NULL; struct ccn_charbuf *newface = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *templ = NULL; const unsigned char *ptr = NULL; size_t length = 0; const char *arg = NULL; const char *progname = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance face_instance_storage = {0}; struct ccn_face_instance *face_instance = &face_instance_storage; struct ccn_forwarding_entry forwarding_entry_storage = {0}; struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct ccn_charbuf *keylocator_templ = NULL; struct ccn_keystore *keystore = NULL; long expire = -1; int ipproto; unsigned char ccndid_storage[32] = {0}; const unsigned char *ccndid = NULL; size_t ccndid_size = 0; int res; int opt; progname = argv[0]; while ((opt = getopt(argc, argv, "h")) != -1) { switch (opt) { case 'h': default: usage(progname); } } /* Sanity check the URI and argument count */ arg = argv[optind]; if (arg == NULL) usage(progname); name = ccn_charbuf_create(); res = ccn_name_from_uri(name, arg); if (res < 0) { fprintf(stderr, "%s: bad ccn URI: %s\n", progname, arg); exit(1); } if (argc - optind < 3 || argc - optind > 4) usage(progname); h = ccn_create(); res = ccn_connect(h, NULL); if (res < 0) { ccn_perror(h, "ccn_connect"); exit(1); } newface = ccn_charbuf_create(); temp = ccn_charbuf_create(); templ = ccn_charbuf_create(); keylocator_templ = ccn_charbuf_create(); resultbuf = ccn_charbuf_create(); name_prefix = ccn_charbuf_create(); null_name = ccn_charbuf_create(); CHKRES(ccn_name_init(null_name)); keystore = ccn_keystore_create(); /* We need to figure out our local ccnd's CCIDID */ /* Set up our Interest template to indicate scope 1 */ ccn_charbuf_reset(templ); ccnb_element_begin(templ, CCN_DTAG_Interest); ccnb_element_begin(templ, CCN_DTAG_Name); ccnb_element_end(templ); /* </Name> */ ccnb_tagged_putf(templ, CCN_DTAG_Scope, "1"); ccnb_element_end(templ); /* </Interest> */ ccn_charbuf_reset(name); CHKRES(res = ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY")); CHKRES(res = ccn_get(h, name, templ, 200, resultbuf, &pcobuf, NULL, 0)); res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid, &ccndid_size); CHKRES(res); if (ccndid_size > sizeof(ccndid_storage)) CHKRES(-1); memcpy(ccndid_storage, ccndid, ccndid_size); ccndid = ccndid_storage; face_instance->action = "newface"; face_instance->ccnd_id = ccndid; face_instance->ccnd_id_size = ccndid_size; if (strcmp(argv[optind + 1], "tcp") == 0) ipproto = 6; else if (strcmp(argv[optind + 1], "udp") == 0) ipproto = 17; else ipproto = atoi(argv[optind + 1]); face_instance->descr.ipproto = ipproto; // XXX - 6 = tcp or 17 = udp face_instance->descr.address = argv[optind + 2]; face_instance->descr.port = argv[optind + 3]; if (face_instance->descr.port == NULL) face_instance->descr.port = CCN_DEFAULT_UNICAST_PORT; face_instance->descr.mcast_ttl = -1; face_instance->lifetime = (~0U) >> 1; CHKRES(res = ccnb_append_face_instance(newface, face_instance)); temp->length = 0; CHKRES(ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"))); res = ccn_keystore_init(keystore, ccn_charbuf_as_string(temp), "Th1s1sn0t8g00dp8ssw0rd."); CHKRES(res); ccnb_element_begin(keylocator_templ, CCN_DTAG_SignedInfo); ccnb_element_begin(keylocator_templ, CCN_DTAG_KeyLocator); ccnb_element_begin(keylocator_templ, CCN_DTAG_Key); CHKRES(ccn_append_pubkey_blob(keylocator_templ, ccn_keystore_public_key(keystore))); ccnb_element_end(keylocator_templ); /* </Key> */ ccnb_element_end(keylocator_templ); /* </KeyLocator> */ ccnb_element_end(keylocator_templ); /* </SignedInfo> */ sp.template_ccnb = keylocator_templ; sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; sp.freshness = expire; ccn_charbuf_reset(temp); res = ccn_sign_content(h, temp, null_name, &sp, newface->buf, newface->length); CHKRES(res); /* Create the new face */ CHKRES(ccn_name_init(name)); CHKRES(ccn_name_append_str(name, "ccnx")); CHKRES(ccn_name_append(name, ccndid, ccndid_size)); CHKRES(ccn_name_append(name, "newface", 7)); CHKRES(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0); if (res < 0) { fprintf(stderr, "no response from face creation request\n"); exit(1); } ptr = resultbuf->buf; length = resultbuf->length; res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); CHKRES(res); face_instance = ccn_face_instance_parse(ptr, length); if (face_instance == NULL) CHKRES(res = -1); CHKRES(face_instance->faceid); /* Finally, register the prefix */ ccn_charbuf_reset(name_prefix); CHKRES(ccn_name_from_uri(name_prefix, arg)); forwarding_entry->action = "prefixreg"; forwarding_entry->name_prefix = name_prefix; forwarding_entry->ccnd_id = ccndid; forwarding_entry->ccnd_id_size = ccndid_size; forwarding_entry->faceid = face_instance->faceid; forwarding_entry->flags = -1; /* let ccnd decide */ forwarding_entry->lifetime = (~0U) >> 1; prefixreg = ccn_charbuf_create(); CHKRES(res = ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); ccn_charbuf_reset(temp); res = ccn_sign_content(h, temp, null_name, &sp, prefixreg->buf, prefixreg->length); CHKRES(res); CHKRES(ccn_name_init(name)); CHKRES(ccn_name_append_str(name, "ccnx")); CHKRES(ccn_name_append(name, ccndid, ccndid_size)); CHKRES(ccn_name_append_str(name, "prefixreg")); CHKRES(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0); if (res < 0) { fprintf(stderr, "no response from prefix registration request\n"); exit(1); } fprintf(stderr, "Prefix %s will be forwarded to face %d\n", arg, face_instance->faceid); /* We're about to exit, so don't bother to free everything. */ ccn_destroy(&h); exit(res < 0); }
enum ccn_upcall_res incoming_content( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *templ = NULL; struct ccn_charbuf *temp = NULL; const unsigned char *ccnb = NULL; size_t ccnb_size = 0; const unsigned char *data = NULL; size_t data_size = 0; // TANG: no need to write data to stdout //size_t written; const unsigned char *ib = NULL; /* info->interest_ccnb */ struct ccn_indexbuf *ic = NULL; int res; struct mydata *md = selfp->data; if (kind == CCN_UPCALL_FINAL) { if (md != NULL) { selfp->data = NULL; free(md); md = NULL; } return(CCN_UPCALL_RESULT_OK); } if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) return(CCN_UPCALL_RESULT_REEXPRESS); if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED) return(CCN_UPCALL_RESULT_ERR); if (md == NULL) selfp->data = md = calloc(1, sizeof(*md)); ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; ib = info->interest_ccnb; ic = info->interest_comps; /* XXX - must verify sig, and make sure it is LEAF content */ res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size); if (res < 0) abort(); if (data_size > CHUNK_SIZE) { /* For us this is spam. Give up now. */ fprintf(stderr, "*** Segment %d found with a data size of %d." " This program only works with segments of 1024 bytes." " Try ccncatchunks2 instead.\n", (int)selfp->intdata, (int)data_size); exit(1); } /* OK, we will accept this block. */ //sleep(1); // TANG: No need to write data to stdout, skip 3 lines //written = fwrite(data, data_size, 1, stdout); //if (written != 1) // exit(1); /* A short block signals EOF for us. */ // TANG: to support data_size smaller than 1024, skip 2 lines //if (data_size < CHUNK_SIZE) // exit(0); /* Ask for the next one */ name = ccn_charbuf_create(); ccn_name_init(name); if (ic->n < 2) abort(); res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]); if (res < 0) abort(); temp = ccn_charbuf_create(); //printf("intdata = %d \n ", selfp->intdata); ccn_charbuf_putf(temp, "%d", ++(selfp->intdata)); ccn_name_append(name, temp->buf, temp->length); ccn_charbuf_destroy(&temp); if(DEBUG){ //Print out the interest's name printf("Interest name = "); int myres = 0; struct ccn_indexbuf* ndx = ccn_indexbuf_create(); unsigned char* mycomp = NULL; size_t mysize = 0; ndx->n = 0; myres = ccn_name_split(name, ndx); if(myres < 0){ fprintf(stderr, "ccn_name_split @ ccntraffic. failed"); } int it = 0; for(it = 0; it < ndx->n-1; it++){ mysize = 0; myres = ccn_name_comp_get(name->buf, ndx, it, &mycomp, &mysize); printf("%s/", mycomp); mycomp = NULL; } printf("\n"); } templ = make_template(md); res = ccn_express_interest(info->h, name, selfp, templ); if (res < 0) abort(); ccn_charbuf_destroy(&templ); ccn_charbuf_destroy(&name); return(CCN_UPCALL_RESULT_OK); }
enum ccn_upcall_res ccn_text_handler(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { UserDataBuf *userBuf = (UserDataBuf *)selfp->data; if (userBuf == NULL || userBuf->iNeedDestroy) { //if (userBuf != NULL) delete userBuf; //selfp->data = NULL; return CCN_UPCALL_RESULT_OK; } switch (kind) { case CCN_UPCALL_INTEREST_TIMED_OUT: { // if it's short Interest without seq, reexpress // TODO: check whether the user is still in the conference // don't re-express if it is not return (CCN_UPCALL_RESULT_REEXPRESS); } case CCN_UPCALL_CONTENT_UNVERIFIED: fprintf(stderr, "unverified content received\n"); return CCN_UPCALL_RESULT_OK; case CCN_UPCALL_FINAL: return CCN_UPCALL_RESULT_OK; case CCN_UPCALL_CONTENT: break; default: return CCN_UPCALL_RESULT_OK; } struct data_buffer *buffer = &userBuf->data_buf; const unsigned char *content_value; size_t len; NDNState *state = buffer->state; const unsigned char *ccnb = info->content_ccnb; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; struct ccn_indexbuf *comps = info->content_comps; ccn_content_get_value(ccnb, ccnb_size, info->pco, &content_value, &len); unsigned char *msg = (unsigned char *)calloc((len + 1), sizeof(char)); memcpy(msg, content_value, len); msg[len] = '\0'; QString textMsg = (const char *)msg; state->emitTextMsgArrival(userBuf->user_name, textMsg); free(msg); long seq; const unsigned char *seqptr = NULL; char *endptr = NULL; size_t seq_size = 0; int k = comps->n - 2; seq = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb, comps->buf[k], comps->buf[k + 1], &seqptr, &seq_size); if (seq >= 0) { seq = strtol((const char *)seqptr, &endptr, 10); if (endptr != ((const char *)seqptr) + seq_size) seq = -1; } if (seq < 0) { return CCN_UPCALL_RESULT_OK; } seq++; struct ccn_charbuf *path = ccn_charbuf_create(); ccn_name_init(path); ccn_name_append_components(path, ccnb, comps->buf[0], comps->buf[k]); struct ccn_charbuf *temp = ccn_charbuf_create(); ccn_charbuf_putf(temp, "%ld", seq); ccn_name_append(path, temp->buf, temp->length); int res = ccn_express_interest(info->h, path, selfp, NULL); if (res < 0) { fprintf(stderr, "sending the first interest failed\n"); exit(1); } ccn_charbuf_destroy(&path); ccn_charbuf_destroy(&temp); return CCN_UPCALL_RESULT_OK; }
/** * Handle the incoming content messages. Extracts the data, and * requests the next block in sequence if the received block was * not the final one. */ enum ccn_upcall_res incoming_content(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *templ = NULL; const unsigned char *ccnb = NULL; size_t ccnb_size = 0; const unsigned char *data = NULL; size_t data_size = 0; size_t written; const unsigned char *ib = NULL; /* info->interest_ccnb */ struct ccn_indexbuf *ic = NULL; int res; struct mydata *md = selfp->data; if (kind == CCN_UPCALL_FINAL) { if (md != NULL) { selfp->data = NULL; free(md); md = NULL; } return(CCN_UPCALL_RESULT_OK); } if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) return(CCN_UPCALL_RESULT_REEXPRESS); if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) return(CCN_UPCALL_RESULT_VERIFY); if (kind != CCN_UPCALL_CONTENT) return(CCN_UPCALL_RESULT_ERR); if (md == NULL) selfp->data = md = calloc(1, sizeof(*md)); ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; ib = info->interest_ccnb; ic = info->interest_comps; res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size); if (res < 0) abort(); if (info->pco->type != CCN_CONTENT_DATA) { /* For us this is spam. For now, give up. */ fprintf(stderr, "*** spammed at block %d\n", (int)selfp->intdata); exit(1); } /* OK, we will accept this block. */ if (data_size == 0) *(md->done) = 1; else { written = fwrite(data, data_size, 1, stdout); if (written != 1) exit(1); } // XXX The test below should get refactored into the library if (info->pco->offset[CCN_PCO_B_FinalBlockID] != info->pco->offset[CCN_PCO_E_FinalBlockID]) { const unsigned char *finalid = NULL; size_t finalid_size = 0; const unsigned char *nameid = NULL; size_t nameid_size = 0; struct ccn_indexbuf *cc = info->content_comps; ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, info->pco->offset[CCN_PCO_B_FinalBlockID], info->pco->offset[CCN_PCO_E_FinalBlockID], &finalid, &finalid_size); if (cc->n < 2) abort(); ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb, cc->buf[cc->n - 2], cc->buf[cc->n - 1], &nameid, &nameid_size); if (finalid_size == nameid_size && 0 == memcmp(finalid, nameid, nameid_size)) *(md->done) = 1; } if (*(md->done)) { ccn_set_run_timeout(info->h, 0); return(CCN_UPCALL_RESULT_OK); } /* Ask for the next fragment */ name = ccn_charbuf_create(); ccn_name_init(name); if (ic->n < 2) abort(); res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]); if (res < 0) abort(); ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, ++(selfp->intdata)); templ = make_template(md, info); res = ccn_express_interest(info->h, name, selfp, templ); if (res < 0) abort(); ccn_charbuf_destroy(&templ); ccn_charbuf_destroy(&name); return(CCN_UPCALL_RESULT_OK); }