src: Another round of source updates: moving all headers close to implementation files

Change-Id: I3d47076504950e67746174623c75383948e9d93d
diff --git a/src/encoding/block-helpers.hpp b/src/encoding/block-helpers.hpp
new file mode 100644
index 0000000..c3ae196
--- /dev/null
+++ b/src/encoding/block-helpers.hpp
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_BLOCK_HELPERS_HPP
+#define NDN_BLOCK_HELPERS_HPP
+
+#include "block.hpp"
+
+namespace ndn {
+
+inline Block
+nonNegativeIntegerBlock(uint32_t type, uint64_t value)
+{
+  OBufferStream os;
+  Tlv::writeVarNumber(os, type);
+  Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(value));
+  Tlv::writeNonNegativeInteger(os, value);
+  return Block(os.buf());
+}
+
+inline uint64_t
+readNonNegativeInteger(const Block &block)
+{
+  Buffer::const_iterator begin = block.value_begin();
+  return Tlv::readNonNegativeInteger(block.value_size(), begin, block.value_end());
+}
+
+inline Block
+booleanBlock(uint32_t type)
+{
+  OBufferStream os;
+  Tlv::writeVarNumber(os, type);
+  Tlv::writeVarNumber(os, 0);
+  return Block(os.buf());
+}
+
+inline Block
+dataBlock(uint32_t type, const char *data, size_t dataSize)
+{
+  OBufferStream os;
+  Tlv::writeVarNumber(os, type);
+  Tlv::writeVarNumber(os, dataSize);
+  os.write(data, dataSize);
+
+  return Block(os.buf());
+}
+
+inline Block
+dataBlock(uint32_t type, const unsigned char *data, size_t dataSize)
+{
+  return dataBlock(type, reinterpret_cast<const char*>(data), dataSize);
+}
+
+} // namespace ndn
+
+#endif // NDN_BLOCK_HELPERS_HPP
diff --git a/src/encoding/block.cpp b/src/encoding/block.cpp
index 4b41ebc..f881c8e 100644
--- a/src/encoding/block.cpp
+++ b/src/encoding/block.cpp
@@ -7,8 +7,8 @@
  * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
-#include <ndn-cpp-dev/encoding/block.hpp>
-#include <ndn-cpp-dev/encoding/tlv.hpp>
+#include "encoding/block.hpp"
+#include "encoding/tlv.hpp"
 
 namespace ndn {
 
diff --git a/src/encoding/block.hpp b/src/encoding/block.hpp
new file mode 100644
index 0000000..3ae5971
--- /dev/null
+++ b/src/encoding/block.hpp
@@ -0,0 +1,428 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_BLOCK_HPP
+#define NDN_BLOCK_HPP
+
+#include "common.hpp"
+
+#include <list>
+#include <exception>
+
+#include "buffer.hpp"
+#include "tlv.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+
+/**
+ * @brief Class representing wire element of the NDN packet
+ */
+class Block
+{
+public:
+  typedef std::list<Block>::iterator element_iterator;
+  typedef std::list<Block>::const_iterator element_const_iterator;
+
+  /// @brief Error that can be thrown from the block
+  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+  
+  /**
+   * @brief Default constructor to create an empty Block
+   */
+  Block();
+
+  /**
+   * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
+   */
+  Block(const ConstBufferPtr &buffer);
+
+  /**
+   * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
+   */
+  Block(const uint8_t *buffer, size_t maxlength);
+
+  Block(const void *buffer, size_t maxlength);
+
+  /*
+   * @brief A helper version of a constructor to create Block from the stream. 
+   */
+  Block(std::istream& is);
+  
+  /**
+   * @brief Create Block from the wire buffer (no parsing)
+   *
+   * This version of the constructor does not do any parsing
+   */
+  Block(const ConstBufferPtr &wire,
+        uint32_t type,
+        const Buffer::const_iterator &begin, Buffer::const_iterator &end,
+        const Buffer::const_iterator &valueBegin, Buffer::const_iterator &valueEnd);
+
+  /**
+   * @brief Create Block of a specific type with empty wire buffer
+   */
+  explicit
+  Block(uint32_t type);
+
+  /**
+   * @brief Create Block of a specific type with the specified value
+   *
+   * The underlying buffer hold only value, additional operations are needed
+   * to construct wire encoding, one need to prepend the wire buffer with type
+   * and value-length VAR-NUMBERs
+   */
+  Block(uint32_t type, const ConstBufferPtr &value);
+
+  /**
+   * @brief Create nested Block of a specific type with the specified value
+   *
+   * The underlying buffer hold only value, additional operations are needed
+   * to construct wire encoding, one need to prepend the wire buffer with type
+   * and value-length VAR-NUMBERs
+   */
+  explicit
+  Block(uint32_t type, const Block &value);
+  
+  /**
+   * @brief Check if the Block has fully encoded wire
+   */
+  inline bool
+  hasWire() const;
+
+  /**
+   * @brief Check if the Block has value block (no type and length are encoded)
+   */
+  inline bool
+  hasValue() const;
+  
+  /**
+   * @brief Reset wire buffer of the element
+   */
+  inline void
+  reset();
+
+  void
+  parse();
+
+  void
+  encode();
+  
+  inline uint32_t
+  type() const;
+
+  /**
+   * @brief Get the first subelement of the requested type
+   */
+  inline const Block &
+  get(uint32_t type) const;
+
+  inline Block &
+  get(uint32_t type);
+  
+  inline element_iterator
+  find(uint32_t type);
+
+  inline element_const_iterator
+  find(uint32_t type) const;
+
+  inline void
+  remove(uint32_t type);
+
+  inline element_iterator
+  erase(element_iterator position);
+
+  inline element_iterator
+  erase(element_iterator first, element_iterator last);
+  
+  inline void
+  push_back(const Block &element);
+  
+  /**
+   * @brief Get all subelements
+   */
+  inline const std::list<Block>&
+  getAll () const;
+
+  inline std::list<Block>&
+  getAll ();
+  
+  /**
+   * @brief Get all elements of the requested type
+   */
+  std::list<Block>
+  getAll(uint32_t type) const;
+
+  inline Buffer::const_iterator
+  begin() const;
+
+  inline Buffer::const_iterator
+  end() const;
+
+  inline size_t
+  size() const;
+
+  inline Buffer::const_iterator
+  value_begin() const;
+
+  inline Buffer::const_iterator
+  value_end() const;
+
+  inline const uint8_t*
+  wire() const;
+  
+  inline const uint8_t*
+  value() const;
+
+  inline size_t
+  value_size() const;
+
+protected:
+  ConstBufferPtr m_buffer;
+
+  uint32_t m_type;
+  
+  Buffer::const_iterator m_begin;
+  Buffer::const_iterator m_end;
+  uint32_t m_size;
+  
+  Buffer::const_iterator m_value_begin;
+  Buffer::const_iterator m_value_end;
+
+  std::list<Block> m_subBlocks;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+inline bool
+Block::hasWire() const
+{
+  return m_buffer && (m_begin != m_end);
+}
+
+inline bool
+Block::hasValue() const
+{
+  return static_cast<bool>(m_buffer);
+}
+
+inline void
+Block::reset()
+{
+  m_buffer.reset(); // reset of the shared_ptr
+  m_subBlocks.clear(); // remove all parsed subelements
+
+  m_type = std::numeric_limits<uint32_t>::max();
+  m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
+}
+
+inline uint32_t
+Block::type() const
+{
+  return m_type;
+}
+
+inline const Block &
+Block::get(uint32_t type) const
+{
+  for (element_const_iterator i = m_subBlocks.begin ();
+       i != m_subBlocks.end();
+       i++)
+    {
+      if (i->type () == type)
+        {
+          return *i;
+        }
+    }
+
+  throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
+}
+
+inline Block &
+Block::get(uint32_t type)
+{
+  for (element_iterator i = m_subBlocks.begin ();
+       i != m_subBlocks.end();
+       i++)
+    {
+      if (i->type () == type)
+        {
+          return *i;
+        }
+    }
+
+  throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
+}
+  
+inline Block::element_const_iterator
+Block::find(uint32_t type) const
+{
+  for (element_const_iterator i = m_subBlocks.begin ();
+       i != m_subBlocks.end();
+       i++)
+    {
+      if (i->type () == type)
+        {
+          return i;
+        }
+    }
+  return m_subBlocks.end();
+}
+
+inline Block::element_iterator
+Block::find(uint32_t type)
+{
+  for (element_iterator i = m_subBlocks.begin ();
+       i != m_subBlocks.end();
+       i++)
+    {
+      if (i->type () == type)
+        {
+          return i;
+        }
+    }
+  return m_subBlocks.end();
+}
+
+struct block_type
+{
+  block_type(uint32_t type)
+    : m_type(type)
+  {
+  }
+  
+  inline bool
+  operator()(const Block &block)
+  {
+    return (block.type() == m_type);
+  }
+private:
+  uint32_t m_type;
+};
+
+inline void
+Block::remove(uint32_t type)
+{
+  m_subBlocks.remove_if(block_type(type));
+}
+
+inline Block::element_iterator
+Block::erase(Block::element_iterator position)
+{
+  return m_subBlocks.erase(position);
+}
+
+inline Block::element_iterator
+Block::erase(Block::element_iterator first, Block::element_iterator last)
+{
+  return m_subBlocks.erase(first, last);
+}
+
+
+inline void
+Block::push_back(const Block &element)
+{
+  m_subBlocks.push_back(element);
+}
+
+
+inline const std::list<Block>&
+Block::getAll () const
+{
+  return m_subBlocks;
+}
+
+inline std::list<Block>&
+Block::getAll ()
+{
+  return m_subBlocks;
+}
+
+
+inline Buffer::const_iterator
+Block::begin() const
+{
+  if (!hasWire())
+      throw Error("Underlying wire buffer is empty");
+
+  return m_begin;
+}
+
+inline Buffer::const_iterator
+Block::end() const
+{
+  if (!hasWire())
+      throw Error("Underlying wire buffer is empty");
+
+  return m_end;
+}
+
+inline size_t
+Block::size() const
+{
+  if (hasWire() || hasValue()) {
+    return m_size;
+  }
+  else
+    throw Error("Block size cannot be determined (undefined block size)");
+}
+
+inline Buffer::const_iterator
+Block::value_begin() const
+{
+  if (!hasValue())
+      throw Error("(Block::value_begin) Underlying value buffer is empty");
+
+  return m_value_begin;
+}
+
+inline Buffer::const_iterator
+Block::value_end() const
+{
+  if (!hasValue())
+      throw Error("(Block::value_end) Underlying value buffer is empty");
+
+  return m_value_end;
+}
+
+inline const uint8_t*
+Block::wire() const
+{
+  if (!hasWire())
+      throw Error("(Block::wire) Underlying wire buffer is empty");
+
+  return &*m_begin;
+}
+
+inline const uint8_t*
+Block::value() const
+{
+  if (!hasValue())
+      throw Error("(Block::value) Underlying value buffer is empty");
+  
+  return &*m_value_begin;
+}
+
+inline size_t
+Block::value_size() const
+{
+  if (!hasValue())
+    throw Error("(Block::value_size) Underlying value buffer is empty");
+
+  return m_value_end - m_value_begin;
+}
+
+} // ndn
+
+#include "block-helpers.hpp"
+
+#endif // NDN_BLOCK_HPP
diff --git a/src/encoding/buffer.hpp b/src/encoding/buffer.hpp
new file mode 100644
index 0000000..f6b7a17
--- /dev/null
+++ b/src/encoding/buffer.hpp
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_BUFFER_HPP
+#define NDN_BUFFER_HPP
+
+#include "common.hpp"
+
+#include <boost/iostreams/detail/ios.hpp>
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/stream.hpp>
+
+#include <vector>
+
+namespace ndn {
+
+class Buffer;
+typedef ptr_lib::shared_ptr<const Buffer> ConstBufferPtr;
+typedef ptr_lib::shared_ptr<Buffer> BufferPtr;
+
+/**
+ * @brief Class representing a general-use automatically managed/resized buffer
+ *
+ * In most respect, Buffer class is equivalent to std::vector<uint8_t> and is in fact
+ * uses it as a base class.  In addition to that, it provides buf() and buf<T>() helper
+ * method for easier access to the underlying data (buf<T>() casts pointer to the requested class)
+ */
+class Buffer : public std::vector<uint8_t>
+{
+public:
+  /**
+   * @brief Creates an empty buffer
+   */
+  Buffer ()
+  {
+  }
+
+  /**
+   * @brief Create a buffer by copying the supplied data from a const buffer
+   * @param buf const pointer to buffer
+   * @param length length of the buffer to copy
+   */
+  Buffer (const void *buf, size_t length)
+    : std::vector<uint8_t> (reinterpret_cast<const uint8_t*> (buf), reinterpret_cast<const uint8_t*> (buf) + length)
+  {
+  }
+
+  /**
+   * @brief Create a buffer by copying the supplied data using iterator interface
+   *
+   * Note that the supplied iterators must be compatible with std::vector<uint8_t> interface
+   *
+   * @param first iterator to a first element to copy
+   * @param last  iterator to an element immediately following the last element to copy
+   */
+  template <class InputIterator>
+  Buffer (InputIterator first, InputIterator last)
+    : std::vector<uint8_t> (first, last)
+  {
+  }
+  
+  /**
+   * @brief Get pointer to the first byte of the buffer
+   */
+  inline uint8_t*
+  get ()
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get pointer to the first byte of the buffer (alternative version)
+   */
+  inline uint8_t*
+  buf ()
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get pointer to the first byte of the buffer and cast
+   * it (reinterpret_cast) to the requested type T
+   */
+  template<class T>
+  inline T*
+  get ()
+  {
+    return reinterpret_cast<T *>(&front ());
+  }
+
+  /**
+   * @brief Get pointer to the first byte of the buffer (alternative version)
+   */
+  inline const uint8_t*
+  buf () const
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get const pointer to the first byte of the buffer
+   */
+  inline const uint8_t*
+  get () const
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get const pointer to the first byte of the buffer and cast
+   * it (reinterpret_cast) to the requested type T
+   */
+  template<class T>
+  inline const T*
+  get () const
+  {
+    return reinterpret_cast<const T *>(&front ());
+  }  
+};
+
+/// @cond include_hidden
+namespace iostreams
+{
+
+class buffer_append_device {
+public:
+  typedef char  char_type;
+  typedef boost::iostreams::sink_tag       category;
+  
+  buffer_append_device (Buffer& container)
+  : m_container (container)
+  {
+  }
+  
+  std::streamsize
+  write(const char_type* s, std::streamsize n)
+  {
+    std::copy (s, s+n, std::back_inserter(m_container));
+    return n;
+  }
+  
+protected:
+  Buffer& m_container;
+};
+
+} // iostreams
+/// @endcond
+
+/**
+ * Class implementing interface similar to ostringstream, but to construct ndn::Buffer
+ *
+ * The benefit of using stream interface is that it provides automatic buffering of written data
+ * and eliminates (or reduces) overhead of resizing the underlying buffer when writing small pieces of data.
+ *
+ * Usage example:
+ * @code
+ *      OBufferStream obuf;
+ *      obuf.put(0);
+ *      obuf.write(another_buffer, another_buffer_size);
+ *      ptr_lib::shared_ptr<Buffer> buf = obuf.get();
+ * @endcode
+ */
+struct OBufferStream : public boost::iostreams::stream<iostreams::buffer_append_device>
+{
+  /**
+   * Default constructor
+   */
+  OBufferStream ()
+    : m_buffer (ptr_lib::make_shared<Buffer> ())
+    , m_device (*m_buffer)
+  {
+    open (m_device);
+  }
+
+  /**
+   * Flush written data to the stream and return shared pointer to the underlying buffer
+   */
+  ptr_lib::shared_ptr<Buffer>
+  buf ()
+  {
+    flush ();
+    return m_buffer;
+  }
+
+private:
+  BufferPtr m_buffer;
+  iostreams::buffer_append_device m_device;
+};
+
+
+} // ndn
+
+#endif // NDN_BUFFER_HPP
diff --git a/src/encoding/cryptopp/asn_ext.cpp b/src/encoding/cryptopp/asn_ext.cpp
index 4df06c5..9a3816e 100644
--- a/src/encoding/cryptopp/asn_ext.cpp
+++ b/src/encoding/cryptopp/asn_ext.cpp
@@ -6,7 +6,7 @@
  * See COPYING for copyright and distribution information.
  */
 
-#include <ndn-cpp-dev/ndn-cpp-config.h>
+#include "ndn-cpp-config.h"
 #include "asn_ext.hpp"
 #include "../../util/time.hpp"
 
diff --git a/src/encoding/cryptopp/asn_ext.hpp b/src/encoding/cryptopp/asn_ext.hpp
index f0ed463..c53cb96 100644
--- a/src/encoding/cryptopp/asn_ext.hpp
+++ b/src/encoding/cryptopp/asn_ext.hpp
@@ -23,7 +23,7 @@
 #endif
 
 #include <stdexcept>
-#include <ndn-cpp-dev/common.hpp>
+#include "common.hpp"
 #include <cryptopp/asn.h>
 
 namespace ndn {
diff --git a/src/encoding/endian.hpp b/src/encoding/endian.hpp
new file mode 100644
index 0000000..9ea5c96
--- /dev/null
+++ b/src/encoding/endian.hpp
@@ -0,0 +1,39 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Junxiao Shi <shijunxiao@email.arizona.edu>
+ */
+
+#ifdef __linux__
+
+#include <endian.h>
+
+#endif
+
+#ifdef __FreeBSD__
+
+#include <sys/endian.h>
+
+#endif
+
+#ifdef __APPLE__
+
+#include <libkern/OSByteOrder.h>
+#define htobe16(x) OSSwapHostToBigInt16(x)
+#define htole16(x) OSSwapHostToLittleInt16(x)
+#define be16toh(x) OSSwapBigToHostInt16(x)
+#define le16toh(x) OSSwapLittleToHostInt16(x)
+#define htobe32(x) OSSwapHostToBigInt32(x)
+#define htole32(x) OSSwapHostToLittleInt32(x)
+#define be32toh(x) OSSwapBigToHostInt32(x)
+#define le32toh(x) OSSwapLittleToHostInt32(x)
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#define le64toh(x) OSSwapLittleToHostInt64(x)
+
+#endif
+
diff --git a/src/encoding/oid.cpp b/src/encoding/oid.cpp
index 4edbf01..d1504e1 100644
--- a/src/encoding/oid.cpp
+++ b/src/encoding/oid.cpp
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <sstream>
 
-#include <ndn-cpp-dev/encoding/oid.hpp>
+#include "encoding/oid.hpp"
 #include <cryptopp/asn.h>
 
 using namespace std;
diff --git a/src/encoding/oid.hpp b/src/encoding/oid.hpp
new file mode 100644
index 0000000..e755c05
--- /dev/null
+++ b/src/encoding/oid.hpp
@@ -0,0 +1,78 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_OID_HPP
+#define NDN_OID_HPP
+
+#include <vector>
+#include <string>
+
+namespace CryptoPP { class BufferedTransformation; }
+
+namespace ndn {
+
+class OID {
+public:
+  OID () 
+  {
+  }
+    
+  OID(const char *oid);
+
+  OID(const std::string& oid);
+
+  OID(const std::vector<int>& oid)
+  : oid_(oid)
+  {
+  }
+
+  const std::vector<int> &
+  getIntegerList() const
+  {
+    return oid_;
+  }
+
+  void
+  setIntegerList(const std::vector<int>& value){
+    oid_ = value;
+  }
+
+  std::string 
+  toString() const;
+
+  bool operator == (const OID& oid) const
+  {
+    return equal(oid);
+  }
+
+  bool operator != (const OID& oid) const
+  {
+    return !equal(oid);
+  }
+
+  void
+  encode(CryptoPP::BufferedTransformation &out) const;
+
+  void
+  decode(CryptoPP::BufferedTransformation &in);
+
+
+private:
+  void
+  construct(const std::string &value);
+  
+  bool
+  equal(const OID& oid) const;
+
+private:
+  std::vector<int> oid_;
+};
+
+}
+
+#endif
diff --git a/src/encoding/tlv-face-management.hpp b/src/encoding/tlv-face-management.hpp
new file mode 100644
index 0000000..86798df
--- /dev/null
+++ b/src/encoding/tlv-face-management.hpp
@@ -0,0 +1,50 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_TLV_FACE_MANAGEMENT_HPP
+#define NDN_TLV_FACE_MANAGEMENT_HPP
+
+#include "tlv.hpp"
+
+namespace ndn {
+namespace Tlv {
+namespace FaceManagement {
+
+enum {
+  FaceInstance       = 128,
+  ForwardingEntry    = 129,
+  StatusResponse     = 130,
+  Action             = 131,
+  FaceID             = 132,
+  IPProto            = 133,
+  Host               = 134,
+  Port               = 135,
+  MulticastInterface = 136,
+  MulticastTTL       = 137,
+  ForwardingFlags    = 138,
+  StatusCode         = 139,
+  StatusText         = 140
+};
+
+enum {
+  FORW_ACTIVE         = 1,
+  FORW_CHILD_INHERIT  = 2,
+  FORW_ADVERTISE      = 4,
+  FORW_LAST           = 8,
+  FORW_CAPTURE       = 16,
+  FORW_LOCAL         = 32,
+  FORW_TAP           = 64,
+  FORW_CAPTURE_OK   = 128
+};
+
+} // namespace FaceManagement
+} // namespace Tlv
+} // namespace ndn
+
+#endif // NDN_TLV_FACE_MANAGEMENT_HPP
diff --git a/src/encoding/tlv.hpp b/src/encoding/tlv.hpp
new file mode 100644
index 0000000..511d0f6
--- /dev/null
+++ b/src/encoding/tlv.hpp
@@ -0,0 +1,466 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_TLV_HPP
+#define NDN_TLV_HPP
+
+#include <stdexcept>
+#include <iterator>
+#include "buffer.hpp"
+#include "endian.hpp"
+
+namespace ndn {
+
+/**
+ * @brief Namespace defining NDN-TLV related constants and procedures
+ */
+namespace Tlv {
+
+struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+
+enum {
+  Interest      = 1,
+  Data          = 2,
+  Name          = 3,
+  NameComponent = 4,
+  Selectors     = 5,
+  Nonce         = 6,
+  Scope         = 7,
+  InterestLifetime          = 8,
+  MinSuffixComponents       = 9,
+  MaxSuffixComponents       = 10,
+  PublisherPublicKeyLocator = 11,
+  Exclude       = 12,
+  ChildSelector = 13,
+  MustBeFresh   = 14,
+  Any           = 15,
+  MetaInfo      = 16,
+  Content       = 17,
+  SignatureInfo = 18,
+  SignatureValue = 19,
+  ContentType   = 20,
+  FreshnessPeriod = 21,
+  SignatureType = 22,
+  KeyLocator    = 23,
+  KeyLocatorDigest = 24,
+
+  AppPrivateBlock1 = 128,
+  AppPrivateBlock2 = 32767
+};
+
+enum SignatureType {
+  DigestSha256 = 0,
+  SignatureSha256WithRsa = 1,
+};
+
+enum ConentType {
+  ContentType_Default = 0,
+  ContentType_Link = 1,
+  ContentType_Key = 2,
+};
+
+/**
+ * @brief Read VAR-NUMBER in NDN-TLV encoding
+ *
+ * This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
+ *
+ * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
+ */
+template<class InputIterator>
+inline uint64_t
+readVarNumber(InputIterator &begin, const InputIterator &end);
+
+/**
+ * @brief Read TLV Type
+ *
+ * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
+ * is larger than 2^32-1 (type in this library is implemented as uint32_t)
+ */
+template<class InputIterator>
+inline uint32_t
+readType(InputIterator &begin, const InputIterator &end);
+
+/**
+ * @brief Get number of bytes necessary to hold value of VAR-NUMBER
+ */
+inline size_t
+sizeOfVarNumber(uint64_t varNumber);
+
+/**
+ * @brief Write VAR-NUMBER to the specified stream
+ */
+inline size_t
+writeVarNumber(std::ostream &os, uint64_t varNumber);
+
+/**
+ * @brief Read nonNegativeInteger in NDN-TLV encoding
+ *
+ * This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
+ *
+ * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
+ *
+ * How many bytes will be read is directly controlled by the size parameter, which can be either
+ * 1, 2, 4, or 8.  If the value of size is different, then an exception will be thrown.
+ */
+template<class InputIterator>
+inline uint64_t
+readNonNegativeInteger(size_t size, InputIterator &begin, const InputIterator &end);
+
+/**
+ * @brief Get number of bytes necessary to hold value of nonNegativeInteger
+ */
+inline size_t
+sizeOfNonNegativeInteger(uint64_t varNumber);
+
+/**
+ * @brief Write nonNegativeInteger to the specified stream
+ */
+inline size_t
+writeNonNegativeInteger(std::ostream &os, uint64_t varNumber);
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+// Inline implementations
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+template<class InputIterator>
+inline uint64_t
+readVarNumber(InputIterator &begin, const InputIterator &end)
+{
+  if (begin == end)
+    throw Error("Empty buffer during TLV processing");
+  
+  uint8_t value = *begin;
+  ++begin;
+  if (value < 253)
+    {
+      return value;
+    }
+  else if (value == 253)
+    {
+      if (end - begin < 2)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin); // kind of dangerous... but should be efficient
+      begin += 2;
+      return be16toh(value);
+    }
+  else if (value == 254)
+    {
+      if (end - begin < 4)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin); // kind of dangerous... but should be efficient
+      begin += 4;
+      return be32toh(value);
+    }
+  else // if (value == 255)
+    {
+      if (end - begin < 8)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
+      begin += 8;
+
+      return be64toh(value);
+    }
+}
+
+template<>
+inline uint64_t
+readVarNumber<std::istream_iterator<uint8_t> >(std::istream_iterator<uint8_t> &begin, 
+                                               const std::istream_iterator<uint8_t> &end)
+{
+  if (begin == end)
+    throw Error("Empty buffer during TLV processing");
+  
+  uint8_t value = *begin;
+  ++begin;
+  if (value < 253)
+    {
+      return value;
+    }
+  else if (value == 253)
+    {
+      uint8_t buffer[2];
+      int count = 0;
+      
+      while(begin != end && count < 2){
+        buffer[count] = *begin;
+        begin++;
+        count++;
+      }
+
+      if (count < 2)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint16_t value = *reinterpret_cast<const uint16_t*>(buffer); 
+      return be16toh(value);
+    }
+  else if (value == 254)
+    {
+      uint8_t buffer[4];
+      int count = 0;
+      
+      while(begin != end && count < 4){
+        buffer[count] = *begin;
+        begin++;
+        count++;
+      }
+
+      if (count < 4)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint32_t value = *reinterpret_cast<const uint32_t*>(buffer);
+      return be32toh(value);
+    }
+  else // if (value == 255)
+    {
+      uint8_t buffer[8];
+      int count = 0;
+      
+      while(begin != end && count < 8){
+        buffer[count] = *begin;
+        begin++;
+        count++;
+      }
+
+      if (count < 8)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint64_t value = *reinterpret_cast<const uint64_t*>(buffer);
+      return be64toh(value);
+    }
+}
+
+template<class InputIterator>
+inline uint32_t
+readType(InputIterator &begin, const InputIterator &end)
+{
+  uint64_t type   = readVarNumber(begin, end);
+  if (type > std::numeric_limits<uint32_t>::max())
+    {
+      throw Error("TLV type code exceeds allowed maximum");
+    }
+
+  return static_cast<uint32_t> (type);
+}
+
+size_t
+sizeOfVarNumber(uint64_t varNumber)
+{
+  if (varNumber < 253) {
+    return 1;
+  }
+  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
+    return 3;
+  }
+  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
+    return 5;
+  }
+  else {
+    return 9;
+  }
+}
+
+inline size_t
+writeVarNumber(std::ostream &os, uint64_t varNumber)
+{
+  if (varNumber < 253) {
+    os.put(static_cast<uint8_t> (varNumber));
+    return 1;
+  }
+  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
+    os.put(253);
+    uint16_t value = htobe16(static_cast<uint16_t> (varNumber));
+    os.write(reinterpret_cast<const char*> (&value), 2);
+    return 3;
+  }
+  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
+    os.put(254);
+    uint32_t value = htobe32(static_cast<uint32_t> (varNumber));
+    os.write(reinterpret_cast<const char*> (&value), 4);
+    return 5;
+  }
+  else {
+    os.put(255);
+    uint64_t value = htobe64(varNumber);
+    os.write(reinterpret_cast<const char*> (&value), 8);
+    return 9;
+  }
+}
+
+template<class InputIterator>
+inline uint64_t
+readNonNegativeInteger(size_t size, InputIterator &begin, const InputIterator &end)
+{
+  switch (size) {
+  case 1:
+    {
+      if (end - begin < 1)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint8_t value = *begin;
+      begin++;
+      return value;
+    }
+  case 2:
+    {
+      if (end - begin < 2)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin); // kind of dangerous... but should be efficient
+      begin += 2;
+      return be16toh(value);
+    }
+  case 4:
+    {
+      if (end - begin < 4)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin); // kind of dangerous... but should be efficient
+      begin += 4;
+      return be32toh(value);
+    }
+  case 8:
+    {
+      if (end - begin < 8)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
+      begin += 8;
+      return be64toh(value);
+    }
+  }
+  throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
+}
+
+template<>
+inline uint64_t
+readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size, 
+                                                        std::istream_iterator<uint8_t> &begin, 
+                                                        const std::istream_iterator<uint8_t> &end)
+{
+  switch (size) {
+  case 1:
+    {
+      if(begin == end)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint8_t value = *begin;
+      begin++;
+      return value;
+    }
+  case 2:
+    {
+      uint8_t buffer[2];
+      int count = 0;
+      
+      while(begin != end && count < 2){
+        buffer[count] = *begin;
+        begin++;
+        count++;
+      }
+      
+      if (count < 2)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint16_t value = *reinterpret_cast<const uint16_t*>(buffer);
+      return be16toh(value);
+    }
+  case 4:
+    {
+      uint8_t buffer[4];
+      int count = 0;
+      
+      while(begin != end && count < 4){
+        buffer[count] = *begin;
+        begin++;
+        count++;
+      }
+
+      if (count < 4)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint32_t value = *reinterpret_cast<const uint32_t*>(buffer);
+      return be32toh(value);
+    }
+  case 8:
+    {
+      uint8_t buffer[8];
+      int count = 0;
+      
+      while(begin != end && count < 8){
+        buffer[count] = *begin;
+        begin++;
+        count++;
+      }
+
+      if (count < 8)
+        throw Error("Insufficient data during TLV processing");
+      
+      uint64_t value = *reinterpret_cast<const uint64_t*>(buffer);
+      return be64toh(value);
+    }
+  }
+  throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
+}
+
+inline size_t
+sizeOfNonNegativeInteger(uint64_t varNumber)
+{
+  if (varNumber < 253) {
+    return 1;
+  }
+  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
+    return 2;
+  }
+  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
+    return 4;
+  }
+  else {
+    return 8;
+  }
+}
+
+
+inline size_t
+writeNonNegativeInteger(std::ostream &os, uint64_t varNumber)
+{
+  if (varNumber < 253) {
+    os.put(static_cast<uint8_t> (varNumber));
+    return 1;
+  }
+  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
+    uint16_t value = htobe16(static_cast<uint16_t> (varNumber));
+    os.write(reinterpret_cast<const char*> (&value), 2);
+    return 2;
+  }
+  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
+    uint32_t value = htobe32(static_cast<uint32_t> (varNumber));
+    os.write(reinterpret_cast<const char*> (&value), 4);
+    return 4;
+  }
+  else {
+    uint64_t value = htobe64(varNumber);
+    os.write(reinterpret_cast<const char*> (&value), 8);
+    return 8;
+  }
+}
+
+
+} // namespace tlv
+} // namespace ndn
+
+#endif // NDN_TLV_HPP