Modification of CcnxFace interface and unification of CCNx applications via common CcnxApp class

Moving functionality of interest limits from PIT to Face.

!!! Code compiles, but probably doesn't work !!!
diff --git a/apps/ccnx-app.cc b/apps/ccnx-app.cc
new file mode 100644
index 0000000..a23167e
--- /dev/null
+++ b/apps/ccnx-app.cc
@@ -0,0 +1,140 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 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>
+ */
+
+#include "ccnx-app.h"
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/ccnx-interest-header.h"
+#include "ns3/ccnx-content-object-header.h"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxApp");
+
+namespace ns3
+{    
+    
+NS_OBJECT_ENSURE_REGISTERED (CcnxApp);
+    
+TypeId
+CcnxConsumer::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxApp")
+    .SetParent<Application> ()
+    .AddConstructor<CcnxApp> ()
+    ;
+  return tid;
+}
+    
+CcnxApp::CcnxApp ()
+  : m_protocolHandler (0)
+  , m_active (true)
+  , m_face (0)
+{
+}
+    
+CcnxApp::~CcnxApp ()
+{
+  StopApplication ();
+}
+
+void
+CcnxProducer::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  StopApplication ();
+  CcnxApp::DoDispose ();
+}
+
+void
+CcnxApp::RegisterProtocolHandler (ProtocolHandler handler)
+{
+  m_protocolHandler = handler;
+}
+    
+void
+CcnxApp::OnInterest (const Ptr<const CcnxInterestHeader> &interest)
+{
+  NS_LOG_FUNCTION (this << interest);
+}
+
+void
+CcnxApp::OnNack (const Ptr<const CcnxInterestHeader> &interest)
+{
+  NS_LOG_FUNCTION (this << interest);
+}
+
+void
+CcnxApp::OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
+                          const Ptr<const Packet> &payload)
+{
+  NS_LOG_FUNCTION (this << contentObject << payload);
+}
+
+// Application Methods
+void 
+CcnxApp::StartApplication () // Called at time specified by Start
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  
+  NS_ASSERT (m_active != true);
+  m_active = true;
+
+  NS_ASSERT_MSG (GetObject<Ccnx> () != 0,
+                 "Ccnx stack should be installed on the node " << GetNode ());
+  NS_ASSERT_MSG (GetObject<CcnxFib> () != 0);
+
+  // step 1. Create a face
+  m_face = Create<CcnxLocalFace> (/*Ptr<CcnxApp> (this)*/this);
+    
+  // step 2. Add face to the CCNx stack
+  GetObject<CcnxFib> ()->Add (m_prefix, m_face, 0);
+  GetObject<Ccnx> ()->AddFace (m_face);
+
+  // step 3. Enable face
+  m_face->SetUp (true);
+}
+    
+void 
+CcnxApp::StopApplication () // Called at time specified by Stop
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (!m_active) return; //don't assert here, just return
+ 
+  NS_ASSERT (GetObject<Ccnx> () != 0);
+  NS_ASSERT (GetObject<CcnxFib> () != 0);
+
+  m_active = false;
+
+  // step 1. Disable face
+  m_face->SetUp (false);
+
+  // step 2. Remove face from CCNx stack
+  GetObject<Ccnx> ()->RemoveFace (m_face);
+  GetObject<CcnxFib> ()->Add (m_prefix, m_face, 0);
+
+  // step 3. Destroy face
+  NS_ASSERT_MSG (m_face->GetReferenceCount ()==1,
+                 "At this point, nobody else should have referenced this face");
+  m_face = 0;
+}
+
+
+}
diff --git a/apps/ccnx-app.h b/apps/ccnx-app.h
new file mode 100644
index 0000000..4f2cb83
--- /dev/null
+++ b/apps/ccnx-app.h
@@ -0,0 +1,104 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 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>
+ */
+
+#ifndef CCNX_APP_H
+#define CCNX_APP_H
+
+#include "ns3/application.h"
+#include "ns3/ptr.h"
+#include "ns3/callback.h"
+
+namespace ns3 
+{
+
+class Packet;
+class CcnxInterestHeader;
+class CcnxContentObjectHeader;
+
+/**
+ * @ingroup ccnx
+ * @brief Base class that all CCNx applications should be derived from.
+ * 
+ * The class implements virtual calls onInterest, onNack, and onContentObject
+ */
+class CcnxApp: public Application
+{
+public:
+  typedef Callback<bool, const Ptr<CcnxFace>&> ProtocolHandler;
+  
+  static TypeId GetTypeId ();
+
+  /**
+   * @brief Default constructor
+   */
+  CcnxApp ();
+  virtual ~CcnxApp ();
+
+  /**
+   * @brief Register lower layer callback (to send interests from the application)
+   */
+  void
+  RegisterProtocolHandler (ProtocolHandler handler);
+  
+  /**
+   * @brief Method that will be called every time new Interest arrives
+   * @param interest Interest header
+   */
+  virtual void
+  OnInterest (const Ptr<const CcnxInterestHeader> &interest);
+
+  /**
+   * @brief Method that will be called every time new NACK arrives
+   * @param interest Interest header
+   */
+  virtual void
+  OnNack (const Ptr<const CcnxInterestHeader> &interest);
+  
+  /**
+   * @brief Method that will be called every time new ContentObject arrives
+   * @param contentObject ContentObject header
+   * @param payload payload (potentially virtual) of the ContentObject packet
+   */
+  virtual void
+  OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
+                   const Ptr<const Packet> &payload);
+        
+protected:
+  virtual void
+  DoDispose ();
+
+  // inherited from Application base class.
+  virtual void
+  StartApplication ();    // Called at time specified by Start
+
+  virtual void
+  StopApplication ();     // Called at time specified by Stop
+
+protected:
+  ProtocolHandler m_protocolHandler;
+  bool m_active; 
+
+private:
+  Ptr<CcnxFace> m_face; // local face that is created 
+};
+
+} // namespace ns3
+
+#endif // CCNX_APP_H
diff --git a/apps/ccnx-consumer.cc b/apps/ccnx-consumer.cc
index ac3950c..01a5b1d 100644
--- a/apps/ccnx-consumer.cc
+++ b/apps/ccnx-consumer.cc
@@ -36,173 +36,132 @@
 TypeId
 CcnxConsumer::GetTypeId (void)
 {
-    static TypeId tid = TypeId ("ns3::CcnxConsumer")
-      .SetParent<Application> ()
-      .AddConstructor<CcnxConsumer> ()
-      .AddAttribute ("OffTime", "Time interval between packets",
-                     StringValue ("100ms"),
-                     MakeTimeAccessor (&CcnxConsumer::m_offTime),
-                     MakeTimeChecker ())
-      .AddAttribute ("InterestName","CcnxName of the Interest (use CcnxNameComponents)",
-                     StringValue ("/"),
-                     MakeCcnxNameComponentsAccessor (&CcnxConsumer::m_interestName),
-                     MakeCcnxNameComponentsChecker ())
-      .AddAttribute ("LifeTime", "LifeTime fo interest packet",
-                     StringValue ("2s"),
-                     MakeTimeAccessor (&CcnxConsumer::m_interestLifeTime),
-                     MakeTimeChecker ())
-      .AddAttribute ("MinSuffixComponents", "MinSuffixComponents",
-                     IntegerValue(-1),
-                     MakeIntegerAccessor(&CcnxConsumer::m_minSuffixComponents),
-                     MakeIntegerChecker<int32_t>())
-      .AddAttribute ("MaxSuffixComponents", "MaxSuffixComponents",
-                     IntegerValue(-1),
-                     MakeIntegerAccessor(&CcnxConsumer::m_maxSuffixComponents),
-                     MakeIntegerChecker<int32_t>())
-      .AddAttribute ("ChildSelector", "ChildSelector",
-                     BooleanValue(false),
-                     MakeBooleanAccessor(&CcnxConsumer::m_childSelector),
-                     MakeBooleanChecker())
-      .AddAttribute ("Exclude", "only simple name matching is supported (use CcnxNameComponents)",
-                     CcnxNameComponentsValue (),
-                     MakeCcnxNameComponentsAccessor (&CcnxConsumer::m_exclude),
-                     MakeCcnxNameComponentsChecker ())
-      .AddAttribute ("Initial Nonce", "If 0 then nonce is not used",
-                     UintegerValue(1),
-                     MakeUintegerAccessor(&CcnxConsumer::m_initialNonce),
-                     MakeUintegerChecker<uint32_t>())
-      .AddTraceSource ("InterestTrace", "Interests that were sent",
-                       MakeTraceSourceAccessor (&CcnxConsumer::m_interestsTrace))
-      .AddTraceSource ("ContentObjectTrace", "ContentObjects that were received",
-                       MakeTraceSourceAccessor (&CcnxConsumer::m_contentObjectsTrace))
-      ;
+  static TypeId tid = TypeId ("ns3::CcnxConsumer")
+    .SetParent<Application> ()
+    .AddConstructor<CcnxConsumer> ()
+    .AddAttribute ("OffTime", "Time interval between packets",
+                   StringValue ("100ms"),
+                   MakeTimeAccessor (&CcnxConsumer::m_offTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("InterestName","CcnxName of the Interest (use CcnxNameComponents)",
+                   StringValue ("/"),
+                   MakeCcnxNameComponentsAccessor (&CcnxConsumer::m_interestName),
+                   MakeCcnxNameComponentsChecker ())
+    .AddAttribute ("LifeTime", "LifeTime fo interest packet",
+                   StringValue ("2s"),
+                   MakeTimeAccessor (&CcnxConsumer::m_interestLifeTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("MinSuffixComponents", "MinSuffixComponents",
+                   IntegerValue(-1),
+                   MakeIntegerAccessor(&CcnxConsumer::m_minSuffixComponents),
+                   MakeIntegerChecker<int32_t>())
+    .AddAttribute ("MaxSuffixComponents", "MaxSuffixComponents",
+                   IntegerValue(-1),
+                   MakeIntegerAccessor(&CcnxConsumer::m_maxSuffixComponents),
+                   MakeIntegerChecker<int32_t>())
+    .AddAttribute ("ChildSelector", "ChildSelector",
+                   BooleanValue(false),
+                   MakeBooleanAccessor(&CcnxConsumer::m_childSelector),
+                   MakeBooleanChecker())
+    .AddAttribute ("Exclude", "only simple name matching is supported (use CcnxNameComponents)",
+                   CcnxNameComponentsValue (),
+                   MakeCcnxNameComponentsAccessor (&CcnxConsumer::m_exclude),
+                   MakeCcnxNameComponentsChecker ())
+    .AddAttribute ("Initial Nonce", "If 0 then nonce is not used",
+                   UintegerValue(1),
+                   MakeUintegerAccessor(&CcnxConsumer::m_initialNonce),
+                   MakeUintegerChecker<uint32_t>())
+    .AddTraceSource ("InterestTrace", "Interests that were sent",
+                     MakeTraceSourceAccessor (&CcnxConsumer::m_interestsTrace))
+    .AddTraceSource ("ContentObjectTrace", "ContentObjects that were received",
+                     MakeTraceSourceAccessor (&CcnxConsumer::m_contentObjectsTrace))
+    ;
 
-    return tid;
+  return tid;
 }
     
 CcnxConsumer::CcnxConsumer ()
-    : m_seq (0)
+  : m_rand (0, std::numeric_limits<uint32_t>::max ())
+  , m_seq (0)
 {
-    NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION_NOARGS ();
 }
     
 CcnxConsumer::~CcnxConsumer()
 {
-    NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION_NOARGS ();
 }
     
 void
 CcnxConsumer::DoDispose (void)
 {
-    NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION_NOARGS ();
         
-    Application::DoDispose ();
+  Application::DoDispose ();
 }
     
 // Application Methods
 void 
 CcnxConsumer::StartApplication () // Called at time specified by Start
 {
-    NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION_NOARGS ();
 
-    NS_ASSERT_MSG (m_face == 0, "Face should not exist");
-    m_face = Create<CcnxLocalFace> ();
-
-    // step 1. Set up forwarding from face to application
-    m_face->SetNode (GetNode ());
-    m_face->SetContentObjectHandler (MakeCallback (&CcnxConsumer::OnContentObject, this));
-
-    // step 2. Set up forwarding to and from ccnx
-    NS_ASSERT_MSG (GetNode ()->GetObject<Ccnx> () !=0,
-                   "Ccnx stack should be installed on the node " << GetNode ());
-    GetNode ()->GetObject<Ccnx> ()->AddFace (m_face);
-
-    // step 3. Enable face
-    m_face->SetUp ();
-
-    // Send first packet immediately
-    m_sendEvent = Simulator::Schedule (Seconds(0.0), &CcnxConsumer::SendPacket, this);
+  // do base stuff
+  CcnxApp::StartApplication ();
+  
+  // schedule periodic packet generation
+  m_sendEvent = Simulator::Schedule (Seconds(0.0), &CcnxConsumer::SendPacket, this);
 }
     
 void 
 CcnxConsumer::StopApplication () // Called at time specified by Stop
 {
-    NS_LOG_FUNCTION_NOARGS ();
-        
-    CancelEvents ();
+  NS_LOG_FUNCTION_NOARGS ();
 
-    // step 1. Disable face
-    m_face->SetDown ();
+  // cancel periodic packet generation
+  Simulator::Cancel (m_sendEvent);
 
-    // step 2. Remove face from ccnx stack
-    GetNode ()->GetObject<Ccnx> ()->RemoveFace (m_face);
-
-    // step 3. Disable callbacks
-    m_face->SetContentObjectHandler (MakeNullCallback<void,
-                                                      const Ptr<const CcnxContentObjectHeader> &,
-                                                      const Ptr<const Packet> &> ());
-}
-    
-void 
-CcnxConsumer::CancelEvents ()
-{
-    NS_LOG_FUNCTION_NOARGS ();
-        
-    Simulator::Cancel (m_sendEvent);
+  // cleanup base stuff
+  CcnxApp::StopApplication ();
 }
     
 void
 CcnxConsumer::SendPacket ()
 {
-    NS_LOG_FUNCTION_NOARGS ();
-    NS_LOG_INFO ("Sending Interest at " << Simulator::Now ());
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_INFO ("Sending Interest at " << Simulator::Now ());
     
-    UniformVariable rand(1, std::numeric_limits<uint32_t>::max ());
-    uint32_t randomNonce = rand.GetValue();
-    
-    CcnxInterestHeader interestHeader;
-    interestHeader.SetNonce(randomNonce);
-    
-    Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> (m_interestName);
-    std::ostringstream os;
-    os << m_seq++;
-    (*name) (os.str ());
-    
-    interestHeader.SetName (name);
-    interestHeader.SetInterestLifetime(m_interestLifeTime);
-    interestHeader.SetChildSelector(m_childSelector);
-    interestHeader.SetExclude(Create<CcnxNameComponents> (m_exclude));
-    interestHeader.SetMaxSuffixComponents(m_maxSuffixComponents);
-    interestHeader.SetMinSuffixComponents(m_minSuffixComponents);
+  //
+  Ptr<CcnxNameComponents> nameWithSequence = Create<CcnxNameComponents> (m_interestName);
+  (*name) (m_seq++);
+  //
+
+  CcnxInterestHeader interestHeader;
+  interestHeader.SetNonce               (m_rand.GetValue ());
+  interestHeader.SetName                (nameWithSequence);
+  interestHeader.SetInterestLifetime    (m_interestLifeTime);
+  interestHeader.SetChildSelector       (m_childSelector);
+  interestHeader.SetExclude             (Create<CcnxNameComponents> (m_exclude));
+  interestHeader.SetMaxSuffixComponents (m_maxSuffixComponents);
+  interestHeader.SetMinSuffixComponents (m_minSuffixComponents);
         
-    NS_LOG_INFO ("Interest: \n" << interestHeader);
+  NS_LOG_INFO ("Interest: \n" << interestHeader);
 
-    Ptr<Packet> packet = Create<Packet> ();
-    packet->AddHeader (interestHeader);
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (interestHeader);
 
-    NS_LOG_INFO ("Packet: " << packet);
-    m_face->ReceiveFromApplication (packet);
+  m_protocolHandler (packet);
     
-    m_interestsTrace (m_face,packet);
-    
-    NS_LOG_INFO("time = " << m_offTime);
-    m_sendEvent = Simulator::Schedule (m_offTime, &CcnxConsumer::SendPacket, this);
+  m_sendEvent = Simulator::Schedule (m_offTime, &CcnxConsumer::SendPacket, this);
 }
-    
-// void
-// CcnxConsumer::OnInterest (const Ptr<const CcnxInterestHeader> &interest)
-// {
-// }
 
 void
 CcnxConsumer::OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
                                const Ptr<const Packet> &payload)
 {
-  // do stuff
-  NS_LOG_FUNCTION ("Received contentObject " << contentObject );
-    NS_LOG_INFO ("Preved!");
-  m_contentObjectsTrace (m_face,payload);
+  NS_LOG_FUNCTION (this << contentObject << payload);
+
+  NS_LOG_INFO ("Received content object: " << cref(*contentObject));
 }
 
-
-}
+} // namespace ns3
diff --git a/apps/ccnx-consumer.h b/apps/ccnx-consumer.h
index 16dbaf7..b2c115b 100644
--- a/apps/ccnx-consumer.h
+++ b/apps/ccnx-consumer.h
@@ -21,76 +21,45 @@
 #ifndef CCNX_CONSUMER_H
 #define CCNX_CONSUMER_H
 
-#include "ns3/application.h"
-#include "ns3/log.h"
-#include "ns3/random-variable.h"
-#include "ns3/nstime.h"
-#include "ns3/event-id.h"
-#include "ns3/ptr.h"
-#include "ns3/simulator.h"
-#include "ns3/ccnx-interest-header.h"
-#include "ns3/ccnx-local-face.h"
-#include "ns3/ccnx-name-components.h"
-#include "ns3/packet.h"
-#include "ns3/boolean.h"
-#include "ns3/integer.h"
-#include "ns3/uinteger.h"
-#include "ns3/pointer.h"
-#include "ns3/traced-callback.h"
-#include "ns3/ccnx-header-helper.h"
-
-#include "ns3/packet.h"
-#include "ns3/header.h"
+#include "ccnx-app.h"
 
 namespace ns3 
 {
 
-class CcnxConsumer: public Application
+class CcnxConsumer: public CcnxApp
 {
 public: 
   static TypeId GetTypeId ();
         
   CcnxConsumer ();
-  virtual ~CcnxConsumer ();
 
   void OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
                         const Ptr<const Packet> &payload);
-        
+
 protected:
-  virtual void DoDispose (void);
+  // from CcnxApp
+  virtual void
+  StartApplication ();
+
+  virtual void
+  StopApplication ();
   
 private:
-  // inherited from Application base class.
-  virtual void StartApplication (void);    // Called at time specified by Start
-  virtual void StopApplication (void);     // Called at time specified by Stop
-        
   //helpers
-  void CancelEvents ();
-
-  // Event handlers
-  // void StartSending ();
-  // void StopSending ();
   void SendPacket ();
-  //typedef Callback<void,const Ptr<CcnxFace>&,const Ptr<const Packet>& > ProtocolHandler;
      
 private:
-  TracedCallback<const Ptr<CcnxFace>&,const Ptr<const Packet>& > m_interestsTrace;
-  TracedCallback<const Ptr<CcnxFace>&,const Ptr<const Packet>& > m_contentObjectsTrace;
+  UniformVariable m_rand;
+  uint32_t        m_seq;
+  EventId         m_sendEvent; // Eventid of pending "send packet" event
 
-  Time m_offTime;
+  Time               m_offTime;
   CcnxNameComponents m_interestName;
-  Time m_interestLifeTime;
-  int32_t m_minSuffixComponents;
-  int32_t m_maxSuffixComponents;
-  bool m_childSelector;
+  Time               m_interestLifeTime;
+  int32_t            m_minSuffixComponents;
+  int32_t            m_maxSuffixComponents;
+  bool               m_childSelector;
   CcnxNameComponents m_exclude;
-  uint32_t m_initialNonce;
-        
-  EventId         m_sendEvent;    // Eventid of pending "send packet" event
-  TypeId          m_tid;
-  Ptr<CcnxLocalFace> m_face;
-    
-  uint32_t m_seq;
 };
 
 } // namespace ns3
diff --git a/apps/ccnx-producer.cc b/apps/ccnx-producer.cc
index d320a2d..1cec691 100644
--- a/apps/ccnx-producer.cc
+++ b/apps/ccnx-producer.cc
@@ -16,202 +16,67 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
 #include "ccnx-producer.h"
+#include "ns3/ccnx-interest-header.h"
+#include "ns3/string.h"
+#include "ns3/integer.h"
 
+#include "ns3/ccnx-local-face.h"
 
 NS_LOG_COMPONENT_DEFINE ("CcnxProducer");
 
 namespace ns3
 {    
-    
+
 NS_OBJECT_ENSURE_REGISTERED (CcnxProducer);
     
 TypeId
 CcnxProducer::GetTypeId (void)
 {
-    static TypeId tid = TypeId ("ns3::CcnxProducer")
-    .SetParent<Application> ()
+  static TypeId tid = TypeId ("ns3::CcnxProducer")
+    .SetParent<CcnxApp> ()
     .AddConstructor<CcnxProducer> ()
-    /*.AddAttribute ("Capacity", "Capacity of the ContentStore",
-                    UintegerValue(100),
-                    MakeUintegerAccessor(&CcnxProducer::m_storeCapacity),
-                    MakeUintegerChecker<uint32_t>())*/
     .AddAttribute ("Prefix","Prefix, for which producer has the data",
-                   CcnxNameComponentsValue (),
+                   StringValue ("/"),
                    MakeCcnxNameComponentsAccessor (&CcnxProducer::m_prefix),
                    MakeCcnxNameComponentsChecker ())
     .AddAttribute ("PayloadSize", "Virtual payload size for Content packets",
-                   UintegerValue(100),
+                   UintegerValue (100),
                    MakeUintegerAccessor(&CcnxProducer::m_virtualPayloadSize),
                    MakeUintegerChecker<uint32_t>())
-    .AddTraceSource ("InterestTrace", "Interests that were received",
-                    MakeTraceSourceAccessor (&CcnxProducer::m_interestsTrace))
-    .AddTraceSource ("ContentObjectTrace", "ContentObjects that were sent",
-                    MakeTraceSourceAccessor (&CcnxProducer::m_contentObjectsTrace))
+    // .AddTraceSource ("InterestTrace", "Interests that were received",
+    //                 MakeTraceSourceAccessor (&CcnxProducer::m_interestsTrace))
+    // .AddTraceSource ("ContentObjectTrace", "ContentObjects that were sent",
+    //                 MakeTraceSourceAccessor (&CcnxProducer::m_contentObjectsTrace))
     ;
         
-    return tid;
+  return tid;
 }
     
 CcnxProducer::CcnxProducer ()
 {
-    NS_LOG_FUNCTION_NOARGS ();
+  // NS_LOG_FUNCTION_NOARGS ();
 }
-    
-CcnxProducer::~CcnxProducer()
-{
-    NS_LOG_FUNCTION_NOARGS ();
-}
-    
+       
 void
-CcnxProducer::DoDispose (void)
+CcnxProducer::OnInterest (const Ptr<const CcnxInterestHeader> &interest)
 {
-    NS_LOG_FUNCTION_NOARGS ();
-        
-    Application::DoDispose ();
-}
-    
-    // Application Methods
-void 
-CcnxProducer::StartApplication () // Called at time specified by Start
-{
-    NS_LOG_FUNCTION_NOARGS ();
-    
-    NS_ASSERT_MSG (m_face == 0, "Face should not exist");
-    m_face = Create<CcnxLocalFace> ();
-    
-    // step 1. Set up forwarding from face to application
-    m_face->SetNode (GetNode ());
-    m_face->SetInterestHandler (MakeCallback (&CcnxProducer::OnInterest, this));
-    
-    // step 2. Set up forwarding to and from ccnx
-    NS_ASSERT_MSG (GetNode ()->GetObject<Ccnx> () !=0,
-                   "Ccnx stack should be installed on the node " << GetNode ());
-    GetNode ()->GetObject<Ccnx> ()->AddFace (m_face);
-    //Add (const CcnxNameComponents &prefix, Ptr<CcnxFace> face, int32_t metric);
-    GetNode ()->GetObject<Ccnx> ()->GetObject<CcnxFib> ()->Add(m_prefix, m_face, 0);
-    // step 3. Enable face
-    m_face->SetUp ();
-}
-    
-void 
-CcnxProducer::StopApplication () // Called at time specified by Stop
-{
-    NS_LOG_FUNCTION_NOARGS ();
-}
-    
-void
-CcnxProducer::OnInterest(const Ptr<const CcnxInterestHeader> &interest)
-{
-    NS_LOG_FUNCTION (this);
-    
-    
-    
-    //Ptr<Packet> data = Lookup (interest);
-    
-    
-    
-    Ptr<Packet> incomingPacket = Create<Packet>(m_virtualPayloadSize);
-    incomingPacket->AddHeader (*interest);
-    m_interestsTrace(m_face,incomingPacket);
-    
-   
+  NS_LOG_FUNCTION (this << interest);
 
-    static CcnxContentObjectTail tail; ///< \internal for optimization purposes
-    Ptr<Packet> outgoingPacket = Create<Packet> (m_virtualPayloadSize);
-    Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader>();
-    header->SetName(Create<CcnxNameComponents>(interest->GetName()));
-    outgoingPacket->AddHeader(*header);
-    outgoingPacket->AddTrailer (tail);
+  if (!m_active) return;
     
-    m_contentObjectsTrace(m_face,outgoingPacket);
-        
-    m_face->ReceiveFromApplication(outgoingPacket);
-   
-}
-    
-void 
-CcnxProducer::CancelEvents ()
-{
-    NS_LOG_FUNCTION_NOARGS ();
-        
-    // Simulator::Cancel (m_sendEvent);
-}
+  static CcnxContentObjectTail tail;
+  Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
+  header->SetName (Create<CcnxNameComponents> (interest->GetName ()));
   
-CcnxNameComponents
-CcnxProducer::GetPrefix() const
-{
-  return m_prefix;
+  Ptr<Packet> packet = Create<Packet> (m_virtualPayloadSize);
+  outgoingPacket->AddHeader (*header);
+  outgoingPacket->AddTrailer (tail);
+
+  m_protocolHandler (outgoingPacket);
 }
-    
-/*uint32_t
-CcnxProducer::GetStoreCapacity()
-{
-  return m_storeCapacity;
-}
-    
-void
-CcnxProducer::SetStoreCapacity(uint32_t capacity)
-{
-  m_storeCapacity = capacity;
-}
-  */  
-/*void
-CcnxProducer::HandlePacket(const Ptr<CcnxFace> &face, const Ptr<const Packet> &packet)
-{
-    uint8_t type[2];
-    uint32_t read = packet->CopyData (type,2);
-    if (read!=2)
-    {
-        NS_LOG_INFO ("Unknown CcnxPacket");
-        return;
-    }
-        
-    if (type[0] == INTEREST_BYTE0 && type[1] == INTEREST_BYTE1)
-    {
-        m_interestsTrace(face,packet);
-    }
-    else if (type[0] == CONTENT_OBJECT_BYTE0 && type[1] == CONTENT_OBJECT_BYTE1)
-    {
-        m_contentObjectsTrace(face,packet);
-    }
-}*/
-    
-/*Ptr<Packet>
-CcnxProducer::Lookup (Ptr<const CcnxInterestHeader> interest)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  DataStoreContainer::type::iterator it = m_availableData.get<i_prefix> ().find (interest->GetName ());
-        
-  if (it != m_availableData.end ())
-  {
-    // return fully formed CCNx packet
-    return it->GetFullyFormedCcnxPacket ();
-  }
-    
-  return 0;
-}   
-    
-void 
-CcnxProducer::Add (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  DataStoreContainer::type::iterator it = m_availableData.get<i_prefix> ().find (header->GetName ());
-        
-  if (it == m_availableData.end ())
-  { // add entry to the top
-    m_availableData.get<i_mru> ().push_front (DataStoreEntry (header, packet));
-            
-    if (m_availableData.size () > m_storeCapacity)
-      m_availableData.get<i_mru> ().pop_back ();
-  }
-  else
-  {
-    // promote entry to the top
-    //m_contentStore.get<i_mru> ().relocate (m_contentStore.get<i_mru> ().begin (),
-      //                                             m_contentStore.project<i_mru> (it));
-  }
-}*/
-}
+
+} // namespace ns3
diff --git a/apps/ccnx-producer.h b/apps/ccnx-producer.h
index 840400b..289c22e 100644
--- a/apps/ccnx-producer.h
+++ b/apps/ccnx-producer.h
@@ -16,194 +16,36 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
 #ifndef CCNX_PRODUCER_H
 #define CCNX_PRODUCER_H
 
-#include "ns3/application.h"
-#include "ns3/log.h"
-#include "ns3/random-variable.h"
-#include "ns3/nstime.h"
-#include "ns3/event-id.h"
+#include "ccnx-app.h"
+
 #include "ns3/ptr.h"
-#include "ns3/simulator.h"
-#include "ns3/ccnx-interest-header.h"
-#include "ns3/ccnx-local-face.h"
 #include "ns3/ccnx-name-components.h"
-#include "ns3/packet.h"
-#include "ns3/boolean.h"
-#include "ns3/integer.h"
-#include "ns3/uinteger.h"
-#include "ns3/random-variable.h"
-#include <limits> 
-#include "ns3/pointer.h"
-#include "ns3/traced-callback.h"
-#include "ns3/ccnx-header-helper.h"
-
-#include "ns3/packet.h"
-#include "ns3/header.h"
-#include "ns3/ccnx.h"
-#include "ns3/ccnx-content-object-header.h"
-#include "ns3/ccnx-name-components.h"
-#include "ns3/ccnx-fib.h"
-
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/tag.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-#include <boost/multi_index/sequenced_index.hpp>
-#include <boost/multi_index/hashed_index.hpp>
-#include <boost/multi_index/mem_fun.hpp>
 
 namespace ns3 
 {
-    
-    class DataStoreEntry
-    {
-    public:
-        /**
-         * \brief Construct data store entry
-         *
-         * \param header Parsed CcnxContentObject header
-         * \param packet Original CCNx packet
-         *
-         * The constructor will make a copy of the supplied packet and calls
-         * RemoveHeader and RemoveTail on the copy.
-         */
-        DataStoreEntry (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet);
-        
-        /**
-         * \brief Get prefix of the stored entry
-         * \returns prefix of the stored entry
-         */
-        inline const CcnxNameComponents&
-        GetName () const;
-        
-        /**
-         * \brief Get CcnxContentObjectHeader of the stored entry
-         * \returns CcnxContentObjectHeader of the stored entry
-         */
-        inline Ptr<const CcnxContentObjectHeader>
-        GetHeader () const;
-        
-        /**
-         * \brief Get content of the stored entry
-         * \returns content of the stored entry
-         */
-        inline Ptr<const Packet>
-        GetPacket () const;
-        
-        /**
-         * \brief Convenience method to create a fully formed CCNx packet from stored header and content
-         * \returns A read-write copy of the packet with CcnxContentObjectHeader and CcxnContentObjectTail
-         */
-        Ptr<Packet>
-        GetFullyFormedCcnxPacket () const;
-        
-        // Copy constructor is required by the container. Though, we're
-        // storing only two pointers, so shouldn't be a problem
-        // private:
-        //   CcnxContentStoreEntry (const CcnxContentStoreEntry &); ///< disabled copy constructor
-        //   CcnxContentStoreEntry& operator= (const CcnxContentStoreEntry&); ///< disabled copy operator
-        
-    private:
-        //Ptr<CcnxContentObjectHeader> m_header; ///< \brief non-modifiable CcnxContentObjectHeader
-        //Ptr<Packet> m_packet; ///< \brief non-modifiable content of the ContentObject packet
-    };
 
-    
-class CcnxProducer: public Application
+class CcnxProducer : public CcnxApp
 {
 public: 
-    static TypeId GetTypeId (void);
+  static TypeId
+  GetTypeId (void);
         
-    CcnxProducer ();
-        
-    virtual ~CcnxProducer ();
-        
-    //void HandlePacket (const Ptr<CcnxFace> &face, const Ptr<const Packet> &packet);
-    //uint32_t GetStoreCapacity();
-    //void SetStoreCapacity(uint32_t capacity);
-    //void AddContentStoreEntry (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet);
-    
-    void OnInterest(const Ptr<const CcnxInterestHeader> &interest);
-    
-    CcnxNameComponents GetPrefix() const;  
-    /**
-     * \brief Add a new content to the data store.
-     *
-     * \param header Fully parsed CcnxContentObjectHeader
-     * \param packet Fully formed CCNx packet to add to content store
-     * (will be copied and stripped down of headers)
-     *
-     * If entry with the same prefix exists, the old entry will be
-     * promoted to the top of the MRU hash
-     */
-    //void
-    //Add (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet);
-    
-protected:
-    virtual void DoDispose (void);
+  CcnxProducer ();
+
+  // inherited from CcnxApp
+  void OnInterest (const Ptr<const CcnxInterestHeader> &interest);
+
 private:
-    // inherited from Application base class.
-    virtual void StartApplication (void);    // Called at time specified by Start
-    virtual void StopApplication (void);     // Called at time specified by Stop
-        
-    /**
-     * \brief Find corresponding CS entry for the given interest
-     *
-     * \param interest Interest for which matching content store entry
-     * will be searched
-     *
-     * If an entry is found, it is promoted to the top of most recent
-     * used entries index, \see m_contentStore
-     */
-    //Ptr<Packet>
-    //Lookup (Ptr<const CcnxInterestHeader> interest);
-
-    
-    Ptr<Ccnx> m_ccnx;
-    Time m_offTime;
-           
-    //EventId         m_sendEvent;    // Eventid of pending "send packet" event
-    TypeId          m_tid;
-    Ptr<CcnxLocalFace> m_face;
-    
-    /*struct DataStoreContainer
-    {
-        typedef
-        boost::multi_index::multi_index_container<
-          DataStoreEntry,
-          boost::multi_index::indexed_by<
-            boost::multi_index::hashed_unique<
-              boost::multi_index::tag<__ccnx_private::i_prefix>,
-              boost::multi_index::const_mem_fun<DataStoreEntry,
-                                                const CcnxNameComponents&,
-                                                &DataStoreEntry::GetName>,
-              CcnxPrefixHash>,
-          boost::multi_index::sequenced<boost::multi_index::tag<__ccnx_private::i_mru> >
-#ifdef _DEBUG
-          ,
-          boost::multi_index::ordered_unique<
-          boost::multi_index::tag<__ccnx_private::i_ordered>,
-          boost::multi_index::const_mem_fun<DataStoreEntry,
-          const CcnxNameComponents&,
-          &CcnxContentStoreEntry::GetName>
-          >
-#endif
-        >
-      > type;
-    };*/
-
-    //helpers
-    void CancelEvents ();
-    
-    //DataStoreContainer::type m_availableData;
-    //uint32_t m_storeCapacity;
-    uint32_t m_virtualPayloadSize;
-    CcnxNameComponents m_prefix;
-    TracedCallback<const Ptr<CcnxFace>&,const Ptr<const Packet>& > m_interestsTrace;
-    TracedCallback<const Ptr<CcnxFace>&,const Ptr<const Packet>& > m_contentObjectsTrace;
+  CcnxNameComponents m_prefix;
+  uint32_t m_virtualPayloadSize;
 };
+
 }
-#endif
+
+#endif // CCNX_PRODUCER_H