api: Major API change.  OnInterest/OnData callbacks now use just references, not shared pointers

If shared pointer is necessary, it can be obtained using
.shared_from_this() on Interest or Data object.

This commit also corrects all internal uses of expressInterest/setIntersetFilter.

Change-Id: I20207a5789fd189902f2c6e3827260b6b27a2514
diff --git a/examples/consumer-with-timer.cpp b/examples/consumer-with-timer.cpp
index b8415d0..9af81da 100644
--- a/examples/consumer-with-timer.cpp
+++ b/examples/consumer-with-timer.cpp
@@ -10,24 +10,17 @@
 #include "face.hpp"
 #include "util/scheduler.hpp"
 
-#include <stdexcept>
-
-#if NDN_CPP_HAVE_CXX11
-// In the std library, the placeholders are in a different namespace than boost.
-using namespace ndn::func_lib::placeholders;
-#endif
-
 void
 onData(ndn::Face &face,
-       const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest, const ndn::ptr_lib::shared_ptr<ndn::Data> &data)
+       const ndn::Interest& interest, ndn::Data& data)
 {
-  std::cout << "I: " << interest->toUri() << std::endl;
-  std::cout << "D: " << data->getName().toUri() << std::endl;
+  std::cout << "I: " << interest.toUri() << std::endl;
+  std::cout << "D: " << data.getName().toUri() << std::endl;
 }
 
 void
 onTimeout(ndn::Face &face,
-          const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest)
+          const ndn::Interest& interest)
 {
   std::cout << "Timeout" << std::endl;
 }
diff --git a/examples/consumer.cpp b/examples/consumer.cpp
index bba9a7f..4dd1036 100644
--- a/examples/consumer.cpp
+++ b/examples/consumer.cpp
@@ -9,30 +9,23 @@
 // #include <ndn-cpp-dev/face.hpp>
 #include "face.hpp"
 
-#include <stdexcept>
-
-#if NDN_CPP_HAVE_CXX11
-// In the std library, the placeholders are in a different namespace than boost.
-using namespace ndn::func_lib::placeholders;
-#endif
-
 void
 onData(ndn::Face &face,
-       const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest, const ndn::ptr_lib::shared_ptr<ndn::Data> &data)
+       const ndn::Interest& interest, ndn::Data& data)
 {
-  std::cout << "I: " << interest->toUri() << std::endl;
-  std::cout << "D: " << data->getName().toUri() << std::endl;
+  std::cout << "I: " << interest.toUri() << std::endl;
+  std::cout << "D: " << data.getName().toUri() << std::endl;
 }
 
 void
 onTimeout(ndn::Face &face,
-          const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest)
+          const ndn::Interest& interest)
 {
   std::cout << "Timeout" << std::endl;
 }
 
 void
-BlockPrinter(const ndn::Block &block, const std::string &indent="")
+BlockPrinter(const ndn::Block& block, const std::string& indent="")
 {
   std::cout << indent << block.type() << " (" << block.value_size() << ") [[";
   std::cout.write(reinterpret_cast<const char *>(block.value()), block.value_size());
@@ -56,8 +49,8 @@
 
     ndn::Face face;
     face.expressInterest(i,
-                          ndn::func_lib::bind(onData, boost::ref(face), _1, _2),
-                          ndn::func_lib::bind(onTimeout, boost::ref(face), _1));
+                          ndn::bind(onData, boost::ref(face), _1, _2),
+                          ndn::bind(onTimeout, boost::ref(face), _1));
 
     // processEvents will block until the requested data received or timeout occurs
     face.processEvents();
diff --git a/examples/producer.cpp b/examples/producer.cpp
index 53ccdc0..d081cb3 100644
--- a/examples/producer.cpp
+++ b/examples/producer.cpp
@@ -12,33 +12,21 @@
 #include "face.hpp"
 #include "security/key-chain.hpp"
 
-#if NDN_CPP_HAVE_CXX11
-// In the std library, the placeholders are in a different namespace than boost.
-using namespace ndn::func_lib::placeholders;
-#endif
-
 using namespace ndn;
 
 class Producer
 {
 public:
-  ////////////////////////////////////////////////////////////////////////////////////////
-  // CREATE TEST KEYCHAIN (THIS CODE IS ONLY FOR DEBUGGING, NOT TO BE USED IN REAL APPS //
-  ////////////////////////////////////////////////////////////////////////////////////////
   Producer()
-    : keyChain_()
   {
   }
-  ////////////////////////////////////////////////////////////////////////////////////////
-  ////////////////////////////////////////////////////////////////////////////////////////
-  ////////////////////////////////////////////////////////////////////////////////////////
 
   void
-  onInterest(const ptr_lib::shared_ptr<const Name> &name, const ptr_lib::shared_ptr<const Interest> &interest)
+  onInterest(const Name& name, const Interest& interest)
   {
-    std::cout << "<< I: " << *interest << std::endl;
+    std::cout << "<< I: " << interest << std::endl;
     
-    ndn::Data data(ndn::Name(interest->getName()).append("testApp").appendVersion());
+    ndn::Data data(ndn::Name(interest.getName()).append("testApp").appendVersion());
     data.setFreshnessPeriod(1000); // 10 sec
 
     data.setContent((const uint8_t*)"HELLO KITTY", sizeof("HELLO KITTY"));
diff --git a/src/data.hpp b/src/data.hpp
index dc6d9f0..d6aba80 100644
--- a/src/data.hpp
+++ b/src/data.hpp
@@ -18,7 +18,8 @@
 
 namespace ndn {
   
-class Data {
+class Data : public enable_shared_from_this<Data>
+{
 public:
   struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
   
diff --git a/src/detail/pending-interest.hpp b/src/detail/pending-interest.hpp
index 85acb23..b53dc1f 100644
--- a/src/detail/pending-interest.hpp
+++ b/src/detail/pending-interest.hpp
@@ -16,8 +16,8 @@
 
 class PendingInterest {
 public:
-  typedef function<void(const shared_ptr<const Interest>&, const shared_ptr<Data>&)> OnData;
-  typedef function<void(const shared_ptr<const Interest>&)> OnTimeout;
+  typedef function<void(const Interest&, Data&)> OnData;
+  typedef function<void(const Interest&)> OnTimeout;
 
   /**
    * Create a new PitEntry and set the timeoutTime_ based on the current time and the interest lifetime.
@@ -71,7 +71,7 @@
   callTimeout()
   {
     if (onTimeout_) {
-      onTimeout_(interest_);
+      onTimeout_(*interest_);
     }
   }
     
diff --git a/src/detail/registered-prefix.hpp b/src/detail/registered-prefix.hpp
index 5cb5523..aeb6c66 100644
--- a/src/detail/registered-prefix.hpp
+++ b/src/detail/registered-prefix.hpp
@@ -15,7 +15,7 @@
 class RegisteredPrefix {
 public:
   typedef function<void
-  (const shared_ptr<const Name>&, const shared_ptr<const Interest>&)> OnInterest;
+  (const Name&, const Interest&)> OnInterest;
 
   /**
    * Create a new PrefixEntry.
diff --git a/src/face.cpp b/src/face.cpp
index 9385358..7e62fe4 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -5,34 +5,342 @@
  * See COPYING for copyright and distribution information.
  */
 
+#include "common.hpp"
+
 #include "face.hpp"
 
-using namespace std;
+#include "security/signature-sha256-with-rsa.hpp"
+
+#include "util/time.hpp"
+#include "util/random.hpp"
+
+#include "management/ndnd-controller.hpp"
+#include "management/nfd-controller.hpp"
 
 namespace ndn {
 
-const PendingInterestId*
-Face::expressInterest
-  (const Name& name, const Interest *interestTemplate, const OnData& onData, const OnTimeout& onTimeout)
+Face::Face(bool nfdMode/* = false*/)
 {
-  if (interestTemplate)
-    return node_.expressInterest(Interest
-      (name,
-       interestTemplate->getMinSuffixComponents(), interestTemplate->getMaxSuffixComponents(),
-       interestTemplate->getExclude(),
-       interestTemplate->getChildSelector(),
-       interestTemplate->getMustBeFresh(),
-       interestTemplate->getScope(),
-       interestTemplate->getInterestLifetime()),
-      onData, onTimeout);
+  construct(shared_ptr<Transport>(new UnixTransport()),
+            make_shared<boost::asio::io_service>(), nfdMode);
+}
+
+Face::Face(const shared_ptr<boost::asio::io_service> &ioService, bool nfdMode/* = false*/)
+{
+  construct(shared_ptr<Transport>(new UnixTransport()),
+            ioService, nfdMode);
+}
+
+Face::Face(const std::string &host, const std::string &port/* = "6363"*/, bool nfdMode/* = false*/)
+{
+  construct(shared_ptr<Transport>(new TcpTransport(host, port)),
+            make_shared<boost::asio::io_service>(), nfdMode);
+}
+
+Face::Face(const shared_ptr<Transport>& transport, bool nfdMode/* = false*/)
+{
+  construct(transport,
+            make_shared<boost::asio::io_service>(), nfdMode);
+}
+
+Face::Face(const shared_ptr<Transport>& transport,
+           const shared_ptr<boost::asio::io_service> &ioService,
+           bool nfdMode/* = false*/)
+{
+  construct(transport, ioService, nfdMode);
+}
+
+void
+Face::construct(const shared_ptr<Transport>& transport,
+                const shared_ptr<boost::asio::io_service> &ioService,
+                bool nfdMode)
+{
+  pitTimeoutCheckTimerActive_ = false;
+  transport_ = transport;
+  ioService_ = ioService;
+
+  pitTimeoutCheckTimer_      = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
+  processEventsTimeoutTimer_ = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
+  
+  if (nfdMode)
+      m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
   else
-    return node_.expressInterest(Interest(name, 4000.0), onData, onTimeout);  
+      m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
+}
+
+
+const PendingInterestId*
+Face::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
+{
+  if (!transport_->isConnected())
+    transport_->connect(*ioService_,
+                        bind(&Face::onReceiveElement, this, _1));
+
+  shared_ptr<const Interest> interestToExpress(new Interest(interest));
+  
+  ioService_->post(bind(&Face::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
+  
+  return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
+}
+
+const PendingInterestId*
+Face::expressInterest(const Name& name,
+                      const Interest &tmpl,
+                      const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
+{
+  return expressInterest(Interest(name,
+                                  tmpl.getMinSuffixComponents(),
+                                  tmpl.getMaxSuffixComponents(),
+                                  tmpl.getExclude(),
+                                  tmpl.getChildSelector(),
+                                  tmpl.getMustBeFresh(),
+                                  tmpl.getScope(),
+                                  tmpl.getInterestLifetime()),
+                         onData, onTimeout);
+}
+
+void
+Face::asyncExpressInterest(const shared_ptr<const Interest> &interest,
+                           const OnData& onData, const OnTimeout& onTimeout)
+{
+  pendingInterestTable_.push_back(shared_ptr<PendingInterest>(new PendingInterest
+                                                              (interest, onData, onTimeout)));
+
+  transport_->send(interest->wireEncode());
+
+  if (!pitTimeoutCheckTimerActive_) {
+    pitTimeoutCheckTimerActive_ = true;
+    pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
+    pitTimeoutCheckTimer_->async_wait(bind(&Face::checkPitExpire, this));
+  }
+}
+    
+void
+Face::put(const Data &data)
+{
+  if (!transport_->isConnected())
+    transport_->connect(*ioService_,
+                        bind(&Face::onReceiveElement, this, _1));
+
+  transport_->send(data.wireEncode());
+}
+
+
+void
+Face::removePendingInterest(const PendingInterestId *pendingInterestId)
+{
+  ioService_->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
+}
+
+
+void
+Face::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
+{
+  pendingInterestTable_.remove_if(MatchPendingInterestId(pendingInterestId));
+}
+
+const RegisteredPrefixId*
+Face::setInterestFilter(const Name& prefix,
+                        const OnInterest& onInterest,
+                        const OnSetInterestFilterFailed& onSetInterestFilterFailed)
+{
+  shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
+
+  m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
+                                     bind(&RegisteredPrefixTable::push_back, &registeredPrefixTable_, prefixToRegister),
+                                     bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
+  
+  return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
+}
+
+void
+Face::unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
+{
+  ioService_->post(bind(&Face::asyncUnsetInterestFilter, this, registeredPrefixId));
+}
+
+void
+Face::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
+{
+  RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
+                                                   MatchRegisteredPrefixId(registeredPrefixId));  
+  if (i != registeredPrefixTable_.end())
+    {
+      m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
+                                           bind(&RegisteredPrefixTable::erase, &registeredPrefixTable_, i),
+                                           Controller::FailCallback());
+    }
+
+  // there cannot be two registered prefixes with the same id. if there are, then something is broken
+}
+
+void 
+Face::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
+{
+  try
+    {
+      if (timeout < 0)
+        {
+          // do not block if timeout is negative, but process pending events
+          ioService_->poll();
+          return;
+        }
+
+      if (timeout > 0)
+        {
+          processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
+          processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
+        }
+      
+      if (keepThread) {
+        // work will ensure that ioService_ is running until work object exists
+        ioServiceWork_ = make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
+      }
+          
+      ioService_->run();
+      ioService_->reset(); // so it is possible to run processEvents again (if necessary)
+    }
+  catch(Face::ProcessEventsTimeout &)
+    {
+      // break
+      ioService_->reset();
+    }
+  catch(const std::exception &)
+    {
+      ioService_->reset();
+      pendingInterestTable_.clear();
+      registeredPrefixTable_.clear();
+      throw;
+    }
 }
 
 void 
 Face::shutdown()
 {
-  node_.shutdown();
+  pendingInterestTable_.clear();
+  registeredPrefixTable_.clear();
+
+  transport_->close();
+  pitTimeoutCheckTimer_->cancel();
+  processEventsTimeoutTimer_->cancel();
+  pitTimeoutCheckTimerActive_ = false;
 }
 
+void
+Face::fireProcessEventsTimeout(const boost::system::error_code& error)
+{
+  if (!error) // can fire for some other reason, e.g., cancelled
+    throw Face::ProcessEventsTimeout();
 }
+
+void
+Face::checkPitExpire()
+{
+  // Check for PIT entry timeouts.  Go backwards through the list so we can erase entries.
+  MillisecondsSince1970 nowMilliseconds = getNowMilliseconds();
+
+  PendingInterestTable::iterator i = pendingInterestTable_.begin();
+  while (i != pendingInterestTable_.end())
+    {
+      if ((*i)->isTimedOut(nowMilliseconds))
+        {
+          // Save the PendingInterest and remove it from the PIT.  Then call the callback.
+          shared_ptr<PendingInterest> pendingInterest = *i;
+
+          i = pendingInterestTable_.erase(i);
+
+          pendingInterest->callTimeout();
+        }
+      else
+        ++i;
+    }
+
+  if (!pendingInterestTable_.empty()) {
+    pitTimeoutCheckTimerActive_ = true;
+    
+    pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
+    pitTimeoutCheckTimer_->async_wait(bind(&Face::checkPitExpire, this));
+  }
+  else {
+    pitTimeoutCheckTimerActive_ = false;
+
+    if (registeredPrefixTable_.empty()) {
+      transport_->close();
+      if (!ioServiceWork_) {
+        processEventsTimeoutTimer_->cancel();
+      }
+    }
+  }
+}
+
+
+void 
+Face::onReceiveElement(const Block &block)
+{
+  if (block.type() == Tlv::Interest)
+    {
+      shared_ptr<Interest> interest(new Interest());
+      interest->wireDecode(block);
+    
+      RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
+      if (entry != registeredPrefixTable_.end()) {
+        (*entry)->getOnInterest()((*entry)->getPrefix(), *interest);
+      }
+    }
+  else if (block.type() == Tlv::Data)
+    {
+      shared_ptr<Data> data(new Data());
+      data->wireDecode(block);
+
+      PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
+      if (entry != pendingInterestTable_.end()) {
+        // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
+        const OnData onData = (*entry)->getOnData();
+        const shared_ptr<const Interest> interest = (*entry)->getInterest();
+        pendingInterestTable_.erase(entry);
+
+        if (onData) {
+          onData(*interest, *data);
+        }
+
+        if (pendingInterestTable_.empty()) {
+          pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
+        }
+      }
+    }
+}
+
+Face::PendingInterestTable::iterator 
+Face::getEntryIndexForExpressedInterest(const Name& name)
+{
+  for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
+       i != pendingInterestTable_.end(); ++i)
+    {
+      if ((*i)->getInterest()->matchesName(name))
+        {
+          return i;
+        }
+    }
+
+  return pendingInterestTable_.end();
+}
+  
+Face::RegisteredPrefixTable::iterator
+Face::getEntryForRegisteredPrefix(const Name& name)
+{
+  RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
+
+  for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
+       i != registeredPrefixTable_.end();
+       ++i)
+    {
+      if (longestPrefix == registeredPrefixTable_.end() ||
+          (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
+        {
+          longestPrefix = i;
+        }
+    }
+  return longestPrefix;
+}
+
+} // namespace ndn
diff --git a/src/face.hpp b/src/face.hpp
index 13fdd6f..e312016 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -1,119 +1,130 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
 /**
  * Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  * See COPYING for copyright and distribution information.
  */
 
 #ifndef NDN_FACE_HPP
 #define NDN_FACE_HPP
 
-#include "node.hpp"
+#include "common.hpp"
+#include "interest.hpp"
+#include "data.hpp"
+
 #include "transport/transport.hpp"
 #include "transport/unix-transport.hpp"
 #include "transport/tcp-transport.hpp"
 
+#include "management/controller.hpp"
+
+#include "detail/registered-prefix.hpp"
+#include "detail/pending-interest.hpp"
+
 namespace ndn {
 
+struct PendingInterestId;
+struct RegisteredPrefixId;
+
 /**
- * The Face class provides the main methods for NDN communication.
+ * An OnData function object is used to pass a callback to expressInterest.
+ */
+typedef function<void(const Interest&, Data&)> OnData;
+
+/**
+ * An OnTimeout function object is used to pass a callback to expressInterest.
+ */
+typedef function<void(const Interest&)> OnTimeout;
+
+/**
+ * An OnInterest function object is used to pass a callback to registerPrefix.
+ */
+typedef function<void (const Name&, const Interest&)> OnInterest;
+
+/**
+ * An OnRegisterFailed function object is used to report when registerPrefix fails.
+ */
+typedef function<void(const Name&, const std::string&)> OnSetInterestFilterFailed;
+
+
+
+/**
+ * @brief Abstraction to communicate with local or remote NDN forwarder
  */
 class Face {
 public:
-  /**
-   * @brief Create a new Face for communication with an NDN hub using the default TcpTransport.
-   */
-  Face()
-    : node_(ptr_lib::shared_ptr<UnixTransport>(new UnixTransport()))
-  {
-  }
+  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
 
   /**
-   * @brief Create a new Face for communication with an NDN hub using the default Transport.
-   * @param ioService A shared pointer to boost::io_service object that should control all IO operations
+   * @brief Create a new Face for communication with an NDN Forwarder using the default UnixTransport.
    */
-  Face(const ptr_lib::shared_ptr<boost::asio::io_service> &ioService)
-    : node_(ptr_lib::shared_ptr<UnixTransport>(new UnixTransport()), ioService)
-  {
-  }
-  
-  /**
-   * Create a new Face for communication with an NDN hub with the given Transport object and connectionInfo.
-   * @param transport A shared_ptr to a Transport object used for communication.
-   */
-  Face(const ptr_lib::shared_ptr<Transport>& transport)
-    : node_(transport)
-  {
-  }
+  Face(bool nfdMode = false);
 
   /**
-   * Create a new Face for communication with an NDN hub with the given Transport object and connectionInfo.
-   * @param transport A shared_ptr to a Transport object used for communication.
+   * @brief Create a new Face for communication with an NDN Forwarder using the default UnixTransport.
    * @param ioService A shared pointer to boost::io_service object that should control all IO operations
    */
-  Face(const ptr_lib::shared_ptr<Transport>& transport, const ptr_lib::shared_ptr<boost::asio::io_service> &ioService)
-    : node_(transport, ioService)
-  {
-  }
+  Face(const ptr_lib::shared_ptr<boost::asio::io_service> &ioService, bool nfdMode = false);
   
   /**
    * Create a new Face for communication with an NDN hub at host:port using the default TcpTransport.
    * @param host The host of the NDN hub.
    * @param port The port or service name of the NDN hub. If omitted. use 6363.
    */
-  Face(const std::string &host, const std::string &port = "6363")
-  : node_(ptr_lib::shared_ptr<TcpTransport>(new TcpTransport(host, port)))
-  {
-  }
+  Face(const std::string &host, const std::string &port = "6363", bool nfdMode = false);
+
+  /**
+   * Create a new Face for communication with an NDN hub with the given Transport object and connectionInfo.
+   * @param transport A shared_ptr to a Transport object used for communication.
+   * @param transport A shared_ptr to a Transport::ConnectionInfo to be used to connect to the transport.
+   */
+  Face(const shared_ptr<Transport>& transport, bool nfdMode = false);
+
+  /**
+   * @brief Alternative (special use case) version of the constructor, can be used to aggregate
+   *        several Faces within one processing thread
+   *
+   * <code>
+   *     Face face1(...);
+   *     Face face2(..., face1.getAsyncService());
+   *
+   *     // Now the following ensures that events on both faces are processed
+   *     face1.processEvents();
+   * </code>
+   */
+  Face(const shared_ptr<Transport>& transport,
+       const shared_ptr<boost::asio::io_service> &ioService,
+       bool nfdMode = false);
   
   /**
-   * Send the Interest through the transport, read the entire response and call onData(interest, data).
-   * @param interest A reference to the Interest.  This copies the Interest.
-   * @param onData A function object to call when a matching data packet is received.  This copies the function object, so you may need to
-   * use func_lib::ref() as appropriate.
-   * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
-   * This copies the function object, so you may need to use func_lib::ref() as appropriate.
+   * @brief Express Interest
+   *
+   * @param interest  A reference to the Interest.  This copies the Interest.
+   * @param onData    A function object to call when a matching data packet is received.
+   * @param onTimeout A function object to call if the interest times out.
+   *                  If onTimeout is an empty OnTimeout(), this does not use it.
+   *
    * @return The pending interest ID which can be used with removePendingInterest.
    */
   const PendingInterestId*
-  expressInterest
-    (const Interest& interest, const OnData& onData, const OnTimeout& onTimeout = OnTimeout())
-  {
-    return node_.expressInterest(interest, onData, onTimeout);
-  }
+  expressInterest(const Interest& interest,
+                  const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
 
   /**
-   * Encode name as an Interest. If interestTemplate is not 0, use its interest selectors.
-   * Send the interest through the transport, read the entire response and call onData(interest, data).
-   * @param name A reference to a Name for the interest.  This copies the Name.
-   * @param interestTemplate if not 0, copy interest selectors from the template.   This does not keep a pointer to the Interest object.
-   * @param onData A function object to call when a matching data packet is received.  This copies the function object, so you may need to
-   *        use func_lib::ref() as appropriate.
-   * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
-   *        This copies the function object, so you may need to use func_lib::ref() as appropriate.
-   */
-  const PendingInterestId*
-  expressInterest
-    (const Name& name, const Interest *interestTemplate, const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
-
-  /**
-   * Encode name as an Interest, using a default interest lifetime.
-   * Send the interest through the transport, read the entire response and call onData(interest, data).
-   * @param name A reference to a Name for the interest.  This copies the Name.
-   * @param onData A function object to call when a matching data packet is received.  This copies the function object, so you may need to
-   * use func_lib::ref() as appropriate.
-   * @param onTimeout A function object to call if the interest times out.  If onTimeout is an empty OnTimeout(), this does not use it.
-   * This copies the function object, so you may need to use func_lib::ref() as appropriate.
-   * @param wireFormat A WireFormat object used to encode the message. If omitted, use WireFormat getDefaultWireFormat().
+   * @brief Express Interest using name and Interest template
+   *
+   * @param name      Name of the Interest
+   * @param tmpl      Interest template to fill parameters
+   * @param onData    A callback to call when a matching data packet is received.
+   * @param onTimeout A callback to call if the interest times out.
+   *                  If onTimeout is an empty OnTimeout(), this does not use it.
+   *
    * @return The pending interest ID which can be used with removePendingInterest.
    */
   const PendingInterestId*
-  expressInterest
-    (const Name& name, const OnData& onData, const OnTimeout& onTimeout = OnTimeout()) 
-  {
-    return expressInterest(name, 0, onData, onTimeout);
-  }
-
+  expressInterest(const Name& name,
+                  const Interest &tmpl,
+                  const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
+  
   /**
    * Remove the pending interest entry with the pendingInterestId from the pending interest table.
    * This does not affect another pending interest with a different pendingInterestId, even it if has the same interest name.
@@ -121,29 +132,22 @@
    * @param pendingInterestId The ID returned from expressInterest.
    */
   void
-  removePendingInterest(const PendingInterestId* pendingInterestId)
-  {
-    node_.removePendingInterest(pendingInterestId);
-  }
+  removePendingInterest(const PendingInterestId *pendingInterestId);
   
   /**
    * Register prefix with the connected NDN hub and call onInterest when a matching interest is received.
    * @param prefix A reference to a Name for the prefix to register.  This copies the Name.
    * @param onInterest A function object to call when a matching interest is received.  This copies the function object, so you may need to
-   * use func_lib::ref() as appropriate.
+   * use ref() as appropriate.
    * @param onRegisterFailed A function object to call if failed to retrieve the connected hub’s ID or failed to register the prefix.
    * This calls onRegisterFailed(prefix) where prefix is the prefix given to registerPrefix.
-   * @param flags The flags for finer control of which interests are forward to the application.  If omitted, use 
-   * the default flags defined by the default ForwardingFlags constructor.
-   * @param wireFormat A WireFormat object used to encode the message. If omitted, use WireFormat getDefaultWireFormat().
+   * @param flags The flags for finer control of which interests are forward to the application.
    * @return The registered prefix ID which can be used with removeRegisteredPrefix.
    */
   const RegisteredPrefixId*
-  setInterestFilter
-    (const Name& prefix, const OnInterest& onInterest, const OnSetInterestFilterFailed& onRegisterFailed)
-  {
-    return node_.setInterestFilter(prefix, onInterest, onRegisterFailed);
-  }
+  setInterestFilter(const Name& prefix,
+                    const OnInterest& onInterest,
+                    const OnSetInterestFilterFailed& onSetInterestFilterFailed);
 
   /**
    * Remove the registered prefix entry with the registeredPrefixId from the pending interest table.  
@@ -152,23 +156,17 @@
    * @param registeredPrefixId The ID returned from registerPrefix.
    */
   void
-  unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
-  {
-    node_.unsetInterestFilter(registeredPrefixId);
-  }
+  unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId);
 
-  /**
+   /**
    * @brief Publish data packet
    *
    * This method can be called to satisfy the incoming Interest or to put Data packet into the cache
    * of the local NDN forwarder
    */
   void
-  put(const Data &data)
-  {
-    node_.put(data);
-  }
-  
+  put(const Data &data);
+ 
   /**
    * Process any data to receive or call timeout callbacks.
    *
@@ -186,25 +184,75 @@
    * call this from an main event loop, you may want to catch and log/disregard all exceptions.
    */
   void 
-  processEvents(Milliseconds timeout = 0, bool keepThread = false)
-  {
-    // Just call Node's processEvents.
-    node_.processEvents(timeout, keepThread);
-  }
+  processEvents(Milliseconds timeout = 0, bool keepThread = false);
 
-  /**
-   * Shut down and disconnect this Face.
-   */
   void 
   shutdown();
 
   shared_ptr<boost::asio::io_service> 
-  ioService() { return node_.ioService(); }
+  ioService() { return ioService_; }
+
+private:
+  void
+  construct(const shared_ptr<Transport>& transport, const shared_ptr<boost::asio::io_service> &ioService, bool nfdMode);
+  
+  struct ProcessEventsTimeout {};
+  typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
+  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
+  asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId);
+  
+  void 
+  onReceiveElement(const Block &wire);
+
+  
+  static void
+  fireProcessEventsTimeout(const boost::system::error_code& error);
+
+  /**
+   * Find the entry from the pit_ where the name conforms to the entry's interest selectors, and
+   * the entry interest name is the longest that matches name.
+   * @param name The name to find the interest for (from the incoming data packet).
+   * @return The index in pit_ of the pit entry, or -1 if not found.
+   */
+  PendingInterestTable::iterator 
+  getEntryIndexForExpressedInterest(const Name& name);
+  
+  /**
+   * Find the first entry from the registeredPrefixTable_ where the entry prefix is the longest that matches name.
+   * @param name The name to find the PrefixEntry for (from the incoming interest packet).
+   * @return A pointer to the entry, or 0 if not found.
+   */
+  RegisteredPrefixTable::iterator
+  getEntryForRegisteredPrefix(const Name& name);
+
+  
+  void
+  checkPitExpire();
   
 private:
-  Node node_;
+  shared_ptr<boost::asio::io_service> ioService_;
+  shared_ptr<boost::asio::io_service::work> ioServiceWork_; // needed if thread needs to be preserved
+  shared_ptr<boost::asio::deadline_timer> pitTimeoutCheckTimer_;
+  bool pitTimeoutCheckTimerActive_;
+  shared_ptr<boost::asio::deadline_timer> processEventsTimeoutTimer_;
+  
+  shared_ptr<Transport> transport_;
+
+  PendingInterestTable pendingInterestTable_;
+  RegisteredPrefixTable registeredPrefixTable_;
+
+  shared_ptr<Controller> m_fwController;
 };
 
-}
+} // namespace ndn
 
-#endif
+#endif // NDN_FACE_HPP
diff --git a/src/interest.hpp b/src/interest.hpp
index e09cf2c..c4d7bc6 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -18,7 +18,7 @@
 /**
  * An Interest holds a Name and other fields for an interest.
  */
-class Interest {
+class Interest : public enable_shared_from_this<Interest> {
 public:    
   /**
    * Create a new Interest for the given name and values.
diff --git a/src/management/controller.hpp b/src/management/controller.hpp
index f919489..f38e64a 100644
--- a/src/management/controller.hpp
+++ b/src/management/controller.hpp
@@ -14,7 +14,8 @@
 
 namespace ndn {
 
-class Node;
+class Name;
+class Face;
 
 class Controller
 {
diff --git a/src/management/ndnd-controller.cpp b/src/management/ndnd-controller.cpp
index e95d85e..302699e 100644
--- a/src/management/ndnd-controller.cpp
+++ b/src/management/ndnd-controller.cpp
@@ -7,7 +7,7 @@
 #include "common.hpp"
 #include "ndnd-controller.hpp"
 
-#include "../node.hpp"
+#include "../face.hpp"
 #include "../security/signature-sha256-with-rsa.hpp"
 #include "../util/random.hpp"
 
@@ -18,7 +18,7 @@
 namespace ndn {
 namespace ndnd {
 
-Controller::Controller(Node& face)
+Controller::Controller(Face& face)
   : m_face(face)
   , m_faceId(-1)
 {
@@ -64,12 +64,11 @@
 
 
 void 
-Controller::onNdnidFetched(const shared_ptr<const Interest>& interest,
-                           const shared_ptr<Data>& data)
+Controller::onNdnidFetched(const Interest& interest, Data& data)
 {
-  if (data->getName().size() > interest->getName().size())
+  if (data.getName().size() > interest.getName().size())
     {
-      m_ndndId = data->getName()[interest->getName().size()];
+      m_ndndId = data.getName()[interest.getName().size()];
 
       for (FilterRequestList::iterator i = m_filterRequests.begin();
            i != m_filterRequests.end();
@@ -169,11 +168,11 @@
 }
 
 void
-Controller::processFaceActionResponse(const shared_ptr<Data>& data,
+Controller::processFaceActionResponse(Data& data,
                                       const FaceOperationSucceedCallback& onSuccess,
                                       const FailCallback& onFail)
 {
-  Block content = data->getContent();
+  Block content = data.getContent();
   content.parse();
 
   if (content.getAll().empty())
@@ -215,11 +214,11 @@
 }
 
 void
-Controller::processPrefixActionResponse(const shared_ptr<Data>& data,
+Controller::processPrefixActionResponse(Data& data,
                                         const PrefixOperationSucceedCallback& onSuccess,
                                         const FailCallback& onFail)
 {
-  Block content = data->getContent();
+  Block content = data.getContent();
   content.parse();
 
   if (content.getAll().empty())
diff --git a/src/management/ndnd-controller.hpp b/src/management/ndnd-controller.hpp
index 319f995..a689d28 100644
--- a/src/management/ndnd-controller.hpp
+++ b/src/management/ndnd-controller.hpp
@@ -7,17 +7,9 @@
 #ifndef NDN_MANAGEMENT_NDND_CONTROLLER_HPP
 #define NDN_MANAGEMENT_NDND_CONTROLLER_HPP
 
-#include "../common.hpp"
 #include "controller.hpp"
 
-#include "../name.hpp"
-#include "../interest.hpp"
-#include "../data.hpp"
-
 namespace ndn {
-
-class Node;
-
 namespace ndnd {
 
 class FaceInstance;
@@ -37,7 +29,7 @@
   /**
    * @brief Construct ndnd::Control object
    */
-  Controller(Node& face);
+  Controller(Face& face);
 
   virtual void
   selfRegisterPrefix(const Name& prefixToRegister,
@@ -62,26 +54,24 @@
 
 private:
   void 
-  onNdnidFetched(const shared_ptr<const Interest>& interest,
-                 const shared_ptr<Data>& data);
-
+  onNdnidFetched(const Interest& interest, Data& data);
 
   void
   recordSelfRegisteredFaceId(const ForwardingEntry& entry,
                              const SuccessCallback& onSuccess);
 
   void
-  processFaceActionResponse(const shared_ptr<Data>& data,
+  processFaceActionResponse(Data& data,
                             const FaceOperationSucceedCallback& onSuccess,
                             const FailCallback&    onFail);
 
   void
-  processPrefixActionResponse(const shared_ptr<Data>& data,
+  processPrefixActionResponse(Data& data,
                               const PrefixOperationSucceedCallback& onSuccess,
                               const FailCallback&    onFail);
 
 private:
-  Node& m_face;
+  Face& m_face;
   Block m_ndndId;
   int64_t m_faceId; // internal face ID (needed for prefix de-registration)
 
diff --git a/src/management/nfd-controller.cpp b/src/management/nfd-controller.cpp
index c72c5d3..b75f0e0 100644
--- a/src/management/nfd-controller.cpp
+++ b/src/management/nfd-controller.cpp
@@ -5,7 +5,7 @@
  */
 
 #include "common.hpp"
-#include "../node.hpp"
+#include "../face.hpp"
 
 #include "nfd-controller.hpp"
 #include "nfd-fib-management-options.hpp"
@@ -14,7 +14,7 @@
 namespace ndn {
 namespace nfd {
 
-Controller::Controller(Node& face)
+Controller::Controller(Face& face)
   : m_face(face)
   , m_faceId(0)
 {
@@ -82,18 +82,18 @@
 }
 
 // void
-// processFaceActionResponse(const shared_ptr<Data>& data,
+// processFaceActionResponse(Data& data,
 //                           const FaceOperationSucceedCallback& onSuccess,
 //                           const FailCallback&    onFail);
 
 void
-Controller::processFibCommandResponse(const shared_ptr<Data>& data,
+Controller::processFibCommandResponse(Data& data,
                                       const FibCommandSucceedCallback& onSuccess,
                                       const FailCallback& onFail)
 {
   try
     {
-      ControlResponse response(data->getContent().blockFromValue());
+      ControlResponse response(data.getContent().blockFromValue());
 
       if (response.getCode() != 200)
         return onFail(response.getText());
diff --git a/src/management/nfd-controller.hpp b/src/management/nfd-controller.hpp
index d5400c6..aa788a9 100644
--- a/src/management/nfd-controller.hpp
+++ b/src/management/nfd-controller.hpp
@@ -7,18 +7,12 @@
 #ifndef NDN_MANAGEMENT_NFD_CONTROL_HPP
 #define NDN_MANAGEMENT_NFD_CONTROL_HPP
 
-#include "../common.hpp"
 #include "controller.hpp"
 
-#include "../name.hpp"
-#include "../interest.hpp"
-#include "../data.hpp"
 #include "../security/key-chain.hpp"
 
 namespace ndn {
 
-class Name;
-
 namespace nfd {
 
 class FibManagementOptions;
@@ -31,7 +25,7 @@
   /**
    * @brief Construct ndnd::Control object
    */
-  Controller(Node& face);
+  Controller(Face& face);
 
   virtual void
   selfRegisterPrefix(const Name& prefixToRegister,
@@ -54,17 +48,17 @@
                              const SuccessCallback& onSuccess);
 
   // void
-  // processFaceActionResponse(const shared_ptr<Data>& data,
+  // processFaceActionResponse(Data& data,
   //                           const FaceOperationSucceedCallback& onSuccess,
   //                           const FailCallback&    onFail);
 
   void
-  processFibCommandResponse(const shared_ptr<Data>& data,
+  processFibCommandResponse(Data& data,
                             const FibCommandSucceedCallback& onSuccess,
                             const FailCallback& onFail);
   
 private:
-  Node& m_face;
+  Face& m_face;
   KeyChain m_keyChain;
   uint64_t m_faceId; // internal face ID (needed for prefix de-registration)
 };
diff --git a/src/node.cpp b/src/node.cpp
deleted file mode 100644
index bd7ce67..0000000
--- a/src/node.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
- * See COPYING for copyright and distribution information.
- */
-
-#include "common.hpp"
-
-#include "node.hpp"
-
-#include "security/signature-sha256-with-rsa.hpp"
-
-#include "util/time.hpp"
-#include "util/random.hpp"
-
-#include "management/ndnd-controller.hpp"
-#include "management/nfd-controller.hpp"
-
-namespace ndn {
-
-Node::Node(const shared_ptr<Transport>& transport, bool nfdMode/* = false*/)
-{
-  construct(transport, make_shared<boost::asio::io_service>(), nfdMode);
-}
-
-Node::Node(const shared_ptr<Transport>& transport,
-           const shared_ptr<boost::asio::io_service> &ioService,
-           bool nfdMode/* = false*/)
-{
-  construct(transport, ioService, nfdMode);
-}
-
-void
-Node::construct(const shared_ptr<Transport>& transport,
-                const shared_ptr<boost::asio::io_service> &ioService,
-                bool nfdMode)
-{
-  pitTimeoutCheckTimerActive_ = false;
-  transport_ = transport;
-  ioService_ = ioService;
-
-  pitTimeoutCheckTimer_      = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
-  processEventsTimeoutTimer_ = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
-  
-  if (nfdMode)
-      m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
-  else
-      m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
-}
-
-
-const PendingInterestId*
-Node::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
-{
-  if (!transport_->isConnected())
-    transport_->connect(*ioService_,
-                        bind(&Node::onReceiveElement, this, _1));
-
-  shared_ptr<const Interest> interestToExpress(new Interest(interest));
-  
-  ioService_->post(bind(&Node::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
-  
-  return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
-}
-
-void
-Node::asyncExpressInterest(const shared_ptr<const Interest> &interest,
-                           const OnData& onData, const OnTimeout& onTimeout)
-{
-  pendingInterestTable_.push_back(shared_ptr<PendingInterest>(new PendingInterest
-                                                              (interest, onData, onTimeout)));
-
-  transport_->send(interest->wireEncode());
-
-  if (!pitTimeoutCheckTimerActive_) {
-    pitTimeoutCheckTimerActive_ = true;
-    pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
-    pitTimeoutCheckTimer_->async_wait(bind(&Node::checkPitExpire, this));
-  }
-}
-    
-void
-Node::put(const Data &data)
-{
-  if (!transport_->isConnected())
-    transport_->connect(*ioService_,
-                        bind(&Node::onReceiveElement, this, _1));
-
-  transport_->send(data.wireEncode());
-}
-
-
-void
-Node::removePendingInterest(const PendingInterestId *pendingInterestId)
-{
-  ioService_->post(bind(&Node::asyncRemovePendingInterest, this, pendingInterestId));
-}
-
-
-void
-Node::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
-{
-  pendingInterestTable_.remove_if(MatchPendingInterestId(pendingInterestId));
-}
-
-const RegisteredPrefixId*
-Node::setInterestFilter(const Name& prefix,
-                        const OnInterest& onInterest,
-                        const OnSetInterestFilterFailed& onSetInterestFilterFailed)
-{
-  shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
-
-  m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
-                                     bind(&RegisteredPrefixTable::push_back, &registeredPrefixTable_, prefixToRegister),
-                                     bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
-  
-  return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
-}
-
-void
-Node::unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
-{
-  ioService_->post(bind(&Node::asyncUnsetInterestFilter, this, registeredPrefixId));
-}
-
-void
-Node::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
-{
-  RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
-                                                   MatchRegisteredPrefixId(registeredPrefixId));  
-  if (i != registeredPrefixTable_.end())
-    {
-      m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
-                                           bind(&RegisteredPrefixTable::erase, &registeredPrefixTable_, i),
-                                           Controller::FailCallback());
-    }
-
-  // there cannot be two registered prefixes with the same id. if there are, then something is broken
-}
-
-void 
-Node::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
-{
-  try
-    {
-      if (timeout < 0)
-        {
-          // do not block if timeout is negative, but process pending events
-          ioService_->poll();
-          return;
-        }
-
-      if (timeout > 0)
-        {
-          processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
-          processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
-        }
-      
-      if (keepThread) {
-        // work will ensure that ioService_ is running until work object exists
-        ioServiceWork_ = make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
-      }
-          
-      ioService_->run();
-      ioService_->reset(); // so it is possible to run processEvents again (if necessary)
-    }
-  catch(Node::ProcessEventsTimeout &)
-    {
-      // break
-      ioService_->reset();
-    }
-  catch(const std::exception &)
-    {
-      ioService_->reset();
-      pendingInterestTable_.clear();
-      registeredPrefixTable_.clear();
-      throw;
-    }
-}
-
-void 
-Node::shutdown()
-{
-  pendingInterestTable_.clear();
-  registeredPrefixTable_.clear();
-
-  transport_->close();
-  pitTimeoutCheckTimer_->cancel();
-  processEventsTimeoutTimer_->cancel();
-  pitTimeoutCheckTimerActive_ = false;
-}
-
-void
-Node::fireProcessEventsTimeout(const boost::system::error_code& error)
-{
-  if (!error) // can fire for some other reason, e.g., cancelled
-    throw Node::ProcessEventsTimeout();
-}
-
-void
-Node::checkPitExpire()
-{
-  // Check for PIT entry timeouts.  Go backwards through the list so we can erase entries.
-  MillisecondsSince1970 nowMilliseconds = getNowMilliseconds();
-
-  PendingInterestTable::iterator i = pendingInterestTable_.begin();
-  while (i != pendingInterestTable_.end())
-    {
-      if ((*i)->isTimedOut(nowMilliseconds))
-        {
-          // Save the PendingInterest and remove it from the PIT.  Then call the callback.
-          shared_ptr<PendingInterest> pendingInterest = *i;
-
-          i = pendingInterestTable_.erase(i);
-
-          pendingInterest->callTimeout();
-        }
-      else
-        ++i;
-    }
-
-  if (!pendingInterestTable_.empty()) {
-    pitTimeoutCheckTimerActive_ = true;
-    
-    pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
-    pitTimeoutCheckTimer_->async_wait(bind(&Node::checkPitExpire, this));
-  }
-  else {
-    pitTimeoutCheckTimerActive_ = false;
-
-    if (registeredPrefixTable_.empty()) {
-      transport_->close();
-      if (!ioServiceWork_) {
-        processEventsTimeoutTimer_->cancel();
-      }
-    }
-  }
-}
-
-
-void 
-Node::onReceiveElement(const Block &block)
-{
-  if (block.type() == Tlv::Interest)
-    {
-      shared_ptr<Interest> interest(new Interest());
-      interest->wireDecode(block);
-    
-      RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
-      if (entry != registeredPrefixTable_.end()) {
-        (*entry)->getOnInterest()((*entry)->getPrefix().shared_from_this(), interest);
-      }
-    }
-  else if (block.type() == Tlv::Data)
-    {
-      shared_ptr<Data> data(new Data());
-      data->wireDecode(block);
-
-      PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
-      if (entry != pendingInterestTable_.end()) {
-        // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
-        const OnData onData = (*entry)->getOnData();
-        const shared_ptr<const Interest> interest = (*entry)->getInterest();
-        pendingInterestTable_.erase(entry);
-
-        if (onData) {
-          onData(interest, data);
-        }
-
-        if (pendingInterestTable_.empty()) {
-          pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
-        }
-      }
-    }
-}
-
-Node::PendingInterestTable::iterator 
-Node::getEntryIndexForExpressedInterest(const Name& name)
-{
-  for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
-       i != pendingInterestTable_.end(); ++i)
-    {
-      if ((*i)->getInterest()->matchesName(name))
-        {
-          return i;
-        }
-    }
-
-  return pendingInterestTable_.end();
-}
-  
-Node::RegisteredPrefixTable::iterator
-Node::getEntryForRegisteredPrefix(const Name& name)
-{
-  RegisteredPrefixTable::iterator longestPrefix = registeredPrefixTable_.end();
-
-  for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
-       i != registeredPrefixTable_.end();
-       ++i)
-    {
-      if (longestPrefix == registeredPrefixTable_.end() ||
-          (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
-        {
-          longestPrefix = i;
-        }
-    }
-  return longestPrefix;
-}
-
-} // namespace ndn
diff --git a/src/node.hpp b/src/node.hpp
deleted file mode 100644
index 7e1a7ca..0000000
--- a/src/node.hpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
- * See COPYING for copyright and distribution information.
- */
-
-#ifndef NDN_NODE_HPP
-#define NDN_NODE_HPP
-
-#include "common.hpp"
-#include "interest.hpp"
-#include "data.hpp"
-#include "transport/transport.hpp"
-
-#include "management/controller.hpp"
-
-#include "detail/registered-prefix.hpp"
-#include "detail/pending-interest.hpp"
-
-namespace ndn {
-
-struct PendingInterestId;
-struct RegisteredPrefixId;
-
-/**
- * An OnData function object is used to pass a callback to expressInterest.
- */
-typedef function<void(const shared_ptr<const Interest>&, const shared_ptr<Data>&)> OnData;
-
-/**
- * An OnTimeout function object is used to pass a callback to expressInterest.
- */
-typedef function<void(const shared_ptr<const Interest>&)> OnTimeout;
-
-/**
- * An OnInterest function object is used to pass a callback to registerPrefix.
- */
-typedef function<void
-  (const shared_ptr<const Name>&, const shared_ptr<const Interest>&)> OnInterest;
-
-/**
- * An OnRegisterFailed function object is used to report when registerPrefix fails.
- */
-typedef function<void(const Name&, const std::string&)> OnSetInterestFilterFailed;
-
-class Node {
-public:
-  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
-
-  /**
-   * Create a new Node for communication with an NDN hub with the given Transport object and connectionInfo.
-   * @param transport A shared_ptr to a Transport object used for communication.
-   * @param transport A shared_ptr to a Transport::ConnectionInfo to be used to connect to the transport.
-   */
-  Node(const shared_ptr<Transport>& transport, bool nfdMode = false);
-
-  /**
-   * @brief Alternative (special use case) version of the constructor, can be used to aggregate
-   *        several Faces within one processing thread
-   *
-   * <code>
-   *     Face face1(...);
-   *     Face face2(..., face1.getAsyncService());
-   *
-   *     // Now the following ensures that events on both faces are processed
-   *     face1.processEvents();
-   * </code>
-   */
-  Node(const shared_ptr<Transport>& transport, const shared_ptr<boost::asio::io_service> &ioService, bool nfdMode = false);
-  
-  /**
-   * @brief Send the Interest through the transport, read the entire response and call onData(interest, data).
-   *
-   * @param interest  A reference to the Interest.  This copies the Interest.
-   * @param onData    A function object to call when a matching data packet is received.
-   * @param onTimeout A function object to call if the interest times out.
-   *                  If onTimeout is an empty OnTimeout(), this does not use it.
-   *
-   * @return The pending interest ID which can be used with removePendingInterest.
-   */
-  const PendingInterestId*
-  expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout);
-  
-  /**
-   * Remove the pending interest entry with the pendingInterestId from the pending interest table.
-   * This does not affect another pending interest with a different pendingInterestId, even it if has the same interest name.
-   * If there is no entry with the pendingInterestId, do nothing.
-   * @param pendingInterestId The ID returned from expressInterest.
-   */
-  void
-  removePendingInterest(const PendingInterestId *pendingInterestId);
-  
-  /**
-   * Register prefix with the connected NDN hub and call onInterest when a matching interest is received.
-   * @param prefix A reference to a Name for the prefix to register.  This copies the Name.
-   * @param onInterest A function object to call when a matching interest is received.  This copies the function object, so you may need to
-   * use ref() as appropriate.
-   * @param onRegisterFailed A function object to call if failed to retrieve the connected hub’s ID or failed to register the prefix.
-   * This calls onRegisterFailed(prefix) where prefix is the prefix given to registerPrefix.
-   * @param flags The flags for finer control of which interests are forward to the application.
-   * @return The registered prefix ID which can be used with removeRegisteredPrefix.
-   */
-  const RegisteredPrefixId*
-  setInterestFilter(const Name& prefix,
-                    const OnInterest& onInterest,
-                    const OnSetInterestFilterFailed& onSetInterestFilterFailed);
-
-  /**
-   * Remove the registered prefix entry with the registeredPrefixId from the pending interest table.  
-   * This does not affect another registered prefix with a different registeredPrefixId, even it if has the same prefix name.
-   * If there is no entry with the registeredPrefixId, do nothing.
-   * @param registeredPrefixId The ID returned from registerPrefix.
-   */
-  void
-  unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId);
-
-   /**
-   * @brief Publish data packet
-   *
-   * This method can be called to satisfy the incoming Interest or to put Data packet into the cache
-   * of the local NDN forwarder
-   */
-  void
-  put(const Data &data);
- 
-  /**
-   * Process any data to receive or call timeout callbacks.
-   *
-   * This call will block forever (default timeout == 0) to process IO on the face.
-   * To exit, one expected to call face.shutdown() from one of the callback methods.
-   *
-   * If positive timeout is specified, then processEvents will exit after this timeout,
-   * if not stopped earlier with face.shutdown() or when all active events finish.
-   * The call can be called repeatedly, if desired.
-   *
-   * If negative timeout is specified, then processEvents will not block and process only pending
-   * events.
-   *
-   * @throw This may throw an exception for reading data or in the callback for processing the data.  If you
-   * call this from an main event loop, you may want to catch and log/disregard all exceptions.
-   */
-  void 
-  processEvents(Milliseconds timeout = 0, bool keepThread = false);
-
-  void 
-  shutdown();
-
-  shared_ptr<boost::asio::io_service> 
-  ioService() { return ioService_; }
-
-private:
-  void
-  construct(const shared_ptr<Transport>& transport, const shared_ptr<boost::asio::io_service> &ioService, bool nfdMode);
-  
-  struct ProcessEventsTimeout {};
-  typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
-  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
-  asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId);
-  
-  void 
-  onReceiveElement(const Block &wire);
-
-  
-  static void
-  fireProcessEventsTimeout(const boost::system::error_code& error);
-
-  /**
-   * Find the entry from the pit_ where the name conforms to the entry's interest selectors, and
-   * the entry interest name is the longest that matches name.
-   * @param name The name to find the interest for (from the incoming data packet).
-   * @return The index in pit_ of the pit entry, or -1 if not found.
-   */
-  PendingInterestTable::iterator 
-  getEntryIndexForExpressedInterest(const Name& name);
-  
-  /**
-   * Find the first entry from the registeredPrefixTable_ where the entry prefix is the longest that matches name.
-   * @param name The name to find the PrefixEntry for (from the incoming interest packet).
-   * @return A pointer to the entry, or 0 if not found.
-   */
-  RegisteredPrefixTable::iterator
-  getEntryForRegisteredPrefix(const Name& name);
-
-  
-  void
-  checkPitExpire();
-  
-private:
-  shared_ptr<boost::asio::io_service> ioService_;
-  shared_ptr<boost::asio::io_service::work> ioServiceWork_; // needed if thread needs to be preserved
-  shared_ptr<boost::asio::deadline_timer> pitTimeoutCheckTimer_;
-  bool pitTimeoutCheckTimerActive_;
-  shared_ptr<boost::asio::deadline_timer> processEventsTimeoutTimer_;
-  
-  shared_ptr<Transport> transport_;
-
-  PendingInterestTable pendingInterestTable_;
-  RegisteredPrefixTable registeredPrefixTable_;
-
-  shared_ptr<Controller> m_fwController;
-};
-
-} // namespace ndn
-
-#endif
diff --git a/src/security/validator-null.hpp b/src/security/validator-null.hpp
index 27dc63d..d1d8faa 100644
--- a/src/security/validator-null.hpp
+++ b/src/security/validator-null.hpp
@@ -21,20 +21,20 @@
   
 protected:
   virtual void
-  checkPolicy (const shared_ptr<const Data>& data, 
+  checkPolicy (const Data& data, 
                int stepCount, 
                const OnDataValidated &onValidated, 
                const OnDataValidationFailed &onValidationFailed,
                std::vector<shared_ptr<ValidationRequest> > &nextSteps)
-  { onValidated(data); }
+  { onValidated(data.shared_from_this()); }
   
   virtual void
-  checkPolicy (const shared_ptr<const Interest>& interest, 
+  checkPolicy (const Interest& interest, 
                int stepCount, 
                const OnInterestValidated &onValidated, 
                const OnInterestValidationFailed &onValidationFailed,
                std::vector<shared_ptr<ValidationRequest> > &nextSteps)
-  { onValidated(interest); }
+  { onValidated(interest.shared_from_this()); }
 };
 
 }
diff --git a/src/security/validator-regex.cpp b/src/security/validator-regex.cpp
index 18dc9bf..1b9dcb9 100644
--- a/src/security/validator-regex.cpp
+++ b/src/security/validator-regex.cpp
@@ -75,7 +75,7 @@
 { onValidationFailed(data); }
 
 void
-ValidatorRegex::checkPolicy(const shared_ptr<const Data> &data, 
+ValidatorRegex::checkPolicy(const Data& data, 
                             int stepCount, 
                             const OnDataValidated &onValidated, 
                             const OnDataValidationFailed &onValidationFailed,
@@ -83,25 +83,25 @@
 {
   if(m_stepLimit == stepCount){
     _LOG_DEBUG("reach the maximum steps of verification");
-    onValidationFailed(data);
+    onValidationFailed(data.shared_from_this());
     return;
   }
   
   RuleList::iterator it = m_mustFailVerify.begin();
   for(; it != m_mustFailVerify.end(); it++)
-    if((*it)->satisfy(*data))
+    if((*it)->satisfy(data))
       {
-        onValidationFailed(data);
+        onValidationFailed(data.shared_from_this());
         return;
       }
 
   it = m_verifyPolicies.begin();
   for(; it != m_verifyPolicies.end(); it++)
     {
-      if((*it)->satisfy(*data))
+      if((*it)->satisfy(data))
         {
           try{
-            SignatureSha256WithRsa sig(data->getSignature());                
+            SignatureSha256WithRsa sig(data.getSignature());                
             
             Name keyLocatorName = sig.getKeyLocator().getName();
             shared_ptr<const Certificate> trustedCert;
@@ -111,20 +111,20 @@
               trustedCert = m_trustAnchors[keyLocatorName];
             
             if(static_cast<bool>(trustedCert)){
-              if(verifySignature(*data, sig, trustedCert->getPublicKeyInfo()))
-                onValidated(data);
+              if(verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
+                onValidated(data.shared_from_this());
               else
-                onValidationFailed(data);
+                onValidationFailed(data.shared_from_this());
               
               return;
             }
             else{
               // _LOG_DEBUG("KeyLocator is not trust anchor");                
               OnDataValidated onKeyValidated = bind(&ValidatorRegex::onCertificateValidated, this, 
-                                                    _1, data, onValidated, onValidationFailed);
+                                                    _1, data.shared_from_this(), onValidated, onValidationFailed);
               
               OnDataValidationFailed onKeyValidationFailed = bind(&ValidatorRegex::onCertificateValidationFailed, this, 
-                                                                  _1, data, onValidationFailed);              
+                                                                  _1, data.shared_from_this(), onValidationFailed);              
 
               shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(Interest(boost::cref(sig.getKeyLocator().getName())), 
                                                                                       onKeyValidated,
@@ -136,17 +136,17 @@
             }
           }catch(SignatureSha256WithRsa::Error &e){
             _LOG_DEBUG("ValidatorRegex Error: " << e.what());
-            onValidationFailed(data);
+            onValidationFailed(data.shared_from_this());
             return;
           }catch(KeyLocator::Error &e){
             _LOG_DEBUG("ValidatorRegex Error: " << e.what());
-            onValidationFailed(data);
+            onValidationFailed(data.shared_from_this());
             return;
           }
         }
     }
 
-  onValidationFailed(data);
+  onValidationFailed(data.shared_from_this());
   return;
 }
 
diff --git a/src/security/validator-regex.hpp b/src/security/validator-regex.hpp
index 6b44d13..d6b9b1d 100644
--- a/src/security/validator-regex.hpp
+++ b/src/security/validator-regex.hpp
@@ -48,19 +48,19 @@
 
 protected:
   virtual void
-  checkPolicy (const shared_ptr<const Data>& data, 
+  checkPolicy (const Data& data, 
                int stepCount, 
                const OnDataValidated &onValidated, 
                const OnDataValidationFailed &onValidationFailed,
                std::vector<shared_ptr<ValidationRequest> > &nextSteps);
 
   virtual void
-  checkPolicy (const shared_ptr<const Interest>& interest, 
+  checkPolicy (const Interest& interest, 
                int stepCount, 
                const OnInterestValidated &onValidated, 
                const OnInterestValidationFailed &onValidationFailed,
                std::vector<shared_ptr<ValidationRequest> > &nextSteps)
-  { onValidationFailed(interest); }
+  { onValidationFailed(interest.shared_from_this()); }
 
   void
   onCertificateValidated(const shared_ptr<const Data> &signCertificate, 
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index ebb8b55..8b1c17f 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -26,7 +26,7 @@
 {}
 
 void
-Validator::validate(const shared_ptr<const Interest> &interest, 
+Validator::validate(const Interest& interest, 
                     const OnInterestValidated &onValidated, 
                     const OnInterestValidationFailed &onValidationFailed,
                     int stepCount)
@@ -40,7 +40,7 @@
         throw Error("Face should be set prior to verify method to call");
       
       vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
-      OnFailure onFailure = bind(onValidationFailed, interest);
+      OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this());
       for(; it != nextSteps.end(); it++)
         m_face->expressInterest((*it)->m_interest,
                                 bind(&Validator::onData, this, _1, _2, *it), 
@@ -57,7 +57,7 @@
 }
 
 void
-Validator::validate(const shared_ptr<const Data> &data, 
+Validator::validate(const Data& data, 
                     const OnDataValidated &onValidated, 
                     const OnDataValidationFailed &onValidationFailed,
                     int stepCount)
@@ -71,7 +71,7 @@
         throw Error("Face should be set prior to verify method to call");
 
       vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
-      OnFailure onFailure = bind(onValidationFailed, data);
+      OnFailure onFailure = bind(onValidationFailed, data.shared_from_this());
       for(; it != nextSteps.end(); it++)
         m_face->expressInterest((*it)->m_interest,
                                 bind(&Validator::onData, this, _1, _2, *it), 
@@ -88,22 +88,22 @@
 }
 
 void
-Validator::onData(const shared_ptr<const Interest> &interest, 
-                  const shared_ptr<const Data> &data, 
-                  shared_ptr<ValidationRequest> nextStep)
+Validator::onData(const Interest& interest, 
+                  Data& data, 
+                  const shared_ptr<ValidationRequest>& nextStep)
 {
   validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_stepCount);
 }
 
 void
-Validator::onTimeout(const shared_ptr<const Interest> &interest, 
+Validator::onTimeout(const Interest& interest, 
                      int retry, 
                      const OnFailure &onFailure, 
-                     shared_ptr<ValidationRequest> nextStep)
+                     const shared_ptr<ValidationRequest>& nextStep)
 {
   if (retry > 0)
     // Issue the same expressInterest except decrement retry.
-    m_face->expressInterest(*interest, 
+    m_face->expressInterest(interest, 
                             bind(&Validator::onData, this, _1, _2, nextStep), 
                             bind(&Validator::onTimeout, this, _1, retry - 1, onFailure, nextStep));
   else
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 1d74aa2..5a1062d 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -39,7 +39,7 @@
    * @param onValidationFailed If the Data validation fails, this calls onValidationFailed(data).
    */
   void
-  validate (const shared_ptr<const Data> &data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
+  validate (const Data& data, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed)
   { validate (data, onValidated, onValidationFailed, 0); }
 
   /**
@@ -50,7 +50,7 @@
    * @param onValidationFailed If the Interest validation fails, this calls onValidationFailed(interest).
    */
   void
-  validate (const shared_ptr<const Interest> &interest, const OnInterestValidated &onValidated, const OnInterestValidationFailed &onValidationFailed)
+  validate (const Interest& interest, const OnInterestValidated &onValidated, const OnInterestValidationFailed &onValidationFailed)
   { validate (interest, onValidated, onValidationFailed, 0); }
 
   /*****************************************
@@ -95,7 +95,7 @@
    * @param nextSteps On return, contains the next validation step.
    */
   virtual void
-  checkPolicy (const shared_ptr<const Data> &data, 
+  checkPolicy (const Data& data, 
                int stepCount, 
                const OnDataValidated &onValidated, 
                const OnDataValidationFailed &onValidationFailed,
@@ -114,7 +114,7 @@
    * @return the indication of next validation step, null if there is no further step.
    */
   virtual void
-  checkPolicy (const shared_ptr<const Interest> &interest, 
+  checkPolicy (const Interest& interest, 
                int stepCount, 
                const OnInterestValidated &onValidated, 
                const OnInterestValidationFailed &onValidationFailed,
@@ -125,25 +125,25 @@
   
   /// @brief Process the received certificate.
   void
-  onData (const shared_ptr<const Interest> &interest, 
-          const shared_ptr<const Data> &data, 
-          shared_ptr<ValidationRequest> nextStep);
+  onData (const Interest& interest, 
+          Data& data, 
+          const shared_ptr<ValidationRequest>& nextStep);
   
   /// @brief Re-express the interest if it times out.
   void
-  onTimeout (const shared_ptr<const Interest> &interest, 
+  onTimeout (const Interest& interest, 
              int retry, 
              const OnFailure &onFailure, 
-             shared_ptr<ValidationRequest> nextStep);
+             const shared_ptr<ValidationRequest>& nextStep);
 
   void
-  validate (const shared_ptr<const Data> &data, 
+  validate (const Data& data, 
             const OnDataValidated &onValidated, 
             const OnDataValidationFailed &onValidationFailed, 
             int stepCount);
 
   void
-  validate (const shared_ptr<const Interest> &interest, 
+  validate (const Interest& interest, 
             const OnInterestValidated &onValidated, 
             const OnInterestValidationFailed &onValidationFailed, 
             int stepCount);
diff --git a/tests/test-validator.cpp b/tests/test-validator.cpp
index 1b24a3d..19e2b78 100644
--- a/tests/test-validator.cpp
+++ b/tests/test-validator.cpp
@@ -38,8 +38,9 @@
   keyChain.signByIdentity(*data, identity);
   
   ValidatorNull validator;
-  
-  validator.validate(data,
+
+  // data must be a shared pointer
+  validator.validate(*data,
 		     bind(&onValidated, _1),
 		     bind(&onValidationFailed, _1));
 
diff --git a/tools/ndncatchunks3.cpp b/tools/ndncatchunks3.cpp
index 6bac64a..c912f26 100644
--- a/tools/ndncatchunks3.cpp
+++ b/tools/ndncatchunks3.cpp
@@ -21,14 +21,6 @@
 
 #include "face.hpp"
 
-#include <stdexcept>
-#include <iostream>
-
-#if NDN_CPP_HAVE_CXX11
-// In the std library, the placeholders are in a different namespace than boost.
-using namespace ndn::func_lib::placeholders;
-#endif
-
 class Consumer
 {
 public:
@@ -51,11 +43,10 @@
   
 private:
   void
-  on_data (const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest,
-	   const ndn::ptr_lib::shared_ptr<ndn::Data> &data);
+  on_data (const ndn::Interest& interest, ndn::Data& data);
 
   void
-  on_timeout (const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest);
+  on_timeout (const ndn::Interest& interest);
   
   ndn::Face m_face;
   ndn::Name m_data_name;
@@ -83,8 +74,8 @@
 	  inst.setMustBeFresh (m_mustBeFresh);
 	  
 	  m_face.expressInterest (inst,
-				  ndn::func_lib::bind (&Consumer::on_data, this, _1, _2),
-				  ndn::func_lib::bind (&Consumer::on_timeout, this, _1));
+				  ndn::bind (&Consumer::on_data, this, _1, _2),
+				  ndn::bind (&Consumer::on_timeout, this, _1));
 	}
       
       // processEvents will block until the requested data received or timeout occurs
@@ -97,10 +88,10 @@
 }
 
 void
-Consumer::on_data (const ndn::ptr_lib::shared_ptr<const ndn::Interest>& interest, const ndn::ptr_lib::shared_ptr<ndn::Data>& data)
+Consumer::on_data (const ndn::Interest& interest, ndn::Data& data)
 {
-  const ndn::Block& content = data->getContent ();
-  const ndn::Name& name = data->getName ();
+  const ndn::Block& content = data.getContent ();
+  const ndn::Name& name = data.getName ();
 
   if (m_output)
     {
@@ -124,14 +115,14 @@
       inst.setMustBeFresh (m_mustBeFresh);
       
       m_face.expressInterest (inst,
-			      ndn::func_lib::bind (&Consumer::on_data, this, _1, _2),
-			      ndn::func_lib::bind (&Consumer::on_timeout, this, _1));  
+			      ndn::bind (&Consumer::on_data, this, _1, _2),
+			      ndn::bind (&Consumer::on_timeout, this, _1));  
     }
 }
 
 
 void
-Consumer::on_timeout (const ndn::ptr_lib::shared_ptr<const ndn::Interest>& interest)
+Consumer::on_timeout (const ndn::Interest& interest)
 {
   //XXX: currently no retrans
   std::cerr << "TIMEOUT: last interest sent for segment #" << (m_next_seg - 1) << std::endl;
diff --git a/tools/ndnputchunks3.cpp b/tools/ndnputchunks3.cpp
index d3a96f5..be03453 100644
--- a/tools/ndnputchunks3.cpp
+++ b/tools/ndnputchunks3.cpp
@@ -55,12 +55,12 @@
   }
 
   void
-  onInterest (const ndn::shared_ptr<const ndn::Name>& name, const ndn::shared_ptr<const ndn::Interest>& interest)
+  onInterest (const ndn::Name& name, const ndn::Interest& interest)
   {
     if (m_verbose)
-      std::cerr << "<< I: " << *interest << std::endl;
+      std::cerr << "<< I: " << interest << std::endl;
     
-    size_t segnum = static_cast<size_t>(interest->getName ().rbegin ()->toSegment ());
+    size_t segnum = static_cast<size_t>(interest.getName ().rbegin ()->toSegment ());
 
     if (segnum < m_store.size())
       {