fw: allow strategies to pick outgoing Interest

This commit changes outgoing Interest pipeline and Strategy API,
to give strategies an opportunity to pick an outgoing Interest that
matches the Interest table entry.
No strategy is updated in this commit.

refs #1756

Change-Id: Iffad77ef0078c437070039fca6b24a85df13bda7
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index efe1fac..27d6735 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -25,7 +25,9 @@
 
 #include "strategy.hpp"
 #include "forwarder.hpp"
+#include "pit-algorithm.hpp"
 #include "core/logger.hpp"
+#include "core/random.hpp"
 
 namespace nfd {
 namespace fw {
@@ -66,6 +68,42 @@
 }
 
 void
+Strategy::sendInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace,
+                       bool wantNewNonce)
+{
+  // scope control
+  if (fw::violatesScope(*pitEntry, outFace)) {
+    NFD_LOG_DEBUG("sendInterestLegacy face=" << outFace.getId() <<
+                  " interest=" << pitEntry->getName() << " violates scope");
+    return;
+  }
+
+  // pick Interest
+  // The outgoing Interest picked is the last incoming Interest that does not come from outFace.
+  // If all in-records come from outFace, it's fine to pick that.
+  // This happens when there's only one in-record that comes from outFace.
+  // The legit use is for vehicular network; otherwise, strategy shouldn't send to the sole inFace.
+  pit::InRecordCollection::iterator pickedInRecord = std::max_element(
+    pitEntry->in_begin(), pitEntry->in_end(),
+    [&outFace] (const pit::InRecord& a, const pit::InRecord& b) {
+      bool isOutFaceA = &a.getFace() == &outFace;
+      bool isOutFaceB = &b.getFace() == &outFace;
+      return (isOutFaceA > isOutFaceB) ||
+             (isOutFaceA == isOutFaceB && a.getLastRenewed() < b.getLastRenewed());
+    });
+  BOOST_ASSERT(pickedInRecord != pitEntry->in_end());
+  auto interest = const_pointer_cast<Interest>(pickedInRecord->getInterest().shared_from_this());
+
+  if (wantNewNonce) {
+    interest = make_shared<Interest>(*interest);
+    static std::uniform_int_distribution<uint32_t> dist;
+    interest->setNonce(dist(getGlobalRng()));
+  }
+
+  this->sendInterest(pitEntry, outFace, *interest);
+}
+
+void
 Strategy::sendNacks(const shared_ptr<pit::Entry>& pitEntry, const lp::NackHeader& header,
                     std::initializer_list<const Face*> exceptFaces)
 {