forked from cawka/ndn.cxx
diff --git a/ndn-cpp/common.h b/ndn-cpp/common.h
new file mode 100644
index 0000000..e45f067
--- /dev/null
+++ b/ndn-cpp/common.h
@@ -0,0 +1,221 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_COMMON_H
+#define NDN_COMMON_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+namespace ndn
+{
+template<class T>
+struct Ptr : public boost::shared_ptr<T>
+{
+  Ptr () { }
+  Ptr (boost::shared_ptr<T> ptr) : boost::shared_ptr<T>(ptr) { }
+  Ptr (T *ptr) :  boost::shared_ptr<T>(ptr) { }
+
+  template<class Y>
+  Ptr & operator = (boost::shared_ptr<Y> ptr)
+  {
+    boost::static_pointer_cast<T> (ptr).swap (*this);
+    // *this = boost::static_pointer_cast<T> (ptr);
+    return *this;
+  }
+
+  operator Ptr<const T> () const { return *this; }
+
+  static Ptr
+  Create () { return boost::make_shared<T> (); }
+};
+
+typedef boost::posix_time::ptime Time;
+typedef boost::posix_time::time_duration TimeInterval;
+
+namespace time
+{
+inline TimeInterval Seconds (int secs) { return boost::posix_time::seconds (secs); }
+inline TimeInterval Milliseconds (int msecs) { return boost::posix_time::milliseconds (msecs); }
+inline TimeInterval Microseconds (int musecs) { return boost::posix_time::microseconds (musecs); }
+
+inline TimeInterval Seconds (double fractionalSeconds)
+{
+  double seconds, microseconds;
+  seconds = std::modf (fractionalSeconds, &microseconds);
+  microseconds *= 1000000;
+
+  return time::Seconds((int)seconds) + time::Microseconds((int)microseconds);
+}
+
+inline Time Now () { return boost::posix_time::microsec_clock::universal_time (); }
+
+const Time UNIX_EPOCH_TIME = Time (boost::gregorian::date (1970, boost::gregorian::Jan, 1));
+inline TimeInterval NowUnixTimestamp ()
+{
+  return TimeInterval (time::Now () - UNIX_EPOCH_TIME);
+}
+} // time
+} // ndn
+
+
+extern "C" {
+#include <ccn/ccn.h>
+#include <ccn/charbuf.h>
+#include <ccn/keystore.h>
+#include <ccn/uri.h>
+#include <ccn/bloom.h>
+#include <ccn/signing.h>
+}
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/exception/all.hpp>
+#include <boost/function.hpp>
+#include <string>
+#include <sstream>
+#include <map>
+#include <utility>
+#include <string.h>
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/make_shared.hpp>
+
+namespace ndn {
+typedef std::vector<unsigned char> Bytes;
+typedef std::vector<std::string>Comps;
+
+typedef boost::shared_ptr<Bytes> BytesPtr;
+
+inline
+const unsigned char *
+head(const Bytes &bytes)
+{
+  return &bytes[0];
+}
+
+inline
+unsigned char *
+head (Bytes &bytes)
+{
+  return &bytes[0];
+}
+
+// --- Bytes operations start ---
+inline void
+readRaw(Bytes &bytes, const unsigned char *src, size_t len)
+{
+  if (len > 0)
+  {
+    bytes.resize(len);
+    memcpy (head (bytes), src, len);
+  }
+}
+
+inline BytesPtr
+readRawPtr (const unsigned char *src, size_t len)
+{
+  if (len > 0)
+    {
+      BytesPtr ret (new Bytes (len));
+      memcpy (head (*ret), src, len);
+
+      return ret;
+    }
+  else
+    return BytesPtr ();
+}
+
+template<class Msg>
+BytesPtr
+serializeMsg(const Msg &msg)
+{
+  int size = msg.ByteSize ();
+  BytesPtr bytes (new Bytes (size));
+  msg.SerializeToArray (head(*bytes), size);
+  return bytes;
+}
+
+template<class Msg>
+boost::shared_ptr<Msg>
+deserializeMsg (const Bytes &bytes)
+{
+  boost::shared_ptr<Msg> retval (new Msg ());
+  if (!retval->ParseFromArray (head (bytes), bytes.size ()))
+    {
+      // to indicate an error
+      return boost::shared_ptr<Msg> ();
+    }
+  return retval;
+}
+
+template<class Msg>
+boost::shared_ptr<Msg>
+deserializeMsg (const void *buf, size_t length)
+{
+  boost::shared_ptr<Msg> retval (new Msg ());
+  if (!retval->ParseFromArray (buf, length))
+    {
+      // to indicate an error
+      return boost::shared_ptr<Msg> ();
+    }
+  return retval;
+}
+
+
+template<class Msg>
+BytesPtr
+serializeGZipMsg(const Msg &msg)
+{
+  std::vector<char> bytes;   // Bytes couldn't work
+  {
+    boost::iostreams::filtering_ostream out;
+    out.push(boost::iostreams::gzip_compressor()); // gzip filter
+    out.push(boost::iostreams::back_inserter(bytes)); // back_inserter sink
+
+    msg.SerializeToOstream(&out);
+  }
+  BytesPtr uBytes = boost::make_shared<Bytes>(bytes.size());
+  memcpy(&(*uBytes)[0], &bytes[0], bytes.size());
+  return uBytes;
+}
+
+template<class Msg>
+boost::shared_ptr<Msg>
+deserializeGZipMsg(const Bytes &bytes)
+{
+  std::vector<char> sBytes(bytes.size());
+  memcpy(&sBytes[0], &bytes[0], bytes.size());
+  boost::iostreams::filtering_istream in;
+  in.push(boost::iostreams::gzip_decompressor()); // gzip filter
+  in.push(boost::make_iterator_range(sBytes)); // source
+
+  boost::shared_ptr<Msg> retval = boost::make_shared<Msg>();
+  if (!retval->ParseFromIstream(&in))
+    {
+      // to indicate an error
+      return boost::shared_ptr<Msg> ();
+    }
+
+  return retval;
+}
+
+
+// --- Bytes operations end ---
+
+// Exceptions
+typedef boost::error_info<struct tag_errmsg, std::string> error_info_str;
+
+} // ndn
+#endif // NDN_COMMON_H
diff --git a/ndn-cpp/data.cc b/ndn-cpp/data.cc
new file mode 100644
index 0000000..5a44da8
--- /dev/null
+++ b/ndn-cpp/data.cc
@@ -0,0 +1,23 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "data.h"
+
+namespace ndn {
+
+Data::Data ()
+{
+}
+
+Data::~Data ()
+{
+}
+
+} // namespace ndn
diff --git a/ndn-cpp/data.h b/ndn-cpp/data.h
new file mode 100644
index 0000000..212dfbd
--- /dev/null
+++ b/ndn-cpp/data.h
@@ -0,0 +1,204 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_DATA_H
+#define NDN_DATA_H
+
+#include "ndn-cpp/fields/name.h"
+#include "ndn-cpp/fields/content.h"
+#include "ndn-cpp/fields/signature.h"
+#include "ndn-cpp/fields/signed-blob.h"
+
+namespace ndn {
+
+/**
+ * @brief Class implementing abstractions to work with NDN Data packets
+ */
+class Data
+{
+public:
+  /**
+   * @brief Create an empty Data with empty payload
+   **/
+  Data ();
+
+  /**
+   * @brief Destructor
+   */
+  ~Data ();
+
+  /**
+   * @brief Set data packet name
+   * @param name name of the data packet
+   * @return reference to self (to allow method chaining)
+   *
+   * In some cases, a direct access to and manipulation of name using getName is more efficient
+   */
+  inline Data &
+  setName (const Name &name);
+
+  /**
+   * @brief Get data packet name (const reference)
+   * @returns name of the data packet
+   */
+  inline const Name &
+  getName () const;
+
+  /**
+   * @brief Get data packet name (reference)
+   * @returns name of the data packet
+   */
+  inline Name &
+  getName ();
+
+  /**
+   * @brief Get const smart pointer to signature object
+   */
+  inline Ptr<const Signature>
+  getSignature () const;
+
+  /**
+   * @brief Get smart pointer to signature object
+   */
+  inline Ptr<Signature>
+  getSignature ();
+
+  /**
+   * @brief Set signature object
+   * @param signature smart pointer to a signature object
+   */
+  inline void
+  setSignature (Ptr<Signature> sigature);
+
+  /**
+   * @brief Get const reference to content object (content info + actual content)
+   */
+  inline const Content &
+  getContent () const;
+
+  /**
+   * @brief Get reference to content object (content info + actual content)
+   */
+  inline Content &
+  getContent ();
+
+  /**
+   * @brief Set content object (content info + actual content)
+   * @param content reference to a content object
+   *
+   * More efficient way (that avoids copying):
+   * @code
+   * Content content (...);
+   * getContent ().swap (content);
+   * @endcode
+   */
+  inline void
+  setContent (const Content &content);
+
+  /**
+   * @brief A helper method to directly access actual content data (const reference)
+   *
+   * This method is equivalent to
+   * @code
+   * getContent ().getContent ()
+   * @endcode
+   */
+  inline const Blob &
+  content () const;
+
+  /**
+   * @brief A helper method to directly access actual content data (reference)
+   *
+   * This method is equivalent to
+   * @code
+   * getContent ().getContent ()
+   * @endcode
+   */
+  inline Blob &
+  content ();
+
+private:
+  Name m_name;
+  Ptr<Signature> m_signature; // signature with its parameters "binds" name and content
+  Content m_content;
+
+  Ptr<SignedBlob> m_wire;  
+};
+
+inline Data &
+Data::setName (const Name &name)
+{
+  m_name = name;
+  return *this;
+}
+
+inline const Name &
+Data::getName () const
+{
+  return m_name;
+}
+
+inline Name &
+Data::getName ()
+{
+  return m_name;
+}
+
+inline Ptr<const Signature>
+Data::getSignature () const
+{
+  return m_signature;
+}
+
+inline Ptr<Signature>
+Data::getSignature ()
+{
+  return m_signature;
+}
+
+inline void
+Data::setSignature (Ptr<Signature> signature)
+{
+  m_signature = signature;
+}
+
+inline const Content &
+Data::getContent () const
+{
+  return m_content;
+}
+
+inline Content &
+Data::getContent ()
+{
+  return m_content;
+}
+
+inline void
+Data::setContent (const Content &content)
+{
+  m_content = content;
+}
+
+inline const Blob &
+Data::content () const
+{
+  return getContent ().getContent ();
+}
+
+inline Blob &
+Data::content ()
+{
+  return getContent ().getContent ();
+}
+
+} // namespace ndn
+
+#endif // NDN_DATA_H
diff --git a/ndn-cpp/error.h b/ndn-cpp/error.h
new file mode 100644
index 0000000..d6379c6
--- /dev/null
+++ b/ndn-cpp/error.h
@@ -0,0 +1,119 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+/**
+ * @file error.h
+ * @brief This file defines basic elements for the library reporting
+ *
+ * The library throws a number of exceptions.
+ * In general, the following example shows how to print out diagnostic information
+ * when one of the exceptions is thrown
+ * @code
+ *     try
+ *       {
+ *         ... operations with ndn::Name
+ *       }
+ *     catch (boost::exception &e)
+ *       {
+ *         std::cerr << boost::diagnostic_information (e) << std::endl;
+ *       }
+ * @endcode
+ */
+
+#ifndef NDN_ERROR_H
+#define NDN_ERROR_H
+
+#include <boost/exception/all.hpp>
+
+namespace ndn
+{
+namespace error
+{
+
+struct Error           : public virtual boost::exception, public virtual std::exception {}; ///< @brief Some error with error reporting engine
+struct Uri             : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with URI processing
+struct StringTransform : public virtual boost::exception, public virtual std::exception {};
+struct Name            : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with Name
+namespace name {
+struct Component       : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with name::Component
+}
+struct Exclude         : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with Exclude
+struct KeyLocator      : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with KeyLocator
+namespace wire {
+struct Ccnb            : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with wire::Ccnb encoding
+}
+struct Keychain        : public virtual boost::exception, public virtual std::exception {}; ///< @brief An error with security::Keychain
+
+// Diagnostic information fields
+
+/**
+ * @brief Free-formatted text message explaining the error
+ *
+ * @code
+ * ...
+ * catch (boost::exception &e)
+ * {
+ *     if (const std::string *error = boost::get_error_info<error::msg> (e))
+ *          ...
+ * }
+ * @endcode
+ *
+ * @see get_msg
+ */
+typedef boost::error_info<struct tag_msg, std::string> msg;
+
+/**
+ * @brief Helper method to get error message from the exception
+ *
+ * Method assumes that message is present, if not, an exception will be thrown
+ */
+inline const std::string &
+get_msg (boost::exception &e)
+{
+  const std::string *error = boost::get_error_info<msg> (e);
+  if (error == 0)
+    BOOST_THROW_EXCEPTION (Error ());
+  return *error;
+}
+
+/**
+ * @brief Report of the position of the error (error-specific meaning)
+ *
+ * @code
+ * ...
+ * catch (boost::exception &e)
+ * {
+ *     if (const int *error = boost::get_error_info<error::pos> (e))
+ *          ...
+ * }
+ * @endcode
+ *
+ * @see get_pos
+ */
+typedef boost::error_info<struct tag_pos, int> pos;
+
+/**
+ * @brief Helper method to get position of the error from the exception
+ *
+ * Method assumes that position is present, if not, an exception will be thrown
+ */
+inline int
+get_pos (boost::exception &e)
+{
+  const int *position = boost::get_error_info<pos> (e);
+  if (position == 0)
+    BOOST_THROW_EXCEPTION (Error ());
+  return *position;
+}
+
+} // error
+} // ndn
+
+#endif // NDN_ERROR_H
diff --git a/ndn-cpp/face.cc b/ndn-cpp/face.cc
new file mode 100644
index 0000000..455f283
--- /dev/null
+++ b/ndn-cpp/face.cc
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "face.h"
+
+namespace ndn {
+
+Face::sent_interest
+Face::sendInterest (Ptr<const Interest> interest, const SatisfiedInterestCallback &dataCallback)
+{
+  // magic to be done in child class
+
+  sent_interest item = m_sentInterests.find_exact (interest->getName ());
+  if (item == m_sentInterests.end ())
+    {
+      std::pair<sent_interest, bool> insertRes =
+        m_sentInterests.insert (interest->getName (), Ptr<sent_interest_container::payload_traits::payload_type>::Create ());
+
+      item = insertRes.first;
+    }
+  item->payload ()->push_back (dataCallback);
+
+  return item;
+}
+
+void
+Face::clearInterest (Face::sent_interest interest)
+{
+  m_sentInterests.erase (interest);
+}
+  
+Face::registered_prefix
+Face::setInterestFilter (Ptr<const Name> prefix, const ExpectedInterestCallback &interestCallback)
+{
+  // magic to be done in child class
+  
+  registered_prefix item = m_registeredPrefixes.find_exact (*prefix);
+  if (item == m_registeredPrefixes.end ())
+    {
+      std::pair<registered_prefix, bool> insertRes =
+        m_registeredPrefixes.insert (*prefix, Ptr<registered_prefix_container::payload_traits::payload_type>::Create ());
+
+      item = insertRes.first;
+    }
+  item->payload ()->push_back (interestCallback);
+
+  return item;
+}
+
+void
+Face::clearInterestFilter (const Name &prefix)
+{
+  registered_prefix item = m_registeredPrefixes.find_exact (prefix);
+  if (item == m_registeredPrefixes.end ())
+    return;
+
+  clearInterestFilter (item);
+}
+
+void
+Face::clearInterestFilter (Face::registered_prefix filter)
+{
+  m_registeredPrefixes.erase (filter);
+}
+
+} // ndn
+
+// void
+// CcnxWrapper::OnInterest (const Ptr<const ndn::Interest> &interest, Ptr<Packet> packet)
+// {
+//   ndn::App::OnInterest (interest, packet);
+
+//   // the app cannot set several filters for the same prefix
+//   CcnxFilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.longest_prefix_match (interest->GetName ());
+//   if (entry == m_interestCallbacks.end ())
+//     {
+//       _LOG_DEBUG ("No Interest callback set");
+//       return;
+//     }
+  
+//   entry->payload ()->m_callback (lexical_cast<string> (interest->GetName ()));  
+// }
+
+// void
+// CcnxWrapper::OnContentObject (const Ptr<const ndn::ContentObject> &contentObject,
+//                               Ptr<Packet> payload)
+// {
+//   ndn::App::OnContentObject (contentObject, payload);
+//   NS_LOG_DEBUG ("<< D " << contentObject->GetName ());
+
+//   CcnxFilterEntryContainer<RawDataCallback>::iterator entry = m_dataCallbacks.longest_prefix_match (contentObject->GetName ());
+//   if (entry == m_dataCallbacks.end ())
+//     {
+//       _LOG_DEBUG ("No Data callback set");
+//       return;
+//     }
+
+//   while (entry != m_dataCallbacks.end ())
+//     {
+//       ostringstream content;
+//       payload->CopyData (&content, payload->GetSize ());
+  
+//       entry->payload ()->m_callback (lexical_cast<string> (contentObject->GetName ()), content.str ().c_str (), content.str ().size ());
+  
+//       m_dataCallbacks.erase (entry);
+
+//       entry = m_dataCallbacks.longest_prefix_match (contentObject->GetName ());
+//     }
+// }
+
+// }
diff --git a/ndn-cpp/face.h b/ndn-cpp/face.h
new file mode 100644
index 0000000..38a618c
--- /dev/null
+++ b/ndn-cpp/face.h
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_CXX_H
+#define NDN_CXX_H
+
+#include "ndn-cpp/common.h"
+#include "ndn-cpp/fields/name.h"
+#include "ndn-cpp/interest.h"
+#include "ndn-cpp/data.h"
+
+#include "trie/trie-with-policy.h"
+#include "trie/policies/counting-policy.h"
+
+#include <list>
+
+namespace ndn {
+
+template<class Callback>
+struct CallbackTable :
+    public trie::trie_with_policy< Name,
+                                   trie::ptr_payload_traits< std::list<Callback> >,
+                                   trie::counting_policy_traits >
+{
+};
+
+
+class Face
+{
+public:
+  typedef boost::function<void (Ptr<Data> incomingData, Ptr<const Interest> satisfiedInterest)> SatisfiedInterestCallback;
+  typedef boost::function<void (Ptr<Interest> incomingInterest, Ptr<const Name> registeredPrefix)> ExpectedInterestCallback;
+
+  // some internal definitions
+  typedef CallbackTable< SatisfiedInterestCallback > sent_interest_container;
+  typedef CallbackTable< ExpectedInterestCallback >  registered_prefix_container;
+
+  typedef sent_interest_container::iterator sent_interest;
+  typedef registered_prefix_container::iterator registered_prefix;
+  
+  sent_interest
+  sendInterest (Ptr<const Interest> interest, const SatisfiedInterestCallback &dataCallback);
+
+  void
+  clearInterest (sent_interest interest);
+  
+  registered_prefix
+  setInterestFilter (Ptr<const Name> prefix, const ExpectedInterestCallback &interestCallback);
+
+  void
+  clearInterestFilter (const Name &prefix);
+
+  void
+  clearInterestFilter (registered_prefix filter);
+  
+private:
+  sent_interest_container m_sentInterests;
+  registered_prefix_container m_registeredPrefixes;
+};
+
+} // ndn
+
+#endif // NDN_CXX_H
diff --git a/ndn-cpp/fields/blob.h b/ndn-cpp/fields/blob.h
new file mode 100644
index 0000000..85fd71b
--- /dev/null
+++ b/ndn-cpp/fields/blob.h
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_BLOB_H
+#define NDN_BLOB_H
+
+#include <vector>
+#include <cstddef>
+
+namespace ndn {
+
+/**
+ * @brief Class representing a general-use binary blob
+ */
+class Blob : public std::vector<char>
+{
+public:
+  /**
+   * @brief Creates an empty blob
+   */
+  Blob ()
+  {
+  }
+
+  Blob (const void *buf, size_t length)
+    : std::vector<char> (reinterpret_cast<const char*> (buf), reinterpret_cast<const char*> (buf) + length)
+  {
+  }
+  
+  /**
+   * @brief Get pointer to the first byte of the binary blob
+   */
+  inline char*
+  buf ()
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get const pointer to the first byte of the binary blob
+   */
+  inline const char*
+  buf () const
+  {
+    return &front ();
+  }
+};
+
+} // ndn
+
+#endif // NDN_BLOB_H
diff --git a/ndn-cpp/fields/content.cc b/ndn-cpp/fields/content.cc
new file mode 100644
index 0000000..0216bd2
--- /dev/null
+++ b/ndn-cpp/fields/content.cc
@@ -0,0 +1,53 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "content.h"
+#include "ndn-cpp/error.h"
+
+namespace ndn
+{
+
+const name::Component Content::noFinalBlock = name::Component ();
+const TimeInterval Content::noFreshness;
+const TimeInterval Content::maxFreshness = time::Seconds (2147);
+
+Content::Content ()
+{
+}
+
+Content::Content (const void *buffer, size_t size,
+                  const Time &timestamp,
+                  Type type/* = DATA*/,
+                  const TimeInterval &freshness/* = maxFreshness*/,
+                  const name::Component &finalBlock/* = noFinalBlock*/)
+  : m_timestamp (timestamp)
+  , m_type (type)
+  , m_freshness (freshness)
+  , m_finalBlockId (finalBlock)
+
+  , m_content (buffer, size)
+{
+}
+
+Content::Content (const void *buffer, size_t size,
+                  Type type/* = DATA*/,
+                  const TimeInterval &freshness/* = maxFreshness*/,
+                  const name::Component &finalBlock/* = noFinalBlock*/)
+  : m_timestamp (time::Now ())
+  , m_type (type)
+  , m_freshness (freshness)
+  , m_finalBlockId (finalBlock)
+
+  , m_content (buffer, size)
+{
+}
+
+
+} // ndn
diff --git a/ndn-cpp/fields/content.h b/ndn-cpp/fields/content.h
new file mode 100644
index 0000000..752f24c
--- /dev/null
+++ b/ndn-cpp/fields/content.h
@@ -0,0 +1,306 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_CONTENT_H
+#define NDN_CONTENT_H
+
+#include "ndn-cpp/common.h"
+#include "ndn-cpp/fields/blob.h"
+#include "ndn-cpp/fields/name-component.h"
+
+namespace ndn {
+
+/**
+ * @brief Class providing an interface to work with content NDN data packets
+ *
+ * Content of data packets consists of two parts: information about content
+ * (timestamp, freshness, type, etc.) and raw content itself
+ *
+ * @code
+ * Content ::= ContentInfo
+ *             ContentData
+ *
+ * ContentInfo ::= Timestamp
+ *                 Type?
+ *                 Freshness?
+ *                 FinalBlockID?
+ * @endcode
+ */
+class Content
+{
+public:
+  /**
+   * @brief Enum of content types
+   */
+  enum Type
+    {
+      DATA = 0, ///< @brief No semantics is defined for the content
+      ENCR,     ///< @brief Indicate that the content is encrypted
+      GONE,     ///< @brief ?
+      KEY,      ///< @brief Content is a key object
+      LINK,     ///< @brief Content contains a LINK object
+      NACK      ///< @brief Negative acknowledgment by the content producer, indicating that there is no data with the requested name
+    };
+
+  /**
+   * @brief Create an empty content
+   */
+  Content ();
+
+  /**
+   * @brief Create a content from a memory buffer
+   * @param buffer pointer to first byte of the memory buffer
+   * @param size size of the memory buffer
+   * @param timestamp content generation timestamp
+   * @param type type of content (default is Content::DATA)
+   * @param freshness amount of time the content is considered "fresh" (default is 2147 seconds, maximum possible value for CCNx)
+   * @param finalBlock name of the final DATA
+   *
+   * Use the other version of the constructor, if timestamp needs to be automatically generated
+   */
+  Content (const void *buffer, size_t size,
+           const Time &timestamp,
+           Type type = DATA,
+           const TimeInterval &freshness = maxFreshness,
+           const name::Component &finalBlock = noFinalBlock);
+
+  /**
+   * @brief Create a content from a memory buffer
+   * @param buffer pointer to first byte of the memory buffer
+   * @param size size of the memory buffer
+   * @param type type of content (default is Content::DATA)
+   * @param freshness amount of time the content is considered "fresh" (default is 2147 seconds, maximum possible value for CCNx)
+   * @param finalBlock name of the final DATA
+   *
+   * This method automatically sets timestamp of the created content to the current time (UTC clock)
+   */
+  Content (const void *buffer, size_t size,
+           Type type = DATA,
+           const TimeInterval &freshness = maxFreshness,
+           const name::Component &finalBlock = noFinalBlock);
+
+  /**
+   * @brief Get content timestamp (const reference)
+   */
+  inline const Time &
+  getTimestamp () const;
+
+  /**
+   * @brief Get content timestamp (reference)
+   */
+  inline Time &
+  getTimestamp ();
+
+  /**
+   * @brief Set content timestamp
+   * @param timestamp content timestamp (default is empty ptime object)
+   *
+   * If parameter is omitted, then the current time (UTC clock) is used
+   */
+  inline void
+  setTimeStamp (const Time &timestamp = Time ());
+
+  /**
+   * @brief Get type of content
+   */
+  inline Type
+  getType () const;
+
+  /**
+   * @brief Set type of content
+   * @param type content type @see Content::Type
+   */
+  inline void
+  setType (Type type);
+
+  /**
+   * @brief Get content freshness (const reference)
+   */
+  inline const TimeInterval &
+  getFreshness () const;
+
+  /**
+   * @brief Get content freshness (reference)
+   */
+  inline TimeInterval &
+  getFreshness ();
+
+  /**
+   * @brief Set content freshness
+   * @param freshness content freshness (default value is Content::maxFreshness = 2147 seconds)
+   */
+  inline void
+  setFreshness (const TimeInterval &freshness = maxFreshness);
+
+  /**
+   * @brief Get final block ID of the content (const reference)
+   */
+  inline const name::Component &
+  getFinalBlockId () const;
+
+  /**
+   * @brief Get final block ID of the content (reference)
+   */
+  inline name::Component &
+  getFinalBlockId ();
+
+  /**
+   * @brief Set final block ID of the content
+   * @param finalBlock component name of the final block
+   */
+  inline void
+  setFinalBlockId (const name::Component &finalBlock);
+
+  /**
+   * @brief Get const reference to content bits
+   */
+  inline const Blob &
+  getContent () const;
+
+  /**
+   * @brief Get reference to content bits
+   */
+  inline Blob &
+  getContent ();
+
+  /**
+   * @brief Set content bits from blob
+   * @param content blob that holds content bits
+   *
+   * In certain cases, getContent ().swap (content); is more appropriate,
+   * since it would avoid object copying
+   */
+  inline void
+  setContent (const Blob &content);
+
+  /**
+   * @brief Set content bits from memory buffer
+   * @param buf pointer to first byte of memory buffer
+   * @param length size of memory buffer
+   */
+  inline void
+  setContent (const void *buf, size_t length);
+
+public:
+  static const name::Component noFinalBlock; ///< @brief Not a final block == name::Component ()
+  static const TimeInterval noFreshness; ///< @brief Minimum freshness == seconds (0)
+  static const TimeInterval maxFreshness; ///< @brief Maximum freshnes == seconds (2147)
+
+private:
+  // ContentInfo
+  Time m_timestamp;
+  Type m_type;
+  TimeInterval m_freshness;
+  name::Component m_finalBlockId;
+
+  // ContentData
+  Blob m_content;
+};
+
+inline const Time &
+Content::getTimestamp () const
+{
+  return m_timestamp;
+}
+
+inline Time &
+Content::getTimestamp ()
+{
+  return m_timestamp;
+}
+
+inline void
+Content::setTimeStamp (const Time &timestamp/* = Time ()*/)
+{
+  if (timestamp != Time ())
+    {
+      m_timestamp = timestamp;
+    }
+  else
+    {
+      m_timestamp = time::Now ();
+    }
+}
+
+inline Content::Type
+Content::getType () const
+{
+  return m_type;
+}
+
+inline void
+Content::setType (Content::Type type)
+{
+  m_type = type;
+}
+
+inline const TimeInterval &
+Content::getFreshness () const
+{
+  return m_freshness;
+}
+
+inline TimeInterval &
+Content::getFreshness ()
+{
+  return m_freshness;
+}
+
+inline void
+Content::setFreshness (const TimeInterval &freshness/* = Content::maxFreshness*/)
+{
+  m_freshness = freshness;
+}
+
+inline const name::Component &
+Content::getFinalBlockId () const
+{
+  return m_finalBlockId;
+}
+
+inline name::Component &
+Content::getFinalBlockId ()
+{
+  return m_finalBlockId;
+}
+
+inline void
+Content::setFinalBlockId (const name::Component &finalBlock)
+{
+  m_finalBlockId = finalBlock;
+}
+
+inline const Blob &
+Content::getContent () const
+{
+  return m_content;
+}
+
+inline Blob &
+Content::getContent ()
+{
+  return m_content;
+}
+
+inline void
+Content::setContent (const Blob &content)
+{
+  m_content = content;
+}
+
+inline void
+Content::setContent (const void *buf, size_t length)
+{
+  Blob (buf, length).swap (m_content);
+}
+
+} // ndn
+
+#endif // NDN_SIGNATURE_H
diff --git a/ndn-cpp/fields/exclude.cc b/ndn-cpp/fields/exclude.cc
new file mode 100644
index 0000000..b637c01
--- /dev/null
+++ b/ndn-cpp/fields/exclude.cc
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "exclude.h"
+
+#include "ndn-cpp/error.h"
+
+namespace ndn
+{
+
+Exclude::Exclude ()
+{
+}
+
+// example: ANY /b /d ANY /f
+//
+// ordered in map as:
+//
+// /f (false); /d (true); /b (false); / (true)
+//
+// lower_bound (/)  -> / (true) <-- excluded (equal)
+// lower_bound (/a) -> / (true) <-- excluded (any)
+// lower_bound (/b) -> /b (false) <--- excluded (equal)
+// lower_bound (/c) -> /b (false) <--- not excluded (not equal and no ANY)
+// lower_bound (/d) -> /d (true) <- excluded
+// lower_bound (/e) -> /d (true) <- excluded
+bool
+Exclude::isExcluded (const name::Component &comp) const
+{
+  const_iterator lowerBound = m_exclude.lower_bound (comp);
+  if (lowerBound == end ())
+    return false;
+
+  if (lowerBound->second)
+    return true;
+  else
+    return lowerBound->first == comp;
+
+  return false;
+}
+
+Exclude &
+Exclude::excludeOne (const name::Component &comp)
+{
+  if (!isExcluded (comp))
+    {
+      m_exclude.insert (std::make_pair (comp, false));
+    }
+  return *this;
+}
+
+
+// example: ANY /b0 /d0 ANY /f0
+//
+// ordered in map as:
+//
+// /f0 (false); /d0 (true); /b0 (false); / (true)
+//
+// lower_bound (/)  -> / (true) <-- excluded (equal)
+// lower_bound (/a0) -> / (true) <-- excluded (any)
+// lower_bound (/b0) -> /b0 (false) <--- excluded (equal)
+// lower_bound (/c0) -> /b0 (false) <--- not excluded (not equal and no ANY)
+// lower_bound (/d0) -> /d0 (true) <- excluded
+// lower_bound (/e0) -> /d0 (true) <- excluded
+
+
+// examples with desired outcomes
+// excludeRange (/, /f0) ->  ANY /f0
+//                          /f0 (false); / (true)
+// excludeRange (/, /f1) ->  ANY /f1
+//                          /f1 (false); / (true)
+// excludeRange (/a0, /e0) ->  ANY /f0
+//                          /f0 (false); / (true)
+// excludeRange (/a0, /e0) ->  ANY /f0
+//                          /f0 (false); / (true)
+
+// excludeRange (/b1, /c0) ->  ANY /b0 /b1 ANY /c0 /d0 ANY /f0
+//                          /f0 (false); /d0 (true); /c0 (false); /b1 (true); /b0 (false); / (true)
+
+Exclude &
+Exclude::excludeRange (const name::Component &from, const name::Component &to)
+{
+  if (from >= to)
+    {
+      BOOST_THROW_EXCEPTION (error::Exclude ()
+                             << error::msg ("Invalid exclude range (for single name exclude use Exclude::excludeOne)")
+                             << error::msg (from.toUri ())
+                             << error::msg (to.toUri ()));
+    }
+
+  iterator newFrom = m_exclude.lower_bound (from);
+  if (newFrom == end () || !newFrom->second /*without ANY*/)
+    {
+      std::pair<iterator, bool> fromResult = m_exclude.insert (std::make_pair (from, true));
+      newFrom = fromResult.first;
+      if (!fromResult.second)
+        {
+          // this means that the lower bound is equal to the item itself. So, just update ANY flag
+          newFrom->second = true;
+        }
+    }
+  // else
+  // nothing special if start of the range already exists with ANY flag set
+
+  iterator newTo = m_exclude.lower_bound (to); // !newTo cannot be end ()
+  if (newTo == newFrom || !newTo->second)
+    {
+      std::pair<iterator, bool> toResult = m_exclude.insert (std::make_pair (to, false));
+      newTo = toResult.first;
+      ++ newTo;
+    }
+  else
+    {
+      // nothing to do really
+    }
+
+  m_exclude.erase (newTo, newFrom); // remove any intermediate node, since all of the are excluded
+
+  return *this;
+}
+
+Exclude &
+Exclude::excludeAfter (const name::Component &from)
+{
+  iterator newFrom = m_exclude.lower_bound (from);
+  if (newFrom == end () || !newFrom->second /*without ANY*/)
+    {
+      std::pair<iterator, bool> fromResult = m_exclude.insert (std::make_pair (from, true));
+      newFrom = fromResult.first;
+      if (!fromResult.second)
+        {
+          // this means that the lower bound is equal to the item itself. So, just update ANY flag
+          newFrom->second = true;
+        }
+    }
+  // else
+  // nothing special if start of the range already exists with ANY flag set
+
+  if (newFrom != m_exclude.begin ())
+    {
+      m_exclude.erase (m_exclude.begin (), newFrom); // remove any intermediate node, since all of the are excluded
+    }
+
+  return *this;
+}
+
+
+std::ostream&
+operator << (std::ostream &os, const Exclude &exclude)
+{
+  for (Exclude::const_reverse_iterator i = exclude.rbegin (); i != exclude.rend (); i++)
+    {
+      os << i->first.toUri () << " ";
+      if (i->second)
+        os << "----> ";
+    }
+  return os;
+}
+
+
+} // ndn
diff --git a/ndn-cpp/fields/exclude.h b/ndn-cpp/fields/exclude.h
new file mode 100644
index 0000000..265a809
--- /dev/null
+++ b/ndn-cpp/fields/exclude.h
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_EXCLUDE_H
+#define NDN_EXCLUDE_H
+
+#include "ndn-cpp/fields/name-component.h"
+
+#include <map>
+
+namespace ndn {
+
+/**
+ * @brief Class to represent Exclude component in NDN interests
+ */
+class Exclude
+{
+public:
+  typedef std::map< name::Component, bool /*any*/, std::greater<name::Component> > exclude_type;
+
+  typedef exclude_type::iterator iterator;
+  typedef exclude_type::const_iterator const_iterator;
+  typedef exclude_type::reverse_iterator reverse_iterator;
+  typedef exclude_type::const_reverse_iterator const_reverse_iterator;
+
+  /**
+   * @brief Default constructor an empty exclude
+   */
+  Exclude ();
+
+  /**
+   * @brief Check if name component is excluded
+   * @param comp Name component to check against exclude filter
+   */
+  bool
+  isExcluded (const name::Component &comp) const;
+
+  /**
+   * @brief Exclude specific name component
+   * @param comp component to exclude
+   * @returns *this to allow chaining
+   */
+  Exclude &
+  excludeOne (const name::Component &comp);
+
+  /**
+   * @brief Exclude components from range [from, to]
+   * @param from first element of the range
+   * @param to last element of the range
+   * @returns *this to allow chaining
+   */
+  Exclude &
+  excludeRange (const name::Component &from, const name::Component &to);
+
+  /**
+   * @brief Exclude all components from range [/, to]
+   * @param to last element of the range
+   * @returns *this to allow chaining
+   */
+  inline Exclude &
+  excludeBefore (const name::Component &to);
+
+  /**
+   * @brief Exclude all components from range [from, +Inf]
+   * @param to last element of the range
+   * @returns *this to allow chaining
+   */
+  Exclude &
+  excludeAfter (const name::Component &from);
+
+  /**
+   * @brief Method to directly append exclude element
+   * @param name excluded name component
+   * @param any  flag indicating if there is a postfix ANY component after the name
+   *
+   * This method is used during conversion from wire format of exclude filter
+   *
+   * If there is an error with ranges (e.g., order of components is wrong) an exception is thrown
+   */
+  void
+  appendExclude (const name::Component &name, bool any);
+
+  /**
+   * @brief Get number of exclude terms
+   */
+  inline size_t
+  size () const;
+
+  /**
+   * @brief Get begin iterator of the exclude terms
+   */
+  inline const_iterator
+  begin () const;
+
+  /**
+   * @brief Get end iterator of the exclude terms
+   */
+  inline const_iterator
+  end () const;
+
+  /**
+   * @brief Get begin iterator of the exclude terms
+   */
+  inline const_reverse_iterator
+  rbegin () const;
+
+  /**
+   * @brief Get end iterator of the exclude terms
+   */
+  inline const_reverse_iterator
+  rend () const;
+
+private:
+  Exclude &
+  excludeRange (iterator fromLowerBound, iterator toLowerBound);
+
+private:
+  exclude_type m_exclude;
+};
+
+std::ostream&
+operator << (std::ostream &os, const Exclude &name);
+
+inline Exclude &
+Exclude::excludeBefore (const name::Component &to)
+{
+  return excludeRange (name::Component (), to);
+}
+
+inline size_t
+Exclude::size () const
+{
+  return m_exclude.size ();
+}
+
+inline Exclude::const_iterator
+Exclude::begin () const
+{
+  return m_exclude.begin ();
+}
+
+inline Exclude::const_iterator
+Exclude::end () const
+{
+  return m_exclude.end ();
+}
+
+inline Exclude::const_reverse_iterator
+Exclude::rbegin () const
+{
+  return m_exclude.rbegin ();
+}
+
+inline Exclude::const_reverse_iterator
+Exclude::rend () const
+{
+  return m_exclude.rend ();
+}
+
+} // ndn
+
+#endif // NDN_EXCLUDE_H
diff --git a/ndn-cpp/fields/key-locator.cc b/ndn-cpp/fields/key-locator.cc
new file mode 100644
index 0000000..84fd60c
--- /dev/null
+++ b/ndn-cpp/fields/key-locator.cc
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "key-locator.h"
+#include "ndn-cpp/error.h"
+
+namespace ndn {
+
+KeyLocator::KeyLocator ()
+  : m_type (NOTSET)
+  , m_data (0)
+{
+}
+
+KeyLocator::KeyLocator (const KeyLocator &keyLocator)
+  : m_type (keyLocator.getType ())
+  , m_data (0)
+{
+  switch (m_type)
+    {
+    case NOTSET:
+      break;
+    case KEY:
+      m_data = new Blob (keyLocator.getKey ());
+      break;
+    case CERTIFICATE:
+      m_data = new Blob (keyLocator.getCertificate ());
+      break;
+    case KEYNAME:
+      m_data = new Name (keyLocator.getKeyName ());
+      break;
+    }
+}
+
+KeyLocator::~KeyLocator ()
+{
+  deleteData ();
+}
+
+KeyLocator &
+KeyLocator::operator = (const KeyLocator &keyLocator)
+{
+  if (this == &keyLocator)
+    return *this;
+
+  deleteData ();
+  m_type = keyLocator.getType ();
+  
+  switch (m_type)
+    {
+    case NOTSET:
+      break;
+    case KEY:
+      m_data = new Blob (keyLocator.getKey ());
+      break;
+    case CERTIFICATE:
+      m_data = new Blob (keyLocator.getCertificate ());
+      break;
+    case KEYNAME:
+      m_data = new Name (keyLocator.getKeyName ());
+      break;
+    }
+
+  return *this;
+}
+
+void
+KeyLocator::deleteData ()
+{
+  switch (m_type)
+    {
+    case NOTSET: // nothing to clean up
+      break;
+    case KEY:
+      delete reinterpret_cast<Blob*> (m_data);
+      break;
+    case CERTIFICATE:
+      delete reinterpret_cast<Blob*> (m_data);
+      break;
+    case KEYNAME:
+      delete reinterpret_cast<Name*> (m_data);
+      break;
+    }
+}
+
+void
+KeyLocator::setType (KeyLocator::Type type)
+{
+  if (m_type == type)
+    return;
+
+  deleteData ();
+  m_type = type;
+  
+  switch (m_type)
+    {
+    case NOTSET:
+      m_data = 0;
+    case KEY:
+      m_data = new Blob;
+      break;
+    case CERTIFICATE:
+      m_data = new Blob;
+      break;
+    case KEYNAME:
+      m_data = new Name;
+      break;
+    }
+}
+
+const Blob &
+KeyLocator::getKey () const
+{
+  if (m_type != KEY)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("getKey called, but KeyLocator is not of type KeyLocator::KEY"));
+  return *reinterpret_cast<const Blob*> (m_data);
+}
+
+Blob &
+KeyLocator::getKey ()
+{
+  if (m_type != KEY)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("getKey called, but KeyLocator is not of type KeyLocator::KEY"));
+  return *reinterpret_cast<Blob*> (m_data);
+}
+
+void
+KeyLocator::setKey (const Blob &key)
+{
+  if (m_type != KEY)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("setKey called, but KeyLocator is not of type KeyLocator::KEY"));
+  *reinterpret_cast<Blob*> (m_data) = key;
+}
+
+const Blob &
+KeyLocator::getCertificate () const
+{
+  if (m_type != CERTIFICATE)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("getCertificate called, but KeyLocator is not of type KeyLocator::CERTIFICATE"));
+  return *reinterpret_cast<const Blob*> (m_data);
+}
+
+Blob &
+KeyLocator::getCertificate ()
+{
+  if (m_type != CERTIFICATE)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("getCertificate called, but KeyLocator is not of type KeyLocator::CERTIFICATE"));
+  return *reinterpret_cast<Blob*> (m_data);
+}
+
+void
+KeyLocator::setCertificate (const Blob &certificate)
+{
+  if (m_type != CERTIFICATE)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("setCertificate called, but KeyLocator is not of type KeyLocator::CERTIFICATE"));
+  *reinterpret_cast<Blob*> (m_data) = certificate;
+}
+
+const Name &
+KeyLocator::getKeyName () const
+{
+  if (m_type != KEYNAME)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("getKeyName called, but KeyLocator is not of type KeyLocator::KEYNAME"));
+  return *reinterpret_cast<const Name*> (m_data);
+}
+
+Name &
+KeyLocator::getKeyName ()
+{
+  if (m_type != KEYNAME)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("getKeyName called, but KeyLocator is not of type KeyLocator::KEYNAME"));
+  return *reinterpret_cast<Name*> (m_data);
+}
+
+
+void
+KeyLocator::setKeyName (const Name &name)
+{
+  if (m_type != KEYNAME)
+    BOOST_THROW_EXCEPTION (error::KeyLocator ()
+                           << error::msg ("setKeyName called, but KeyLocator is not of type KeyLocator::KEYNAME"));
+  *reinterpret_cast<Name*> (m_data) = name;
+}
+
+}
diff --git a/ndn-cpp/fields/key-locator.h b/ndn-cpp/fields/key-locator.h
new file mode 100644
index 0000000..cf1c6ea
--- /dev/null
+++ b/ndn-cpp/fields/key-locator.h
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_KEY_LOCATOR_H
+#define NDN_KEY_LOCATOR_H
+
+#include "ndn-cpp/fields/blob.h"
+#include "ndn-cpp/fields/name.h"
+
+namespace ndn {
+
+/**
+ * @brief Class providing an interface to work with key locators in NDN data packets
+ */
+class KeyLocator
+{
+public:
+  /**
+   * @brief Key locator type
+   *
+   * Key locator can be only of the defined types, i.e., it cannot contain key bits and key name
+   */
+  enum Type
+    {
+      NOTSET=-1,   ///< @brief Unset key locator type, any attempt to use KeyLocator of NOTSET type will cause an exception
+      KEY,         ///< @brief Key locator contains key bits
+      CERTIFICATE, ///< @brief Key locator contains certificate bits
+      KEYNAME      ///< @brief key locator contains name of the key
+    };
+
+  /**
+   * @brief Default constructor
+   */
+  KeyLocator ();
+
+  /**
+   * @brief Copy constructor
+   */
+  KeyLocator (const KeyLocator &keyLocator);
+  
+  /**
+   * @brief Destructor
+   */
+  ~KeyLocator ();
+
+  /**
+   * @brief Copy operator
+   */
+  KeyLocator &
+  operator = (const KeyLocator &keyLocator);
+  
+  /**
+   * @brief Set type of the key locator
+   * @param type key locator type, @see Type
+   *
+   * If type of the key locator changes, setType will delete any previously allocated
+   * data, allocate appropriate type and store it in m_data
+   */
+  void
+  setType (Type type);
+
+  /**
+   * @brief Get type of the key locator
+   */
+  inline Type
+  getType () const;
+
+  /**
+   * @brief Get const reference to key bits, associated with key locator
+   *
+   * If key locator type is not KEY, then an exception will be thrown
+   */
+  const Blob &
+  getKey () const;
+
+  /**
+   * @brief Get reference to key bits, associated with key locator
+   *
+   * If key locator type is not KEY, then an exception will be thrown
+   */
+  Blob &
+  getKey ();
+
+  /**
+   * @brief Set key bits, associated with key locator
+   * @param key const reference to key bits
+   *
+   * If key locator type is not KEY, then an exception will be thrown
+   */
+  void
+  setKey (const Blob &key);
+
+  /**
+   * @brief Get const reference to certificated bits, associated with key locator
+   *
+   * If key locator type is not CERTIFICATE, then an exception will be thrown
+   */
+  const Blob &
+  getCertificate () const;
+
+  /**
+   * @brief Get reference to certificated bits, associated with key locator
+   *
+   * If key locator type is not CERTIFICATE, then an exception will be thrown
+   */
+  Blob &
+  getCertificate ();
+
+  /**
+   * @brief Set certificated bits, associated with key locator
+   * @param certificate const reference to certificate bits
+   *
+   * If key locator type is not CERTIFICATE, then an exception will be thrown
+   */
+  void
+  setCertificate (const Blob &certificate);
+
+  /**
+   * @brief Get const reference to key name, associated with key locator
+   *
+   * If key locator type is not KEYNAME, then an exception will be thrown
+   */
+  const Name &
+  getKeyName () const;
+
+  /**
+   * @brief Get reference to key name, associated with key locator
+   *
+   * If key locator type is not KEYNAME, then an exception will be thrown
+   */
+  Name &
+  getKeyName ();
+
+  /**
+   * @brief Set key name, associated with key locator
+   * @param name const reference to key name
+   *
+   * If key locator type is not KEYNAME, then an exception will be thrown
+   */
+  void
+  setKeyName (const Name &name);
+
+private:
+  void
+  deleteData ();
+  
+private:
+  Type m_type;
+  void *m_data;
+};
+
+inline KeyLocator::Type
+KeyLocator::getType () const
+{
+  return m_type;
+}
+
+
+} // ndn
+
+#endif // NDN_KEY_LOCATOR_H
diff --git a/ndn-cpp/fields/name-component.cc b/ndn-cpp/fields/name-component.cc
new file mode 100644
index 0000000..ecc87b1
--- /dev/null
+++ b/ndn-cpp/fields/name-component.cc
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "name-component.h"
+
+#include "ndn-cpp/error.h"
+#include "ndn-cpp/helpers/uri.h"
+
+using namespace std;
+
+namespace ndn
+{
+namespace name
+{
+  
+Component::Component ()
+{
+}
+
+Component::Component (const std::string &uri)
+{
+  try
+    {
+      Uri::fromEscaped (uri.begin (), uri.end (), back_inserter (*this));
+    }
+  catch (error::Uri &err)
+    {
+      // re-throwing different exception
+      BOOST_THROW_EXCEPTION (error::name::Component ()
+                             << error::msg (uri)
+                             << error::pos (error::get_pos (err)));
+    }
+}
+
+Component::Component (std::string::const_iterator begin, std::string::const_iterator end)
+{
+  try
+    {
+      Uri::fromEscaped (begin, end, back_inserter (*this));
+    }
+  catch (error::Uri &err)
+    {
+      // re-throwing different exception
+      BOOST_THROW_EXCEPTION (error::name::Component ()
+                             << error::msg (string (begin, end))
+                             << error::pos (error::get_pos (err)));
+    }
+}
+
+Component::Component (const void *buf, size_t length)
+{
+  copy (static_cast<const char*> (buf),
+        static_cast<const char*> (buf)+length,
+        back_inserter (*this));
+}
+
+int
+Component::compare (const Component &other) const
+{
+  if (size () < other.size ())
+    return -1;
+
+  if (size () > other.size ())
+    return +1;
+
+  // now we know that sizes are equal
+
+  pair<const_iterator, const_iterator> diff = mismatch (begin (), end (), other.begin ());
+  if (diff.first == end ()) // components are actually equal
+    return 0;
+
+  return (std::lexicographical_compare (diff.first, end (), diff.second, other.end ())) ? -1 : +1;    
+}
+
+Component
+Component::fromNumber (uint64_t number)
+{
+  Component comp;
+  while (number > 0)
+    {
+      comp.push_back (static_cast<unsigned char> (number & 0xFF));
+      number >>= 8;
+    }
+  std::reverse (comp.begin (), comp.end ());
+  return comp;
+}
+
+Component
+Component::fromNumberWithMarker (uint64_t number, unsigned char marker)
+{
+  Component comp;
+  comp.push_back (marker);
+
+  while (number > 0)
+    {
+      comp.push_back (static_cast<unsigned char> (number & 0xFF));
+      number >>= 8;
+    }
+
+  std::reverse (comp.begin () + 1, comp.end ());
+  return comp;
+}
+
+std::string
+Component::toBlob () const
+{
+  return std::string (begin (), end ());
+}
+
+void
+Component::toBlob (std::ostream &os) const
+{
+  os.write (buf (), size ());
+}
+
+std::string
+Component::toUri () const
+{
+  ostringstream os;
+  toUri (os);
+  return os.str ();  
+}
+
+void
+Component::toUri (std::ostream &os) const
+{
+  Uri::toEscaped (begin (), end (), ostream_iterator<char> (os));
+}
+
+uint64_t
+Component::toNumber () const
+{
+  uint64_t ret = 0;
+  for (const_iterator i = begin (); i != end (); i++)
+    {
+      ret <<= 8;
+      ret |= static_cast<unsigned char> (*i);
+    }
+  return ret;
+}
+
+uint64_t
+Component::toNumberWithMarker (unsigned char marker) const
+{
+  if (empty () ||
+      static_cast<unsigned char> (*(begin ())) != marker)
+    {
+      BOOST_THROW_EXCEPTION (error::name::Component ()
+                             << error::msg ("Name component does not have required marker [" + toUri () + "]"));
+    }
+
+  uint64_t ret = 0;
+  for (const_iterator i = begin () + 1; i != end (); i++)
+    {
+      ret <<= 8;
+      ret |= static_cast<unsigned char> (*i);
+    }
+  return ret;
+}
+
+
+} // name
+} // ndn
diff --git a/ndn-cpp/fields/name-component.h b/ndn-cpp/fields/name-component.h
new file mode 100644
index 0000000..0bcf862
--- /dev/null
+++ b/ndn-cpp/fields/name-component.h
@@ -0,0 +1,282 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_NAME_COMPONENT_H
+#define NDN_NAME_COMPONENT_H
+
+#include <string>
+#include <vector>
+
+#include "blob.h"
+#include <stdint.h>
+
+namespace ndn {
+
+namespace name {
+
+/**
+ * @brief Class to representing binary blob of NDN name component
+ *
+ * This class is based on std::vector<char> and just provides several helpers
+ * to work with name components, as well as operator to apply canonical
+ * ordering on name components
+ */
+class Component : public Blob
+{
+public:
+  /**
+   * @brief Default constructor an empty exclude
+   */
+  Component ();
+
+  /**
+   * @brief Create component from URI encoded string
+   * @param uri URI encoded name component (convert escaped with % characters)
+   */
+  Component (const std::string &uri);
+
+  /**
+   * @brief Create component from URI encoded string, with string specified by a pair of iterators
+   * @param begin begin iterator pointing to the URI encoded name
+   * @param end end iterator
+   */
+  Component (std::string::const_iterator begin, std::string::const_iterator end);
+  
+  /**
+   * @brief Create component using a binary blob
+   * @param buf pointer to first byte of binary blob to store as a name component
+   * @param length length of the binary blob
+   */
+  Component (const void *buf, size_t length);
+
+  /**
+   * @brief Apply canonical ordering on component comparison
+   * @return 0  They compare equal
+   *         <0 If *this comes before other in the canonical ordering
+   *         >0 If *this comes after in the canonical ordering
+   *
+   * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+   */
+  int
+  compare (const Component &other) const;
+  
+  /**
+   * @brief Apply canonical ordering on component comparison (less or equal)
+   *
+   * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+   */
+  inline bool
+  operator <= (const Component &other) const;
+
+  /**
+   * @brief Apply canonical ordering on component comparison (less)
+   *
+   * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+   */
+  inline bool
+  operator < (const Component &other) const;
+
+  /**
+   * @brief Apply canonical ordering on component comparison (greater or equal)
+   *
+   * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+   */
+  inline bool
+  operator >= (const Component &other) const;
+
+  /**
+   * @brief Apply canonical ordering on component comparison (greater)
+   *
+   * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+   */
+  inline bool
+  operator > (const Component &other) const;
+
+  ////////////////////////////////////
+  // Component construction helpers //
+  ////////////////////////////////////
+
+  /**
+   * @brief Create network-ordered numeric component
+   *
+   * @param number number to be encoded and added as a component
+   *
+   * Number is encoded and added in network order. Tail zero-bytes are not included.
+   * For example, if the number is 1, then 1-byte binary blob will be added  0x01.
+   * If the number is 256, then 2 binary blob will be added: 0x01 0x01
+   *
+   * If the number is zero, an empty component will be created
+   */
+  static Component
+  fromNumber (uint64_t number);
+
+  /**
+   * @brief Create network-ordered numeric component to the name with marker
+   *
+   * @param number number to be encoded and added as a component
+   * @param marker byte marker, specified by the desired naming convention
+   *
+   * Currently defined naming conventions of the marker:
+   * - 0x00  sequence number
+   * - 0xC1  control number
+   * - 0xFB  block id
+   * - 0xFD  version number
+   *
+   * This version is almost exactly as appendNumber, with exception that it adds initial marker.
+   * The number is formatted in the exactly the same way.
+   *
+   * @see fromNumber
+   */
+  static Component
+  fromNumberWithMarker (uint64_t number, unsigned char marker);
+  
+  //////////////////////////////////////////////////////////////////////////////////
+  // helpers
+  //////////////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * @brief Convert binary blob name component to std::string (no conversion is made)
+   * @param comp name component to be converted
+   * @see asUriString
+   */  
+  std::string
+  toBlob () const;
+
+  /**
+   * @brief Write blob of the name component to the specified output stream
+   * @param os output stream
+   */
+  void
+  toBlob (std::ostream &os) const;
+
+  /**
+   * @brief Convert binary blob name component to std::string, escaping all non-printable characters in URI format
+   * @param comp name component to be converted
+   * @see asString
+   */
+  std::string
+  toUri () const;
+
+  /**
+   * @brief Write name as URI to the specified output stream
+   * @param os output stream
+   */
+  void
+  toUri (std::ostream &os) const;
+  
+  /**
+   * @brief Convert binary blob name component (network-ordered number) to number
+   * @param comp name component to be converted
+   */  
+  uint64_t
+  toNumber () const;
+
+  /**
+   * @brief Convert binary blob name component (network-ordered number) to number, using appropriate marker from the naming convention
+   * @param comp name component to be converted
+   * @param marker required marker from the naming convention
+   *
+   * If the required marker does not exist, an exception will be thrown
+   */  
+  uint64_t
+  toNumberWithMarker (unsigned char marker) const;
+
+  /**
+   * @brief Convert binary blob name component, assuming sequence number naming convention (marker = 0x00)
+   * @param comp name component to be converted
+   * @see asNumberWithMarker
+   */
+  inline uint64_t
+  toSeqNum () const;
+  
+  /**
+   * @brief Convert binary blob name component, assuming control number naming convention (marker = 0xC1)
+   * @param comp name component to be converted
+   * @see asNumberWithMarker
+   */
+  inline uint64_t
+  toControlNum () const;
+
+  /**
+   * @brief Convert binary blob name component, assuming block ID naming convention (marker = 0xFB)
+   * @param comp name component to be converted
+   * @see asNumberWithMarker
+   */
+  inline uint64_t
+  toBlkId () const;
+
+  /**
+   * @brief Convert binary blob name component, assuming time-stamping version naming convention (marker = 0xFD)
+   * @param comp name component to be converted
+   * @see asNumberWithMarker
+   */
+  inline uint64_t
+  toVersion () const;
+};
+
+bool
+Component::operator <= (const Component &other) const
+{
+  return (compare (other) <= 0);
+}
+
+bool
+Component::operator < (const Component &other) const
+{
+  return (compare (other) < 0);
+}
+
+bool
+Component::operator >= (const Component &other) const
+{
+  return (compare (other) >= 0);
+}
+
+bool
+Component::operator > (const Component &other) const
+{
+  return (compare (other) > 0);
+}
+
+inline uint64_t
+Component::toSeqNum () const
+{
+  return toNumberWithMarker (0x00);
+}
+  
+inline uint64_t
+Component::toControlNum () const
+{
+  return toNumberWithMarker (0xC1);
+}
+
+inline uint64_t
+Component::toBlkId () const
+{
+  return toNumberWithMarker (0xFB);
+}
+
+inline uint64_t
+Component::toVersion () const
+{
+  return toNumberWithMarker (0xFD);
+}
+
+/**
+ * @brief Stream output operator (output in escaped URI format)
+ */
+std::ostream&
+operator <<(std::ostream &os, const Component &name);
+
+} // name
+
+} // ndn
+
+#endif // NDN_EXCLUDE_H
diff --git a/ndn-cpp/fields/name.cc b/ndn-cpp/fields/name.cc
new file mode 100644
index 0000000..d3e2ec6
--- /dev/null
+++ b/ndn-cpp/fields/name.cc
@@ -0,0 +1,264 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "name.h"
+
+#include "ndn-cpp/error.h"
+#include <boost/algorithm/string.hpp>
+
+#include <ctype.h>
+
+using namespace std;
+
+namespace ndn
+{
+
+///////////////////////////////////////////////////////////////////////////////
+//                              CONSTRUCTORS                                 //
+///////////////////////////////////////////////////////////////////////////////
+
+Name::Name ()
+{
+}
+
+Name::Name (const string &uri)
+{ 
+  string::const_iterator i = uri.begin ();
+  string::const_iterator end = uri.end ();
+
+  string::const_iterator firstSlash = std::find (i, end, '/');
+  if (firstSlash == end)
+    {
+      BOOST_THROW_EXCEPTION (error::Name ()
+                             << error::msg ("Name should include at least one slash (did you forget to specify initial /?)"));
+    }
+
+  if (firstSlash != i)
+    {
+      string schema (i, firstSlash);
+      if (*schema.rbegin () != ':')
+        {
+          BOOST_THROW_EXCEPTION (error::Name ()
+                                 << error::msg ("First component of the name does not start with a slash (did you forget to specify initial /?)"));
+        }
+
+      i = firstSlash;
+
+      if (!boost::iequals (schema, "ccnx:") &&
+          !boost::iequals (schema, "ndn:"))
+        {
+          BOOST_THROW_EXCEPTION (error::Name ()
+                                 << error::msg ("URI schema is not supported (only ccnx: or ndn: is allowed)")
+                                 << error::msg (schema));
+        }
+    }
+
+  string::const_iterator secondSlash = i;
+  secondSlash ++;
+  if (secondSlash != end && *secondSlash == '/')
+    {
+      // The authority component (the part after the initial "//" in the familiar http and ftp URI schemes) is present,
+      // but it is not relevant to NDN name.
+      // skipping it
+      secondSlash ++;
+      i = std::find (secondSlash, end, '/');
+    }
+  
+  if (i == end)
+    {
+      BOOST_THROW_EXCEPTION (error::Name ()
+                             << error::msg ("Invalid URI")
+                             << error::msg (uri));
+    }
+
+  while (i != end)
+    {
+      // skip any extra slashes
+      while (i != end && *i == '/')
+        {
+          i ++;
+        }
+      if (i == end)
+        break;
+      
+      string::const_iterator endOfComponent = std::find (i, end, '/');
+      append (name::Component (i, endOfComponent));
+
+      i = endOfComponent;
+    }
+}
+
+Name::Name (const Name &other)
+{
+  m_comps = other.m_comps;
+}
+
+Name &
+Name::operator= (const Name &other)
+{
+  m_comps = other.m_comps;
+  return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                SETTERS                                    //
+///////////////////////////////////////////////////////////////////////////////
+
+Name &
+Name::appendVersion (uint64_t version/* = Name::nversion*/)
+{
+  if (version != Name::nversion)
+    return appendNumberWithMarker (version, 0xFD);
+  else
+    {
+      TimeInterval now = time::NowUnixTimestamp ();
+      version = (now.total_seconds () << 12) | (0xFFF & (now.fractional_seconds () / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
+      return appendNumberWithMarker (version, 0xFD);
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//                                GETTERS                                    //
+///////////////////////////////////////////////////////////////////////////////
+
+const name::Component &
+Name::get (int index) const
+{
+  if (index < 0)
+    {
+      index = size () - (-index);
+    }
+
+  if (static_cast<unsigned int> (index) >= size ())
+    {
+      BOOST_THROW_EXCEPTION (error::Name ()
+                             << error::msg ("Index out of range")
+                             << error::pos (index));
+    }
+  return m_comps [index];
+}
+
+name::Component &
+Name::get (int index)
+{
+  if (index < 0)
+    {
+      index = size () - (-index);
+    }
+
+  if (static_cast<unsigned int> (index) >= size())
+    {
+      BOOST_THROW_EXCEPTION (error::Name ()
+                             << error::msg ("Index out of range")
+                             << error::pos (index));
+    }
+  return m_comps [index];
+}
+
+
+/////
+///// Static helpers to convert name component to appropriate value
+/////
+
+
+Name
+Name::getSubName (size_t pos/* = 0*/, size_t len/* = Name::npos*/) const
+{
+  Name retval;
+
+  if (len == npos)
+    {
+      len = size () - pos;
+    }
+
+  if (pos + len > size ())
+    {
+      BOOST_THROW_EXCEPTION (error::Name ()
+                             << error::msg ("getSubName parameter out of range")
+                             << error::pos (pos)
+                             << error::pos (len));
+    }
+
+  for (size_t i = pos; i < pos + len; i++)
+    {
+      retval.append (get (i));
+    }
+
+  return retval;
+}
+
+Name
+Name::operator+ (const Name &name) const
+{
+  Name newName;
+  newName
+    .append (*this)
+    .append (name);
+
+  return newName;
+}
+
+std::string
+Name::toUri () const
+{
+  ostringstream os;
+  toUri (os);
+  return os.str ();
+}
+
+void
+Name::toUri (std::ostream &os) const
+{
+  for (Name::const_iterator comp = begin (); comp != end (); comp++)
+    {
+      os << "/";
+      comp->toUri (os);
+    }
+  if (size () == 0)
+    os << "/";
+}
+
+// ostream &
+// operator << (ostream &os, const Name &name)
+// {
+//   for (Name::const_iterator comp = name.begin (); comp != name.end (); comp++)
+//     {
+//       os << "/" << *comp;
+//     }
+//   if (name.size () == 0)
+//     os << "/";
+//   return os;
+// }
+
+int
+Name::compare (const Name &name) const
+{
+  Name::const_iterator i = this->begin ();
+  Name::const_iterator j = name.begin ();
+
+  for (; i != this->end () && j != name.end (); i++, j++)
+    {
+      int res = i->compare (*j);
+      if (res == 0)
+        continue;
+      else
+        return res;
+    }
+
+  if (i == this->end () && j == name.end ())
+    return 0; // prefixes are equal
+
+  return (i == this->end ()) ? -1 : +1;
+}
+
+} // ndn
diff --git a/ndn-cpp/fields/name.h b/ndn-cpp/fields/name.h
new file mode 100644
index 0000000..18e2412
--- /dev/null
+++ b/ndn-cpp/fields/name.h
@@ -0,0 +1,637 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#ifndef NDN_NAME_H
+#define NDN_NAME_H
+
+#include "ndn-cpp/fields/name-component.h"
+#include "ndn-cpp/common.h"
+
+namespace ndn {
+
+/**
+ * @brief Class for NDN Name
+ */
+class Name
+{
+public:
+  typedef std::vector<name::Component>::iterator iterator;
+  typedef std::vector<name::Component>::const_iterator const_iterator;
+  typedef std::vector<name::Component>::reverse_iterator reverse_iterator;
+  typedef std::vector<name::Component>::const_reverse_iterator const_reverse_iterator;
+  typedef std::vector<name::Component>::reference reference;
+  typedef std::vector<name::Component>::const_reference const_reference;
+
+  typedef name::Component partial_type;
+  
+  ///////////////////////////////////////////////////////////////////////////////
+  //                              CONSTRUCTORS                                 //
+  ///////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Default constructor to create an empty name (zero components, or "/")
+   */
+  Name ();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @param other reference to a NDN name object
+   */
+  Name (const Name &other);
+
+  /**
+   * @brief Create a name from URL string
+   *
+   * @param url URI-represented name
+   */
+  Name (const std::string &url);
+
+  /**
+   * @brief Create a name from a container of elements [begin, end)
+   *
+   * @param begin begin iterator of the container
+   * @param end end iterator of the container
+   */
+  template<class Iterator>
+  Name (Iterator begin, Iterator end);
+
+  /**
+   * @brief Assignment operator
+   */
+  Name &
+  operator= (const Name &other);
+
+
+  ///////////////////////////////////////////////////////////////////////////////
+  //                                SETTERS                                    //
+  ///////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Append a binary blob as a name component
+   *
+   * @param comp a binary blob
+   * @returns reference to self (to allow chaining of append methods)
+   */
+  inline Name &
+  append (const name::Component &comp);
+
+  /**
+   * @brief Append a binary blob as a name component
+   * @param comp a binary blob
+   *
+   * This version is a little bit more efficient, since it swaps contents of comp and newly added component
+   *
+   * Attention!!! This method has an intended side effect: content of comp becomes empty
+   */
+  inline Name &
+  appendBySwap (name::Component &comp);
+  
+  /**
+   * @brief Append components a container of elements [begin, end)
+   *
+   * @param begin begin iterator of the container
+   * @param end end iterator of the container
+   * @returns reference to self (to allow chaining of append methods)
+   */
+  template<class Iterator>
+  inline Name &
+  append (Iterator begin, Iterator end);
+
+  /**
+   * @brief Append components from another ndn::Name object
+   *
+   * @param comp reference to Name object
+   * @returns reference to self (to allow chaining of append methods)
+   */
+  inline Name &
+  append (const Name &comp);
+
+  /**
+   * @brief Append a string as a name component
+   *
+   * @param compStr a string
+   * @returns reference to self (to allow chaining of append methods)
+   *
+   * No conversions will be done to the string.  The string is included in raw form,
+   * without any leading '\0' symbols.
+   */
+  inline Name &
+  append (const std::string &compStr);
+
+  /**
+   * @brief Append a binary blob as a name component
+   *
+   * @param buf pointer to the first byte of the binary blob
+   * @param size length of the binary blob
+   * @returns reference to self (to allow chaining of append methods)
+   */
+  inline Name &
+  append (const void *buf, size_t size);
+
+  /**
+   * @brief Append network-ordered numeric component to the name
+   *
+   * @param number number to be encoded and added as a component
+   *
+   * Number is encoded and added in network order. Tail zero-bytes are not included.
+   * For example, if the number is 1, then 1-byte binary blob will be added  0x01.
+   * If the number is 256, then 2 binary blob will be added: 0x01 0x01
+   *
+   * If the number is zero, an empty component will be added
+   */
+  inline Name &
+  appendNumber (uint64_t number);
+
+  /**
+   * @brief Append network-ordered numeric component to the name with marker
+   *
+   * @param number number to be encoded and added as a component
+   * @param marker byte marker, specified by the desired naming convention
+   *
+   * Currently defined naming conventions of the marker:
+   * - 0x00  sequence number
+   * - 0xC1  control number
+   * - 0xFB  block id
+   * - 0xFD  version number
+   *
+   * This version is almost exactly as appendNumber, with exception that it adds initial marker.
+   * The number is formatted in the exactly the same way.
+   *
+   * @see appendNumber
+   */
+  inline Name &
+  appendNumberWithMarker (uint64_t number, unsigned char marker);
+
+  /**
+   * @brief Helper method to add sequence number to the name (marker = 0x00)
+   * @param seqno sequence number
+   * @see appendNumberWithMarker
+   */
+  inline Name &
+  appendSeqNum (uint64_t seqno);
+
+  /**
+   * @brief Helper method to add control number to the name (marker = 0xC1)
+   * @param control control number
+   * @see appendNumberWithMarker
+   */
+  inline Name &
+  appendControlNum (uint64_t control);
+
+  /**
+   * @brief Helper method to add block ID to the name (marker = 0xFB)
+   * @param blkid block ID
+   * @see appendNumberWithMarker
+   */
+  inline Name &
+  appendBlkId (uint64_t blkid);
+
+  /**
+   * @brief Helper method to add version to the name (marker = 0xFD)
+   * @param version fully formatted version in a desired format (e.g., timestamp).
+   *                If version is Name::nversion, then the version number is automatically
+   *                assigned based on UTC timestamp
+   * @see appendNumberWithMarker
+   */
+  Name &
+  appendVersion (uint64_t version = Name::nversion);
+
+  ///////////////////////////////////////////////////////////////////////////////
+  //                                GETTERS                                    //
+  ///////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Get number of the name components
+   * @return number of name components
+   */
+  inline size_t
+  size () const;
+
+  /**
+   * @brief Get binary blob of name component
+   * @param index index of the name component.  If less than 0, then getting component from the back:
+   *              get(-1) getting the last component, get(-2) is getting second component from back, etc.
+   * @returns const reference to binary blob of the requested name component
+   *
+   * If index is out of range, an exception will be thrown
+   */
+  const name::Component &
+  get (int index) const;
+
+  /**
+   * @brief Get binary blob of name component
+   * @param index index of the name component.  If less than 0, then getting component from the back
+   * @returns reference to binary blob of the requested name component
+   *
+   * If index is out of range, an exception will be thrown
+   */
+  name::Component &
+  get (int index);
+
+  /////
+  ///// Iterator interface to name components
+  /////
+  inline Name::const_iterator
+  begin () const;           ///< @brief Begin iterator (const)
+
+  inline Name::iterator
+  begin ();                 ///< @brief Begin iterator
+
+  inline Name::const_iterator
+  end () const;             ///< @brief End iterator (const)
+
+  inline Name::iterator
+  end ();                   ///< @brief End iterator
+
+  inline Name::const_reverse_iterator
+  rbegin () const;          ///< @brief Reverse begin iterator (const)
+
+  inline Name::reverse_iterator
+  rbegin ();                ///< @brief Reverse begin iterator
+
+  inline Name::const_reverse_iterator
+  rend () const;            ///< @brief Reverse end iterator (const)
+
+  inline Name::reverse_iterator
+  rend ();                  ///< @brief Reverse end iterator
+
+
+  /////
+  ///// Static helpers to convert name component to appropriate value
+  /////
+
+  /**
+   * @brief Get a new name, constructed as a subset of components
+   * @param pos Position of the first component to be copied to the subname
+   * @param len Number of components to be copied. Value Name::npos indicates that all components till the end of the name.
+   */
+  Name
+  getSubName (size_t pos = 0, size_t len = npos) const;
+
+  /**
+   * @brief Get prefix of the name
+   * @param len length of the prefix
+   * @param skip number of components to skip from beginning of the name
+   */
+  inline Name
+  getPrefix (size_t len, size_t skip = 0) const;
+
+  /**
+   * @brief Get postfix of the name
+   * @param len length of the postfix
+   * @param skip number of components to skip from end of the name
+   */
+  inline Name
+  getPostfix (size_t len, size_t skip = 0) const;
+
+  /**
+   * @brief Get text representation of the name (URI)
+   */
+  std::string
+  toUri () const;
+
+  /**
+   * @brief Write name as URI to the specified output stream
+   * @param os output stream
+   */
+  void
+  toUri (std::ostream &os) const;
+
+  /////////////////////////////////////////////////
+  // Helpers and compatibility wrappers
+  /////////////////////////////////////////////////
+
+  /**
+   * @brief Compare two names, using canonical ordering for each component
+   * @return 0  They compare equal
+   *         <0 If *this comes before other in the canonical ordering
+   *         >0 If *this comes after in the canonical ordering
+   */
+  int
+  compare (const Name &name) const;
+
+  /**
+   * @brief Check if to Name objects are equal (have the same number of components with the same binary data)
+   */
+  inline bool
+  operator == (const Name &name) const;
+
+  /**
+   * @brief Check if two Name objects are not equal
+   */
+  inline bool
+  operator != (const Name &name) const;
+
+  /**
+   * @brief Less or equal comparison of two name objects
+   */
+  inline bool
+  operator <= (const Name &name) const;
+
+  /**
+   * @brief Less comparison of two name objects
+   */
+  inline bool
+  operator < (const Name &name) const;
+
+  /**
+   * @brief Great or equal comparison of two name objects
+   */
+  inline bool
+  operator >= (const Name &name) const;
+
+  /**
+   * @brief Great comparison of two name objects
+   */
+  inline bool
+  operator > (const Name &name) const;
+
+  /**
+   * @brief Operator [] to simplify access to name components
+   * @see get
+   */
+  inline name::Component &
+  operator [] (int index);
+
+  /**
+   * @brief Operator [] to simplify access to name components
+   * @see get
+   */
+  inline const name::Component &
+  operator [] (int index) const;
+
+  /**
+   * @brief Create a new Name object, by copying components from first and second name
+   */
+  Name
+  operator + (const Name &name) const;
+
+  /**
+   * @brief A wrapper for append method
+   */
+  template<class T>
+  inline void
+  push_back (const T &comp);
+
+public:
+  // Data Members (public):
+  ///  Value returned by various member functions when they fail.
+  const static size_t npos = static_cast<size_t> (-1);
+  const static uint64_t nversion = static_cast<uint64_t> (-1);
+
+private:
+  std::vector<name::Component> m_comps;
+};
+
+typedef boost::shared_ptr<Name> NamePtr;
+
+inline std::ostream &
+operator << (std::ostream &os, const Name &name)
+{
+  name.toUri (os);
+  return os;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+// Definition of inline methods
+/////////////////////////////////////////////////////////////////////////////////////
+
+template<class Iterator>
+Name::Name (Iterator begin, Iterator end)
+{
+  append (begin, end);
+}
+
+inline Name &
+Name::append (const name::Component &comp)
+{
+  if (comp.size () != 0)
+    m_comps.push_back (comp);
+  return *this;
+}
+
+inline Name &
+Name::appendBySwap (name::Component &comp)
+{
+  if (comp.size () != 0)
+    {
+      Name::iterator newComp = m_comps.insert (end (), name::Component ());
+      newComp->swap (comp);
+    }
+  return *this;
+}
+
+template<class Iterator>
+inline Name &
+Name::append (Iterator begin, Iterator end)
+{
+  for (Iterator i = begin; i != end; i++)
+    {
+      append (*i);
+    }
+  return *this;
+}
+
+Name &
+Name::append (const Name &comp)
+{
+  if (this == &comp)
+    {
+      // have to double-copy if the object is self, otherwise results very frustrating (because we use vector...)
+      return append (Name (comp.begin (), comp.end ()));
+    }
+  return append (comp.begin (), comp.end ());
+}
+
+Name &
+Name::append (const std::string &compStr)
+{
+  name::Component comp (compStr);
+  return appendBySwap (comp);
+}
+
+Name &
+Name::append (const void *buf, size_t size)
+{
+  name::Component comp (buf, size);
+  return appendBySwap (comp);
+}
+
+Name &
+Name::appendNumber (uint64_t number)
+{
+  name::Component comp;
+  name::Component::fromNumber (number).swap (comp);
+  return appendBySwap (comp);
+}
+
+Name &
+Name::appendNumberWithMarker (uint64_t number, unsigned char marker)
+{
+  name::Component comp;
+  name::Component::fromNumberWithMarker (number, marker).swap (comp);
+  return appendBySwap (comp);
+}
+
+inline Name &
+Name::appendSeqNum (uint64_t seqno)
+{
+  return appendNumberWithMarker (seqno, 0x00);
+}
+
+inline Name &
+Name::appendControlNum (uint64_t control)
+{
+  return appendNumberWithMarker (control, 0xC1);
+}
+
+inline Name &
+Name::appendBlkId (uint64_t blkid)
+{
+  return appendNumberWithMarker (blkid, 0xFB);
+}
+
+inline size_t
+Name::size () const
+{
+  return m_comps.size ();
+}
+
+/////
+///// Iterator interface to name components
+/////
+inline Name::const_iterator
+Name::begin () const
+{
+  return m_comps.begin ();
+}
+
+inline Name::iterator
+Name::begin ()
+{
+  return m_comps.begin ();
+}
+
+inline Name::const_iterator
+Name::end () const
+{
+  return m_comps.end ();
+}
+
+inline Name::iterator
+Name::end ()
+{
+  return m_comps.end ();
+}
+
+inline Name::const_reverse_iterator
+Name::rbegin () const
+{
+  return m_comps.rbegin ();
+}
+
+inline Name::reverse_iterator
+Name::rbegin ()
+{
+  return m_comps.rbegin ();
+}
+
+inline Name::const_reverse_iterator
+Name::rend () const
+{
+  return m_comps.rend ();
+}
+
+
+inline Name::reverse_iterator
+Name::rend ()
+{
+  return m_comps.rend ();
+}
+
+
+//// helpers
+
+
+inline Name
+Name::getPrefix (size_t len, size_t skip/* = 0*/) const
+{
+  return getSubName (skip, len);
+}
+
+inline Name
+Name::getPostfix (size_t len, size_t skip/* = 0*/) const
+{
+  return getSubName (size () - len - skip, len);
+}
+
+
+template<class T>
+inline void
+Name::push_back (const T &comp)
+{
+  append (comp);
+}
+
+inline bool
+Name::operator ==(const Name &name) const
+{
+  return (compare (name) == 0);
+}
+
+inline bool
+Name::operator !=(const Name &name) const
+{
+  return (compare (name) != 0);
+}
+
+inline bool
+Name::operator <= (const Name &name) const
+{
+  return (compare (name) <= 0);
+}
+
+inline bool
+Name::operator < (const Name &name) const
+{
+  return (compare (name) < 0);
+}
+
+inline bool
+Name::operator >= (const Name &name) const
+{
+  return (compare (name) >= 0);
+}
+
+inline bool
+Name::operator > (const Name &name) const
+{
+  return (compare (name) > 0);
+}
+
+inline name::Component &
+Name::operator [] (int index)
+{
+  return get (index);
+}
+
+inline const name::Component &
+Name::operator [] (int index) const
+{
+  return get (index);
+}
+
+} // ndn
+
+#endif
diff --git a/ndn-cpp/fields/signature-sha256-with-rsa.cc b/ndn-cpp/fields/signature-sha256-with-rsa.cc
new file mode 100644
index 0000000..c84ef5a
--- /dev/null
+++ b/ndn-cpp/fields/signature-sha256-with-rsa.cc
@@ -0,0 +1,30 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "signature-sha256-with-rsa.h"
+#include "ndn-cpp/wire/base.h"
+
+namespace ndn {
+namespace signature {
+
+const std::string Sha256WithRsa::s_oid = "2.16.840.1.101.3.4.2.1";
+
+Sha256WithRsa::~Sha256WithRsa ()
+{
+}
+
+void
+Sha256WithRsa::doubleDispatch (std::ostream &os, wire::Base &wire, void *userData) const
+{
+  wire.appendSignature (os, *this, userData);
+}
+
+} // signature
+} // ndn
diff --git a/ndn-cpp/fields/signature-sha256-with-rsa.h b/ndn-cpp/fields/signature-sha256-with-rsa.h
new file mode 100644
index 0000000..be6766b
--- /dev/null
+++ b/ndn-cpp/fields/signature-sha256-with-rsa.h
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_SIGNATURE_SHA256_WITH_RSA_H
+#define NDN_SIGNATURE_SHA256_WITH_RSA_H
+
+#include "signature.h"
+
+#include "ndn-cpp/fields/blob.h"
+#include "ndn-cpp/fields/key-locator.h"
+
+#include <string>
+
+namespace ndn {
+
+namespace signature {
+
+/**
+ * @brief Class providing operations to work with SHA256withRSA (OID: "2.16.840.1.101.3.4.2.1")
+ */
+class Sha256WithRsa : public virtual Signature
+{
+public:
+  /**
+   * @brief Virtual destructor
+   */
+  virtual
+  ~Sha256WithRsa ();
+
+  /**
+   * @brief Get OID of the signature algorithm
+   */
+  inline const std::string &
+  getDigestAlgorithm () const;
+
+  /**
+   * @brief Get reference to signature bits
+   */
+  inline Blob &
+  getSignatureBits ();
+
+  /**
+   * @brief Get const reference to signature bits
+   */
+  inline const Blob &
+  getSignatureBits () const;
+
+  /**
+   * @brief Set signature bits
+   */
+  inline void
+  setSignatureBits (const Blob &signatureBits);
+
+  /**
+   * @brief Get reference to publisher key digest bits
+   */
+  inline Blob &
+  getPublisherKeyDigest ();
+
+  /**
+   * @brief Get const reference to publisher key digest bits
+   */
+  inline const Blob &
+  getPublisherKeyDigest () const;
+
+  /**
+   * @brief Set publisher key digest bits
+   */
+  inline void
+  setPublisherKeyDigest (const Blob &publisherKeyDigest);
+
+  /**
+   * @brief Get reference to key locator object
+   */
+  inline KeyLocator &
+  getKeyLocator ();
+
+  /**
+   * @brief Get const reference to key locator object
+   */
+  inline const KeyLocator &
+  getKeyLocator () const;
+
+  /**
+   * @brief Set key locator object
+   */
+  inline void
+  setKeyLocator (const KeyLocator &keyLocator);
+
+  // from Signature
+  virtual void
+  doubleDispatch (std::ostream &os, wire::Base &wire, void *userData) const;
+
+private:
+  static const std::string s_oid;
+
+  Blob m_signatureBits;
+  Blob m_publisherKeyDigest;
+  KeyLocator m_keyLocator;
+};
+
+const std::string &
+Sha256WithRsa::getDigestAlgorithm () const
+{
+  return s_oid;
+}
+
+inline Blob &
+Sha256WithRsa::getSignatureBits ()
+{
+  return m_signatureBits;
+}
+
+inline const Blob &
+Sha256WithRsa::getSignatureBits () const
+{
+  return m_signatureBits;
+}
+
+inline void
+Sha256WithRsa::setSignatureBits (const Blob &signatureBits)
+{
+  m_signatureBits = signatureBits;
+}
+
+inline Blob &
+Sha256WithRsa::getPublisherKeyDigest ()
+{
+  return m_publisherKeyDigest;
+}
+
+inline const Blob &
+Sha256WithRsa::getPublisherKeyDigest () const
+{
+  return m_publisherKeyDigest;
+}
+
+inline void
+Sha256WithRsa::setPublisherKeyDigest (const Blob &publisherKeyDigest)
+{
+  m_publisherKeyDigest = publisherKeyDigest;
+}
+
+inline KeyLocator &
+Sha256WithRsa::getKeyLocator ()
+{
+  return m_keyLocator;
+}
+
+inline const KeyLocator &
+Sha256WithRsa::getKeyLocator () const
+{
+  return m_keyLocator;
+}
+
+inline void
+Sha256WithRsa::setKeyLocator (const KeyLocator &keyLocator)
+{
+  m_keyLocator = keyLocator;
+}
+
+} // signature
+} // ndn
+
+#endif // NDN_EXCLUDE_H
diff --git a/ndn-cpp/fields/signature.cc b/ndn-cpp/fields/signature.cc
new file mode 100644
index 0000000..4c7a3a5
--- /dev/null
+++ b/ndn-cpp/fields/signature.cc
@@ -0,0 +1,18 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "signature.h"
+#include "ndn-cpp/error.h"
+
+namespace ndn
+{
+
+
+} // ndn
diff --git a/ndn-cpp/fields/signature.h b/ndn-cpp/fields/signature.h
new file mode 100644
index 0000000..a9fb39a
--- /dev/null
+++ b/ndn-cpp/fields/signature.h
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_SIGNATURE_H
+#define NDN_SIGNATURE_H
+
+#include <iostream>
+
+namespace ndn {
+
+namespace wire { class Base; }
+
+/**
+ * @brief Pure virtual class providing an interface to work with signatures for NDN data packets
+ */
+class Signature
+{
+public:
+  /**
+   * @brief Virtual destructor
+   */
+  virtual
+  ~Signature () { }
+
+  /**
+   * @brief A double dispatch pattern to call the right wireFormatter method to format signature
+   * @param os reference to output stream
+   * @param wireFormatter a reference to a wireFormatter object
+   * @param userData any user-specific data
+   */
+  virtual void
+  doubleDispatch (std::ostream &os, wire::Base &wireFormatter, void *userData) const = 0;
+};
+
+} // ndn
+
+#endif // NDN_SIGNATURE_H
diff --git a/ndn-cpp/fields/signed-blob.h b/ndn-cpp/fields/signed-blob.h
new file mode 100644
index 0000000..2686977
--- /dev/null
+++ b/ndn-cpp/fields/signed-blob.h
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_SIGNED_BLOB_H
+#define NDN_SIGNED_BLOB_H
+
+#include "blob.h"
+
+namespace ndn {
+
+/**
+ * @brief Class representing a blob, which has a signed portion (e.g., bytes of DATA packet)
+ */
+class SignedBlob : public Blob
+{
+public:
+  /**
+   * @brief Set signed portion of the blob
+   * @param offset An offset from the beginning of the blob
+   * @param size Size of the signed portion of the blob
+   */
+  inline void
+  setSignedPortion (size_t offset, size_t size);
+  
+  /**
+   * @brief Get begin iterator to a signed portion of the blob
+   */
+  inline const_iterator
+  signed_begin () const;
+
+  /**
+   * @brief Get end iterator of a signed portion of the blob
+   */
+  inline const_iterator
+  signed_end () const;
+
+  /**
+   * @brief Get pointer to a first byte of the signed blob
+   */
+  inline const char*
+  signed_buf () const;
+
+  /**
+   * @brief Get size of the signed blob
+   */
+  inline size_t
+  signed_size () const;
+
+private:
+  const_iterator m_signedBegin;
+  const_iterator m_signedEnd;
+};
+
+
+inline void
+SignedBlob::setSignedPortion (size_t offset, size_t size)
+{
+  m_signedBegin = begin () + offset;
+  m_signedEnd = begin () + offset + size;
+}
+  
+inline SignedBlob::const_iterator
+SignedBlob::signed_begin () const
+{
+  return m_signedBegin;
+}
+
+inline SignedBlob::const_iterator
+SignedBlob::signed_end () const
+{
+  return m_signedEnd;
+}
+
+inline const char*
+SignedBlob::signed_buf () const
+{
+  return &*m_signedBegin;
+}
+
+inline size_t
+SignedBlob::signed_size () const
+{
+  return m_signedEnd - m_signedBegin;
+}
+
+
+} // ndn
+
+#endif // NDN_SIGNED_BLOB_H
diff --git a/ndn-cpp/helpers/hash.cc b/ndn-cpp/helpers/hash.cc
new file mode 100644
index 0000000..0ecf927
--- /dev/null
+++ b/ndn-cpp/helpers/hash.cc
@@ -0,0 +1,130 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "hash.h"
+#include "ndn-cpp/helpers/uri.h"
+
+#include <boost/lexical_cast.hpp>
+#include <openssl/evp.h>
+#include <fstream>
+
+using namespace boost;
+using namespace std;
+
+// Other options: VP_md2, EVP_md5, EVP_sha, EVP_sha1, EVP_sha256, EVP_dss, EVP_dss1, EVP_mdc2, EVP_ripemd160
+#define HASH_FUNCTION EVP_sha256
+
+namespace ndn
+{
+
+std::ostream &
+operator << (std::ostream &os, const Hash &hash)
+{
+  if (hash.m_length == 0)
+    return os;
+
+  ostreambuf_iterator<char> out_it (os); // ostream iterator
+  // need to encode to base64
+  copy (detail::string_from_binary (reinterpret_cast<const char*> (hash.m_buf)),
+        detail::string_from_binary (reinterpret_cast<const char*> (hash.m_buf+hash.m_length)),
+        out_it);
+
+  return os;
+}
+
+std::string
+Hash::shortHash () const
+{
+  return lexical_cast<string> (*this).substr (0, 10);
+}
+
+
+unsigned char Hash::_origin = 0;
+HashPtr Hash::Origin(new Hash(&Hash::_origin, sizeof(unsigned char)));
+
+HashPtr
+Hash::FromString (const std::string &hashInTextEncoding)
+{
+  HashPtr retval = make_shared<Hash> (reinterpret_cast<void*> (0), 0);
+
+  if (hashInTextEncoding.size () == 0)
+    {
+      return retval;
+    }
+
+  if (hashInTextEncoding.size () > EVP_MAX_MD_SIZE * 2)
+    {
+      cerr << "Input hash is too long. Returning an empty hash" << endl;
+      return retval;
+    }
+
+  retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+  unsigned char *end = copy (detail::string_to_binary (hashInTextEncoding.begin ()),
+                             detail::string_to_binary (hashInTextEncoding.end ()),
+                             retval->m_buf);
+
+  retval->m_length = end - retval->m_buf;
+
+  return retval;
+}
+
+HashPtr
+Hash::FromFileContent (const char *filename)
+{
+  HashPtr retval = make_shared<Hash> (reinterpret_cast<void*> (0), 0);
+  retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+  EVP_MD_CTX *hash_context = EVP_MD_CTX_create ();
+  EVP_DigestInit_ex (hash_context, HASH_FUNCTION (), 0);
+
+  ifstream iff (filename, std::ios::in | std::ios::binary);
+  while (iff.good ())
+    {
+      char buf[1024];
+      iff.read (buf, 1024);
+      EVP_DigestUpdate (hash_context, buf, iff.gcount ());
+    }
+
+  retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+  EVP_DigestFinal_ex (hash_context,
+                      retval->m_buf, &retval->m_length);
+
+  EVP_MD_CTX_destroy (hash_context);
+
+  return retval;
+}
+
+HashPtr
+Hash::FromBytes (const ndn::Bytes &bytes)
+{
+  HashPtr retval = make_shared<Hash> (reinterpret_cast<void*> (0), 0);
+  retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+  EVP_MD_CTX *hash_context = EVP_MD_CTX_create ();
+  EVP_DigestInit_ex (hash_context, HASH_FUNCTION (), 0);
+
+  // not sure whether it's bad to do so if bytes.size is huge
+  EVP_DigestUpdate(hash_context, ndn::head(bytes), bytes.size());
+
+  retval->m_buf = new unsigned char [EVP_MAX_MD_SIZE];
+
+  EVP_DigestFinal_ex (hash_context,
+                      retval->m_buf, &retval->m_length);
+
+  EVP_MD_CTX_destroy (hash_context);
+
+  return retval;
+}
+
+} // ndn
diff --git a/ndn-cpp/helpers/hash.h b/ndn-cpp/helpers/hash.h
new file mode 100644
index 0000000..1652f2b
--- /dev/null
+++ b/ndn-cpp/helpers/hash.h
@@ -0,0 +1,162 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#ifndef NDN_HASH_H
+#define NDN_HASH_H
+
+#include <string.h>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/exception/all.hpp>
+
+#include "ndn-cpp/common.h"
+
+namespace ndn
+{
+
+class Hash;
+typedef boost::shared_ptr<Hash> HashPtr;
+
+class Hash
+{
+public:
+  static unsigned char _origin;
+  static HashPtr Origin;
+
+  Hash ()
+    : m_buf(0)
+    , m_length(0)
+  {
+  }
+
+  Hash (const void *buf, unsigned int length)
+    : m_length (length)
+  {
+    if (m_length != 0)
+      {
+        m_buf = new unsigned char [length];
+        memcpy (m_buf, buf, length);
+      }
+  }
+
+  Hash (const Hash &otherHash)
+  : m_length (otherHash.m_length)
+  {
+    if (m_length != 0)
+      {
+        m_buf = new unsigned char [m_length];
+        memcpy (m_buf, otherHash.m_buf, otherHash.m_length);
+      }
+  }
+
+  static HashPtr
+  FromString (const std::string &hashInTextEncoding);
+
+  static HashPtr
+  FromFileContent (const char *fileName);
+
+  static HashPtr
+  FromBytes (const ndn::Bytes &bytes);
+
+  ~Hash ()
+  {
+    if (m_length != 0)
+      delete [] m_buf;
+  }
+
+  Hash &
+  operator = (const Hash &otherHash)
+  {
+    if (m_length != 0)
+      delete [] m_buf;
+
+    m_length = otherHash.m_length;
+    if (m_length != 0)
+      {
+        m_buf = new unsigned char [m_length];
+        memcpy (m_buf, otherHash.m_buf, otherHash.m_length);
+      }
+    return *this;
+  }
+
+  bool
+  IsZero () const
+  {
+    return m_length == 0 ||
+      (m_length == 1 && m_buf[0] == 0);
+  }
+
+  bool
+  operator == (const Hash &otherHash) const
+  {
+    if (m_length != otherHash.m_length)
+      return false;
+
+    return memcmp (m_buf, otherHash.m_buf, m_length) == 0;
+  }
+
+  bool operator < (const Hash &otherHash) const
+  {
+    if (m_length < otherHash.m_length)
+      return true;
+
+    if (m_length > otherHash.m_length)
+      return false;
+
+    for (unsigned int i = 0; i < m_length; i++)
+      {
+        if (m_buf [i] < otherHash.m_buf [i])
+          return true;
+
+        if (m_buf [i] > otherHash.m_buf [i])
+          return false;
+
+        // if equal, continue
+      }
+
+    return false;
+  }
+
+  const void *
+  GetHash () const
+  {
+    return m_buf;
+  }
+
+  unsigned int
+  GetHashBytes () const
+  {
+    return m_length;
+  }
+
+  std::string
+  shortHash () const;
+
+private:
+  unsigned char *m_buf;
+  unsigned int m_length;
+
+  friend std::ostream &
+  operator << (std::ostream &os, const Hash &digest);
+};
+
+namespace Error {
+struct HashConversion : virtual boost::exception, virtual std::exception { };
+}
+
+
+std::ostream &
+operator << (std::ostream &os, const Hash &digest);
+
+}
+
+#endif // NDN_HASH_H
diff --git a/ndn-cpp/helpers/uri.h b/ndn-cpp/helpers/uri.h
new file mode 100644
index 0000000..3fbda7c
--- /dev/null
+++ b/ndn-cpp/helpers/uri.h
@@ -0,0 +1,155 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_DETAIL_URI_H
+#define NDN_DETAIL_URI_H
+
+#include "ndn-cpp/error.h"
+
+#include <boost/archive/iterators/transform_width.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+
+namespace ndn
+{
+
+namespace detail
+{
+
+static const bool ESCAPE_CHARACTER [256] = {
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 26
+  1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 53
+  0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 107
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 134
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 161
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 188
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 215
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 242
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 255
+};
+
+/// @cond include_hidden
+template<class CharType>
+struct hex_from_4_bit
+{
+  typedef CharType result_type;
+  CharType operator () (CharType ch) const
+  {
+    const char lookup_table [16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+    // cout << "New character: " << (int) ch << " (" << (char) ch << ")" << "\n";
+    BOOST_ASSERT (ch < 16);
+    return lookup_table[static_cast<size_t>(ch)];
+  }
+};
+
+typedef boost::transform_iterator<hex_from_4_bit<std::string::const_iterator::value_type>,
+                                  boost::archive::iterators::transform_width<std::string::const_iterator, 4, 8, std::string::const_iterator::value_type> > string_from_binary;
+
+
+
+template<class CharType>
+struct hex_to_4_bit
+{
+  typedef CharType result_type;
+  CharType operator () (CharType ch) const
+  {
+    const signed char lookup_table [] = {
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
+      -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+    };
+
+    signed char value = -1;
+    if ((unsigned)ch < 128)
+      value = lookup_table [(unsigned)ch];
+    if (value == -1)
+      boost::throw_exception (error::StringTransform ());
+
+    return value;
+  }
+};
+
+typedef boost::archive::iterators::transform_width<boost::transform_iterator<hex_to_4_bit<std::string::const_iterator::value_type>, std::string::const_iterator>, 8, 4> string_to_binary;
+/// @endcond
+
+} // detail
+
+/**
+ * @brief A helper class to convert to/from URI
+ */
+class Uri
+{
+public:
+  template<class Iterator1, class Iterator2>
+  inline static void
+  fromEscaped (Iterator1 begin, Iterator1 end, Iterator2 inserter)
+  {
+    Iterator1 i = begin;
+    while (i != end)
+      {
+        if (*i == '%')
+          {
+            try
+              {
+                ++i;
+                Iterator1 j = i;
+                advance (i, 2);
+              
+                std::copy (detail::string_to_binary (j), detail::string_to_binary (i), inserter);
+              }
+            catch (ndn::error::StringTransform &e)
+              {
+                BOOST_THROW_EXCEPTION (error::Uri ()
+                                       << error::pos (std::distance (i, begin)));
+              }
+          }
+        else if (!detail::ESCAPE_CHARACTER[static_cast<unsigned char> (*i)])
+          {
+            *inserter = *i;
+            ++inserter; ++i;
+          }
+        else
+          {
+            BOOST_THROW_EXCEPTION (error::Uri ()
+                                   << error::pos (std::distance (i, begin)));
+          }
+      }
+  }
+
+  template<class Iterator1, class Iterator2>
+  inline static void
+  toEscaped (Iterator1 begin, Iterator1 end, Iterator2 inserter)
+  {
+    const char lookup_table [16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+    
+    for (Iterator1 i = begin; i != end; i++)
+      {
+        if (detail::ESCAPE_CHARACTER[static_cast<unsigned char> (*i)])
+          {
+            *inserter = '%';         ++inserter;
+            *inserter = lookup_table [(*i >> 4) & 0x0F]; ++inserter;
+            *inserter = lookup_table [(*i & 0x0F)];      ++inserter;
+          }
+        else
+          {
+            *inserter = *i; ++inserter;
+          }
+      }
+  }
+};
+
+} // ndn
+
+#endif // NDN_DETAIL_URI_H
diff --git a/ndn-cpp/interest.cc b/ndn-cpp/interest.cc
new file mode 100644
index 0000000..3825677
--- /dev/null
+++ b/ndn-cpp/interest.cc
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "interest.h"
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+
+namespace ndn {
+
+Interest::Interest ()
+  // m_name
+  : m_maxSuffixComponents (Interest::ncomps)
+  , m_minSuffixComponents (Interest::ncomps)
+  , m_answerOriginKind (AOK_DEFAULT)
+  , m_interestLifetime (time::Seconds (-1.0))
+  , m_scope (NO_SCOPE)
+  , m_childSelector (CHILD_DEFAULT)
+  // m_publisherKeyDigest
+{
+}
+
+Interest::Interest (const Name &name)
+  : m_name (name)
+  , m_maxSuffixComponents (Interest::ncomps)
+  , m_minSuffixComponents (Interest::ncomps)
+  , m_answerOriginKind(AOK_DEFAULT)
+  , m_interestLifetime (time::Seconds (-1.0))
+  , m_scope (NO_SCOPE)
+  , m_childSelector (CHILD_DEFAULT)
+  // m_publisherKeyDigest
+{
+}
+
+Interest::Interest (const Interest &other)
+{
+  m_name = other.m_name;
+  m_maxSuffixComponents = other.m_maxSuffixComponents;
+  m_minSuffixComponents = other.m_minSuffixComponents;
+  m_answerOriginKind = other.m_answerOriginKind;
+  m_interestLifetime = other.m_interestLifetime;
+  m_scope = other.m_scope;
+  m_childSelector = other.m_childSelector;
+  m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
+}
+
+Interest::Interest (const ccn_parsed_interest *pi)
+  : m_maxSuffixComponents (Interest::ncomps)
+  , m_minSuffixComponents (Interest::ncomps)
+  , m_answerOriginKind (AOK_DEFAULT)
+  , m_interestLifetime (time::Seconds (-1.0))
+  , m_scope (NO_SCOPE)
+  , m_childSelector (CHILD_DEFAULT)
+{
+  if (pi != NULL)
+  {
+    m_maxSuffixComponents = pi->max_suffix_comps;
+    m_minSuffixComponents = pi->min_suffix_comps;
+    switch(pi->orderpref)
+      {
+      case 0: m_childSelector = CHILD_LEFT; break;
+      case 1: m_childSelector = CHILD_RIGHT; break;
+      default: m_childSelector = CHILD_DEFAULT; break;
+      }
+
+    switch(pi->answerfrom)
+    {
+      case 0x1: m_answerOriginKind = AOK_CS; break;
+      case 0x2: m_answerOriginKind = AOK_NEW; break;
+      case 0x3: m_answerOriginKind = AOK_DEFAULT; break;
+      case 0x4: m_answerOriginKind = AOK_STALE; break;
+      case 0x10: m_answerOriginKind = AOK_EXPIRE; break;
+      default: break;
+    }
+    m_scope = static_cast<Scope> (pi->scope);
+  }
+
+  /// @todo copy publisher key digest
+}
+
+bool
+Interest::operator == (const Interest &other)
+{
+  return
+       m_name == other.m_name
+    && m_maxSuffixComponents == other.m_maxSuffixComponents
+    && m_minSuffixComponents == other.m_minSuffixComponents
+    && m_answerOriginKind == other.m_answerOriginKind
+    && m_interestLifetime == other.m_interestLifetime
+    && m_scope == other.m_scope
+    && m_childSelector == other.m_childSelector;
+}
+
+} // ndn
diff --git a/ndn-cpp/interest.h b/ndn-cpp/interest.h
new file mode 100644
index 0000000..d929efa
--- /dev/null
+++ b/ndn-cpp/interest.h
@@ -0,0 +1,461 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *                     Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#ifndef NDN_INTEREST_H
+#define NDN_INTEREST_H
+
+#include <ndn-cpp/common.h>
+#include <ndn-cpp/fields/name.h>
+#include <ndn-cpp/fields/exclude.h>
+#include <ndn-cpp/helpers/hash.h>
+
+namespace ndn {
+
+/**
+ * @brief Class abstracting operations with Interests (constructing and getting access to Interest fields)
+ */
+class Interest
+{
+public:
+  /**
+   * @brief Default constructor, creates an interest for / prefix without any selectors
+   */
+  Interest ();
+
+  /**
+   * @brief Create an interest for the name
+   * @param name name of the data to request
+   */
+  Interest (const Name &name);
+
+  /**
+   * @brief Copy constructor
+   * @param interest interest to copy
+   */
+  Interest (const Interest &interest);
+
+  /**
+   * @brief Create an interest based on ccn_parsed_interest data structure
+   * @param interest pointer to ccn_parsed_interest data structure
+   *
+   * This method will create an interest with empty name, since ccn_parsed_interest structure
+   * has limited amount of information
+   */
+  Interest (const ccn_parsed_interest *interest);
+
+  /**
+   * @brief Set interest name
+   * @param name name of the interest
+   * @return reference to self (to allow method chaining)
+   *
+   * In some cases, a direct access to and manipulation of name using getName is more efficient
+   */
+  inline Interest &
+  setName (const Name &name);
+
+  /**
+   * @brief Get interest name (const reference)
+   * @returns name of the interest
+   */
+  inline const Name &
+  getName () const;
+
+  /**
+   * @brief Get interest name (reference)
+   * @returns name of the interest
+   */
+  inline Name &
+  getName ();
+
+  /**
+   * @brief Set interest lifetime (time_duration)
+   * @param interestLifetime interest lifetime specified as a time_duration value.
+   *        Negative value means that InterestLifetime is not set.
+   * @return reference to self (to allow method chaining)
+   */
+  inline Interest &
+  setInterestLifetime (const TimeInterval &interestLifetime);
+
+  /**
+   * @brief Set interest lifetime (double)
+   * @param interestLifetime interest lifetime expressed in seconds, with possible fractional seconds (double).
+   *        Negative value means that InterestLifetime is not set.
+   * @return reference to self (to allow method chaining)
+   */
+  inline Interest &
+  setInterestLifetime (double interestLifetimeSeconds);
+
+  /**
+   * @brief Get interest lifetime
+   * @return TimeInterval representing lifetime of the interest.
+   *         Use time_duration::total_seconds () or time_duration::total_microseconds (),
+   *         if you need interest lifetime as a plain number.
+   *         @see http://www.boost.org/doc/libs/1_53_0/doc/html/date_time/posix_time.html
+   */
+  inline const TimeInterval &
+  getInterestLifetime () const;
+
+  /**
+   * @brief Set intended interest scope
+   * @param scope requested scope of the interest @see Scope
+   * @return reference to self (to allow method chaining)
+   */
+  inline Interest &
+  setScope (uint8_t scope);
+
+  /**
+   * @brief Get intended interest scope
+   * @return intended interest scope @see Scope
+   */
+  inline uint8_t
+  getScope () const;
+
+  ///////////////////////////////////////////////////////////////////////
+  //                          SELECTORS                                //
+  ///////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Enum defining constants for AnswerOriginKind selector field
+   */
+  enum AnswerOriginKind
+  {
+    AOK_CS = 0x1,      ///< @brief request item from the content store
+    AOK_NEW = 0x2,     ///< @brief request item from the original producer
+    AOK_DEFAULT = 0x3, ///< @brief default: either from content store or original producer
+    AOK_STALE = 0x4,   ///< @brief Allow stale data
+    AOK_EXPIRE = 0x10  ///< @brief Allow expired data (?)
+  };
+
+  /**
+   * @brief Enum defining constants for ChildSelector field
+   */
+  enum ChildSelector
+    {
+      CHILD_LEFT = 0,   ///< @brief request left child
+      CHILD_RIGHT = 1,  ///< @brief request right child
+      CHILD_DEFAULT = 2 ///< @brief do not specify which child is requested
+    };
+
+  /**
+   * @brief Enum defining constants for Scope field
+   */
+  enum Scope
+    {
+      NO_SCOPE = 255,        ///< @brief Interest scope is not defined
+      SCOPE_LOCAL_CCND = 0,  ///< @brief Interest scope is only toward local NDN daemon
+      SCOPE_LOCAL_HOST = 1,  ///< @brief Interest scope is within local host (any local application only)
+      SCOPE_NEXT_HOST = 2    ///< @brief Interest scope is within local host and immediate neighboring node
+    };
+
+  /**
+   * @brief Set interest selector for maximum suffix components
+   * @param maxSuffixComponents maximum number of suffix components. If Interest::ncomps, then not restricted
+   * @return reference to self (to allow method chaining)
+   */
+  inline Interest &
+  setMaxSuffixComponents (uint32_t maxSuffixComponents);
+
+  /**
+   * \brief Get interest selector for maximum suffix components
+   *
+   * MaxSuffixComponents refer to the number of name components beyond those in the prefix,
+   * and counting the implicit digest, that may occur in the matching ContentObject.
+   * For more information, see http://www.ccnx.org/releases/latest/doc/technical/InterestMessage.html
+   **/
+  inline uint32_t
+  getMaxSuffixComponents () const;
+
+  /**
+   * @brief Set interest selector for minimum suffix components
+   * @param minSuffixComponents minimum number of suffix components. If Interest::ncomps, then not restricted
+   * @return reference to self (to allow method chaining)
+   */
+  inline Interest &
+  setMinSuffixComponents (uint32_t minSuffixComponents);
+
+  /**
+   * \brief Get interest selector for minimum suffix components
+   *
+   * MinSuffixComponents refer to the number of name components beyond those in the prefix,
+   * and counting the implicit digest, that may occur in the matching ContentObject.
+   * For more information, see http://www.ccnx.org/releases/latest/doc/technical/InterestMessage.html
+   **/
+  inline uint32_t
+  getMinSuffixComponents () const;
+
+  /**
+   * @brief Set interest selector for answer origin kind
+   * @param answerOriginKind type of answer @see AnswerOriginKind
+   * @return reference to self (to allow method chaining)
+   */
+  inline Interest &
+  setAnswerOriginKind (uint32_t answerOriginKind);
+
+  /**
+   * @brief Get interest selector for answer origin kind
+   */
+  inline uint32_t
+  getAnswerOriginKind () const;
+
+  /**
+   * @brief Set interest selector for child selector
+   * @param child child selector @see ChildSelector
+   * @return reference to self (to allow method chaining)
+   *
+   * Often a given interest will match more than one ContentObject within a given content store.
+   * The ChildSelector provides a way of expressing a preference for which of these should be returned.
+   * If the value is false, the leftmost child is preferred. If true, the rightmost child is preferred.
+   * \see http://www.ccnx.org/releases/latest/doc/technical/InterestMessage.html for more information.
+   */
+  inline Interest &
+  setChildSelector (uint8_t child);
+
+  /**
+   * @brief Get interest selector for child selector
+   */
+  inline uint8_t
+  getChildSelector () const;
+
+  /**
+   * @brief Set interest selector for publisher public key digest
+   * @param digest publisher public key digest
+   * @return reference to self (to allow method chaining)
+   *
+   * Currently, this method has no effect
+   * @todo Implement PublisherPublicKeyDigest
+   */
+  inline Interest &
+  setPublisherPublicKeyDigest(const Hash &digest);
+
+  /**
+   * @brief Get interest selector for publisher public key digest
+   *
+   * @todo Implement
+   */
+  inline const Hash&
+  getPublisherPublicKeyDigest () const;
+
+  /**
+   * @brief Set exclude filter
+   * @param exclude An exclude filter to set
+   *
+   * In some cases, a direct access to and manipulation of exclude filter using getExclude is more efficient
+   */
+  inline void
+  setExclude (const Exclude &exclude);
+
+  /**
+   * @brief Get exclude filter (const reference)
+   */
+  inline const Exclude &
+  getExclude () const;
+
+  /**
+   * @brief Get exclude filter (reference)
+   */
+  inline Exclude &
+  getExclude ();
+
+  ///////////////////////////////////////////////////////////////////////
+  //                           HELPERS                                 //
+  ///////////////////////////////////////////////////////////////////////
+
+  /**
+   * @brief Compare equality of two interests
+   */
+  bool
+  operator== (const Interest &interest);
+
+public:
+  // Data Members (public):
+  /// @brief Value indicating that number of components parameter is invalid
+  const static uint32_t ncomps = static_cast<uint32_t> (-1);
+
+private:
+  Name m_name;
+  uint32_t m_maxSuffixComponents;
+  uint32_t m_minSuffixComponents;
+  uint32_t m_answerOriginKind;
+  TimeInterval m_interestLifetime; // lifetime in seconds
+
+  uint8_t m_scope;
+  uint8_t m_childSelector;
+  // not used now
+  Hash m_publisherPublicKeyDigest;
+  Exclude m_exclude;
+
+  Ptr<Blob> m_wire;
+};
+
+typedef boost::shared_ptr<Interest> InterestPtr;
+
+namespace Error
+{
+/**
+ * @brief Exception that is thrown in case of error during interest construction or parsing
+ */
+struct Interest:
+    virtual boost::exception, virtual std::exception {};
+}
+
+
+
+inline Interest &
+Interest::setName (const Name &name)
+{
+  m_name = name;
+  return *this;
+}
+
+inline const Name &
+Interest::getName () const
+{
+  return m_name;
+}
+
+inline Name &
+Interest::getName ()
+{
+  return m_name;
+}
+
+inline Interest &
+Interest::setInterestLifetime (const TimeInterval &interestLifetime)
+{
+  m_interestLifetime = interestLifetime;
+  return *this;
+}
+
+inline Interest &
+Interest::setInterestLifetime (double interestLifetimeSeconds)
+{
+  m_interestLifetime = time::Seconds (interestLifetimeSeconds);
+  return *this;
+}
+
+inline const TimeInterval &
+Interest::getInterestLifetime () const
+{
+  return m_interestLifetime;
+}
+
+inline Interest &
+Interest::setScope (uint8_t scope)
+{
+  m_scope = scope;
+  return *this;
+}
+
+inline uint8_t
+Interest::getScope () const
+{
+  return m_scope;
+}
+
+///////////////////////////////////////////////////////////////////////
+//                          SELECTORS                                //
+///////////////////////////////////////////////////////////////////////
+
+
+inline Interest &
+Interest::setMaxSuffixComponents (uint32_t maxSuffixComponents)
+{
+  m_maxSuffixComponents = maxSuffixComponents;
+  return *this;
+}
+
+inline uint32_t
+Interest::getMaxSuffixComponents () const
+{
+  return m_maxSuffixComponents;
+}
+
+inline Interest &
+Interest::setMinSuffixComponents (uint32_t minSuffixComponents)
+{
+  m_minSuffixComponents = minSuffixComponents;
+  return *this;
+}
+
+inline uint32_t
+Interest::getMinSuffixComponents () const
+{
+  return m_minSuffixComponents;
+}
+
+inline Interest &
+Interest::setAnswerOriginKind (uint32_t answerOriginKind)
+{
+  m_answerOriginKind = answerOriginKind;
+  return *this;
+}
+
+inline uint32_t
+Interest::getAnswerOriginKind () const
+{
+  return m_answerOriginKind;
+}
+
+inline Interest &
+Interest::setChildSelector (uint8_t childSelector)
+{
+  m_childSelector = childSelector;
+  return *this;
+}
+
+inline uint8_t
+Interest::getChildSelector () const
+{
+  return m_childSelector;
+}
+
+inline Interest &
+Interest::setPublisherPublicKeyDigest(const Hash &publisherPublicKeyDigest)
+{
+  m_publisherPublicKeyDigest = publisherPublicKeyDigest;
+  return *this;
+}
+
+inline const Hash&
+Interest::getPublisherPublicKeyDigest () const
+{
+  return m_publisherPublicKeyDigest;
+}
+
+inline void
+Interest::setExclude (const Exclude &exclude)
+{
+  m_exclude = exclude;
+}
+
+/**
+ * @brief Get exclude filter (const reference)
+ */
+inline const Exclude &
+Interest::getExclude () const
+{
+  return m_exclude;
+}
+
+/**
+ * @brief Get exclude filter (reference)
+ */
+inline Exclude &
+Interest::getExclude ()
+{
+  return m_exclude;
+}
+
+
+} // ndn
+
+#endif // NDN_INTEREST_H
diff --git a/ndn-cpp/security/certificate.h b/ndn-cpp/security/certificate.h
new file mode 100644
index 0000000..e0efa91
--- /dev/null
+++ b/ndn-cpp/security/certificate.h
@@ -0,0 +1,43 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_CERTIFICATE_H
+#define NDN_CERTIFICATE_H
+
+#include "ndn-cpp/data.h"
+
+namespace ndn {
+
+/**
+ * @brief Class representing NDN identity
+ *
+ * - name
+ *   - full NDN name of the NDN certificate
+ *     - /ndn/ucla.edu/alex/cert/<pubkey.sha256>/<issuer>
+ * - content
+ *   - X.509 certificate in DER format (X.509 certificate can include any necessary identity information, as well as is fully extendable)
+ *     - Subject: 
+ *       - full real name, associated with the certificate
+ *       - full affiliation, associated with the certificate
+ *     - Subject Public Key Info
+ *     - Validity
+ * - signature
+ *   - issuerCertName (KeyLocator/CertName)
+ *     - /ndn/ucla.edu/cert/<pubkey.sha256>/<issuer>
+ *
+ */
+class Certificate : public Data
+{
+public:
+};
+
+} // ndn
+
+#endif // NDN_CERTIFICATE_H
diff --git a/ndn-cpp/security/identity.h b/ndn-cpp/security/identity.h
new file mode 100644
index 0000000..676b3b3
--- /dev/null
+++ b/ndn-cpp/security/identity.h
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_IDENTITY_H
+#define NDN_IDENTITY_H
+
+namespace ndn {
+
+/**
+ * @brief Class representing NDN identity
+ *
+ * - name 
+ *   - (indexing and lookup)
+ *   - /ndn/ucla.edu/alex
+ * - contents
+ *   - privateKeyName
+ *     - unique name of the private key
+ *     - private key bits are not exposed anywhere
+ *     - /ndn/ucla.edu/alex/privKey/<pubkey.sha256>
+ *   - indexed list of certificates
+ *     - NDN DATA packets
+ *     - easy access data structure of NDN certificate (“parsed DATA packet”)
+ *   - link to default certificate
+ *   - revocation list
+ *     - one or more NDN DATA packets
+ *     - name: <identity-name>/revocation-list/<version>(/<seqno>)?
+ *       - /ndn/ucla.edu/alex/revocation-list/%FD...01
+ *       - initially empty, updated whenever an issued certificate is getting revoked
+ *     - revocation always exists
+ *
+ */
+class Identity
+{
+public:
+};
+
+} // ndn
+
+#endif // NDN_IDENTITY_H
diff --git a/ndn-cpp/security/keychain-pkcs12.cc b/ndn-cpp/security/keychain-pkcs12.cc
new file mode 100644
index 0000000..8a01fd5
--- /dev/null
+++ b/ndn-cpp/security/keychain-pkcs12.cc
@@ -0,0 +1,69 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "keychain-pkcs12.h"
+
+namespace ndn {
+
+/////////////////////////////////////////////////////
+// interface to manage certificates and identities //
+/////////////////////////////////////////////////////
+
+Ptr<const Identity>
+KeychainKeystoreOpenssl::getDefaultIdentity ()
+{
+  return Ptr<const Identity> ();
+}
+
+Ptr<const Identity>
+KeychainKeystoreOpenssl::getIdentity (const Name &identityName)
+{
+  return Ptr<const Identity> ();
+}
+
+Ptr<const Identity>
+KeychainKeystoreOpenssl::generateIdentity (const Name &identityName)
+{
+  return Ptr<const Identity> ();
+}
+
+void
+KeychainKeystoreOpenssl::requestIdentityCertificate (const Identity &identity, std::ostream &os)
+{
+}
+
+Ptr<const Certificate>
+KeychainKeystoreOpenssl::issueCertificate (const Identity &identity, std::istream &is)
+{
+  return Ptr<const Certificate> ();
+}
+
+Ptr<const Certificate>
+KeychainKeystoreOpenssl::issueCertificate (std::istream &is)
+{
+  return Ptr<const Certificate> ();
+}
+
+void
+KeychainKeystoreOpenssl::installIdentityCertificate (const Certificate &cert)
+{
+}
+
+/////////////////////////////////////////////////////
+//       interface to sign and encrypt data        //
+/////////////////////////////////////////////////////
+Ptr<Signature>
+KeychainKeystoreOpenssl::sign (const Identity &identity, const void *buffer, size_t size)
+{
+  return Ptr<Signature> ();
+}
+
+
+} // ndn
diff --git a/ndn-cpp/security/keychain-pkcs12.h b/ndn-cpp/security/keychain-pkcs12.h
new file mode 100644
index 0000000..898d792
--- /dev/null
+++ b/ndn-cpp/security/keychain-pkcs12.h
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_KEYCHAIN_PKCS12_H
+#define NDN_KEYCHAIN_PKCS12_H
+
+#include "keychain.h"
+#include "ndn-cpp/helpers/hash.h"
+
+namespace ndn
+{
+
+/**
+ * @brief Class implementing logic to work with pkcs12 CCNx keystore file (.ccnx_keystore)
+ */
+class KeychainKeystoreOpenssl : public virtual Keychain
+{
+public:
+  KeychainKeystoreOpenssl ();
+  KeychainKeystoreOpenssl (const std::string &path);
+
+public:
+  /////////////////////////////////////////////////////
+  // interface to manage certificates and identities //
+  /////////////////////////////////////////////////////
+
+  virtual Ptr<const Identity>
+  getDefaultIdentity ();
+
+  virtual Ptr<const Identity>
+  getIdentity (const Name &identityName);
+
+  virtual Ptr<const Identity>
+  generateIdentity (const Name &identityName);
+
+  virtual void
+  requestIdentityCertificate (const Identity &identity, std::ostream &os);
+
+  virtual Ptr<const Certificate>
+  issueCertificate (const Identity &identity, std::istream &is);
+
+  virtual Ptr<const Certificate>
+  issueCertificate (std::istream &is);
+
+  virtual void
+  installIdentityCertificate (const Certificate &cert);
+
+public:
+  /////////////////////////////////////////////////////
+  //       interface to sign and encrypt data        //
+  /////////////////////////////////////////////////////
+  virtual Ptr<Signature>
+  sign (const Identity &identity, const void *buffer, size_t size);
+
+  
+private:
+  void
+  initialize (const std::string &pkcs12);
+  
+private:
+  Name m_publicKeyName;
+  Hash m_publicKeyDigest;
+};
+  
+} // ndn
+
+#endif // NDN_KEYCHAIN_KEYSTORE_OPENSSL_H
diff --git a/ndn-cpp/security/keychain.cc b/ndn-cpp/security/keychain.cc
new file mode 100644
index 0000000..2f7fbe5
--- /dev/null
+++ b/ndn-cpp/security/keychain.cc
@@ -0,0 +1,15 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "keychain.h"
+
+ndn::Keychain::~Keychain ()
+{
+}
diff --git a/ndn-cpp/security/keychain.h b/ndn-cpp/security/keychain.h
new file mode 100644
index 0000000..83a09dd
--- /dev/null
+++ b/ndn-cpp/security/keychain.h
@@ -0,0 +1,130 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_KEYCHAIN_H
+#define NDN_KEYCHAIN_H
+
+// #include "ndn-cpp/fields/blob.h"
+// #include "ndn-cpp/fields/name.h"
+
+#include "identity.h"
+#include "certificate.h"
+
+#include <iostream>
+
+namespace ndn {
+
+/**
+ * @brief Interface for a keychain operations
+ *
+ * Keychain has the following set of operations:
+ *
+ * --- interface to manage certificates and identities
+ *     - identities are permanently stored
+ *     - certificates can be cached (or stored permanently, if user is willing to)
+ * --- interface to sign and encrypt data
+ *
+ */
+class Keychain
+{
+public:
+  /**
+   * @brief Virtual destructor
+   */
+  virtual
+  ~Keychain ();
+
+  /////////////////////////////////////////////////////
+  // interface to manage certificates and identities //
+  /////////////////////////////////////////////////////
+
+  /**
+   * @brief Get default identity
+   */
+  virtual Ptr<const Identity>
+  getDefaultIdentity () = 0;
+
+  /**
+   * @brief Get identity by name
+   * @param identityName name of the requested identity
+   */
+  virtual Ptr<const Identity>
+  getIdentity (const Name &identityName) = 0;
+
+  /**
+   * @brief Create a self-certified identity
+   * @param identityName name of the identity to create
+   */
+  virtual Ptr<const Identity>
+  generateIdentity (const Name &identityName) = 0;
+
+  /**
+   * @brief Create identity certification request
+   * @param identity identity for which create the request
+   * @param os output stream which will receive the request
+   */
+  virtual void
+  requestIdentityCertificate (const Identity &identity, std::ostream &os) = 0;
+
+  /**
+   * @brief Issue a certificate using parameters from the input stream (formatted as request)
+   * @param identity Identity which will be used to issue the certificate
+   * @param is input stream from which to read parameters of the certificate
+   *
+   * @returns smart pointer to a signed certificate
+   */
+  virtual Ptr<const Certificate>
+  issueCertificate (const Identity &identity, std::istream &is) = 0;
+
+  /**
+   * @brief Issue a certificate using parameters from the input stream (formatted as request)
+   *
+   * Same as another version, but using the default identity
+   *
+   * @returns smart pointer to a signed certificate
+   */
+  virtual Ptr<const Certificate>
+  issueCertificate (std::istream &is) = 0;
+
+  /**
+   * @brief Install identity certificate
+   * @param cert certificate to install
+   */
+  virtual void
+  installIdentityCertificate (const Certificate &cert) = 0;
+
+public:
+  /////////////////////////////////////////////////////
+  //       interface to sign and encrypt data        //
+  /////////////////////////////////////////////////////
+
+  /**
+   * @brief Sign data using specified identity
+   * @param identity selected identity to sign data
+   * @param buffer pointer to the data to sign
+   * @param size length of data to sign
+   *
+   * @return pointer to base class of a signature object (depending on identity,
+   *         different types signature can be produced)
+   */
+  virtual Ptr<Signature>
+  sign (const Identity &identity, const void *buffer, size_t size) = 0;
+
+  // TBD
+  // /**
+  //  * @brief Decrypt data using the specified identity
+  //  */
+  // virtual ?
+  // decrypt (Ptr<Identity> identity, const void *buffer, size_t size, ?) = 0;
+};
+
+} // ndn
+
+#endif // NDN_KEYCHAIN_H
diff --git a/ndn-cpp/security/verifier.h b/ndn-cpp/security/verifier.h
new file mode 100644
index 0000000..cb98243
--- /dev/null
+++ b/ndn-cpp/security/verifier.h
@@ -0,0 +1,38 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_VERIFIER_H
+#define NDN_VERIFIER_H
+
+namespace ndn {
+
+/**
+ * @brief Interface for NDN DATA packet verification (trust model)
+ *
+ * --- interface to verify DATA packets
+ *     - application selects required implementation
+ *     - at least two build-in models:
+ *       = hierarchical (default)
+ *       = simple chain (without authorization)
+ *     - uses NDN keychain as a backend to cache certificates
+ */
+class Verifier
+{
+public:
+  /**
+   * @brief Virtual destructor
+   */
+  virtual
+  ~Verifier ();
+};
+
+} // ndn
+
+#endif // NDN_VERIFIER_H
diff --git a/ndn-cpp/trie/detail/functor-hook.h b/ndn-cpp/trie/detail/functor-hook.h
new file mode 100644
index 0000000..f34969c
--- /dev/null
+++ b/ndn-cpp/trie/detail/functor-hook.h
@@ -0,0 +1,70 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef FUNCTOR_HOOK_H_
+#define FUNCTOR_HOOK_H_
+
+#include <boost/intrusive/parent_from_member.hpp>
+
+namespace ns3 {
+namespace ndn {
+namespace ndnSIM {
+namespace detail {
+
+template<class BaseHook, class ValueType, int N>
+struct FunctorHook
+{
+  typedef typename BaseHook::template index<N>::type hook_type;
+  typedef hook_type*            hook_ptr;
+  typedef const hook_type*      const_hook_ptr;
+  
+  typedef ValueType             value_type;
+  typedef value_type*           pointer;
+  typedef const value_type*     const_pointer;
+  
+  //Required static functions
+  static hook_ptr to_hook_ptr (value_type &value)
+  {  return &value.policy_hook_.template get<N> (); }
+  
+  static const_hook_ptr to_hook_ptr(const value_type &value)
+  {  return &value.policy_hook_.template get<N> (); }
+  
+  static pointer to_value_ptr(hook_ptr n)
+  {
+    return
+      boost::intrusive::get_parent_from_member<value_type>
+      (static_cast<BaseHook*> (boost::intrusive::get_parent_from_member< wrap<hook_type> >(n, &wrap<hook_type>::value_)),
+       &value_type::policy_hook_);
+  }
+  static const_pointer to_value_ptr(const_hook_ptr n)
+  {
+    return
+      boost::intrusive::get_parent_from_member<value_type>
+      (static_cast<const BaseHook*> (boost::intrusive::get_parent_from_member< wrap<hook_type> >(n, &wrap<hook_type>::value_)),
+       &value_type::policy_hook_);
+  }
+};
+
+} // detail
+} // ndnSIM
+} // ndn
+} // ns3
+
+#endif // FUNCTOR_HOOK_H_
diff --git a/ndn-cpp/trie/detail/multi-policy-container.h b/ndn-cpp/trie/detail/multi-policy-container.h
new file mode 100644
index 0000000..c1251e9
--- /dev/null
+++ b/ndn-cpp/trie/detail/multi-policy-container.h
@@ -0,0 +1,175 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef MULTI_POLICY_CONTAINER_H_
+#define MULTI_POLICY_CONTAINER_H_
+
+#include <boost/mpl/inherit_linearly.hpp>
+#include <boost/mpl/at.hpp>
+
+namespace ns3 {
+namespace ndn {
+namespace ndnSIM {
+namespace detail {
+
+template< class Base, class Value >
+struct policy_wrap
+{
+  policy_wrap (Base &base) : value_ (base) { }
+  Value value_;
+};
+
+template< class Base, class Super/*empy_wrap/previous level*/, class Value/*policy_wrap< element in vector >*/ >
+struct inherit_with_base : Super, Value
+{
+  inherit_with_base (Base &base) : Super (base), Value (base) { }
+
+  void
+  update (typename Base::iterator item)
+  {
+    Value::value_.update (item);
+    Super::update (item);
+  }
+
+  bool
+  insert (typename Base::iterator item)
+  {
+    bool ok = Value::value_.insert (item);
+    if (!ok)
+      return false;
+
+    ok = Super::insert (item);
+    if (!ok)
+      {
+        Value::value_.erase (item);
+        return false;
+      }
+    return true;
+  }
+
+  void
+  lookup (typename Base::iterator item)
+  {
+    Value::value_.lookup (item);
+    Super::lookup (item);
+  }
+
+  void
+  erase (typename Base::iterator item)
+  {
+    Value::value_.erase (item);
+    Super::erase (item);
+  }  
+
+  void
+  clear ()
+  {
+    Value::value_.clear ();
+    Super::clear ();
+  }
+};
+
+template< class Base >
+struct empty_policy_wrap
+{
+  empty_policy_wrap (Base &base) { }
+
+  void update (typename Base::iterator item) {}
+  bool insert (typename Base::iterator item) { return true; }
+  void lookup (typename Base::iterator item) {}
+  void erase (typename Base::iterator item) {}
+  void clear () {}
+};
+
+template< class Base, class Vector >
+struct multi_policy_container
+  : public boost::mpl::fold< Vector,
+                      empty_policy_wrap<Base>,
+                      inherit_with_base<Base,
+                                        boost::mpl::_1/*empty/previous*/,
+                                        policy_wrap<Base, boost::mpl::_2>/*element in vector*/>
+                      >::type
+{
+  typedef typename boost::mpl::fold< Vector,
+                              empty_policy_wrap<Base>,
+                              inherit_with_base<Base,
+                                                boost::mpl::_1/*empty/previous*/,
+                                                policy_wrap<Base, boost::mpl::_2>/*element in vector*/>
+                              >::type super;
+
+  typedef typename boost::mpl::at_c<Vector, 0>::type::iterator iterator;
+  typedef typename boost::mpl::at_c<Vector, 0>::type::const_iterator const_iterator;
+
+  iterator begin ()             { return this->get<0> ().begin (); }
+  const_iterator begin () const { return this->get<0> ().begin (); }
+
+  iterator end ()             { return this->get<0> ().end (); }
+  const_iterator end () const { return this->get<0> ().end (); }
+
+  size_t size () const { return this->get<0> ().size (); }
+  
+  multi_policy_container (Base &base)
+  : super (base)
+  { }
+
+  template<int N>
+  struct index
+  {
+    typedef typename boost::mpl::at_c<Vector, N>::type type;
+  };
+  
+  template<class T>
+  T &
+  get ()
+  {
+    return static_cast< policy_wrap<Base, T> &> (*this).value_;
+  }
+
+  template<class T>
+  const T &
+  get () const
+  {
+    return static_cast< const policy_wrap<Base, T> &> (*this).value_;
+  }
+
+  template<int N>
+  typename boost::mpl::at_c<Vector, N>::type &
+  get ()
+  {
+    typedef typename boost::mpl::at_c<Vector, N>::type T;
+    return static_cast< policy_wrap<Base, T> &> (*this).value_;
+  }
+
+  template<int N>
+  const typename boost::mpl::at_c<Vector, N>::type &
+  get () const
+  {
+    typedef typename boost::mpl::at_c<Vector, N>::type T;
+    return static_cast< const policy_wrap<Base, T> &> (*this).value_;
+  }
+};
+
+
+} // detail
+} // ndnSIM
+} // ndn
+} // ns3
+
+#endif // MULTI_POLICY_CONTAINER_H_
diff --git a/ndn-cpp/trie/detail/multi-type-container.h b/ndn-cpp/trie/detail/multi-type-container.h
new file mode 100644
index 0000000..d4971c4
--- /dev/null
+++ b/ndn-cpp/trie/detail/multi-type-container.h
@@ -0,0 +1,86 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef MULTI_TYPE_CONTAINER_H_
+#define MULTI_TYPE_CONTAINER_H_
+
+#include <boost/mpl/inherit_linearly.hpp>
+#include <boost/mpl/inherit.hpp>
+#include <boost/mpl/at.hpp>
+
+namespace ns3 {
+namespace ndn {
+namespace ndnSIM {
+namespace detail {
+
+template <class T>
+struct wrap
+{
+  T value_;
+};
+
+template< class Vector >
+struct multi_type_container
+  : public boost::mpl::inherit_linearly< Vector, boost::mpl::inherit<wrap<boost::mpl::_2>, boost::mpl::_1 >
+  >::type
+{
+  template<int N>
+  struct index
+  {
+    typedef typename boost::mpl::at_c<Vector, N>::type type;
+  };
+  
+  template<class T>
+  T &
+  get ()
+  {
+    return static_cast< wrap<T> &> (*this).value_;
+  }
+
+  template<class T>
+  const T &
+  get () const
+  {
+    return static_cast< const wrap<T> &> (*this).value_;
+  }
+  
+  template<int N>
+  typename boost::mpl::at_c<Vector, N>::type &
+  get ()
+  {
+    typedef typename boost::mpl::at_c<Vector, N>::type T;
+    return static_cast< wrap<T> &> (*this).value_;
+  }
+
+  template<int N>
+  const typename boost::mpl::at_c<Vector, N>::type &
+  get () const
+  {
+    typedef typename boost::mpl::at_c<Vector, N>::type T;
+    return static_cast< const wrap<T> &> (*this).value_;
+  }
+};
+  
+} // detail
+} // ndnSIM
+} // ndn
+} // ns3
+
+#endif // MULTI_TYPE_CONTAINER_H_
diff --git a/ndn-cpp/trie/payload-traits/pointer.h b/ndn-cpp/trie/payload-traits/pointer.h
new file mode 100644
index 0000000..8290fbe
--- /dev/null
+++ b/ndn-cpp/trie/payload-traits/pointer.h
@@ -0,0 +1,40 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_TRIE_PAYLOAD_TRAITS_POINTER_H
+#define NDN_TRIE_PAYLOAD_TRAITS_POINTER_H
+
+namespace ndn {
+namespace trie {
+
+template<typename Payload, typename BasePayload = Payload>
+struct pointer_payload_traits
+{
+  typedef Payload         payload_type; // general type of the payload
+  typedef Payload*        storage_type; // how the payload is actually stored
+  typedef Payload*        insert_type;  // what parameter is inserted
+
+  typedef Payload*        return_type;  // what is returned on access
+  typedef const Payload*  const_return_type; // what is returned on const access
+
+  typedef BasePayload*       base_type;       // base type of the entry (when implementation details need to be hidden)
+  typedef const BasePayload* const_base_type; // const base type of the entry (when implementation details need to be hidden)
+
+  static Payload* empty_payload;
+};
+
+template<typename Payload, typename BasePayload>
+Payload*
+pointer_payload_traits<Payload, BasePayload>::empty_payload = NULL;
+
+} // trie
+} // ndn
+
+#endif // NDN_TRIE_PAYLOAD_TRAITS_POINTER_H
diff --git a/ndn-cpp/trie/payload-traits/ptr.h b/ndn-cpp/trie/payload-traits/ptr.h
new file mode 100644
index 0000000..3caf020
--- /dev/null
+++ b/ndn-cpp/trie/payload-traits/ptr.h
@@ -0,0 +1,40 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_TRIE_PAYLOAD_TRAITS_PTR_H
+#define NDN_TRIE_PAYLOAD_TRAITS_PTR_H
+
+namespace ndn {
+namespace trie {
+
+template<typename Payload, typename BasePayload = Payload>
+struct ptr_payload_traits
+{
+  typedef Payload            payload_type;
+  typedef Ptr<Payload>       storage_type;
+  typedef Ptr<Payload>       insert_type;
+
+  typedef Ptr<Payload>       return_type;
+  typedef Ptr<const Payload> const_return_type;
+
+  typedef Ptr<BasePayload> base_type;
+  typedef Ptr<const BasePayload> const_base_type;
+
+  static Ptr<Payload> empty_payload;
+};
+
+template<typename Payload, typename BasePayload>
+Ptr<Payload>
+ptr_payload_traits<Payload, BasePayload>::empty_payload; // = Ptr<Payload> ();
+
+} // trie
+} // ndn
+
+#endif // NDN_TRIE_PAYLOAD_TRAITS_PTR_H
diff --git a/ndn-cpp/trie/policies/counting-policy.h b/ndn-cpp/trie/policies/counting-policy.h
new file mode 100644
index 0000000..d27f915
--- /dev/null
+++ b/ndn-cpp/trie/policies/counting-policy.h
@@ -0,0 +1,101 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef COUNTING_POLICY_H_
+#define COUNTING_POLICY_H_
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for policy that just keeps track of number of elements
+ * It's doing a rather expensive job, but just in case it needs to be extended later
+ */
+struct counting_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return "Counting"; }
+
+  struct policy_hook_type : public boost::intrusive::list_member_hook<> {};
+
+  template<class Container>
+  struct container_hook
+  {
+    // could be class/struct implementation
+    typedef boost::intrusive::member_hook< Container,
+                             policy_hook_type,
+                             &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    typedef typename boost::intrusive::list< Container, Hook > policy_container;
+    
+    // could be just typedef
+    class type : public policy_container
+    {
+    public:
+      typedef Container parent_trie;
+
+      type (Base &base)
+        : base_ (base)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+  
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        policy_container::push_back (*item);
+        return true;
+      }
+  
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+  
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+    private:
+      type () : base_(*((Base*)0)) { };
+
+    private:
+      Base &base_;
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif // COUNTING_POLICY_H_
diff --git a/ndn-cpp/trie/policies/empty-policy.h b/ndn-cpp/trie/policies/empty-policy.h
new file mode 100644
index 0000000..0cfe962
--- /dev/null
+++ b/ndn-cpp/trie/policies/empty-policy.h
@@ -0,0 +1,50 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef EMPTY_POLICY_H_
+#define EMPTY_POLICY_H_
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for empty (bogus) replacement policy
+ */
+struct empty_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return ""; }
+
+  typedef void* policy_hook_type;
+
+  template<class Container> struct container_hook { typedef void* type; };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    struct type
+    {
+      inline type (Base &base) {}
+      
+      inline void update (typename Container::iterator) { }
+      inline bool insert (typename Container::iterator) { return true; }
+      inline void lookup (typename Container::iterator item) { }
+      inline void erase (typename Container::iterator item) { }
+      inline void clear () { }
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif // EMPTY_POLICY_H_
diff --git a/ndn-cpp/trie/policies/fifo-policy.h b/ndn-cpp/trie/policies/fifo-policy.h
new file mode 100644
index 0000000..7acad2b
--- /dev/null
+++ b/ndn-cpp/trie/policies/fifo-policy.h
@@ -0,0 +1,119 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef FIFO_POLICY_H_
+#define FIFO_POLICY_H_
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for First In First Out replacement policy
+ */
+struct fifo_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return "Fifo"; }
+
+  struct policy_hook_type : public boost::intrusive::list_member_hook<> {};
+
+  template<class Container>
+  struct container_hook
+  {
+    // could be class/struct implementation
+    typedef boost::intrusive::member_hook< Container,
+                             policy_hook_type,
+                             &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    typedef typename boost::intrusive::list< Container, Hook > policy_container;
+    
+    // could be just typedef
+    class type : public policy_container
+    {
+    public:
+      typedef Container parent_trie;
+
+      type (Base &base)
+        : base_ (base)
+        , max_size_ (100)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+  
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
+          {
+            base_.erase (&(*policy_container::begin ()));
+          }
+      
+        policy_container::push_back (*item);
+        return true;
+      }
+  
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+  
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      inline void
+      set_max_size (size_t max_size)
+      {
+        max_size_ = max_size;
+      }
+
+      inline size_t
+      get_max_size () const
+      {
+        return max_size_;
+      }
+
+    private:
+      type () : base_(*((Base*)0)) { };
+
+    private:
+      Base &base_;
+      size_t max_size_;
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif
diff --git a/ndn-cpp/trie/policies/lfu-policy.h b/ndn-cpp/trie/policies/lfu-policy.h
new file mode 100644
index 0000000..802f64b
--- /dev/null
+++ b/ndn-cpp/trie/policies/lfu-policy.h
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef LFU_POLICY_H_
+#define LFU_POLICY_H_
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/set.hpp>
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for LFU replacement policy
+ */
+struct lfu_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return "Lfu"; }
+
+  struct policy_hook_type : public boost::intrusive::set_member_hook<> { double frequency; };
+
+  template<class Container>
+  struct container_hook
+  {
+    typedef boost::intrusive::member_hook< Container,
+                                           policy_hook_type,
+                                           &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy
+  {
+    static double& get_order (typename Container::iterator item)
+    {
+      return static_cast<policy_hook_type*>
+        (policy_container::value_traits::to_node_ptr(*item))->frequency;
+    }
+
+    static const double& get_order (typename Container::const_iterator item)
+    {
+      return static_cast<const policy_hook_type*>
+        (policy_container::value_traits::to_node_ptr(*item))->frequency;
+    }
+
+    template<class Key>
+    struct MemberHookLess
+    {
+      bool operator () (const Key &a, const Key &b) const
+      {
+        return get_order (&a) < get_order (&b);
+      }
+    };
+
+    typedef boost::intrusive::multiset< Container,
+                                   boost::intrusive::compare< MemberHookLess< Container > >,
+                                   Hook > policy_container;
+
+    // could be just typedef
+    class type : public policy_container
+    {
+    public:
+      typedef policy policy_base; // to get access to get_order methods from outside
+      typedef Container parent_trie;
+
+      type (Base &base)
+        : base_ (base)
+        , max_size_ (100)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+        get_order (item) += 1;
+        policy_container::insert (*item);
+      }
+
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        get_order (item) = 0;
+
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
+          {
+            // this erases the "least frequently used item" from cache
+            base_.erase (&(*policy_container::begin ()));
+          }
+
+        policy_container::insert (*item);
+        return true;
+      }
+
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+        get_order (item) += 1;
+        policy_container::insert (*item);
+      }
+
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      inline void
+      set_max_size (size_t max_size)
+      {
+        max_size_ = max_size;
+      }
+
+      inline size_t
+      get_max_size () const
+      {
+        return max_size_;
+      }
+
+    private:
+      type () : base_(*((Base*)0)) { };
+
+    private:
+      Base &base_;
+      size_t max_size_;
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif // LFU_POLICY_H
diff --git a/ndn-cpp/trie/policies/lru-policy.h b/ndn-cpp/trie/policies/lru-policy.h
new file mode 100644
index 0000000..ad3a382
--- /dev/null
+++ b/ndn-cpp/trie/policies/lru-policy.h
@@ -0,0 +1,124 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef LRU_POLICY_H_
+#define LRU_POLICY_H_
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for Least Recently Used replacement policy
+ */
+struct lru_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return "Lru"; }
+  
+  struct policy_hook_type : public boost::intrusive::list_member_hook<> {};
+
+  template<class Container>
+  struct container_hook
+  {
+    typedef boost::intrusive::member_hook< Container,
+                                           policy_hook_type,
+                                           &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    typedef typename boost::intrusive::list< Container, Hook > policy_container;
+    
+    // could be just typedef
+    class type : public policy_container
+    {
+    public:
+      typedef Container parent_trie;
+    
+      type (Base &base)
+        : base_ (base)
+        , max_size_ (100)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        // do relocation
+        policy_container::splice (policy_container::end (),
+                                  *this,
+                                  policy_container::s_iterator_to (*item));
+      }
+  
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
+          {
+            base_.erase (&(*policy_container::begin ()));
+          }
+      
+        policy_container::push_back (*item);
+        return true;
+      }
+  
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        // do relocation
+        policy_container::splice (policy_container::end (),
+                                  *this,
+                                  policy_container::s_iterator_to (*item));
+      }
+  
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      inline void
+      set_max_size (size_t max_size)
+      {
+        max_size_ = max_size;
+      }
+
+      inline size_t
+      get_max_size () const
+      {
+        return max_size_;
+      }
+
+    private:
+      type () : base_(*((Base*)0)) { };
+
+    private:
+      Base &base_;
+      size_t max_size_;
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif
diff --git a/ndn-cpp/trie/policies/multi-policy.h b/ndn-cpp/trie/policies/multi-policy.h
new file mode 100644
index 0000000..739de7b
--- /dev/null
+++ b/ndn-cpp/trie/policies/multi-policy.h
@@ -0,0 +1,177 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef MULTI_POLICY_H_
+#define MULTI_POLICY_H_
+
+#include "detail/multi-type-container.h"
+#include "detail/multi-policy-container.h"
+#include "detail/functor-hook.h"
+
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/for_each.hpp>
+
+#include <boost/intrusive/options.hpp>
+
+namespace ndn {
+namespace trie {
+
+template<typename Policies> // e.g., mpl::vector1< lru_policy_traits >
+struct multi_policy_traits
+{
+  typedef Policies policy_traits;
+
+  struct getHook { template<class Item> struct apply { typedef typename Item::policy_hook_type type; }; };
+  typedef detail::multi_type_container< typename boost::mpl::transform1<policy_traits, getHook>::type > policy_hook_type;
+  
+  template<class Container>
+  struct container_hook
+  {
+    typedef policy_hook_type type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    typedef boost::mpl::range_c<int, 0, boost::mpl::size<policy_traits>::type::value> policies_range;
+
+    struct getPolicy
+    {
+      template<class Number>
+      struct apply
+      {
+        typedef
+        typename boost::mpl::at_c<policy_traits, Number::value>::type::
+        template policy<Base,
+                        Container,
+                        boost::intrusive::function_hook< detail::FunctorHook <Hook,
+                                                                              Container,
+                                                                              Number::value> > >::type
+        type;
+      };
+    };
+    
+    typedef
+    typename boost::mpl::transform1<policies_range,
+                                    getPolicy,
+                                    boost::mpl::back_inserter< boost::mpl::vector0<> > >::type policies;
+                             
+    
+    typedef detail::multi_policy_container< Base, policies > policy_container;
+    
+    class type : public policy_container
+    {
+    public:
+      typedef policy policy_base; // to get access to get_time methods from outside
+      typedef Container parent_trie;
+
+      type (Base &base)
+        : policy_container (base)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        policy_container::update (item);
+      }
+  
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        return policy_container::insert (item);
+      }
+  
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        policy_container::lookup (item);
+      }
+  
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (item);
+      }
+      
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      struct max_size_setter
+      {
+        max_size_setter (policy_container &container, size_t size) : m_container (container), m_size (size) { }
+        
+        template< typename U > void operator() (U index)
+        {
+          m_container.template get<U::value> ().set_max_size (m_size);
+        }
+
+      private:
+        policy_container &m_container;
+        size_t m_size;
+      };
+      
+      inline void
+      set_max_size (size_t max_size)
+      {
+        boost::mpl::for_each< boost::mpl::range_c<int, 0, boost::mpl::size<policy_traits>::type::value> >
+          (max_size_setter (*this, max_size));
+      }
+
+      inline size_t
+      get_max_size () const
+      {
+        // as max size should be the same everywhere, get the value from the first available policy
+        return policy_container::template get<0> ().get_max_size ();
+      }
+      
+    };
+  };
+
+
+  struct name_getter
+  {
+    name_getter (std::string &name) : m_name (name) { }
+    
+    template< typename U > void operator() (U index)
+    {
+      if (!m_name.empty ())
+        m_name += "::";
+      m_name += boost::mpl::at_c< policy_traits, U::value >::type::GetName ();
+    }
+
+    std::string &m_name;
+  };
+
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName ()
+  {
+    // combine names of all internal policies
+    std::string name;
+    boost::mpl::for_each< boost::mpl::range_c<int, 0, boost::mpl::size<policy_traits>::type::value> > (name_getter (name));
+    
+    return name;
+  }
+};
+
+} // trie
+} // ndn
+
+#endif // MULTI_POLICY_H_
diff --git a/ndn-cpp/trie/policies/persistent-policy.h b/ndn-cpp/trie/policies/persistent-policy.h
new file mode 100644
index 0000000..d34f373
--- /dev/null
+++ b/ndn-cpp/trie/policies/persistent-policy.h
@@ -0,0 +1,119 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef PERSISTENT_POLICY_H_
+#define PERSISTENT_POLICY_H_
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for persistent replacement policy
+ *
+ * In this policy entries are added until there is a space (controlled by set_max_size call).
+ * If maximum is reached, new entries will not be added and nothing will be removed from the container
+ */
+struct persistent_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return "Persistent"; }
+
+  struct policy_hook_type : public boost::intrusive::list_member_hook<> {};
+
+  template<class Container>
+  struct container_hook
+  {
+    typedef boost::intrusive::member_hook< Container,
+                                           policy_hook_type,
+                                           &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    typedef typename boost::intrusive::list< Container, Hook > policy_container;
+    
+    // could be just typedef
+    class type : public policy_container
+    {
+    public:
+      typedef Container parent_trie;
+    
+      type (Base &base)
+        : base_ (base)
+        , max_size_ (100) // when 0, policy is not enforced
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+  
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
+          return false;
+      
+        policy_container::push_back (*item);
+        return true;
+      }
+  
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        // do nothing
+      }
+  
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      inline void
+      set_max_size (size_t max_size)
+      {
+        max_size_ = max_size;
+      }
+
+      inline size_t
+      get_max_size () const
+      {
+        return max_size_;
+      }
+
+    private:
+      // type () : base_(*((Base*)0)) { };
+
+    private:
+      Base &base_;
+      size_t max_size_;
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif // PERSISTENT_POLICY_H_
diff --git a/ndn-cpp/trie/policies/random-policy.h b/ndn-cpp/trie/policies/random-policy.h
new file mode 100644
index 0000000..d896e89
--- /dev/null
+++ b/ndn-cpp/trie/policies/random-policy.h
@@ -0,0 +1,158 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef RANDOM_POLICY_H_
+#define RANDOM_POLICY_H_
+
+#include "ns3/random-variable.h"
+
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/set.hpp>
+
+namespace ndn {
+namespace trie {
+
+/**
+ * @brief Traits for random replacement policy
+ */
+struct random_policy_traits
+{
+  /// @brief Name that can be used to identify the policy (e.g., for logging)
+  static std::string GetName () { return "Random"; }
+
+  struct policy_hook_type : public boost::intrusive::set_member_hook<> { uint32_t randomOrder; };
+
+  template<class Container>
+  struct container_hook
+  {
+    typedef boost::intrusive::member_hook< Container,
+                                           policy_hook_type,
+                                           &Container::policy_hook_ > type;
+  };
+
+  template<class Base,
+           class Container,
+           class Hook>
+  struct policy 
+  {
+    static uint32_t& get_order (typename Container::iterator item)
+    {
+      return static_cast<typename policy_container::value_traits::hook_type*>
+        (policy_container::value_traits::to_node_ptr(*item))->randomOrder;
+    }
+      
+    static const uint32_t& get_order (typename Container::const_iterator item)
+    {
+      return static_cast<const typename policy_container::value_traits::hook_type*>
+        (policy_container::value_traits::to_node_ptr(*item))->randomOrder;
+    }
+    
+    template<class Key>
+    struct MemberHookLess
+    {
+      bool operator () (const Key &a, const Key &b) const
+      {
+        return get_order (&a) < get_order (&b);
+      }
+    };
+
+    typedef boost::intrusive::multiset< Container,
+                                   boost::intrusive::compare< MemberHookLess< Container > >,
+                                   Hook > policy_container;
+    
+    // could be just typedef
+    class type : public policy_container
+    {
+    public:
+      typedef policy policy_base; // to get access to get_order methods from outside
+      typedef Container parent_trie;
+
+      type (Base &base)
+        : base_ (base)
+        , u_rand (0, std::numeric_limits<uint32_t>::max ())
+        , max_size_ (100)
+      {
+      }
+
+      inline void
+      update (typename parent_trie::iterator item)
+      {
+        // do nothing. it's random policy
+      }
+  
+      inline bool
+      insert (typename parent_trie::iterator item)
+      {
+        get_order (item) = u_rand.GetValue ();
+
+        if (max_size_ != 0 && policy_container::size () >= max_size_)
+          {
+            if (MemberHookLess<Container>() (*item, *policy_container::begin ()))
+              {
+                // std::cout << "Cannot add. Signaling fail\n";
+                // just return false. Indicating that insert "failed"
+                return false;
+              }
+            else
+              {
+                // removing some random element
+                base_.erase (&(*policy_container::begin ()));
+              }
+          }
+
+        policy_container::insert (*item);
+        return true;
+      }
+  
+      inline void
+      lookup (typename parent_trie::iterator item)
+      {
+        // do nothing. it's random policy
+      }
+  
+      inline void
+      erase (typename parent_trie::iterator item)
+      {
+        policy_container::erase (policy_container::s_iterator_to (*item));
+      }
+
+      inline void
+      clear ()
+      {
+        policy_container::clear ();
+      }
+
+      inline void
+      set_max_size (size_t max_size)
+      {
+        max_size_ = max_size;
+      }
+
+      inline size_t
+      get_max_size () const
+      {
+        return max_size_;
+      }
+
+    private:
+      type () : base_(*((Base*)0)) { };
+      
+    private:
+      Base &base_;
+      ns3::UniformVariable u_rand;
+      size_t max_size_;
+    };
+  };
+};
+
+} // trie
+} // ndn
+
+#endif // RANDOM_POLICY_H
diff --git a/ndn-cpp/trie/trie-with-policy.h b/ndn-cpp/trie/trie-with-policy.h
new file mode 100644
index 0000000..5a0d896
--- /dev/null
+++ b/ndn-cpp/trie/trie-with-policy.h
@@ -0,0 +1,263 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef TRIE_TRIE_WITH_POLICY_H_
+#define TRIE_TRIE_WITH_POLICY_H_
+
+#include "trie.h"
+
+namespace ndn {
+namespace trie {
+
+template<typename FullKey,
+         typename PayloadTraits,
+         typename PolicyTraits
+         >
+class trie_with_policy
+{
+public:
+  typedef trie< FullKey,
+                PayloadTraits,
+                typename PolicyTraits::policy_hook_type > parent_trie;
+
+  typedef typename parent_trie::iterator iterator;
+  typedef typename parent_trie::const_iterator const_iterator;
+  typedef typename parent_trie::payload_traits payload_traits;
+
+  typedef typename PolicyTraits::template policy<
+    trie_with_policy<FullKey, PayloadTraits, PolicyTraits>,
+    parent_trie,
+    typename PolicyTraits::template container_hook<parent_trie>::type >::type policy_container;
+
+  inline
+  trie_with_policy (size_t bucketSize = 10, size_t bucketIncrement = 10)
+    : trie_ ("", bucketSize, bucketIncrement)
+    , policy_ (*this)
+  {
+  }
+
+  inline std::pair< iterator, bool >
+  insert (const FullKey &key, typename PayloadTraits::insert_type payload)
+  {
+    std::pair<iterator, bool> item =
+      trie_.insert (key, payload);
+
+    if (item.second) // real insert
+      {
+        bool ok = policy_.insert (s_iterator_to (item.first));
+        if (!ok)
+          {
+            item.first->erase (); // cannot insert
+            return std::make_pair (end (), false);
+          }
+      }
+    else
+      {
+        return std::make_pair (s_iterator_to (item.first), false);
+      }
+
+    return item;
+  }
+
+  inline void
+  erase (const FullKey &key)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+
+    if (!reachLast || lastItem->payload () == PayloadTraits::empty_payload)
+      return; // nothing to invalidate
+
+    erase (lastItem);
+  }
+
+  inline void
+  erase (iterator node)
+  {
+    if (node == end ()) return;
+
+    policy_.erase (s_iterator_to (node));
+    node->erase (); // will do cleanup here
+  }
+
+  inline void
+  clear ()
+  {
+    policy_.clear ();
+    trie_.clear ();
+  }
+
+  template<typename Modifier>
+  bool
+  modify (iterator position, Modifier mod)
+  {
+    if (position == end ()) return false;
+    if (position->payload () == PayloadTraits::empty_payload) return false;
+
+    mod (*position->payload ());
+    policy_.update (position);
+    return true;
+  }
+
+  /**
+   * @brief Find a node that has the exact match with the key
+   */
+  inline iterator
+  find_exact (const FullKey &key)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+
+    if (!reachLast || lastItem->payload () == PayloadTraits::empty_payload)
+      return end ();
+
+    return lastItem;
+  }
+
+  /**
+   * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
+   */
+  inline iterator
+  longest_prefix_match (const FullKey &key)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+    if (foundItem != trie_.end ())
+      {
+        policy_.lookup (s_iterator_to (foundItem));
+      }
+    return foundItem;
+  }
+
+  /**
+   * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
+   */
+  template<class Predicate>
+  inline iterator
+  longest_prefix_match_if (const FullKey &key, Predicate pred)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find_if (key, pred);
+    if (foundItem != trie_.end ())
+      {
+        policy_.lookup (s_iterator_to (foundItem));
+      }
+    return foundItem;
+  }
+
+  // /**
+  //  * @brief Const version of the longest common prefix match
+  //  * (semi-const, because there could be update of the policy anyways)
+  //  */
+  // inline const_iterator
+  // longest_prefix_match (const FullKey &key) const
+  // {
+  //   return static_cast<trie_with_policy*> (this)->longest_prefix_match (key);
+  // }
+
+  /**
+   * @brief Find a node that has prefix at least as the key (cache lookup)
+   */
+  inline iterator
+  deepest_prefix_match (const FullKey &key)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+
+    // guard in case we don't have anything in the trie
+    if (lastItem == trie_.end ())
+      return trie_.end ();
+
+    if (reachLast)
+      {
+        if (foundItem == trie_.end ())
+          {
+            foundItem = lastItem->find (); // should be something
+          }
+        policy_.lookup (s_iterator_to (foundItem));
+        return foundItem;
+      }
+    else
+      { // couldn't find a node that has prefix at least as key
+        return trie_.end ();
+      }
+  }
+
+  /**
+   * @brief Find a node that has prefix at least as the key
+   */
+  template<class Predicate>
+  inline iterator
+  deepest_prefix_match (const FullKey &key, Predicate pred)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+
+    // guard in case we don't have anything in the trie
+    if (lastItem == trie_.end ())
+      return trie_.end ();
+
+    if (reachLast)
+      {
+        foundItem = lastItem->find_if (pred); // may or may not find something
+        if (foundItem == trie_.end ())
+          {
+            return trie_.end ();
+          }
+        policy_.lookup (s_iterator_to (foundItem));
+        return foundItem;
+      }
+    else
+      { // couldn't find a node that has prefix at least as key
+        return trie_.end ();
+      }
+  }
+
+  iterator end () const
+  {
+    return 0;
+  }
+
+  const parent_trie &
+  getTrie () const { return trie_; }
+
+  parent_trie &
+  getTrie () { return trie_; }
+
+  const policy_container &
+  getPolicy () const { return policy_; }
+
+  policy_container &
+  getPolicy () { return policy_; }
+
+  static inline iterator
+  s_iterator_to (typename parent_trie::iterator item)
+  {
+    if (item == 0)
+      return 0;
+    else
+      return &(*item);
+  }
+
+private:
+  parent_trie      trie_;
+  mutable policy_container policy_;
+};
+
+} // trie
+} // ndn
+
+#endif // TRIE_TRIE_WITH_POLICY_H_
diff --git a/ndn-cpp/trie/trie.h b/ndn-cpp/trie/trie.h
new file mode 100644
index 0000000..edc8a1b
--- /dev/null
+++ b/ndn-cpp/trie/trie.h
@@ -0,0 +1,636 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_TRIE_TRIE_H_
+#define NDN_TRIE_TRIE_H_
+
+#include <boost/intrusive/unordered_set.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/set.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/foreach.hpp>
+#include <boost/mpl/if.hpp>
+
+#include "payload-traits/pointer.h"
+#include "payload-traits/ptr.h"
+
+namespace ndn {
+namespace trie {
+
+////////////////////////////////////////////////////
+// forward declarations
+//
+template<typename FullKey,
+         typename PayloadTraits,
+         typename PolicyHook >
+class trie;
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook>
+inline std::ostream&
+operator << (std::ostream &os,
+             const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook>
+bool
+operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
+            const trie<FullKey, PayloadTraits, PolicyHook> &b);
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook >
+std::size_t
+hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
+
+///////////////////////////////////////////////////
+// actual definition
+//
+template<class T, class NonConstT>
+class trie_iterator;
+
+template<class T>
+class trie_point_iterator;
+
+template<typename FullKey,
+	 typename PayloadTraits,
+         typename PolicyHook >
+class trie
+{
+public:
+  typedef typename FullKey::partial_type Key;
+
+  typedef trie*       iterator;
+  typedef const trie* const_iterator;
+
+  typedef trie_iterator<trie, trie> recursive_iterator;
+  typedef trie_iterator<const trie, trie> const_recursive_iterator;
+
+  typedef trie_point_iterator<trie> point_iterator;
+  typedef trie_point_iterator<const trie> const_point_iterator;
+
+  typedef PayloadTraits payload_traits;
+
+  inline
+  trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
+    : key_ (key)
+    , initialBucketSize_ (bucketSize)
+    , bucketIncrement_ (bucketIncrement)
+    , bucketSize_ (initialBucketSize_)
+    , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
+    , children_ (bucket_traits (buckets_.get (), bucketSize_))
+    , payload_ (PayloadTraits::empty_payload)
+    , parent_ (0)
+  {
+  }
+
+  inline
+  ~trie ()
+  {
+    payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
+    children_.clear_and_dispose (trie_delete_disposer ());
+  }
+
+  void
+  clear ()
+  {
+    children_.clear_and_dispose (trie_delete_disposer ());
+  }
+
+  template<class Predicate>
+  void
+  clear_if (Predicate cond)
+  {
+    recursive_iterator trieNode (this);
+    recursive_iterator end (0);
+
+    while (trieNode != end)
+      {
+        if (cond (*trieNode))
+          {
+            trieNode = recursive_iterator (trieNode->erase ());
+          }
+        trieNode ++;
+      }
+  }
+
+  // actual entry
+  friend bool
+  operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
+                 const trie<FullKey, PayloadTraits, PolicyHook> &b);
+
+  friend std::size_t
+  hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
+
+  inline std::pair<iterator, bool>
+  insert (const FullKey &key,
+          typename PayloadTraits::insert_type payload)
+  {
+    trie *trieNode = this;
+
+    BOOST_FOREACH (const Key &subkey, key)
+      {
+        typename unordered_set::iterator item = trieNode->children_.find (subkey);
+        if (item == trieNode->children_.end ())
+          {
+            trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
+            // std::cout << "new " << newNode << "\n";
+            newNode->parent_ = trieNode;
+
+            if (trieNode->children_.size () >= trieNode->bucketSize_)
+              {
+                trieNode->bucketSize_ += trieNode->bucketIncrement_;
+                trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially
+
+                buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
+                trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
+                trieNode->buckets_.swap (newBuckets);
+              }
+
+            std::pair< typename unordered_set::iterator, bool > ret =
+              trieNode->children_.insert (*newNode);
+
+            trieNode = &(*ret.first);
+          }
+        else
+          trieNode = &(*item);
+      }
+
+    if (trieNode->payload_ == PayloadTraits::empty_payload)
+      {
+        trieNode->payload_ = payload;
+        return std::make_pair (trieNode, true);
+      }
+    else
+      return std::make_pair (trieNode, false);
+  }
+
+  /**
+   * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
+   */
+  inline iterator
+  erase ()
+  {
+    payload_ = PayloadTraits::empty_payload;
+    return prune ();
+  }
+
+  /**
+   * @brief Do exactly as erase, but without erasing the payload
+   */
+  inline iterator
+  prune ()
+  {
+    if (payload_ == PayloadTraits::empty_payload &&
+        children_.size () == 0)
+      {
+        if (parent_ == 0) return this;
+
+        trie *parent = parent_;
+        parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
+
+        return parent->prune ();
+      }
+    return this;
+  }
+
+  /**
+   * @brief Perform prune of the node, but without attempting to parent of the node
+   */
+  inline void
+  prune_node ()
+  {
+    if (payload_ == PayloadTraits::empty_payload &&
+        children_.size () == 0)
+      {
+        if (parent_ == 0) return;
+
+        trie *parent = parent_;
+        parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
+      }
+  }
+
+  // inline boost::tuple<const iterator, bool, const iterator>
+  // find (const FullKey &key) const
+  // {
+  //   return const_cast<trie*> (this)->find (key);
+  // }
+
+  /**
+   * @brief Perform the longest prefix match
+   * @param key the key for which to perform the longest prefix match
+   *
+   * @return ->second is true if prefix in ->first is longer than key
+   */
+  inline boost::tuple<iterator, bool, iterator>
+  find (const FullKey &key)
+  {
+    trie *trieNode = this;
+    iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
+    bool reachLast = true;
+
+    BOOST_FOREACH (const Key &subkey, key)
+      {
+        typename unordered_set::iterator item = trieNode->children_.find (subkey);
+        if (item == trieNode->children_.end ())
+          {
+            reachLast = false;
+            break;
+          }
+        else
+          {
+            trieNode = &(*item);
+
+            if (trieNode->payload_ != PayloadTraits::empty_payload)
+              foundNode = trieNode;
+          }
+      }
+
+    return boost::make_tuple (foundNode, reachLast, trieNode);
+  }
+
+  /**
+   * @brief Perform the longest prefix match satisfying preficate
+   * @param key the key for which to perform the longest prefix match
+   *
+   * @return ->second is true if prefix in ->first is longer than key
+   */
+  template<class Predicate>
+  inline boost::tuple<iterator, bool, iterator>
+  find_if (const FullKey &key, Predicate pred)
+  {
+    trie *trieNode = this;
+    iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
+    bool reachLast = true;
+
+    BOOST_FOREACH (const Key &subkey, key)
+      {
+        typename unordered_set::iterator item = trieNode->children_.find (subkey);
+        if (item == trieNode->children_.end ())
+          {
+            reachLast = false;
+            break;
+          }
+        else
+          {
+            trieNode = &(*item);
+
+            if (trieNode->payload_ != PayloadTraits::empty_payload &&
+                pred (trieNode->payload_))
+              {
+                foundNode = trieNode;
+              }
+          }
+      }
+
+    return boost::make_tuple (foundNode, reachLast, trieNode);
+  }
+
+  /**
+   * @brief Find next payload of the sub-trie
+   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
+   */
+  inline iterator
+  find ()
+  {
+    if (payload_ != PayloadTraits::empty_payload)
+      return this;
+
+    typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
+    for (typename trie::unordered_set::iterator subnode = children_.begin ();
+         subnode != children_.end ();
+         subnode++ )
+      // BOOST_FOREACH (trie &subnode, children_)
+      {
+        iterator value = subnode->find ();
+        if (value != 0)
+          return value;
+      }
+
+    return 0;
+  }
+
+  /**
+   * @brief Find next payload of the sub-trie satisfying the predicate
+   * @param pred predicate
+   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
+   */
+  template<class Predicate>
+  inline const iterator
+  find_if (Predicate pred)
+  {
+    if (payload_ != PayloadTraits::empty_payload && pred (payload_))
+      return this;
+
+    typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
+    for (typename trie::unordered_set::iterator subnode = children_.begin ();
+         subnode != children_.end ();
+         subnode++ )
+      // BOOST_FOREACH (const trie &subnode, children_)
+      {
+        iterator value = subnode->find_if (pred);
+        if (value != 0)
+          return value;
+      }
+
+    return 0;
+  }
+
+  iterator end ()
+  {
+    return 0;
+  }
+
+  const_iterator end () const
+  {
+    return 0;
+  }
+
+  typename PayloadTraits::const_return_type
+  payload () const
+  {
+    return payload_;
+  }
+
+  typename PayloadTraits::return_type
+  payload ()
+  {
+    return payload_;
+  }
+
+  void
+  set_payload (typename PayloadTraits::insert_type payload)
+  {
+    payload_ = payload;
+  }
+
+  Key key () const
+  {
+    return key_;
+  }
+
+  inline void
+  PrintStat (std::ostream &os) const;
+
+private:
+  //The disposer object function
+  struct trie_delete_disposer
+  {
+    void operator() (trie *delete_this)
+    {
+      delete delete_this;
+    }
+  };
+
+  template<class D>
+  struct array_disposer
+  {
+    void operator() (D *array)
+    {
+      delete [] array;
+    }
+  };
+
+  friend
+  std::ostream&
+  operator<< < > (std::ostream &os, const trie &trie_node);
+
+public:
+  PolicyHook policy_hook_;
+
+private:
+  boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
+
+  // necessary typedefs
+  typedef trie self_type;
+  typedef boost::intrusive::member_hook< trie,
+                                         boost::intrusive::unordered_set_member_hook< >,
+                                         &trie::unordered_set_member_hook_ > member_hook;
+
+  typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
+  typedef typename unordered_set::bucket_type   bucket_type;
+  typedef typename unordered_set::bucket_traits bucket_traits;
+
+  template<class T, class NonConstT>
+  friend class trie_iterator;
+
+  template<class T>
+  friend class trie_point_iterator;
+
+  ////////////////////////////////////////////////
+  // Actual data
+  ////////////////////////////////////////////////
+
+  Key key_; ///< name component
+
+  size_t initialBucketSize_;
+  size_t bucketIncrement_;
+
+  size_t bucketSize_;
+  typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
+  buckets_array buckets_;
+  unordered_set children_;
+
+  typename PayloadTraits::storage_type payload_;
+  trie *parent_; // to make cleaning effective
+};
+
+
+
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook>
+inline std::ostream&
+operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
+{
+  os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
+  typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
+
+  for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
+       subnode != trie_node.children_.end ();
+       subnode++ )
+  // BOOST_FOREACH (const trie &subnode, trie_node.children_)
+    {
+      os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
+      os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
+
+      os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
+      os << *subnode;
+    }
+
+  return os;
+}
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook>
+inline void
+trie<FullKey, PayloadTraits, PolicyHook>
+::PrintStat (std::ostream &os) const
+{
+  os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
+  for (size_t bucket = 0, maxbucket = children_.bucket_count ();
+       bucket < maxbucket;
+       bucket++)
+    {
+      os << " " << children_.bucket_size (bucket);
+    }
+  os << "\n";
+
+  typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
+  for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
+       subnode != children_.end ();
+       subnode++ )
+  // BOOST_FOREACH (const trie &subnode, children_)
+    {
+      subnode->PrintStat (os);
+    }
+}
+
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook>
+inline bool
+operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
+             const trie<FullKey, PayloadTraits, PolicyHook> &b)
+{
+  return a.key_ == b.key_;
+}
+
+template<typename FullKey, typename PayloadTraits, typename PolicyHook>
+inline std::size_t
+hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
+{
+  return boost::hash_value (trie_node.key_);
+}
+
+
+
+template<class Trie, class NonConstTrie> // hack for boost < 1.47
+class trie_iterator
+{
+public:
+  trie_iterator () : trie_ (0) {}
+  trie_iterator (typename Trie::iterator item) : trie_ (item) {}
+  trie_iterator (Trie &item) : trie_ (&item) {}
+
+  Trie & operator* () { return *trie_; }
+  const Trie & operator* () const { return *trie_; }
+  Trie * operator-> () { return trie_; }
+  const Trie * operator-> () const { return trie_; }
+  bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
+  bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
+  bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
+  bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
+
+  trie_iterator<Trie,NonConstTrie> &
+  operator++ (int)
+  {
+    if (trie_->children_.size () > 0)
+      trie_ = &(*trie_->children_.begin ());
+    else
+      trie_ = goUp ();
+    return *this;
+  }
+
+  trie_iterator<Trie,NonConstTrie> &
+  operator++ ()
+  {
+    (*this)++;
+    return *this;
+  }
+
+private:
+  typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
+                                    typename Trie::unordered_set::iterator,
+                                    typename Trie::unordered_set::const_iterator>::type set_iterator;
+
+  Trie* goUp ()
+  {
+    if (trie_->parent_ != 0)
+      {
+        // typename Trie::unordered_set::iterator item =
+        set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
+        item++;
+        if (item != trie_->parent_->children_.end ())
+          {
+            return &(*item);
+          }
+        else
+          {
+            trie_ = trie_->parent_;
+            return goUp ();
+          }
+      }
+    else
+      return 0;
+  }
+private:
+  Trie *trie_;
+};
+
+
+template<class Trie>
+class trie_point_iterator
+{
+private:
+  typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
+                                    typename Trie::unordered_set::const_iterator,
+                                    typename Trie::unordered_set::iterator>::type set_iterator;
+
+public:
+  trie_point_iterator () : trie_ (0) {}
+  trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
+  trie_point_iterator (Trie &item)
+  {
+    if (item.children_.size () != 0)
+      trie_ = &*item.children_.begin ();
+    else
+      trie_ = 0;
+  }
+
+  Trie & operator* () { return *trie_; }
+  const Trie & operator* () const { return *trie_; }
+  Trie * operator-> () { return trie_; }
+  const Trie * operator-> () const { return trie_; }
+  bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
+  bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
+  bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
+  bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
+
+  trie_point_iterator<Trie> &
+  operator++ (int)
+  {
+    if (trie_->parent_ != 0)
+      {
+        set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
+        item ++;
+        if (item == trie_->parent_->children_.end ())
+          trie_ = 0;
+        else
+          trie_ = &*item;
+      }
+    else
+      {
+        trie_ = 0;
+      }
+    return *this;
+  }
+
+  trie_point_iterator<Trie> &
+  operator++ ()
+  {
+    (*this)++;
+    return *this;
+  }
+
+private:
+  Trie *trie_;
+};
+
+
+} // trie
+} // ndn
+
+#endif // NDN_TRIE_TRIE_H_
diff --git a/ndn-cpp/version.h b/ndn-cpp/version.h
new file mode 100644
index 0000000..34b65de
--- /dev/null
+++ b/ndn-cpp/version.h
@@ -0,0 +1,22 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_CXX_VERSION_H
+#define NDN_CXX_VERSION_H
+
+//  NDN_CXX_VERSION % 100 is the minor version
+//  NDN_CXX_VERSION / 100 % 1000 is the major version
+
+#define NDN_CXX_VERSION 0001
+
+#define NDN_CXX_VERSION_MAJOR  0
+#define NDN_CXX_VERSION_MINOR  1
+
+#endif // NDN_CXX_VERSION_H
diff --git a/ndn-cpp/wire/base.h b/ndn-cpp/wire/base.h
new file mode 100644
index 0000000..8247d09
--- /dev/null
+++ b/ndn-cpp/wire/base.h
@@ -0,0 +1,33 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_WIRE_BASE_H
+#define NDN_WIRE_BASE_H
+
+#include "ndn-cpp/fields/signature-sha256-with-rsa.h"
+
+namespace ndn {
+namespace wire {
+
+/**
+ * @brief Class defining interface for double dispatch pattern (=visitor pattern)
+ *        to format variable fields in wire format
+ */
+class Base
+{
+public:
+  virtual void
+  appendSignature (std::ostream &os, const signature::Sha256WithRsa &signature, void *userData) = 0;
+};
+
+} // wire
+} // ndn
+
+#endif // NDN_WIRE_BASE_H
diff --git a/ndn-cpp/wire/ccnb.cc b/ndn-cpp/wire/ccnb.cc
new file mode 100644
index 0000000..86c3f5f
--- /dev/null
+++ b/ndn-cpp/wire/ccnb.cc
@@ -0,0 +1,259 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnb.h"
+#include "ndn-cpp/error.h"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace wire {
+
+#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))
+
+void
+Ccnb::appendBlockHeader (std::ostream &os, size_t val, Ccnb::ccn_tt tt)
+{
+  unsigned char buf[1+8*((sizeof(val)+6)/7)];
+  unsigned char *p = &(buf[sizeof(buf)-1]);
+  size_t n = 1;
+  p[0] = (CCN_TT_HBIT & ~Ccnb::CCN_CLOSE_TAG) |
+  ((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) | Ccnb::CCN_CLOSE_TAG;
+    n++;
+    val >>= 7;
+  }
+  os.write (reinterpret_cast<const char*> (p), n);
+  // return n;
+}
+
+void
+Ccnb::appendNumber (std::ostream &os, uint32_t number)
+{
+  std::string numberStr = boost::lexical_cast<std::string> (number);
+
+  appendBlockHeader (os, numberStr.size (), Ccnb::CCN_UDATA);
+  numberStr.size ();
+  os.write (numberStr.c_str (), numberStr.size ());
+}
+
+void
+Ccnb::appendName (std::ostream &os, const Name &name)
+{
+  Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_Name, Ccnb::CCN_DTAG); // <Name>
+  for (Name::const_iterator component = name.begin (); component != name.end (); component ++)
+    {
+      appendTaggedBlob (os, Ccnb::CCN_DTAG_Component, component->buf (), component->size ());
+    }
+  Ccnb::appendCloser (os);                                        // </Name>
+}
+
+void
+Ccnb::appendTimestampBlob (std::ostream &os, const TimeInterval &time)
+{
+  // CCNx method function implements some markers, which are not really defined anywhere else...
+
+  // Determine miminal number of bytes required to store the timestamp
+  int required_bytes = 2; // 12 bits for fractions of a second, 4 bits left for seconds. Sometimes it is enough
+  intmax_t ts = time.total_seconds () >> 4;
+  for (;  required_bytes < 7 && ts != 0; ts >>= 8) // not more than 6 bytes?
+     required_bytes++;
+
+  appendBlockHeader(os, required_bytes, Ccnb::CCN_BLOB);
+
+  // write part with seconds
+  ts = time.total_seconds () >> 4;
+  for (int i = 0; i < required_bytes - 2; i++)
+    os.put ( ts >> (8 * (required_bytes - 3 - i)) );
+
+  /* arithmetic contortions are to avoid overflowing 31 bits */
+  ts = ((time.total_seconds () & 15) << 12) +
+    (((time.total_nanoseconds () % 1000000000) / 5 * 8 + 195312) / 390625);
+  for (int i = required_bytes - 2; i < required_bytes; i++)
+    os.put ( ts >> (8 * (required_bytes - 1 - i)) );
+
+  // return len + required_bytes;
+}
+
+void
+Ccnb::appendExclude (std::ostream &os, const Exclude &exclude)
+{
+  appendBlockHeader (os, Ccnb::CCN_DTAG_Exclude, Ccnb::CCN_DTAG); // <Exclude>
+
+  for (Exclude::const_reverse_iterator item = exclude.rbegin (); item != exclude.rend (); item ++)
+    {
+      if (!item->first.empty ())
+        appendTaggedBlob (os, Ccnb::CCN_DTAG_Component, item->first.buf (), item->first.size ());
+      if (item->second)
+        {
+          appendBlockHeader (os, Ccnb::CCN_DTAG_Any, Ccnb::CCN_DTAG); // <Any>
+          appendCloser (os); // </Any>
+        }
+    }
+  appendCloser (os); // </Exclude>
+}
+
+void
+Ccnb::appendInterest (std::ostream &os, const Interest &interest)
+{
+  Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_Interest, Ccnb::CCN_DTAG); // <Interest>
+
+  // this is used for now as an interest template. Name should be empty
+  // Ccnb::appendName (os, interest.getName ());
+  Ccnb::appendName (os, Name ());                              // <Component>...</Component>...
+
+  if (interest.getMinSuffixComponents () != Interest::ncomps)
+    {
+      appendTaggedNumber (os, Ccnb::CCN_DTAG_MinSuffixComponents, interest.getMinSuffixComponents ());
+    }
+  if (interest.getMaxSuffixComponents () != Interest::ncomps)
+    {
+      appendTaggedNumber (os, Ccnb::CCN_DTAG_MaxSuffixComponents, interest.getMaxSuffixComponents ());
+    }
+  if (interest.getExclude ().size () > 0)
+    {
+      appendExclude (os, interest.getExclude ());
+    }
+  if (interest.getChildSelector () != Interest::CHILD_DEFAULT)
+    {
+      appendTaggedNumber (os, Ccnb::CCN_DTAG_ChildSelector, interest.getChildSelector ());
+    }
+  if (interest.getAnswerOriginKind () != Interest::AOK_DEFAULT)
+    {
+      appendTaggedNumber (os, Ccnb::CCN_DTAG_AnswerOriginKind, interest.getAnswerOriginKind ());
+    }
+  if (interest.getScope () != Interest::NO_SCOPE)
+    {
+      appendTaggedNumber (os, Ccnb::CCN_DTAG_Scope, interest.getScope ());
+    }
+  if (!interest.getInterestLifetime ().is_negative ())
+    {
+      Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_InterestLifetime, Ccnb::CCN_DTAG);
+      Ccnb::appendTimestampBlob (os, interest.getInterestLifetime ());
+      Ccnb::appendCloser (os);
+    }
+  // if (GetNonce()>0)
+  //   {
+  //     uint32_t nonce = interest.GetNonce();
+  //     appendTaggedBlob (start, Ccnb::CCN_DTAG_Nonce, nonce);
+  //   }
+
+  // if (GetNack ()>0)
+  //   {
+  //     appendBlockHeader (start, Ccnb::CCN_DTAG_Nack, Ccnb::CCN_DTAG);
+  //     appendNumber (start, interest.GetNack ());
+  //     appendCloser (start);
+  //   }
+  Ccnb::appendCloser (os); // </Interest>
+}
+
+static void *SIGNATURE_Block = 0;
+static void *SINATURE_INFO_PublisherPublicKeyDigest = reinterpret_cast<void *> (1);
+static void *SINATURE_INFO_KeyLocator = reinterpret_cast<void *> (2);
+
+static const char TYPES [][3] =  {
+  {0x0C, 0x04, 0xC0},
+  {0x10, 0xD0, 0x91},
+  {0x18, 0xE3, 0x44},
+  {0x28, 0x46, 0x3F},
+  {0x2C, 0x83, 0x4A},
+  {0x34, 0x00, 0x8A}
+};
+
+void
+Ccnb::appendSignature (std::ostream &os, const signature::Sha256WithRsa &signature, void *userData)
+{
+  if (userData == SIGNATURE_Block)
+    {
+      Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_Signature, Ccnb::CCN_DTAG); // <Signature>
+      // if (signature.getDigestAlgorithm () != "2.16.840.1.101.3.4.2.1")
+      //   {
+      //     appendString (os, Ccnb::CCN_DTAG_DigestAlgorithm, signature.getDigestAlgorithm ());
+      //   }
+      appendTaggedBlob (os, Ccnb::CCN_DTAG_SignatureBits, signature.getSignatureBits ());
+      Ccnb::appendCloser (os); // </Signature>
+    }
+  else if (userData == SINATURE_INFO_PublisherPublicKeyDigest)
+    {
+      Ccnb::appendTaggedBlob (os, Ccnb::CCN_DTAG_PublisherPublicKeyDigest, signature.getPublisherKeyDigest ());
+    }
+  else if (userData == SINATURE_INFO_KeyLocator)
+    {
+      Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_Signature, Ccnb::CCN_DTAG); // <Signature>
+      switch (signature.getKeyLocator ().getType ())
+        {
+        case KeyLocator::NOTSET:
+          break;
+        case KeyLocator::KEY:
+          Ccnb::appendTaggedBlob (os, Ccnb::CCN_DTAG_Key, signature.getKeyLocator ().getKey ());
+          break;
+        case KeyLocator::CERTIFICATE:
+          Ccnb::appendTaggedBlob (os, Ccnb::CCN_DTAG_Key, signature.getKeyLocator ().getCertificate ());
+          break;
+        case KeyLocator::KEYNAME:
+          Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_KeyName, Ccnb::CCN_DTAG); // <KeyName>
+          Ccnb::appendName (os, signature.getKeyLocator ().getKeyName ());
+          Ccnb::appendCloser (os); // </KeyName>
+          break;
+        }
+      Ccnb::appendCloser (os); // </Signature>
+    }
+  // other cases should not be possible, but don't do anything
+}
+
+void
+Ccnb::appendData (std::ostream &os, const Data &data)
+{
+  if (!data.getSignature ())
+    BOOST_THROW_EXCEPTION (error::wire::Ccnb ()
+                           << error::msg ("Signature is required, but not set"));
+
+  Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_ContentObject, Ccnb::CCN_DTAG); // <ContentObject>
+
+  // necessary for now, because of the changed storage order
+  data.getSignature ()->doubleDispatch (os, *this, SIGNATURE_Block);
+
+  Ccnb::appendName (os, data.getName ());
+
+  Ccnb::appendBlockHeader (os, Ccnb::CCN_DTAG_SignedInfo, Ccnb::CCN_DTAG); // <SignedInfo>
+  data.getSignature ()->doubleDispatch (os, *this, SINATURE_INFO_PublisherPublicKeyDigest);
+
+  Ccnb::appendTimestampBlob (os, data.getContent ().getTimestamp ());
+
+  BOOST_ASSERT (sizeof (TYPES) == 3 * (static_cast<int> (Content::NACK)+1));
+  Ccnb::appendTaggedBlob (os, Ccnb::CCN_DTAG_Type, TYPES [data.getContent ().getType ()], 3);
+
+  if (data.getContent ().getFreshness () != Content::noFreshness)
+    {
+      Ccnb::appendTaggedNumber (os, Ccnb::CCN_DTAG_FreshnessSeconds,
+                                data.getContent ().getFreshness ().total_seconds ());
+    }
+
+  if (data.getContent ().getFinalBlockId () != Content::noFinalBlock)
+    {
+      Ccnb::appendTaggedBlob (os, Ccnb::CCN_DTAG_FinalBlockID, data.getContent ().getFinalBlockId ());
+    }
+
+  data.getSignature ()->doubleDispatch (os, *this, SINATURE_INFO_KeyLocator);
+  Ccnb::appendCloser (os); // </SignedInfo>
+
+  Ccnb::appendTaggedBlob (os, Ccnb::CCN_DTAG_Content, data.content ());
+
+  Ccnb::appendCloser (os); // </ContentObject>
+}
+
+} // namespace wire
+} // namespace ndn
diff --git a/ndn-cpp/wire/ccnb.h b/ndn-cpp/wire/ccnb.h
new file mode 100644
index 0000000..fc99bad
--- /dev/null
+++ b/ndn-cpp/wire/ccnb.h
@@ -0,0 +1,350 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_WIRE_CCNB_H
+#define NDN_WIRE_CCNB_H
+
+#include "base.h"
+
+#include "ndn-cpp/interest.h"
+#include "ndn-cpp/data.h"
+
+namespace ndn {
+namespace wire {
+
+/**
+ * @brief Class for working with ccnb encoding
+ */
+class Ccnb : public Base
+{
+public:
+  /**
+   * \brief Type tag for a ccnb start marker.
+   *
+   * \see http://www.ccnx.org/releases/latest/doc/technical/DTAG.html
+   */
+  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 */
+  };
+
+  /** \brief CCN_CLOSE_TAG terminates composites */
+  enum {CCN_CLOSE_TAG = 0};
+
+  /**
+   * \brief DTAG identifies ccnb-encoded elements.
+   *
+   * \see http://www.ccnx.org/releases/latest/doc/technical/DTAG.html
+   */
+  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_Nack = 200,
+    CCN_DTAG_SequenceNumber = 256,
+    CCN_DTAG_CCNProtocolDataUnit = 17702112
+  };
+
+
+  /**
+   * @brief Append CCNB block header
+   * @param os output stream to write
+   * @param value dictionary id of the block header
+   * @param block_type Type of CCNB block
+   */
+  static void
+  appendBlockHeader (std::ostream &os, size_t value, ccn_tt block_type);
+
+  /**
+   * @brief Add number in CCNB encoding
+   * @param os output stream to write
+   * @param number Number to be written
+   *
+   * @returns written length
+   */
+  static void
+  appendNumber (std::ostream &os, uint32_t number);
+
+  /**
+   * @brief Append CCNB closer tag (size is 1)
+   * @param os output stream to write
+   */
+  inline static void
+  appendCloser (std::ostream &os);
+
+  /**
+   * @brief Append Name in CCNB encoding
+   * @param os output stream to write
+   * @param name constant reference to Name object
+   *
+   * @returns written length
+   */
+  static void
+  appendName (std::ostream &os, const Name &name);
+
+  /**
+   * Append a binary timestamp as a BLOB using the ccn binary
+   * Timestamp representation (12-bit fraction).
+   *
+   * @param os output stream to write
+   * @param time reference to time duration object
+   */
+  static void
+  appendTimestampBlob (std::ostream &os, const TimeInterval &timestamp);
+
+  /**
+   * Append a binary timestamp as a BLOB using the ccn binary
+   * Timestamp representation (12-bit fraction).
+   *
+   * @param os output stream to write
+   * @param time reference to Time (posix_time::ptime) object.
+   *             This method automatically calculates duration between time and gregorian::date(1970,1,1)
+   *             and calls the other version of the method
+   */
+  inline static void
+  appendTimestampBlob (std::ostream &os, const Time &time);
+
+  /**
+   * Append a tagged BLOB
+   *
+   * This is a ccnb-encoded element with containing the BLOB as content
+   *
+   * @param os output stream to write
+   * @param dtag is the element's dtag
+   * @param data points to the binary data
+   * @param size is the size of the data, in bytes
+   */
+  inline static void
+  appendTaggedBlob (std::ostream &os, ccn_dtag dtag, const void *data, size_t size);
+
+  /**
+   * Append a tagged BLOB
+   *
+   * This is a ccnb-encoded element with containing the BLOB as content
+   *
+   * @param os output stream to write
+   * @param dtag is the element's dtag
+   * @param blob reference to the data blob
+   */
+  inline static void
+  appendTaggedBlob (std::ostream &os, ccn_dtag dtag, const Blob &blob);
+
+  /**
+   * Append a tagged BLOB
+   *
+   * This is a ccnb-encoded element with containing the BLOB as content
+   *
+   * @param os output stream to write
+   * @param dtag is the element's dtag
+   * @param data points to the binary data
+   * @param size is the size of the data, in bytes
+   */
+  inline static void
+  appendTaggedNumber (std::ostream &os, ccn_dtag dtag, uint32_t number);
+
+  /**
+   * Append a tagged string (should be a valid UTF-8 coded string)
+   *
+   * This is a ccnb-encoded element with containing UDATA as content
+   *
+   * @param os output stream to write
+   * @param dtag is the element's dtag
+   * @param string UTF-8 string to be written
+   */
+  inline static void
+  appendString (std::ostream &os, ccn_dtag dtag, const std::string &string);
+
+  /**
+   * @brief Format interest in CCNb encoding
+   * @param os output stream to write
+   * @param interest Interest to be formatted
+   *
+   * @todo For now, this method is used to create Interest template, which doesn't output name to the stream
+   */
+  static void
+  appendInterest (std::ostream &os, const Interest &interest);
+
+  /**
+   * @brief Append exclude filter in CCNb encoding
+   * @param os output stream to write
+   * @param exclude Exclude filter to be formatted
+   */
+  static void
+  appendExclude (std::ostream &os, const Exclude &exclude);
+
+  /**
+   * @brief Append signature in SHA256withRSA format
+   */
+  virtual void
+  appendSignature (std::ostream &os, const signature::Sha256WithRsa &signature, void *userData);
+
+  /**
+   * @brief Format data in CCNb encoding
+   * @param os output stream to write
+   * @param data data to be formatted
+   */
+  void
+  appendData (std::ostream &os, const Data &data);
+};
+
+
+inline void
+Ccnb::appendCloser (std::ostream &os)
+{
+  os.put (Ccnb::CCN_CLOSE_TAG);
+}
+
+inline void
+Ccnb::appendTimestampBlob (std::ostream &os, const Time &time)
+{
+  appendTimestampBlob (os, time - time::UNIX_EPOCH_TIME);
+}
+
+inline void
+Ccnb::appendTaggedBlob (std::ostream &os, Ccnb::ccn_dtag dtag, const void *data, size_t size)
+{
+  appendBlockHeader (os, dtag, Ccnb::CCN_DTAG);
+  /* 2 */
+  if (size>0)
+    {
+      appendBlockHeader (os, size, Ccnb::CCN_BLOB);
+      os.write (reinterpret_cast<const char*> (data), size);
+      /* size */
+    }
+  appendCloser (os);
+  /* 1 */
+}
+
+inline void
+Ccnb::appendTaggedBlob (std::ostream &os, ccn_dtag dtag, const Blob &blob)
+{
+  appendTaggedBlob (os, dtag, blob.buf (), blob.size ());
+}
+
+inline void
+Ccnb::appendTaggedNumber (std::ostream &os, Ccnb::ccn_dtag dtag, uint32_t number)
+{
+  appendBlockHeader (os, dtag, Ccnb::CCN_DTAG);
+  {
+    appendNumber (os, number);
+  }
+  appendCloser (os);
+}
+
+inline void
+Ccnb::appendString (std::ostream &os, Ccnb::ccn_dtag dtag, const std::string &string)
+{
+  appendBlockHeader (os, dtag, Ccnb::CCN_DTAG);
+  {
+    appendBlockHeader (os, string.size (), Ccnb::CCN_UDATA);
+    os.write (string.c_str (), string.size ());
+  }
+  appendCloser (os);
+}
+
+} // wire
+} // ndn
+
+#endif // NDN_WIRE_CCNB_H