src: Refactoring common.hpp and minimizing exposed includes

Face class has relatively large rewrite to hide internals using
Implementor pattern.  As of this commit, <boost/asio.hpp> is not
automatically included whenever ndn-cxx/face.hpp is included.  If it is
needed to directly work with io_service, asio.hpp should be specifically
included.

Change-Id: Ie742b851025b4e3da634eb981319df0f42937855
diff --git a/src/common-pch.hpp b/src/common-pch.hpp
new file mode 100644
index 0000000..7b3c03a
--- /dev/null
+++ b/src/common-pch.hpp
@@ -0,0 +1,41 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#ifndef NDN_COMMON_PCH_HPP
+#define NDN_COMMON_PCH_HPP
+
+// If compiler supports precompiled header, this header should be compiled and include
+// before anything else
+
+#include "common.hpp"
+
+// STL headers to precompile
+#include <vector>
+#include <list>
+#include <set>
+#include <algorithm>
+#include <map>
+#include <sstream>
+#include <fstream>
+#include <exception>
+#include <map>
+
+// Other useful headers to precompile
+#include <boost/lexical_cast.hpp>
+#include <boost/asio.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <boost/iostreams/detail/ios.hpp>
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/stream.hpp>
+
+#endif // NDN_COMMON_PCH_HPP
diff --git a/src/common.hpp b/src/common.hpp
index ed2bf19..05c3319 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -14,33 +14,11 @@
 #define NDN_COMMON_HPP
 
 #include "ndn-cxx-config.hpp"
+
 #include <stdint.h>
-// TODO: Is stddef.h portable?
 #include <stddef.h>
 #include <unistd.h>
 
-// Standard headers to precompile
-
-#include <vector>
-#include <list>
-#include <set>
-#include <algorithm>
-#include <map>
-#include <sstream>
-#include <fstream>
-#include <exception>
-#include <map>
-
-// Other useful headers to precompile
-#include <boost/lexical_cast.hpp>
-#include <boost/asio.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/iostreams/detail/ios.hpp>
-#include <boost/iostreams/categories.hpp>
-#include <boost/iostreams/stream.hpp>
-
 #if defined(__GNUC__) || defined(__clang__)
 #define DEPRECATED(func) func __attribute__ ((deprecated))
 #elif defined(_MSC_VER)
@@ -132,12 +110,12 @@
 
 #endif // NDN_CXX_HAVE_CXX11
 
+#include <boost/utility.hpp>
+
 namespace ndn {
 
 using boost::noncopyable;
 
 }
 
-#include "util/time.hpp"
-
-#endif
+#endif // NDN_COMMON_HPP
diff --git a/src/detail/face-impl.hpp b/src/detail/face-impl.hpp
new file mode 100644
index 0000000..52f9dd3
--- /dev/null
+++ b/src/detail/face-impl.hpp
@@ -0,0 +1,319 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#ifndef NDN_DETAIL_FACE_IMPL_HPP
+#define NDN_DETAIL_FACE_IMPL_HPP
+
+#include "../common.hpp"
+#include "../face.hpp"
+
+#include "registered-prefix.hpp"
+#include "pending-interest.hpp"
+
+#include "../util/scheduler.hpp"
+#include "../util/config-file.hpp"
+
+#include "transport/transport.hpp"
+#include "transport/unix-transport.hpp"
+#include "transport/tcp-transport.hpp"
+
+#include "management/nfd-controller.hpp"
+
+namespace ndn {
+
+class Face::Impl : noncopyable
+{
+public:
+  typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
+  typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
+  typedef std::list<shared_ptr<RegisteredPrefix> > RegisteredPrefixTable;
+
+  explicit
+  Impl(Face& face)
+    : m_face(face)
+  {
+  }
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void
+  satisfyPendingInterests(Data& data)
+  {
+    for (PendingInterestTable::iterator i = m_pendingInterestTable.begin();
+         i != m_pendingInterestTable.end();
+         )
+      {
+        if ((*i)->getInterest()->matchesData(data))
+          {
+            // Copy pointers to the objects and remove the PIT entry before calling the callback.
+            OnData onData = (*i)->getOnData();
+            shared_ptr<const Interest> interest = (*i)->getInterest();
+
+            PendingInterestTable::iterator next = i;
+            ++next;
+            m_pendingInterestTable.erase(i);
+            i = next;
+
+            if (static_cast<bool>(onData)) {
+              onData(*interest, data);
+            }
+          }
+        else
+          ++i;
+      }
+  }
+
+  void
+  processInterestFilters(Interest& interest)
+  {
+    for (InterestFilterTable::iterator i = m_interestFilterTable.begin();
+         i != m_interestFilterTable.end();
+         ++i)
+      {
+        if ((*i)->doesMatch(interest.getName()))
+          {
+            (**i)(interest);
+          }
+      }
+  }
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void
+  asyncExpressInterest(const shared_ptr<const Interest>& interest,
+                       const OnData& onData, const OnTimeout& onTimeout)
+  {
+    if (!m_face.m_transport->isExpectingData())
+      m_face.m_transport->resume();
+
+    m_pendingInterestTable.push_back(make_shared<PendingInterest>(interest, onData, onTimeout));
+
+    if (!interest->getLocalControlHeader().empty(false, true))
+      {
+        // encode only NextHopFaceId towards the forwarder
+        m_face.m_transport->send(interest->getLocalControlHeader()
+                                   .wireEncode(*interest, false, true),
+                                 interest->wireEncode());
+      }
+    else
+      {
+        m_face.m_transport->send(interest->wireEncode());
+      }
+
+    if (!m_pitTimeoutCheckTimerActive) {
+      m_pitTimeoutCheckTimerActive = true;
+      m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
+      m_pitTimeoutCheckTimer->async_wait(bind(&Impl::checkPitExpire, this));
+    }
+  }
+
+  void
+  asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
+  {
+    m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
+  }
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void
+  asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord)
+  {
+    m_interestFilterTable.push_back(interestFilterRecord);
+  }
+
+  void
+  asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
+  {
+    InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
+                                                   m_interestFilterTable.end(),
+                                                   MatchInterestFilterId(interestFilterId));
+    if (i != m_interestFilterTable.end())
+      {
+        m_interestFilterTable.erase(i);
+      }
+  }
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  template<class SignatureGenerator>
+  const RegisteredPrefixId*
+  registerPrefix(const Name& prefix,
+                 const shared_ptr<InterestFilterRecord>& filter,
+                 const RegisterPrefixSuccessCallback& onSuccess,
+                 const RegisterPrefixFailureCallback& onFailure,
+                 const SignatureGenerator& signatureGenerator)
+  {
+    using namespace nfd;
+
+    typedef void (nfd::Controller::*Registrator)
+      (const nfd::ControlParameters&,
+       const nfd::Controller::CommandSucceedCallback&,
+       const nfd::Controller::CommandFailCallback&,
+       const SignatureGenerator&,
+       const time::milliseconds&);
+
+    Registrator registrator, unregistrator;
+    if (!m_face.m_isDirectNfdFibManagementRequested) {
+      registrator = static_cast<Registrator>(&Controller::start<RibRegisterCommand>);
+      unregistrator = static_cast<Registrator>(&Controller::start<RibUnregisterCommand>);
+    }
+    else {
+      registrator = static_cast<Registrator>(&Controller::start<FibAddNextHopCommand>);
+      unregistrator = static_cast<Registrator>(&Controller::start<FibRemoveNextHopCommand>);
+    }
+
+    ControlParameters parameters;
+    parameters.setName(prefix);
+
+    RegisteredPrefix::Unregistrator bindedUnregistrator =
+      bind(unregistrator, m_face.m_nfdController, parameters, _1, _2,
+           signatureGenerator,
+           m_face.m_nfdController->getDefaultCommandTimeout());
+
+    shared_ptr<RegisteredPrefix> prefixToRegister =
+      ndn::make_shared<RegisteredPrefix>(prefix, filter, bindedUnregistrator);
+
+    ((*m_face.m_nfdController).*registrator)(parameters,
+                                             bind(&Impl::afterPrefixRegistered, this,
+                                                  prefixToRegister, onSuccess),
+                                             bind(onFailure, prefixToRegister->getPrefix(), _2),
+                                             signatureGenerator,
+                                             m_face.m_nfdController->getDefaultCommandTimeout());
+
+    return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
+  }
+
+  void
+  afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
+                        const RegisterPrefixSuccessCallback& onSuccess)
+  {
+    m_registeredPrefixTable.push_back(registeredPrefix);
+
+    if (static_cast<bool>(registeredPrefix->getFilter())) {
+      // it was a combined operation
+      m_interestFilterTable.push_back(registeredPrefix->getFilter());
+    }
+
+    if (static_cast<bool>(onSuccess)) {
+      onSuccess(registeredPrefix->getPrefix());
+    }
+  }
+
+  void
+  asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
+                        const UnregisterPrefixSuccessCallback& onSuccess,
+                        const UnregisterPrefixFailureCallback& onFailure)
+  {
+    RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
+                                                     m_registeredPrefixTable.end(),
+                                                     MatchRegisteredPrefixId(registeredPrefixId));
+    if (i != m_registeredPrefixTable.end())
+      {
+        const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
+        if (static_cast<bool>(filter))
+          {
+            // it was a combined operation
+            m_interestFilterTable.remove(filter);
+          }
+
+        (*i)->unregister(bind(&Impl::finalizeUnregisterPrefix, this, i, onSuccess),
+                         bind(onFailure, _2));
+      }
+    else
+      onFailure("Unrecognized PrefixId");
+
+    // there cannot be two registered prefixes with the same id
+  }
+
+  void
+  finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
+                           const UnregisterPrefixSuccessCallback& onSuccess)
+  {
+    m_registeredPrefixTable.erase(item);
+
+    if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
+      {
+        m_face.m_transport->pause();
+        if (!m_ioServiceWork) {
+          m_processEventsTimeoutTimer->cancel();
+        }
+      }
+    onSuccess();
+  }
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  void
+  checkPitExpire()
+  {
+    // Check for PIT entry timeouts.
+    time::steady_clock::TimePoint now = time::steady_clock::now();
+
+    PendingInterestTable::iterator i = m_pendingInterestTable.begin();
+    while (i != m_pendingInterestTable.end())
+      {
+        if ((*i)->isTimedOut(now))
+          {
+            // Save the PendingInterest and remove it from the PIT.  Then call the callback.
+            shared_ptr<PendingInterest> pendingInterest = *i;
+
+            i = m_pendingInterestTable.erase(i);
+
+            pendingInterest->callTimeout();
+          }
+        else
+          ++i;
+      }
+
+    if (!m_pendingInterestTable.empty()) {
+      m_pitTimeoutCheckTimerActive = true;
+
+      m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
+      m_pitTimeoutCheckTimer->async_wait(bind(&Impl::checkPitExpire, this));
+    }
+    else {
+      m_pitTimeoutCheckTimerActive = false;
+
+      if (m_registeredPrefixTable.empty()) {
+        m_face.m_transport->pause();
+        if (!m_ioServiceWork) {
+          m_processEventsTimeoutTimer->cancel();
+        }
+      }
+    }
+  }
+
+private:
+  Face& m_face;
+
+  PendingInterestTable m_pendingInterestTable;
+  InterestFilterTable m_interestFilterTable;
+  RegisteredPrefixTable m_registeredPrefixTable;
+
+  ConfigFile m_config;
+
+  shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
+  shared_ptr<monotonic_deadline_timer> m_pitTimeoutCheckTimer;
+  bool m_pitTimeoutCheckTimerActive;
+  shared_ptr<monotonic_deadline_timer> m_processEventsTimeoutTimer;
+
+  friend class Face;
+};
+
+} // namespace ndn
+
+#endif // NDN_DETAIL_FACE_IMPL_HPP
diff --git a/src/detail/pending-interest.hpp b/src/detail/pending-interest.hpp
index ad03746..f23db08 100644
--- a/src/detail/pending-interest.hpp
+++ b/src/detail/pending-interest.hpp
@@ -37,12 +37,12 @@
    */
   PendingInterest(const shared_ptr<const Interest>& interest, const OnData& onData,
                   const OnTimeout& onTimeout)
-    : interest_(interest)
-    , onData_(onData)
+    : m_interest(interest)
+    , m_onData(onData)
     , m_onTimeout(onTimeout)
   {
-    if (interest_->getInterestLifetime() >= time::milliseconds::zero())
-      m_timeout = time::steady_clock::now() + interest_->getInterestLifetime();
+    if (m_interest->getInterestLifetime() >= time::milliseconds::zero())
+      m_timeout = time::steady_clock::now() + m_interest->getInterestLifetime();
     else
       m_timeout = time::steady_clock::now() + DEFAULT_INTEREST_LIFETIME;
   }
@@ -50,13 +50,13 @@
   const shared_ptr<const Interest>&
   getInterest()
   {
-    return interest_;
+    return m_interest;
   }
 
   const OnData&
   getOnData()
   {
-    return onData_;
+    return m_onData;
   }
 
   /**
@@ -76,25 +76,27 @@
   callTimeout()
   {
     if (m_onTimeout) {
-      m_onTimeout(*interest_);
+      m_onTimeout(*m_interest);
     }
   }
 
 private:
-  shared_ptr<const Interest> interest_;
-  const OnData onData_;
+  shared_ptr<const Interest> m_interest;
+  const OnData m_onData;
   const OnTimeout m_onTimeout;
   time::steady_clock::TimePoint m_timeout;
 };
 
 
-struct PendingInterestId;
+class PendingInterestId;
 
 /**
  * @brief Functor to match pending interests against PendingInterestId
  */
-struct MatchPendingInterestId
+class MatchPendingInterestId
 {
+public:
+  explicit
   MatchPendingInterestId(const PendingInterestId* pendingInterestId)
     : m_id(pendingInterestId)
   {
diff --git a/src/encoding/block-helpers.hpp b/src/encoding/block-helpers.hpp
index 317cd13..36c9474 100644
--- a/src/encoding/block-helpers.hpp
+++ b/src/encoding/block-helpers.hpp
@@ -12,21 +12,24 @@
  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
-#ifndef NDN_BLOCK_HELPERS_HPP
-#define NDN_BLOCK_HELPERS_HPP
+#ifndef NDN_ENCODING_BLOCK_HELPERS_HPP
+#define NDN_ENCODING_BLOCK_HELPERS_HPP
 
 #include "block.hpp"
+#include "encoding-buffer.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());
+  EncodingEstimator estimator;
+  size_t totalLength = prependNonNegativeIntegerBlock(estimator, type, value);
+
+  EncodingBuffer encoder(totalLength, 0);
+  prependNonNegativeIntegerBlock(encoder, type, value);
+
+  return encoder.block();
 }
 
 inline uint64_t
@@ -39,45 +42,49 @@
 inline Block
 booleanBlock(uint32_t type)
 {
-  OBufferStream os;
-  Tlv::writeVarNumber(os, type);
-  Tlv::writeVarNumber(os, 0);
-  return Block(os.buf());
+  EncodingEstimator estimator;
+  size_t totalLength = prependBooleanBlock(estimator, type);
+
+  EncodingBuffer encoder(totalLength, 0);
+  prependBooleanBlock(encoder, type);
+
+  return encoder.block();
+}
+
+inline Block
+dataBlock(uint32_t type, const uint8_t* data, size_t dataSize)
+{
+  EncodingEstimator estimator;
+  size_t totalLength = prependByteArrayBlock(estimator, type, data, dataSize);
+
+  EncodingBuffer encoder(totalLength, 0);
+  prependByteArrayBlock(encoder, type, data, dataSize);
+
+  return encoder.block();
 }
 
 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());
+  return dataBlock(type, reinterpret_cast<const uint8_t*>(data), dataSize);
 }
 
-inline Block
-dataBlock(uint32_t type, const unsigned char* data, size_t dataSize)
-{
-  return dataBlock(type, reinterpret_cast<const char*>(data), dataSize);
-}
+// template<class InputIterator>
+// inline Block
+// dataBlock(uint32_t type, InputIterator first, InputIterator last)
+// {
+//   size_t dataSize = 0;
+//   for (InputIterator i = first; i != last; i++)
+//     ++dataSize;
 
-template<class InputIterator>
-inline Block
-dataBlock(uint32_t type, InputIterator first, InputIterator last)
-{
-  size_t dataSize = 0;
-  for (InputIterator i = first; i != last; i++)
-    ++dataSize;
+//   OBufferStream os;
+//   Tlv::writeVarNumber(os, type);
+//   Tlv::writeVarNumber(os, dataSize);
+//   std::copy(first, last, std::ostream_iterator<uint8_t>(os));
 
-  OBufferStream os;
-  Tlv::writeVarNumber(os, type);
-  Tlv::writeVarNumber(os, dataSize);
-  std::copy(first, last, std::ostream_iterator<uint8_t>(os));
-
-  return Block(os.buf());
-}
+//   return Block(os.buf());
+// }
 
 } // namespace ndn
 
-#endif // NDN_BLOCK_HELPERS_HPP
+#endif // NDN_ENCODING_BLOCK_HELPERS_HPP
diff --git a/src/encoding/block.cpp b/src/encoding/block.cpp
index e3730c3..3f0cee3 100644
--- a/src/encoding/block.cpp
+++ b/src/encoding/block.cpp
@@ -15,11 +15,18 @@
 #include "common.hpp"
 
 #include "block.hpp"
+#include "block-helpers.hpp"
+
 #include "tlv.hpp"
 #include "encoding-buffer.hpp"
+#include "buffer-stream.hpp"
+
+#include <boost/lexical_cast.hpp>
 
 namespace ndn {
 
+const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM = 8800;
+
 Block::Block()
   : m_type(std::numeric_limits<uint32_t>::max())
 {
@@ -96,44 +103,6 @@
     }
 }
 
-Block::Block(std::istream& is)
-{
-  std::istream_iterator<uint8_t> tmp_begin(is);
-  std::istream_iterator<uint8_t> tmp_end;
-
-  m_type = Tlv::readType(tmp_begin, tmp_end);
-  uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
-
-  // We may still have some problem here, if some exception happens in this constructor,
-  // we may completely lose all the bytes extracted from the stream.
-
-  OBufferStream os;
-  size_t headerLength = Tlv::writeVarNumber(os, m_type);
-  headerLength += Tlv::writeVarNumber(os, length);
-
-  char* buf = new char[length];
-  buf[0] = *tmp_begin;
-  is.read(buf+1, length-1);
-
-  if (length != static_cast<uint64_t>(is.gcount()) + 1)
-    {
-      delete [] buf;
-      throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
-    }
-
-  os.write(buf, length);
-  delete [] buf;
-
-  m_buffer = os.buf();
-
-  m_begin = m_buffer->begin();
-  m_end = m_buffer->end();
-  m_size = m_end - m_begin;
-
-  m_value_begin = m_buffer->begin() + headerLength;
-  m_value_end   = m_buffer->end();
-}
-
 
 Block::Block(const uint8_t* buffer, size_t maxlength)
 {
@@ -210,6 +179,32 @@
   m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
 }
 
+Block
+Block::fromStream(std::istream& is)
+{
+  std::istream_iterator<uint8_t> tmp_begin(is);
+  std::istream_iterator<uint8_t> tmp_end;
+
+  uint32_t type = Tlv::readType(tmp_begin, tmp_end);
+  uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
+
+  if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM)
+    throw Tlv::Error("Length of block from stream is too large");
+
+  // We may still have some problem here, if some exception happens,
+  // we may completely lose all the bytes extracted from the stream.
+
+  char buf[MAX_SIZE_OF_BLOCK_FROM_STREAM];
+  buf[0] = *tmp_begin;
+  is.read(buf+1, length-1);
+
+  if (length != static_cast<uint64_t>(is.gcount()) + 1) {
+    throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
+  }
+
+  return dataBlock(type, buf, length);
+}
+
 bool
 Block::fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block)
 {
@@ -376,4 +371,21 @@
                begin, end);
 }
 
+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");
+}
+
 } // namespace ndn
diff --git a/src/encoding/block.hpp b/src/encoding/block.hpp
index d23e8c8..d1a762f 100644
--- a/src/encoding/block.hpp
+++ b/src/encoding/block.hpp
@@ -12,8 +12,8 @@
  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
-#ifndef NDN_BLOCK_HPP
-#define NDN_BLOCK_HPP
+#ifndef NDN_ENCODING_BLOCK_HPP
+#define NDN_ENCODING_BLOCK_HPP
 
 #include "../common.hpp"
 
@@ -83,12 +83,6 @@
 
   Block(const void* buffer, size_t maxlength);
 
-  /*
-   * @brief A helper version of a constructor to create Block from the stream.
-   */
-  explicit
-  Block(std::istream& is);
-
   /**
    * @brief Create Block from the wire buffer (no parsing)
    *
@@ -124,6 +118,23 @@
   explicit
   Block(uint32_t type, const Block& value);
 
+  /*
+   * @brief A helper version of a constructor to create Block from the stream
+   *
+   * @deprecated Use Block::fromStream instead
+   */
+  explicit
+  Block(std::istream& is)
+  {
+    *this = Block::fromStream(is);
+  }
+
+  /*
+   * @brief A helper version of a constructor to create Block from the stream.
+   */
+  Block
+  fromStream(std::istream& is);
+
   /**
    * @brief Try to construct block from Buffer, referencing data block pointed by wire
    *
@@ -327,23 +338,6 @@
   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::element_const_iterator
 Block::find(uint32_t type) const
 {
@@ -504,6 +498,4 @@
 
 } // ndn
 
-#include "block-helpers.hpp"
-
-#endif // NDN_BLOCK_HPP
+#endif // NDN_ENCODING_BLOCK_HPP
diff --git a/src/encoding/buffer-stream.hpp b/src/encoding/buffer-stream.hpp
new file mode 100644
index 0000000..127d457
--- /dev/null
+++ b/src/encoding/buffer-stream.hpp
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ *
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ */
+
+#ifndef NDN_ENCODING_BUFFER_STREAM_HPP
+#define NDN_ENCODING_BUFFER_STREAM_HPP
+
+#include "buffer.hpp"
+
+#include <boost/iostreams/detail/ios.hpp>
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/stream.hpp>
+
+namespace ndn {
+
+/// @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);
+ *      shared_ptr<Buffer> buf = obuf.get();
+ * @endcode
+ */
+class OBufferStream : public boost::iostreams::stream<iostreams::buffer_append_device>
+{
+public:
+  /**
+   * Default constructor
+   */
+  OBufferStream()
+    : m_buffer(make_shared<Buffer>())
+    , m_device(*m_buffer)
+  {
+    open(m_device);
+  }
+
+  /**
+   * Flush written data to the stream and return shared pointer to the underlying buffer
+   */
+  shared_ptr<Buffer>
+  buf()
+  {
+    flush();
+    return m_buffer;
+  }
+
+private:
+  BufferPtr m_buffer;
+  iostreams::buffer_append_device m_device;
+};
+
+} // ndn
+
+#endif // NDN_ENCODING_BUFFER_STREAM_HPP
diff --git a/src/encoding/buffer.hpp b/src/encoding/buffer.hpp
index d4b14c0..5701511 100644
--- a/src/encoding/buffer.hpp
+++ b/src/encoding/buffer.hpp
@@ -12,11 +12,13 @@
  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
-#ifndef NDN_BUFFER_HPP
-#define NDN_BUFFER_HPP
+#ifndef NDN_ENCODING_BUFFER_HPP
+#define NDN_ENCODING_BUFFER_HPP
 
 #include "../common.hpp"
 
+#include <vector>
+
 namespace ndn {
 
 class Buffer;
@@ -134,78 +136,6 @@
   }
 };
 
-/// @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);
- *      shared_ptr<Buffer> buf = obuf.get();
- * @endcode
- */
-struct OBufferStream : public boost::iostreams::stream<iostreams::buffer_append_device>
-{
-  /**
-   * Default constructor
-   */
-  OBufferStream()
-    : m_buffer(make_shared<Buffer>())
-    , m_device(*m_buffer)
-  {
-    open(m_device);
-  }
-
-  /**
-   * Flush written data to the stream and return shared pointer to the underlying buffer
-   */
-  shared_ptr<Buffer>
-  buf()
-  {
-    flush();
-    return m_buffer;
-  }
-
-private:
-  BufferPtr m_buffer;
-  iostreams::buffer_append_device m_device;
-};
-
-
 } // ndn
 
-#endif // NDN_BUFFER_HPP
+#endif // NDN_ENCODING_BUFFER_HPP
diff --git a/src/encoding/cryptopp/asn_ext.hpp b/src/encoding/cryptopp/asn_ext.hpp
index bbfe733..0d64d40 100644
--- a/src/encoding/cryptopp/asn_ext.hpp
+++ b/src/encoding/cryptopp/asn_ext.hpp
@@ -19,6 +19,8 @@
 #include "../../common.hpp"
 #include "../../security/cryptopp.hpp"
 
+#include "../../util/time.hpp"
+
 namespace ndn {
 
 size_t
diff --git a/src/encoding/encoding-buffer.hpp b/src/encoding/encoding-buffer.hpp
index 07ee33d..0464287 100644
--- a/src/encoding/encoding-buffer.hpp
+++ b/src/encoding/encoding-buffer.hpp
@@ -13,17 +13,14 @@
  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
-#ifndef NDN_ENCODING_BUFFER_HPP
-#define NDN_ENCODING_BUFFER_HPP
+#ifndef NDN_ENCODING_ENCODING_BUFFER_HPP
+#define NDN_ENCODING_ENCODING_BUFFER_HPP
 
 #include "../common.hpp"
 
 #include "buffer.hpp"
-#include "tlv.hpp"
 #include "block.hpp"
 
-#include <boost/lexical_cast.hpp>
-
 namespace ndn {
 
 namespace encoding {
@@ -566,4 +563,4 @@
 
 } // ndn
 
-#endif // NDN_ENCODING_BUFFER_HPP
+#endif // NDN_ENCODING_ENCODING_BUFFER_HPP
diff --git a/src/encoding/endian.hpp b/src/encoding/endian.hpp
index 5329112..8b330b9 100644
--- a/src/encoding/endian.hpp
+++ b/src/encoding/endian.hpp
@@ -12,17 +12,20 @@
  * @author Junxiao Shi <http://www.cs.arizona.edu/people/shijunxiao/>
  */
 
+#ifndef NDN_ENCODING_ENDIAN_HPP
+#define NDN_ENCODING_ENDIAN_HPP
+
 #ifdef __linux__
 
 #include <endian.h>
 
-#endif
+#endif // __linux__
 
 #ifdef __FreeBSD__
 
 #include <sys/endian.h>
 
-#endif
+#endif // __FreeBSD__
 
 #ifdef __APPLE__
 
@@ -40,4 +43,6 @@
 #define be64toh(x) OSSwapBigToHostInt64(x)
 #define le64toh(x) OSSwapLittleToHostInt64(x)
 
-#endif
+#endif // __APPLE__
+
+#endif // NDN_ENCODING_ENDIAN_HPP
diff --git a/src/encoding/oid.cpp b/src/encoding/oid.cpp
index edbfa1a..f9085b2 100644
--- a/src/encoding/oid.cpp
+++ b/src/encoding/oid.cpp
@@ -17,6 +17,8 @@
 
 #include "../security/cryptopp.hpp"
 
+#include <sstream>
+
 using namespace std;
 using namespace CryptoPP;
 
diff --git a/src/encoding/oid.hpp b/src/encoding/oid.hpp
index b9b41e0..9dc846f 100644
--- a/src/encoding/oid.hpp
+++ b/src/encoding/oid.hpp
@@ -10,11 +10,13 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
-#ifndef NDN_OID_HPP
-#define NDN_OID_HPP
+#ifndef NDN_ENCODING_OID_HPP
+#define NDN_ENCODING_OID_HPP
 
 #include "../common.hpp"
 
+#include <vector>
+
 namespace CryptoPP {
 class BufferedTransformation;
 }
@@ -81,4 +83,4 @@
 
 }
 
-#endif
+#endif // NDN_ENCODING_OID_HPP
diff --git a/src/encoding/tlv-ndnd.hpp b/src/encoding/tlv-ndnd.hpp
deleted file mode 100644
index ddb3421..0000000
--- a/src/encoding/tlv-ndnd.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (c) 2013-2014,  Regents of the University of California.
- * All rights reserved.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * This file licensed under New BSD License.  See COPYING for detailed information about
- * ndn-cxx library copyright, permissions, and redistribution restrictions.
- */
-
-#ifndef NDN_TLV_NDND_HPP
-#define NDN_TLV_NDND_HPP
-
-#include "tlv.hpp"
-
-namespace ndn {
-namespace tlv {
-namespace ndnd {
-
-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 ndnd
-} // namespace tlv
-
-
-// temporary, until all the dependent code is updated
-namespace Tlv {
-namespace FaceManagement {
-using namespace ::ndn::tlv::ndnd;
-} // namespace FaceManagement
-} // namespace Tlv
-
-} // namespace ndn
-
-#endif // NDN_TLV_NDND_HPP
diff --git a/src/encoding/tlv-nfd.hpp b/src/encoding/tlv-nfd.hpp
index 490b6da..ad86636 100644
--- a/src/encoding/tlv-nfd.hpp
+++ b/src/encoding/tlv-nfd.hpp
@@ -10,8 +10,8 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
-#ifndef NDN_TLV_NFD_HPP
-#define NDN_TLV_NFD_HPP
+#ifndef NDN_ENCODING_TLV_NFD_HPP
+#define NDN_ENCODING_TLV_NFD_HPP
 
 #include "../common.hpp"
 
@@ -81,4 +81,4 @@
 
 } // namespace ndn
 
-#endif // NDN_TLV_NFD_HPP
+#endif // NDN_ENCODING_TLV_NFD_HPP
diff --git a/src/encoding/tlv-nrd.hpp b/src/encoding/tlv-nrd.hpp
deleted file mode 100644
index 3a3076f..0000000
--- a/src/encoding/tlv-nrd.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (c) 2013-2014,  Regents of the University of California.
- * All rights reserved.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * This file licensed under New BSD License.  See COPYING for detailed information about
- * ndn-cxx library copyright, permissions, and redistribution restrictions.
- */
-
-#ifndef NDN_TLV_NRD_HPP
-#define NDN_TLV_NRD_HPP
-
-#include "tlv.hpp"
-
-namespace ndn {
-namespace tlv {
-namespace nrd {
-
-// \deprecated use NFD RIB Management
-enum {
-  PrefixRegOptions = 101,
-  FaceId           = 102,
-  Flags            = 103,
-  Cost             = 104,
-  ExpirationPeriod = 105,
-  StrategyName     = 106,
-  Protocol         = 107
-};
-
-enum {
-  NDN_FORW_CHILD_INHERIT = 1,
-  NDN_FORW_CAPTURE       = 2
-};
-
-} // namespace nrd
-} // namespace tlv
-} // namespace ndn
-
-#endif // NDN_TLV_NRD_HPP
diff --git a/src/encoding/tlv-security.hpp b/src/encoding/tlv-security.hpp
index 8e1f224..ab10201 100644
--- a/src/encoding/tlv-security.hpp
+++ b/src/encoding/tlv-security.hpp
@@ -10,8 +10,8 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
-#ifndef NDN_TLV_SECURITY_HPP
-#define NDN_TLV_SECURITY_HPP
+#ifndef NDN_ENCODING_TLV_SECURITY_HPP
+#define NDN_ENCODING_TLV_SECURITY_HPP
 
 #include "tlv.hpp"
 
@@ -29,4 +29,4 @@
 } // namespace tlv
 } // namespace ndn
 
-#endif // NDN_TLV_SECURITY_HPP
+#endif // NDN_ENCODING_TLV_SECURITY_HPP
diff --git a/src/encoding/tlv.hpp b/src/encoding/tlv.hpp
index 594cdce..d071a2e 100644
--- a/src/encoding/tlv.hpp
+++ b/src/encoding/tlv.hpp
@@ -10,8 +10,8 @@
  * ndn-cxx library copyright, permissions, and redistribution restrictions.
  */
 
-#ifndef NDN_TLV_HPP
-#define NDN_TLV_HPP
+#ifndef NDN_ENCODING_TLV_HPP
+#define NDN_ENCODING_TLV_HPP
 
 #include <stdexcept>
 #include <iterator>
@@ -527,4 +527,4 @@
 
 } // namespace ndn
 
-#endif // NDN_TLV_HPP
+#endif // NDN_ENCODING_TLV_HPP
diff --git a/src/exclude.hpp b/src/exclude.hpp
index 2fa939f..d187a1a 100644
--- a/src/exclude.hpp
+++ b/src/exclude.hpp
@@ -17,6 +17,8 @@
 
 #include "name-component.hpp"
 
+#include <map>
+
 namespace ndn {
 
 /**
diff --git a/src/face.cpp b/src/face.cpp
index 6432acf..c2231c6 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -12,26 +12,24 @@
  * Based on code originally written by Jeff Thompson <jefft0@remap.ucla.edu>
  */
 
-#include "common.hpp"
-
 #include "face.hpp"
+#include "detail/face-impl.hpp"
 
-#include "security/signature-sha256-with-rsa.hpp"
+#include "interest.hpp"
+#include "data.hpp"
+#include "security/identity-certificate.hpp"
 
 #include "util/time.hpp"
 #include "util/random.hpp"
-#include "util/config-file.hpp"
-#include <cstdlib>
-
-#include "management/nfd-controller.hpp"
 
 namespace ndn {
 
 Face::Face()
   : m_nfdController(new nfd::Controller(*this))
   , m_isDirectNfdFibManagementRequested(false)
+  , m_impl(make_shared<Impl>(ref(*this)))
 {
-  const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
+  const std::string socketName = UnixTransport::getDefaultSocketName(m_impl->m_config);
   construct(make_shared<UnixTransport>(socketName),
             make_shared<boost::asio::io_service>());
 }
@@ -39,8 +37,9 @@
 Face::Face(const shared_ptr<boost::asio::io_service>& ioService)
   : m_nfdController(new nfd::Controller(*this))
   , m_isDirectNfdFibManagementRequested(false)
+  , m_impl(make_shared<Impl>(ref(*this)))
 {
-  const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
+  const std::string socketName = UnixTransport::getDefaultSocketName(m_impl->m_config);
   construct(make_shared<UnixTransport>(socketName),
             ioService);
 }
@@ -55,24 +54,27 @@
 };
 
 Face::Face(boost::asio::io_service& ioService)
-  : m_nfdController(new nfd::Controller(*this))
+  : m_nfdController(make_shared<nfd::Controller>(ref(*this)))
   , m_isDirectNfdFibManagementRequested(false)
+  , m_impl(make_shared<Impl>(ref(*this)))
 {
-  const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
+  const std::string socketName = UnixTransport::getDefaultSocketName(m_impl->m_config);
   construct(make_shared<UnixTransport>(socketName),
             shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
 }
 
 Face::Face(const std::string& host, const std::string& port/* = "6363"*/)
-  : m_nfdController(new nfd::Controller(*this))
+  : m_nfdController(make_shared<nfd::Controller>(ref(*this)))
+  , m_impl(make_shared<Impl>(ref(*this)))
 {
   construct(make_shared<TcpTransport>(host, port),
             make_shared<boost::asio::io_service>());
 }
 
 Face::Face(const shared_ptr<Transport>& transport)
-  : m_nfdController(new nfd::Controller(*this))
+  : m_nfdController(make_shared<nfd::Controller>(ref(*this)))
   , m_isDirectNfdFibManagementRequested(false)
+  , m_impl(make_shared<Impl>(ref(*this)))
 {
   construct(transport,
             make_shared<boost::asio::io_service>());
@@ -80,34 +82,30 @@
 
 Face::Face(const shared_ptr<Transport>& transport,
            boost::asio::io_service& ioService)
-  : m_nfdController(new nfd::Controller(*this))
+  : m_nfdController(make_shared<nfd::Controller>(ref(*this)))
   , m_isDirectNfdFibManagementRequested(false)
+  , m_impl(make_shared<Impl>(ref(*this)))
 {
   construct(transport,
             shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
 }
 
-Face::~Face()
-{
-  delete m_nfdController;
-}
-
 void
 Face::construct(const shared_ptr<Transport>& transport,
                 const shared_ptr<boost::asio::io_service>& ioService)
 {
-  m_pitTimeoutCheckTimerActive = false;
+  m_impl->m_pitTimeoutCheckTimerActive = false;
   m_transport = transport;
   m_ioService = ioService;
 
-  m_pitTimeoutCheckTimer      = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
-  m_processEventsTimeoutTimer = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
+  m_impl->m_pitTimeoutCheckTimer      = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
+  m_impl->m_processEventsTimeoutTimer = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
 
   std::string protocol = "nrd-0.1";
 
   try
     {
-      protocol = m_config.getParsedConfiguration().get<std::string>("protocol");
+      protocol = m_impl->m_config.getParsedConfiguration().get<std::string>("protocol");
     }
   catch (boost::property_tree::ptree_bad_path& error)
     {
@@ -142,7 +140,7 @@
   shared_ptr<Interest> interestToExpress = make_shared<Interest>(interest);
 
   // If the same ioService thread, dispatch directly calls the method
-  m_ioService->dispatch(bind(&Face::asyncExpressInterest, this,
+  m_ioService->dispatch(bind(&Impl::asyncExpressInterest, m_impl,
                              interestToExpress, onData, onTimeout));
 
   return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
@@ -165,33 +163,6 @@
 }
 
 void
-Face::asyncExpressInterest(const shared_ptr<const Interest>& interest,
-                           const OnData& onData, const OnTimeout& onTimeout)
-{
-  if (!m_transport->isExpectingData())
-    m_transport->resume();
-
-  m_pendingInterestTable.push_back(make_shared<PendingInterest>(interest, onData, onTimeout));
-
-  if (!interest->getLocalControlHeader().empty(false, true))
-    {
-      // encode only NextHopFaceId towards the forwarder
-      m_transport->send(interest->getLocalControlHeader().wireEncode(*interest, false, true),
-                        interest->wireEncode());
-    }
-  else
-    {
-      m_transport->send(interest->wireEncode());
-    }
-
-  if (!m_pitTimeoutCheckTimerActive) {
-    m_pitTimeoutCheckTimerActive = true;
-    m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
-    m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
-  }
-}
-
-void
 Face::put(const Data& data)
 {
   if (!m_transport->isConnected())
@@ -212,61 +183,10 @@
 void
 Face::removePendingInterest(const PendingInterestId* pendingInterestId)
 {
-  m_ioService->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
+  m_ioService->post(bind(&Impl::asyncRemovePendingInterest, m_impl, pendingInterestId));
 }
 
 
-void
-Face::asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
-{
-  m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
-}
-
-
-template<class SignatureGenerator>
-const RegisteredPrefixId*
-Face::registerPrefixImpl(const Name& prefix,
-                         const shared_ptr<InterestFilterRecord>& filter,
-                         const RegisterPrefixSuccessCallback& onSuccess,
-                         const RegisterPrefixFailureCallback& onFailure,
-                         const SignatureGenerator& signatureGenerator)
-{
-  typedef void (nfd::Controller::*Registrator)
-    (const nfd::ControlParameters&,
-     const nfd::Controller::CommandSucceedCallback&,
-     const nfd::Controller::CommandFailCallback&,
-     const SignatureGenerator&,
-     const time::milliseconds&);
-
-  Registrator registrator, unregistrator;
-  if (!m_isDirectNfdFibManagementRequested) {
-    registrator = static_cast<Registrator>(&nfd::Controller::start<nfd::RibRegisterCommand>);
-    unregistrator = static_cast<Registrator>(&nfd::Controller::start<nfd::RibUnregisterCommand>);
-  }
-  else {
-    registrator = static_cast<Registrator>(&nfd::Controller::start<nfd::FibAddNextHopCommand>);
-    unregistrator = static_cast<Registrator>(&nfd::Controller::start<nfd::FibRemoveNextHopCommand>);
-  }
-
-  nfd::ControlParameters parameters;
-  parameters.setName(prefix);
-
-  RegisteredPrefix::Unregistrator bindedUnregistrator =
-    bind(unregistrator, m_nfdController, parameters, _1, _2,
-         signatureGenerator,
-         m_nfdController->getDefaultCommandTimeout());
-
-  shared_ptr<RegisteredPrefix> prefixToRegister =
-    ndn::make_shared<RegisteredPrefix>(prefix, filter, bindedUnregistrator);
-
-  (m_nfdController->*registrator)(parameters,
-    bind(&Face::afterPrefixRegistered, this, prefixToRegister, onSuccess),
-    bind(onFailure, prefixToRegister->getPrefix(), _2),
-    signatureGenerator,
-    m_nfdController->getDefaultCommandTimeout());
-
-  return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
-}
 
 const RegisteredPrefixId*
 Face::setInterestFilter(const InterestFilter& interestFilter,
@@ -278,9 +198,9 @@
   shared_ptr<InterestFilterRecord> filter =
     make_shared<InterestFilterRecord>(interestFilter, onInterest);
 
-  return registerPrefixImpl(interestFilter.getPrefix(), filter,
-                            onSuccess, onFailure,
-                            certificate);
+  return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
+                                onSuccess, onFailure,
+                                certificate);
 }
 
 const RegisteredPrefixId*
@@ -292,9 +212,9 @@
   shared_ptr<InterestFilterRecord> filter =
     make_shared<InterestFilterRecord>(interestFilter, onInterest);
 
-  return registerPrefixImpl(interestFilter.getPrefix(), filter,
-                            RegisterPrefixSuccessCallback(), onFailure,
-                            certificate);
+  return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
+                                RegisterPrefixSuccessCallback(), onFailure,
+                                certificate);
 }
 
 const RegisteredPrefixId*
@@ -307,9 +227,9 @@
   shared_ptr<InterestFilterRecord> filter =
     make_shared<InterestFilterRecord>(interestFilter, onInterest);
 
-  return registerPrefixImpl(interestFilter.getPrefix(), filter,
-                            onSuccess, onFailure,
-                            identity);
+  return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
+                                onSuccess, onFailure,
+                                identity);
 }
 
 const RegisteredPrefixId*
@@ -321,9 +241,9 @@
   shared_ptr<InterestFilterRecord> filter =
     make_shared<InterestFilterRecord>(interestFilter, onInterest);
 
-  return registerPrefixImpl(interestFilter.getPrefix(), filter,
-                            RegisterPrefixSuccessCallback(), onFailure,
-                            identity);
+  return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
+                                RegisterPrefixSuccessCallback(), onFailure,
+                                identity);
 }
 
 
@@ -334,26 +254,20 @@
   shared_ptr<InterestFilterRecord> filter =
     make_shared<InterestFilterRecord>(interestFilter, onInterest);
 
-  getIoService().post(bind(&Face::asyncSetInterestFilter, this, filter));
+  getIoService().post(bind(&Impl::asyncSetInterestFilter, m_impl, filter));
 
   return reinterpret_cast<const InterestFilterId*>(filter.get());
 }
 
-void
-Face::asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord)
-{
-  m_interestFilterTable.push_back(interestFilterRecord);
-}
-
 const RegisteredPrefixId*
 Face::registerPrefix(const Name& prefix,
                      const RegisterPrefixSuccessCallback& onSuccess,
                      const RegisterPrefixFailureCallback& onFailure,
                      const IdentityCertificate& certificate)
 {
-  return registerPrefixImpl(prefix, shared_ptr<InterestFilterRecord>(),
-                            onSuccess, onFailure,
-                            certificate);
+  return m_impl->registerPrefix(prefix, shared_ptr<InterestFilterRecord>(),
+                                onSuccess, onFailure,
+                                certificate);
 }
 
 const RegisteredPrefixId*
@@ -362,101 +276,34 @@
                      const RegisterPrefixFailureCallback& onFailure,
                      const Name& identity)
 {
-  return registerPrefixImpl(prefix, shared_ptr<InterestFilterRecord>(),
-                            onSuccess, onFailure,
-                            identity);
+  return m_impl->registerPrefix(prefix, shared_ptr<InterestFilterRecord>(),
+                                onSuccess, onFailure,
+                                identity);
 }
 
 
 void
-Face::afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
-                            const RegisterPrefixSuccessCallback& onSuccess)
-{
-  m_registeredPrefixTable.push_back(registeredPrefix);
-
-  if (static_cast<bool>(registeredPrefix->getFilter())) {
-    // it was a combined operation
-    m_interestFilterTable.push_back(registeredPrefix->getFilter());
-  }
-
-  if (static_cast<bool>(onSuccess)) {
-    onSuccess(registeredPrefix->getPrefix());
-  }
-}
-
-void
 Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
 {
-  m_ioService->post(bind(&Face::asyncUnregisterPrefix, this, registeredPrefixId,
+  m_ioService->post(bind(&Impl::asyncUnregisterPrefix, m_impl, registeredPrefixId,
                          UnregisterPrefixSuccessCallback(), UnregisterPrefixFailureCallback()));
 }
 
+void
+Face::unsetInterestFilter(const InterestFilterId* interestFilterId)
+{
+  m_ioService->post(bind(&Impl::asyncUnsetInterestFilter, m_impl, interestFilterId));
+}
 
 void
 Face::unregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
                        const UnregisterPrefixSuccessCallback& onSuccess,
                        const UnregisterPrefixFailureCallback& onFailure)
 {
-  m_ioService->post(bind(&Face::asyncUnregisterPrefix, this, registeredPrefixId,
+  m_ioService->post(bind(&Impl::asyncUnregisterPrefix, m_impl, registeredPrefixId,
                          onSuccess, onFailure));
 }
 
-
-void
-Face::asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
-{
-  InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
-                                                 m_interestFilterTable.end(),
-                                                 MatchInterestFilterId(interestFilterId));
-  if (i != m_interestFilterTable.end())
-    {
-      m_interestFilterTable.erase(i);
-    }
-}
-
-
-void
-Face::asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
-                            const UnregisterPrefixSuccessCallback& onSuccess,
-                            const UnregisterPrefixFailureCallback& onFailure)
-{
-  RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
-                                                   m_registeredPrefixTable.end(),
-                                                   MatchRegisteredPrefixId(registeredPrefixId));
-  if (i != m_registeredPrefixTable.end())
-    {
-      const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
-      if (static_cast<bool>(filter))
-        {
-          // it was a combined operation
-          m_interestFilterTable.remove(filter);
-        }
-
-      (*i)->unregister(bind(&Face::finalizeUnregisterPrefix, this, i, onSuccess),
-                       bind(onFailure, _2));
-    }
-  else
-    onFailure("Unrecognized PrefixId");
-
-  // there cannot be two registered prefixes with the same id
-}
-
-void
-Face::finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
-                               const UnregisterPrefixSuccessCallback& onSuccess)
-{
-  m_registeredPrefixTable.erase(item);
-
-  if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
-    {
-      m_transport->pause();
-      if (!m_ioServiceWork) {
-        m_processEventsTimeoutTimer->cancel();
-      }
-    }
-  onSuccess();
-}
-
 void
 Face::processEvents(const time::milliseconds& timeout/* = time::milliseconds::zero()*/,
                     bool keepThread/* = false*/)
@@ -472,13 +319,13 @@
 
       if (timeout > time::milliseconds::zero())
         {
-          m_processEventsTimeoutTimer->expires_from_now(time::milliseconds(timeout));
-          m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
+          m_impl->m_processEventsTimeoutTimer->expires_from_now(time::milliseconds(timeout));
+          m_impl->m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
         }
 
       if (keepThread) {
         // work will ensure that m_ioService is running until work object exists
-        m_ioServiceWork = make_shared<boost::asio::io_service::work>(ref(*m_ioService));
+        m_impl->m_ioServiceWork = make_shared<boost::asio::io_service::work>(ref(*m_ioService));
       }
 
       m_ioService->run();
@@ -492,8 +339,8 @@
   catch (std::exception&)
     {
       m_ioService->reset();
-      m_pendingInterestTable.clear();
-      m_registeredPrefixTable.clear();
+      m_impl->m_pendingInterestTable.clear();
+      m_impl->m_registeredPrefixTable.clear();
       throw;
     }
 }
@@ -507,15 +354,15 @@
 void
 Face::asyncShutdown()
 {
-  m_pendingInterestTable.clear();
-  m_registeredPrefixTable.clear();
+  m_impl->m_pendingInterestTable.clear();
+  m_impl->m_registeredPrefixTable.clear();
 
   if (m_transport->isConnected())
     m_transport->close();
 
-  m_pitTimeoutCheckTimer->cancel();
-  m_processEventsTimeoutTimer->cancel();
-  m_pitTimeoutCheckTimerActive = false;
+  m_impl->m_pitTimeoutCheckTimer->cancel();
+  m_impl->m_processEventsTimeoutTimer->cancel();
+  m_impl->m_pitTimeoutCheckTimerActive = false;
 }
 
 void
@@ -525,46 +372,6 @@
     throw Face::ProcessEventsTimeout();
 }
 
-void
-Face::checkPitExpire()
-{
-  // Check for PIT entry timeouts.
-  time::steady_clock::TimePoint now = time::steady_clock::now();
-
-  PendingInterestTable::iterator i = m_pendingInterestTable.begin();
-  while (i != m_pendingInterestTable.end())
-    {
-      if ((*i)->isTimedOut(now))
-        {
-          // Save the PendingInterest and remove it from the PIT.  Then call the callback.
-          shared_ptr<PendingInterest> pendingInterest = *i;
-
-          i = m_pendingInterestTable.erase(i);
-
-          pendingInterest->callTimeout();
-        }
-      else
-        ++i;
-    }
-
-  if (!m_pendingInterestTable.empty()) {
-    m_pitTimeoutCheckTimerActive = true;
-
-    m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
-    m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
-  }
-  else {
-    m_pitTimeoutCheckTimerActive = false;
-
-    if (m_registeredPrefixTable.empty()) {
-      m_transport->pause();
-      if (!m_ioServiceWork) {
-        m_processEventsTimeoutTimer->cancel();
-      }
-    }
-  }
-}
-
 
 void
 Face::onReceiveElement(const Block& blockFromDaemon)
@@ -578,7 +385,7 @@
       if (&block != &blockFromDaemon)
         interest->getLocalControlHeader().wireDecode(blockFromDaemon);
 
-      processInterestFilters(*interest);
+      m_impl->processInterestFilters(*interest);
     }
   else if (block.type() == Tlv::Data)
     {
@@ -587,54 +394,15 @@
       if (&block != &blockFromDaemon)
         data->getLocalControlHeader().wireDecode(blockFromDaemon);
 
-      satisfyPendingInterests(*data);
+      m_impl->satisfyPendingInterests(*data);
 
-      if (m_pendingInterestTable.empty()) {
-        m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
+      if (m_impl->m_pendingInterestTable.empty()) {
+        m_impl->m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
       }
     }
   // ignore any other type
 }
 
-void
-Face::satisfyPendingInterests(Data& data)
-{
-  for (PendingInterestTable::iterator i = m_pendingInterestTable.begin ();
-       i != m_pendingInterestTable.end();
-       )
-    {
-      if ((*i)->getInterest()->matchesData(data))
-        {
-          // Copy pointers to the objects and remove the PIT entry before calling the callback.
-          OnData onData = (*i)->getOnData();
-          shared_ptr<const Interest> interest = (*i)->getInterest();
 
-          PendingInterestTable::iterator next = i;
-          ++next;
-          m_pendingInterestTable.erase(i);
-          i = next;
-
-          if (static_cast<bool>(onData)) {
-            onData(*interest, data);
-          }
-        }
-      else
-        ++i;
-    }
-}
-
-void
-Face::processInterestFilters(Interest& interest)
-{
-  for (InterestFilterTable::iterator i = m_interestFilterTable.begin();
-       i != m_interestFilterTable.end();
-       ++i)
-    {
-      if ((*i)->doesMatch(interest.getName()))
-        {
-          (**i)(interest);
-        }
-    }
-}
 
 } // namespace ndn
diff --git a/src/face.hpp b/src/face.hpp
index 18f40e6..139ff28 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -16,20 +16,27 @@
 #define NDN_FACE_HPP
 
 #include "common.hpp"
+
+#include "name.hpp"
 #include "interest.hpp"
+#include "interest-filter.hpp"
 #include "data.hpp"
 #include "security/identity-certificate.hpp"
 
-#include "transport/transport.hpp"
-#include "transport/unix-transport.hpp"
-#include "transport/tcp-transport.hpp"
-
-#include "util/scheduler.hpp"
-#include "detail/registered-prefix.hpp"
-#include "detail/pending-interest.hpp"
+namespace boost {
+namespace asio {
+class io_service;
+}
+}
 
 namespace ndn {
 
+class Transport;
+
+class PendingInterestId;
+class RegisteredPrefixId;
+class InterestFilterId;
+
 namespace nfd {
 class Controller;
 }
@@ -167,9 +174,6 @@
   Face(const shared_ptr<Transport>& transport,
        boost::asio::io_service& ioService);
 
-
-  ~Face();
-
   /**
    * @brief Express Interest
    *
@@ -457,7 +461,6 @@
   }
 
 private:
-
   /**
    * @throws Face::Error on unsupported protocol
    */
@@ -475,36 +478,6 @@
   {
   };
 
-  typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
-  typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
-  typedef std::list<shared_ptr<RegisteredPrefix> > RegisteredPrefixTable;
-
-  void
-  asyncExpressInterest(const shared_ptr<const Interest>& interest,
-                       const OnData& onData, const OnTimeout& onTimeout);
-
-  void
-  asyncRemovePendingInterest(const PendingInterestId* pendingInterestId);
-
-  void
-  afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
-                        const RegisterPrefixSuccessCallback& onSuccess);
-
-  void
-  asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord);
-
-  void
-  asyncUnsetInterestFilter(const InterestFilterId* interestFilterId);
-
-  void
-  asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
-                        const UnregisterPrefixSuccessCallback& onSuccess,
-                        const UnregisterPrefixFailureCallback& onFailure);
-
-  void
-  finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
-                           const UnregisterPrefixSuccessCallback& onSuccess);
-
   void
   onReceiveElement(const Block& wire);
 
@@ -514,40 +487,16 @@
   static void
   fireProcessEventsTimeout(const boost::system::error_code& error);
 
-  void
-  satisfyPendingInterests(Data& data);
-
-  void
-  processInterestFilters(Interest& interest);
-
-  void
-  checkPitExpire();
-
-  template<class SignatureGenerator>
-  const RegisteredPrefixId*
-  registerPrefixImpl(const Name& prefix,
-                     const shared_ptr<InterestFilterRecord>& filter,
-                     const RegisterPrefixSuccessCallback& onSuccess,
-                     const RegisterPrefixFailureCallback& onFailure,
-                     const SignatureGenerator& signatureGenerator);
-
 private:
   shared_ptr<boost::asio::io_service> m_ioService;
-  shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
-  shared_ptr<monotonic_deadline_timer> m_pitTimeoutCheckTimer;
-  bool m_pitTimeoutCheckTimerActive;
-  shared_ptr<monotonic_deadline_timer> m_processEventsTimeoutTimer;
 
   shared_ptr<Transport> m_transport;
 
-  PendingInterestTable m_pendingInterestTable;
-  InterestFilterTable m_interestFilterTable;
-  RegisteredPrefixTable m_registeredPrefixTable;
-
-  nfd::Controller* m_nfdController;
+  shared_ptr<nfd::Controller> m_nfdController;
   bool m_isDirectNfdFibManagementRequested;
 
-  ConfigFile m_config;
+  class Impl;
+  shared_ptr<Impl> m_impl;
 };
 
 inline bool
diff --git a/src/interest-filter.cpp b/src/interest-filter.cpp
new file mode 100644
index 0000000..1f4f3fb
--- /dev/null
+++ b/src/interest-filter.cpp
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#include "interest-filter.hpp"
+
+#include "util/regex/regex-pattern-list-matcher.hpp"
+
+namespace ndn {
+
+InterestFilter::InterestFilter(const Name& prefix, const std::string& regexFilter)
+  : m_prefix(prefix)
+  , m_regexFilter(ndn::make_shared<RegexPatternListMatcher>(regexFilter,
+                                                            shared_ptr<RegexBackrefManager>()))
+{
+}
+
+bool
+InterestFilter::doesMatch(const Name& name) const
+{
+  if (name.size() < m_prefix.size())
+    return false;
+
+  if (hasRegexFilter()) {
+    // perform prefix match and regular expression match for the remaining components
+    bool isMatch = m_prefix.isPrefixOf(name);
+
+    if (!isMatch)
+      return false;
+
+    return m_regexFilter->match(name, m_prefix.size(), name.size() - m_prefix.size());
+  }
+  else {
+    // perform just prefix match
+
+    return m_prefix.isPrefixOf(name);
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const InterestFilter& filter)
+{
+  os << filter.getPrefix();
+  if (filter.hasRegexFilter()) {
+    os << "?regex=" << filter.getRegexFilter();
+  }
+  return os;
+}
+
+} // namespace ndn
diff --git a/src/interest-filter.hpp b/src/interest-filter.hpp
index 4cb77af..3833e59 100644
--- a/src/interest-filter.hpp
+++ b/src/interest-filter.hpp
@@ -13,11 +13,12 @@
 #ifndef NDN_INTEREST_FILTER_HPP
 #define NDN_INTEREST_FILTER_HPP
 
-#include "util/regex/regex-pattern-list-matcher.hpp"
 #include "name.hpp"
 
 namespace ndn {
 
+class RegexPatternListMatcher;
+
 class InterestFilter
 {
 public:
@@ -119,6 +120,10 @@
   shared_ptr<RegexPatternListMatcher> m_regexFilter;
 };
 
+std::ostream&
+operator<<(std::ostream& os, const InterestFilter& filter);
+
+
 inline
 InterestFilter::InterestFilter(const Name& prefix)
   : m_prefix(prefix)
@@ -137,45 +142,6 @@
 {
 }
 
-inline
-InterestFilter::InterestFilter(const Name& prefix, const std::string& regexFilter)
-  : m_prefix(prefix)
-  , m_regexFilter(new RegexPatternListMatcher(regexFilter, shared_ptr<RegexBackrefManager>()))
-{
-}
-
-inline bool
-InterestFilter::doesMatch(const Name& name) const
-{
-  if (name.size() < m_prefix.size())
-    return false;
-
-  if (hasRegexFilter()) {
-    // perform prefix match and regular expression match for the remaining components
-    bool isMatch = m_prefix.isPrefixOf(name);
-
-    if (!isMatch)
-      return false;
-
-    return m_regexFilter->match(name, m_prefix.size(), name.size() - m_prefix.size());
-  }
-  else {
-    // perform just prefix match
-
-    return m_prefix.isPrefixOf(name);
-  }
-}
-
-inline std::ostream&
-operator<<(std::ostream& os, const InterestFilter& filter)
-{
-  os << filter.getPrefix();
-  if (filter.hasRegexFilter()) {
-    os << "?regex=" << filter.getRegexFilter();
-  }
-  return os;
-}
-
 } // namespace ndn
 
 #endif // NDN_INTEREST_FILTER_HPP
diff --git a/src/interest.hpp b/src/interest.hpp
index ea007bd..c433ae8 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -16,6 +16,7 @@
 #define NDN_INTEREST_HPP
 
 #include "common.hpp"
+
 #include "name.hpp"
 #include "selectors.hpp"
 #include "interest-filter.hpp"
@@ -28,7 +29,7 @@
 const time::seconds DEFAULT_INTEREST_LIFETIME = time::seconds(4);
 
 /**
- * An Interest holds a Name and other fields for an interest.
+ * An Interest holds a Name and other fields for an Interest
  */
 class Interest : public enable_shared_from_this<Interest>
 {
diff --git a/src/management/nfd-control-response.hpp b/src/management/nfd-control-response.hpp
index 0a97504..c239804 100644
--- a/src/management/nfd-control-response.hpp
+++ b/src/management/nfd-control-response.hpp
@@ -14,6 +14,7 @@
 #define NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
 
 #include "../encoding/block.hpp"
+#include "../encoding/block-helpers.hpp"
 #include "../encoding/tlv-nfd.hpp"
 
 namespace ndn {
diff --git a/src/management/nfd-face-event-notification.hpp b/src/management/nfd-face-event-notification.hpp
index 307c0d9..6432d30 100644
--- a/src/management/nfd-face-event-notification.hpp
+++ b/src/management/nfd-face-event-notification.hpp
@@ -18,6 +18,7 @@
 
 #include "../encoding/tlv-nfd.hpp"
 #include "../encoding/encoding-buffer.hpp"
+#include "../encoding/block-helpers.hpp"
 
 namespace ndn {
 namespace nfd {
diff --git a/src/management/nfd-face-status.hpp b/src/management/nfd-face-status.hpp
index b3cf120..02e9b9a 100644
--- a/src/management/nfd-face-status.hpp
+++ b/src/management/nfd-face-status.hpp
@@ -18,6 +18,7 @@
 
 #include "../encoding/tlv-nfd.hpp"
 #include "../encoding/encoding-buffer.hpp"
+#include "../encoding/block-helpers.hpp"
 
 namespace ndn {
 namespace nfd {
diff --git a/src/management/nfd-fib-entry.hpp b/src/management/nfd-fib-entry.hpp
index 1ed98cf..eaa372c 100644
--- a/src/management/nfd-fib-entry.hpp
+++ b/src/management/nfd-fib-entry.hpp
@@ -18,6 +18,8 @@
 #include "../encoding/tlv-nfd.hpp"
 #include "../name.hpp"
 
+#include <list>
+
 namespace ndn {
 namespace nfd {
 
diff --git a/src/management/nfd-forwarder-status.hpp b/src/management/nfd-forwarder-status.hpp
index ce34d36..43e6150 100644
--- a/src/management/nfd-forwarder-status.hpp
+++ b/src/management/nfd-forwarder-status.hpp
@@ -15,6 +15,9 @@
 
 #include "../encoding/tlv-nfd.hpp"
 #include "../encoding/encoding-buffer.hpp"
+#include "../encoding/block-helpers.hpp"
+
+#include "../util/time.hpp"
 
 namespace ndn {
 namespace nfd {
diff --git a/src/name-component.hpp b/src/name-component.hpp
index b83dd40..d58e4d6 100644
--- a/src/name-component.hpp
+++ b/src/name-component.hpp
@@ -19,6 +19,7 @@
 
 #include "common.hpp"
 #include "encoding/block.hpp"
+#include "encoding/block-helpers.hpp"
 #include "encoding/encoding-buffer.hpp"
 #include "util/string-helper.hpp"
 
diff --git a/src/name.hpp b/src/name.hpp
index 1abffbc..11a438d 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -19,6 +19,7 @@
 
 #include "common.hpp"
 #include "name-component.hpp"
+#include "util/time.hpp"
 
 #include "encoding/block.hpp"
 #include "encoding/encoding-buffer.hpp"
diff --git a/src/security/certificate.cpp b/src/security/certificate.cpp
index 690ec31..69597fc 100644
--- a/src/security/certificate.cpp
+++ b/src/security/certificate.cpp
@@ -20,6 +20,7 @@
 #include "../util/time.hpp"
 #include "cryptopp.hpp"
 #include "../encoding/cryptopp/asn_ext.hpp"
+#include "../encoding/buffer-stream.hpp"
 
 using namespace std;
 
diff --git a/src/security/certificate.hpp b/src/security/certificate.hpp
index 695faf1..4663ea9 100644
--- a/src/security/certificate.hpp
+++ b/src/security/certificate.hpp
@@ -165,9 +165,6 @@
     return m_key;
   }
 
-  // virtual Name
-  // getPublicKeyName() const = 0;
-
   /**
    * Check if the certificate is valid.
    * @return True if the current time is earlier than notBefore.
diff --git a/src/security/conf/checker.hpp b/src/security/conf/checker.hpp
index 1ebcf0d..67ab3b1 100644
--- a/src/security/conf/checker.hpp
+++ b/src/security/conf/checker.hpp
@@ -15,11 +15,14 @@
 #ifndef NDN_SECURITY_CONF_CHECKER_HPP
 #define NDN_SECURITY_CONF_CHECKER_HPP
 
+#include "common.hpp"
+
 #include "key-locator-checker.hpp"
 #include "../../util/io.hpp"
-#include <boost/algorithm/string.hpp>
 
-#include "common.hpp"
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
 
 namespace ndn {
 namespace security {
diff --git a/src/security/public-key.cpp b/src/security/public-key.cpp
index 17f204b..9977950 100644
--- a/src/security/public-key.cpp
+++ b/src/security/public-key.cpp
@@ -13,8 +13,9 @@
  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
  */
 
-#include "common.hpp"
 #include "public-key.hpp"
+
+#include "../encoding/oid.hpp"
 #include "cryptopp.hpp"
 
 using namespace std;
diff --git a/src/security/public-key.hpp b/src/security/public-key.hpp
index e939978..b8222c2 100644
--- a/src/security/public-key.hpp
+++ b/src/security/public-key.hpp
@@ -18,10 +18,14 @@
 #define NDN_SECURITY_PUBLIC_KEY_HPP
 
 #include "../common.hpp"
-#include "../encoding/oid.hpp"
+
 #include "../encoding/buffer.hpp"
 #include "security-common.hpp"
 
+namespace CryptoPP {
+class BufferedTransformation;
+}
+
 namespace ndn {
 
 class PublicKey
diff --git a/src/security/sec-public-info-memory.hpp b/src/security/sec-public-info-memory.hpp
index 0c6b70f..20ccde6 100644
--- a/src/security/sec-public-info-memory.hpp
+++ b/src/security/sec-public-info-memory.hpp
@@ -18,6 +18,8 @@
 #include "../common.hpp"
 #include "sec-public-info.hpp"
 
+#include <map>
+
 namespace ndn {
 
 /**
diff --git a/src/security/sec-tpm-file.cpp b/src/security/sec-tpm-file.cpp
index c49fcd7..096fe9d 100644
--- a/src/security/sec-tpm-file.cpp
+++ b/src/security/sec-tpm-file.cpp
@@ -17,6 +17,7 @@
 #include "common.hpp"
 
 #include "sec-tpm-file.hpp"
+#include "../encoding/buffer-stream.hpp"
 
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
diff --git a/src/security/sec-tpm-memory.hpp b/src/security/sec-tpm-memory.hpp
index e0dd34c..45e3bd3 100644
--- a/src/security/sec-tpm-memory.hpp
+++ b/src/security/sec-tpm-memory.hpp
@@ -18,6 +18,8 @@
 #include "../common.hpp"
 #include "sec-tpm.hpp"
 
+#include <map>
+
 struct rsa_st;
 
 namespace ndn {
diff --git a/src/security/sec-tpm-osx.cpp b/src/security/sec-tpm-osx.cpp
index 69c3deb..cda3633 100644
--- a/src/security/sec-tpm-osx.cpp
+++ b/src/security/sec-tpm-osx.cpp
@@ -16,6 +16,8 @@
 
 #include "sec-tpm-osx.hpp"
 #include "public-key.hpp"
+#include "../encoding/oid.hpp"
+#include "../encoding/buffer-stream.hpp"
 #include "cryptopp.hpp"
 
 #include <pwd.h>
diff --git a/src/security/sec-tpm.cpp b/src/security/sec-tpm.cpp
index e4e1315..b038688 100644
--- a/src/security/sec-tpm.cpp
+++ b/src/security/sec-tpm.cpp
@@ -14,6 +14,8 @@
 
 #include "sec-tpm.hpp"
 
+#include "../encoding/oid.hpp"
+#include "../encoding/buffer-stream.hpp"
 #include "cryptopp.hpp"
 
 using namespace std;
diff --git a/src/transport/stream-transport.hpp b/src/transport/stream-transport.hpp
index c9d61b7..bbf01b9 100644
--- a/src/transport/stream-transport.hpp
+++ b/src/transport/stream-transport.hpp
@@ -15,6 +15,8 @@
 
 #include "../common.hpp"
 
+#include <list>
+
 namespace ndn {
 
 const size_t MAX_LENGTH = 9000;
diff --git a/src/transport/transport.hpp b/src/transport/transport.hpp
index 8b16639..e383f4e 100644
--- a/src/transport/transport.hpp
+++ b/src/transport/transport.hpp
@@ -16,6 +16,8 @@
 #include "../common.hpp"
 #include "../encoding/block.hpp"
 
+#include <boost/asio.hpp>
+
 namespace ndn {
 
 class Transport
diff --git a/src/util/command-interest-validator.hpp b/src/util/command-interest-validator.hpp
index 6bd3250..2dcc947 100644
--- a/src/util/command-interest-validator.hpp
+++ b/src/util/command-interest-validator.hpp
@@ -17,6 +17,8 @@
 #include "../security/identity-certificate.hpp"
 #include "../security/sec-rule-specific.hpp"
 
+#include <list>
+
 namespace ndn {
 
 class CommandInterestValidator : public Validator
diff --git a/src/util/config-file.hpp b/src/util/config-file.hpp
index 8d49d26..880657a 100644
--- a/src/util/config-file.hpp
+++ b/src/util/config-file.hpp
@@ -15,6 +15,8 @@
 
 #include "../common.hpp"
 
+#include <fstream>
+
 #include <boost/property_tree/ptree.hpp>
 #include <boost/filesystem.hpp>
 
diff --git a/src/util/crypto.cpp b/src/util/crypto.cpp
index 29cbe9d..6e559dd 100644
--- a/src/util/crypto.cpp
+++ b/src/util/crypto.cpp
@@ -13,6 +13,7 @@
 #include "../common.hpp"
 
 #include "crypto.hpp"
+#include "../encoding/buffer-stream.hpp"
 #include "../security/cryptopp.hpp"
 
 namespace ndn {
diff --git a/src/util/io.hpp b/src/util/io.hpp
index 6ca861f..c61dccf 100644
--- a/src/util/io.hpp
+++ b/src/util/io.hpp
@@ -16,6 +16,7 @@
 #include "../common.hpp"
 
 #include "../encoding/block.hpp"
+#include "../encoding/buffer-stream.hpp"
 
 #include <string>
 #include <iostream>
diff --git a/src/util/regex/regex-backref-manager.hpp b/src/util/regex/regex-backref-manager.hpp
index 9ca95ea..a87640c 100644
--- a/src/util/regex/regex-backref-manager.hpp
+++ b/src/util/regex/regex-backref-manager.hpp
@@ -17,6 +17,8 @@
 
 #include "../../common.hpp"
 
+#include <vector>
+
 namespace ndn {
 
 class RegexMatcher;
diff --git a/src/util/regex/regex-component-set-matcher.hpp b/src/util/regex/regex-component-set-matcher.hpp
index 8e0e908..6bccffe 100644
--- a/src/util/regex/regex-component-set-matcher.hpp
+++ b/src/util/regex/regex-component-set-matcher.hpp
@@ -20,6 +20,8 @@
 #include "regex-matcher.hpp"
 #include "regex-component-matcher.hpp"
 
+#include <set>
+
 namespace ndn {
 
 class RegexComponentSetMatcher : public RegexMatcher
diff --git a/src/util/regex/regex-top-matcher.cpp b/src/util/regex/regex-top-matcher.cpp
index e2317c7..3c95959 100644
--- a/src/util/regex/regex-top-matcher.cpp
+++ b/src/util/regex/regex-top-matcher.cpp
@@ -17,6 +17,8 @@
 #include "regex-backref-manager.hpp"
 #include "regex-pattern-list-matcher.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 namespace ndn {
 
 RegexTopMatcher::RegexTopMatcher(const std::string& expr, const std::string& expand)
diff --git a/src/util/scheduler.hpp b/src/util/scheduler.hpp
index 89892e1..b2a7831 100644
--- a/src/util/scheduler.hpp
+++ b/src/util/scheduler.hpp
@@ -16,6 +16,8 @@
 #include "../common.hpp"
 #include "monotonic_deadline_timer.hpp"
 
+#include <set>
+
 namespace ndn {
 
 struct EventIdImpl; ///< \brief Private storage of information about the event
diff --git a/src/util/time.cpp b/src/util/time.cpp
new file mode 100644
index 0000000..3dacbc6
--- /dev/null
+++ b/src/util/time.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#include "time.hpp"
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+namespace ndn {
+namespace time {
+
+std::string
+toIsoString(const system_clock::TimePoint& timePoint)
+{
+  namespace bpt = boost::posix_time;
+  bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
+
+  uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
+  if (micro > 0)
+    {
+      ptime += bpt::microseconds(micro);
+      return bpt::to_iso_string(ptime);
+    }
+  else
+    return bpt::to_iso_string(ptime);
+}
+
+
+system_clock::TimePoint
+fromIsoString(const std::string& isoString)
+{
+  namespace bpt = boost::posix_time;
+  static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
+
+  bpt::ptime ptime = bpt::from_iso_string(isoString);
+
+  system_clock::TimePoint point =
+    system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
+  point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
+  return point;
+}
+
+
+std::string
+toString(const system_clock::TimePoint& timePoint,
+         const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
+         const std::locale& locale/* = std::locale("C")*/)
+{
+  namespace bpt = boost::posix_time;
+  bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
+
+  uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
+  ptime += bpt::microseconds(micro);
+
+  bpt::time_facet* facet = new bpt::time_facet(format.c_str());
+  std::ostringstream formattedTimePoint;
+  formattedTimePoint.imbue(std::locale(locale, facet));
+  formattedTimePoint << ptime;
+
+  return formattedTimePoint.str();
+}
+
+
+system_clock::TimePoint
+fromString(const std::string& formattedTimePoint,
+           const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
+           const std::locale& locale/* = std::locale("C")*/)
+{
+  namespace bpt = boost::posix_time;
+  static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
+
+  bpt::time_input_facet* facet = new bpt::time_input_facet(format);
+  std::istringstream is(formattedTimePoint);
+
+  is.imbue(std::locale(locale, facet));
+  bpt::ptime ptime;
+  is >> ptime;
+
+  system_clock::TimePoint point =
+    system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
+  point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
+  return point;
+}
+
+} // namespace time
+} // namespace ndn
diff --git a/src/util/time.hpp b/src/util/time.hpp
index 3bc4e4f..98d27e8 100644
--- a/src/util/time.hpp
+++ b/src/util/time.hpp
@@ -15,7 +15,6 @@
 
 #include "../common.hpp"
 #include <boost/chrono.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
 
 namespace ndn {
 namespace time {
@@ -138,21 +137,8 @@
  *   - with fractional milliseconds: 20020131T100001,123
  *   - without fractional seconds:   20020131T100001
  */
-inline std::string
-toIsoString(const system_clock::TimePoint& timePoint)
-{
-  namespace bpt = boost::posix_time;
-  bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
-
-  uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
-  if (micro > 0)
-    {
-      ptime += bpt::microseconds(micro);
-      return bpt::to_iso_string(ptime);
-    }
-  else
-    return bpt::to_iso_string(ptime);
-}
+std::string
+toIsoString(const system_clock::TimePoint& timePoint);
 
 /**
  * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
@@ -166,19 +152,8 @@
  *   - without fractional seconds:   20020131T100001
  *
  */
-inline system_clock::TimePoint
-fromIsoString(const std::string& isoString)
-{
-  namespace bpt = boost::posix_time;
-  static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
-
-  bpt::ptime ptime = bpt::from_iso_string(isoString);
-
-  system_clock::TimePoint point =
-    system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
-  point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
-  return point;
-}
+system_clock::TimePoint
+fromIsoString(const std::string& isoString);
 
 /**
  * \brief Convert time point to string with specified format
@@ -193,24 +168,10 @@
  * \sa http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.format_flags
  *     described possible formatting flags
  **/
-inline std::string
+std::string
 toString(const system_clock::TimePoint& timePoint,
          const std::string& format = "%Y-%m-%d %H:%M:%S",
-         const std::locale& locale = std::locale("C"))
-{
-  namespace bpt = boost::posix_time;
-  bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
-
-  uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
-  ptime += bpt::microseconds(micro);
-
-  bpt::time_facet* facet = new bpt::time_facet(format.c_str());
-  std::ostringstream formattedTimePoint;
-  formattedTimePoint.imbue(std::locale(locale, facet));
-  formattedTimePoint << ptime;
-
-  return formattedTimePoint.str();
-}
+         const std::locale& locale = std::locale("C"));
 
 /**
  * \brief Convert from string of specified format into time point
@@ -225,26 +186,10 @@
  * \sa http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.format_flags
  *     described possible formatting flags
  */
-inline system_clock::TimePoint
+system_clock::TimePoint
 fromString(const std::string& formattedTimePoint,
            const std::string& format = "%Y-%m-%d %H:%M:%S",
-           const std::locale& locale = std::locale("C"))
-{
-  namespace bpt = boost::posix_time;
-  static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
-
-  bpt::time_input_facet* facet = new bpt::time_input_facet(format);
-  std::istringstream is(formattedTimePoint);
-
-  is.imbue(std::locale(locale, facet));
-  bpt::ptime ptime;
-  is >> ptime;
-
-  system_clock::TimePoint point =
-    system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
-  point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
-  return point;
-}
+           const std::locale& locale = std::locale("C"));
 
 } // namespace time
 } // namespace ndn
diff --git a/tests-integrated/security/test-validator-config.cpp b/tests-integrated/security/test-validator-config.cpp
index e122523..def5ae3 100644
--- a/tests-integrated/security/test-validator-config.cpp
+++ b/tests-integrated/security/test-validator-config.cpp
@@ -16,6 +16,9 @@
 
 #include "security/key-chain.hpp"
 #include "util/io.hpp"
+#include "util/scheduler.hpp"
+
+#include <boost/asio.hpp>
 
 #include "boost-test.hpp"
 
diff --git a/tests/management/test-nfd-controller.cpp b/tests/management/test-nfd-controller.cpp
index 609c65f..c672fcb 100644
--- a/tests/management/test-nfd-controller.cpp
+++ b/tests/management/test-nfd-controller.cpp
@@ -15,6 +15,8 @@
 
 #include "../transport/dummy-face.hpp"
 
+#include <boost/tuple/tuple.hpp>
+
 #include "boost-test.hpp"
 
 namespace ndn {
diff --git a/tests/security/test-sec-tpm-file.cpp b/tests/security/test-sec-tpm-file.cpp
index 05f1afc..191764e 100644
--- a/tests/security/test-sec-tpm-file.cpp
+++ b/tests/security/test-sec-tpm-file.cpp
@@ -16,6 +16,8 @@
 
 #include "util/time.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 #include "boost-test.hpp"
 
 using namespace std;
diff --git a/tests/security/test-sec-tpm-osx.cpp b/tests/security/test-sec-tpm-osx.cpp
index f8df5e8..887b19c 100644
--- a/tests/security/test-sec-tpm-osx.cpp
+++ b/tests/security/test-sec-tpm-osx.cpp
@@ -15,6 +15,8 @@
 
 #include "util/time.hpp"
 
+#include <boost/lexical_cast.hpp>
+
 #include "boost-test.hpp"
 
 using namespace std;
diff --git a/tests/test-block.cpp b/tests/test-block.cpp
index bed9958..a4183f9 100644
--- a/tests/test-block.cpp
+++ b/tests/test-block.cpp
@@ -11,6 +11,7 @@
  */
 
 #include "encoding/encoding-buffer.hpp"
+#include "encoding/buffer-stream.hpp"
 
 #include "boost-test.hpp"
 
diff --git a/tests/test-data.cpp b/tests/test-data.cpp
index 2e022a1..bfb2cd4 100644
--- a/tests/test-data.cpp
+++ b/tests/test-data.cpp
@@ -13,6 +13,7 @@
 #include "data.hpp"
 #include "security/key-chain.hpp"
 #include "security/cryptopp.hpp"
+#include "encoding/buffer-stream.hpp"
 
 #include "boost-test.hpp"
 
diff --git a/tests/test-interest.cpp b/tests/test-interest.cpp
index 10f88d6..54efad4 100644
--- a/tests/test-interest.cpp
+++ b/tests/test-interest.cpp
@@ -14,6 +14,7 @@
 #include "data.hpp"
 #include "security/signature-sha256-with-rsa.hpp"
 #include "security/signature-sha256.hpp"
+#include "encoding/buffer-stream.hpp"
 
 #include "boost-test.hpp"
 
diff --git a/tests/transport/dummy-face.hpp b/tests/transport/dummy-face.hpp
index 58b4e81..735702e 100644
--- a/tests/transport/dummy-face.hpp
+++ b/tests/transport/dummy-face.hpp
@@ -14,6 +14,7 @@
 #define NDN_TESTS_TRANSPORT_DUMMY_FACE_HPP
 
 #include "face.hpp"
+#include "transport/transport.hpp"
 
 namespace ndn {