[ndnSIM] fw: Add beforeSatisfyInterest and beforeExpirePendingInterest signals

The beforeExpirePendingInterest signal, in addition to actually timed out
interests, also includes NACKed interests.

Change-Id: I01b3a6e9f6090673c864d29065fd6d182fc251c4
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index 122fa58..f77a098 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -31,6 +31,8 @@
 #include "table/cleanup.hpp"
 #include <ndn-cxx/lp/tags.hpp>
 
+#include "face/null-face.hpp"
+
 namespace nfd {
 
 NFD_LOG_INIT("Forwarder");
@@ -47,7 +49,10 @@
   , m_pit(m_nameTree)
   , m_measurements(m_nameTree)
   , m_strategyChoice(*this)
+  , m_csFace(face::makeNullFace(FaceUri("contentstore://")))
 {
+  getFaceTable().addReserved(m_csFace, face::FACEID_CONTENT_STORE);
+
   m_faceTable.afterAdd.connect([this] (Face& face) {
     face.afterReceiveInterest.connect(
       [this, &face] (const Interest& interest) {
@@ -227,6 +232,10 @@
   // set PIT expiry timer to now
   this->setExpiryTimer(pitEntry, 0_ms);
 
+  beforeSatisfyInterest(*pitEntry, *m_csFace, data);
+  this->dispatchToStrategy(*pitEntry,
+    [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, *m_csFace, data); });
+
   // dispatch to strategy: after Content Store hit
   this->dispatchToStrategy(*pitEntry,
     [&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
@@ -252,6 +261,10 @@
   NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
                 (pitEntry->isSatisfied ? " satisfied" : " unsatisfied"));
 
+  if (!pitEntry->isSatisfied) {
+    beforeExpirePendingInterest(*pitEntry);
+  }
+
   // Dead Nonce List insert if necessary
   this->insertDeadNonceList(*pitEntry, 0);
 
@@ -301,6 +314,7 @@
     // set PIT expiry timer to now
     this->setExpiryTimer(pitEntry, 0_ms);
 
+    beforeSatisfyInterest(*pitEntry, inFace, data);
     // trigger strategy: after receive Data
     this->dispatchToStrategy(*pitEntry,
       [&] (fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, inFace, data); });
@@ -335,6 +349,7 @@
       this->setExpiryTimer(pitEntry, 0_ms);
 
       // invoke PIT satisfy callback
+      beforeSatisfyInterest(*pitEntry, inFace, data);
       this->dispatchToStrategy(*pitEntry,
         [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
 
diff --git a/daemon/fw/forwarder.hpp b/daemon/fw/forwarder.hpp
index 1c3c518..c873107 100644
--- a/daemon/fw/forwarder.hpp
+++ b/daemon/fw/forwarder.hpp
@@ -191,6 +191,17 @@
     m_csFromNdnSim = cs;
   }
 
+public:
+  /** \brief trigger before PIT entry is satisfied
+   *  \sa Strategy::beforeSatisfyInterest
+   */
+  signal::Signal<Forwarder, pit::Entry, Face, Data> beforeSatisfyInterest;
+
+  /** \brief trigger before PIT entry expires
+   *  \sa Strategy::beforeExpirePendingInterest
+   */
+  signal::Signal<Forwarder, pit::Entry> beforeExpirePendingInterest;
+
 PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
   /** \brief incoming Interest pipeline
    */
@@ -292,6 +303,7 @@
   StrategyChoice     m_strategyChoice;
   DeadNonceList      m_deadNonceList;
   NetworkRegionTable m_networkRegionTable;
+  shared_ptr<Face>   m_csFace;
 
   ns3::Ptr<ns3::ndn::ContentStore> m_csFromNdnSim;