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/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:
   /**