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(&timestring[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