nlsr: canonize Adjacent FaceURIs on startup
Change-Id: I6a2b31631918c1ece79c3fc13e392917162efc2d
refs: #4063
diff --git a/src/common.hpp b/src/common.hpp
index 65105d7..4e82370 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -23,6 +23,7 @@
#define NLSR_COMMON_HPP
#include <ndn-cxx/common.hpp>
+#include <ndn-cxx/util/time.hpp>
namespace nlsr {
@@ -31,6 +32,8 @@
using std::shared_ptr;
using std::function;
-}
+const ndn::time::seconds TIME_ALLOWED_FOR_CANONIZATION = ndn::time::seconds(4);
+
+} // namespace nlsr
#endif // NLSR_COMMON_HPP
diff --git a/src/nlsr-runner.cpp b/src/nlsr-runner.cpp
index d5bf709..29e4737 100644
--- a/src/nlsr-runner.cpp
+++ b/src/nlsr-runner.cpp
@@ -57,8 +57,16 @@
m_nlsr.daemonize();
}
- m_nlsr.initialize();
-
+ /**
+ * This really should be part of Nlsr::initialize, but because URI
+ * canonization happens asynchronously and we need to ensure that it
+ * happens before we proceed, the canonization function has to be
+ * the one to call initialize.
+ */
+ m_nlsr.canonizeNeighborUris(m_nlsr.getAdjacencyList().getAdjList().begin(),
+ [this] (std::list<Adjacent>::iterator iterator) {
+ m_nlsr.canonizeContinuation(iterator);
+ });
try {
m_nlsr.startEventLoop();
}
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 2bcc157..8a88c1f 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -190,6 +190,40 @@
}
void
+Nlsr::canonizeContinuation(std::list<Adjacent>::iterator iterator)
+{
+ canonizeNeighborUris(iterator, [this] (std::list<Adjacent>::iterator iterator) {
+ canonizeContinuation(iterator);
+ });
+}
+
+void
+Nlsr::canonizeNeighborUris(std::list<Adjacent>::iterator currentNeighbor,
+ std::function<void(std::list<Adjacent>::iterator)> then)
+{
+ if (currentNeighbor != m_adjacencyList.getAdjList().end()) {
+ ndn::util::FaceUri uri(currentNeighbor->getConnectingFaceUri());
+ uri.canonize([this, then, currentNeighbor] (ndn::util::FaceUri canonicalUri) {
+ _LOG_DEBUG("Canonized URI: " << currentNeighbor->getConnectingFaceUri()
+ << " to: " << canonicalUri);
+ currentNeighbor->setConnectingFaceUri(canonicalUri.toString());
+ then(std::next(currentNeighbor));
+ },
+ [this, then, currentNeighbor] (const std::string& reason) {
+ _LOG_ERROR("Could not canonize URI: " << currentNeighbor->getConnectingFaceUri()
+ << " because: " << reason);
+ then(std::next(currentNeighbor));
+ },
+ m_nlsrFace.getIoService(),
+ TIME_ALLOWED_FOR_CANONIZATION);
+ }
+ // We have finished canonizing all neighbors, so initialize NLSR.
+ else {
+ initialize();
+ }
+}
+
+void
Nlsr::initialize()
{
_LOG_DEBUG("Initializing Nlsr");
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index eb9132d..574e53a 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -53,13 +53,14 @@
#include "update/nfd-rib-command-processor.hpp"
#include "utility/name-helper.hpp"
-
namespace nlsr {
static ndn::Name DEFAULT_BROADCAST_PREFIX("/ndn/broadcast");
class Nlsr
{
+ friend class NlsrRunner;
+
class Error : public std::runtime_error
{
public:
@@ -323,6 +324,26 @@
return m_firstHelloInterval;
}
+ /**
+ * \brief Canonize the URI for this and all proceeding neighbors in a list.
+ *
+ * This function canonizes the URI of the Adjacent object pointed to
+ * by currentNeighbor. It then executes the then callback, providing
+ * the next iterator in the list to the callback. A standard
+ * invocation would be to pass the begin() iterator of NLSR's
+ * adjacency list, and to provide Nlsr::canonizeContinuation as the
+ * callback. Because every URI must be canonical before we begin
+ * operations, the canonize function must call initialize itself.
+ *
+ * \sa Nlsr::canonizeContinuation
+ * \sa Nlsr::initialize
+ * \sa NlsrRunner::run
+ */
+ void
+ canonizeNeighborUris(std::list<Adjacent>::iterator currentNeighbor,
+ std::function<void(std::list<Adjacent>::iterator)> then);
+
+
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
addCertificateToCache(std::shared_ptr<ndn::IdentityCertificate> certificate)
@@ -366,6 +387,17 @@
m_firstHelloInterval = interval;
}
+ /**
+ * \brief Continues canonizing neighbor URIs.
+ *
+ * For testability reasons, we want what each instance of
+ * canonization does after completion to be controllable. The best
+ * way to do this is to control that by simply passing a
+ * continuation function.
+ */
+ void
+ canonizeContinuation(std::list<Adjacent>::iterator iterator);
+
public:
static const ndn::Name LOCALHOST_PREFIX;
diff --git a/src/utility/face-controller.cpp b/src/utility/face-controller.cpp
index 62778cd..e6c0a8b 100644
--- a/src/utility/face-controller.cpp
+++ b/src/utility/face-controller.cpp
@@ -31,8 +31,6 @@
using ndn::util::FaceUri;
-const ndn::time::seconds FaceController::TIME_ALLOWED_FOR_CANONIZATION = ndn::time::seconds(4);
-
void
FaceController::createFace(const std::string& request,
const CommandSuccessCallback& onSuccess,
diff --git a/src/utility/face-controller.hpp b/src/utility/face-controller.hpp
index 9e4527e..d44c2ec 100644
--- a/src/utility/face-controller.hpp
+++ b/src/utility/face-controller.hpp
@@ -68,7 +68,6 @@
ndn::nfd::Controller& m_controller;
static const uint32_t CANONIZE_ERROR_CODE = 408;
- static const ndn::time::seconds TIME_ALLOWED_FOR_CANONIZATION;
};
} // namespace util
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index 39fbee5..3553a43 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -36,7 +36,7 @@
{
public:
NlsrFixture()
- : face(std::make_shared<ndn::util::DummyClientFace>())
+ : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
, nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
, lsdb(nlsr.getLsdb())
, neighbors(nlsr.getAdjacencyList())
@@ -52,7 +52,7 @@
std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
nlsr.m_helloProtocol.onContentValidated(data);
- }
+ }
public:
std::shared_ptr<ndn::util::DummyClientFace> face;
@@ -447,6 +447,37 @@
BOOST_CHECK_EQUAL(lsa->getAdl().getSize(), 2);
}
+BOOST_AUTO_TEST_CASE(CanonizeUris)
+{
+ ndn::Name neighborAName("/ndn/site/%C1.router/routerA");
+ Adjacent neighborA(neighborAName, "udp://10.0.0.1", 0, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborA);
+
+ ndn::Name neighborBName("/ndn/site/%C1.router/routerB");
+ Adjacent neighborB(neighborBName, "udp://10.0.0.2", 0, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborB);
+
+ int nCanonizationsLeft = nlsr.getAdjacencyList().getAdjList().size();
+ std::function<void(std::list<Adjacent>::iterator)> thenCallback =
+ [this, &thenCallback, &nCanonizationsLeft] (std::list<Adjacent>::iterator iterator) {
+ nCanonizationsLeft--;
+ nlsr.canonizeNeighborUris(iterator, thenCallback);
+ };
+ nlsr.canonizeNeighborUris(nlsr.getAdjacencyList().getAdjList().begin(),
+ [thenCallback] (std::list<Adjacent>::iterator iterator) {
+ thenCallback(iterator);
+ });
+ while (nCanonizationsLeft != 0) {
+ this->advanceClocks(ndn::time::milliseconds(1));
+ }
+
+ BOOST_CHECK_EQUAL(nlsr.getAdjacencyList().getAdjacent(neighborAName).getConnectingFaceUri(),
+ "udp4://10.0.0.1:6363");
+
+ BOOST_CHECK_EQUAL(nlsr.getAdjacencyList().getAdjacent(neighborBName).getConnectingFaceUri(),
+ "udp4://10.0.0.2:6363");
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace test