table+fw: move forwarding semantics out of PIT entry
refs #3546
Change-Id: I1e6f87fd81176c116b6d758156da1cf96ea03608
diff --git a/daemon/fw/pit-algorithm.cpp b/daemon/fw/pit-algorithm.cpp
new file mode 100644
index 0000000..ac04e2a
--- /dev/null
+++ b/daemon/fw/pit-algorithm.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pit-algorithm.hpp"
+
+namespace nfd {
+namespace fw {
+
+namespace scope_prefix {
+const Name LOCALHOST("ndn:/localhost");
+const Name LOCALHOP("ndn:/localhop");
+} // namespace scope_prefix
+
+bool
+violatesScope(const pit::Entry& pitEntry, const Face& outFace)
+{
+ if (outFace.getScope() == ndn::nfd::FACE_SCOPE_LOCAL) {
+ return false;
+ }
+ BOOST_ASSERT(outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL);
+
+ if (scope_prefix::LOCALHOST.isPrefixOf(pitEntry.getName())) {
+ // face is non-local, violates localhost scope
+ return true;
+ }
+
+ if (scope_prefix::LOCALHOP.isPrefixOf(pitEntry.getName())) {
+ // face is non-local, violates localhop scope unless PIT entry has local in-record
+ return std::none_of(pitEntry.getInRecords().begin(), pitEntry.getInRecords().end(),
+ [] (const pit::InRecord& inRecord) { return inRecord.getFace()->getScope() == ndn::nfd::FACE_SCOPE_LOCAL; });
+ }
+
+ // Name is not subject to scope control
+ return false;
+}
+
+bool
+canForwardToLegacy(const pit::Entry& pitEntry, const Face& face)
+{
+ time::steady_clock::TimePoint now = time::steady_clock::now();
+
+ bool hasUnexpiredOutRecord = std::any_of(pitEntry.getOutRecords().begin(), pitEntry.getOutRecords().end(),
+ [&face, &now] (const pit::OutRecord& outRecord) {
+ return outRecord.getFace().get() == &face && outRecord.getExpiry() >= now;
+ });
+ if (hasUnexpiredOutRecord) {
+ return false;
+ }
+
+ bool hasUnexpiredOtherInRecord = std::any_of(pitEntry.getInRecords().begin(), pitEntry.getInRecords().end(),
+ [&face, &now] (const pit::InRecord& inRecord) {
+ return inRecord.getFace().get() != &face && inRecord.getExpiry() >= now;
+ });
+ if (!hasUnexpiredOtherInRecord) {
+ return false;
+ }
+
+ return !violatesScope(pitEntry, face);
+}
+
+int
+findDuplicateNonce(const pit::Entry& pitEntry, uint32_t nonce, const Face& face)
+{
+ int dnw = DUPLICATE_NONCE_NONE;
+
+ for (const pit::InRecord& inRecord : pitEntry.getInRecords()) {
+ if (inRecord.getLastNonce() == nonce) {
+ if (inRecord.getFace().get() == &face) {
+ dnw |= DUPLICATE_NONCE_IN_SAME;
+ }
+ else {
+ dnw |= DUPLICATE_NONCE_IN_OTHER;
+ }
+ }
+ }
+
+ for (const pit::OutRecord& outRecord : pitEntry.getOutRecords()) {
+ if (outRecord.getLastNonce() == nonce) {
+ if (outRecord.getFace().get() == &face) {
+ dnw |= DUPLICATE_NONCE_OUT_SAME;
+ }
+ else {
+ dnw |= DUPLICATE_NONCE_OUT_OTHER;
+ }
+ }
+ }
+
+ return dnw;
+}
+
+bool
+hasPendingOutRecords(const pit::Entry& pitEntry)
+{
+ time::steady_clock::TimePoint now = time::steady_clock::now();
+ return std::any_of(pitEntry.getOutRecords().begin(), pitEntry.getOutRecords().end(),
+ [&now] (const pit::OutRecord& outRecord) { return outRecord.getExpiry() >= now; });
+}
+
+} // namespace fw
+} // namespace nfd