PyObject * Interest_obj_from_ccn(PyObject *py_interest) { struct ccn_charbuf *interest; struct ccn_parsed_interest *pi; PyObject *py_obj_Interest, *py_o; int r; debug("Interest_from_ccn_parsed start\n"); interest = CCNObject_Get(INTEREST, py_interest); // 1) Create python object py_obj_Interest = PyObject_CallObject(g_type_Interest, NULL); if (!py_obj_Interest) return NULL; pi = _pyccn_interest_get_pi(py_interest); JUMP_IF_NULL(pi, error); // 2) Set ccn_data to a cobject pointing to the c struct // and ensure proper destructor is set up for the c object. r = PyObject_SetAttrString(py_obj_Interest, "ccn_data", py_interest); JUMP_IF_NEG(r, error); // 3) Parse c structure and fill python attributes // using PyObject_SetAttrString ssize_t len; const unsigned char *blob; size_t blob_size, start, end; struct ccn_charbuf * cb; // Best decoding examples are in packet-ccn.c for wireshark plugin? // self.name = None # Start from None to use for templates? len = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name]; if (len > 0) { PyObject *py_cname; py_cname = CCNObject_New_charbuf(NAME, &cb); JUMP_IF_NULL(py_cname, error); r = ccn_charbuf_append(cb, interest->buf + pi->offset[CCN_PI_B_Name], len); JUMP_IF_NEG_MEM(r, error); py_o = Name_obj_from_ccn(py_cname); Py_DECREF(py_cname); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "name", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } else { PyErr_SetString(g_PyExc_CCNInterestError, "Got interest without a" " name!"); goto error; } // self.minSuffixComponents = None # default 0 len = pi->offset[CCN_PI_E_MinSuffixComponents] - pi->offset[CCN_PI_B_MinSuffixComponents]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_MinSuffixComponents, interest->buf, pi->offset[CCN_PI_B_MinSuffixComponents], pi->offset[CCN_PI_E_MinSuffixComponents]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " MinSuffixComponents value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "minSuffixComponents", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.maxSuffixComponents = None # default infinity len = pi->offset[CCN_PI_E_MaxSuffixComponents] - pi->offset[CCN_PI_B_MaxSuffixComponents]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_MaxSuffixComponents, interest->buf, pi->offset[CCN_PI_B_MaxSuffixComponents], pi->offset[CCN_PI_E_MaxSuffixComponents]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " MaxSuffixComponents value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "maxSuffixComponents", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.publisherPublicKeyDigest = None # SHA256 hash // TODO: what is CN_PI_B_PublisherID? -- looks like it is the data including // the tags while PublisherIDKeyDigest // is just the raw digest -- dk start = pi->offset[CCN_PI_B_PublisherID]; end = pi->offset[CCN_PI_E_PublisherID]; len = end - start; if (len > 0) { r = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, interest->buf, start, end, &blob, &blob_size); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " PublisherPublicKeyDigest value"); goto error; } py_o = PyBytes_FromStringAndSize((const char*) blob, blob_size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "publisherPublicKeyDigest", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.exclude = None len = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]; if (len > 0) { PyObject *py_exclusion_filter; py_exclusion_filter = CCNObject_New_charbuf(EXCLUSION_FILTER, &cb); JUMP_IF_NULL(py_exclusion_filter, error); r = ccn_charbuf_append(cb, interest->buf + pi->offset[CCN_PI_B_Exclude], len); JUMP_IF_NEG_MEM(r, error); py_o = ExclusionFilter_obj_from_ccn(py_exclusion_filter); Py_DECREF(py_exclusion_filter); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "exclude", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.childSelector = None len = pi->offset[CCN_PI_E_ChildSelector] - pi->offset[CCN_PI_B_ChildSelector]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_ChildSelector, interest->buf, pi->offset[CCN_PI_B_ChildSelector], pi->offset[CCN_PI_E_ChildSelector]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " ChildSelector value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "childSelector", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.answerOriginKind = None len = pi->offset[CCN_PI_E_AnswerOriginKind] - pi->offset[CCN_PI_B_AnswerOriginKind]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_AnswerOriginKind, interest->buf, pi->offset[CCN_PI_B_AnswerOriginKind], pi->offset[CCN_PI_E_AnswerOriginKind]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " AnswerOriginKind value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "answerOriginKind", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.scope = None len = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_Scope, interest->buf, pi->offset[CCN_PI_B_Scope], pi->offset[CCN_PI_E_Scope]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " Scope value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "scope", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.interestLifetime = None len = pi->offset[CCN_PI_E_InterestLifetime] - pi->offset[CCN_PI_B_InterestLifetime]; if (len > 0) { double lifetime; // From packet-ccn.c r = ccn_ref_tagged_BLOB(CCN_DTAG_InterestLifetime, interest->buf, pi->offset[CCN_PI_B_InterestLifetime], pi->offset[CCN_PI_E_InterestLifetime], &blob, &blob_size); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " InterestLifetime value"); goto error; } /* XXX: probably won't work with bigendian */ lifetime = 0.0; for (size_t i = 0; i < blob_size; i++) lifetime = lifetime * 256.0 + (double) blob[i]; lifetime /= 4096.0; py_o = PyFloat_FromDouble(lifetime); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "interestLifetime", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.nonce = None len = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce]; if (len > 0) { r = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, interest->buf, pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob, &blob_size); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " Nonce value"); goto error; } py_o = PyBytes_FromStringAndSize((const char *) blob, blob_size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "nonce", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } r = PyObject_SetAttrString(py_obj_Interest, "ccn_data_dirty", Py_False); JUMP_IF_NEG(r, error); // 4) Return the created object debug("Interest_from_ccn ends\n"); return py_obj_Interest; error: Py_DECREF(py_obj_Interest); return NULL; }
static int dissect_ccn_contentobject(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *signature_tree; proto_tree *name_tree; proto_tree *signedinfo_tree; proto_tree *content_tree; proto_item *titem; struct ccn_parsed_ContentObject co; struct ccn_parsed_ContentObject *pco = &co; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; size_t blob_size; const unsigned char *blob; int l; unsigned int i; double dt; nstime_t timestamp; int res; comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnb, ccnb_size, pco, comps); if (res < 0) return (-1); /* Signature */ l = pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]; titem = proto_tree_add_item(tree, hf_ccn_signature, tvb, pco->offset[CCN_PCO_B_Signature], l, FALSE); signature_tree = proto_item_add_subtree(titem, ett_signature); /* DigestAlgorithm */ l = pco->offset[CCN_PCO_E_DigestAlgorithm] - pco->offset[CCN_PCO_B_DigestAlgorithm]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, ccnb, pco->offset[CCN_PCO_B_DigestAlgorithm], pco->offset[CCN_PCO_E_DigestAlgorithm], &blob, &blob_size); titem = proto_tree_add_item(signature_tree, hf_ccn_signaturedigestalg, tvb, blob - ccnb, blob_size, FALSE); } /* Witness */ l = pco->offset[CCN_PCO_E_Witness] - pco->offset[CCN_PCO_B_Witness]; if (l > 0) { /* add the witness item to the signature tree */ } /* Signature bits */ l = pco->offset[CCN_PCO_E_SignatureBits] - pco->offset[CCN_PCO_B_SignatureBits]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, ccnb, pco->offset[CCN_PCO_B_SignatureBits], pco->offset[CCN_PCO_E_SignatureBits], &blob, &blob_size); titem = proto_tree_add_bytes(signature_tree, hf_ccn_signaturebits, tvb, blob - ccnb, blob_size, blob); } /* /Signature */ /* Name */ l = pco->offset[CCN_PCO_E_Name] - pco->offset[CCN_PCO_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pco->offset[CCN_PCO_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); /* Name Components */ for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* /Name */ /* SignedInfo */ l = pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]; titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_SignedInfo], l, "SignedInfo"); signedinfo_tree = proto_item_add_subtree(titem, ett_signedinfo); /* PublisherPublicKeyDigest */ l = pco->offset[CCN_PCO_E_PublisherPublicKeyDigest] - pco->offset[CCN_PCO_B_PublisherPublicKeyDigest]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, ccnb, pco->offset[CCN_PCO_B_PublisherPublicKeyDigest], pco->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); titem = proto_tree_add_bytes(signedinfo_tree, hf_ccn_publisherpublickeydigest, tvb, blob - ccnb, blob_size, blob); } /* Timestamp */ l = pco->offset[CCN_PCO_E_Timestamp] - pco->offset[CCN_PCO_B_Timestamp]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, ccnb, pco->offset[CCN_PCO_B_Timestamp], pco->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); dt = 0.0; for (i = 0; i < blob_size; i++) dt = dt * 256.0 + (double)blob[i]; dt /= 4096.0; timestamp.secs = dt; /* truncates */ timestamp.nsecs = (dt - (double) timestamp.secs) * 1000000000.0; titem = proto_tree_add_time(signedinfo_tree, hf_ccn_timestamp, tvb, blob - ccnb, blob_size, ×tamp); } /* Type */ l = pco->offset[CCN_PCO_E_Type] - pco->offset[CCN_PCO_B_Type]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Type, ccnb, pco->offset[CCN_PCO_B_Type], pco->offset[CCN_PCO_E_Type], &blob, &blob_size); titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, tvb, blob - ccnb, blob_size, pco->type); } else { titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, NULL, 0, 0, pco->type); } /* FreshnessSeconds */ l = pco->offset[CCN_PCO_E_FreshnessSeconds] - pco->offset[CCN_PCO_B_FreshnessSeconds]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds], &blob, &blob_size); i = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds]); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_freshnessseconds, tvb, blob - ccnb, blob_size, i); } /* FinalBlockID */ l = pco->offset[CCN_PCO_E_FinalBlockID] - pco->offset[CCN_PCO_B_FinalBlockID]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, pco->offset[CCN_PCO_B_FinalBlockID], pco->offset[CCN_PCO_E_FinalBlockID], &blob, &blob_size); titem = proto_tree_add_item(signedinfo_tree, hf_ccn_finalblockid, tvb, blob - ccnb, blob_size, FALSE); } /* TODO: KeyLocator */ /* /SignedInfo */ /* Content */ l = pco->offset[CCN_PCO_E_Content] - pco->offset[CCN_PCO_B_Content]; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnb, pco->offset[CCN_PCO_B_Content], pco->offset[CCN_PCO_E_Content], &blob, &blob_size); titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_Content], l, "Content: %d bytes", blob_size); if (blob_size > 0) { content_tree = proto_item_add_subtree(titem, ett_content); titem = proto_tree_add_item(content_tree, hf_ccn_contentdata, tvb, blob - ccnb, blob_size, FALSE); } return (ccnb_size); }
PUBLIC struct content_entry * r_store_lookup(struct ccnr_handle *h, const unsigned char *msg, const struct ccn_parsed_interest *pi, struct ccn_indexbuf *comps) { struct content_entry *content = NULL; struct ccn_btree_node *leaf = NULL; ccnr_cookie last_match = 0; ccnr_accession last_match_acc = CCNR_NULL_ACCESSION; struct ccn_charbuf *scratch = NULL; size_t size = pi->offset[CCN_PI_E]; int ndx; int res; int try; content = r_store_find_first_match_candidate(h, msg, pi); if (content != NULL && CCNSHOULDLOG(h, LM_8, CCNL_FINER)) ccnr_debug_content(h, __LINE__, "first_candidate", NULL, content); if (content != NULL && !r_store_content_matches_interest_prefix(h, content, msg, size)) { if (CCNSHOULDLOG(h, LM_8, CCNL_FINER)) ccnr_debug_ccnb(h, __LINE__, "prefix_mismatch", NULL, msg, size); content = NULL; } scratch = ccn_charbuf_create(); for (try = 0; content != NULL; try++) { res = ccn_btree_lookup(h->btree, content->flatname->buf, content->flatname->length, &leaf); if (CCN_BT_SRCH_FOUND(res) == 0) { ccnr_debug_content(h, __LINE__, "impossible", NULL, content); content = NULL; break; } ndx = CCN_BT_SRCH_INDEX(res); res = ccn_btree_match_interest(leaf, ndx, msg, pi, scratch); if (res == -1) { ccnr_debug_ccnb(h, __LINE__, "match_error", NULL, msg, size); content = NULL; break; } if (res == 1) { if ((pi->orderpref & 1) == 0) // XXX - should be symbolic break; last_match = content->cookie; last_match_acc = content->accession; content = r_store_next_child_at_level(h, content, comps->n - 1); } else content = r_store_content_next(h, content); if (content != NULL && !r_store_content_matches_interest_prefix(h, content, msg, size)) content = NULL; } if (last_match != 0) { content = r_store_content_from_cookie(h, last_match); if (content == NULL) content = r_store_content_from_accession(h, last_match_acc); } ccn_charbuf_destroy(&scratch); return(content); } /** * Find the first content handle that matches the prefix given by the namish, * which may be a Name, Interest, ContentObject, ... * * Does not check the other parts of namish, in particular, does not generate * the digest component of a ContentObject. */ PUBLIC struct content_entry * r_store_lookup_ccnb(struct ccnr_handle *h, const unsigned char *namish, size_t size) { struct content_entry *content = NULL; struct ccn_charbuf *flatname = NULL; int res; flatname = ccn_charbuf_create(); if (flatname == NULL) goto Bail; res = ccn_flatname_from_ccnb(flatname, namish, size); if (res < 0) goto Bail; content = r_store_look(h, flatname->buf, flatname->length); if (content != NULL) { res = ccn_flatname_charbuf_compare(flatname, content->flatname); if (res == 0 || res == -9999) { /* prefix matches */ } else content = NULL; } Bail: ccn_charbuf_destroy(&flatname); return(content); } /** * Mark content as stale */ PUBLIC void r_store_mark_stale(struct ccnr_handle *h, struct content_entry *content) { ccnr_cookie cookie = content->cookie; if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0) return; if (CCNSHOULDLOG(h, LM_4, CCNL_FINE)) ccnr_debug_content(h, __LINE__, "stale", NULL, content); content->flags |= CCN_CONTENT_ENTRY_STALE; h->n_stale++; if (cookie < h->min_stale) h->min_stale = cookie; if (cookie > h->max_stale) h->max_stale = cookie; } /** * Scheduled event that makes content stale when its FreshnessSeconds * has expired. */ static int expire_content(struct ccn_schedule *sched, void *clienth, struct ccn_scheduled_event *ev, int flags) { struct ccnr_handle *h = clienth; ccnr_cookie cookie = ev->evint; struct content_entry *content = NULL; if ((flags & CCN_SCHEDULE_CANCEL) != 0) return(0); content = r_store_content_from_cookie(h, cookie); if (content != NULL) r_store_mark_stale(h, content); return(0); } /** * Schedules content expiration based on its FreshnessSeconds. * */ PUBLIC void r_store_set_content_timer(struct ccnr_handle *h, struct content_entry *content, struct ccn_parsed_ContentObject *pco) { int seconds = 0; int microseconds = 0; size_t start = pco->offset[CCN_PCO_B_FreshnessSeconds]; size_t stop = pco->offset[CCN_PCO_E_FreshnessSeconds]; const unsigned char *content_msg = NULL; if (start == stop) return; content_msg = r_store_content_base(h, content); seconds = ccn_fetch_tagged_nonNegativeInteger( CCN_DTAG_FreshnessSeconds, content_msg, start, stop); if (seconds <= 0) return; if (seconds > ((1U<<31) / 1000000)) { ccnr_debug_content(h, __LINE__, "FreshnessSeconds_too_large", NULL, content); return; } microseconds = seconds * 1000000; ccn_schedule_event(h->sched, microseconds, &expire_content, NULL, content->cookie); }