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; }
static PyObject * Exclusion_Name_Obj(unsigned char *buf, size_t start, size_t stop) { struct ccn_charbuf *name; PyObject *py_name, *res; int r; py_name = CCNObject_New_charbuf(NAME, &name); JUMP_IF_NULL(py_name, error); r = ccn_name_init(name); JUMP_IF_NEG_MEM(r, error); r = ccn_name_append_components(name, buf, start, stop); JUMP_IF_NEG_MEM(r, error); res = Name_obj_from_ccn(py_name); Py_DECREF(py_name); return res; error: Py_XDECREF(py_name); return NULL; }
static void collect_forwarding_html(struct ccnd_handle *h, struct ccn_charbuf *b) { struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ struct ccn_forwarding *f; int res; struct ccn_charbuf *name = ccn_charbuf_create(); ccn_charbuf_putf(b, "<h4>Forwarding</h4>" NL); ccn_charbuf_putf(b, "<ul>"); hashtb_start(h->nameprefix_tab, e); for (; e->data != NULL; hashtb_next(e)) { struct nameprefix_entry *ipe = e->data; ccn_name_init(name); res = ccn_name_append_components(name, e->key, 0, e->keysize); if (res < 0) abort(); if (0) { ccn_charbuf_putf(b, " <li>"); ccn_uri_append(b, name->buf, name->length, 1); ccn_charbuf_putf(b, "</li>" NL); } for (f = ipe->forwarding; f != NULL; f = f->next) { if ((f->flags & (CCN_FORW_ACTIVE | CCN_FORW_PFXO)) != 0) { ccn_name_init(name); ccn_name_append_components(name, e->key, 0, e->keysize); ccn_charbuf_putf(b, " <li>"); ccn_uri_append(b, name->buf, name->length, 1); ccn_charbuf_putf(b, " <b>face:</b> %u" " <b>flags:</b> 0x%x" " <b>expires:</b> %d", f->faceid, f->flags & CCN_FORW_PUBMASK, f->expires); ccn_charbuf_putf(b, "</li>" NL); } } } hashtb_end(e); ccn_charbuf_destroy(&name); ccn_charbuf_putf(b, "</ul>"); }
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; }
/** * Verify a signed interest * * params are as returned in upcall info structure * key is what should be used to verify * * returns: * -1 for parsing error * 0 for incorrect signature / unverified * 1 for proper verification * */ int verify_signed_interest(const unsigned char *ccnb, const struct ccn_indexbuf *comps, size_t num_comps, size_t start, size_t stop, struct ccn_pkey* key) { fprintf(stderr,"verifying signed interest...\n"); // What is info->interest_comps->n ? //fprintf(stderr, "Interest components %d\n", (int) info->interest_comps->n); unsigned char* comp; size_t size; int res; // Create a charbuf with the matched interest name incl nonce struct ccn_charbuf* name = ccn_charbuf_create(); ccn_name_init(name); res = ccn_name_append_components(name, ccnb, start, stop); // Last component, should be the signature res = ccn_name_comp_get(ccnb, comps, num_comps, (const unsigned char**)&comp, &size); if (memcmp(NS_SIGNATURE, comp, NS_SIGNATURE_LEN) != 0) { fprintf(stderr, "debug: Last component not tagged as a signature.\n"); return(-1); } // Parse our nameless, dataless content object that follows the namespace // and replace the name with the implicit name from the interest, so that // we can use the standard signature verification calls. Could be made // more efficient with different library calls. struct ccn_charbuf* co_with_name = ccn_charbuf_create(); unsigned char* co = &comp[NS_SIGNATURE_LEN]; replace_name(co_with_name, co, size-NS_SIGNATURE_LEN, name); //fprintf(stderr, "replace_name == %d (%s)\n", res, (res==0)?"ok":"fail"); // For now, use standard routines to verify signature struct ccn_parsed_ContentObject pco = {0}; fprintf(stderr,"verifying signed interest...2\n"); res = ccn_parse_ContentObject(co_with_name->buf, co_with_name->length, &pco, NULL); if (!res) { // Verify the signature against the authorized public key given to us, passed through to the handler res = ccn_verify_signature(co_with_name->buf, pco.offset[CCN_PCO_E], &pco, key ); } else { fprintf(stderr, "debug: Constructed content object parse failed (res==%d)\n", res); } fprintf(stderr,"verifying signed interest...3\n"); ccn_charbuf_destroy(&co_with_name); ccn_charbuf_destroy(&name); return (res); }
void NdnMediaProcess::initPipe(struct ccn_closure *selfp, struct ccn_upcall_info *info, UserDataBuf *userBuf) { fprintf(stderr, "initializing pipe\n"); // get seq const unsigned char *ccnb = info->content_ccnb; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; struct ccn_indexbuf *comps = info->content_comps; long seq; const unsigned char *seqptr = NULL; char *endptr = NULL; size_t seq_size = 0; int k = comps->n - 2; if (userBuf->seq < 0) { 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) { userBuf->seq = seq; } else { return; } } fprintf(stderr, "fetched content with seq %d\n", seq); // send hint-ahead interests for (int i = 0; i < hint_ahead; i ++) { userBuf->seq++; struct ccn_charbuf *pathbuf = ccn_charbuf_create(); ccn_name_init(pathbuf); ccn_name_append_components(pathbuf, ccnb, comps->buf[0], comps->buf[k]); struct ccn_charbuf *temp = ccn_charbuf_create(); ccn_charbuf_putf(temp, "%ld", userBuf->seq); ccn_name_append(pathbuf, temp->buf, temp->length); // no need to trylock as we already have the lock // this should use pipe callback, selfp is normal callback int res = ccn_express_interest(info->h, pathbuf, userBuf->data_buf.pipe_callback, NULL); if (res < 0) { fprintf(stderr, "Sending interest failed at normal processor\n"); std::exit(1); } ccn_charbuf_destroy(&pathbuf); ccn_charbuf_destroy(&temp); } }
static void collect_forwarding_xml(struct ccnd_handle *h, struct ccn_charbuf *b) { struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ struct ccn_forwarding *f; int res; struct ccn_charbuf *name = ccn_charbuf_create(); ccn_charbuf_putf(b, "<forwarding>"); hashtb_start(h->nameprefix_tab, e); for (; e->data != NULL; hashtb_next(e)) { struct nameprefix_entry *ipe = e->data; for (f = ipe->forwarding, res = 0; f != NULL && !res; f = f->next) { if ((f->flags & (CCN_FORW_ACTIVE | CCN_FORW_PFXO)) != 0) res = 1; } if (res) { ccn_name_init(name); ccn_name_append_components(name, e->key, 0, e->keysize); ccn_charbuf_putf(b, "<fentry>"); ccn_charbuf_putf(b, "<prefix>"); ccn_uri_append(b, name->buf, name->length, 1); ccn_charbuf_putf(b, "</prefix>"); for (f = ipe->forwarding; f != NULL; f = f->next) { if ((f->flags & (CCN_FORW_ACTIVE | CCN_FORW_PFXO)) != 0) { ccn_charbuf_putf(b, "<dest>" "<faceid>%u</faceid>" "<flags>%x</flags>" "<expires>%d</expires>" "</dest>", f->faceid, f->flags & CCN_FORW_PUBMASK, f->expires); } } ccn_charbuf_putf(b, "</fentry>"); } } hashtb_end(e); ccn_charbuf_destroy(&name); ccn_charbuf_putf(b, "</forwarding>"); }
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); }
void GroupManager::incomingInterest(ccn_upcall_info *info) { int res; const char *data = NULL; const unsigned char *requester = NULL; const unsigned char *refresher = NULL; const unsigned char *filter = NULL; size_t filter_len = 0; ccn_charbuf *signed_info = NULL; ccn_charbuf *name = NULL; ccn_charbuf *content = NULL; RemoteUser *refreshUser = NULL; // requesterPrefix starts from index 4 to (info->interest_comps->n - 2) int nameEnd = 0; nameEnd = (info->interest_comps)->n - 2; /* construct reply data * name format: * /ndn/broadcast/conference/conference-name/speaker-list/username */ signed_info = ccn_charbuf_create(); struct ccn_charbuf *keylocator = ccn_charbuf_create(); ccn_create_keylocator(keylocator, ccn_keystore_public_key(cached_keystore)); res = ccn_signed_info_create(signed_info, /*pubkeyid*/ get_my_publisher_key_id(), /*publisher_key_id_size*/ get_my_publisher_key_id_length(), /*datetime*/ NULL, /*type*/ CCN_CONTENT_DATA, ///*freshness*/ -1, /*freshness*/ FRESHNESS, /*finalblockid*/ NULL, /*keylocator*/ keylocator); if (res < 0) { DPRINT("FAILED TO CREATE signed_info (res == %d)", res); } name = ccn_charbuf_create(); content = ccn_charbuf_create(); ccn_name_init(name); ccn_name_append_components(name, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[nameEnd + 1]); // append own username ccn_name_append_str(name, userName.toLocal8Bit().constData()); // get user list, the caller need to free the data buffer allocated int dlen = userListtoXml(&data); ccn_encode_ContentObject(content, name, signed_info, data, dlen, NULL, get_my_private_key()); // already have the lock, no need to trylock ccn_put(info->h, content->buf, content->length); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&content); if (data != NULL) { free((void *)data); data = NULL; } }
/** * 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); }
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; }
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); }
/* does that mean the last component is the implicit digest ? */ enum ccn_upcall_res packet_handler(struct ccn_closure *selfp, enum ccn_upcall_kind upcall_kind, struct ccn_upcall_info *info) { handler_data* h_data = (handler_data*) selfp->data; // Client data returned fprintf(stderr, "\nUpcall from %s handle\n", (info->h==(*h_data->ccn_rec))? "receiver":"publisher"); ccn_set_run_timeout(info->h, 0); // Return to client faster switch(upcall_kind) { case CCN_UPCALL_FINAL: fprintf(stderr, "CCN_UPCALL_FINAL\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST_TIMED_OUT: fprintf(stderr, "CCN_UPCALL_INTEREST_TIMED_OUT\n"); (*h_data->complete) = 1; // End the main loop, some sort of problem return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT: fprintf(stderr, "CCN_UPCALL_CONTENT\n"); const unsigned char* content = NULL; size_t content_bytes = 0; ccn_ref_tagged_BLOB(CCN_DTAG_Content, info->content_ccnb, info->pco->offset[CCN_PCO_B_Content], info->pco->offset[CCN_PCO_E_Content], &content, &content_bytes); fprintf(stderr, "\tContent: %s\n", content); (*h_data->outstanding_interests)--; return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT_UNVERIFIED: fprintf(stderr, "CCN_UPCALL_CONTENT_UNVERIFIED\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT_BAD: fprintf(stderr, "CCN_UPCALL_CONTENT_BAD\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONSUMED_INTEREST: fprintf(stderr, "CCN_UPCALL_CONSUMED_INTEREST\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST: fprintf(stderr, "CCN_UPCALL_INTEREST, (matched comp == %d)\n", info->matched_comps); fprintf(stderr, " (interest comps == %zu)\n", info->interest_comps->n); int res = 0; // Corrected 20-May-2011 to support interests with additional components after prefix // if (info->interest_comps->n < 3) { // Name + signature + implicit digest, minimum fprintf(stderr, "\tnot enough components, %zu<3\n", info->interest_comps->n); } else { // Verify the interest res = verify_signed_interest(info->interest_ccnb, info->interest_comps, info->interest_comps->n-2, info->interest_comps->buf[0], info->interest_comps->buf[info->interest_comps->n-2], (*h_data->public_key)); fprintf(stderr, "\tverify_signed_interest == %d (%s)\n", res, (res==1)?"verified":"unverified"); } // Based on the results, // create and send a reply using default key & algorithm for the receiving handle // to sign the content object. // char* reply_data = (res==1) ? "OK" : "AUTH_FAIL"; // A modest content. struct ccn_charbuf* reply = ccn_charbuf_create(); struct ccn_charbuf* name = ccn_charbuf_create(); struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; ccn_name_init(name); // Don't need to create a new name, could just index into the buffer. res = ccn_name_append_components(name, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[info->interest_comps->n - 1]); ccn_sign_content(info->h, reply, name, &sp, (void*)reply_data, strlen(reply_data)+1); res = ccn_put(info->h, reply->buf, reply->length); ccn_charbuf_destroy(&reply); ccn_charbuf_destroy(&name); if (res >= 0) { fprintf (stderr, "\tReturned Content: %s\n", reply_data); return (CCN_UPCALL_RESULT_INTEREST_CONSUMED); } return (CCN_UPCALL_RESULT_OK); } return (CCN_UPCALL_RESULT_ERR); }
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); }
int sync_cb(struct ccns_name_closure *nc, struct ccn_charbuf *lhash, struct ccn_charbuf *rhash, struct ccn_charbuf *name) { nlsr_lock(); int res; struct ccn_charbuf *content_name; struct ccn_indexbuf *content_comps; struct ccn_indexbuf *name_comps; content_comps = ccn_indexbuf_create(); res = ccn_name_split(name, content_comps); if ( res < 0 ) return 0; if (content_comps->n < 2) return 0; content_name = ccn_charbuf_create(); ccn_name_init(content_name); res = ccn_name_append_components( content_name, name->buf, content_comps->buf[0], content_comps->buf[content_comps->n - 1]); if ( res < 0) return 0; // for debugging struct ccn_charbuf *temp=ccn_charbuf_create(); ccn_uri_append(temp, content_name->buf, content_name->length, 0); if ( nlsr->debugging ) printf("Name before chopping: %s \n",ccn_charbuf_as_string(temp)); ccn_charbuf_destroy(&temp); name_comps = ccn_indexbuf_create(); res=ccn_name_split (content_name, name_comps); if (res < 0) return 0; if ( nlsr->debugging ) { printf("Number of components in name = %d \n",res); printf("Number of components in name as indexbuf->n = %d \n", (int)name_comps->n); } ccn_name_chop(content_name, name_comps, -3); if ( nlsr->debugging ) printf("Number of components in name as indexbuf->n after chopping= %d \n" , (int)name_comps->n); //for debugging struct ccn_charbuf *temp1=ccn_charbuf_create(); ccn_uri_append(temp1, content_name->buf, content_name->length, 0); if ( nlsr->debugging ) printf("Name after chopping: %s \n",ccn_charbuf_as_string(temp1)); ccn_charbuf_destroy(&temp1); //main method that processes contents from the sync process_content_from_sync(content_name, name_comps); ccn_charbuf_destroy(&content_name); ccn_indexbuf_destroy(&content_comps); ccn_indexbuf_destroy(&name_comps); nlsr_unlock(); return(0); }
/** * 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); }
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; struct ccn_charbuf *templ = 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 upcalldata *data = selfp->data; if (data->magic != 856372) abort(); if (kind == CCN_UPCALL_FINAL) return(CCN_UPCALL_RESULT_OK); if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) return(CCN_UPCALL_RESULT_REEXPRESS); if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) { if ((data->option & MUST_VERIFY) != 0) return(CCN_UPCALL_RESULT_VERIFY); } else if (kind != CCN_UPCALL_CONTENT) 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(); templ = ccn_charbuf_create(); /* note that comps->n is 1 greater than the number of explicit components */ if (matched_comps > 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]++; /* Recover the same prefix as before */ ccn_name_init(c); res = ccn_name_append_components(c, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[matched_comps]); if (res < 0) abort(); comp = ccn_charbuf_create(); ccn_name_init(comp); if (matched_comps + 1 == comps->n) { /* Reconstruct the implicit ContentObject digest component */ ccn_digest_ContentObject(ccnb, info->pco); ccn_name_append(comp, info->pco->digest, info->pco->digest_bytes); } else if (matched_comps < comps->n) { ccn_name_append_components(comp, ccnb, comps->buf[matched_comps], comps->buf[matched_comps + 1]); } res = ccn_uri_append(uri, comp->buf, comp->length, 0); if (res < 0 || uri->length < 1) fprintf(stderr, "*** Error: ccnls line %d res=%d\n", __LINE__, res); else { if (uri->length == 1) ccn_charbuf_append(uri, ".", 1); printf("%s%s\n", ccn_charbuf_as_string(uri) + 1, kind == CCN_UPCALL_CONTENT ? " [verified]" : " [unverified]"); } ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG); ccn_charbuf_append(templ, c->buf, c->length); /* Name */ if (matched_comps == comps->n) { /* The interest supplied the digest component */ ccn_charbuf_destroy(&comp); /* * We can't rely on the Exclude filter to keep from seeing this, so * say that we need at least one more name component. */ ccn_charbuf_append_tt(templ, CCN_DTAG_MinSuffixComponents, CCN_DTAG); ccn_charbuf_append_tt(templ, 1, CCN_UDATA); ccn_charbuf_append(templ, "1", 1); ccn_charbuf_append_closer(templ); /* </MinSuffixComponents> */ } else { 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); ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG); for (i = 0; i < data->n_excl; i++) { comp = data->excl[i]; if (comp->length < 4) abort(); ccn_charbuf_append(templ, comp->buf + 1, comp->length - 2); } comp = NULL; ccn_charbuf_append_closer(templ); /* </Exclude> */ ccnb_tagged_putf(templ, CCN_DTAG_AnswerOriginKind, "%d", CCN_AOK_CS); if (data->scope > -1) ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", data->scope); ccn_charbuf_append_closer(templ); /* </Interest> */ if (templ->length > data->warn) { fprintf(stderr, "*** Interest packet is %d bytes\n", (int)templ->length); data->warn = data->warn * 8 / 5; } ccn_express_interest(info->h, c, selfp, templ); ccn_charbuf_destroy(&templ); ccn_charbuf_destroy(&c); ccn_charbuf_destroy(&uri); return(CCN_UPCALL_RESULT_OK); }
/* * 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); }
enum ccn_upcall_res andana_server_decap_interest( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { enum ccn_upcall_res upcall_res = CCN_UPCALL_RESULT_ERR; struct andana_server *server = selfp->data; struct ccn_proxy *proxy = server->proxy; struct ccn_charbuf *new_interest = NULL; struct ccn_charbuf *new_name = NULL; struct ccn_charbuf *orig_name = NULL; struct ccn_indexbuf *orig_name_indexbuf = NULL; int orig_name_ncomps; char is_session = 0; struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ int res; DEBUG_PRINT("IN %d %s\n", __LINE__, __func__); switch (kind) { case CCN_UPCALL_INTEREST: DEBUG_PRINT("%d %s received interest\n", __LINE__, __func__); break; case CCN_UPCALL_INTEREST_TIMED_OUT: DEBUG_PRINT("%d %s received interest time out\n", __LINE__, __func__); /* Fall through */ default: DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_OK); } /* Extract Name from Interest */ orig_name_ncomps = ccn_util_extract_name(info->interest_ccnb, info->interest_comps, &orig_name, &orig_name_indexbuf); #ifdef PROXYDEBUG ccn_util_print_pc_fmt(orig_name->buf, orig_name->length); DEBUG_PRINT("\n"); DEBUG_PRINT("Name has %lu comps\n", orig_name_indexbuf->n-1); #endif /*Decapsulate & decrypt Interest. */ const unsigned char *const_encrypted = NULL; unsigned char *encrypted = NULL; size_t encrypted_size; if (orig_name_ncomps >= 2) { const unsigned char *session_check = NULL; size_t session_check_size; res = ccn_name_comp_get(orig_name->buf, orig_name_indexbuf, (unsigned int)server->SESSION_FLAG, &session_check, &session_check_size); if (res < 0) { DEBUG_PRINT("%d %s Error extracting session check component %lu\n", __LINE__, __func__, server->SESSION_FLAG); goto SessionFail; } else { DEBUG_PRINT("%d %s Extracted component %lu\n", __LINE__, __func__,server->SESSION_FLAG); } if (session_check_size == strlen("SESSION") && memcmp(session_check, "SESSION", session_check_size) == 0) { DEBUG_PRINT("%d %s Session identified\n", __LINE__, __func__); is_session = 1; } else { DEBUG_PRINT("%d %s Not a session\n", __LINE__, __func__); } } /* Decrypt the name (contains a new name and an Interest template) */ struct ccn_pkey *symkey = NULL; struct ccn_charbuf *decrypted = NULL; struct ccn_indexbuf *decrypted_comps = ccn_indexbuf_create(); if (is_session) { res = ccn_name_comp_get(orig_name->buf, orig_name_indexbuf, (unsigned int)server->SESSION_ENC, &const_encrypted, &encrypted_size); if (res < 0) { DEBUG_PRINT("%d %s Error extracting encrypted session component %lu\n", __LINE__, __func__, server->SESSION_ENC); goto SessionParseFail; } else { DEBUG_PRINT("%d %s Extracted encrypted session component %lu\n", __LINE__, __func__, server->SESSION_ENC); } encrypted = calloc(encrypted_size, sizeof(unsigned char)); memcpy(encrypted, const_encrypted, encrypted_size); ccn_crypto_name_sym_decrypt(server->node_key, encrypted, encrypted_size, &symkey, &decrypted, &decrypted_comps); } else { ccn_name_comp_get(orig_name->buf, orig_name_indexbuf, (unsigned int)server->ENC, &const_encrypted, &encrypted_size); encrypted = calloc(encrypted_size, sizeof(unsigned char)); memcpy(encrypted, const_encrypted, encrypted_size); ccn_crypto_name_asym_decrypt(server->privkey, encrypted, &symkey, &decrypted, &decrypted_comps); } size_t ncomps = decrypted_comps->n-1; const unsigned char *tmpl = NULL; size_t tmpl_size; res = ccn_name_comp_get(decrypted->buf, decrypted_comps, (unsigned int)ncomps - 1, &tmpl, &tmpl_size); if (res < 0) { DEBUG_PRINT("ABORT %d %s unable to retrieve component %d\n", __LINE__, __func__, (int)ncomps); goto CompExtractFail; } /* Pull timestamp component (comp 0) */ const unsigned char *ts_data = NULL; size_t ts_size; res = ccn_name_comp_get(decrypted->buf, decrypted_comps, 0, &ts_data, &ts_size); if (res < 0) { goto CompExtractFail; } struct timeval timestamp; ccn_util_extract_timestamp(ts_data, ts_size, ×tamp); struct timeval window = {.tv_sec = 1, .tv_usec = 600000}; if (ccn_util_timestamp_window(×tamp, &window) == 0) { /* Timestamp too far away, this may be a replay attack */ DEBUG_PRINT("%d %s Timestamp too distant\n", __LINE__, __func__); goto TimestampFail; } new_name = ccn_charbuf_create(); ccn_name_init(new_name); res = ccn_name_append_components(new_name, decrypted->buf, decrypted_comps->buf[1], decrypted_comps->buf[ncomps-1]); if (res < 0) { DEBUG_PRINT("ABORT %d %s unable to append components\n", __LINE__, __func__); goto AppendCompFail; } /*Construct new Interest*/ if (tmpl_size == 0) { /* Detected default template */ DEBUG_PRINT("%d %s Using default Interest template\n", __LINE__, __func__); new_interest = NULL; } else { DEBUG_PRINT("%d %s Copying Interest template\n", __LINE__, __func__); new_interest = ccn_charbuf_create(); ccn_charbuf_append(new_interest, tmpl, tmpl_size); } /*Map new name to that of the original Interest and the requested symkey */ hashtb_start(server->cname_to_pair, e); res = hashtb_seek(e, new_name->buf, new_name->length, 0); if (res == HT_NEW_ENTRY) { struct andana_server_pair *p = andana_server_pair_init(orig_name, symkey); struct andana_server_pair **loc = e->data; *loc = p; } else if (res == HT_OLD_ENTRY) { DEBUG_PRINT("Interest recording found old entry\n"); goto LookupFail; } else { DEBUG_PRINT("Error in Interest insertion\n"); goto LookupFail; } DEBUG_PRINT("%d %s starting to write new interest\n", __LINE__, __func__); res = ccn_express_interest(proxy->handle, new_name, proxy->content_handler, new_interest); DEBUG_PRINT("%d %s done to writing new interest\n", __LINE__, __func__); if(res != 0) { DEBUG_PRINT("ABORT %d %s express interest res = %d\n", __LINE__, __func__, res); goto SendFail; } upcall_res = CCN_UPCALL_RESULT_OK; SendFail: LookupFail: if (upcall_res == CCN_UPCALL_RESULT_ERR) { hashtb_delete(e); } hashtb_end(e); if (new_interest != NULL) { ccn_charbuf_destroy(&new_interest); } TimestampFail: AppendCompFail: ccn_charbuf_destroy(&new_name); CompExtractFail: ccn_charbuf_destroy(&decrypted); free(encrypted); ccn_crypto_symkey_destroy(&symkey); SessionParseFail: ccn_indexbuf_destroy(&decrypted_comps); SessionFail: ccn_charbuf_destroy(&orig_name); ccn_indexbuf_destroy(&orig_name_indexbuf); DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(upcall_res); } /** * Encapsulate and encrypt returning content objects. Encryption * uses the ephemeral symmetric key provided by the user in the original * interest (stored in a pair). * * This node will naturally sign the outgoing content object, thus providing * verifiability. */ enum ccn_upcall_res andana_server_encap_content( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { enum ccn_upcall_res upcall_res = CCN_UPCALL_RESULT_ERR; struct andana_server *server = selfp->data; struct ccn_proxy *proxy = server->proxy; struct ccn_charbuf *new_name = NULL; struct andana_server_pair **pair_ptr = NULL; struct ccn_charbuf *new_content = NULL; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ int res; DEBUG_PRINT("IN %d %s\n",__LINE__, __func__); switch (kind) { case CCN_UPCALL_CONTENT: /**< incoming verified content */ DEBUG_PRINT("%d %s Incoming verified content\n",__LINE__, __func__); break; case CCN_UPCALL_CONTENT_UNVERIFIED:/**< content that has not been verified */ DEBUG_PRINT("%d %s Incoming unverified content\n", __LINE__, __func__); break; case CCN_UPCALL_CONTENT_BAD: /**< verification failed */ DEBUG_PRINT("%d %s Incoming bad content (verification failure)\n", __LINE__, __func__); break; case CCN_UPCALL_INTEREST_TIMED_OUT:/**< interest timed out */ { DEBUG_PRINT("OUT %d %s Interest timed out\n", __LINE__, __func__); const unsigned char *name = info->interest_ccnb + info->pi->offset[CCN_PI_B_Name]; const size_t length = info->pi->offset[CCN_PI_E_Name] - info->pi->offset[CCN_PI_B_Name]; hashtb_start(server->cname_to_pair, e); hashtb_seek(e, name, length, 0); hashtb_delete(e); hashtb_end(e); return(CCN_UPCALL_RESULT_OK); } case CCN_UPCALL_FINAL:/**< handler is about to be deregistered */ DEBUG_PRINT("OUT %d %s final upcall\n", __LINE__, __func__); return(CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST: /**< incoming interest */ case CCN_UPCALL_CONSUMED_INTEREST: /**< incoming interest, someone has answered */ default: DEBUG_PRINT("OUT %d %s upcall other kind = %d\n", __LINE__, __func__, kind); return(CCN_UPCALL_RESULT_ERR); } DEBUG_PRINT("%d %s Received content object\n", __LINE__, __func__); if (info->content_ccnb == NULL) { DEBUG_PRINT("OUT %d %s in content upcall, but no content, check kind: %d\n", __LINE__, __func__, kind); return(CCN_UPCALL_RESULT_OK); } /*Find name in Content Object*/ new_name = ccn_charbuf_create(); ccn_name_init(new_name); ccn_name_append_components(new_name, info->content_ccnb, info->content_comps->buf[0], info->content_comps->buf[info->matched_comps]); #ifdef PROXYDEBUG DEBUG_PRINT("name matches %d comps\n", info->matched_comps); ccn_util_print_pc_fmt(info->content_ccnb + info->pco->offset[CCN_PCO_B_Name], info->pco->offset[CCN_PCO_E_Name] - info->pco->offset[CCN_PCO_B_Name]); DEBUG_PRINT("\n"); #endif pair_ptr = hashtb_lookup(server->cname_to_pair, new_name->buf, new_name->length); if(pair_ptr == NULL) { /* No match for name*/ #ifdef PROXYDEBUG DEBUG_PRINT("Unsolicited content object with name: "); ccn_util_print_pc_fmt(new_name->buf, new_name->length); DEBUG_PRINT("\n"); #endif goto LookupFail; } struct ccn_charbuf *orig_name = (*pair_ptr)->name; struct ccn_pkey *symkey = (*pair_ptr)->symkey; /*Created signed info for new content object*/ unsigned char *encrypted_content = NULL; size_t encrypted_length; struct ccn_charbuf *content = ccn_charbuf_create(); ccn_charbuf_append(content, info->content_ccnb, info->pco->offset[CCN_PCO_E]); ccn_crypto_content_encrypt(symkey, content->buf, content->length, &encrypted_content, &encrypted_length); new_content = ccn_charbuf_create(); sp.type = CCN_CONTENT_DATA; res = ccn_sign_content(proxy->handle, new_content, orig_name, &sp, encrypted_content, encrypted_length); if (ccn_util_validate_content_object(new_content->buf, new_content->length) != 0) { DEBUG_PRINT("ABORT %d %s Failed to validated signed content\n", __LINE__, __func__); abort(); goto SignFail; } else { DEBUG_PRINT("OK %d %s signed content is valid\n", __LINE__, __func__); } if (res != 0) { DEBUG_PRINT("ABORT %d %s Failed to encode ContentObject (res == %d)\n", __LINE__, __func__, res); goto SignFail; } DEBUG_PRINT("%d %s starting content write\n", __LINE__, __func__); res = ccn_put(proxy->handle, new_content->buf, new_content->length); DEBUG_PRINT("%d %s done content write line\n", __LINE__, __func__); if (res < 0) { DEBUG_PRINT("ABORT %d %s ccn_put failed (res == %d)\n", __LINE__, __func__, res); goto SendFail; } DEBUG_PRINT("%d %s Reply sent\n", __LINE__, __func__); upcall_res = CCN_UPCALL_RESULT_OK; SendFail: hashtb_start(server->cname_to_pair, e); hashtb_seek(e, new_name->buf, new_name->length, 0); hashtb_delete(e); hashtb_end(e); SignFail: ccn_charbuf_destroy(&new_content); free(encrypted_content); ccn_charbuf_destroy(&content); LookupFail: ccn_charbuf_destroy(&new_name); DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(upcall_res); } /** * Clean up and destroy anonymous server object. Expect * to be called once at program close. * * @param pointer to anonymous server to be destroyed * @returns 0 (always) */ int andana_server_destroy(struct andana_server **server) { struct andana_server *s = *server; free(s->proxy->int_handler); free(s->proxy->content_handler); ccn_proxy_destroy(&(s->proxy)); ccn_crypto_pubkey_destroy(&(s->privkey)); hashtb_destroy(&(s->cname_to_pair)); free(s); return(0); }