More progress with buffers
diff --git a/apps/ndn-app.cc b/apps/ndn-app.cc
index ab119d1..5b362d0 100644
--- a/apps/ndn-app.cc
+++ b/apps/ndn-app.cc
@@ -155,7 +155,7 @@
   GetNode ()->GetObject<ForwardingStrategy> ()->RemoveFace (m_face); // notify that face is removed
 
   // step 3. Destroy face
-  NS_ASSERT_MSG (m_face->GetReferenceCount ()==1,
+  NS_ASSERT_MSG (m_face->GetReferenceCount ()==2,
                  "At this point, nobody else should have referenced this face, but we have "
                  << m_face->GetReferenceCount () << " references");
   m_face = 0;
diff --git a/model/fw/nacks.cc b/model/fw/nacks.cc
index 6ad5066..4a4245c 100644
--- a/model/fw/nacks.cc
+++ b/model/fw/nacks.cc
@@ -88,8 +88,6 @@
                Ptr<const InterestHeader> header,
                Ptr<const Packet> origPacket)
 {
-  NS_ASSERT (m_nacksEnabled);
-
   // NS_LOG_FUNCTION (inFace << header << origPacket);
   m_inNacks (header, inFace);
 
@@ -106,29 +104,29 @@
   //
   // inFace->LeakBucketByOnePacket ();
 
-  pitEntry->SetWaitingInVain (inFace);
+  // pitEntry->SetWaitingInVain (inFace);
 
   DidReceiveValidNack (inFace, header->GetNack (), pitEntry);
   
-  if (!pitEntry->AreAllOutgoingInVain ()) // not all ougtoing are in vain
-    {
-      NS_LOG_DEBUG ("Not all outgoing are in vain");
-      // suppress
-      // Don't do anything, we are still expecting data from some other face
-      m_dropNacks (header, inFace);
-      return;
-    }
+  // if (!pitEntry->AreAllOutgoingInVain ()) // not all ougtoing are in vain
+  //   {
+  //     NS_LOG_DEBUG ("Not all outgoing are in vain");
+  //     // suppress
+  //     // Don't do anything, we are still expecting data from some other face
+  //     m_dropNacks (header, inFace);
+  //     return;
+  //   }
   
-  Ptr<Packet> nonNackInterest = Create<Packet> ();
-  Ptr<InterestHeader> nonNackHeader = Create<InterestHeader> (*header);
-  nonNackHeader->SetNack (InterestHeader::NORMAL_INTEREST);
-  nonNackInterest->AddHeader (*nonNackHeader);
+  // Ptr<Packet> nonNackInterest = Create<Packet> ();
+  // Ptr<InterestHeader> nonNackHeader = Create<InterestHeader> (*header);
+  // nonNackHeader->SetNack (InterestHeader::NORMAL_INTEREST);
+  // nonNackInterest->AddHeader (*nonNackHeader);
   
-  bool propagated = DoPropagateInterest (inFace, nonNackHeader, nonNackInterest, pitEntry);
-  if (!propagated)
-    {
-      DidExhaustForwardingOptions (inFace, nonNackHeader, nonNackInterest, pitEntry);
-    }  
+  // bool propagated = DoPropagateInterest (inFace, nonNackHeader, nonNackInterest, pitEntry);
+  // if (!propagated)
+  //   {
+  //     DidExhaustForwardingOptions (inFace, nonNackHeader, nonNackInterest, pitEntry);
+  //   }  
 }
 
 void
diff --git a/model/fw/per-fib-limits.cc b/model/fw/per-fib-limits.cc
index d56d48c..9703bd7 100644
--- a/model/fw/per-fib-limits.cc
+++ b/model/fw/per-fib-limits.cc
@@ -68,8 +68,6 @@
 void
 PerFibLimits::RemoveFace (Ptr<Face> face)
 {  
-  super::RemoveFace (face);
-
   for (PitQueueMap::iterator item = m_pitQueues.begin ();
        item != m_pitQueues.end ();
        item ++)
@@ -77,6 +75,8 @@
       item->second.Remove (face);
     }
   m_pitQueues.erase (face);
+
+  super::RemoveFace (face);
 }
 
 
@@ -117,6 +117,10 @@
       NS_LOG_DEBUG ("Face limit for " << header->GetName ());
     }
 
+  // hack
+  // offset lifetime, so we don't keep entries in queue for too long
+  pitEntry->OffsetLifetime (Seconds (- 0.9 * pitEntry->GetInterest ()->GetInterestLifetime ().ToDouble (Time::S)));
+  
   bool enqueued = m_pitQueues[outFace].Enqueue (inFace, pitEntry);
   if (enqueued)
     {
@@ -133,6 +137,18 @@
   NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
   super::WillEraseTimedOutPendingInterest (pitEntry);
 
+  Ptr<Packet> pkt = Create<Packet> ();
+  Ptr<InterestHeader> nackHeader = Create<InterestHeader> (*pitEntry->GetInterest ());
+  nackHeader->SetNack (99);
+  pkt->AddHeader (*nackHeader);
+
+  for (pit::Entry::in_container::iterator face = pitEntry->GetIncoming ().begin ();
+       face != pitEntry->GetIncoming ().end ();
+       face ++)
+    {
+      face->m_face->Send (pkt->Copy ());
+    }
+  
   PitQueue::Remove (pitEntry);
   
   for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
@@ -184,8 +200,9 @@
           // now we have enqueued packet and have slot available. Send out delayed packet
           Ptr<pit::Entry> pitEntry = queue->second.Pop ();
 
-          // wrong, but for experimental purposes
-          // pitEntry->UpdateLifetime (pitEntry->GetInterest ()->GetInterestLifetime ());
+          // hack
+          // offset lifetime back, so PIT entry wouldn't prematurely expire
+          pitEntry->OffsetLifetime (Seconds (0.7 * pitEntry->GetInterest ()->GetInterestLifetime ().ToDouble (Time::S)));
           
           NS_ASSERT_MSG (pitEntry != 0, "There *have to* be an entry in queue");
           
@@ -201,15 +218,39 @@
     }
 }
 
-// void
-// PerFibLimits::DidReceiveValidNack (Ptr<Face> inFace,
-//                                    uint32_t nackCode,
-//                                    Ptr<pit::Entry> pitEntry)
-// {
-//   // super::DidReceiveValidNack (inFace, nackCode, pitEntry);
+void
+PerFibLimits::DidReceiveValidNack (Ptr<Face> inFace,
+                                   uint32_t nackCode,
+                                   Ptr<pit::Entry> pitEntry)
+{
+  // super::DidReceiveValidNack (inFace, nackCode, pitEntry);
+  // NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
 
-//   // ??
-// }
+  Ptr<Packet> pkt = Create<Packet> ();
+  Ptr<InterestHeader> nackHeader = Create<InterestHeader> (*pitEntry->GetInterest ());
+  nackHeader->SetNack (99);
+  pkt->AddHeader (*nackHeader);
+
+  for (pit::Entry::in_container::iterator face = pitEntry->GetIncoming ().begin ();
+       face != pitEntry->GetIncoming ().end ();
+       face ++)
+    {
+      face->m_face->Send (pkt->Copy ());
+    }
+  
+  PitQueue::Remove (pitEntry);
+
+  for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
+       face != pitEntry->GetOutgoing ().end ();
+       face ++)
+    {
+      face->m_face->GetLimits ().RemoveOutstanding ();
+    }
+
+  m_pit->MarkErased (pitEntry);
+  
+  ProcessFromQueue ();
+}
 
 
 } // namespace fw
diff --git a/model/fw/per-fib-limits.h b/model/fw/per-fib-limits.h
index 3f23992..298c9ee 100644
--- a/model/fw/per-fib-limits.h
+++ b/model/fw/per-fib-limits.h
@@ -68,6 +68,11 @@
   WillSatisfyPendingInterest (Ptr<Face> inFace,
                               Ptr<pit::Entry> pitEntry);
 
+  virtual void
+  DidReceiveValidNack (Ptr<Face> inFace,
+                       uint32_t nackCode,
+                       Ptr<pit::Entry> pitEntry);
+  
 private:
   void
   ProcessFromQueue ();
diff --git a/model/ndn-interest-header.cc b/model/ndn-interest-header.cc
index 46cbf25..39c87e9 100644
--- a/model/ndn-interest-header.cc
+++ b/model/ndn-interest-header.cc
@@ -67,7 +67,7 @@
   : m_name                (Create<NameComponents> (interest.GetName ()))
   , m_minSuffixComponents (interest.m_minSuffixComponents)
   , m_maxSuffixComponents (interest.m_maxSuffixComponents)
-  , m_exclude             (Create<NameComponents> (interest.GetExclude ()))
+  , m_exclude             (interest.IsEnabledExclude () ? Create<NameComponents> (interest.GetExclude ()) : 0)
   , m_childSelector       (interest.m_childSelector)
   , m_answerOriginKind    (interest.m_answerOriginKind)
   , m_scope               (interest.m_scope)
diff --git a/model/pit/ndn-pit-entry-impl.h b/model/pit/ndn-pit-entry-impl.h
index 85c94f1..6af9cc5 100644
--- a/model/pit/ndn-pit-entry-impl.h
+++ b/model/pit/ndn-pit-entry-impl.h
@@ -62,6 +62,15 @@
     CONTAINER.RescheduleCleaning ();
   }
 
+  virtual void
+  OffsetLifetime (const Time &offsetTime)
+  {
+    CONTAINER.i_time.erase (Pit::time_index::s_iterator_to (*this));
+    super::OffsetLifetime (offsetTime);
+    CONTAINER.i_time.insert (*this);
+
+    CONTAINER.RescheduleCleaning ();
+  }
   
   // to make sure policies work
   void
diff --git a/model/pit/ndn-pit-entry.cc b/model/pit/ndn-pit-entry.cc
index 4dcf6d0..af66570 100644
--- a/model/pit/ndn-pit-entry.cc
+++ b/model/pit/ndn-pit-entry.cc
@@ -70,6 +70,18 @@
   NS_LOG_INFO ("Updated lifetime to " << m_expireTime.ToDouble (Time::S));
 }
 
+void
+Entry::OffsetLifetime (const Time &offsetTime)
+{
+  m_expireTime += offsetTime;
+  if (m_expireTime < Simulator::Now ())
+    {
+      m_expireTime = Simulator::Now ();
+    }
+  NS_LOG_INFO ("Offsetting lifetime to " << m_expireTime.ToDouble (Time::S));
+}
+
+
 const NameComponents &
 Entry::GetPrefix () const
 {
diff --git a/model/pit/ndn-pit-entry.h b/model/pit/ndn-pit-entry.h
index ecec2a6..7f4ef0e 100644
--- a/model/pit/ndn-pit-entry.h
+++ b/model/pit/ndn-pit-entry.h
@@ -119,12 +119,21 @@
    * This function will update PIT entry lifetime to the maximum of the current lifetime and
    * the lifetime Simulator::Now () + offsetTime
    *
-   * @param offsetTime Relative time to the current moment, representing PIT entry lifetime
+   * @param lifetime Relative time to the current moment, representing PIT entry lifetime
    */
   virtual void
-  UpdateLifetime (const Time &offsetTime);
+  UpdateLifetime (const Time &lifetime);
 
   /**
+   * @brief Offset the currently set PIT lifetime (allowed both negative and positive offsets)
+   * @param offsetTime positive or negative offset for the PIT lifetime.
+   *
+   * If PIT expire time becomes less than Simulator::Now, then it is adjusted to Simulator::Now.
+   */
+  virtual void
+  OffsetLifetime (const Time &offsetTime);
+  
+  /**
    * @brief Get prefix of the PIT entry
    */
   const NameComponents &
diff --git a/test/generic-tests.cc b/test/generic-tests.cc
index 652a7f8..6fdc1a7 100644
--- a/test/generic-tests.cc
+++ b/test/generic-tests.cc
@@ -39,6 +39,9 @@
 namespace ns3 {
 namespace ndn {
 
+struct Bla {
+};
+
 void
 GenericTests::DoRun ()
 {
@@ -90,9 +93,6 @@
 
   cerr << "===========\n\n";
 
-  struct Bla {
-  };
-
   shared_ptr<Bla> p1 = make_shared <Bla> ();
   shared_ptr<Bla> p2 = make_shared <Bla> ();
 
@@ -100,6 +100,10 @@
     {
       cerr << "They are equal\n";
     }
+
+
+  Time x = Seconds (-1);
+  cout << x << endl;
 }
 
 } // namespace ndn