fw: introduce afterReceiveData strategy trigger

Change-Id: Ia805f1bd48f481c9b903b6ce5c388dd66fbbb7d1
refs: #4290
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index a05080f..ae1b4bd 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -167,6 +167,18 @@
 }
 
 void
+Strategy::afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
+                           const Face& inFace, const Data& data)
+{
+  NFD_LOG_DEBUG("afterReceiveData pitEntry=" << pitEntry->getName() <<
+                " inFace=" << inFace.getId() << " data=" << data.getName());
+
+  this->beforeSatisfyInterest(pitEntry, inFace, data);
+
+  this->sendDataToAll(pitEntry, inFace, data);
+}
+
+void
 Strategy::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
                            const shared_ptr<pit::Entry>& pitEntry)
 {
@@ -181,6 +193,40 @@
 }
 
 void
+Strategy::sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data, const Face& outFace)
+{
+  BOOST_ASSERT(pitEntry->getInterest().matchesData(data));
+
+  // delete the PIT entry's in-record based on outFace,
+  // since Data is sent to outFace from which the Interest was received
+  pitEntry->deleteInRecord(outFace);
+
+  m_forwarder.onOutgoingData(data, *const_pointer_cast<Face>(outFace.shared_from_this()));
+}
+
+void
+Strategy::sendDataToAll(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace, const Data& data)
+{
+  std::set<Face*> pendingDownstreams;
+  auto now = time::steady_clock::now();
+
+  // remember pending downstreams
+  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
+    if (inRecord.getExpiry() > now) {
+      if (inRecord.getFace().getId() == inFace.getId() &&
+          inRecord.getFace().getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
+        continue;
+      }
+      pendingDownstreams.insert(&inRecord.getFace());
+    }
+  }
+
+  for (const Face* pendingDownstream : pendingDownstreams) {
+    this->sendData(pitEntry, data, *pendingDownstream);
+  }
+}
+
+void
 Strategy::sendNacks(const shared_ptr<pit::Entry>& pitEntry, const lp::NackHeader& header,
                     std::initializer_list<const Face*> exceptFaces)
 {