nlsr: discover Faces from NFD
refs: #2954
Change-Id: I072972d88bce0e1012e96f33577657048b7df1e1
diff --git a/docs/GETTING-STARTED.rst b/docs/GETTING-STARTED.rst
index 216677f..0dbfafd 100644
--- a/docs/GETTING-STARTED.rst
+++ b/docs/GETTING-STARTED.rst
@@ -14,6 +14,20 @@
:doc:`INSTALL`
+
+Important Notes About Configuration
+-----------------------------------
+
+Since v0.4.0, NLSR no longer creates Faces for the neighbors that are
+specified in ``nlsr.conf``. Instead, it relies on the pre-existence of
+the Faces in NFD. NLSR will obtain this information from NFD, and
+configure its neighbors using this information.
+
+For people who were relying on NLSR to automagically configure their
+networks, this must now be done with ``nfdc``. Its documentation can
+be found `here
+<https://named-data.net/doc/NFD/current/manpages/nfdc.html>`_
+
Configuration
-------------
diff --git a/nlsr.conf b/nlsr.conf
index 329a702..ef569ce 100644
--- a/nlsr.conf
+++ b/nlsr.conf
@@ -11,7 +11,7 @@
; lsa-refresh-time is the time in seconds, after which router will refresh its LSAs
lsa-refresh-time 1800 ; default value 1800. Valid values 240-7200
- ; router-dead-interval is the time in seconds after which an inactive router's
+ ; router-dead-interval is the time in seconds after which an inactive routers
; LSAs are removed
;router-dead-interval 3600 ; default value: 2*lsa-refresh-time. Value must be larger
; than lsa-refresh-time
@@ -39,7 +39,7 @@
;log4cxx-conf /path/to/log4cxx-conf ; path for log4cxx configuration file (Absolute path)
}
-; the neighbors section contains the configuration for router's neighbors and hello's behavior
+; the neighbor's section contains the configuration for router's neighbors and hellos behavior
neighbors
{
@@ -65,6 +65,16 @@
first-hello-interval 10 ; Default value 10. Valid values 0-10
+ face-dataset-fetch-tries 3 ; default is 3. Valid values 1-10. The FaceDataset is
+ ; gotten from NFD, and is needed to configure NLSR
+ ; correctly. It is recommended not to set this
+ : variable too high, because it could cause
+ ; congestion for NFD.
+
+ face-dataset-fetch-interval 3600 ; default is 3600. Valid values 1800-5400.
+ ; This controls how often (in seconds) NLSR will attempt to
+ ; fetch a FaceStatus dataset from NFD.
+
; neighbor command is used to configure router's neighbor. Each neighbor will need
; one block of neighbor command
@@ -105,7 +115,7 @@
}
-; the fib section is used to configure fib entry's type to ndn FIB updated by NLSR
+; the fib section is used to configure fib entrys type to ndn FIB updated by NLSR
fib
{
diff --git a/src/adjacent.hpp b/src/adjacent.hpp
index 4aded01..29d7567 100644
--- a/src/adjacent.hpp
+++ b/src/adjacent.hpp
@@ -115,7 +115,7 @@
}
uint64_t
- getFaceId()
+ getFaceId() const
{
return m_faceId;
}
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index 789efc4..5362a41 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -454,6 +454,33 @@
if (!adjLsaBuildInterval.parseFromConfigSection(section)) {
return false;
}
+ // Set the retry count for fetching the FaceStatus dataset
+ ConfigurationVariable<uint32_t> faceDatasetFetchTries("face-dataset-fetch-tries",
+ std::bind(&ConfParameter::setFaceDatasetFetchTries,
+ &m_nlsr.getConfParameter(),
+ _1));
+
+ faceDatasetFetchTries.setMinAndMaxValue(FACE_DATASET_FETCH_TRIES_MIN,
+ FACE_DATASET_FETCH_TRIES_MAX);
+ faceDatasetFetchTries.setOptional(FACE_DATASET_FETCH_TRIES_DEFAULT);
+
+ if (!faceDatasetFetchTries.parseFromConfigSection(section)) {
+ return false;
+ }
+
+ // Set the interval between FaceStatus dataset fetch attempts.
+ ConfigurationVariable<ndn::time::seconds> faceDatasetFetchInterval("face-dataset-fetch-interval",
+ bind(&ConfParameter::setFaceDatasetFetchInterval,
+ &m_nlsr.getConfParameter(),
+ _1));
+
+ faceDatasetFetchInterval.setMinAndMaxValue(ndn::time::seconds(FACE_DATASET_FETCH_INTERVAL_MIN),
+ ndn::time::seconds(FACE_DATASET_FETCH_INTERVAL_MAX));
+ faceDatasetFetchInterval.setOptional(ndn::time::seconds(FACE_DATASET_FETCH_INTERVAL_DEFAULT));
+
+ if (!faceDatasetFetchInterval.parseFromConfigSection(section)) {
+ return false;
+ }
// first-hello-interval
ConfigurationVariable<uint32_t> firstHelloInterval("first-hello-interval",
@@ -469,8 +496,7 @@
for (ConfigSection::const_iterator tn =
section.begin(); tn != section.end(); ++tn) {
- if (tn->first == "neighbor")
- {
+ if (tn->first == "neighbor") {
try {
ConfigSection CommandAttriTree = tn->second;
std::string name = CommandAttriTree.get<std::string>("name");
@@ -479,7 +505,7 @@
ndn::util::FaceUri faceUri;
try {
faceUri = ndn::util::FaceUri(uriString);
- } catch (ndn::util::FaceUri::Error e) {
+ } catch (const ndn::util::FaceUri::Error& e) {
std::cerr << "Malformed face-uri <" << uriString << "> for " << name << std::endl;
return false;
}
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index 9bcd95c..6ec21f5 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -62,6 +62,19 @@
ROUTING_CALC_INTERVAL_MAX = 15
};
+
+enum {
+ FACE_DATASET_FETCH_TRIES_MIN = 1,
+ FACE_DATASET_FETCH_TRIES_MAX = 10,
+ FACE_DATASET_FETCH_TRIES_DEFAULT = 3
+};
+
+enum {
+ FACE_DATASET_FETCH_INTERVAL_MIN = 1800,
+ FACE_DATASET_FETCH_INTERVAL_MAX = 5400,
+ FACE_DATASET_FETCH_INTERVAL_DEFAULT = 3600
+};
+
enum {
HELLO_RETRIES_MIN = 1,
HELLO_RETRIES_DEFAULT = 3,
@@ -261,6 +274,30 @@
}
void
+ setFaceDatasetFetchTries(uint32_t count)
+ {
+ m_faceDatasetFetchTries = count;
+ }
+
+ uint32_t
+ getFaceDatasetFetchTries() const
+ {
+ return m_faceDatasetFetchTries;
+ }
+
+ void
+ setFaceDatasetFetchInterval(ndn::time::seconds interval)
+ {
+ m_faceDatasetFetchInterval = interval;
+ }
+
+ const ndn::time::seconds
+ getFaceDatasetFetchInterval() const
+ {
+ return m_faceDatasetFetchInterval;
+ }
+
+ void
setLogLevel(const std::string& logLevel)
{
m_logLevel = logLevel;
@@ -423,6 +460,9 @@
uint32_t m_firstHelloInterval;
uint32_t m_routingCalcInterval;
+ uint32_t m_faceDatasetFetchTries;
+ ndn::time::seconds m_faceDatasetFetchInterval;
+
ndn::time::seconds m_lsaInterestLifetime;
uint32_t m_routerDeadInterval;
std::string m_logLevel;
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index 52e8997..4a995de 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -17,8 +17,6 @@
* You should have received a copy of the GNU General Public License along with
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
- * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
- *
**/
#include "nlsr.hpp"
@@ -68,13 +66,6 @@
m_nlsr.getConfParameter().getInterestResendTime());
_LOG_DEBUG("Sending scheduled interest: " << interestName);
}
- // If it does not have a Face, we need to give it one. A
- // successful registration prompts a callback that sends the hello
- // Interest to the new Face.
- else {
- registerPrefixes((*it).getName(), (*it).getFaceUri().toString(),
- (*it).getLinkCost(), ndn::time::milliseconds::max());
- }
}
scheduleInterest(m_nlsr.getConfParameter().getInfoInterestInterval());
}
@@ -126,12 +117,6 @@
expressInterest(interestName,
m_nlsr.getConfParameter().getInterestResendTime());
}
- // If the originator of the Interest currently lacks a Face, we
- // need to give it one.
- else {
- registerPrefixes(adjacent->getName(), adjacent->getFaceUri().toString(),
- adjacent->getLinkCost(), ndn::time::milliseconds::max());
- }
}
}
}
@@ -235,82 +220,4 @@
_LOG_DEBUG("Validation Error: " << msg);
}
-
- // Asks the FIB to register the supplied adjacency (in other words,
- // create a Face for it).
-void
-HelloProtocol::registerPrefixes(const ndn::Name& adjName, const std::string& faceUri,
- double linkCost, const ndn::time::milliseconds& timeout)
-{
- m_nlsr.getFib().registerPrefix(adjName, faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0,
- std::bind(&HelloProtocol::onRegistrationSuccess,
- this, _1, adjName,timeout),
- std::bind(&HelloProtocol::onRegistrationFailure,
- this, _1, adjName));
-}
-
- // After we create a new Face, we need to set it up for use. This
- // function sets the controlling strategy, registers prefixes in
- // sync, broadcast, and LSA.
-void
-HelloProtocol::onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
- const ndn::Name& neighbor,const ndn::time::milliseconds& timeout)
-{
- auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
- if (adjacent != m_nlsr.getAdjacencyList().end()){
- adjacent->setFaceId(commandSuccessResult.getFaceId());
- ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
- broadcastKeyPrefix.append("KEYS");
- std::string faceUri = adjacent->getFaceUri().toString();
- double linkCost = adjacent->getLinkCost();
- m_nlsr.getFib().registerPrefix(m_nlsr.getConfParameter().getChronosyncPrefix(),
- faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
- m_nlsr.getFib().registerPrefix(m_nlsr.getConfParameter().getLsaPrefix(),
- faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
- m_nlsr.getFib().registerPrefix(broadcastKeyPrefix,
- faceUri, linkCost, timeout,
- ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
-
- // Sends a Hello Interest to determine status before the next scheduled.
- // interest name: /<neighbor>/NLSR/INFO/<router>
- ndn::Name interestName(neighbor);
- interestName.append(NLSR_COMPONENT);
- interestName.append(INFO_COMPONENT);
- interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
- expressInterest(interestName,
- m_nlsr.getConfParameter().getInterestResendTime());
- }
-}
-
-void
-HelloProtocol::onRegistrationFailure(const ndn::nfd::ControlResponse& response,
- const ndn::Name& name)
-{
- _LOG_DEBUG(response.getText() << " (code: " << response.getCode() << ")");
- /*
- * If NLSR can not create face for given faceUri then it will treat this
- * failure as one INFO interest timed out. So that NLSR can move on with
- * building Adj Lsa and calculate routing table. NLSR does not build Adj
- * Lsa unless all the neighbors are ACTIVE or DEAD. For considering the
- * missconfigured(link) neighbour dead this is required.
- */
- auto adjacent = m_nlsr.getAdjacencyList().findAdjacent(name);
- if (adjacent != m_nlsr.getAdjacencyList().end()) {
- adjacent->setInterestTimedOutNo(adjacent->getInterestTimedOutNo() + 1);
- Adjacent::Status status = adjacent->getStatus();
- uint32_t infoIntTimedOutCount = adjacent->getInterestTimedOutNo();
-
- if (infoIntTimedOutCount == m_nlsr.getConfParameter().getInterestRetryNumber()) {
- if (status == Adjacent::STATUS_ACTIVE) {
- adjacent->setStatus(Adjacent::STATUS_INACTIVE);
- }
-
- m_nlsr.getLsdb().scheduleAdjLsaBuild();
- }
- }
-}
-
} // namespace nlsr
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index 1817850..808b843 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -117,9 +117,6 @@
onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
const ndn::Name& neighbor, const ndn::time::milliseconds& timeout);
- void
- registerPrefixes(const ndn::Name& adjName, const std::string& faceUri,
- double linkCost, const ndn::time::milliseconds& timeout);
private:
Nlsr& m_nlsr;
ndn::Scheduler& m_scheduler;
diff --git a/src/nlsr-runner.cpp b/src/nlsr-runner.cpp
index 29e4737..827593a 100644
--- a/src/nlsr-runner.cpp
+++ b/src/nlsr-runner.cpp
@@ -75,7 +75,6 @@
std::cerr << "ERROR: " << e.what() << std::endl;
m_nlsr.getFib().clean();
- m_nlsr.destroyFaces();
}
}
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index ca829e0..5709313 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -29,6 +29,7 @@
#include "adjacent.hpp"
#include "logger.hpp"
+#include <ndn-cxx/util/face-uri.hpp>
namespace nlsr {
@@ -63,9 +64,12 @@
m_routerNameDispatcher,
m_nlsrFace,
m_keyChain)
+
, m_helloProtocol(*this, scheduler)
, m_certificateCache(new ndn::CertificateCacheTtl(ioService))
, m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache, m_certStore)
+ , m_controller(m_nlsrFace, m_keyChain, m_validator)
+ , m_faceDatasetController(m_nlsrFace, m_keyChain)
, m_prefixUpdateProcessor(m_nlsrFace,
m_namePrefixList,
m_nlsrLsdb,
@@ -252,6 +256,9 @@
setInfoInterestFilter();
setLsaInterestFilter();
+ initializeFaces(std::bind(&Nlsr::processFaceDataset, this, _1),
+ std::bind(&Nlsr::onFaceDatasetFetchTimeout, this, _1, _2, 0));
+
// Set event intervals
setFirstHelloInterval(m_confParam.getFirstHelloInterval());
m_nlsrLsdb.setAdjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval());
@@ -377,78 +384,195 @@
}
void
-Nlsr::onDestroyFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult)
-{
-}
-
-void
-Nlsr::onDestroyFaceFailure(const ndn::nfd::ControlResponse& response)
-{
- std::cerr << response.getText() << " (code: " << response.getCode() << ")";
- BOOST_THROW_EXCEPTION(Error("Error: Face destruction failed"));
-}
-
-void
-Nlsr::destroyFaces()
-{
- std::list<Adjacent>& adjacents = m_adjacencyList.getAdjList();
- for (std::list<Adjacent>::iterator it = adjacents.begin();
- it != adjacents.end(); it++) {
- m_fib.destroyFace((*it).getFaceUri().toString(),
- std::bind(&Nlsr::onDestroyFaceSuccess, this, _1),
- std::bind(&Nlsr::onDestroyFaceFailure, this, _1));
- }
-}
-
-void
Nlsr::onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification)
{
_LOG_TRACE("Nlsr::onFaceEventNotification called");
- ndn::nfd::FaceEventKind kind = faceEventNotification.getKind();
- if (kind == ndn::nfd::FACE_EVENT_DESTROYED) {
- uint64_t faceId = faceEventNotification.getFaceId();
+ switch (faceEventNotification.getKind()) {
+ case ndn::nfd::FACE_EVENT_DESTROYED: {
+ uint64_t faceId = faceEventNotification.getFaceId();
- auto adjacent = m_adjacencyList.findAdjacent(faceId);
+ auto adjacent = m_adjacencyList.findAdjacent(faceId);
- if (adjacent != m_adjacencyList.end()) {
- _LOG_DEBUG("Face to " << adjacent->getName() << " with face id: " << faceId << " destroyed");
+ if (adjacent != m_adjacencyList.end()) {
+ _LOG_DEBUG("Face to " << adjacent->getName() << " with face id: " << faceId << " destroyed");
- adjacent->setFaceId(0);
+ adjacent->setFaceId(0);
- // Only trigger an Adjacency LSA build if this node is changing
- // from ACTIVE to INACTIVE since this rebuild will effectively
- // cancel the previous Adjacency LSA refresh event and schedule
- // a new one further in the future.
- //
- // Continuously scheduling the refresh in the future will block
- // the router from refreshing its Adjacency LSA. Since other
- // routers' Name prefixes' expiration times are updated when
- // this router refreshes its Adjacency LSA, the other routers'
- // prefixes will expire and be removed from the RIB.
- //
- // This check is required to fix Bug #2733 for now. This check
- // would be unnecessary to fix Bug #2733 when Issue #2732 is
- // completed, but the check also helps with optimization so it
- // can remain even when Issue #2732 is implemented.
- if (adjacent->getStatus() == Adjacent::STATUS_ACTIVE) {
- adjacent->setStatus(Adjacent::STATUS_INACTIVE);
+ // Only trigger an Adjacency LSA build if this node is changing
+ // from ACTIVE to INACTIVE since this rebuild will effectively
+ // cancel the previous Adjacency LSA refresh event and schedule
+ // a new one further in the future.
+ //
+ // Continuously scheduling the refresh in the future will block
+ // the router from refreshing its Adjacency LSA. Since other
+ // routers' Name prefixes' expiration times are updated when
+ // this router refreshes its Adjacency LSA, the other routers'
+ // prefixes will expire and be removed from the RIB.
+ //
+ // This check is required to fix Bug #2733 for now. This check
+ // would be unnecessary to fix Bug #2733 when Issue #2732 is
+ // completed, but the check also helps with optimization so it
+ // can remain even when Issue #2732 is implemented.
+ if (adjacent->getStatus() == Adjacent::STATUS_ACTIVE) {
+ adjacent->setStatus(Adjacent::STATUS_INACTIVE);
- // A new adjacency LSA cannot be built until the neighbor is marked INACTIVE and
- // has met the HELLO retry threshold
- adjacent->setInterestTimedOutNo(m_confParam.getInterestRetryNumber());
+ // A new adjacency LSA cannot be built until the neighbor is marked INACTIVE and
+ // has met the HELLO retry threshold
+ adjacent->setInterestTimedOutNo(m_confParam.getInterestRetryNumber());
- if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
- getRoutingTable().scheduleRoutingTableCalculation(*this);
- }
- else {
- m_nlsrLsdb.scheduleAdjLsaBuild();
+ if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
+ getRoutingTable().scheduleRoutingTableCalculation(*this);
+ }
+ else {
+ m_nlsrLsdb.scheduleAdjLsaBuild();
+ }
}
}
+ break;
}
+ case ndn::nfd::FACE_EVENT_CREATED: {
+ // Find the neighbor in our adjacency list
+ _LOG_DEBUG("Face created event received.");
+ auto adjacent = m_adjacencyList.findAdjacent(
+ ndn::util::FaceUri(faceEventNotification.getRemoteUri()));
+ // If we have a neighbor by that FaceUri and it has no FaceId, we
+ // have a match.
+ if (adjacent != m_adjacencyList.end()) {
+ _LOG_DEBUG("Face creation event matches neighbor: " << adjacent->getName()
+ << ". New Face ID: " << faceEventNotification.getFaceId()
+ << ". Registering prefixes.");
+ adjacent->setFaceId(faceEventNotification.getFaceId());
+
+ registerAdjacencyPrefixes(*adjacent, ndn::time::milliseconds::max());
+ }
+ break;
+ }
+ default:
+ break;
}
}
+void
+Nlsr::initializeFaces(const FetchDatasetCallback& onFetchSuccess,
+ const FetchDatasetTimeoutCallback& onFetchFailure)
+{
+ _LOG_TRACE("Initializing Faces...");
+
+ m_faceDatasetController.fetch<ndn::nfd::FaceDataset>(onFetchSuccess, onFetchFailure);
+
+}
+
+void
+Nlsr::processFaceDataset(const std::vector<ndn::nfd::FaceStatus>& faces)
+{
+ // Iterate over each neighbor listed in nlsr.conf
+ bool anyFaceChanged = false;
+ for (auto&& adjacency : m_adjacencyList.getAdjList()) {
+
+ const std::string faceUriString = adjacency.getFaceUri().toString();
+ // Check the list of FaceStatus objects we got for a match
+ for (const ndn::nfd::FaceStatus& faceStatus : faces) {
+
+ // Set the adjacency FaceID if we find a URI match and it was
+ // previously unset. Change the boolean to true.
+ if (adjacency.getFaceId() == 0 && faceUriString == faceStatus.getRemoteUri()) {
+ adjacency.setFaceId(faceStatus.getFaceId());
+ anyFaceChanged = true;
+ // Register the prefixes for each neighbor
+ this->registerAdjacencyPrefixes(adjacency, ndn::time::milliseconds::max());
+ }
+ }
+ // If this adjacency has no information in this dataset, then one
+ // of two things is happening: 1. NFD is starting slowly and this
+ // Face wasn't ready yet, or 2. NFD is configured
+ // incorrectly and this Face isn't available.
+ if (adjacency.getFaceId() == 0) {
+ _LOG_WARN("The adjacency " << adjacency.getName() <<
+ " has no Face information in this dataset.");
+ }
+ }
+
+ if (anyFaceChanged) {
+ // Only do these things if something has changed. Schedule an
+ // adjacency LSA build to update with all of the new neighbors if
+ // HR is off.
+ if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
+ getRoutingTable().scheduleRoutingTableCalculation(*this);
+ }
+ else {
+ m_nlsrLsdb.scheduleAdjLsaBuild();
+ }
+
+ // Begin the Hello Protocol loop immediately, so we don't wait.
+ m_helloProtocol.sendScheduledInterest(0);
+ }
+
+ scheduleDatasetFetch();
+}
+
+void
+Nlsr::registerAdjacencyPrefixes(const Adjacent& adj,
+ const ndn::time::milliseconds& timeout)
+{
+ std::string faceUri = adj.getFaceUri().toString();
+ double linkCost = adj.getLinkCost();
+
+ m_fib.registerPrefix(adj.getName(), faceUri, linkCost,
+ timeout, ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+
+ m_fib.registerPrefix(m_confParam.getChronosyncPrefix(),
+ faceUri, linkCost, timeout,
+ ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+
+ m_fib.registerPrefix(m_confParam.getLsaPrefix(),
+ faceUri, linkCost, timeout,
+ ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+
+ ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
+ broadcastKeyPrefix.append("KEYS");
+ m_fib.registerPrefix(broadcastKeyPrefix,
+ faceUri, linkCost, timeout,
+ ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+}
+
+void
+Nlsr::onFaceDatasetFetchTimeout(uint32_t code,
+ const std::string& msg,
+ uint32_t nRetriesSoFar)
+{
+ // If we have exceeded the maximum attempt count, do not try again.
+ if (nRetriesSoFar++ < m_confParam.getFaceDatasetFetchTries()) {
+ _LOG_DEBUG("Failed to fetch dataset: " << msg << ". Attempting retry #" << nRetriesSoFar);
+ m_faceDatasetController.fetch<ndn::nfd::FaceDataset>(std::bind(&Nlsr::processFaceDataset,
+ this, _1),
+ std::bind(&Nlsr::onFaceDatasetFetchTimeout,
+ this, _1, _2, nRetriesSoFar));
+ }
+ else {
+ _LOG_ERROR("Failed to fetch dataset: " << msg << ". Exceeded limit of " <<
+ m_confParam.getFaceDatasetFetchTries() << ", so not trying again this time.");
+ // If we fail to fetch it, just do nothing until the next
+ // interval. Since this is a backup mechanism, we aren't as
+ // concerned with retrying.
+ scheduleDatasetFetch();
+ }
+}
+
+void
+Nlsr::scheduleDatasetFetch()
+{
+ m_scheduler.scheduleEvent(m_confParam.getFaceDatasetFetchInterval(),
+ [this] {
+ this->initializeFaces(
+ [this] (const std::vector<ndn::nfd::FaceStatus>& faces) {
+ this->processFaceDataset(faces);
+ },
+ [this] (uint32_t code, const std::string& msg) {
+ this->onFaceDatasetFetchTimeout(code, msg, 0);
+ });
+ });
+}
void
Nlsr::startEventLoop()
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 81629ae..bb67f2d 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -33,6 +33,9 @@
#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
#include <ndn-cxx/mgmt/nfd/face-monitor.hpp>
#include <ndn-cxx/mgmt/dispatcher.hpp>
+#include <ndn-cxx/mgmt/nfd/face-status.hpp>
+#include <ndn-cxx/data.hpp>
+#include <ndn-cxx/encoding/block.hpp>
#include "adjacency-list.hpp"
#include "common.hpp"
@@ -57,7 +60,9 @@
class Nlsr
{
- friend class NlsrRunner;
+public:
+ using FetchDatasetCallback = std::function<void(const std::vector<ndn::nfd::FaceStatus>&)>;
+ using FetchDatasetTimeoutCallback = std::function<void(uint32_t, const std::string&)>;
class Error : public std::runtime_error
{
@@ -69,7 +74,6 @@
}
};
-public:
Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler, ndn::Face& face, ndn::KeyChain& keyChain);
void
@@ -225,6 +229,51 @@
void
initialize();
+ /*! \brief Initializes neighbors' Faces using information from NFD.
+ * \sa Nlsr::initialize()
+ * \sa Nlsr::processFaceDataset()
+ *
+ * This function serves as the entry-point for initializing the
+ * neighbors listed in nlsr.conf during Nlsr::initialize(). NLSR
+ * will attempt to fetch a dataset of Faces from NFD, and configure
+ * each of its neighbors using information from that dataset. The
+ * explicit callbacks allow for better testability.
+ */
+ void
+ initializeFaces(const FetchDatasetCallback& onFetchSuccess,
+ const FetchDatasetTimeoutCallback& onFetchFailure);
+
+ void
+ onFaceDatasetFetchTimeout(uint32_t code,
+ const std::string& reason,
+ uint32_t nRetriesSoFar);
+
+ /*! \brief Consumes a Face StatusDataset to configure NLSR neighbors.
+ * \sa Nlsr::initializeFaces
+ * \param faces A Face Dataset that should conform to FaceMgmt specifications.
+ *
+ * This function processes a Face StatusDataset that should conform
+ * to the FaceMgmt specifications listed
+ * [here](https://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset).
+ * Any newly configured neighbors will have prefixes registered with NFD
+ * and be sent Hello Interests as well.
+ */
+ void
+ processFaceDataset(const std::vector<ndn::nfd::FaceStatus>& faces);
+
+ /*! \brief Registers NLSR-specific prefixes for a neighbor (Adjacent)
+ * \sa Nlsr::initializeFaces
+ * \param adj A reference to the neighbor to register prefixes for
+ * \param timeout The amount of time to give NFD to respond to *each* registration request.
+ *
+ * Registers the prefixes in NFD that NLSR needs to route with a
+ * neighbor. The timeout given is how long to set the timeout for
+ * *each* registration request that is made.
+ */
+ void
+ registerAdjacencyPrefixes(const Adjacent& adj,
+ const ndn::time::milliseconds& timeout);
+
void
initializeKey();
@@ -297,14 +346,6 @@
}
void
- createFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
- destroyFaces();
-
- void
setStrategies();
void
@@ -316,8 +357,7 @@
return m_firstHelloInterval;
}
- /**
- * \brief Canonize the URI for this and all proceeding neighbors in a list.
+ /*! \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
@@ -365,12 +405,6 @@
onKeyPrefixRegSuccess(const ndn::Name& name);
void
- onDestroyFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult);
-
- void
- onDestroyFaceFailure(const ndn::nfd::ControlResponse& response);
-
- void
onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification);
void
@@ -379,8 +413,7 @@
m_firstHelloInterval = interval;
}
- /**
- * \brief Continues canonizing neighbor URIs.
+ /*! \brief Continues canonizing neighbor URIs.
*
* For testability reasons, we want what each instance of
* canonization does after completion to be controllable. The best
@@ -390,6 +423,9 @@
void
canonizeContinuation(std::list<Adjacent>::iterator iterator);
+ void
+ scheduleDatasetFetch();
+
public:
static const ndn::Name LOCALHOST_PREFIX;
@@ -421,7 +457,13 @@
private:
std::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
security::CertificateStore m_certStore;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Validator m_validator;
+
+private:
+ ndn::nfd::Controller m_controller;
+ ndn::nfd::Controller m_faceDatasetController;
ndn::security::SigningInfo m_signingInfo;
ndn::Name m_defaultCertName;
update::PrefixUpdateProcessor m_prefixUpdateProcessor;
@@ -430,6 +472,8 @@
ndn::nfd::FaceMonitor m_faceMonitor;
uint32_t m_firstHelloInterval;
+
+ friend class NlsrRunner;
};
} // namespace nlsr
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 73cde75..49ce647 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -209,37 +209,6 @@
}
void
-Fib::createFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- m_faceController.createFace(faceUri, onSuccess, onFailure);
-}
-
-void
-Fib::destroyFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- createFace(faceUri,
- std::bind(&Fib::destroyFaceInNfd, this, _1, onSuccess, onFailure),
- onFailure);
-}
-
-void
-Fib::destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- ndn::nfd::ControlParameters faceParameters;
- faceParameters
- .setFaceId(faceDestroyResult.getFaceId());
- m_controller.start<ndn::nfd::FaceDestroyCommand>(faceParameters,
- onSuccess,
- onFailure);
-}
-
-void
Fib::registerPrefix(const ndn::Name& namePrefix, const std::string& faceUri,
uint64_t faceCost, const ndn::time::milliseconds& timeout,
uint64_t flags, uint8_t times)
@@ -264,35 +233,6 @@
}
}
-typedef void(Fib::*RegisterPrefixCallback)(const ndn::nfd::ControlParameters&,
- const ndn::nfd::ControlParameters&, uint8_t,
- const CommandSucceedCallback&,
- const CommandFailCallback&);
-
-void
-Fib::registerPrefix(const ndn::Name& namePrefix,
- const std::string& faceUri,
- uint64_t faceCost,
- const ndn::time::milliseconds& timeout,
- uint64_t flags,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-
-{
- ndn::nfd::ControlParameters parameters;
- parameters
- .setName(namePrefix)
- .setFlags(flags)
- .setCost(faceCost)
- .setExpirationPeriod(timeout)
- .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
- createFace(faceUri,
- std::bind(static_cast<RegisterPrefixCallback>(&Fib::registerPrefixInNfd),
- this, _1, parameters, times, onSuccess, onFailure),
- onFailure);
-}
-
void
Fib::registerPrefixInNfd(ndn::nfd::ControlParameters& parameters,
const std::string& faceUri,
@@ -304,33 +244,13 @@
"Successful in name registration",
faceUri),
std::bind(&Fib::onRegistrationFailure,
- this, _1,
+ this, _1,
"Failed in name registration",
parameters,
faceUri, times));
}
void
-Fib::registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
- const ndn::nfd::ControlParameters& parameters,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure)
-{
- ndn::nfd::ControlParameters controlParameters;
- controlParameters
- .setName(parameters.getName())
- .setFaceId(faceCreateResult.getFaceId())
- .setCost(parameters.getCost())
- .setFlags(parameters.getFlags())
- .setExpirationPeriod(parameters.getExpirationPeriod())
- .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
- m_controller.start<ndn::nfd::RibRegisterCommand>(controlParameters,
- onSuccess,
- onFailure);
-}
-
-void
Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
{
uint32_t faceId = m_faceMap.getFaceId(faceUri);
@@ -374,6 +294,9 @@
_LOG_DEBUG("Register successful Prefix: " << commandSuccessResult.getName() <<
" Face Uri: " << faceUri);
+ // Update the adjacency list with the new Face ID
+ m_adjacencyList.findAdjacent(faceUri)->setFaceId(commandSuccessResult.getFaceId());
+ // Update the fast-access FaceMap with the new Face ID, too
m_faceMap.update(faceUri, commandSuccessResult.getFaceId());
m_faceMap.writeLog();
}
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 10aa4fa..2705e47 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -26,15 +26,12 @@
#include "face-map.hpp"
#include "fib-entry.hpp"
#include "test-access-control.hpp"
-#include "utility/face-controller.hpp"
#include <ndn-cxx/mgmt/nfd/controller.hpp>
#include <ndn-cxx/util/time.hpp>
namespace nlsr {
-typedef ndn::nfd::Controller::CommandSucceedCallback CommandSucceedCallback;
-typedef ndn::nfd::Controller::CommandFailCallback CommandFailCallback;
typedef std::function<void(FibEntry&)> afterRefreshCallback;
class AdjacencyList;
@@ -49,7 +46,6 @@
: m_scheduler(scheduler)
, m_refreshTime(0)
, m_controller(face, keyChain)
- , m_faceController(face.getIoService(), m_controller)
, m_adjacencyList(adjacencyList)
, m_confParameter(conf)
{
@@ -82,26 +78,11 @@
uint8_t times);
void
- registerPrefix(const ndn::Name& namePrefix,
- const std::string& faceUri,
- uint64_t faceCost,
- const ndn::time::milliseconds& timeout,
- uint64_t flags,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
setStrategy(const ndn::Name& name, const std::string& strategy, uint32_t count);
void
writeLog();
- void
- destroyFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
private:
bool
isPrefixUpdatable(const ndn::Name& name);
@@ -113,28 +94,11 @@
getNumberOfFacesForName(NexthopList& nextHopList);
void
- createFace(const std::string& faceUri,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
registerPrefixInNfd(ndn::nfd::ControlParameters& parameters,
const std::string& faceUri,
uint8_t times);
void
- registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
- const ndn::nfd::ControlParameters& parameters,
- uint8_t times,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
- destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult,
- const CommandSucceedCallback& onSuccess,
- const CommandFailCallback& onFailure);
-
- void
unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri);
void
@@ -184,7 +148,6 @@
ndn::Scheduler& m_scheduler;
int32_t m_refreshTime;
ndn::nfd::Controller m_controller;
- util::FaceController m_faceController;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
FaceMap m_faceMap;
diff --git a/src/utility/face-controller.cpp b/src/utility/face-controller.cpp
deleted file mode 100644
index e6c0a8b..0000000
--- a/src/utility/face-controller.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017, The University of Memphis,
- * Regents of the University of California
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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
- * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- **/
-
-#include "face-controller.hpp"
-
-#include "common.hpp"
-#include "logger.hpp"
-
-namespace nlsr {
-namespace util {
-
-INIT_LOGGER("FaceController");
-
-using ndn::util::FaceUri;
-
-void
-FaceController::createFace(const std::string& request,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure)
-{
- FaceUri uri(request);
-
- _LOG_TRACE("Converting " << uri << " to canonical form");
- uri.canonize(std::bind(&FaceController::onCanonizeSuccess, this, _1, onSuccess, onFailure, uri),
- std::bind(&FaceController::onCanonizeFailure, this, _1, onSuccess, onFailure, uri),
- m_ioService, TIME_ALLOWED_FOR_CANONIZATION);
-}
-
-void
-FaceController::createFaceInNfd(const FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure)
-{
- ndn::nfd::ControlParameters faceParameters;
- faceParameters.setUri(uri.toString());
-
- _LOG_DEBUG("Creating Face in NFD with face-uri: " << uri);
- m_controller.start<ndn::nfd::FaceCreateCommand>(faceParameters, onSuccess,
- [onSuccess, onFailure, uri] (const ndn::nfd::ControlResponse& response) {
- ndn::nfd::ControlParameters faceParams(response.getBody());
- if (response.getCode() == 409 && faceParams.getUri() == uri.toString()) {
- _LOG_DEBUG("Got 409 - treating as success");
- onSuccess(faceParams);
- }
- else {
- onFailure(response);
- }
- }
- );
-}
-
-void
-FaceController::onCanonizeSuccess(const FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const FaceUri& request)
-{
- _LOG_DEBUG("Converted " << request << " to canonical form: " << uri);
-
- createFaceInNfd(uri, onSuccess, onFailure);
-}
-
-void
-FaceController::onCanonizeFailure(const std::string& reason,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const FaceUri& request)
-{
- _LOG_WARN("Could not convert " << request << " to canonical form: " << reason);
- onFailure(ndn::nfd::ControlResponse(CANONIZE_ERROR_CODE,
- "Could not canonize face-uri: " + request.toString()));
-}
-
-} // namespace util
-} // namespace nlsr
diff --git a/src/utility/face-controller.hpp b/src/utility/face-controller.hpp
deleted file mode 100644
index d44c2ec..0000000
--- a/src/utility/face-controller.hpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017, The University of Memphis,
- * Regents of the University of California,
- * Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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
- * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#ifndef NLSR_UTIL_FACE_CONTROLLER_HPP
-#define NLSR_UTIL_FACE_CONTROLLER_HPP
-
-#include <ndn-cxx/util/face-uri.hpp>
-#include <ndn-cxx/mgmt/nfd/controller.hpp>
-
-namespace nlsr {
-namespace util {
-
-class FaceController : boost::noncopyable
-{
-public:
- typedef ndn::nfd::Controller::CommandSucceedCallback CommandSuccessCallback;
- typedef ndn::nfd::Controller::CommandFailCallback CommandFailureCallback;
-
- FaceController(boost::asio::io_service& io, ndn::nfd::Controller& controller)
- : m_ioService(io)
- , m_controller(controller)
- {
- }
-
- void
- createFace(const std::string& request,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure);
-
-private:
- void
- createFaceInNfd(const ndn::util::FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure);
-
- void
- onCanonizeSuccess(const ndn::util::FaceUri& uri,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const ndn::util::FaceUri& request);
-
- void
- onCanonizeFailure(const std::string& reason,
- const CommandSuccessCallback& onSuccess,
- const CommandFailureCallback& onFailure,
- const ndn::util::FaceUri& request);
-
-private:
- boost::asio::io_service& m_ioService;
- ndn::nfd::Controller& m_controller;
-
- static const uint32_t CANONIZE_ERROR_CODE = 408;
-};
-
-} // namespace util
-} // namespace nlsr
-
-#endif // NLSR_UTIL_FACE_CONTROLLER_HPP
diff --git a/src/validator.cpp b/src/validator.cpp
new file mode 100644
index 0000000..a73c9ee
--- /dev/null
+++ b/src/validator.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR 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.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "validator.hpp"
+
+namespace nlsr {
+
+void
+Validator::checkPolicy(const ndn::Data& data, int nSteps, const ndn::OnDataValidated& onValidated,
+ const ndn::OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps)
+{
+ if (!m_shouldValidate) {
+ onValidated(data.shared_from_this());
+ }
+ else {
+ ValidatorConfig::checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
+ }
+}
+
+void
+Validator::afterCheckPolicy(const NextSteps& nextSteps, const OnFailure& onFailure)
+{
+ if (m_face == nullptr) {
+ onFailure("Require more information to validate the packet!");
+ return;
+ }
+
+ for (const std::shared_ptr<ndn::ValidationRequest>& request : nextSteps) {
+
+ ndn::Interest& interest = request->m_interest;
+
+ // Look for certificate in permanent storage
+ std::shared_ptr<const ndn::IdentityCertificate> cert = m_certStore.find(interest.getName());
+
+ if (cert != nullptr) {
+ // If the certificate is found, no reason to express interest
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(interest.getName());
+ data->setContent(cert->wireEncode());
+
+ Validator::onData(interest, *data, request);
+ }
+ else {
+ // Prepend broadcast prefix to interest name
+ ndn::Name broadcastName = m_broadcastPrefix;
+ broadcastName.append(interest.getName());
+ interest.setName(broadcastName);
+
+ // Attempt to fetch the certificate
+ m_face->expressInterest(interest,
+ std::bind(&Validator::onData, this, _1, _2, request),
+ std::bind(&Validator::onTimeout, // Nack
+ this, _1, request->m_nRetries,
+ onFailure,
+ request),
+ std::bind(&Validator::onTimeout,
+ this, _1, request->m_nRetries,
+ onFailure,
+ request));
+ }
+ }
+}
+
+std::shared_ptr<const ndn::Data>
+Validator::preCertificateValidation(const ndn::Data& data)
+{
+ std::shared_ptr<ndn::Data> internalData = std::make_shared<ndn::Data>();
+ internalData->wireDecode(data.getContent().blockFromValue());
+ return internalData;
+}
+
+} // namespace nlsr
diff --git a/src/validator.hpp b/src/validator.hpp
index 4387ea5..c4f2a19 100644
--- a/src/validator.hpp
+++ b/src/validator.hpp
@@ -49,6 +49,7 @@
security::CertificateStore& certStore,
const int stepLimit = 10)
: ndn::ValidatorConfig(face, cache, ndn::ValidatorConfig::DEFAULT_GRACE_INTERVAL, stepLimit)
+ , m_shouldValidate(true)
, m_broadcastPrefix(broadcastPrefix)
, m_certStore(certStore)
{
@@ -75,57 +76,22 @@
protected:
typedef std::vector<std::shared_ptr<ndn::ValidationRequest>> NextSteps;
- virtual void
+ void
+ checkPolicy(const ndn::Data& data,
+ int nSteps,
+ const ndn::OnDataValidated& onValidated,
+ const ndn::OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps) override;
+
+ void
afterCheckPolicy(const NextSteps& nextSteps,
- const OnFailure& onFailure)
- {
- if (m_face == nullptr) {
- onFailure("Require more information to validate the packet!");
- return;
- }
+ const OnFailure& onFailure) override;
- for (const std::shared_ptr<ndn::ValidationRequest>& request : nextSteps) {
+ std::shared_ptr<const ndn::Data>
+ preCertificateValidation(const ndn::Data& data) override;
- ndn::Interest& interest = request->m_interest;
-
- // Look for certificate in permanent storage
- std::shared_ptr<const ndn::IdentityCertificate> cert = m_certStore.find(interest.getName());
-
- if (cert != nullptr) {
- // If the certificate is found, no reason to express interest
- std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(interest.getName());
- data->setContent(cert->wireEncode());
-
- Validator::onData(interest, *data, request);
- }
- else {
- // Prepend broadcast prefix to interest name
- ndn::Name broadcastName = m_broadcastPrefix;
- broadcastName.append(interest.getName());
- interest.setName(broadcastName);
-
- // Attempt to fetch the certificate
- m_face->expressInterest(interest,
- std::bind(&Validator::onData, this, _1, _2, request),
- std::bind(&Validator::onTimeout, // Nack
- this, _1, request->m_nRetries,
- onFailure,
- request),
- std::bind(&Validator::onTimeout,
- this, _1, request->m_nRetries,
- onFailure,
- request));
- }
- }
- }
-
- virtual std::shared_ptr<const ndn::Data>
- preCertificateValidation(const ndn::Data& data)
- {
- std::shared_ptr<ndn::Data> internalData = std::make_shared<ndn::Data>();
- internalData->wireDecode(data.getContent().blockFromValue());
- return internalData;
- }
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ bool m_shouldValidate;
private:
ndn::Name m_broadcastPrefix;
diff --git a/tests/test-common.cpp b/tests/test-common.cpp
new file mode 100644
index 0000000..e6b5e78
--- /dev/null
+++ b/tests/test-common.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, The University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR 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.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "test-common.hpp"
+
+namespace nlsr {
+namespace test {
+
+ndn::Data&
+signData(ndn::Data& data)
+{
+ ndn::SignatureSha256WithRsa fakeSignature;
+ fakeSignature.setValue(ndn::encoding::makeEmptyBlock(ndn::tlv::SignatureValue));
+ data.setSignature(fakeSignature);
+ data.wireEncode();
+
+ return data;
+}
+
+MockNfdMgmtFixture::MockNfdMgmtFixture()
+ : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
+{
+}
+
+void
+MockNfdMgmtFixture::signDatasetReply(ndn::Data& data)
+{
+ signData(data);
+}
+
+void
+UnitTestTimeFixture::advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks)
+{
+ for (size_t i = 0; i < nTicks; ++i) {
+ steadyClock->advance(tick);
+ systemClock->advance(tick);
+
+ if (g_ioService.stopped()) {
+ g_ioService.reset();
+ }
+
+ g_ioService.poll();
+ }
+}
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index 817b77e..dcba6c0 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -17,7 +17,6 @@
* You should have received a copy of the GNU General Public License along with
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
- *
**/
#ifndef NLSR_TEST_COMMON_HPP
@@ -32,9 +31,25 @@
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/util/time-unit-test-clock.hpp>
+#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
namespace nlsr {
namespace test {
+ndn::Data&
+signData(ndn::Data& data);
+
+/** \brief add a fake signature to Data
+ */
+inline shared_ptr<ndn::Data>
+signData(shared_ptr<ndn::Data> data)
+{
+ signData(*data);
+ return data;
+}
+
class BaseFixture
{
public:
@@ -65,25 +80,89 @@
}
void
- advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks = 1)
- {
- for (size_t i = 0; i < nTicks; ++i) {
- steadyClock->advance(tick);
- systemClock->advance(tick);
-
- if (g_ioService.stopped()) {
- g_ioService.reset();
- }
-
- g_ioService.poll();
- }
- }
+ advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks = 1);
protected:
std::shared_ptr<ndn::time::UnitTestSteadyClock> steadyClock;
std::shared_ptr<ndn::time::UnitTestSystemClock> systemClock;
};
+class MockNfdMgmtFixture : public UnitTestTimeFixture
+{
+public:
+ MockNfdMgmtFixture();
+
+ /** \brief send one WireEncodable in reply to StatusDataset request
+ * \param prefix dataset prefix without version and segment
+ * \param payload payload block
+ * \note payload must fit in one Data
+ * \pre Interest for dataset has been expressed, sendDataset has not been invoked
+ */
+ template<typename T>
+ void
+ sendDataset(const ndn::Name& prefix, const T& payload)
+ {
+ BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));
+
+ this->sendDatasetReply(prefix, payload.wireEncode());
+ }
+
+ /** \brief send two WireEncodables in reply to StatusDataset request
+ * \param prefix dataset prefix without version and segment
+ * \param payload1 first vector item
+ * \param payload2 second vector item
+ * \note all payloads must fit in one Data
+ * \pre Interest for dataset has been expressed, sendDataset has not been invoked
+ */
+ template<typename T1, typename T2>
+ void
+ sendDataset(const ndn::Name& prefix, const T1& payload1, const T2& payload2)
+ {
+ BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
+ BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));
+
+ ndn::encoding::EncodingBuffer buffer;
+ payload2.wireEncode(buffer);
+ payload1.wireEncode(buffer);
+
+ this->sendDatasetReply(prefix, buffer.buf(), buffer.size());
+ }
+
+ /** \brief send a payload in reply to StatusDataset request
+ * \param name dataset prefix without version and segment
+ * \param contentArgs passed to Data::setContent
+ */
+ template<typename ...ContentArgs>
+ void
+ sendDatasetReply(ndn::Name name, ContentArgs&&... contentArgs)
+ {
+ name.appendVersion().appendSegment(0);
+
+ // These warnings assist in debugging when nfdc does not receive StatusDataset.
+ // They usually indicate a misspelled prefix or incorrect timing in the test case.
+ if (face->sentInterests.empty()) {
+ BOOST_WARN_MESSAGE(false, "no Interest expressed");
+ }
+ else {
+ BOOST_WARN_MESSAGE(face->sentInterests.back().getName().isPrefixOf(name),
+ "last Interest " << face->sentInterests.back().getName() <<
+ " cannot be satisfied by this Data " << name);
+ }
+
+ auto data = make_shared<ndn::Data>(name);
+ data->setFinalBlockId(name[-1]);
+ data->setContent(std::forward<ContentArgs>(contentArgs)...);
+ this->signDatasetReply(*data);
+ face->receive(*data);
+ }
+
+ virtual void
+ signDatasetReply(ndn::Data& data);
+
+public:
+ std::shared_ptr<ndn::util::DummyClientFace> face;
+};
+
} // namespace test
} // namespace nlsr
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index 78e0fb9..2cfe46f 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -25,21 +25,21 @@
#include "nlsr.hpp"
#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
-#include <ndn-cxx/util/dummy-client-face.hpp>
namespace nlsr {
namespace test {
using std::shared_ptr;
-class NlsrFixture : public UnitTestTimeFixture
+class NlsrFixture : public MockNfdMgmtFixture
{
public:
NlsrFixture()
- : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
- , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+ : nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
, lsdb(nlsr.getLsdb())
, neighbors(nlsr.getAdjacencyList())
+ , nSuccessCallbacks(0)
+ , nFailureCallbacks(0)
{
}
@@ -55,10 +55,12 @@
}
public:
- std::shared_ptr<ndn::util::DummyClientFace> face;
Nlsr nlsr;
Lsdb& lsdb;
AdjacencyList& neighbors;
+ uint32_t nSuccessCallbacks;
+ uint32_t nFailureCallbacks;
+
};
BOOST_FIXTURE_TEST_SUITE(TestNlsr, NlsrFixture)
@@ -124,6 +126,92 @@
BOOST_CHECK_EQUAL(rt.getRoutingCalcInterval(), ndn::time::seconds(9));
}
+BOOST_AUTO_TEST_CASE(FaceCreateEvent)
+{
+ // Setting constants for the unit test
+ const uint32_t faceId = 1;
+ const std::string faceUri = "udp4://10.0.0.1:6363";
+ Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(faceUri), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+ BOOST_REQUIRE_EQUAL(nlsr.getAdjacencyList().insert(neighbor), 0);
+
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // Build, sign, and send the Face Event
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_CREATED)
+ .setRemoteUri(faceUri)
+ .setFaceId(faceId);
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+ face->receive(*data);
+
+ // Move the clocks forward so that the Face processes the event.
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // Need to explicitly provide a FaceUri object, because the
+ // conversion will attempt to create Name objects.
+ auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(faceUri));
+ BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
+ BOOST_CHECK_EQUAL(iterator->getFaceId(), faceId);
+}
+
+BOOST_AUTO_TEST_CASE(FaceCreateEventNoMatch)
+{
+ // Setting constants for the unit test
+ const uint32_t faceId = 1;
+ const std::string eventUri = "udp4://10.0.0.1:6363";
+ const std::string neighborUri = "udp4://10.0.0.2:6363";
+ Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(neighborUri), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+ nlsr.getAdjacencyList().insert(neighbor);
+
+ // Build, sign, and send the Face Event
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_CREATED)
+ .setRemoteUri(eventUri)
+ .setFaceId(faceId);
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+ face->receive(*data);
+
+ // Move the clocks forward so that the Face processes the event.
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // The Face URIs did not match, so this neighbor should be unconfigured.
+ auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(neighborUri));
+ BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
+ BOOST_CHECK_EQUAL(iterator->getFaceId(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceCreateEventAlreadyConfigured)
+{
+ // Setting constants for the unit test
+ const uint32_t eventFaceId = 1;
+ const uint32_t neighborFaceId = 2;
+ const std::string faceUri = "udp4://10.0.0.1:6363";
+ Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(faceUri), 10, Adjacent::STATUS_ACTIVE, 0, neighborFaceId);
+ nlsr.getAdjacencyList().insert(neighbor);
+
+ // Build, sign, and send the Face Event
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_CREATED)
+ .setRemoteUri(faceUri)
+ .setFaceId(eventFaceId);
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+ face->receive(*data);
+
+ // Move the clocks forward so that the Face processes the event.
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // Since the neighbor was already configured, this (simply erroneous) event should have no effect.
+ auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(faceUri));
+ BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
+ BOOST_CHECK_EQUAL(iterator->getFaceId(), neighborFaceId);
+}
+
BOOST_FIXTURE_TEST_CASE(FaceDestroyEvent, UnitTestTimeFixture)
{
std::shared_ptr<ndn::util::DummyClientFace> face = std::make_shared<ndn::util::DummyClientFace>(g_ioService);
@@ -480,6 +568,134 @@
ndn::util::FaceUri("udp4://10.0.0.2:6363"));
}
+BOOST_AUTO_TEST_CASE(FaceDatasetFetchSuccess)
+{
+ bool hasResult = false;
+ nlsr.m_validator.m_shouldValidate = false;
+
+ nlsr.initializeFaces([&hasResult] (const std::vector<ndn::nfd::FaceStatus>& faces) {
+ hasResult = true;
+ BOOST_CHECK_EQUAL(faces.size(), 2);
+ BOOST_CHECK_EQUAL(faces.front().getFaceId(), 25401);
+ BOOST_CHECK_EQUAL(faces.back().getFaceId(), 25402);
+ },
+ [] (uint32_t code, const std::string& reason) {});
+
+ this->advanceClocks(ndn::time::milliseconds(500));
+
+ ndn::nfd::FaceStatus payload1;
+ payload1.setFaceId(25401);
+ ndn::nfd::FaceStatus payload2;
+ payload2.setFaceId(25402);
+ this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
+
+ this->advanceClocks(ndn::time::milliseconds(500));
+ BOOST_CHECK(hasResult);
+}
+
+BOOST_AUTO_TEST_CASE(FaceDatasetFetchFailure)
+{
+ nlsr.m_validator.m_shouldValidate = false;
+ nlsr.initializeFaces([](const std::vector<ndn::nfd::FaceStatus>& faces) {},
+ [this](uint32_t code, const std::string& reason){
+ this->nFailureCallbacks++;
+ });
+ this->advanceClocks(ndn::time::milliseconds(500));
+
+ ndn::Name payload;
+ this->sendDataset("/localhost/nfd/faces/list", payload);
+ this->advanceClocks(ndn::time::milliseconds(500));
+
+ BOOST_CHECK_EQUAL(nFailureCallbacks, 1);
+ BOOST_CHECK_EQUAL(nSuccessCallbacks, 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceDatasetProcess)
+{
+ Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://192.168.0.100:6363"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborA);
+
+ Adjacent neighborB("/ndn/neighborB", ndn::util::FaceUri("udp4://192.168.0.101:6363"), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborB);
+
+ ndn::nfd::FaceStatus payload1;
+ payload1.setFaceId(1)
+ .setRemoteUri("udp4://192.168.0.100:6363");
+ ndn::nfd::FaceStatus payload2;
+ payload2.setFaceId(2)
+ .setRemoteUri("udp4://192.168.0.101:6363");
+ std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload1, payload2};
+
+ nlsr.processFaceDataset(faceStatuses);
+ this->advanceClocks(ndn::time::milliseconds(100));
+
+ AdjacencyList adjList = nlsr.getAdjacencyList();
+
+ BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), payload1.getFaceId());
+ BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborB").getFaceId(), payload2.getFaceId());
+}
+
+BOOST_AUTO_TEST_CASE(UnconfiguredNeighbor)
+{
+ Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://192.168.0.100:6363"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborA);
+
+ ndn::nfd::FaceStatus payload;
+ payload.setFaceId(1)
+ .setRemoteUri("udp4://192.168.0.101:6363"); // Note dissimilar Face URI.
+ std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload};
+
+ nlsr.processFaceDataset(faceStatuses);
+ this->advanceClocks(ndn::time::milliseconds(100));
+
+ AdjacencyList adjList = nlsr.getAdjacencyList();
+
+ BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceDatasetPeriodicFetch)
+{
+ int nNameMatches = 0;
+ ndn::Name datasetPrefix("/localhost/nfd/faces/list");
+ ndn::nfd::CommandOptions options;
+ ndn::time::milliseconds defaultTimeout = options.getTimeout();
+
+ ndn::time::seconds fetchInterval(1);
+ ConfParameter& conf = nlsr.getConfParameter();
+ conf.setFaceDatasetFetchInterval(fetchInterval);
+ conf.setFaceDatasetFetchTries(0);
+
+ nlsr.initializeFaces(std::bind(&Nlsr::processFaceDataset, &nlsr, _1),
+ std::bind(&Nlsr::onFaceDatasetFetchTimeout, &nlsr, _1, _2, 0));
+
+ // Elapse the default timeout time of the interest.
+ this->advanceClocks(defaultTimeout);
+
+ // Check that we have one interest for face list in the sent interests.
+ for (const ndn::Interest& interest : face->sentInterests) {
+ if (datasetPrefix.isPrefixOf(interest.getName())) {
+ nNameMatches++;
+ }
+ }
+ BOOST_CHECK_EQUAL(nNameMatches, 1);
+
+ // Elapse the clock by the reschedule time (that we set)
+ this->advanceClocks(fetchInterval);
+ // Elapse the default timeout on the interest.
+ this->advanceClocks(defaultTimeout);
+ // Plus a little more to let the events process.
+ this->advanceClocks(ndn::time::seconds(1));
+
+ // Check that we now have two interests
+ nNameMatches = 0;
+ for (const ndn::Interest& interest : face->sentInterests) {
+ if (datasetPrefix.isPrefixOf(interest.getName())) {
+ nNameMatches++;
+ }
+ }
+ BOOST_CHECK_EQUAL(nNameMatches, 2);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace test
diff --git a/tests/utility/test-face-controller.cpp b/tests/utility/test-face-controller.cpp
deleted file mode 100644
index 7684256..0000000
--- a/tests/utility/test-face-controller.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017, The University of Memphis,
- * Regents of the University of California,
- * Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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
- * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#include "tests/test-common.hpp"
-#include "tests/control-commands.hpp"
-
-#include "utility/face-controller.hpp"
-
-#include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/mgmt/nfd/controller.hpp>
-#include <ndn-cxx/util/dummy-client-face.hpp>
-
-namespace nlsr {
-namespace test {
-
-using std::bind;
-using std::shared_ptr;
-using ndn::Interest;
-
-class FaceControllerFixture : public BaseFixture
-{
-public:
- FaceControllerFixture()
- : face(std::make_shared<ndn::util::DummyClientFace>())
- , interests(face->sentInterests)
- , controller(*face, keyChain)
- , faceController(g_ioService, controller)
- {
- }
-
- void
- onFailure(const ndn::nfd::ControlResponse& response)
- {
- BOOST_CHECK_EQUAL(response.getCode(), 408);
- }
-
-public:
- std::shared_ptr<ndn::util::DummyClientFace> face;
- ndn::KeyChain keyChain;
- std::vector<Interest>& interests;
- ndn::nfd::Controller controller;
- util::FaceController faceController;
-};
-
-BOOST_FIXTURE_TEST_SUITE(TestFaceController, FaceControllerFixture)
-
-BOOST_AUTO_TEST_CASE(FaceCreateCanonizeSuccess)
-{
- const std::string uri("udp4://192.0.2.1:6363");
- faceController.createFace(uri, nullptr, nullptr);
-
- face->processEvents(ndn::time::milliseconds(1));
-
- BOOST_REQUIRE_EQUAL(interests.size(), 1);
- Interest interest = interests.front();
-
- ndn::nfd::ControlParameters extractedParameters;
- ndn::Name::Component verb;
-
- extractFaceCommandParameters(interest, verb, extractedParameters);
-
- BOOST_CHECK_EQUAL(verb, ndn::Name::Component("create"));
- BOOST_CHECK_EQUAL(uri, extractedParameters.getUri());
-}
-
-BOOST_AUTO_TEST_CASE(FaceCreateCanonizeFailure)
-{
- faceController.createFace("invalid://256.0.0.1:6363",
- nullptr,
- std::bind(&FaceControllerFixture::onFailure, this, _1));
-
- face->processEvents(ndn::time::milliseconds(1));
-
- BOOST_CHECK_EQUAL(interests.size(), 0);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace test
-} // namespace nlsr