model: First set of major API changes and reorganizations

Main motive: change interface in Face class, resulting in need to change forwarding strategy interfaces

Refs #1005 (http://redmine.named-data.net/)
diff --git a/apps/ndn-app.cc b/apps/ndn-app.cc
index d29f509..7880849 100644
--- a/apps/ndn-app.cc
+++ b/apps/ndn-app.cc
@@ -64,8 +64,7 @@
 }
     
 App::App ()
-  : m_protocolHandler (0)
-  , m_active (false)
+  : m_active (false)
   , m_face (0)
 {
 }
@@ -85,12 +84,6 @@
   Application::DoDispose ();
 }
 
-void
-App::RegisterProtocolHandler (ProtocolHandler handler)
-{
-  m_protocolHandler = handler;
-}
-
 uint32_t
 App::GetId () const
 {
@@ -164,7 +157,7 @@
   // step 3. Destroy face
   if (m_face->GetReferenceCount () != 1)
     {
-      NS_LOG_ERROR ("Please a bug report on https://github.com/NDN-Routing/ndnSIM/issues:");
+      NS_LOG_ERROR ("Please a bug report on https://github.com/NDN-Routing/ndnSIM/issues");
       NS_LOG_ERROR ("At this point, nobody else should have referenced this face, but we have "
                     << m_face->GetReferenceCount () << " references");
 
diff --git a/apps/ndn-app.h b/apps/ndn-app.h
index 57d1d83..491cae4 100644
--- a/apps/ndn-app.h
+++ b/apps/ndn-app.h
@@ -35,9 +35,6 @@
 class Interest;
 class ContentObject;
 
-typedef Interest InterestHeader;
-typedef ContentObject ContentObjectHeader;
-
 class Face;
 
 /**
@@ -52,7 +49,8 @@
   /**
    * @brief A callback to pass packets to underlying NDN protocol
    */
-  typedef Callback<bool, const Ptr<const Packet>&> ProtocolHandler;
+  typedef Callback<bool, Ptr<const Interest>, Ptr<const Packet> > InterestHandler;
+  typedef Callback<bool, Ptr<const ContentObject>, Ptr<const Packet> > DataHandler;
   
   static TypeId GetTypeId ();
 
@@ -63,12 +61,6 @@
   virtual ~App ();
 
   /**
-   * @brief Register lower layer callback (to send interests from the application)
-   */
-  void
-  RegisterProtocolHandler (ProtocolHandler handler);
-
-  /**
    * @brief Get application ID (ID of applications face)
    */
   uint32_t
@@ -114,7 +106,6 @@
   StopApplication ();     ///< @brief Called at time specified by Stop
 
 protected:
-  ProtocolHandler m_protocolHandler; ///< @brief A callback to pass packets to underlying NDN protocol
   bool m_active;  ///< @brief Flag to indicate that application is active (set by StartApplication and StopApplication)
   Ptr<Face> m_face;   ///< @brief automatically created application face through which application communicates
 
diff --git a/examples/custom-apps/custom-app.cc b/examples/custom-apps/custom-app.cc
index 9abd7bb..7ab508c 100644
--- a/examples/custom-apps/custom-app.cc
+++ b/examples/custom-apps/custom-app.cc
@@ -94,23 +94,20 @@
   Ptr<ndn::Name> prefix = Create<ndn::Name> ("/prefix/sub"); // another way to create name
 
   // Create and configure ndn::Interest
-  ndn::Interest interestHeader;
+  Ptr<ndn::Interest> interestHeader = Create<ndn::Interest> ();
   UniformVariable rand (0,std::numeric_limits<uint32_t>::max ());
-  interestHeader.SetNonce            (rand.GetValue ());
-  interestHeader.SetName             (prefix);
-  interestHeader.SetInterestLifetime (Seconds (1.0));
-
-  // Create packet and add ndn::Interest
-  Ptr<Packet> packet = Create<Packet> ();
-  packet->AddHeader (interestHeader);
+  interestHeader->SetNonce            (rand.GetValue ());
+  interestHeader->SetName             (prefix);
+  interestHeader->SetInterestLifetime (Seconds (1.0));
 
   NS_LOG_DEBUG ("Sending Interest packet for " << *prefix);
   
   // Forward packet to lower (network) layer
-  m_protocolHandler (packet);
+  Ptr<Packet> payload = Create<Packet> ();
+  m_face->ReceiveInterest (interestHeader, payload);
 
   // Call trace (for logging purposes)
-  m_transmittedInterests (&interestHeader, this, m_face);
+  m_transmittedInterests (interestHeader, this, m_face);
 }
 
 // Callback that will be called when Interest arrives
@@ -124,23 +121,18 @@
 
   // Note that Interests send out by the app will not be sent back to the app !
   
-  ndn::ContentObject data;
-  data.SetName (Create<ndn::Name> (interest->GetName ())); // data will have the same name as Interests
-
-  ndn::ContentObjectTail trailer; // doesn't require any configuration
+  Ptr<ndn::ContentObject> data = Create<ndn::ContentObject> ();
+  data->SetName (Create<ndn::Name> (interest->GetName ())); // data will have the same name as Interests
 
   // Create packet and add header and trailer
-  Ptr<Packet> packet = Create<Packet> (1024);
-  packet->AddHeader (data);
-  packet->AddTrailer (trailer);
-
-  NS_LOG_DEBUG ("Sending ContentObject packet for " << data.GetName ());
+  NS_LOG_DEBUG ("Sending ContentObject packet for " << data->GetName ());
 
   // Forward packet to lower (network) layer
-  m_protocolHandler (packet);
+  Ptr<Packet> payload = Create<Packet> (1024);
+  m_face->ReceiveData (data, payload); 
 
   // Call trace (for logging purposes)
-  m_transmittedContentObjects (&data, packet, this, m_face);
+  m_transmittedContentObjects (data, payload, this, m_face);
 }
 
 // Callback that will be called when Data arrives
diff --git a/examples/custom-apps/ndn-api-app.cc b/examples/custom-apps/ndn-api-app.cc
index 3df6a27..90ebece 100644
--- a/examples/custom-apps/ndn-api-app.cc
+++ b/examples/custom-apps/ndn-api-app.cc
@@ -41,28 +41,28 @@
 
 ApiApp::ApiApp ()
 {
-  m_handler = CreateObject<Handler> ();
+  // m_handler = CreateObject<Handler> ();
 }
 
 void
 ApiApp::RequestData ()
 {
-  m_handler->sendInterest ("/test/prefix", boost::bind (&ApiApp::OnData
+  // m_handler->sendInterest ("/test/prefix", boost::bind (&ApiApp::OnData
 }
 
 void
 ApiApp::StartApplication ()
 {
-  m_handler->SetNode (GetNode ());
-  m_handler->StartApplication ();
+  // m_handler->SetNode (GetNode ());
+  // m_handler->StartApplication ();
   
-  Simulator::Schedule (Seconds (1), &::ns3::ndn::ApiApp::RequestData, this);
+  // Simulator::Schedule (Seconds (1), &::ns3::ndn::ApiApp::RequestData, this);
 }
 
 void
 ApiApp::StopApplication ()
 {
-  m_handler->StopApplication ();
+  // m_handler->StopApplication ();
 }
 
 } // namespace ndn
diff --git a/examples/ndn-simple-with-cs-lfu.cc b/examples/ndn-simple-with-cs-lfu.cc
index 59c9a46..c184863 100644
--- a/examples/ndn-simple-with-cs-lfu.cc
+++ b/examples/ndn-simple-with-cs-lfu.cc
@@ -47,8 +47,8 @@
 {
   os << "SimulationTime" << "\t"
      << "RealTime" << "\t"
-     << "NumberOfProcessedData" << "\t"
-     << "NumberOfProcessedInterests" << "\t"
+     // << "NumberOfProcessedData" << "\t"
+     // << "NumberOfProcessedInterests" << "\t"
      << "NumberPitEntries" << "\t"
      << "NumberCsEntries" << "\t"
      << "MemUsage" << "\n";
@@ -64,8 +64,8 @@
   os << Simulator::Now ().ToDouble (Time::S) << "\t";
   os << realTime << "\t";
 
-  os << ndn::L3Protocol::GetDataCounter () << "\t";
-  os << ndn::L3Protocol::GetInterestCounter () << "\t";
+  // os << ndn::L3Protocol::GetDataCounter () << "\t";
+  // os << ndn::L3Protocol::GetInterestCounter () << "\t";
 
   uint64_t pitCount = 0;
   uint64_t csCount = 0;
diff --git a/model/fw/ndn-forwarding-strategy.cc b/model/fw/ndn-forwarding-strategy.cc
index 9d72e74..1d6bcda 100644
--- a/model/fw/ndn-forwarding-strategy.cc
+++ b/model/fw/ndn-forwarding-strategy.cc
@@ -144,7 +144,7 @@
 void
 ForwardingStrategy::OnInterest (Ptr<Face> inFace,
                                 Ptr<const Interest> header,
-                                Ptr<const Packet> origPacket)
+                                Ptr<const Packet> payload)
 {
   m_inInterests (header, inFace);
 
@@ -227,10 +227,9 @@
 void
 ForwardingStrategy::OnData (Ptr<Face> inFace,
                             Ptr<const ContentObject> header,
-                            Ptr<Packet> payload,
-                            Ptr<const Packet> origPacket)
+                            Ptr<Packet> payload)
 {
-  NS_LOG_FUNCTION (inFace << header->GetName () << payload << origPacket);
+  NS_LOG_FUNCTION (inFace << header->GetName () << payload);
   m_inData (header, payload, inFace);
 
   // Lookup PIT entry
@@ -258,7 +257,7 @@
           m_dropData (header, payload, inFace);
         }
 
-      DidReceiveUnsolicitedData (inFace, header, payload, origPacket, cached);
+      DidReceiveUnsolicitedData (inFace, header, payload, cached);
       return;
     }
   else
@@ -280,7 +279,7 @@
           cached = m_contentStore->Add (header, payload); // no need for extra copy
         }
 
-      DidReceiveSolicitedData (inFace, header, payload, origPacket, cached);
+      DidReceiveSolicitedData (inFace, header, payload, cached);
     }
 
   while (pitEntry != 0)
@@ -289,7 +288,7 @@
       WillSatisfyPendingInterest (inFace, pitEntry);
 
       // Actually satisfy pending interest
-      SatisfyPendingInterest (inFace, header, payload, origPacket, pitEntry);
+      SatisfyPendingInterest (inFace, header, payload, pitEntry);
 
       // Lookup another PIT entry
       pitEntry = m_pit->Lookup (*header);
@@ -299,7 +298,7 @@
 void
 ForwardingStrategy::DidCreatePitEntry (Ptr<Face> inFace,
                                        Ptr<const Interest> header,
-                                       Ptr<const Packet> origPacket,
+                                       Ptr<const Packet> payload,
                                        Ptr<pit::Entry> pitEntrypitEntry)
 {
 }
@@ -307,7 +306,7 @@
 void
 ForwardingStrategy::FailedToCreatePitEntry (Ptr<Face> inFace,
                                             Ptr<const Interest> header,
-                                            Ptr<const Packet> origPacket)
+                                            Ptr<const Packet> payload)
 {
   m_dropInterests (header, inFace);
 }
@@ -315,7 +314,7 @@
 void
 ForwardingStrategy::DidReceiveDuplicateInterest (Ptr<Face> inFace,
                                                  Ptr<const Interest> header,
-                                                 Ptr<const Packet> origPacket,
+                                                 Ptr<const Packet> payload,
                                                  Ptr<pit::Entry> pitEntry)
 {
   /////////////////////////////////////////////////////////////////////////////////////////
@@ -330,7 +329,7 @@
 void
 ForwardingStrategy::DidSuppressSimilarInterest (Ptr<Face> face,
                                                 Ptr<const Interest> header,
-                                                Ptr<const Packet> origPacket,
+                                                Ptr<const Packet> payload,
                                                 Ptr<pit::Entry> pitEntry)
 {
 }
@@ -338,7 +337,7 @@
 void
 ForwardingStrategy::DidForwardSimilarInterest (Ptr<Face> inFace,
                                                Ptr<const Interest> header,
-                                               Ptr<const Packet> origPacket,
+                                               Ptr<const Packet> payload,
                                                Ptr<pit::Entry> pitEntry)
 {
 }
@@ -346,7 +345,7 @@
 void
 ForwardingStrategy::DidExhaustForwardingOptions (Ptr<Face> inFace,
                                                  Ptr<const Interest> header,
-                                                 Ptr<const Packet> origPacket,
+                                                 Ptr<const Packet> payload,
                                                  Ptr<pit::Entry> pitEntry)
 {
   NS_LOG_FUNCTION (this << boost::cref (*inFace));
@@ -370,7 +369,7 @@
 bool
 ForwardingStrategy::DetectRetransmittedInterest (Ptr<Face> inFace,
                                                  Ptr<const Interest> header,
-                                                 Ptr<const Packet> packet,
+                                                 Ptr<const Packet> payload,
                                                  Ptr<pit::Entry> pitEntry)
 {
   pit::Entry::in_iterator existingInFace = pitEntry->GetIncoming ().find (inFace);
@@ -390,7 +389,6 @@
 ForwardingStrategy::SatisfyPendingInterest (Ptr<Face> inFace,
                                             Ptr<const ContentObject> header,
                                             Ptr<const Packet> payload,
-                                            Ptr<const Packet> origPacket,
                                             Ptr<pit::Entry> pitEntry)
 {
   if (inFace != 0)
@@ -399,7 +397,7 @@
   //satisfy all pending incoming Interests
   BOOST_FOREACH (const pit::IncomingFace &incoming, pitEntry->GetIncoming ())
     {
-      bool ok = incoming.m_face->Send (origPacket->Copy ());
+      bool ok = incoming.m_face->SendData (header, payload);
 
       DidSendOutData (inFace, incoming.m_face, header, payload, origPacket, pitEntry);
       NS_LOG_DEBUG ("Satisfy " << *incoming.m_face);
@@ -425,7 +423,6 @@
 ForwardingStrategy::DidReceiveSolicitedData (Ptr<Face> inFace,
                                              Ptr<const ContentObject> header,
                                              Ptr<const Packet> payload,
-                                             Ptr<const Packet> origPacket,
                                              bool didCreateCacheEntry)
 {
   // do nothing
@@ -435,7 +432,6 @@
 ForwardingStrategy::DidReceiveUnsolicitedData (Ptr<Face> inFace,
                                                Ptr<const ContentObject> header,
                                                Ptr<const Packet> payload,
-                                               Ptr<const Packet> origPacket,
                                                bool didCreateCacheEntry)
 {
   // do nothing
@@ -459,7 +455,7 @@
 bool
 ForwardingStrategy::ShouldSuppressIncomingInterest (Ptr<Face> inFace,
                                                     Ptr<const Interest> header,
-                                                    Ptr<const Packet> origPacket,
+                                                    Ptr<const Packet> payload,
                                                     Ptr<pit::Entry> pitEntry)
 {
   bool isNew = pitEntry->GetIncoming ().size () == 0 && pitEntry->GetOutgoing ().size () == 0;
@@ -494,7 +490,7 @@
 void
 ForwardingStrategy::PropagateInterest (Ptr<Face> inFace,
                                        Ptr<const Interest> header,
-                                       Ptr<const Packet> origPacket,
+                                       Ptr<const Packet> payload,
                                        Ptr<pit::Entry> pitEntry)
 {
   bool isRetransmitted = m_detectRetransmissions && // a small guard
@@ -504,7 +500,7 @@
   /// @todo Make lifetime per incoming interface
   pitEntry->UpdateLifetime (header->GetInterestLifetime ());
 
-  bool propagated = DoPropagateInterest (inFace, header, origPacket, pitEntry);
+  bool propagated = DoPropagateInterest (inFace, header, payload, origPacket, pitEntry);
 
   if (!propagated && isRetransmitted) //give another chance if retransmitted
     {
@@ -512,7 +508,7 @@
       pitEntry->IncreaseAllowedRetxCount ();
 
       // try again
-      propagated = DoPropagateInterest (inFace, header, origPacket, pitEntry);
+      propagated = DoPropagateInterest (inFace, header, payload, origPacket, pitEntry);
     }
 
   // if (!propagated)
@@ -527,7 +523,7 @@
   // ForwardingStrategy failed to find it.
   if (!propagated && pitEntry->AreAllOutgoingInVain ())
     {
-      DidExhaustForwardingOptions (inFace, header, origPacket, pitEntry);
+      DidExhaustForwardingOptions (inFace, header, payload, origPacket, pitEntry);
     }
 }
 
@@ -535,7 +531,7 @@
 ForwardingStrategy::CanSendOutInterest (Ptr<Face> inFace,
                                         Ptr<Face> outFace,
                                         Ptr<const Interest> header,
-                                        Ptr<const Packet> origPacket,
+                                        Ptr<const Packet> payload,
                                         Ptr<pit::Entry> pitEntry)
 {
   if (outFace == inFace)
@@ -566,10 +562,10 @@
 ForwardingStrategy::TrySendOutInterest (Ptr<Face> inFace,
                                         Ptr<Face> outFace,
                                         Ptr<const Interest> header,
-                                        Ptr<const Packet> origPacket,
+                                        Ptr<const Packet> payload,
                                         Ptr<pit::Entry> pitEntry)
 {
-  if (!CanSendOutInterest (inFace, outFace, header, origPacket, pitEntry))
+  if (!CanSendOutInterest (inFace, outFace, header, payload, pitEntry))
     {
       return false;
     }
@@ -577,14 +573,13 @@
   pitEntry->AddOutgoing (outFace);
 
   //transmission
-  Ptr<Packet> packetToSend = origPacket->Copy ();
-  bool successSend = outFace->Send (packetToSend);
+  bool successSend = outFace->SendInterest (header, payload);
   if (!successSend)
     {
       m_dropInterests (header, outFace);
     }
 
-  DidSendOutInterest (inFace, outFace, header, origPacket, pitEntry);
+  DidSendOutInterest (inFace, outFace, header, payload, pitEntry);
 
   return true;
 }
@@ -593,7 +588,7 @@
 ForwardingStrategy::DidSendOutInterest (Ptr<Face> inFace,
                                         Ptr<Face> outFace,
                                         Ptr<const Interest> header,
-                                        Ptr<const Packet> origPacket,
+                                        Ptr<const Packet> payload,
                                         Ptr<pit::Entry> pitEntry)
 {
   m_outInterests (header, outFace);
@@ -604,7 +599,6 @@
                                     Ptr<Face> outFace,
                                     Ptr<const ContentObject> header,
                                     Ptr<const Packet> payload,
-                                    Ptr<const Packet> origPacket,
                                     Ptr<pit::Entry> pitEntry)
 {
   m_outData (header, payload, inFace == 0, outFace);
diff --git a/model/fw/ndn-forwarding-strategy.h b/model/fw/ndn-forwarding-strategy.h
index f077332..45ccc55 100644
--- a/model/fw/ndn-forwarding-strategy.h
+++ b/model/fw/ndn-forwarding-strategy.h
@@ -34,9 +34,6 @@
 class Interest;
 class ContentObject;
 
-typedef Interest InterestHeader;
-typedef ContentObject ContentObjectHeader;
-
 class Pit;
 namespace pit { class Entry; }
 class FibFaceMetric;
@@ -76,7 +73,7 @@
   virtual void
   OnInterest (Ptr<Face> face,
               Ptr<const Interest> header,
-              Ptr<const Packet> origPacket);
+              Ptr<const Packet> payload);
 
   /**
    * \brief Actual processing of incoming Ndn content objects
@@ -85,13 +82,11 @@
    * @param face    incoming face
    * @param header  deserialized ContentObject header
    * @param payload data packet payload
-   * @param origPacket  original packet
    */
   virtual void
   OnData (Ptr<Face> face,
           Ptr<const ContentObject> header,
-          Ptr<Packet> payload,
-          Ptr<const Packet> origPacket);
+          Ptr<Packet> payload);
 
   /**
    * @brief Event fired just before PIT entry is removed by timeout
@@ -142,7 +137,6 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    * @param pitEntry created PIT entry (incoming and outgoing face sets are empty)
    *
    * @see DidReceiveDuplicateInterest, DidSuppressSimilarInterest, DidForwardSimilarInterest, ShouldSuppressIncomingInterest
@@ -150,7 +144,7 @@
   virtual void
   DidCreatePitEntry (Ptr<Face> inFace,
                      Ptr<const Interest> header,
-                     Ptr<const Packet> origPacket,
+                     Ptr<const Packet> payload,
                      Ptr<pit::Entry> pitEntry);
 
   /**
@@ -161,12 +155,11 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    */
   virtual void
   FailedToCreatePitEntry (Ptr<Face> inFace,
                           Ptr<const Interest> header,
-                          Ptr<const Packet> origPacket);
+                          Ptr<const Packet> payload);
 
   /**
    * @brief An event that is fired every time a duplicated Interest is received
@@ -175,7 +168,6 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DidReceiveDuplicateInterest, DidSuppressSimilarInterest, DidForwardSimilarInterest, ShouldSuppressIncomingInterest
@@ -183,7 +175,7 @@
   virtual void
   DidReceiveDuplicateInterest (Ptr<Face> inFace,
                                Ptr<const Interest> header,
-                               Ptr<const Packet> origPacket,
+                               Ptr<const Packet> payload,
                                Ptr<pit::Entry> pitEntry);
 
   /**
@@ -193,7 +185,6 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DidReceiveDuplicateInterest, DidForwardSimilarInterest, ShouldSuppressIncomingInterest
@@ -201,7 +192,7 @@
   virtual void
   DidSuppressSimilarInterest (Ptr<Face> inFace,
                               Ptr<const Interest> header,
-                              Ptr<const Packet> origPacket,
+                              Ptr<const Packet> payload,
                               Ptr<pit::Entry> pitEntry);
 
   /**
@@ -211,7 +202,6 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DidReceiveDuplicateInterest, DidSuppressSimilarInterest, ShouldSuppressIncomingInterest
@@ -219,7 +209,7 @@
   virtual void
   DidForwardSimilarInterest (Ptr<Face> inFace,
                              Ptr<const Interest> header,
-                             Ptr<const Packet> origPacket,
+                             Ptr<const Packet> payload,
                              Ptr<pit::Entry> pitEntry);
 
   /**
@@ -230,7 +220,6 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    *
    * @see DetectRetransmittedInterest
@@ -238,7 +227,7 @@
   virtual void
   DidExhaustForwardingOptions (Ptr<Face> inFace,
                                Ptr<const Interest> header,
-                               Ptr<const Packet> origPacket,
+                               Ptr<const Packet> payload,
                                Ptr<pit::Entry> pitEntry);
 
   /**
@@ -251,14 +240,13 @@
    *
    * @param inFace  incoming face
    * @param header  deserialized Interest header
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    * @return true if Interest should be considered as retransmitted
    */
   virtual bool
   DetectRetransmittedInterest (Ptr<Face> inFace,
                                Ptr<const Interest> header,
-                               Ptr<const Packet> origPacket,
+                               Ptr<const Packet> payload,
                                Ptr<pit::Entry> pitEntry);
 
   /**
@@ -281,14 +269,12 @@
    * @param inFace  incoming face
    * @param header  deserialized ContentObject header
    * @param payload ContentObject payload
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    */
   virtual void
   SatisfyPendingInterest (Ptr<Face> inFace, // 0 allowed (from cache)
                           Ptr<const ContentObject> header,
                           Ptr<const Packet> payload,
-                          Ptr<const Packet> origPacket,
                           Ptr<pit::Entry> pitEntry);
 
   /**
@@ -298,7 +284,6 @@
    * @param outFace  outgoing face
    * @param header  deserialized ContentObject header
    * @param payload ContentObject payload
-   * @param origPacket  original packet
    * @param pitEntry an existing PIT entry, corresponding to the duplicated Interest
    */
   virtual void
@@ -306,7 +291,6 @@
                   Ptr<Face> outFace,
                   Ptr<const ContentObject> header,
                   Ptr<const Packet> payload,
-                  Ptr<const Packet> origPacket,
                   Ptr<pit::Entry> pitEntry);
 
   /**
@@ -315,14 +299,12 @@
    * @param inFace  incoming face
    * @param header  deserialized ContentObject header
    * @param payload ContentObject payload
-   * @param origPacket  original packet
    * @param didCreateCacheEntry flag indicating whether a cache entry was added for this data packet or not (e.g., packet already exists in cache)
    */
   virtual void
   DidReceiveSolicitedData (Ptr<Face> inFace,
                            Ptr<const ContentObject> header,
                            Ptr<const Packet> payload,
-                           Ptr<const Packet> origPacket,
                            bool didCreateCacheEntry);
 
   /**
@@ -334,14 +316,12 @@
    * @param inFace  incoming face
    * @param header  deserialized ContentObject header
    * @param payload ContentObject payload
-   * @param origPacket  original packet
    * @param didCreateCacheEntry flag indicating whether a cache entry was added for this data packet or not (e.g., packet already exists in cache)
    */
   virtual void
   DidReceiveUnsolicitedData (Ptr<Face> inFace,
                              Ptr<const ContentObject> header,
                              Ptr<const Packet> payload,
-                             Ptr<const Packet> origPacket,
                              bool didCreateCacheEntry);
 
   /**
@@ -355,12 +335,11 @@
    * @param inFace  incoming face
    * @param header  deserialized ContentObject header
    * @param payload ContentObject payload
-   * @param origPacket  original packet
    */
   virtual bool
   ShouldSuppressIncomingInterest (Ptr<Face> inFace,
                                   Ptr<const Interest> header,
-                                  Ptr<const Packet> origPacket,
+                                  Ptr<const Packet> payload,
                                   Ptr<pit::Entry> pitEntry);
 
   /**
@@ -374,7 +353,6 @@
    * @param inFace     incoming face of the Interest
    * @param outFace    proposed outgoing face of the Interest
    * @param header     parsed Interest header
-   * @param origPacket original Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @see DetectRetransmittedInterest
@@ -383,7 +361,7 @@
   CanSendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
                       Ptr<const Interest> header,
-                      Ptr<const Packet> origPacket,
+                      Ptr<const Packet> payload,
                       Ptr<pit::Entry> pitEntry);
 
   /**
@@ -394,7 +372,6 @@
    * @param inFace     incoming face of the Interest
    * @param outFace    proposed outgoing face of the Interest
    * @param header     parsed Interest header
-   * @param origPacket original Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @see CanSendOutInterest
@@ -403,7 +380,7 @@
   TrySendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
                       Ptr<const Interest> header,
-                      Ptr<const Packet> origPacket,
+                      Ptr<const Packet> payload,
                       Ptr<pit::Entry> pitEntry);
 
   /**
@@ -412,14 +389,12 @@
    * @param inFace     incoming face of the Interest
    * @param outFace    outgoing face of the Interest
    * @param header     parsed Interest header
-   * @param origPacket original Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    */
   virtual void
   DidSendOutInterest (Ptr<Face> inFace,
                       Ptr<Face> outFace,
                       Ptr<const Interest> header,
-                      Ptr<const Packet> origPacket,
                       Ptr<pit::Entry> pitEntry);
 
   /**
@@ -430,7 +405,6 @@
    *
    * @param inFace     incoming face
    * @param header     Interest header
-   * @param origPacket original Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @see DoPropagateInterest
@@ -438,7 +412,7 @@
   virtual void
   PropagateInterest (Ptr<Face> inFace,
                      Ptr<const Interest> header,
-                     Ptr<const Packet> origPacket,
+                     Ptr<const Packet> payload,
                      Ptr<pit::Entry> pitEntry);
 
   /**
@@ -453,7 +427,6 @@
    *
    * @param inFace     incoming face
    * @param header     Interest header
-   * @param origPacket original Interest packet
    * @param pitEntry   reference to PIT entry (reference to corresponding FIB entry inside)
    *
    * @return true if interest was successfully propagated, false if all options have failed
@@ -463,7 +436,7 @@
   virtual bool
   DoPropagateInterest (Ptr<Face> inFace,
                        Ptr<const Interest> header,
-                       Ptr<const Packet> origPacket,
+                       Ptr<const Packet> payload,
                        Ptr<pit::Entry> pitEntry) = 0;
 
 protected:
@@ -480,13 +453,13 @@
   bool m_cacheUnsolicitedData;
   bool m_detectRetransmissions;
 
-  TracedCallback<Ptr<const Interest>,
+  TracedCallback<Ptr<const Interest>, Ptr<const Packet>,
                  Ptr<const Face> > m_outInterests; ///< @brief Transmitted interests trace
 
-  TracedCallback<Ptr<const Interest>,
+  TracedCallback<Ptr<const Interest>, Ptr<const Packet>,
                  Ptr<const Face> > m_inInterests; ///< @brief trace of incoming Interests
 
-  TracedCallback<Ptr<const Interest>,
+  TracedCallback<Ptr<const Interest>, Ptr<const Packet>,
                  Ptr<const Face> > m_dropInterests; ///< @brief trace of dropped Interests
 
   ////////////////////////////////////////////////////////////////////
diff --git a/model/ndn-app-face.cc b/model/ndn-app-face.cc
index 669f9a8..23712f2 100644
--- a/model/ndn-app-face.cc
+++ b/model/ndn-app-face.cc
@@ -81,61 +81,36 @@
   return *((AppFace*)0);
 }
 
-
-void
-AppFace::RegisterProtocolHandler (ProtocolHandler handler)
+bool
+Face::SendInterest (Ptr<const Interest> interest, Ptr<const Packet> packet)
 {
-  NS_LOG_FUNCTION (this);
+  NS_LOG_FUNCTION (this << interest << packet);
 
-  Face::RegisterProtocolHandler (handler);
+  if (!IsUp ())
+    {
+      return false;
+    }
 
-  m_app->RegisterProtocolHandler (MakeCallback (&Face::Receive, this));
+  if (interest->GetNack () > 0)
+    m_app->OnNack (interest, packet);
+  else
+    m_app->OnInterest (interest, packet);
+  
+  return true;
 }
 
 bool
-AppFace::SendImpl (Ptr<Packet> p)
+Face::SendData (Ptr<const ContentObject> data, Ptr<const Packet> packet)
 {
-  NS_LOG_FUNCTION (this << p);
+  NS_LOG_FUNCTION (this << data << packet);
 
-  try
+  if (!IsUp ())
     {
-      HeaderHelper::Type type = HeaderHelper::GetNdnHeaderType (p);
-      switch (type)
-        {
-        case HeaderHelper::INTEREST_NDNSIM:
-          {
-            Ptr<Interest> header = Create<Interest> ();
-            p->RemoveHeader (*header);
-
-            if (header->GetNack () > 0)
-              m_app->OnNack (header, p);
-            else
-              m_app->OnInterest (header, p);
-          
-            break;
-          }
-        case HeaderHelper::CONTENT_OBJECT_NDNSIM:
-          {
-            static ContentObjectTail tail;
-            Ptr<ContentObject> header = Create<ContentObject> ();
-            p->RemoveHeader (*header);
-            p->RemoveTrailer (tail);
-            m_app->OnContentObject (header, p/*payload*/);
-          
-            break;
-          }
-        default:
-          NS_FATAL_ERROR ("ccnb support is currently broken");
-          break;
-        }
-      
-      return true;
-    }
-  catch (UnknownHeaderException)
-    {
-      NS_LOG_ERROR ("Unknown header type");
       return false;
     }
+
+  m_app->OnContentObject (data, packet);
+  return true;
 }
 
 std::ostream&
diff --git a/model/ndn-app-face.h b/model/ndn-app-face.h
index 3a90f11..4b47fda 100644
--- a/model/ndn-app-face.h
+++ b/model/ndn-app-face.h
@@ -63,12 +63,11 @@
   
   ////////////////////////////////////////////////////////////////////
   // methods overloaded from Face
-  virtual void
-  RegisterProtocolHandler (ProtocolHandler handler);
-
-protected:
   virtual bool
-  SendImpl (Ptr<Packet> p);
+  SendInterest (Ptr<const Interest> interest, Ptr<const Packet> packet);
+
+  virtual bool
+  SendData (Ptr<const ContentObject> data, Ptr<const Packet> packet);
 
 public:
   virtual std::ostream&
diff --git a/model/ndn-content-object.h b/model/ndn-content-object.h
index 9803efe..a5d534c 100644
--- a/model/ndn-content-object.h
+++ b/model/ndn-content-object.h
@@ -170,26 +170,6 @@
   uint32_t m_signature; // 0, means no signature, any other value application dependent (not a real signature)
 };
 
-typedef ContentObject ContentObjectHeader;
-
-/**
- * ContentObjectTail for compatibility with other packet formats
- */
-class ContentObjectTail : public Trailer
-{
-public:
-  ContentObjectTail ();
-  //////////////////////////////////////////////////////////////////
-
-  static TypeId GetTypeId (void); ///< @brief Get TypeId
-  virtual TypeId GetInstanceTypeId (void) const; ///< @brief Get TypeId of the instance
-  virtual void Print (std::ostream &os) const; ///< @brief Print out information about Tail into the stream
-  virtual uint32_t GetSerializedSize (void) const; ///< @brief Get size necessary to serialize the Tail
-  virtual void Serialize (Buffer::Iterator start) const; ///< @brief Serialize the Tail
-  virtual uint32_t Deserialize (Buffer::Iterator start); ///< @brief Deserialize the Tail
-};
-
-
 /**
  * @ingroup ndn-exceptions
  * @brief Class for ContentObject parsing exception
diff --git a/model/ndn-face.cc b/model/ndn-face.cc
index 625af55..b5f7c34 100644
--- a/model/ndn-face.cc
+++ b/model/ndn-face.cc
@@ -54,13 +54,6 @@
                    UintegerValue (0),
                    MakeUintegerAccessor (&Face::m_id),
                    MakeUintegerChecker<uint32_t> ())
-
-    .AddTraceSource ("NdnTx", "Transmitted packet trace",
-                     MakeTraceSourceAccessor (&Face::m_txTrace))
-    .AddTraceSource ("NdnRx", "Received packet trace",
-                     MakeTraceSourceAccessor (&Face::m_rxTrace))
-    .AddTraceSource ("NdnDrop", "Dropped packet trace",
-                     MakeTraceSourceAccessor (&Face::m_dropTrace))
     ;
   return tid;
 }
@@ -104,25 +97,59 @@
 }
 
 void
-Face::RegisterProtocolHandler (ProtocolHandler handler)
+Face::RegisterProtocolHandlers (const InterestHandler &interestHandler, const DataHandler &dataHandler)
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  m_protocolHandler = handler;
+  m_upstreamInterestHandler = interestHandler;
+  m_upstreamDataHandler = dataHandler;
+}
+
+void
+Face::UnRegisterProtocolHandlers ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  m_upstreamInterestHandler = MakeNullCallback< void, const Ptr<Face>&, Ptr<Interest>, Ptr<Packet> > ();
+  m_upstreamDataHandler = MakeNullCallback< void, const Ptr<Face>&, Ptr<ContentObject>, Ptr<Packet> > ();
+}
+
+
+bool
+Face::SendInterest (Ptr<const Interest> interest, Ptr<const Packet> packet)
+{
+  NS_LOG_FUNCTION (this << interest << packet);
+
+  if (!IsUp ())
+    {
+      return false;
+    }
+
+  Ptr<Packet> copy = packet->Copy ();
+  copy->AddHeader (*interest);
+
+  return Send (copy);
+}
+
+bool
+Face::SendData (Ptr<const ContentObject> data, Ptr<const Packet> packet)
+{
+  NS_LOG_FUNCTION (this << data << packet);
+
+  if (!IsUp ())
+    {
+      return false;
+    }
+
+  Ptr<Packet> copy = packet->Copy ();
+  copy->AddHeader (*data);
+  
+  return Send (copy);
 }
 
 bool
 Face::Send (Ptr<Packet> packet)
 {
-  NS_LOG_FUNCTION (boost::cref (*this) << packet << packet->GetSize ());
-  NS_LOG_DEBUG (*packet);
-
-  if (!IsUp ())
-    {
-      m_dropTrace (packet);
-      return false;
-    }
-
   FwHopCountTag hopCount;
   bool tagExists = packet->RemovePacketTag (hopCount);
   if (tagExists)
@@ -131,23 +158,13 @@
       packet->AddPacketTag (hopCount);
     }
 
-  bool ok = SendImpl (packet);
-  if (ok)
-    {
-      m_txTrace (packet);
-      return true;
-    }
-  else
-    {
-      m_dropTrace (packet);
-      return false;
-    }
+  return true;
 }
 
 bool
-Face::Receive (const Ptr<const Packet> &packet)
+Face::Receive (Ptr<const Packet> p)
 {
-  NS_LOG_FUNCTION (boost::cref (*this) << packet << packet->GetSize ());
+  NS_LOG_FUNCTION (this << packet << packet->GetSize ());
 
   if (!IsUp ())
     {
@@ -155,9 +172,65 @@
       return false;
     }
 
-  m_rxTrace (packet);
-  m_protocolHandler (this, packet);
+  Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
+  try
+    {
+      HeaderHelper::Type type = HeaderHelper::GetNdnHeaderType (packet);
+      switch (type)
+        {
+        case HeaderHelper::INTEREST_NDNSIM:
+          {
+            Ptr<Interest> interest = Create<Interest> ();
+            packet->RemoveHeader (*header);
 
+            return ReceiveInterest (interest, packet/*payload*/);
+          }
+        case HeaderHelper::CONTENT_OBJECT_NDNSIM:
+          {
+            Ptr<ContentObject> data = Create<ContentObject> ();
+            packet->RemoveHeader (*header);
+
+            return ReceiveData (data, packet);
+          }
+        case HeaderHelper::INTEREST_CCNB:
+        case HeaderHelper::CONTENT_OBJECT_CCNB:
+          NS_FATAL_ERROR ("ccnb support is broken in this implementation");
+          return false;
+        }
+
+      // exception will be thrown if packet is not recognized
+    }
+  catch (UnknownHeaderException)
+    {
+      NS_ASSERT_MSG (false, "Unknown NDN header. Should not happen");
+      NS_LOG_ERROR ("Unknown NDN header. Should not happen");
+      return false;
+    }
+}
+
+bool
+Face::ReceiveInterest (Ptr<Interest> interest, Ptr<Packet> payload)
+{
+  if (!IsUp ())
+    {
+      // no tracing here. If we were off while receiving, we shouldn't even know that something was there
+      return false;
+    }
+
+  m_upstreamInterestHandler (this, interest, payload);
+  return true;
+}
+
+bool
+Face::ReceiveData (Ptr<ContentObject> data, Ptr<Packet> payload)
+{
+  if (!IsUp ())
+    {
+      // no tracing here. If we were off while receiving, we shouldn't even know that something was there
+      return false;
+    }
+
+  m_upstreamDataHandler (this, data, payload);
   return true;
 }
 
@@ -171,7 +244,6 @@
 uint16_t
 Face::GetMetric (void) const
 {
-  NS_LOG_FUNCTION_NOARGS ();
   return m_metric;
 }
 
@@ -181,20 +253,6 @@
  * (where the device may be down but face state is still up).
  */
 
-bool
-Face::IsUp (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_ifup;
-}
-
-void
-Face::SetUp (bool up/* = true*/)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_ifup = up;
-}
-
 void
 Face::SetFlags (uint32_t flags)
 {
diff --git a/model/ndn-face.h b/model/ndn-face.h
index 97c75f9..edcd5d2 100644
--- a/model/ndn-face.h
+++ b/model/ndn-face.h
@@ -38,6 +38,9 @@
 
 namespace ndn {
 
+class Interest;
+class ContentObject;
+
 /**
  * \ingroup ndn
  * \defgroup ndn-face Faces
@@ -60,12 +63,13 @@
   GetTypeId ();
 
   /**
-   * \brief NDN protocol handler
+   * \brief NDN protocol handlers
    *
    * \param face Face from which packet has been received
    * \param packet Original packet
    */
-  typedef Callback<void,const Ptr<Face>&,const Ptr<const Packet>& > ProtocolHandler;
+  typedef Callback<void, Ptr<Face>, Ptr<Interest>, Ptr<Packet> > InterestHandler;
+  typedef Callback<void, Ptr<Face>, Ptr<ContentObject>, Ptr<Packet> > DataHandler;
 
   /**
    * \brief Default constructor
@@ -87,27 +91,51 @@
    * This method should call protocol-dependent registration function
    */
   virtual void
-  RegisterProtocolHandler (ProtocolHandler handler);
+  RegisterProtocolHandlers (const InterestHandler &interestHandler, const DataHandler &dataHandler);
 
   /**
-   * \brief Send packet on a face
+   * \brief Un-Register callback to call when new packet arrives on the face
    *
-   * This method will be called by lower layers to send data to device or application
-   *
-   * \param p smart pointer to a packet to send
-   *
-   * @return false if either limit is reached
+   * This method should call protocol-dependent registration function
    */
-  bool
-  Send (Ptr<Packet> p);
+  virtual void
+  UnRegisterProtocolHandlers ();
 
   /**
-   * \brief Receive packet from application or another node and forward it to the Ndn stack
+   * @brief Send out interest through the face
+   * @param interest Interest to send out
+   * @param packet "payload" that is attached to the interest (can carry some packet tags)
    *
-   * \todo The only reason for this call is to handle tracing, if requested
+   * @returns true if interest is considered to be send out (enqueued)
    */
-  bool
-  Receive (const Ptr<const Packet> &p);
+  virtual bool
+  SendInterest (Ptr<const Interest> interest, Ptr<const Packet> packet);
+
+  /**
+   * @brief Send out Dat packet through the face
+   * @param data Data packet to send out
+   * @param packet Data packet payload, can also carry packet tags
+   *
+   * @returns true if Data packet is considered to be send out (enqueued)
+   */
+  virtual bool
+  SendData (Ptr<const ContentObject> data, Ptr<const Packet> packet);
+
+  /**
+   * \brief Receive interest from application or another node and forward it up to the NDN stack
+   *
+   * By default it is called from inside Receive method, but can be used directly, if appropriate
+   */
+  virtual bool
+  ReceiveInterest (Ptr<Interest> interest, Ptr<Packet> payload);
+
+  /**
+   * \brief Receive Data packet from application or another node and forward it up to the NDN stack
+   *
+   * By default it is called from inside Receive method, but can be used directly, if appropriate
+   */
+  virtual bool
+  ReceiveData (Ptr<ContentObject> data, Ptr<Packet> payload);
   ////////////////////////////////////////////////////////////////////
 
   /**
@@ -135,13 +163,13 @@
   /**
    * \brief Enable or disable this face
    */
-  virtual void
+  inline void
   SetUp (bool up = true);
 
   /**
    * \brief Returns true if this face is enabled, false otherwise.
    */
-  virtual bool
+  inline bool
   IsUp () const;
 
   /**
@@ -216,13 +244,20 @@
 
 protected:
   /**
-   * \brief Send packet on a face (actual implementation)
-   *
-   * \param p smart pointer to a packet to send
+   * @brief Send packet down to the stack (towards app or network)
    */
   virtual bool
-  SendImpl (Ptr<Packet> p) = 0;
+  Send (Ptr<Packet> packet);
+  
+  /**
+   * @brief Send packet up to the stack (towards forwarding strategy)
+   */
+  virtual bool
+  Receive (Ptr<const Packet> p);
 
+  /**
+   * @brief Set face flags
+   */
   void
   SetFlags (uint32_t flags);
 
@@ -234,20 +269,29 @@
   Ptr<Node> m_node; ///< \brief Smart pointer to Node
 
 private:
-  ProtocolHandler m_protocolHandler; ///< Callback via which packets are getting send to Ndn stack
-  bool m_ifup; ///< \brief flag indicating that the interface is UP
+  InterestHandler m_upstreamInterestHandler;
+  DataHandler m_upstreamDataHandler;
+  bool m_ifup;
   uint32_t m_id; ///< \brief id of the interface in NDN stack (per-node uniqueness)
   uint32_t m_metric; ///< \brief metric of the face
-  uint32_t m_flags;
-
-  TracedCallback<Ptr<const Packet> > m_txTrace;
-  TracedCallback<Ptr<const Packet> > m_rxTrace;
-  TracedCallback<Ptr<const Packet> > m_dropTrace;
+  uint32_t m_flags; ///< @brief faces flags (e.g., APPLICATION)
 };
 
 std::ostream&
 operator<< (std::ostream& os, const Face &face);
 
+inline bool
+Face::IsUp (void) const
+{
+  return m_ifup;
+}
+
+inline void
+Face::SetUp (bool up/* = true*/)
+{
+  m_ifup = up;
+}
+
 inline uint32_t
 Face::GetFlags () const
 {
diff --git a/model/ndn-interest.h b/model/ndn-interest.h
index c5808f7..88d1159 100644
--- a/model/ndn-interest.h
+++ b/model/ndn-interest.h
@@ -265,8 +265,6 @@
   uint8_t  m_nackType;           ///< Negative Acknowledgement type
 };
 
-typedef Interest InterestHeader;
-
 /**
  * @ingroup ndn-exceptions
  * @brief Class for Interest parsing exception 
diff --git a/model/ndn-l3-protocol.cc b/model/ndn-l3-protocol.cc
index 5593040..272e445 100644
--- a/model/ndn-l3-protocol.cc
+++ b/model/ndn-l3-protocol.cc
@@ -108,28 +108,14 @@
       m_node = GetObject<Node> ();
       if (m_node != 0)
         {
-          // NS_ASSERT_MSG (m_pit != 0 && m_fib != 0 && m_contentStore != 0 && m_forwardingStrategy != 0,
-          //                "PIT, FIB, and ContentStore should be aggregated before L3Protocol");
           NS_ASSERT_MSG (m_forwardingStrategy != 0,
                          "Forwarding strategy should be aggregated before L3Protocol");
         }
     }
-  // if (m_pit == 0)
-  //   {
-  //     m_pit = GetObject<Pit> ();
-  //   }
-  // if (m_fib == 0)
-  //   {
-  //     m_fib = GetObject<Fib> ();
-  //   }
   if (m_forwardingStrategy == 0)
     {
       m_forwardingStrategy = GetObject<ForwardingStrategy> ();
     }
-  // if (m_contentStore == 0)
-  //   {
-  //     m_contentStore = GetObject<ContentStore> ();
-  //   }
 
   Object::NotifyNewAggregate ();
 }
@@ -160,7 +146,8 @@
   face->SetId (m_faceCounter); // sets a unique ID of the face. This ID serves only informational purposes
 
   // ask face to register in lower-layer stack
-  face->RegisterProtocolHandler (MakeCallback (&L3Protocol::Receive, this));
+  face->RegisterProtocolHandlers (MakeCallback (&ForwardingStrategy::OnInterest, m_forwardingStrategy),
+                                  MakeCallback (&ForwardingStrategy::OnData, m_forwardingStrategy));
 
   m_faces.push_back (face);
   m_faceCounter++;
@@ -173,7 +160,7 @@
 L3Protocol::RemoveFace (Ptr<Face> face)
 {
   // ask face to register in lower-layer stack
-  face->RegisterProtocolHandler (MakeNullCallback<void,const Ptr<Face>&,const Ptr<const Packet>&> ());
+  face->UnRegisterProtocolHandlers ();
   Ptr<Pit> pit = GetObject<Pit> ();
 
   // just to be on a safe side. Do the process in two steps
@@ -241,76 +228,5 @@
   return m_faces.size ();
 }
 
-// Callback from lower layer
-void
-L3Protocol::Receive (const Ptr<Face> &face, const Ptr<const Packet> &p)
-{
-  if (!face->IsUp ())
-    return;
-
-  NS_LOG_DEBUG (*p);
-
-  NS_LOG_LOGIC ("Packet from face " << *face << " received on node " <<  m_node->GetId ());
-
-  Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
-  try
-    {
-      HeaderHelper::Type type = HeaderHelper::GetNdnHeaderType (p);
-      switch (type)
-        {
-        case HeaderHelper::INTEREST_NDNSIM:
-          {
-            s_interestCounter ++;
-            Ptr<Interest> header = Create<Interest> ();
-
-            // Deserialization. Exception may be thrown
-            packet->RemoveHeader (*header);
-
-            // this assert is legitimately failing with CSMA-style devices, when interest size is less then
-            // minimally required 46 bytes.  At the same time, it is safe to ignore the fact
-            if (packet->GetSize () != 0)
-              {
-                NS_LOG_WARN ("Payload size is not zero. Valid only for CSMA (Ethernet) devices");
-              }
-            // NS_ASSERT_MSG (packet->GetSize () == 0, "Payload of Interests should be zero");
-
-            m_forwardingStrategy->OnInterest (face, header, p/*original packet*/);
-            // if (header->GetNack () > 0)
-            //   OnNack (face, header, p/*original packet*/);
-            // else
-            //   OnInterest (face, header, p/*original packet*/);
-            break;
-          }
-        case HeaderHelper::CONTENT_OBJECT_NDNSIM:
-          {
-            s_dataCounter ++;
-            Ptr<ContentObject> header = Create<ContentObject> ();
-
-            static ContentObjectTail contentObjectTrailer; //there is no data in this object
-
-            // Deserialization. Exception may be thrown
-            packet->RemoveHeader (*header);
-            packet->RemoveTrailer (contentObjectTrailer);
-
-            m_forwardingStrategy->OnData (face, header, packet/*payload*/, p/*original packet*/);
-            break;
-          }
-        case HeaderHelper::INTEREST_CCNB:
-        case HeaderHelper::CONTENT_OBJECT_CCNB:
-          NS_FATAL_ERROR ("ccnb support is broken in this implementation");
-          break;
-        }
-
-      // exception will be thrown if packet is not recognized
-    }
-  catch (UnknownHeaderException)
-    {
-      NS_ASSERT_MSG (false, "Unknown NDN header. Should not happen");
-      NS_LOG_ERROR ("Unknown NDN header. Should not happen");
-      return;
-    }
-}
-
-
 } //namespace ndn
 } //namespace ns3
diff --git a/model/ndn-l3-protocol.h b/model/ndn-l3-protocol.h
index 2505a63..292de13 100644
--- a/model/ndn-l3-protocol.h
+++ b/model/ndn-l3-protocol.h
@@ -137,16 +137,6 @@
   virtual Ptr<Face>
   GetFaceByNetDevice (Ptr<NetDevice> netDevice) const;
 
-  static uint64_t
-  GetInterestCounter ();
-
-  static uint64_t
-  GetDataCounter ();
-  
-private:
-  void
-  Receive (const Ptr<Face> &face, const Ptr<const Packet> &p);
-
 protected:
   virtual void DoDispose (void); ///< @brief Do cleanup
 
@@ -164,9 +154,6 @@
   uint32_t m_faceCounter; ///< \brief counter of faces. Increased every time a new face is added to the stack
   FaceList m_faces; ///< \brief list of faces that belongs to ndn stack on this node
 
-  static uint64_t s_interestCounter;
-  static uint64_t s_dataCounter;
-  
   // These objects are aggregated, but for optimization, get them here
   Ptr<Node> m_node; ///< \brief node on which ndn stack is installed
   Ptr<ForwardingStrategy> m_forwardingStrategy; ///< \brief smart pointer to the selected forwarding strategy
diff --git a/model/ndn-net-device-face.cc b/model/ndn-net-device-face.cc
index 67dc659..03a9cca 100644
--- a/model/ndn-net-device-face.cc
+++ b/model/ndn-net-device-face.cc
@@ -82,19 +82,31 @@
 }
 
 void
-NetDeviceFace::RegisterProtocolHandler (ProtocolHandler handler)
+NetDeviceFace::RegisterProtocolHandlers (const InterestHandler &interestHandler, const DataHandler &dataHandler)
 {
   NS_LOG_FUNCTION (this);
 
-  Face::RegisterProtocolHandler (handler);
+  Face::RegisterProtocolHandlers (interestHandler, dataHandler);
 
   m_node->RegisterProtocolHandler (MakeCallback (&NetDeviceFace::ReceiveFromNetDevice, this),
                                    L3Protocol::ETHERNET_FRAME_TYPE, m_netDevice, true/*promiscuous mode*/);
 }
 
-bool
-NetDeviceFace::SendImpl (Ptr<Packet> packet)
+void
+NetDeviceFace:: UnRegisterProtocolHandlers ()
 {
+  m_node->UnRegisterProtocolHandler (MakeCallback (&NetDeviceFace::ReceiveFromNetDevice, this));
+  Face::UnRegisterProtocolHandlers ();
+}
+
+bool
+NetDeviceFace::Send (Ptr<Packet> packet)
+{
+  if (!Face::Send ())
+    {
+      return false;
+    }
+  
   NS_LOG_FUNCTION (this << packet);
 
   NS_ASSERT_MSG (packet->GetSize () <= m_netDevice->GetMtu (),
diff --git a/model/ndn-net-device-face.h b/model/ndn-net-device-face.h
index 651a7ae..d001015 100644
--- a/model/ndn-net-device-face.h
+++ b/model/ndn-net-device-face.h
@@ -60,12 +60,14 @@
   ////////////////////////////////////////////////////////////////////
   // methods overloaded from NdnFace
   virtual void
-  RegisterProtocolHandler (ProtocolHandler handler);
+  RegisterProtocolHandlers (const InterestHandler &interestHandler, const DataHandler &dataHandler);
+
+  virtual void
+  UnRegisterProtocolHandlers ();
   
 protected:
-  // also from NdnFace
   virtual bool
-  SendImpl (Ptr<Packet> p);
+  Send (Ptr<Packet> p);
 
 public:
   /**
diff --git a/ndn.cxx/ndn-api-face.cc b/ndn.cxx/ndn-api-face.cc
new file mode 100644
index 0000000..6b80251
--- /dev/null
+++ b/ndn.cxx/ndn-api-face.cc
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ */
+
+#include "ndn-api-face.h"
+
+#include <boost/throw_exception.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
+
+#include <ns3/packet.h>
+
+#include <ns3/ndn-interest.h>
+#include <ns3/ndn-content-object.h>
+#include <ns3/ndn-face.h>
+#include <ns3/ndn-fib.h>
+#include <ns3/log.h>
+
+typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
+typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;
+
+using namespace std;
+using namespace boost;
+using namespace ns3;
+
+#define INIT_LOGGER NS_LOG_COMPONENT_DEFINE
+#define _LOG_DEBUG NS_LOG_DEBUG
+#define _LOG_TRACE NS_LOG_TRACE
+#define _LOG_INFO NS_LOG_INFO
+
+
+INIT_LOGGER ("ndn.ApiFace");
+
+namespace ns3 {
+namespace ndn {
+
+// ApiFace::ApiFace()
+//   : m_rand (0, std::numeric_limits<uint32_t>::max ())
+// {
+// }
+
+// ApiFace::~ApiFace()
+// {
+// }
+
+// int
+// ApiFace::publishRawData (const std::string &name, const char *buf, size_t len, int freshness)
+// {
+//   // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
+//   _LOG_INFO (">> publishRawData " << name);
+
+//   static ndn::ContentObjectTail trailer;
+  
+//   ndn::ContentObject data;
+//   data.SetName (name);
+//   data.SetFreshness (Seconds (freshness));
+
+//   Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t*> (buf), len);
+//   // packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::DATA));
+//   packet->AddHeader (data);
+//   packet->AddTrailer (trailer);
+
+//   m_protocolHandler (packet);
+
+//   m_transmittedContentObjects (&data, packet, this, m_face);
+
+//   return 0;
+// }
+
+
+// void
+// RawDataCallback2StringDataCallback (ApiFace::StringDataCallback callback, std::string str, const char *buf, size_t len)
+// {
+//   callback (str, string (buf, len));
+// }
+
+// int
+// ApiFace::sendInterestForString (const std::string &strInterest, const StringDataCallback &strDataCallback/*, int retry*/)
+// {
+//   return sendInterest (strInterest, boost::bind (RawDataCallback2StringDataCallback, strDataCallback, _1, _2, _3));
+// }
+
+// int ApiFace::sendInterest (const string &strInterest, const RawDataCallback &rawDataCallback)
+// {
+//   // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
+//   _LOG_INFO (">> I " << strInterest);
+//   Ptr<ndn::Name> name = Create<ndn::Name> (strInterest);
+
+//   ndn::Interest interestHeader;
+//   interestHeader.SetNonce            (m_rand.GetValue ());
+//   interestHeader.SetName             (*name);
+//   interestHeader.SetInterestLifetime (Seconds (9.9)); // really long-lived interests
+
+//   Ptr<Packet> packet = Create<Packet> ();
+//   // packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::INTEREST));
+//   packet->AddHeader (interestHeader);
+
+//   // NS_LOG_DEBUG (interestHeader);
+  
+//   // Record the callback
+//   FilterEntryContainer<RawDataCallback>::iterator entry = m_dataCallbacks.find_exact (*name);
+//   if (entry == m_dataCallbacks.end ())
+//     {
+//       pair<FilterEntryContainer<RawDataCallback>::iterator, bool> status =
+//         m_dataCallbacks.insert (*name, Create< FilterEntry<RawDataCallback> > (name));
+
+//       entry = status.first;
+//     }
+//   entry->payload ()->AddCallback (rawDataCallback);
+
+//   m_protocolHanler (packet);
+//   m_transmittedInterests (&interestHeader, this, m_face);
+  
+//   return 0;
+// }
+
+// int ApiFace::setInterestFilter (const string &prefix, const InterestCallback &interestCallback)
+// {
+//   NS_LOG_DEBUG ("== setInterestFilter " << prefix << " (" << GetNode ()->GetId () << ")");
+//   Ptr<ndn::Name> name = Create<ndn::Name> (prefix);
+
+//   FilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.find_exact (*name);
+//   if (entry == m_interestCallbacks.end ())
+//     {
+//       pair<FilterEntryContainer<InterestCallback>::iterator, bool> status =
+//         m_interestCallbacks.insert (*name, Create < FilterEntry<InterestCallback> > (name));
+
+//       entry = status.first;
+//     }
+
+//   entry->payload ()->AddCallback (interestCallback);
+
+//   // creating actual face
+//   Ptr<ndn::Fib> fib = GetNode ()->GetObject<ndn::Fib> ();
+//   Ptr<ndn::fib::Entry> fibEntry = fib->Add (name, m_face, 0);
+//   fibEntry->UpdateStatus (m_face, ndn::fib::FaceMetric::NDN_FIB_GREEN);
+
+//   return 0;
+// }
+
+// void
+// ApiFace::clearInterestFilter (const std::string &prefix)
+// {
+//   Ptr<ndn::Name> name = Create<ndn::Name> (prefix);
+
+//   FilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.find_exact (*name);
+//   if (entry == m_interestCallbacks.end ())
+//     return;
+
+//   entry->payload ()->ClearCallback ();
+// }
+
+// void
+// ApiFace::OnInterest (const Ptr<const ndn::Interest> &interest, Ptr<Packet> packet)
+// {
+//   ndn::App::OnInterest (interest, packet);
+
+//   // the app cannot set several filters for the same prefix
+//   FilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.longest_prefix_match (interest->GetName ());
+//   if (entry == m_interestCallbacks.end ())
+//     {
+//       _LOG_DEBUG ("No Interest callback set");
+//       return;
+//     }
+  
+//   entry->payload ()->m_callback (lexical_cast<string> (interest->GetName ()));  
+// }
+
+// void
+// ApiFace::OnContentObject (const Ptr<const ndn::ContentObject> &contentObject,
+//                               Ptr<Packet> payload)
+// {
+//   ndn::App::OnContentObject (contentObject, payload);
+//   NS_LOG_DEBUG ("<< D " << contentObject->GetName ());
+
+//   FilterEntryContainer<RawDataCallback>::iterator entry = m_dataCallbacks.longest_prefix_match (contentObject->GetName ());
+//   if (entry == m_dataCallbacks.end ())
+//     {
+//       _LOG_DEBUG ("No Data callback set");
+//       return;
+//     }
+
+//   while (entry != m_dataCallbacks.end ())
+//     {
+//       entry->payload ()->m_callback (lexical_cast<string> (contentObject->GetName ()), payload);
+//       m_dataCallbacks.erase (entry);
+
+//       entry = m_dataCallbacks.longest_prefix_match (contentObject->GetName ());
+//     }
+// }
+
+}
+}
diff --git a/ndn.cxx/ndn-api-face.h b/ndn.cxx/ndn-api-face.h
new file mode 100644
index 0000000..133f29c
--- /dev/null
+++ b/ndn.cxx/ndn-api-face.h
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ */
+
+#ifndef NDN_API_FACE_H
+#define NDN_API_FACE_H
+
+#include <boost/exception/all.hpp>
+#include <boost/function.hpp>
+#include <string>
+
+#include <ns3/ptr.h>
+#include <ns3/node.h>
+#include <ns3/random-variable.h>
+#include <ns3/ndn-app.h>
+#include <ns3/ndn-name.h>
+
+#include <ns3/ndnSIM/utils/trie/trie-with-policy.h>
+#include <ns3/ndnSIM/utils/trie/counting-policy.h>
+
+namespace ns3 {
+namespace ndn {
+
+template<class Callback>
+struct FilterEntry : public ns3::SimpleRefCount< FilterEntry<Callback> >
+{
+public:
+  FilterEntry (ns3::Ptr<const ns3::ndn::Name> prefix)
+    : m_prefix (prefix)
+  { }
+  
+  const ns3::ndn::Name &
+  GetPrefix () const
+  { return *m_prefix; }
+
+  void
+  AddCallback (Callback callback)
+  { 
+    m_callback = callback;
+  }
+
+  void
+  ClearCallback ()
+  {
+    m_callback = 0;
+  }
+  
+public:
+  ns3::Ptr<const ns3::ndn::Name> m_prefix; ///< \brief Prefix of the PIT entry
+  Callback m_callback;
+};
+
+
+template<class Callback>
+struct FilterEntryContainer :
+    public ns3::ndn::ndnSIM::trie_with_policy<ns3::ndn::Name,
+                                              ns3::ndn::ndnSIM::smart_pointer_payload_traits< FilterEntry<Callback> >,
+                                              ns3::ndn::ndnSIM::counting_policy_traits>
+{
+};
+
+
+struct OperationException : virtual boost::exception, virtual std::exception { };
+/**
+ * \ingroup sync
+ * @brief A handler for NDN; clients of this code do not need to deal
+ * with NDN API directly
+ */
+class ApiFace
+  // : private ns3::ndn::Face
+{
+public:
+  // typedef boost::function<void (const ndn::Name &, Ptr<Packet>)> DataCallback;
+  // typedef boost::function<void (const ndn::Name &)> InterestCallback;
+  
+  // /**
+  //  * @brief initialize the handler; a lot of things needs to be done. 1) init
+  //  * keystore 2) init keylocator 3) start a thread to hold a loop of ccn_run
+  //  *
+  //  */
+  // ApiFace (Ptr<Node> node);
+  // ~ApiFace ();
+
+  // /**
+  //  * @brief send Interest; need to grab lock m_mutex first
+  //  *
+  //  * @param name the Interest name
+  //  * @param dataCallback the callback function to deal with the returned data
+  //  * @return the return code of ccn_express_interest
+  //  */
+  // // int
+  // // sendInterestForString (const std::string &strInterest, const StringDataCallback &strDataCallback/*, int retry = 0*/);
+
+  // int
+  // sendInterest (const ndn::Name &name, const DataCallback &rawDataCallback/*, int retry = 0*/);
+  
+  // /**
+  //  * @brief set Interest filter (specify what interest you want to receive)
+  //  *
+  //  * @param prefix the prefix of Interest
+  //  * @param interestCallback the callback function to deal with the returned data
+  //  * @return the return code of ccn_set_interest_filter
+  //  */
+  // int
+  // setInterestFilter (const ndn::Name &prefix, const InterestCallback &interestCallback);
+
+  // /**
+  //  * @brief clear Interest filter
+  //  * @param prefix the prefix of Interest
+  //  */
+  // void
+  // clearInterestFilter (const std::string &prefix);
+
+  /**
+   * @brief publish data and put it to local ccn content store; need to grab
+   * lock m_mutex first
+   *
+   * @param name the name for the data object
+   * @param dataBuffer the data to be published
+   * @param freshness the freshness time for the data object
+   * @return code generated by NDN library calls, >0 if success
+   */
+  // int
+  // publishStringData (const std::string &name, const std::string &dataBuffer, int freshness)
+  // {
+  //   return publishRawData (name, dataBuffer.c_str(), dataBuffer.length(), freshness);
+  // }
+
+  // int
+  // publishRawData (const std::string &name, const char *buf, size_t len, int freshness);
+
+private:
+  // // from ndn::App
+  // virtual void
+  // OnInterest (const ns3::Ptr<const ns3::ndn::Interest> &interest, ns3::Ptr<ns3::Packet> packet);
+ 
+  // virtual void
+  // OnContentObject (const ns3::Ptr<const ns3::ndn::ContentObject> &contentObject,
+  //                  ns3::Ptr<ns3::Packet> payload);
+
+private:
+  ns3::UniformVariable m_rand; // nonce generator
+
+  FilterEntryContainer<RawDataCallback> m_dataCallbacks;
+  FilterEntryContainer<InterestCallback> m_interestCallbacks;
+};
+
+}
+}
+
+#endif // NDN_API_HANDLER_H
diff --git a/ndn.cxx/ndn-handler.cc b/ndn.cxx/ndn-handler.cc
deleted file mode 100644
index c7c9e66..0000000
--- a/ndn.cxx/ndn-handler.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012 University of California, Los Angeles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
- *         Chaoyi Bian <bcy@pku.edu.cn>
- */
-
-#include "ndn-handler.h"
-
-#include <boost/throw_exception.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/lambda/lambda.hpp>
-#include <boost/lambda/bind.hpp>
-namespace ll = boost::lambda;
-
-#include <ns3/packet.h>
-
-#include <ns3/ndn-interest.h>
-#include <ns3/ndn-content-object.h>
-#include <ns3/ndn-face.h>
-#include <ns3/ndn-fib.h>
-#include <ns3/log.h>
-
-typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
-typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;
-
-using namespace std;
-using namespace boost;
-using namespace ns3;
-
-#define INIT_LOGGER NS_LOG_COMPONENT_DEFINE
-#define _LOG_DEBUG NS_LOG_DEBUG
-#define _LOG_TRACE NS_LOG_TRACE
-#define _LOG_INFO NS_LOG_INFO
-
-
-INIT_LOGGER ("ndn.Handler");
-
-namespace ns3 {
-namespace ndn {
-
-Handler::Handler()
-  : m_rand (0, std::numeric_limits<uint32_t>::max ())
-{
-}
-
-Handler::~Handler()
-{
-}
-
-void
-Handler::StartApplication ()
-{
-  ndn::App::StartApplication ();
-}
-
-void
-Handler::StopApplication ()
-{
-  ndn::App::StopApplication ();
-}
-
-int
-Handler::publishRawData (const std::string &name, const char *buf, size_t len, int freshness)
-{
-  // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
-  _LOG_INFO (">> publishRawData " << name);
-
-  static ndn::ContentObjectTail trailer;
-  
-  ndn::ContentObject data;
-  data.SetName (name);
-  data.SetFreshness (Seconds (freshness));
-
-  Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t*> (buf), len);
-  // packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::DATA));
-  packet->AddHeader (data);
-  packet->AddTrailer (trailer);
-
-  m_protocolHandler (packet);
-
-  m_transmittedContentObjects (&data, packet, this, m_face);
-
-  return 0;
-}
-
-
-// void
-// RawDataCallback2StringDataCallback (Handler::StringDataCallback callback, std::string str, const char *buf, size_t len)
-// {
-//   callback (str, string (buf, len));
-// }
-
-// int
-// Handler::sendInterestForString (const std::string &strInterest, const StringDataCallback &strDataCallback/*, int retry*/)
-// {
-//   return sendInterest (strInterest, boost::bind (RawDataCallback2StringDataCallback, strDataCallback, _1, _2, _3));
-// }
-
-int Handler::sendInterest (const string &strInterest, const RawDataCallback &rawDataCallback)
-{
-  // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
-  _LOG_INFO (">> I " << strInterest);
-  Ptr<ndn::Name> name = Create<ndn::Name> (strInterest);
-
-  ndn::Interest interestHeader;
-  interestHeader.SetNonce            (m_rand.GetValue ());
-  interestHeader.SetName             (*name);
-  interestHeader.SetInterestLifetime (Seconds (9.9)); // really long-lived interests
-
-  Ptr<Packet> packet = Create<Packet> ();
-  // packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::INTEREST));
-  packet->AddHeader (interestHeader);
-
-  // NS_LOG_DEBUG (interestHeader);
-  
-  // Record the callback
-  FilterEntryContainer<RawDataCallback>::iterator entry = m_dataCallbacks.find_exact (*name);
-  if (entry == m_dataCallbacks.end ())
-    {
-      pair<FilterEntryContainer<RawDataCallback>::iterator, bool> status =
-        m_dataCallbacks.insert (*name, Create< FilterEntry<RawDataCallback> > (name));
-
-      entry = status.first;
-    }
-  entry->payload ()->AddCallback (rawDataCallback);
-
-  m_protocolHandler (packet);
-  m_transmittedInterests (&interestHeader, this, m_face);
-  
-  return 0;
-}
-
-int Handler::setInterestFilter (const string &prefix, const InterestCallback &interestCallback)
-{
-  NS_LOG_DEBUG ("== setInterestFilter " << prefix << " (" << GetNode ()->GetId () << ")");
-  Ptr<ndn::Name> name = Create<ndn::Name> (prefix);
-
-  FilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.find_exact (*name);
-  if (entry == m_interestCallbacks.end ())
-    {
-      pair<FilterEntryContainer<InterestCallback>::iterator, bool> status =
-        m_interestCallbacks.insert (*name, Create < FilterEntry<InterestCallback> > (name));
-
-      entry = status.first;
-    }
-
-  entry->payload ()->AddCallback (interestCallback);
-
-  // creating actual face
-  Ptr<ndn::Fib> fib = GetNode ()->GetObject<ndn::Fib> ();
-  Ptr<ndn::fib::Entry> fibEntry = fib->Add (name, m_face, 0);
-  fibEntry->UpdateStatus (m_face, ndn::fib::FaceMetric::NDN_FIB_GREEN);
-
-  return 0;
-}
-
-void
-Handler::clearInterestFilter (const std::string &prefix)
-{
-  Ptr<ndn::Name> name = Create<ndn::Name> (prefix);
-
-  FilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.find_exact (*name);
-  if (entry == m_interestCallbacks.end ())
-    return;
-
-  entry->payload ()->ClearCallback ();
-}
-
-void
-Handler::OnInterest (const Ptr<const ndn::Interest> &interest, Ptr<Packet> packet)
-{
-  ndn::App::OnInterest (interest, packet);
-
-  // the app cannot set several filters for the same prefix
-  FilterEntryContainer<InterestCallback>::iterator entry = m_interestCallbacks.longest_prefix_match (interest->GetName ());
-  if (entry == m_interestCallbacks.end ())
-    {
-      _LOG_DEBUG ("No Interest callback set");
-      return;
-    }
-  
-  entry->payload ()->m_callback (lexical_cast<string> (interest->GetName ()));  
-}
-
-void
-Handler::OnContentObject (const Ptr<const ndn::ContentObject> &contentObject,
-                              Ptr<Packet> payload)
-{
-  ndn::App::OnContentObject (contentObject, payload);
-  NS_LOG_DEBUG ("<< D " << contentObject->GetName ());
-
-  FilterEntryContainer<RawDataCallback>::iterator entry = m_dataCallbacks.longest_prefix_match (contentObject->GetName ());
-  if (entry == m_dataCallbacks.end ())
-    {
-      _LOG_DEBUG ("No Data callback set");
-      return;
-    }
-
-  while (entry != m_dataCallbacks.end ())
-    {
-      entry->payload ()->m_callback (lexical_cast<string> (contentObject->GetName ()), payload);
-      m_dataCallbacks.erase (entry);
-
-      entry = m_dataCallbacks.longest_prefix_match (contentObject->GetName ());
-    }
-}
-
-}
-}
diff --git a/ndn.cxx/ndn-handler.h b/ndn.cxx/ndn-handler.h
deleted file mode 100644
index 420645d..0000000
--- a/ndn.cxx/ndn-handler.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2013 University of California, Los Angeles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
- *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
- *         Chaoyi Bian <bcy@pku.edu.cn>
- */
-
-#ifndef NDN_HANDLER_H
-#define NDN_HANDLER_H
-
-#include <boost/exception/all.hpp>
-#include <boost/function.hpp>
-#include <string>
-
-#include <ns3/ptr.h>
-#include <ns3/node.h>
-#include <ns3/random-variable.h>
-#include <ns3/ndn-app.h>
-#include <ns3/ndn-name.h>
-
-#include <ns3/ndnSIM/utils/trie/trie-with-policy.h>
-#include <ns3/ndnSIM/utils/trie/counting-policy.h>
-
-namespace ns3 {
-namespace ndn {
-
-template<class Callback>
-struct FilterEntry : public ns3::SimpleRefCount< FilterEntry<Callback> >
-{
-public:
-  FilterEntry (ns3::Ptr<const ns3::ndn::Name> prefix)
-    : m_prefix (prefix)
-  { }
-  
-  const ns3::ndn::Name &
-  GetPrefix () const
-  { return *m_prefix; }
-
-  void
-  AddCallback (Callback callback)
-  { 
-    m_callback = callback;
-  }
-
-  void
-  ClearCallback ()
-  {
-    m_callback = 0;
-  }
-  
-public:
-  ns3::Ptr<const ns3::ndn::Name> m_prefix; ///< \brief Prefix of the PIT entry
-  Callback m_callback;
-};
-
-
-template<class Callback>
-struct FilterEntryContainer :
-    public ns3::ndn::ndnSIM::trie_with_policy<ns3::ndn::Name,
-                                              ns3::ndn::ndnSIM::smart_pointer_payload_traits< FilterEntry<Callback> >,
-                                              ns3::ndn::ndnSIM::counting_policy_traits>
-{
-};
-
-
-struct OperationException : virtual boost::exception, virtual std::exception { };
-/**
- * \ingroup sync
- * @brief A handler for NDN; clients of this code do not need to deal
- * with NDN API directly
- */
-class Handler
-  : public ns3::ndn::App
-{
-public:
-  typedef boost::function<void (std::string, std::string)> StringDataCallback;
-  typedef boost::function<void (std::string, Ptr<Packet>)> RawDataCallback;
-  typedef boost::function<void (std::string)> InterestCallback;
-
-  
-  /**
-   * @brief initialize the handler; a lot of things needs to be done. 1) init
-   * keystore 2) init keylocator 3) start a thread to hold a loop of ccn_run
-   *
-   */
-  Handler();
-  ~Handler();
-
-  /**
-   * @brief send Interest; need to grab lock m_mutex first
-   *
-   * @param strInterest the Interest name
-   * @param dataCallback the callback function to deal with the returned data
-   * @return the return code of ccn_express_interest
-   */
-  // int
-  // sendInterestForString (const std::string &strInterest, const StringDataCallback &strDataCallback/*, int retry = 0*/);
-
-  int
-  sendInterest (const std::string &strInterest, const RawDataCallback &rawDataCallback/*, int retry = 0*/);
-  
-  /**
-   * @brief set Interest filter (specify what interest you want to receive)
-   *
-   * @param prefix the prefix of Interest
-   * @param interestCallback the callback function to deal with the returned data
-   * @return the return code of ccn_set_interest_filter
-   */
-  int
-  setInterestFilter (const std::string &prefix, const InterestCallback &interestCallback);
-
-  /**
-   * @brief clear Interest filter
-   * @param prefix the prefix of Interest
-   */
-  void
-  clearInterestFilter (const std::string &prefix);
-
-  /**
-   * @brief publish data and put it to local ccn content store; need to grab
-   * lock m_mutex first
-   *
-   * @param name the name for the data object
-   * @param dataBuffer the data to be published
-   * @param freshness the freshness time for the data object
-   * @return code generated by NDN library calls, >0 if success
-   */
-  int
-  publishStringData (const std::string &name, const std::string &dataBuffer, int freshness)
-  {
-    return publishRawData (name, dataBuffer.c_str(), dataBuffer.length(), freshness);
-  }
-
-  int
-  publishRawData (const std::string &name, const char *buf, size_t len, int freshness);
-  
-  // from ndn::App
-  virtual void
-  OnInterest (const ns3::Ptr<const ns3::ndn::Interest> &interest, ns3::Ptr<ns3::Packet> packet);
- 
-  virtual void
-  OnContentObject (const ns3::Ptr<const ns3::ndn::ContentObject> &contentObject,
-                   ns3::Ptr<ns3::Packet> payload);
-
-
-public:
-  // inherited from Application base class.
-  virtual void
-  StartApplication ();    // Called at time specified by Start
-
-  virtual void
-  StopApplication ();     // Called at time specified by Stop
-
-private:
-  ns3::UniformVariable m_rand; // nonce generator
-
-  FilterEntryContainer<RawDataCallback> m_dataCallbacks;
-  FilterEntryContainer<InterestCallback> m_interestCallbacks;
-};
-
-}
-}
-
-#endif // NDN_HANDLER_H
diff --git a/wscript b/wscript
index 8dbff90..da9044c 100644
--- a/wscript
+++ b/wscript
@@ -183,7 +183,7 @@
 
     bld.recurse ('tools')
 
-    bld.ns3_python_bindings()
+    # bld.ns3_python_bindings()
 
 
 @TaskGen.feature('ns3fullmoduleheaders')