low level name and packet parsing was added (You may edit external dependency to OpenSSL in root wscript file)
diff --git a/model/ccn_buf_decoder.cc b/model/ccn_buf_decoder.cc
new file mode 100644
index 0000000..cee63ba
--- /dev/null
+++ b/model/ccn_buf_decoder.cc
@@ -0,0 +1,939 @@
+/*
+ * ccn_buf_decoder.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "ccn_ccn.h"
+#include "ccn_charbuf.h"
+#include "ccn_coding.h"
+#include "ccn_indexbuf.h"
+
+/**
+ * @file ccn_buf_decoder.c
+ * @brief Support for Interest and ContentObject decoding.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008, 2009, 2010 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+struct ccn_buf_decoder *
+ccn_buf_decoder_start(struct ccn_buf_decoder *d,
+ const unsigned char *buf, size_t size)
+{
+ memset(&d->decoder, 0, sizeof(d->decoder));
+ d->decoder.state |= CCN_DSTATE_PAUSE;
+ d->buf = buf;
+ d->size = size;
+ ccn_skeleton_decode(&d->decoder, buf, size);
+ return(d);
+}
+
+void
+ccn_buf_advance(struct ccn_buf_decoder *d)
+{
+ ccn_skeleton_decode(&d->decoder,
+ d->buf + d->decoder.index,
+ d->size - d->decoder.index);
+}
+
+int
+ccn_buf_match_dtag(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
+{
+ return (d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG &&
+ (int)d->decoder.numval == dtag);
+}
+
+int
+ccn_buf_match_some_dtag(struct ccn_buf_decoder *d)
+{
+ return(d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG);
+}
+
+int
+ccn_buf_match_some_blob(struct ccn_buf_decoder *d)
+{
+ return(d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB);
+}
+
+int
+ccn_buf_match_blob(struct ccn_buf_decoder *d,
+ const unsigned char **bufp, size_t *sizep)
+{
+ if (ccn_buf_match_some_blob(d)) {
+ if (bufp != NULL)
+ *bufp = d->buf + d->decoder.index;
+ if (sizep != NULL)
+ *sizep = d->decoder.numval;
+ return (1);
+ }
+ if (bufp != NULL)
+ *bufp = d->buf + d->decoder.token_index;
+ if (sizep != NULL)
+ *sizep = 0;
+ return(0);
+}
+
+int
+ccn_buf_match_udata(struct ccn_buf_decoder *d, const char *s)
+{
+ size_t len = strlen(s);
+ return (d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA &&
+ d->decoder.numval == len &&
+ 0 == memcmp(d->buf + d->decoder.index, s, len));
+}
+
+int
+ccn_buf_match_attr(struct ccn_buf_decoder *d, const char *s)
+{
+ size_t len = strlen(s);
+ return (d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_ATTR &&
+ d->decoder.numval == len &&
+ 0 == memcmp(d->buf + d->decoder.index, s, len));
+}
+
+void
+ccn_buf_check_close(struct ccn_buf_decoder *d)
+{
+ if (d->decoder.state >= 0) {
+ if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) != CCN_NO_TOKEN)
+ d->decoder.state = CCN_DSTATE_ERR_NEST;
+ else
+ ccn_buf_advance(d);
+ }
+}
+
+int
+ccn_buf_advance_past_element(struct ccn_buf_decoder *d)
+{
+ enum ccn_tt tt;
+ int nest;
+ if (d->decoder.state < 0)
+ return(d->decoder.state);
+ tt = (ccn_tt)CCN_GET_TT_FROM_DSTATE(d->decoder.state);
+ if (tt == CCN_DTAG || tt == CCN_TAG) {
+ nest = d->decoder.nest;
+ ccn_buf_advance(d);
+ while (d->decoder.state >= 0 && d->decoder.nest >= nest)
+ ccn_buf_advance(d);
+ /* The nest decrements before the closer is consumed */
+ ccn_buf_check_close(d);
+ }
+ else
+ return(-1);
+ if (d->decoder.state < 0)
+ return(d->decoder.state);
+ return (0);
+}
+
+int
+ccn_parse_required_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
+ int minlen, int maxlen)
+{
+ int res = -1;
+ size_t len = 0;
+ if (ccn_buf_match_dtag(d, dtag)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ if (ccn_buf_match_some_blob(d)) {
+ len = d->decoder.numval;
+ ccn_buf_advance(d);
+ }
+ ccn_buf_check_close(d);
+ if ((int)len < minlen || (maxlen >= 0 && (int)len > maxlen)) {
+ d->decoder.state = -__LINE__;
+ }
+ }
+ else
+ d->decoder.state = -__LINE__;
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(res);
+}
+
+int
+ccn_parse_optional_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
+ int minlen, int maxlen)
+{
+ if (ccn_buf_match_dtag(d, dtag))
+ return(ccn_parse_required_tagged_BLOB(d, dtag, minlen, maxlen));
+ return(-1);
+}
+
+uintmax_t
+ccn_parse_required_tagged_binary_number(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag,
+ int minlen, int maxlen)
+{
+ uintmax_t value = 0;
+ const unsigned char *p = NULL;
+ size_t len = 0;
+ int i;
+ if (0 <= minlen && minlen <= maxlen && maxlen <= (int)sizeof(value) &&
+ ccn_buf_match_dtag(d, dtag)) {
+ ccn_buf_advance(d);
+ if (ccn_buf_match_blob(d, &p, &len))
+ ccn_buf_advance(d);
+ ccn_buf_check_close(d);
+ if (d->decoder.state < 0)
+ return(value);
+ if (minlen <= (int)len && (int)len <= maxlen)
+ for (i = 0; i < (int)len; i++)
+ value = (value << 8) + p[i];
+ else
+ d->decoder.state = -__LINE__;
+ }
+ else
+ d->decoder.state = -__LINE__;
+ return(value);
+}
+
+uintmax_t
+ccn_parse_optional_tagged_binary_number(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
+ int minlen, int maxlen, uintmax_t default_value)
+{
+ if (ccn_buf_match_dtag(d, dtag))
+ return(ccn_parse_required_tagged_binary_number(d, dtag, minlen, maxlen));
+ return(default_value);
+}
+
+int
+ccn_parse_required_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
+{
+ int res = -1;
+ if (ccn_buf_match_dtag(d, dtag)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ if (d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA)
+ ccn_buf_advance(d);
+ else
+ d->decoder.state = -__LINE__;
+ ccn_buf_check_close(d);
+ }
+ else
+ d->decoder.state = -__LINE__;
+ if (d->decoder.state < 0)
+ return (-1);
+ return(res);
+}
+
+int
+ccn_parse_optional_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
+{
+ if (ccn_buf_match_dtag(d, dtag))
+ return(ccn_parse_required_tagged_UDATA(d, dtag));
+ return(-1);
+}
+
+/**
+ * Parses a ccnb-encoded element expected to contain a UDATA string.
+ * @param d is the decoder
+ * @param dtag is the expected dtag value
+ * @param store - on success, the string value is appended to store,
+ * with null termination.
+ * @returns the offset into the store buffer of the copied value, or -1 for error.
+ * If a parse error occurs, d->decoder.state is set to a negative value.
+ * If the element is not present, -1 is returned but no parse error
+ * is indicated.
+ */
+int
+ccn_parse_tagged_string(struct ccn_buf_decoder *d, enum ccn_dtag dtag, struct ccn_charbuf *store)
+{
+ const unsigned char *p = NULL;
+ size_t size = 0;
+ int res;
+
+ if (ccn_buf_match_dtag(d, dtag)) {
+ ccn_buf_advance(d);
+ if (d->decoder.state >= 0 &&
+ CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
+ res = store->length;
+ p = d->buf + d->decoder.index;
+ size = d->decoder.numval;
+ ccn_buf_advance(d);
+ }
+ ccn_buf_check_close(d);
+ if (d->decoder.state >= 0) {
+ // XXX - should check for valid utf-8 data.
+ res = store->length;
+ if (size > 0)
+ ccn_charbuf_append(store, p, size);
+ ccn_charbuf_append_value(store, 0, 1);
+ return(res);
+ }
+ }
+ return(-1);
+}
+
+/**
+ * Parses a ccnb-encoded name
+ * @param d is the decoder
+ * @param components may be NULL, otherwise is filled in with the
+ * Component boundary offsets
+ * @returns the number of Components in the Name, or -1 if there is an error.
+ */
+int
+ccn_parse_Name(struct ccn_buf_decoder *d, struct ccn_indexbuf *components)
+{
+ int ncomp = 0;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
+ if (components != NULL) components->n = 0;
+ ccn_buf_advance(d);
+ while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
+ if (components != NULL)
+ ccn_indexbuf_append_element(components, d->decoder.token_index);
+ ncomp += 1;
+ ccn_buf_advance(d);
+ if (ccn_buf_match_blob(d, NULL, NULL))
+ ccn_buf_advance(d);
+ ccn_buf_check_close(d);
+ }
+ if (components != NULL)
+ ccn_indexbuf_append_element(components, d->decoder.token_index);
+ ccn_buf_check_close(d);
+ }
+ else
+ d->decoder.state = -__LINE__;
+ if (d->decoder.state < 0)
+ return(-1);
+ else
+ return(ncomp);
+}
+
+int
+ccn_parse_PublisherID(struct ccn_buf_decoder *d, struct ccn_parsed_interest *pi)
+{
+ int res = -1;
+ int iskey = 0;
+ unsigned pubstart = d->decoder.token_index;
+ unsigned keystart = pubstart;
+ unsigned keyend = pubstart;
+ unsigned pubend = pubstart;
+ iskey = ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest);
+ if (iskey ||
+ ccn_buf_match_dtag(d, CCN_DTAG_PublisherCertificateDigest) ||
+ ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerKeyDigest) ||
+ ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerCertificateDigest)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ keystart = d->decoder.token_index;
+ if (!ccn_buf_match_some_blob(d))
+ return (d->decoder.state = -__LINE__);
+ ccn_buf_advance(d);
+ keyend = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ pubend = d->decoder.token_index;
+ }
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ if (pi != NULL) {
+ pi->offset[CCN_PI_B_PublisherID] = pubstart;
+ pi->offset[CCN_PI_B_PublisherIDKeyDigest] = keystart;
+ pi->offset[CCN_PI_E_PublisherIDKeyDigest] = iskey ? keyend : keystart;
+ pi->offset[CCN_PI_E_PublisherID] = pubend;
+ }
+ return(res);
+}
+
+static int
+ccn_parse_optional_Any_or_Bloom(struct ccn_buf_decoder *d)
+{
+ int res;
+ res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Bloom, 1, 1024+8);
+ if (res >= 0)
+ return(res);
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) {
+ ccn_buf_advance(d);
+ ccn_buf_check_close(d);
+ res = 0;
+ }
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(res);
+}
+
+int
+ccn_parse_Exclude(struct ccn_buf_decoder *d)
+{
+ int res = -1;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ ccn_parse_optional_Any_or_Bloom(d);
+ while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
+ ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Component, 0, -1);
+ ccn_parse_optional_Any_or_Bloom(d);
+ }
+ ccn_buf_check_close(d);
+ }
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(res);
+}
+
+
+
+int
+ccn_parse_nonNegativeInteger(struct ccn_buf_decoder *d)
+{
+ const unsigned char *p;
+ int i;
+ int n;
+ int val;
+ int newval;
+ unsigned char c;
+ if (d->decoder.state < 0)
+ return(d->decoder.state);
+ if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
+ p = d->buf + d->decoder.index;
+ n = d->decoder.numval;
+ if (n < 1)
+ return(d->decoder.state = -__LINE__);
+ val = 0;
+ for (i = 0; i < n; i++) {
+ c = p[i];
+ if ('0' <= c && c <= '9') {
+ newval = val * 10 + (c - '0');
+ if (newval < val)
+ return(d->decoder.state = -__LINE__);
+ val = newval;
+ }
+ else
+ return(d->decoder.state = -__LINE__);
+ }
+ ccn_buf_advance(d);
+ return(val);
+ }
+ return(d->decoder.state = -__LINE__);
+}
+
+/**
+ * Parse a potentially large non-negative integer.
+ *
+ * @returns 0 for success, and the value is place in *result; for an error
+ * a negative value is returned and *result is unchanged.
+ */
+int
+ccn_parse_uintmax(struct ccn_buf_decoder *d, uintmax_t *result)
+{
+ const unsigned char *p;
+ int i;
+ int n;
+ uintmax_t val;
+ uintmax_t newval;
+ unsigned char c;
+ if (d->decoder.state < 0)
+ return(d->decoder.state);
+ if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
+ p = d->buf + d->decoder.index;
+ n = d->decoder.numval;
+ if (n < 1)
+ return(d->decoder.state = -__LINE__);
+ val = 0;
+ for (i = 0; i < n; i++) {
+ c = p[i];
+ if ('0' <= c && c <= '9') {
+ newval = val * 10 + (c - '0');
+ if (newval < val)
+ return(d->decoder.state = -__LINE__);
+ val = newval;
+ }
+ else
+ return(d->decoder.state = -__LINE__);
+ }
+ ccn_buf_advance(d);
+ *result = val;
+ return(0);
+ }
+ return(d->decoder.state = -__LINE__);
+}
+
+int
+ccn_parse_timestamp(struct ccn_buf_decoder *d)
+{
+ const unsigned char dlm[] = "--T::.Z";
+ const unsigned char *p;
+ int i;
+ int k;
+ int n;
+ if (d->decoder.state < 0)
+ return(d->decoder.state);
+ if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB) {
+ /* New-style binary timestamp, 12-bit fraction */
+ n = d->decoder.numval;
+ if (n < 3 || n > 7)
+ return(d->decoder.state = -__LINE__);
+ ccn_buf_advance(d);
+ return(0);
+ }
+ if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
+ /* This is for some temporary back-compatibility */
+ p = d->buf + d->decoder.index;
+ n = d->decoder.numval;
+ if (n < 8 || n > 40)
+ return(d->decoder.state = -__LINE__);
+ if (p[n - 1] != 'Z')
+ return(d->decoder.state = -__LINE__);
+ for (i = 0, k = 0; i < n && '0' <= p[i] && p[i] <= '9';) {
+ i++;
+ if (i < n && p[i] == dlm[k]) {
+ if (dlm[k++] == 0)
+ return(d->decoder.state = -__LINE__);
+ i++;
+ }
+ }
+ if (k < 5)
+ return(d->decoder.state = -__LINE__);
+ if (!(i == n || i == n - 1))
+ return(d->decoder.state = -__LINE__);
+ ccn_buf_advance(d);
+ return(0);
+ }
+ return(d->decoder.state = -__LINE__);
+}
+
+int
+ccn_parse_required_tagged_timestamp(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
+{
+ int res = -1;
+ if (ccn_buf_match_dtag(d, dtag)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ ccn_parse_timestamp(d);
+ ccn_buf_check_close(d);
+ }
+ else
+ d->decoder.state = -__LINE__;
+ if (d->decoder.state < 0)
+ return (-1);
+ return(res);
+}
+
+int
+ccn_parse_optional_tagged_nonNegativeInteger(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
+{
+ int res = -1;
+ if (ccn_buf_match_dtag(d, dtag)) {
+ ccn_buf_advance(d);
+ res = ccn_parse_nonNegativeInteger(d);
+ ccn_buf_check_close(d);
+ }
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(res);
+}
+
+int
+ccn_fetch_tagged_nonNegativeInteger(enum ccn_dtag tt,
+ const unsigned char *buf,
+ size_t start, size_t stop)
+{
+ struct ccn_buf_decoder decoder;
+ struct ccn_buf_decoder *d;
+ int result = -1;
+ if (stop < start) return(-1);
+ d = ccn_buf_decoder_start(&decoder, buf + start, stop - start);
+ if (ccn_buf_match_dtag(d, tt)) {
+ ccn_buf_advance(d);
+ result = ccn_parse_nonNegativeInteger(d);
+ ccn_buf_check_close(d);
+ }
+ if (result < 0)
+ return(-1);
+ return(result);
+}
+
+
+int
+ccn_parse_interest(const unsigned char *msg, size_t size,
+ struct ccn_parsed_interest *interest,
+ struct ccn_indexbuf *components)
+{
+ struct ccn_buf_decoder decoder;
+ struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
+ int magic = 0;
+ int ncomp = 0;
+ int res;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Interest)) {
+ if (components == NULL) {
+ /* We need to have the component offsets. */
+ components = ccn_indexbuf_create();
+ if (components == NULL) return(-1);
+ res = ccn_parse_interest(msg, size, interest, components);
+ ccn_indexbuf_destroy(&components);
+ return(res);
+ }
+ ccn_buf_advance(d);
+ interest->offset[CCN_PI_B_Name] = d->decoder.element_index;
+ interest->offset[CCN_PI_B_Component0] = d->decoder.index;
+ ncomp = ccn_parse_Name(d, components);
+ if (d->decoder.state < 0) {
+ memset(interest->offset, 0, sizeof(interest->offset));
+ return(d->decoder.state);
+ }
+ interest->offset[CCN_PI_E_ComponentLast] = d->decoder.token_index - 1;
+ interest->offset[CCN_PI_E_Name] = d->decoder.token_index;
+ interest->prefix_comps = ncomp;
+ interest->offset[CCN_PI_B_LastPrefixComponent] = components->buf[(ncomp > 0) ? (ncomp - 1) : 0];
+ interest->offset[CCN_PI_E_LastPrefixComponent] = components->buf[ncomp];
+ /* optional MinSuffixComponents, MaxSuffixComponents */
+ interest->min_suffix_comps = 0;
+ interest->max_suffix_comps = 32767;
+ interest->offset[CCN_PI_B_MinSuffixComponents] = d->decoder.token_index;
+ res = ccn_parse_optional_tagged_nonNegativeInteger(d,
+ CCN_DTAG_MinSuffixComponents);
+ interest->offset[CCN_PI_E_MinSuffixComponents] = d->decoder.token_index;
+ if (res >= 0)
+ interest->min_suffix_comps = res;
+ interest->offset[CCN_PI_B_MaxSuffixComponents] = d->decoder.token_index;
+ res = ccn_parse_optional_tagged_nonNegativeInteger(d,
+ CCN_DTAG_MaxSuffixComponents);
+ interest->offset[CCN_PI_E_MaxSuffixComponents] = d->decoder.token_index;
+ if (res >= 0)
+ interest->max_suffix_comps = res;
+ if (interest->max_suffix_comps < interest->min_suffix_comps)
+ return (d->decoder.state = -__LINE__);
+ /* optional PublisherID */
+ res = ccn_parse_PublisherID(d, interest);
+ /* optional Exclude element */
+ interest->offset[CCN_PI_B_Exclude] = d->decoder.token_index;
+ res = ccn_parse_Exclude(d);
+ interest->offset[CCN_PI_E_Exclude] = d->decoder.token_index;
+ /* optional ChildSelector */
+ interest->offset[CCN_PI_B_ChildSelector] = d->decoder.token_index;
+ res = ccn_parse_optional_tagged_nonNegativeInteger(d,
+ CCN_DTAG_ChildSelector);
+ if (res < 0)
+ res = 0;
+ interest->orderpref = res;
+ interest->offset[CCN_PI_E_ChildSelector] = d->decoder.token_index;
+ if (interest->orderpref > 5)
+ return (d->decoder.state = -__LINE__);
+ /* optional AnswerOriginKind */
+ interest->offset[CCN_PI_B_AnswerOriginKind] = d->decoder.token_index;
+ interest->answerfrom = ccn_parse_optional_tagged_nonNegativeInteger(d,
+ CCN_DTAG_AnswerOriginKind);
+ interest->offset[CCN_PI_E_AnswerOriginKind] = d->decoder.token_index;
+ if (interest->answerfrom == -1)
+ interest->answerfrom = CCN_AOK_DEFAULT;
+ else if ((interest->answerfrom & CCN_AOK_NEW) != 0 &&
+ (interest->answerfrom & CCN_AOK_CS) == 0)
+ return (d->decoder.state = -__LINE__);
+ /* optional Scope */
+ interest->offset[CCN_PI_B_Scope] = d->decoder.token_index;
+ interest->scope = ccn_parse_optional_tagged_nonNegativeInteger(d,
+ CCN_DTAG_Scope);
+ interest->offset[CCN_PI_E_Scope] = d->decoder.token_index;
+ if (interest->scope > 9)
+ return (d->decoder.state = -__LINE__);
+ if ((interest->answerfrom & CCN_AOK_EXPIRE) != 0 &&
+ interest->scope != 0)
+ return (d->decoder.state = -__LINE__);
+ /* optional InterestLifetime */
+ interest->offset[CCN_PI_B_InterestLifetime] = d->decoder.token_index;
+ res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_InterestLifetime, 1, 8);
+ if (res >= 0)
+ magic |= 20100401;
+ interest->offset[CCN_PI_E_InterestLifetime] = d->decoder.token_index;
+ /* optional Nonce */
+ interest->offset[CCN_PI_B_Nonce] = d->decoder.token_index;
+ res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Nonce, 4, 64);
+ interest->offset[CCN_PI_E_Nonce] = d->decoder.token_index;
+ /* Allow for no experimental stuff */
+ interest->offset[CCN_PI_B_OTHER] = d->decoder.token_index;
+ interest->offset[CCN_PI_E_OTHER] = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ interest->offset[CCN_PI_E] = d->decoder.index;
+ }
+ else
+ return (d->decoder.state = -__LINE__);
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ if (d->decoder.index != (int)size || !CCN_FINAL_DSTATE(d->decoder.state))
+ return (CCN_DSTATE_ERR_CODING);
+ if (magic == 0)
+ magic = 20090701;
+ if (!(magic == 20090701 || magic == 20100401))
+ return (d->decoder.state = -__LINE__);
+ interest->magic = magic;
+ return (ncomp);
+}
+
+struct parsed_KeyName {
+ int Name;
+ int endName;
+ int PublisherID;
+ int endPublisherID;
+};
+
+static int
+ccn_parse_KeyName(struct ccn_buf_decoder *d, struct parsed_KeyName *x)
+{
+ int res = -1;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ x->Name = d->decoder.token_index;
+ ccn_parse_Name(d, NULL);
+ x->endName = d->decoder.token_index;
+ x->PublisherID = ccn_parse_PublisherID(d, NULL);
+ x->endPublisherID = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ }
+ else
+ d->decoder.state = -__LINE__;
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(res);
+}
+
+static int
+ccn_parse_Signature(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
+{
+ int res = -1;
+ int i;
+ struct ccn_parsed_ContentObject dummy;
+ if (x == NULL)
+ x = &dummy;
+ for (i = CCN_PCO_B_Signature; i <= CCN_PCO_E_Signature; i++) {
+ x->offset[i] = d->decoder.token_index;
+ }
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Signature)) {
+ res = d->decoder.element_index;
+ ccn_buf_advance(d);
+ x->offset[CCN_PCO_B_DigestAlgorithm] = d->decoder.token_index;
+ ccn_parse_optional_tagged_UDATA(d, CCN_DTAG_DigestAlgorithm);
+ x->offset[CCN_PCO_E_DigestAlgorithm] = d->decoder.token_index;
+ x->offset[CCN_PCO_B_Witness] = d->decoder.token_index;
+ ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Witness, 8, -1);
+ x->offset[CCN_PCO_E_Witness] = d->decoder.token_index;
+ x->offset[CCN_PCO_B_SignatureBits] = d->decoder.token_index;
+ ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SignatureBits, 16, -1);
+ x->offset[CCN_PCO_E_SignatureBits] = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ x->offset[CCN_PCO_E_Signature] = d->decoder.token_index;
+ }
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(res);
+}
+
+static int
+ccn_parse_SignedInfo(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
+{
+ x->offset[CCN_PCO_B_SignedInfo] = d->decoder.token_index;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
+ ccn_buf_advance(d);
+ x->offset[CCN_PCO_B_PublisherPublicKeyDigest] = d->decoder.token_index;
+ ccn_parse_required_tagged_BLOB(d, CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
+ x->offset[CCN_PCO_E_PublisherPublicKeyDigest] = d->decoder.token_index;
+
+ x->offset[CCN_PCO_B_Timestamp] = d->decoder.token_index;
+ ccn_parse_required_tagged_timestamp(d, CCN_DTAG_Timestamp);
+ x->offset[CCN_PCO_E_Timestamp] = d->decoder.token_index;
+
+ x->offset[CCN_PCO_B_Type] = d->decoder.token_index;
+ x->type = CCN_CONTENT_DATA;
+ x->type = (ccn_content_type)ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3, CCN_CONTENT_DATA);
+ x->offset[CCN_PCO_E_Type] = d->decoder.token_index;
+
+ x->offset[CCN_PCO_B_FreshnessSeconds] = d->decoder.token_index;
+ ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds);
+ x->offset[CCN_PCO_E_FreshnessSeconds] = d->decoder.token_index;
+
+ x->offset[CCN_PCO_B_FinalBlockID] = d->decoder.token_index;
+ ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_FinalBlockID, 1, -1);
+ x->offset[CCN_PCO_E_FinalBlockID] = d->decoder.token_index;
+
+ x->offset[CCN_PCO_B_KeyLocator] = d->decoder.token_index;
+ x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
+ x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
+ x->offset[CCN_PCO_B_KeyName_Name] = d->decoder.token_index;
+ x->offset[CCN_PCO_E_KeyName_Name] = d->decoder.token_index;
+ x->offset[CCN_PCO_B_KeyName_Pub] = d->decoder.token_index;
+ x->offset[CCN_PCO_E_KeyName_Pub] = d->decoder.token_index;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) {
+ ccn_buf_advance(d);
+ x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
+ (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Key, 0, -1);
+ }
+ else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
+ (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Certificate, 0, -1);
+ }
+ else {
+ struct parsed_KeyName keyname = {-1, -1, -1, -1};
+ if (ccn_parse_KeyName(d, &keyname) >= 0) {
+ if (keyname.Name >= 0) {
+ x->offset[CCN_PCO_B_KeyName_Name] = keyname.Name;
+ x->offset[CCN_PCO_E_KeyName_Name] = keyname.endName;
+ }
+ if (keyname.PublisherID >= 0) {
+ x->offset[CCN_PCO_B_KeyName_Pub] = keyname.PublisherID;
+ x->offset[CCN_PCO_E_KeyName_Pub] = keyname.endPublisherID;
+ }
+ }
+ }
+ x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ }
+ x->offset[CCN_PCO_E_KeyLocator] = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ }
+ else
+ d->decoder.state = -__LINE__;
+ x->offset[CCN_PCO_E_SignedInfo] = d->decoder.token_index;
+ if (d->decoder.state < 0)
+ return (d->decoder.state);
+ return(0);
+}
+
+int
+ccn_parse_ContentObject(const unsigned char *msg, size_t size,
+ struct ccn_parsed_ContentObject *x,
+ struct ccn_indexbuf *components)
+{
+ struct ccn_buf_decoder decoder;
+ struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
+ int res;
+ x->magic = 20090415;
+ x->digest_bytes = 0;
+ if (ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) {
+ ccn_buf_advance(d);
+ res = ccn_parse_Signature(d, x);
+ x->offset[CCN_PCO_B_Name] = d->decoder.token_index;
+ x->offset[CCN_PCO_B_Component0] = d->decoder.index;
+ res = ccn_parse_Name(d, components);
+ if (res < 0)
+ d->decoder.state = -__LINE__;
+ x->name_ncomps = res;
+ x->offset[CCN_PCO_E_ComponentLast] = d->decoder.token_index - 1;
+ x->offset[CCN_PCO_E_Name] = d->decoder.token_index;
+ ccn_parse_SignedInfo(d, x);
+ x->offset[CCN_PCO_B_Content] = d->decoder.token_index;
+ ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Content, 0, -1);
+ x->offset[CCN_PCO_E_Content] = d->decoder.token_index;
+ ccn_buf_check_close(d);
+ x->offset[CCN_PCO_E] = d->decoder.index;
+ }
+ else
+ d->decoder.state = -__LINE__;
+ if (d->decoder.index != (int)size || !CCN_FINAL_DSTATE(d->decoder.state))
+ return (CCN_DSTATE_ERR_CODING);
+ return(0);
+}
+
+int
+ccn_ref_tagged_BLOB(enum ccn_dtag tt,
+ const unsigned char *buf, size_t start, size_t stop,
+ const unsigned char **presult, size_t *psize)
+{
+ struct ccn_buf_decoder decoder;
+ struct ccn_buf_decoder *d;
+ if (stop < start) return(-1);
+ d = ccn_buf_decoder_start(&decoder, buf + start, stop - start);
+ if (ccn_buf_match_dtag(d, tt)) {
+ ccn_buf_advance(d);
+ if (ccn_buf_match_blob(d, presult, psize))
+ ccn_buf_advance(d);
+ ccn_buf_check_close(d);
+ }
+ else
+ return(-1);
+ if (d->decoder.index != (int)d->size || !CCN_FINAL_DSTATE(d->decoder.state))
+ return (CCN_DSTATE_ERR_CODING);
+ return(0);
+}
+
+static struct ccn_buf_decoder *
+ccn_buf_decoder_start_at_components(struct ccn_buf_decoder *d,
+ const unsigned char *buf, size_t buflen)
+{
+ ccn_buf_decoder_start(d, buf, buflen);
+ while (ccn_buf_match_dtag(d, CCN_DTAG_Name) ||
+ ccn_buf_match_dtag(d, CCN_DTAG_Interest) ||
+ ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)
+ ) {
+ ccn_buf_advance(d);
+ ccn_parse_Signature(d, NULL);
+ }
+ return(d);
+}
+
+int
+ccn_content_get_value(const unsigned char *data, size_t data_size,
+ const struct ccn_parsed_ContentObject *content,
+ const unsigned char **value, size_t *value_size)
+{
+ int res;
+ res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, data,
+ content->offset[CCN_PCO_B_Content],
+ content->offset[CCN_PCO_E_Content],
+ value, value_size);
+ return(res);
+}
+
+int
+ccn_compare_names(const unsigned char *a, size_t asize,
+ const unsigned char *b, size_t bsize)
+{
+ struct ccn_buf_decoder a_decoder;
+ struct ccn_buf_decoder b_decoder;
+ struct ccn_buf_decoder *aa =
+ ccn_buf_decoder_start_at_components(&a_decoder, a, asize);
+ struct ccn_buf_decoder *bb =
+ ccn_buf_decoder_start_at_components(&b_decoder, b, bsize);
+ const unsigned char *acp = NULL;
+ const unsigned char *bcp = NULL;
+ size_t acsize;
+ size_t bcsize;
+ int cmp = 0;
+ int more_a;
+ for (;;) {
+ more_a = ccn_buf_match_dtag(aa, CCN_DTAG_Component);
+ cmp = more_a - ccn_buf_match_dtag(bb, CCN_DTAG_Component);
+ if (more_a == 0 || cmp != 0)
+ break;
+ ccn_buf_advance(aa);
+ ccn_buf_advance(bb);
+ acsize = bcsize = 0;
+ if (ccn_buf_match_blob(aa, &acp, &acsize))
+ ccn_buf_advance(aa);
+ if (ccn_buf_match_blob(bb, &bcp, &bcsize))
+ ccn_buf_advance(bb);
+ cmp = acsize - bcsize;
+ if (cmp != 0)
+ break;
+ cmp = memcmp(acp, bcp, acsize);
+ if (cmp != 0)
+ break;
+ ccn_buf_check_close(aa);
+ ccn_buf_check_close(bb);
+ }
+ return (cmp);
+}
+
diff --git a/model/ccn_buf_encoder.cc b/model/ccn_buf_encoder.cc
new file mode 100644
index 0000000..54b58aa
--- /dev/null
+++ b/model/ccn_buf_encoder.cc
@@ -0,0 +1,45 @@
+/*
+ * ccn_buf_encoder.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include "ccn_ccn.h"
+#include "ccn_charbuf.h"
+#include "ccn_coding.h"
+#include "ccn_indexbuf.h"
+
+/**
+ * Append a ccnb start marker
+ *
+ * This forms the basic building block of ccnb-encoded data.
+ * @param c is the buffer to append to.
+ * @param val is the numval, intepreted according to tt (see enum ccn_tt).
+ * @param tt is the type field.
+ * @returns 0 for success or -1 for error.
+ */
+int
+ccn_charbuf_append_tt(struct ccn_charbuf *c, size_t val, enum ccn_tt tt)
+{
+ unsigned char buf[1+8*((sizeof(val)+6)/7)];
+ unsigned char *p = &(buf[sizeof(buf)-1]);
+ int n = 1;
+ p[0] = (CCN_TT_HBIT & ~CCN_CLOSE) |
+ ((val & CCN_MAX_TINY) << CCN_TT_BITS) |
+ (CCN_TT_MASK & tt);
+ val >>= (7-CCN_TT_BITS);
+ while (val != 0) {
+ (--p)[0] = (((unsigned char)val) & ~CCN_TT_HBIT) | CCN_CLOSE;
+ n++;
+ val >>= 7;
+ }
+ return(ccn_charbuf_append(c, p, n));
+}
diff --git a/model/ccn_ccn.h b/model/ccn_ccn.h
new file mode 100644
index 0000000..f5b9d86
--- /dev/null
+++ b/model/ccn_ccn.h
@@ -0,0 +1,306 @@
+/*
+ * ccn_ccn.h
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef CCN_CCN_DEFINED
+#define CCN_CCN_DEFINED
+
+#include <stdint.h>
+#include "ccn_coding.h"
+#include "ccn_charbuf.h"
+#include "ccn_indexbuf.h"
+
+enum ccn_marker {
+ CCN_MARKER_NONE = -1,
+ CCN_MARKER_SEQNUM = 0x00, /**< consecutive block sequence numbers */
+ CCN_MARKER_CONTROL = 0xC1, /**< commands, etc. */
+ CCN_MARKER_OSEQNUM = 0xF8, /**< deprecated */
+ CCN_MARKER_BLKID = 0xFB, /**< nonconsecutive block ids */
+ CCN_MARKER_VERSION = 0xFD /**< timestamp-based versioning */
+};
+
+
+/*********** Interest parsing ***********/
+
+/*
+ * The parse of an interest results in an array of offsets into the
+ * wire representation, with the start and end of each major element and
+ * a few of the inportant sub-elements. The following enum allows those
+ * array items to be referred to symbolically. The *_B_* indices correspond
+ * to beginning offsets and the *_E_* indices correspond to ending offsets.
+ * An omitted element has its beginning and ending offset equal to each other.
+ * Normally these offsets will end up in non-decreasing order.
+ * Some aliasing tricks may be played here, e.g. since
+ * offset[CCN_PI_E_ComponentLast] is always equal to
+ * offset[CCN_PI_E_LastPrefixComponent],
+ * we may define CCN_PI_E_ComponentLast = CCN_PI_E_LastPrefixComponent.
+ * However, code should not rely on that,
+ * since it may change from time to time as the
+ * interest schema evolves.
+ */
+enum ccn_parsed_interest_offsetid {
+ CCN_PI_B_Name,
+ CCN_PI_B_Component0,
+ CCN_PI_B_LastPrefixComponent,
+ CCN_PI_E_LastPrefixComponent,
+ CCN_PI_E_ComponentLast = CCN_PI_E_LastPrefixComponent,
+ CCN_PI_E_Name,
+ CCN_PI_B_MinSuffixComponents,
+ CCN_PI_E_MinSuffixComponents,
+ CCN_PI_B_MaxSuffixComponents,
+ CCN_PI_E_MaxSuffixComponents,
+ CCN_PI_B_PublisherID, // XXX - rename
+ CCN_PI_B_PublisherIDKeyDigest,
+ CCN_PI_E_PublisherIDKeyDigest,
+ CCN_PI_E_PublisherID,
+ CCN_PI_B_Exclude,
+ CCN_PI_E_Exclude,
+ CCN_PI_B_ChildSelector,
+ CCN_PI_E_ChildSelector,
+ CCN_PI_B_AnswerOriginKind,
+ CCN_PI_E_AnswerOriginKind,
+ CCN_PI_B_Scope,
+ CCN_PI_E_Scope,
+ CCN_PI_B_InterestLifetime,
+ CCN_PI_E_InterestLifetime,
+ CCN_PI_B_Nonce,
+ CCN_PI_E_Nonce,
+ CCN_PI_B_OTHER,
+ CCN_PI_E_OTHER,
+ CCN_PI_E
+};
+
+
+struct ccn_parsed_interest {
+ int magic;
+ int prefix_comps;
+ int min_suffix_comps;
+ int max_suffix_comps;
+ int orderpref;
+ int answerfrom;
+ int scope;
+ unsigned short offset[CCN_PI_E+1];
+};
+
+/*
+ * Bitmasks for AnswerOriginKind
+ */
+#define CCN_AOK_CS 0x1 /* Answer from content store */
+#define CCN_AOK_NEW 0x2 /* OK to produce new content */
+#define CCN_AOK_DEFAULT (CCN_AOK_CS | CCN_AOK_NEW)
+#define CCN_AOK_STALE 0x4 /* OK to answer with stale data */
+#define CCN_AOK_EXPIRE 0x10 /* Mark as stale (must have Scope 0) */
+
+/***********************************
+ * Low-level binary formatting
+ */
+
+/*
+ * Append a ccnb start marker
+ *
+ * This forms the basic building block of ccnb-encoded data.
+ * c is the buffer to append to.
+ * Return value is 0, or -1 for error.
+ */
+int ccn_charbuf_append_tt(struct ccn_charbuf *c, size_t val, enum ccn_tt tt);
+
+/**
+ * Append a CCN_CLOSE
+ *
+ * Use this to close off an element in ccnb-encoded data.
+ * @param c is the buffer to append to.
+ * @returns 0 for success or -1 for error.
+ */
+int ccn_charbuf_append_closer(struct ccn_charbuf *c);
+
+/***********************************
+ * Slightly higher level binary formatting
+ */
+
+/*
+ * Append a non-negative integer as a UDATA.
+ */
+int ccnb_append_number(struct ccn_charbuf *c, int nni);
+
+/*
+ * Append a binary timestamp
+ * as a BLOB using the ccn binary Timestamp representation (12-bit fraction).
+ */
+int ccnb_append_timestamp_blob(struct ccn_charbuf *c,
+ enum ccn_marker marker,
+ long long secs, int nsecs);
+
+/*
+ * Append a binary timestamp, using the current time.
+ */
+int ccnb_append_now_blob(struct ccn_charbuf *c, enum ccn_marker marker);
+
+/*
+ * Append a start-of-element marker.
+ */
+int ccnb_element_begin(struct ccn_charbuf *c, enum ccn_dtag dtag);
+
+/*
+ * Append an end-of-element marker.
+ * This is the same as ccn_charbuf_append_closer()
+ */
+int ccnb_element_end(struct ccn_charbuf *c);
+
+/*
+ * Append a tagged BLOB
+ */
+int ccnb_append_tagged_blob(struct ccn_charbuf *c, enum ccn_dtag dtag,
+ const void *data, size_t size);
+
+/*
+ * Append a tagged UDATA string, with printf-style formatting
+ */
+int ccnb_tagged_putf(struct ccn_charbuf *c, enum ccn_dtag dtag,
+ const char *fmt, ...);
+
+
+
+/***********************************
+ * Binary decoding
+ * These routines require that the whole binary object be buffered.
+ */
+
+struct ccn_buf_decoder {
+ struct ccn_skeleton_decoder decoder;
+ const unsigned char *buf;
+ size_t size;
+};
+
+struct ccn_buf_decoder *ccn_buf_decoder_start(struct ccn_buf_decoder *d,
+ const unsigned char *buf, size_t size);
+
+void ccn_buf_advance(struct ccn_buf_decoder *d);
+int ccn_buf_advance_past_element(struct ccn_buf_decoder *d);
+
+/* The match routines return a boolean - true for match */
+int ccn_buf_match_dtag(struct ccn_buf_decoder *d, enum ccn_dtag dtag);
+
+int ccn_buf_match_some_dtag(struct ccn_buf_decoder *d);
+
+int ccn_buf_match_some_blob(struct ccn_buf_decoder *d);
+int ccn_buf_match_blob(struct ccn_buf_decoder *d,
+ const unsigned char **bufp, size_t *sizep);
+
+int ccn_buf_match_udata(struct ccn_buf_decoder *d, const char *s);
+
+int ccn_buf_match_attr(struct ccn_buf_decoder *d, const char *s);
+
+/* On error, the parse routines enter an error state and return a negative value. */
+/*int ccn_parse_required_tagged_BLOB(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag,
+ int minlen, int maxlen);
+int ccn_parse_optional_tagged_BLOB(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag,
+ int minlen, int maxlen);
+int ccn_parse_nonNegativeInteger(struct ccn_buf_decoder *d);
+int ccn_parse_optional_tagged_nonNegativeInteger(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag);
+int ccn_parse_uintmax(struct ccn_buf_decoder *d, uintmax_t *result);
+int ccn_parse_tagged_string(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag, struct ccn_charbuf *store);*/
+/* check the decoder error state for these two - result can't be negative */
+/*uintmax_t ccn_parse_required_tagged_binary_number(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag,
+ int minlen, int maxlen);
+uintmax_t ccn_parse_optional_tagged_binary_number(struct ccn_buf_decoder *d,
+ enum ccn_dtag dtag,
+ int minlen, int maxlen,
+ uintmax_t default_value);*/
+
+/**
+ * Enter an error state if element closer not found.
+ */
+void ccn_buf_check_close(struct ccn_buf_decoder *d);
+
+/*
+ * ccn_ref_tagged_BLOB: Get address & size associated with blob-valued element
+ * Returns 0 for success, negative value for error.
+ */
+int ccn_ref_tagged_BLOB(enum ccn_dtag tt,
+ const unsigned char *buf,
+ size_t start, size_t stop,
+ const unsigned char **presult, size_t *psize);
+
+/*
+ * ccn_parse_Name: Parses a ccnb-encoded name
+ * components may be NULL, otherwise is filled in with Component boundary offsets
+ * Returns the number of Components in the Name, or -1 if there is an error.
+ */
+int ccn_parse_Name(struct ccn_buf_decoder *d, struct ccn_indexbuf *components);
+
+/***********************************
+ * Authenticators and signatures for content are constructed in charbufs
+ * using the following routines.
+ */
+
+enum ccn_content_type {
+ CCN_CONTENT_DATA = 0x0C04C0,
+ CCN_CONTENT_ENCR = 0x10D091,
+ CCN_CONTENT_GONE = 0x18E344,
+ CCN_CONTENT_KEY = 0x28463F,
+ CCN_CONTENT_LINK = 0x2C834A,
+ CCN_CONTENT_NACK = 0x34008A
+};
+
+
+/*********** ContentObject parsing ***********/
+/* Analogous to enum ccn_parsed_interest_offsetid, but for content */
+enum ccn_parsed_content_object_offsetid {
+ CCN_PCO_B_Signature,
+ CCN_PCO_B_DigestAlgorithm,
+ CCN_PCO_E_DigestAlgorithm,
+ CCN_PCO_B_Witness,
+ CCN_PCO_E_Witness,
+ CCN_PCO_B_SignatureBits,
+ CCN_PCO_E_SignatureBits,
+ CCN_PCO_E_Signature,
+ CCN_PCO_B_Name,
+ CCN_PCO_B_Component0,
+ CCN_PCO_E_ComponentN,
+ CCN_PCO_E_ComponentLast = CCN_PCO_E_ComponentN,
+ CCN_PCO_E_Name,
+ CCN_PCO_B_SignedInfo,
+ CCN_PCO_B_PublisherPublicKeyDigest,
+ CCN_PCO_E_PublisherPublicKeyDigest,
+ CCN_PCO_B_Timestamp,
+ CCN_PCO_E_Timestamp,
+ CCN_PCO_B_Type,
+ CCN_PCO_E_Type,
+ CCN_PCO_B_FreshnessSeconds,
+ CCN_PCO_E_FreshnessSeconds,
+ CCN_PCO_B_FinalBlockID,
+ CCN_PCO_E_FinalBlockID,
+ CCN_PCO_B_KeyLocator,
+ /* Exactly one of Key, Certificate, or KeyName will be present */
+ CCN_PCO_B_Key_Certificate_KeyName,
+ CCN_PCO_B_KeyName_Name,
+ CCN_PCO_E_KeyName_Name,
+ CCN_PCO_B_KeyName_Pub,
+ CCN_PCO_E_KeyName_Pub,
+ CCN_PCO_E_Key_Certificate_KeyName,
+ CCN_PCO_E_KeyLocator,
+ CCN_PCO_E_SignedInfo,
+ CCN_PCO_B_Content,
+ CCN_PCO_E_Content,
+ CCN_PCO_E
+};
+
+struct ccn_parsed_ContentObject {
+ int magic;
+ enum ccn_content_type type;
+ int name_ncomps;
+ unsigned short offset[CCN_PCO_E+1];
+ unsigned char digest[32]; /* Computed only when needed */
+ int digest_bytes;
+};
+#endif
diff --git a/model/ccn_charbuf.cc b/model/ccn_charbuf.cc
new file mode 100644
index 0000000..69273a3
--- /dev/null
+++ b/model/ccn_charbuf.cc
@@ -0,0 +1,204 @@
+/*
+ * ccn_charbuf.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "ccn_charbuf.h"
+
+/**
+ * @file ccn_charbuf.c
+ * @brief Support expandable buffer for counted sequences of arbitrary bytes.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include "ccn_coding.h"
+
+struct ccn_charbuf *
+ccn_charbuf_create(void)
+{
+ struct ccn_charbuf *c;
+ c = (ccn_charbuf*)calloc(1, sizeof(*c));
+ return(c);
+}
+
+void
+ccn_charbuf_destroy(struct ccn_charbuf **cbp)
+{
+ struct ccn_charbuf *c = *cbp;
+ if (c != NULL) {
+ if (c->buf != NULL)
+ free(c->buf);
+ free(c);
+ *cbp = NULL;
+ }
+}
+
+/*
+ * ccn_charbuf_reserve: expand buffer as necessary to hold n more chars
+ */
+unsigned char *
+ccn_charbuf_reserve(struct ccn_charbuf *c, size_t n)
+{
+ size_t newsz = n + c->length;
+ unsigned char *buf = c->buf;
+ if (newsz < n)
+ return(NULL);
+ if (newsz > c->limit) {
+ if (2 * c->limit > newsz)
+ newsz = 2 * c->limit;
+ buf = (unsigned char*)realloc(c->buf, newsz);
+ if (buf == NULL)
+ return(NULL);
+ memset(buf + c->limit, 0, newsz - c->limit);
+ c->buf = buf;
+ c->limit = newsz;
+ }
+ buf += c->length;
+ return(buf);
+}
+
+void ccn_charbuf_reset(struct ccn_charbuf *c)
+{
+ if (c == NULL) {
+ return;
+ }
+ c->length = 0;
+}
+
+int
+ccn_charbuf_append(struct ccn_charbuf *c, const void *p, size_t n)
+{
+ unsigned char *dst = ccn_charbuf_reserve(c, n);
+ if (dst == NULL)
+ return(-1);
+ memcpy(dst, p, n);
+ c->length += n;
+ return(0);
+}
+
+int
+ccn_charbuf_append_value(struct ccn_charbuf *c, unsigned val, unsigned n)
+{
+ unsigned char *dst;
+ unsigned i;
+ if (n > sizeof(val))
+ return(-1);
+ dst = ccn_charbuf_reserve(c, n);
+ if (dst == NULL)
+ return(-1);
+ for (i = 0; i < n; i++)
+ dst[i] = (unsigned char)(val >> (8 * (n-1-i)));
+ c->length += n;
+ return(0);
+}
+
+int
+ccn_charbuf_append_charbuf(struct ccn_charbuf *c, const struct ccn_charbuf *in)
+{
+ return(ccn_charbuf_append(c, in->buf, in->length));
+}
+
+int
+ccn_charbuf_append_string(struct ccn_charbuf *c, const char *s)
+{
+ return(ccn_charbuf_append(c, s, strlen(s)));
+}
+
+int
+ccn_charbuf_putf(struct ccn_charbuf *c, const char *fmt, ...)
+{
+ int sz;
+ va_list ap;
+ char *buf;
+ buf = (char *)ccn_charbuf_reserve(c, strlen(fmt) + 10); /* estimate */
+ if (buf == NULL) return(-1);
+ va_start(ap, fmt);
+ sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
+ va_end(ap);
+ if (sz < 0)
+ return(sz);
+ if (c->length + sz < c->limit) {
+ c->length += sz;
+ return(sz);
+ }
+ va_end(ap);
+ buf = (char *)ccn_charbuf_reserve(c, sz + 1); /* accurate */
+ if (buf == NULL) return(-1);
+ va_start(ap, fmt);
+ sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
+ va_end(ap);
+ if (c->length + sz < c->limit) {
+ c->length += sz;
+ return(sz);
+ }
+ return(-1);
+}
+
+/* This formats time into xs:dateTime format */
+int
+ccn_charbuf_append_datetime(struct ccn_charbuf *c, time_t secs, int nsecs)
+{
+ char timestring[32];
+ int timelen;
+ struct tm time_tm;
+ int res;
+
+ timelen = strftime(timestring, sizeof(timestring),
+ "%FT%T", gmtime_r(&secs, &time_tm));
+ if (timelen >= (int)sizeof(timestring))
+ return(-1);
+ if (nsecs != 0) {
+ if (nsecs < 0 || nsecs >= 1000000000)
+ return(-1);
+ timelen += snprintf(×tring[timelen], sizeof(timestring) - timelen,
+ ".%09d", nsecs);
+ if (timelen >= (int)sizeof(timestring))
+ return(-1);
+ while (timestring[timelen - 1] == '0') timelen--;
+ }
+ timestring[timelen++] = 'Z';
+ res = ccn_charbuf_append(c, timestring, timelen);
+ return (res);
+}
+
+char *
+ccn_charbuf_as_string(struct ccn_charbuf *c)
+{
+ unsigned char *r;
+ r = ccn_charbuf_reserve(c, 1);
+ if (r == NULL)
+ return(NULL);
+ r[0] = 0;
+ return((char *)c->buf);
+}
+
+int
+ccn_charbuf_append_closer(struct ccn_charbuf *c)
+{
+ int res;
+ const unsigned char closer = CCN_CLOSE;
+ res = ccn_charbuf_append(c, &closer, 1);
+ return(res);
+}
diff --git a/model/ccn_charbuf.h b/model/ccn_charbuf.h
new file mode 100644
index 0000000..1d7fbb7
--- /dev/null
+++ b/model/ccn_charbuf.h
@@ -0,0 +1,126 @@
+/*
+ * ccn_charbuf.h
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+/**
+ * @file ccn/charbuf.h
+ *
+ * Expandable character buffer for counted sequences of arbitrary octets.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CCN_CHARBUF_DEFINED
+#define CCN_CHARBUF_DEFINED
+
+#include <stddef.h>
+#include <time.h>
+
+struct ccn_charbuf {
+ size_t length;
+ size_t limit;
+ unsigned char *buf;
+};
+
+/*
+ * ccn_charbuf_create: allocate a new charbuf
+ * ccn_charbuf_destroy: destroy a charbuf
+ */
+struct ccn_charbuf *ccn_charbuf_create(void);
+void ccn_charbuf_destroy(struct ccn_charbuf **cbp);
+
+/*
+ * ccn_charbuf_reserve: reserve some space in the buffer
+ * Grows c->buf if needed and returns a pointer to the new region.
+ * Does not modify c->length
+ */
+unsigned char *ccn_charbuf_reserve(struct ccn_charbuf *c, size_t n);
+
+/*
+ * ccn_charbuf_reset: reset to empty for reuse
+ * Sets c->length to 0
+ */
+void ccn_charbuf_reset(struct ccn_charbuf *c);
+
+/*
+ * ccn_charbuf_append: append character content
+ */
+int ccn_charbuf_append(struct ccn_charbuf *c, const void *p, size_t n);
+
+/*
+ * ccn_charbuf_append: append n bytes of val
+ * The n low-order bytes are appended in network byte order (big-endian)
+ */
+int ccn_charbuf_append_value(struct ccn_charbuf *c, unsigned val, unsigned n);
+
+
+/*
+ * ccn_charbuf_append_charbuf: append content from another charbuf
+ */
+int ccn_charbuf_append_charbuf(struct ccn_charbuf *c, const struct ccn_charbuf *i);
+
+/*
+ * ccn_charbuf_append: append a string
+ * Sometimes you have a null-terminated string in hand...
+ */
+int ccn_charbuf_append_string(struct ccn_charbuf *c, const char *s);
+
+/*
+ * ccn_charbuf_putf: formatting output
+ * Use this in preference to snprintf to simplify bookkeeping.
+ */
+int ccn_charbuf_putf(struct ccn_charbuf *c, const char *fmt, ...);
+
+/*
+ * ccn_charbuf_append_datetime: append a date/time string
+ * Appends a dateTime string in canonical form according to
+ * http://www.w3.org/TR/xmlschema-2/
+ * Return value is 0, or -1 for error.
+ * example: 2008-07-22T17:33:14.109Z
+ */
+int ccn_charbuf_append_datetime(struct ccn_charbuf *c, time_t secs, int nsecs);
+
+/*
+ * ccn_charbuf_append_datetime_now: append a date/time string
+ * Appends a dateTime string representing the current date and time
+ * in canonical form according to
+ * http://www.w3.org/TR/xmlschema-2/
+ * precision, a non-negative number, indicates the maximum number
+ * of fractional digits in the seconds. Only values 0..6 have
+ * any effect, at this times, since the gettimeofday() function
+ * is defined to return microsecond resolution.
+ * Return value is 0, or -1 for error.
+ * example: 2008-07-22T17:33:14.109Z
+ */
+#define CCN_DATETIME_PRECISION_USEC 6
+#define CCN_DATETIME_PRECISION_MAX 6
+int ccn_charbuf_append_datetime_now(struct ccn_charbuf *c, int precision);
+
+/*
+ * ccn_charbuf_as_string: view charbuf contents as a string
+ * This assures that c->buf has a null termination, and simply
+ * returns the pointer into the buffer. If the result needs to
+ * persist beyond the next operation on c, the caller is
+ * responsible for copying it.
+ */
+char *ccn_charbuf_as_string(struct ccn_charbuf *c);
+
+#endif
diff --git a/model/ccn_coding.cc b/model/ccn_coding.cc
new file mode 100644
index 0000000..cbb5345
--- /dev/null
+++ b/model/ccn_coding.cc
@@ -0,0 +1,273 @@
+/*
+ * ccn_coding.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "ccn_coding.h"
+
+/**
+ * @file ccn_coding.c
+ * @brief Support for scanning and parsing ccnb-encoded data.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+//#include <ccn/coding.h>
+
+/**
+ * This macro documents what's happening in the state machine by
+ * hinting at the XML syntax would be emitted in a re-encoder.
+ * But it actually does nothing.
+ */
+#define XML(goop) ((void)0)
+
+/**
+ * Decodes ccnb decoded data
+ *
+ * @param d holds the current state of the decoder.
+ * @param p points to a new block of ccnb data to feed to the decoder.
+ * @param n is the size of the input, in bytes.
+ * @returns the number of bytes consumed.
+ *
+ * The client should ensure that the decoder is initialized to all zero
+ * before the first call. In the default mode, the decoder will return
+ * only when it runs out of data, encounters an error, or reaches the end
+ * of the element that it started at. This is a good way to pull
+ * ccnb-encoded objects from a byte stream.
+ *
+ * By setting the CCN_DSTATE_PAUSE bit is set in the decoder state, the
+ * decoder will additionally return just after recognizing each token.
+ * In this instance, use CCN_GET_TT_FROM_DSTATE() to extract
+ * the token type from the decoder state;
+ * CCN_CLOSE will be reported as CCN_NO_TOKEN.
+ *
+ * The pause bit persists, so the end test should take that into account
+ * by using the CCN_FINAL_DSTATE() macro instead of testing for state 0.
+ *
+ * Once an error state is entered, no addition input is processed.
+ *
+ * @see ccn_buf_decoder_start(), ccn_buf_advance(), ccn_buf_check_close()
+ */
+ssize_t
+ccn_skeleton_decode(struct ccn_skeleton_decoder *d,
+ const unsigned char *p, size_t n)
+{
+ enum ccn_decoder_state state = (ccn_decoder_state)(d->state);
+ int tagstate = 0;
+ size_t numval = d->numval;
+ ssize_t i = 0;
+ unsigned char c;
+ size_t chunk;
+ int pause = 0;
+ if (d->state >= 0) {
+ pause = d->state & CCN_DSTATE_PAUSE;
+ tagstate = (d->state >> 8) & 3;
+ state = (ccn_decoder_state)(d->state & 0xFF);
+ }
+ while (i < (ssize_t)n) {
+ switch (state) {
+ case CCN_DSTATE_INITIAL:
+ case CCN_DSTATE_NEWTOKEN: /* start new thing */
+ d->token_index = i + d->index;
+ if (tagstate > 1 && tagstate-- == 2) {
+ XML("\""); /* close off the attribute value */
+ }
+ if (p[i] == CCN_CLOSE) {
+ i++;
+ if (d->nest <= 0 || tagstate > 1) {
+ state = CCN_DSTATE_ERR_NEST;
+ break;
+ }
+ if (tagstate == 1) {
+ tagstate = 0;
+ XML("/>");
+ }
+ else {
+ XML("</%s>");
+ }
+ d->nest -= 1;
+ if (d->nest == 0) {
+ state = CCN_DSTATE_INITIAL;
+ n = i;
+ }
+ if (pause) {
+ int temp = (int)state;
+ //state |= (((int)CCN_NO_TOKEN) << 16);
+ temp |= (((int)CCN_NO_TOKEN) << 16);
+ state = (ccn_decoder_state)temp;
+ n = i;
+ }
+ break;
+ }
+ numval = 0;
+ state = CCN_DSTATE_NUMVAL;
+ /* FALLTHRU */
+ case CCN_DSTATE_NUMVAL: /* parsing numval */
+ c = p[i++];
+ if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
+ if (numval > ((~(size_t)0U) >> (7 + CCN_TT_BITS)))
+ state = CCN_DSTATE_ERR_OVERFLOW;
+ numval = (numval << 7) + (c & 127);
+ }
+ else {
+ numval = (numval << (7-CCN_TT_BITS)) +
+ ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
+ c &= CCN_TT_MASK;
+ switch (c) {
+ case CCN_EXT:
+ if (tagstate == 1) {
+ tagstate = 0;
+ XML(">");
+ }
+ d->nest += 1;
+ d->element_index = d->token_index;
+ state = CCN_DSTATE_NEWTOKEN;
+ break;
+ case CCN_DTAG:
+ if (tagstate == 1) {
+ tagstate = 0;
+ XML(">");
+ }
+ d->nest += 1;
+ d->element_index = d->token_index;
+ XML("<%s");
+ tagstate = 1;
+ state = CCN_DSTATE_NEWTOKEN;
+ break;
+ case CCN_BLOB:
+ if (tagstate == 1) {
+ tagstate = 0;
+ XML(" ccnbencoding=\"base64Binary\">");
+ }
+ state = CCN_DSTATE_BLOB;
+ if (numval == 0)
+ state = CCN_DSTATE_NEWTOKEN;
+ break;
+ case CCN_UDATA:
+ if (tagstate == 1) {
+ tagstate = 0;
+ XML(">");
+ }
+ state = CCN_DSTATE_UDATA;
+ if (numval == 0)
+ state = CCN_DSTATE_NEWTOKEN;
+ break;
+ case CCN_DATTR:
+ if (tagstate != 1) {
+ state = CCN_DSTATE_ERR_ATTR;
+ break;
+ }
+ tagstate = 3;
+ state = CCN_DSTATE_NEWTOKEN;
+ break;
+ case CCN_ATTR:
+ if (tagstate != 1) {
+ state = CCN_DSTATE_ERR_ATTR;
+ break;
+ }
+ numval += 1; /* encoded as length-1 */
+ state = CCN_DSTATE_ATTRNAME;
+ break;
+ case CCN_TAG:
+ if (tagstate == 1) {
+ tagstate = 0;
+ XML(">");
+ }
+ numval += 1; /* encoded as length-1 */
+ d->nest += 1;
+ d->element_index = d->token_index;
+ state = CCN_DSTATE_TAGNAME;
+ break;
+ default:
+ state = CCN_DSTATE_ERR_CODING;
+ }
+ if (pause) {
+ int temp = (int)state;
+ //state |= (c << 16);
+ temp |= (c << 16);
+ state = (ccn_decoder_state)temp;
+ n = i;
+ }
+ }
+ break;
+ case CCN_DSTATE_TAGNAME: /* parsing tag name */
+ chunk = n - i;
+ if (chunk > numval)
+ chunk = numval;
+ if (chunk == 0) {
+ state = CCN_DSTATE_ERR_BUG;
+ break;
+ }
+ numval -= chunk;
+ i += chunk;
+ if (numval == 0) {
+ if (d->nest == 0) {
+ state = CCN_DSTATE_ERR_NEST;
+ break;
+ }
+ XML("<%s");
+ tagstate = 1;
+ state = CCN_DSTATE_NEWTOKEN;
+ }
+ break;
+ case CCN_DSTATE_ATTRNAME: /* parsing attribute name */
+ chunk = n - i;
+ if (chunk > numval)
+ chunk = numval;
+ if (chunk == 0) {
+ state = CCN_DSTATE_ERR_BUG;
+ break;
+ }
+ numval -= chunk;
+ i += chunk;
+ if (numval == 0) {
+ if (d->nest == 0) {
+ state = CCN_DSTATE_ERR_ATTR;
+ break;
+ }
+ XML(" %s=\"");
+ tagstate = 3;
+ state = CCN_DSTATE_NEWTOKEN;
+ }
+ break;
+ case CCN_DSTATE_UDATA: /* utf-8 data */
+ case CCN_DSTATE_BLOB: /* BLOB */
+ chunk = n - i;
+ if (chunk > numval)
+ chunk = numval;
+ if (chunk == 0) {
+ state = CCN_DSTATE_ERR_BUG;
+ break;
+ }
+ numval -= chunk;
+ i += chunk;
+ if (numval == 0)
+ state = CCN_DSTATE_NEWTOKEN;
+ break;
+ default:
+ n = i;
+ }
+ }
+ if (state < 0)
+ tagstate = pause = 0;
+ d->state = state | pause | (tagstate << 8);
+ d->numval = numval;
+ d->index += i;
+ return(i);
+}
diff --git a/model/ccn_coding.h b/model/ccn_coding.h
new file mode 100644
index 0000000..808d5be
--- /dev/null
+++ b/model/ccn_coding.h
@@ -0,0 +1,230 @@
+/*
+ * ccn_coding.h
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+/**
+ * @file ccn/coding.h
+ *
+ * Details of the ccn binary wire encoding.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008-2010 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CCN_CODING_DEFINED
+#define CCN_CODING_DEFINED
+
+#include <sys/types.h>
+#include <stddef.h>
+
+#define CCN_TT_BITS 3
+#define CCN_TT_MASK ((1 << CCN_TT_BITS) - 1)
+#define CCN_MAX_TINY ((1 << (7-CCN_TT_BITS)) - 1)
+#define CCN_TT_HBIT ((unsigned char)(1 << 7))
+
+/**
+ * Type tag for a ccnb start marker.
+ */
+enum ccn_tt {
+ CCN_EXT, /**< starts composite extension - numval is subtype */
+ CCN_TAG, /**< starts composite - numval is tagnamelen-1 */
+ CCN_DTAG, /**< starts composite - numval is tagdict index (enum ccn_dtag) */
+ CCN_ATTR, /**< attribute - numval is attrnamelen-1, value follows */
+ CCN_DATTR, /**< attribute numval is attrdict index */
+ CCN_BLOB, /**< opaque binary data - numval is byte count */
+ CCN_UDATA, /**< UTF-8 encoded character data - numval is byte count */
+ CCN_NO_TOKEN /**< should not occur in encoding */
+};
+
+/** CCN_CLOSE terminates composites */
+#define CCN_CLOSE ((unsigned char)(0))
+
+enum ccn_ext_subtype {
+ /* skip smallest values for now */
+ CCN_PROCESSING_INSTRUCTIONS = 16 /* <?name:U value:U?> */
+};
+
+/**
+ * DTAG identifies ccnb-encoded elements.
+ * c.f. tagname.csvdict
+ * See the gen_enum_dtag script for help updating these.
+ */
+enum ccn_dtag {
+ CCN_DTAG_Any = 13,
+ CCN_DTAG_Name = 14,
+ CCN_DTAG_Component = 15,
+ CCN_DTAG_Certificate = 16,
+ CCN_DTAG_Collection = 17,
+ CCN_DTAG_CompleteName = 18,
+ CCN_DTAG_Content = 19,
+ CCN_DTAG_SignedInfo = 20,
+ CCN_DTAG_ContentDigest = 21,
+ CCN_DTAG_ContentHash = 22,
+ CCN_DTAG_Count = 24,
+ CCN_DTAG_Header = 25,
+ CCN_DTAG_Interest = 26, /* 20090915 */
+ CCN_DTAG_Key = 27,
+ CCN_DTAG_KeyLocator = 28,
+ CCN_DTAG_KeyName = 29,
+ CCN_DTAG_Length = 30,
+ CCN_DTAG_Link = 31,
+ CCN_DTAG_LinkAuthenticator = 32,
+ CCN_DTAG_NameComponentCount = 33, /* DeprecatedInInterest */
+ CCN_DTAG_RootDigest = 36,
+ CCN_DTAG_Signature = 37,
+ CCN_DTAG_Start = 38,
+ CCN_DTAG_Timestamp = 39,
+ CCN_DTAG_Type = 40,
+ CCN_DTAG_Nonce = 41,
+ CCN_DTAG_Scope = 42,
+ CCN_DTAG_Exclude = 43,
+ CCN_DTAG_Bloom = 44,
+ CCN_DTAG_BloomSeed = 45,
+ CCN_DTAG_AnswerOriginKind = 47,
+ CCN_DTAG_InterestLifetime = 48,
+ CCN_DTAG_Witness = 53,
+ CCN_DTAG_SignatureBits = 54,
+ CCN_DTAG_DigestAlgorithm = 55,
+ CCN_DTAG_BlockSize = 56,
+ CCN_DTAG_FreshnessSeconds = 58,
+ CCN_DTAG_FinalBlockID = 59,
+ CCN_DTAG_PublisherPublicKeyDigest = 60,
+ CCN_DTAG_PublisherCertificateDigest = 61,
+ CCN_DTAG_PublisherIssuerKeyDigest = 62,
+ CCN_DTAG_PublisherIssuerCertificateDigest = 63,
+ CCN_DTAG_ContentObject = 64, /* 20090915 */
+ CCN_DTAG_WrappedKey = 65,
+ CCN_DTAG_WrappingKeyIdentifier = 66,
+ CCN_DTAG_WrapAlgorithm = 67,
+ CCN_DTAG_KeyAlgorithm = 68,
+ CCN_DTAG_Label = 69,
+ CCN_DTAG_EncryptedKey = 70,
+ CCN_DTAG_EncryptedNonceKey = 71,
+ CCN_DTAG_WrappingKeyName = 72,
+ CCN_DTAG_Action = 73,
+ CCN_DTAG_FaceID = 74,
+ CCN_DTAG_IPProto = 75,
+ CCN_DTAG_Host = 76,
+ CCN_DTAG_Port = 77,
+ CCN_DTAG_MulticastInterface = 78,
+ CCN_DTAG_ForwardingFlags = 79,
+ CCN_DTAG_FaceInstance = 80,
+ CCN_DTAG_ForwardingEntry = 81,
+ CCN_DTAG_MulticastTTL = 82,
+ CCN_DTAG_MinSuffixComponents = 83,
+ CCN_DTAG_MaxSuffixComponents = 84,
+ CCN_DTAG_ChildSelector = 85,
+ CCN_DTAG_RepositoryInfo = 86,
+ CCN_DTAG_Version = 87,
+ CCN_DTAG_RepositoryVersion = 88,
+ CCN_DTAG_GlobalPrefix = 89,
+ CCN_DTAG_LocalName = 90,
+ CCN_DTAG_Policy = 91,
+ CCN_DTAG_Namespace = 92,
+ CCN_DTAG_GlobalPrefixName = 93,
+ CCN_DTAG_PolicyVersion = 94,
+ CCN_DTAG_KeyValueSet = 95,
+ CCN_DTAG_KeyValuePair = 96,
+ CCN_DTAG_IntegerValue = 97,
+ CCN_DTAG_DecimalValue = 98,
+ CCN_DTAG_StringValue = 99,
+ CCN_DTAG_BinaryValue = 100,
+ CCN_DTAG_NameValue = 101,
+ CCN_DTAG_Entry = 102,
+ CCN_DTAG_ACL = 103,
+ CCN_DTAG_ParameterizedName = 104,
+ CCN_DTAG_Prefix = 105,
+ CCN_DTAG_Suffix = 106,
+ CCN_DTAG_Root = 107,
+ CCN_DTAG_ProfileName = 108,
+ CCN_DTAG_Parameters = 109,
+ CCN_DTAG_InfoString = 110,
+ CCN_DTAG_StatusResponse = 112,
+ CCN_DTAG_StatusCode = 113,
+ CCN_DTAG_StatusText = 114,
+ CCN_DTAG_SequenceNumber = 256,
+ CCN_DTAG_CCNProtocolDataUnit = 17702112
+};
+
+struct ccn_dict_entry {
+ int index; /**< matches enum ccn_dtag above */
+ const char *name; /**< textual name of dtag */
+};
+
+struct ccn_dict {
+ int count; /**< Count of elements in the table */
+ const struct ccn_dict_entry *dict; /**< the table entries */
+};
+
+/**
+ * Table for translating from DTAGs to names and vice versa.
+ */
+extern const struct ccn_dict ccn_dtag_dict; /* matches enum ccn_dtag above */
+
+struct ccn_skeleton_decoder { /* initialize to all 0 */
+ ssize_t index; /**< Number of bytes processed */
+ int state; /**< Decoder state */
+ int nest; /**< Element nesting */
+ size_t numval; /**< Current numval, meaning depends on state */
+ size_t token_index; /**< Starting index of most-recent token */
+ size_t element_index; /**< Starting index of most-recent element */
+};
+
+/**
+ * The decoder state is one of these, possibly with some
+ * additional bits set for internal use. A complete parse
+ * ends up in state 0 or an error state. Not all possible
+ * error states are listed here.
+ */
+enum ccn_decoder_state {
+ CCN_DSTATE_INITIAL = 0,
+ CCN_DSTATE_NEWTOKEN,
+ CCN_DSTATE_NUMVAL,
+ CCN_DSTATE_UDATA,
+ CCN_DSTATE_TAGNAME,
+ CCN_DSTATE_ATTRNAME,
+ CCN_DSTATE_BLOB,
+ /* All error states are negative */
+ CCN_DSTATE_ERR_OVERFLOW = -1,
+ CCN_DSTATE_ERR_ATTR = -2,
+ CCN_DSTATE_ERR_CODING = -3,
+ CCN_DSTATE_ERR_NEST = -4,
+ CCN_DSTATE_ERR_BUG = -5
+};
+
+/**
+ * If the CCN_DSTATE_PAUSE bit is set in the decoder state,
+ * the decoder will return just after recognizing each token.
+ * In this instance, use CCN_GET_TT_FROM_DSTATE() to extract
+ * the token type from the decoder state;
+ * CCN_CLOSE will be reported as CCN_NO_TOKEN.
+ * The pause bit persists, so the end test should take that into account
+ * by using the CCN_FINAL_DSTATE macro instead of testing for state 0.
+ */
+#define CCN_DSTATE_PAUSE (1 << 15)
+#define CCN_GET_TT_FROM_DSTATE(state) (CCN_TT_MASK & ((state) >> 16))
+#define CCN_FINAL_DSTATE(state) (((state) & (CCN_DSTATE_PAUSE-1)) == 0)
+
+ssize_t ccn_skeleton_decode(struct ccn_skeleton_decoder *d,
+ const unsigned char *p,
+ size_t n);
+
+#endif
+
diff --git a/model/ccn_indexbuf.cc b/model/ccn_indexbuf.cc
new file mode 100644
index 0000000..3d04e13
--- /dev/null
+++ b/model/ccn_indexbuf.cc
@@ -0,0 +1,236 @@
+/*
+ * ccn_indexbuf.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "ccn_indexbuf.h"
+
+/**
+ * @file ccn_indexbuf.c
+ * @brief Support for expandable buffer of non-negative values.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ELEMENT size_t
+
+/**
+ * Create a new indexbuf.
+ */
+struct ccn_indexbuf *
+ccn_indexbuf_create(void)
+{
+ struct ccn_indexbuf *c;
+ c = (ccn_indexbuf*)calloc(1, sizeof(*c));
+ return(c);
+}
+
+/**
+ * Deallocate indexbuf.
+ */
+void
+ccn_indexbuf_destroy(struct ccn_indexbuf **cbp)
+{
+ struct ccn_indexbuf *c = *cbp;
+ if (c != NULL) {
+ if (c->buf != NULL) {
+ free(c->buf);
+ }
+ free(c);
+ *cbp = NULL;
+ }
+}
+
+/**
+ * Expand buffer as necessary to hold at least n more values.
+ * @returns pointer to reserved space
+ */
+ELEMENT *
+ccn_indexbuf_reserve(struct ccn_indexbuf *c, size_t n)
+{
+ size_t newlim = n + c->n;
+ size_t oldlim = c->limit;
+ ELEMENT *buf = c->buf;
+ if (newlim < n)
+ return(NULL);
+ if (newlim > oldlim) {
+ if (2 * oldlim > newlim)
+ newlim = 2 * oldlim;
+ buf = (size_t*)realloc(c->buf, newlim * sizeof(ELEMENT));
+ if (buf == NULL)
+ return(NULL);
+ memset(buf + oldlim, 0, (newlim - oldlim) * sizeof(ELEMENT));
+ c->buf = buf;
+ c->limit = newlim;
+ }
+ buf += c->n;
+ return(buf);
+}
+
+/**
+ * Append multiple elements to the indexbuf.
+ * @returns 0 for success, -1 for failure.
+ */
+int
+ccn_indexbuf_append(struct ccn_indexbuf *c, const ELEMENT *p, size_t n)
+{
+ ELEMENT *dst = ccn_indexbuf_reserve(c, n);
+ if (dst == NULL)
+ return(-1);
+ memcpy(dst, p, n * sizeof(ELEMENT));
+ c->n += n;
+ return(0);
+}
+
+/**
+ * Append v to the indexbuf
+ * @returns 0 for success, -1 for failure.
+ */
+int
+ccn_indexbuf_append_element(struct ccn_indexbuf *c, ELEMENT v)
+{
+ ELEMENT *dst = ccn_indexbuf_reserve(c, 1);
+ if (dst == NULL)
+ return(-1);
+ *dst = v;
+ c->n += 1;
+ return(0);
+}
+
+/**
+ * @returns index at which the element was found or appended, or -1 if not found.
+ */
+int
+ccn_indexbuf_member(struct ccn_indexbuf *x, ELEMENT val)
+{
+ int i;
+ if (x == NULL)
+ return (-1);
+ for (i = x->n - 1; i >= 0; i--)
+ if (x->buf[i] == val)
+ return(i);
+ return(-1);
+}
+
+/**
+ * Removes up to one instance of val from the indexbuf.
+ * Order of elements not preserved.
+ */
+void
+ccn_indexbuf_remove_element(struct ccn_indexbuf *x, ELEMENT val)
+{
+ int i;
+ if (x == NULL) return;
+ for (i = x->n - 1; i >= 0; i--)
+ if (x->buf[i] == val) {
+ x->buf[i] = x->buf[--x->n]; /* move last element into vacant spot */
+ return;
+ }
+}
+
+/**
+ * @returns index at which the element was found or appended,
+ * or -1 in case of error.
+ */
+int
+ccn_indexbuf_set_insert(struct ccn_indexbuf *x, ELEMENT val)
+{
+ int i;
+ if (x == NULL)
+ return (-1);
+ for (i = 0; i < (int)x->n; i++)
+ if (x->buf[i] == val)
+ return(i);
+ if (ccn_indexbuf_append_element(x, val) < 0)
+ return(-1);
+ return(i);
+}
+
+/**
+ * Removes first occurrence of val, preserving order
+ * @returns index at which the element was found,
+ * or -1 if the element was not found.
+ */
+int
+ccn_indexbuf_remove_first_match(struct ccn_indexbuf *x, ELEMENT val)
+{
+ int i;
+ int n;
+ if (x == NULL)
+ return (-1);
+ for (i = 0, n = x->n; i < n; i++) {
+ if (x->buf[i] == val) {
+ if (i + 1 < n)
+ memmove(&(x->buf[i]),
+ &(x->buf[i + 1]),
+ sizeof(x->buf[i]) * (n - i - 1));
+ x->n--;
+ return(i);
+ }
+ }
+ return(-1);
+}
+
+/**
+ * If val is present in the indexbuf, move it to the final place.
+ */
+void
+ccn_indexbuf_move_to_end(struct ccn_indexbuf *x, ELEMENT val)
+{
+ int i;
+ int n;
+ if (x == NULL)
+ return;
+ for (i = 0, n = x->n; i + 1 < n; i++) {
+ if (x->buf[i] == val) {
+ memmove(&(x->buf[i]),
+ &(x->buf[i + 1]),
+ sizeof(x->buf[i]) * (n - i - 1));
+ x->buf[n - 1] = val;
+ return;
+ }
+ }
+}
+
+/**
+ * If val is present in the indexbuf, move it to the first place.
+ */
+void
+ccn_indexbuf_move_to_front(struct ccn_indexbuf *x, ELEMENT val)
+{
+ int i;
+ int n;
+ if (x == NULL)
+ return;
+ for (i = 0, n = x->n; i < n; i++) {
+ if (x->buf[i] == val) {
+ memmove(&(x->buf[1]),
+ &(x->buf[0]),
+ sizeof(x->buf[i]) * i);
+ x->buf[0] = val;
+ return;
+ }
+ }
+
+}
+
diff --git a/model/ccn_indexbuf.h b/model/ccn_indexbuf.h
new file mode 100644
index 0000000..369d466
--- /dev/null
+++ b/model/ccn_indexbuf.h
@@ -0,0 +1,54 @@
+/*
+ * ccn_indexbuf.h
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+/**
+ * @file ccn/indexbuf.h
+ *
+ * Expandable buffer of non-negative values.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CCN_INDEXBUF_DEFINED
+#define CCN_INDEXBUF_DEFINED
+
+#include <stddef.h>
+
+struct ccn_indexbuf {
+ size_t n;
+ size_t limit;
+ size_t *buf;
+};
+
+struct ccn_indexbuf *ccn_indexbuf_create(void);
+void ccn_indexbuf_destroy(struct ccn_indexbuf **cbp);
+size_t *ccn_indexbuf_reserve(struct ccn_indexbuf *c, size_t n);
+int ccn_indexbuf_append(struct ccn_indexbuf *c, const size_t *p, size_t n);
+int ccn_indexbuf_append_element(struct ccn_indexbuf *c, size_t v);
+int ccn_indexbuf_member(struct ccn_indexbuf *x, size_t val);
+void ccn_indexbuf_remove_element(struct ccn_indexbuf *x, size_t val);
+int ccn_indexbuf_set_insert(struct ccn_indexbuf *x, size_t val);
+int ccn_indexbuf_remove_first_match(struct ccn_indexbuf *x, size_t val);
+void ccn_indexbuf_move_to_end(struct ccn_indexbuf *x, size_t val);
+void ccn_indexbuf_move_to_front(struct ccn_indexbuf *x, size_t val);
+
+#endif
diff --git a/model/ccn_name_util.cc b/model/ccn_name_util.cc
new file mode 100644
index 0000000..18a3040
--- /dev/null
+++ b/model/ccn_name_util.cc
@@ -0,0 +1,315 @@
+/*
+ * ccn_name_util.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "ccn_name_util.h"
+#include "ccn_coding.h"
+#include "ccn_charbuf.h"
+#include "ccn_indexbuf.h"
+#include <string.h>
+#include <stdlib.h>
+#include "ccn_random.h"
+#include "ccn_ccn.h"
+
+/**
+ * @file ccn_name_util.c
+ * @brief Support for manipulating ccnb-encoded Names.
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2008-2010 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+//#include <ccn/ccn.h>
+
+/**
+ * Reset charbuf to represent an empty Name in binary format.
+ * @returns 0, or -1 for error.
+ */
+int
+ccn_name_init(struct ccn_charbuf *c)
+{
+ int res;
+ c->length = 0;
+ res = ccn_charbuf_append_tt(c, CCN_DTAG_Name, CCN_DTAG);
+ if (res == -1) return(res);
+ res = ccn_charbuf_append_closer(c);
+ return(res);
+}
+
+/**
+ * Add a Component to a Name.
+ *
+ * The component is an arbitrary string of n octets, no escaping required.
+ * @returns 0, or -1 for error.
+ */
+int
+ccn_name_append(struct ccn_charbuf *c, const void *component, size_t n)
+{
+ int res;
+ const unsigned char closer[2] = {CCN_CLOSE, CCN_CLOSE};
+ if (c->length < 2 || c->buf[c->length-1] != closer[1])
+ return(-1);
+ c->length -= 1;
+ ccn_charbuf_reserve(c, n + 8);
+ res = ccn_charbuf_append_tt(c, CCN_DTAG_Component, CCN_DTAG);
+ if (res == -1) return(res);
+ res = ccn_charbuf_append_tt(c, n, CCN_BLOB);
+ if (res == -1) return(res);
+ res = ccn_charbuf_append(c, component, n);
+ if (res == -1) return(res);
+ res = ccn_charbuf_append(c, closer, sizeof(closer));
+ return(res);
+}
+
+/**
+ * Add a Component that is a NUL-terminated string.
+ *
+ * The component added consists of the bytes of the string without the NUL.
+ * This function is convenient for those applications that construct
+ * component names from simple strings.
+ * @returns 0, or -1 for error.
+ */
+int
+ccn_name_append_str(struct ccn_charbuf *c, const char *s)
+{
+ return(ccn_name_append(c, s, strlen(s)));
+}
+
+/**
+ * Add a binary Component to a ccnb-encoded Name
+ *
+ * These are special components used for marking versions, fragments, etc.
+ * @returns 0, or -1 for error
+ * see doc/technical/NameConventions.html
+ */
+int
+ccn_name_append_numeric(struct ccn_charbuf *c,
+ enum ccn_marker marker, unsigned long long value)
+{
+ //uintmax_t v;
+ unsigned long long v;
+ int i;
+ char b[32];
+
+ for (v = value, i = sizeof(b); v != 0 && i > 0; i--, v >>= 8)
+ b[i-1] = v & 0xff;
+ if (i < 1)
+ return(-1);
+ if (marker >= 0)
+ b[--i] = marker;
+ return(ccn_name_append(c, b + i, sizeof(b) - i));
+}
+
+/**
+ * Add nonce Component to ccnb-encoded Name
+ *
+ * Uses %C1.N namespace.
+ * @returns 0, or -1 for error
+ * see doc/technical/NameConventions.html
+ */
+int
+ccn_name_append_nonce(struct ccn_charbuf *c)
+{
+ const unsigned char pre[4] = { CCN_MARKER_CONTROL, '.', 'N', 0 };
+ unsigned char b[15];
+
+ memcpy(b, pre, sizeof(pre));
+ ccn_random_bytes(b + sizeof(pre), sizeof(b) - sizeof(pre));
+ return(ccn_name_append(c, b, sizeof(b)));
+}
+
+/**
+ * Add sequence of ccnb-encoded Components to a ccnb-encoded Name.
+ *
+ * start and stop are offsets from ccnb
+ * @returns 0, or -1 for obvious error
+ */
+int
+ccn_name_append_components(struct ccn_charbuf *c,
+ const unsigned char *ccnb,
+ size_t start, size_t stop)
+{
+ int res;
+ if (c->length < 2 || start > stop)
+ return(-1);
+ c->length -= 1;
+ ccn_charbuf_reserve(c, stop - start + 1);
+ res = ccn_charbuf_append(c, ccnb + start, stop - start);
+ if (res == -1) return(res);
+ res = ccn_charbuf_append_closer(c);
+ return(res);
+}
+
+/**
+ * Extract a pointer to and size of component at
+ * given index i. The first component is index 0.
+ * @returns 0, or -1 for error.
+ */
+int
+ccn_name_comp_get(const unsigned char *data,
+ const struct ccn_indexbuf *indexbuf,
+ unsigned int i,
+ const unsigned char **comp, size_t *size)
+{
+ int len;
+ struct ccn_buf_decoder decoder;
+ struct ccn_buf_decoder *d;
+ /* indexbuf should have an extra value marking end of last component,
+ so we need to use last 2 values */
+ if (indexbuf->n < 2 || i > indexbuf->n - 2) {
+ /* There isn't a component at this index */
+ return(-1);
+ }
+ len = indexbuf->buf[i + 1]-indexbuf->buf[i];
+ d = ccn_buf_decoder_start(&decoder, data + indexbuf->buf[i], len);
+ if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
+ ccn_buf_advance(d);
+ if (ccn_buf_match_blob(d, comp, size))
+ return(0);
+ *comp = d->buf + d->decoder.index;
+ *size = 0;
+ ccn_buf_check_close(d);
+ if (d->decoder.state >= 0)
+ return(0);
+ }
+ return(-1);
+}
+
+int
+ccn_name_comp_strcmp(const unsigned char *data,
+ const struct ccn_indexbuf *indexbuf,
+ unsigned int i, const char *val)
+{
+ const unsigned char *comp_ptr;
+ size_t comp_size;
+
+ // XXX - We probably want somewhat different semantics in the API -
+ // comparing a string against a longer string with a 0 byte should
+ // not claim equality.
+ if (ccn_name_comp_get(data, indexbuf, i, &comp_ptr, &comp_size) == 0)
+ return(strncmp(val, (const char *)comp_ptr, comp_size));
+ /* Probably no such component, say query is greater-than */
+ return(1);
+}
+
+/**
+ * Find Component boundaries in a ccnb-encoded Name.
+ *
+ * Thin veneer over ccn_parse_Name().
+ * components arg may be NULL to just do a validity check
+ *
+ * @returns -1 for error, otherwise the number of Components.
+ */
+int
+ccn_name_split(const struct ccn_charbuf *c, struct ccn_indexbuf *components)
+{
+ struct ccn_buf_decoder decoder;
+ struct ccn_buf_decoder *d;
+ d = ccn_buf_decoder_start(&decoder, c->buf, c->length);
+ return(ccn_parse_Name(d, components));
+}
+
+/**
+ * Chop the name down to n components.
+ * @param c contains a ccnb-encoded Name
+ * @param components may be NULL; if provided it must be consistent with
+ * some prefix of the name, and is updated accordingly.
+ * @param n is the number or components to leave, or, if negative, specifies
+ * how many components to remove,
+ e.g. -1 will remove just the last component.
+ * @returns -1 for error, otherwise the new number of Components
+ */
+int
+ccn_name_chop(struct ccn_charbuf *c, struct ccn_indexbuf *components, int n)
+{
+ if (components == NULL) {
+ int res;
+ components = ccn_indexbuf_create();
+ if (components == NULL)
+ return(-1);
+ res = ccn_name_split(c, components);
+ if (res >= 0)
+ res = ccn_name_chop(c, components, n);
+ ccn_indexbuf_destroy(&components);
+ return(res);
+ }
+ /* Fix up components if needed. We could be a little smarter about this. */
+ if (components->n == 0 || components->buf[components->n-1] + 1 != c->length)
+ if (ccn_name_split(c, components) < 0)
+ return(-1);
+ if (n < 0)
+ n += (components->n - 1); /* APL-style indexing */
+ if (n < 0)
+ return(-1);
+ if (n < (int)(components->n)) {
+ c->length = components->buf[n];
+ ccn_charbuf_append_value(c, CCN_CLOSE, 1);
+ components->n = n + 1;
+ return(n);
+ }
+ return(-1);
+}
+
+/**
+ * Advance the last Component of a Name to the next possible value.
+ * @param c contains a ccnb-encoded Name to be updated.
+ * @returns -1 for error, otherwise the number of Components
+ */
+int
+ccn_name_next_sibling(struct ccn_charbuf *c)
+{
+ int res = -1;
+ struct ccn_indexbuf *ndx;
+ unsigned char *lastcomp = NULL;
+ size_t lastcompsize = 0;
+ size_t i;
+ int carry;
+ struct ccn_charbuf *newcomp;
+
+ ndx = ccn_indexbuf_create();
+ if (ndx == NULL) goto Finish;
+ res = ccn_name_split(c, ndx);
+ if (res <= 0) {
+ res = -1;
+ goto Finish;
+ }
+ res = ccn_ref_tagged_BLOB(CCN_DTAG_Component, c->buf,
+ ndx->buf[res-1], ndx->buf[res],
+ (const unsigned char **)&lastcomp,
+ &lastcompsize);
+ if (res < 0) goto Finish;
+ for (carry = 1, i = lastcompsize; carry && i > 0; i--) {
+ carry = (((++lastcomp[i-1]) & 0xFF) == 0x00);
+ }
+ if (carry) {
+ newcomp = ccn_charbuf_create();
+ res |= ccn_charbuf_append_value(newcomp, 0, 1);
+ res |= ccn_charbuf_append(newcomp, lastcomp, lastcompsize);
+ res |= ccn_name_chop(c, ndx, ndx->n - 2);
+ res |= ccn_name_append(c, newcomp->buf, newcomp->length);
+ ccn_charbuf_destroy(&newcomp);
+ if (res < 0) goto Finish;
+ }
+ res = ndx->n - 1;
+Finish:
+ ccn_indexbuf_destroy(&ndx);
+ return(res);
+}
+
diff --git a/model/ccn_name_util.h b/model/ccn_name_util.h
new file mode 100644
index 0000000..a22f266
--- /dev/null
+++ b/model/ccn_name_util.h
@@ -0,0 +1,9 @@
+/*
+ * ccn_name_util.h
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
diff --git a/model/ccn_random.cc b/model/ccn_random.cc
new file mode 100644
index 0000000..10912e5
--- /dev/null
+++ b/model/ccn_random.cc
@@ -0,0 +1,48 @@
+/*
+ * ccn_random.cc
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "ccn_random.h"
+#include <openssl/rand.h>
+//#include <openssl/rand.c>
+
+/**
+ * Generate pseudo-random bytes.
+ *
+ * @param buf is the destination buffer
+ * @param size is in bytes
+ */
+void
+ccn_random_bytes(unsigned char *buf, size_t size)
+{
+ int num = size;
+
+ if (num < 0 || num != (int)size)
+ abort();
+ RAND_bytes(buf, num);
+}
+
+/**
+ * Feed some entropy to the random number generator.
+ *
+ * @param buf is the source buffer
+ * @param size is in bytes
+ * @param bits_of_entropy is an estimate; use 0 to make me guess
+ */
+void
+ccn_add_entropy(const void *buf, size_t size, int bits_of_entropy)
+{
+ int num = size;
+
+ if (num < 0 || num != (int)size)
+ abort();
+ /* Supply a hopefully conservative estimate of entropy. */
+ if (bits_of_entropy <= 0)
+ bits_of_entropy = (num < 32) ? 1 : num / 32;
+ RAND_add((unsigned char *)buf, num, bits_of_entropy * 0.125);
+}
diff --git a/model/ccn_random.h b/model/ccn_random.h
new file mode 100644
index 0000000..5a576c0
--- /dev/null
+++ b/model/ccn_random.h
@@ -0,0 +1,39 @@
+/*
+ * ccn_random.h
+ * Abstraction
+ *
+ * Created by Ilya on 7/29/11.
+ * Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+/**
+ * @file random.h
+ * @brief Pseudo-random number generation
+ *
+ * Part of the CCNx C Library.
+ *
+ * Copyright (C) 2010 Palo Alto Research Center, Inc.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received
+ * a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CCN_RANDOM_DEFINED
+#define CCN_RANDOM_DEFINED
+
+#include <stddef.h>
+#include <openssl/rand.h>
+
+void ccn_random_bytes(unsigned char *buf, size_t size);
+void ccn_add_entropy(const void *buf, size_t size, int bits_of_entropy);
+
+#endif