Merge feature branch 'mgmt-refactoring'
Change-Id: I3f122ede5bcfbad40800d8dae440dfea887bb10e
Refs: #2107
diff --git a/common.hpp b/common.hpp
index bd8f10b..9e44569 100644
--- a/common.hpp
+++ b/common.hpp
@@ -97,6 +97,7 @@
using ndn::Interest;
using ndn::Data;
using ndn::Name;
+using ndn::PartialName;
using ndn::Exclude;
using ndn::Link;
using ndn::Block;
diff --git a/core/config-file.cpp b/core/config-file.cpp
index 9724168..d989455 100644
--- a/core/config-file.cpp
+++ b/core/config-file.cpp
@@ -52,6 +52,25 @@
// do nothing
}
+bool
+ConfigFile::parseYesNo(const ConfigSection::const_iterator& i,
+ const std::string& optionName,
+ const std::string& sectionName)
+{
+ const std::string value = i->second.get_value<std::string>();
+ if (value == "yes") {
+ return true;
+ }
+
+ if (value == "no") {
+ return false;
+ }
+
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
+ optionName + "\" in \"" +
+ sectionName + "\" section"));
+}
+
ConfigFile::ConfigFile(UnknownConfigSectionHandler unknownSectionCallback)
: m_unknownSectionCallback(unknownSectionCallback)
{
diff --git a/core/config-file.hpp b/core/config-file.hpp
index 9991484..ae9102e 100644
--- a/core/config-file.hpp
+++ b/core/config-file.hpp
@@ -73,6 +73,16 @@
const ConfigSection& section,
bool isDryRun);
+ /** @brief parse a config option that can be either "yes" or "no"
+ *
+ * @throw ConfigFile::Error value is neither "yes" nor "no"
+ * @return true if "yes", false if "no"
+ */
+ static bool
+ parseYesNo(const ConfigSection::const_iterator& i,
+ const std::string& optionName,
+ const std::string& sectionName);
+
/// \brief setup notification of configuration file sections
void
addSectionHandler(const std::string& sectionName,
diff --git a/daemon/face/internal-client-face.cpp b/daemon/face/internal-client-face.cpp
new file mode 100644
index 0000000..510b087
--- /dev/null
+++ b/daemon/face/internal-client-face.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "internal-client-face.hpp"
+#include "internal-face.hpp"
+#include "core/global-io.hpp"
+
+#include <ndn-cxx/management/nfd-local-control-header.hpp>
+
+namespace nfd {
+
+void
+InternalClientFace::Transport::receive(const Block& block)
+{
+ if (m_receiveCallback) {
+ m_receiveCallback(block);
+ }
+}
+
+void
+InternalClientFace::Transport::close()
+{
+}
+
+void
+InternalClientFace::Transport::send(const Block& wire)
+{
+ onSendBlock(wire);
+}
+
+void
+InternalClientFace::Transport::send(const Block& header, const Block& payload)
+{
+ ndn::EncodingBuffer encoder(header.size() + payload.size(), header.size() + payload.size());
+ encoder.appendByteArray(header.wire(), header.size());
+ encoder.appendByteArray(payload.wire(), payload.size());
+
+ this->send(encoder.block());
+}
+
+void
+InternalClientFace::Transport::pause()
+{
+}
+
+void
+InternalClientFace::Transport::resume()
+{
+}
+
+InternalClientFace::InternalClientFace(const shared_ptr<InternalFace>& face,
+ const shared_ptr<InternalClientFace::Transport>& transport,
+ ndn::KeyChain& keyChain)
+ : ndn::Face(transport, getGlobalIoService(), keyChain)
+ , m_face(face)
+ , m_transport(transport)
+{
+ construct();
+}
+
+void
+InternalClientFace::construct()
+{
+ m_face->onSendInterest.connect(bind(&InternalClientFace::receive<Interest>, this, _1));
+ m_face->onSendData.connect(bind(&InternalClientFace::receive<Data>, this, _1));
+ m_transport->onSendBlock.connect(bind(&InternalFace::receive, m_face, _1));
+}
+
+shared_ptr<InternalClientFace>
+makeInternalClientFace(const shared_ptr<InternalFace>& face,
+ ndn::KeyChain& keyChain)
+{
+ auto transport = make_shared<InternalClientFace::Transport>();
+ return shared_ptr<InternalClientFace>(new InternalClientFace(face, transport, keyChain));
+}
+
+} // namespace nfd
diff --git a/daemon/face/internal-client-face.hpp b/daemon/face/internal-client-face.hpp
new file mode 100644
index 0000000..8eb3c46
--- /dev/null
+++ b/daemon/face/internal-client-face.hpp
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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/>.
+ */
+
+#ifndef NFD_DAEMON_FACE_INTERNAL_CLIENT_FACE_HPP
+#define NFD_DAEMON_FACE_INTERNAL_CLIENT_FACE_HPP
+
+#include "common.hpp"
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/transport/transport.hpp>
+
+namespace nfd {
+
+class InternalFace;
+class InternalClientFace;
+
+shared_ptr<InternalClientFace>
+makeInternalClientFace(const shared_ptr<InternalFace>& face, ndn::KeyChain& keyChain);
+
+/** \brief a client face that is connected to NFD InternalFace
+ */
+class InternalClientFace : public ndn::Face
+{
+public:
+ template<typename Packet>
+ void
+ receive(const Packet& packet);
+
+private:
+ class Transport : public ndn::Transport
+ {
+ public:
+ signal::Signal<Transport, Block> onSendBlock;
+
+ void
+ receive(const Block& block);
+
+ virtual void
+ close() DECL_OVERRIDE;
+
+ virtual void
+ send(const Block& wire) DECL_OVERRIDE;
+
+ virtual void
+ send(const Block& header, const Block& payload) DECL_OVERRIDE;
+
+ virtual void
+ pause() DECL_OVERRIDE;
+
+ virtual void
+ resume() DECL_OVERRIDE;
+ };
+
+private:
+ InternalClientFace(const shared_ptr<InternalFace>& face,
+ const shared_ptr<InternalClientFace::Transport>& transport,
+ ndn::KeyChain& keyChain);
+
+ void
+ construct();
+
+ friend shared_ptr<InternalClientFace>
+ makeInternalClientFace(const shared_ptr<InternalFace>& face,
+ ndn::KeyChain& keyChain);
+
+private:
+ shared_ptr<InternalFace> m_face;
+ shared_ptr<InternalClientFace::Transport> m_transport;
+};
+
+template<typename Packet>
+void
+InternalClientFace::receive(const Packet& packet)
+{
+ if (!packet.getLocalControlHeader().empty(ndn::nfd::LocalControlHeader::ENCODE_ALL)) {
+
+ Block header = packet.getLocalControlHeader()
+ .wireEncode(packet, ndn::nfd::LocalControlHeader::ENCODE_ALL);
+ Block payload = packet.wireEncode();
+
+ ndn::EncodingBuffer encoder(header.size() + payload.size(),
+ header.size() + payload.size());
+ encoder.appendByteArray(header.wire(), header.size());
+ encoder.appendByteArray(payload.wire(), payload.size());
+
+ m_transport->receive(encoder.block());
+ }
+ else {
+ m_transport->receive(packet.wireEncode());
+ }
+}
+
+} // namespace nfd
+
+#endif // NFD_DAEMON_FACE_INTERNAL_CLIENT_FACE_HPP
diff --git a/daemon/face/internal-face.cpp b/daemon/face/internal-face.cpp
new file mode 100644
index 0000000..c5ab2ca
--- /dev/null
+++ b/daemon/face/internal-face.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "internal-face.hpp"
+
+namespace nfd {
+
+InternalFace::InternalFace()
+ : Face(FaceUri("internal://"), FaceUri("internal://"), true)
+{
+}
+
+void
+InternalFace::sendInterest(const Interest& interest)
+{
+ this->emitSignal(onSendInterest, interest);
+}
+
+void
+InternalFace::sendData(const Data& data)
+{
+ this->emitSignal(onSendData, data);
+}
+
+void
+InternalFace::close()
+{
+}
+
+void
+InternalFace::receive(const Block& blockFromClient)
+{
+ const Block& payLoad = ndn::nfd::LocalControlHeader::getPayload(blockFromClient);
+ if (payLoad.type() == ndn::tlv::Interest) {
+ receiveInterest(*extractPacketFromBlock<Interest>(blockFromClient, payLoad));
+ }
+ else if (payLoad.type() == ndn::tlv::Data) {
+ receiveData(*extractPacketFromBlock<Data>(blockFromClient, payLoad));
+ }
+}
+
+void
+InternalFace::receiveInterest(const Interest& interest)
+{
+ this->emitSignal(onReceiveInterest, interest);
+}
+
+void
+InternalFace::receiveData(const Data& data)
+{
+ this->emitSignal(onReceiveData, data);
+}
+
+template<typename Packet>
+shared_ptr<Packet>
+InternalFace::extractPacketFromBlock(const Block& blockFromClient, const Block& payLoad)
+{
+ auto packet = make_shared<Packet>(payLoad);
+ if (&payLoad != &blockFromClient) {
+ packet->getLocalControlHeader().wireDecode(blockFromClient);
+ }
+ return packet;
+}
+
+template shared_ptr<Interest>
+InternalFace::extractPacketFromBlock<Interest>(const Block& blockFromClient, const Block& payLoad);
+
+template shared_ptr<Data>
+InternalFace::extractPacketFromBlock<Data>(const Block& blockFromClient, const Block& payLoad);
+
+} // namespace nfd
diff --git a/daemon/face/internal-face.hpp b/daemon/face/internal-face.hpp
new file mode 100644
index 0000000..1014fca
--- /dev/null
+++ b/daemon/face/internal-face.hpp
@@ -0,0 +1,102 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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/>.
+ */
+
+#ifndef NFD_DAEMON_FACE_INTERNAL_FACE_HPP
+#define NFD_DAEMON_FACE_INTERNAL_FACE_HPP
+
+#include "face.hpp"
+
+namespace nfd {
+
+/**
+ * @brief represents a face for internal use in NFD.
+ */
+class InternalFace : public Face
+{
+public:
+
+ InternalFace();
+
+ virtual void
+ sendInterest(const Interest& interest) DECL_OVERRIDE;
+
+ virtual void
+ sendData(const Data& data) DECL_OVERRIDE;
+
+ virtual void
+ close() DECL_OVERRIDE;
+
+ /**
+ * @brief receive a block from a client face
+ *
+ * step1. extracte the packet payload from the received block.
+ * step2. check the type (either Interest or Data) through the payload.
+ * step3. call receiveInterest / receiveData respectively according to the type.
+ *
+ * @param blockFromClient the block from a client face
+ */
+ void
+ receive(const Block& blockFromClient);
+
+ /**
+ * @brief receive an Interest from a client face
+ *
+ * emit the onReceiveInterest signal.
+ *
+ * @param interest the received Interest packet
+ */
+ void
+ receiveInterest(const Interest& interest);
+
+ /**
+ * @brief receive a Data from a client face
+ *
+ * emit the onReceiveData signal.
+ *
+ * @param data the received Data packet
+ */
+ void
+ receiveData(const Data& data);
+
+ /**
+ * @brief compose the whole packet from the received block after payload is extracted
+ *
+ * construct a packet from the extracted payload, and then decode the localControlHeader if the
+ * received block holds more information than the payload.
+ *
+ * @tparam Packet the type of packet, Interest or Data
+ * @param blockFromClient the received block
+ * @param payLoad the extracted payload
+ *
+ * @return a complete packet
+ */
+ template<typename Packet>
+ static shared_ptr<Packet>
+ extractPacketFromBlock(const Block& blockFromClient, const Block& payLoad);
+};
+
+} // namespace nfd
+
+#endif // NFD_DAEMON_FACE_INTERNAL_FACE_HPP
diff --git a/daemon/mgmt/channel-status-publisher.cpp b/daemon/mgmt/channel-status-publisher.cpp
deleted file mode 100644
index bb14879..0000000
--- a/daemon/mgmt/channel-status-publisher.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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 "channel-status-publisher.hpp"
-#include "face/protocol-factory.hpp"
-#include "face/channel.hpp"
-
-#include <ndn-cxx/management/nfd-channel-status.hpp>
-
-namespace nfd {
-
-ChannelStatusPublisher::ChannelStatusPublisher(const FactoryMap& factories,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain)
- : SegmentPublisher(face, prefix, keyChain)
- , m_factories(factories)
-{
-}
-
-ChannelStatusPublisher::~ChannelStatusPublisher()
-{
-}
-
-size_t
-ChannelStatusPublisher::generate(ndn::EncodingBuffer& outBuffer)
-{
- size_t totalLength = 0;
- std::set<shared_ptr<ProtocolFactory> > seenFactories;
-
- for (FactoryMap::const_iterator i = m_factories.begin();
- i != m_factories.end(); ++i)
- {
- const shared_ptr<ProtocolFactory>& factory = i->second;
-
- if (seenFactories.find(factory) != seenFactories.end())
- {
- continue;
- }
- seenFactories.insert(factory);
-
- std::list<shared_ptr<const Channel> > channels = factory->getChannels();
-
- for (std::list<shared_ptr<const Channel> >::const_iterator j = channels.begin();
- j != channels.end(); ++j)
- {
- ndn::nfd::ChannelStatus entry;
- entry.setLocalUri((*j)->getUri().toString());
-
- totalLength += entry.wireEncode(outBuffer);
- }
- }
-
- return totalLength;
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/channel-status-publisher.hpp b/daemon/mgmt/channel-status-publisher.hpp
deleted file mode 100644
index ef660a3..0000000
--- a/daemon/mgmt/channel-status-publisher.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_DAEMON_MGMT_CHANNEL_STATUS_PUBLISHER_HPP
-#define NFD_DAEMON_MGMT_CHANNEL_STATUS_PUBLISHER_HPP
-
-#include "core/segment-publisher.hpp"
-#include "mgmt/app-face.hpp"
-
-namespace nfd {
-
-class ProtocolFactory;
-
-class ChannelStatusPublisher : public SegmentPublisher<AppFace>
-{
-public:
- typedef std::map< std::string/*protocol*/, shared_ptr<ProtocolFactory> > FactoryMap;
-
- ChannelStatusPublisher(const FactoryMap& factories,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain);
-
- virtual
- ~ChannelStatusPublisher();
-
-protected:
-
- virtual size_t
- generate(ndn::EncodingBuffer& outBuffer);
-
-private:
- const FactoryMap& m_factories;
-};
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_CHANNEL_STATUS_PUBLISHER_HPP
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index db3b92f..2991ee6 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -25,12 +25,14 @@
#include "face-manager.hpp"
-#include "core/logger.hpp"
#include "core/network-interface.hpp"
#include "fw/face-table.hpp"
#include "face/tcp-factory.hpp"
#include "face/udp-factory.hpp"
-#include "core/config-file.hpp"
+
+#include <ndn-cxx/management/nfd-face-status.hpp>
+#include <ndn-cxx/management/nfd-channel-status.hpp>
+#include <ndn-cxx/management/nfd-face-event-notification.hpp>
#ifdef HAVE_UNIX_SOCKETS
#include "face/unix-stream-factory.hpp"
@@ -45,120 +47,304 @@
#include "face/websocket-factory.hpp"
#endif // HAVE_WEBSOCKET
-#include <ndn-cxx/management/nfd-face-event-notification.hpp>
-#include <ndn-cxx/management/nfd-face-query-filter.hpp>
-
namespace nfd {
NFD_LOG_INIT("FaceManager");
-const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
-
-const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
- FaceManager::COMMAND_PREFIX.size() +
- 1 + // verb
- 1; // verb parameters
-
-const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
- FaceManager::COMMAND_UNSIGNED_NCOMPS +
- 4; // (timestamp, nonce, signed info tlv, signature tlv)
-
-const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
- {
- SignedVerbAndProcessor(
- Name::Component("create"),
- &FaceManager::createFace
- ),
-
- SignedVerbAndProcessor(
- Name::Component("destroy"),
- &FaceManager::destroyFace
- ),
-
- SignedVerbAndProcessor(
- Name::Component("enable-local-control"),
- &FaceManager::enableLocalControl
- ),
-
- SignedVerbAndProcessor(
- Name::Component("disable-local-control"),
- &FaceManager::disableLocalControl
- ),
- };
-
-const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
- {
- UnsignedVerbAndProcessor(
- Name::Component("list"),
- &FaceManager::listFaces
- ),
-
- UnsignedVerbAndProcessor(
- Name::Component("events"),
- &FaceManager::ignoreUnsignedVerb
- ),
-
- UnsignedVerbAndProcessor(
- Name::Component("channels"),
- &FaceManager::listChannels
- ),
-
- UnsignedVerbAndProcessor(
- Name::Component("query"),
- &FaceManager::listQueriedFaces
- ),
- };
-
-const Name FaceManager::FACES_LIST_DATASET_PREFIX("/localhost/nfd/faces/list");
-const size_t FaceManager::FACES_LIST_DATASET_NCOMPS = FACES_LIST_DATASET_PREFIX.size();
-
-const Name FaceManager::FACE_EVENTS_PREFIX("/localhost/nfd/faces/events");
-
-const Name FaceManager::CHANNELS_LIST_DATASET_PREFIX("/localhost/nfd/faces/channels");
-const size_t FaceManager::CHANNELS_LIST_DATASET_NCOMPS = CHANNELS_LIST_DATASET_PREFIX.size();
-
-const Name FaceManager::FACES_QUERY_DATASET_PREFIX("/localhost/nfd/faces/query");
-const size_t FaceManager::FACES_QUERY_DATASET_NCOMPS = FACES_QUERY_DATASET_PREFIX.size() + 1;
-
FaceManager::FaceManager(FaceTable& faceTable,
- shared_ptr<InternalFace> face,
- ndn::KeyChain& keyChain)
- : ManagerBase(face, FACE_MANAGER_PRIVILEGE, keyChain)
+ Dispatcher& dispatcher,
+ CommandValidator& validator)
+ : ManagerBase(dispatcher, validator, "faces")
, m_faceTable(faceTable)
- , m_faceAddConn(m_faceTable.onAdd.connect(bind(&FaceManager::onAddFace, this, _1)))
- , m_faceRemoveConn(m_faceTable.onRemove.connect(bind(&FaceManager::onRemoveFace, this, _1)))
- , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
- , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
- , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
- , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
- SIGNED_COMMAND_VERBS +
- (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
- , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
- UNSIGNED_COMMAND_VERBS +
- (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
-
{
- face->setInterestFilter("/localhost/nfd/faces",
- bind(&FaceManager::onFaceRequest, this, _2));
-}
+ registerCommandHandler<ndn::nfd::FaceCreateCommand>("create",
+ bind(&FaceManager::createFace, this, _2, _3, _4, _5));
-FaceManager::~FaceManager()
-{
+ registerCommandHandler<ndn::nfd::FaceDestroyCommand>("destroy",
+ bind(&FaceManager::destroyFace, this, _2, _3, _4, _5));
+ registerCommandHandler<ndn::nfd::FaceEnableLocalControlCommand>("enable-local-control",
+ bind(&FaceManager::enableLocalControl, this, _2, _3, _4, _5));
+
+ registerCommandHandler<ndn::nfd::FaceDisableLocalControlCommand>("disable-local-control",
+ bind(&FaceManager::disableLocalControl, this, _2, _3, _4, _5));
+
+ registerStatusDatasetHandler("list", bind(&FaceManager::listFaces, this, _1, _2, _3));
+ registerStatusDatasetHandler("channels", bind(&FaceManager::listChannels, this, _1, _2, _3));
+ registerStatusDatasetHandler("query", bind(&FaceManager::queryFaces, this, _1, _2, _3));
+
+ auto postNotification = registerNotificationStream("events");
+ m_faceAddConn =
+ m_faceTable.onAdd.connect(bind(&FaceManager::afterFaceAdded, this, _1, postNotification));
+ m_faceRemoveConn =
+ m_faceTable.onRemove.connect(bind(&FaceManager::afterFaceRemoved, this, _1, postNotification));
}
void
FaceManager::setConfigFile(ConfigFile& configFile)
{
- configFile.addSectionHandler("face_system",
- bind(&FaceManager::onConfig, this, _1, _2, _3));
+ configFile.addSectionHandler("face_system", bind(&FaceManager::processConfig, this, _1, _2, _3));
}
+void
+FaceManager::createFace(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ FaceUri uri;
+ if (!uri.parse(parameters.getUri())) {
+ NFD_LOG_TRACE("failed to parse URI");
+ return done(ControlResponse(400, "Malformed command"));
+ }
+
+ if (!uri.isCanonical()) {
+ NFD_LOG_TRACE("received non-canonical URI");
+ return done(ControlResponse(400, "Non-canonical URI"));
+ }
+
+ FactoryMap::iterator factory = m_factories.find(uri.getScheme());
+ if (factory == m_factories.end()) {
+ return done(ControlResponse(501, "Unsupported protocol"));
+ }
+
+ try {
+ factory->second->createFace(uri,
+ parameters.getFacePersistency(),
+ bind(&FaceManager::afterCreateFaceSuccess,
+ this, parameters, _1, done),
+ bind(&FaceManager::afterCreateFaceFailure,
+ this, _1, done));
+ }
+ catch (const std::runtime_error& error) {
+ std::string errorMessage = "Face creation failed: ";
+ errorMessage += error.what();
+
+ NFD_LOG_ERROR(errorMessage);
+ return done(ControlResponse(500, errorMessage));
+ }
+ catch (const std::logic_error& error) {
+ std::string errorMessage = "Face creation failed: ";
+ errorMessage += error.what();
+
+ NFD_LOG_ERROR(errorMessage);
+ return done(ControlResponse(500, errorMessage));
+ }
+}
void
-FaceManager::onConfig(const ConfigSection& configSection,
- bool isDryRun,
- const std::string& filename)
+FaceManager::destroyFace(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
+ if (target) {
+ target->close();
+ }
+
+ done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
+}
+
+void
+FaceManager::enableLocalControl(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ auto result = extractLocalControlParameters(interest, parameters, done);
+ if (result.isValid) {
+ result.face->setLocalControlHeaderFeature(result.feature, true);
+ return done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
+ }
+}
+
+void
+FaceManager::disableLocalControl(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ auto result = extractLocalControlParameters(interest, parameters, done);
+ if (result.isValid) {
+ result.face->setLocalControlHeaderFeature(result.feature, false);
+ return done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
+ }
+}
+
+void
+FaceManager::afterCreateFaceSuccess(ControlParameters& parameters,
+ const shared_ptr<Face>& newFace,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ addCreatedFaceToForwarder(newFace);
+ parameters.setFaceId(newFace->getId());
+ parameters.setUri(newFace->getRemoteUri().toString());
+ parameters.setFacePersistency(newFace->getPersistency());
+
+ done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
+}
+
+void
+FaceManager::afterCreateFaceFailure(const std::string& reason,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ NFD_LOG_DEBUG("Failed to create face: " << reason);
+
+ done(ControlResponse(408, "Failed to create face: " + reason));
+}
+
+FaceManager::ExtractLocalControlParametersResult
+FaceManager::extractLocalControlParameters(const Interest& request,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done)
+{
+ ExtractLocalControlParametersResult result;
+ result.isValid = false;
+
+ auto face = m_faceTable.get(request.getIncomingFaceId());
+ if (!static_cast<bool>(face)) {
+ NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
+ done(ControlResponse(410, "Face not found"));
+ return result;
+ }
+
+ if (!face->isLocal()) {
+ NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
+ face->getId());
+ done(ControlResponse(412, "Face is non-local"));
+ return result;
+ }
+
+ result.isValid = true;
+ result.face = dynamic_pointer_cast<LocalFace>(face);
+ result.feature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
+
+ return result;
+}
+
+void
+FaceManager::listFaces(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context)
+{
+ for (const auto& face : m_faceTable) {
+ context.append(face->getFaceStatus().wireEncode());
+ }
+ context.end();
+}
+
+void
+FaceManager::listChannels(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context)
+{
+ std::set<shared_ptr<ProtocolFactory>> seenFactories;
+
+ for (auto i = m_factories.begin(); i != m_factories.end(); ++i) {
+ const shared_ptr<ProtocolFactory>& factory = i->second;
+
+ if (seenFactories.find(factory) != seenFactories.end()) {
+ continue;
+ }
+ seenFactories.insert(factory);
+
+ std::list<shared_ptr<const Channel>> channels = factory->getChannels();
+
+ for (auto j = channels.begin(); j != channels.end(); ++j) {
+ ndn::nfd::ChannelStatus entry;
+ entry.setLocalUri((*j)->getUri().toString());
+ context.append(entry.wireEncode());
+ }
+ }
+
+ context.end();
+}
+
+void
+FaceManager::queryFaces(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context)
+{
+ ndn::nfd::FaceQueryFilter faceFilter;
+ const Name& query = interest.getName();
+ try {
+ faceFilter.wireDecode(query[-1].blockFromValue());
+ }
+ catch (const tlv::Error&) {
+ NFD_LOG_DEBUG("query result: malformed filter");
+ return context.reject(ControlResponse(400, "malformed filter"));
+ }
+
+ for (const auto& face : m_faceTable) {
+ if (doesMatchFilter(faceFilter, face)) {
+ context.append(face->getFaceStatus().wireEncode());
+ }
+ }
+ context.end();
+}
+
+bool
+FaceManager::doesMatchFilter(const ndn::nfd::FaceQueryFilter& filter, shared_ptr<Face> face)
+{
+ if (filter.hasFaceId() &&
+ filter.getFaceId() != static_cast<uint64_t>(face->getId())) {
+ return false;
+ }
+
+ if (filter.hasUriScheme() &&
+ filter.getUriScheme() != face->getRemoteUri().getScheme() &&
+ filter.getUriScheme() != face->getLocalUri().getScheme()) {
+ return false;
+ }
+
+ if (filter.hasRemoteUri() &&
+ filter.getRemoteUri() != face->getRemoteUri().toString()) {
+ return false;
+ }
+
+ if (filter.hasLocalUri() &&
+ filter.getLocalUri() != face->getLocalUri().toString()) {
+ return false;
+ }
+
+ if (filter.hasFaceScope() &&
+ (filter.getFaceScope() == ndn::nfd::FACE_SCOPE_LOCAL) != face->isLocal()) {
+ return false;
+ }
+
+ if (filter.hasFacePersistency() &&
+ filter.getFacePersistency() != face->getPersistency()) {
+ return false;
+ }
+
+ if (filter.hasLinkType() &&
+ (filter.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) != face->isMultiAccess()) {
+ return false;
+ }
+
+ return true;
+}
+
+void
+FaceManager::afterFaceAdded(shared_ptr<Face> face,
+ const ndn::mgmt::PostNotification& post)
+{
+ ndn::nfd::FaceEventNotification notification;
+ notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
+ face->copyStatusTo(notification);
+
+ post(notification.wireEncode());
+}
+
+void
+FaceManager::afterFaceRemoved(shared_ptr<Face> face,
+ const ndn::mgmt::PostNotification& post)
+{
+ ndn::nfd::FaceEventNotification notification;
+ notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
+ face->copyStatusTo(notification);
+
+ post(notification.wireEncode());
+}
+
+void
+FaceManager::processConfig(const ConfigSection& configSection,
+ bool isDryRun,
+ const std::string& filename)
{
bool hasSeenUnix = false;
bool hasSeenTcp = false;
@@ -168,53 +354,51 @@
const std::vector<NetworkInterfaceInfo> nicList(listNetworkInterfaces());
- for (const auto& item : configSection)
- {
- if (item.first == "unix")
- {
- if (hasSeenUnix)
- BOOST_THROW_EXCEPTION(Error("Duplicate \"unix\" section"));
- hasSeenUnix = true;
+ for (const auto& item : configSection) {
+ if (item.first == "unix") {
+ if (hasSeenUnix) {
+ BOOST_THROW_EXCEPTION(Error("Duplicate \"unix\" section"));
+ }
+ hasSeenUnix = true;
- processSectionUnix(item.second, isDryRun);
- }
- else if (item.first == "tcp")
- {
- if (hasSeenTcp)
- BOOST_THROW_EXCEPTION(Error("Duplicate \"tcp\" section"));
- hasSeenTcp = true;
-
- processSectionTcp(item.second, isDryRun);
- }
- else if (item.first == "udp")
- {
- if (hasSeenUdp)
- BOOST_THROW_EXCEPTION(Error("Duplicate \"udp\" section"));
- hasSeenUdp = true;
-
- processSectionUdp(item.second, isDryRun, nicList);
- }
- else if (item.first == "ether")
- {
- if (hasSeenEther)
- BOOST_THROW_EXCEPTION(Error("Duplicate \"ether\" section"));
- hasSeenEther = true;
-
- processSectionEther(item.second, isDryRun, nicList);
- }
- else if (item.first == "websocket")
- {
- if (hasSeenWebSocket)
- BOOST_THROW_EXCEPTION(Error("Duplicate \"websocket\" section"));
- hasSeenWebSocket = true;
-
- processSectionWebSocket(item.second, isDryRun);
- }
- else
- {
- BOOST_THROW_EXCEPTION(Error("Unrecognized option \"" + item.first + "\""));
- }
+ processSectionUnix(item.second, isDryRun);
}
+ else if (item.first == "tcp") {
+ if (hasSeenTcp) {
+ BOOST_THROW_EXCEPTION(Error("Duplicate \"tcp\" section"));
+ }
+ hasSeenTcp = true;
+
+ processSectionTcp(item.second, isDryRun);
+ }
+ else if (item.first == "udp") {
+ if (hasSeenUdp) {
+ BOOST_THROW_EXCEPTION(Error("Duplicate \"udp\" section"));
+ }
+ hasSeenUdp = true;
+
+ processSectionUdp(item.second, isDryRun, nicList);
+ }
+ else if (item.first == "ether") {
+ if (hasSeenEther) {
+ BOOST_THROW_EXCEPTION(Error("Duplicate \"ether\" section"));
+ }
+ hasSeenEther = true;
+
+ processSectionEther(item.second, isDryRun, nicList);
+ }
+ else if (item.first == "websocket") {
+ if (hasSeenWebSocket) {
+ BOOST_THROW_EXCEPTION(Error("Duplicate \"websocket\" section"));
+ }
+ hasSeenWebSocket = true;
+
+ processSectionWebSocket(item.second, isDryRun);
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Unrecognized option \"" + item.first + "\""));
+ }
+ }
}
void
@@ -230,50 +414,34 @@
std::string path = "/var/run/nfd.sock";
- for (ConfigSection::const_iterator i = configSection.begin();
- i != configSection.end();
- ++i)
- {
- if (i->first == "path")
- {
- path = i->second.get_value<std::string>();
- }
- else
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first + "\" in "
- "\"unix\" section"));
- }
+ for (auto i = configSection.begin(); i != configSection.end(); ++i) {
+ if (i->first == "path") {
+ path = i->second.get_value<std::string>();
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
+ i->first + "\" in \"unix\" section"));
+ }
+ }
+
+ if (!isDryRun) {
+ if (m_factories.count("unix") > 0) {
+ return;
}
- if (!isDryRun)
- {
- if (m_factories.count("unix") > 0)
- {
- return;
- // shared_ptr<UnixStreamFactory> factory
- // = static_pointer_cast<UnixStreamFactory>(m_factories["unix"]);
- // shared_ptr<UnixStreamChannel> unixChannel = factory->findChannel(path);
+ shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
+ shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
- // if (static_cast<bool>(unixChannel))
- // {
- // return;
- // }
- }
+ // Should acceptFailed callback be used somehow?
+ unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
+ UnixStreamChannel::ConnectFailedCallback());
- shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
- shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
-
- // Should acceptFailed callback be used somehow?
- unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
- UnixStreamChannel::ConnectFailedCallback());
-
- m_factories.insert(std::make_pair("unix", factory));
- }
+ m_factories.insert(std::make_pair("unix", factory));
+ }
#else
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
"cannot process \"unix\" section"));
#endif // HAVE_UNIX_SOCKETS
-
}
void
@@ -291,86 +459,69 @@
bool enableV4 = true;
bool enableV6 = true;
- for (ConfigSection::const_iterator i = configSection.begin();
- i != configSection.end();
- ++i)
- {
- if (i->first == "port")
- {
- port = i->second.get_value<std::string>();
- try
- {
- uint16_t portNo = boost::lexical_cast<uint16_t>(port);
- NFD_LOG_TRACE("TCP port set to " << portNo);
- }
- catch (const std::bad_cast& error)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
- i->first + "\" in \"tcp\" section"));
- }
- }
- else if (i->first == "listen")
- {
- needToListen = parseYesNo(i, i->first, "tcp");
- }
- else if (i->first == "enable_v4")
- {
- enableV4 = parseYesNo(i, i->first, "tcp");
- }
- else if (i->first == "enable_v6")
- {
- enableV6 = parseYesNo(i, i->first, "tcp");
- }
- else
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first + "\" in "
- "\"tcp\" section"));
- }
+ for (auto i = configSection.begin(); i != configSection.end(); ++i) {
+ if (i->first == "port") {
+ port = i->second.get_value<std::string>();
+ try {
+ uint16_t portNo = boost::lexical_cast<uint16_t>(port);
+ NFD_LOG_TRACE("TCP port set to " << portNo);
+ }
+ catch (const std::bad_cast& error) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
+ i->first + "\" in \"tcp\" section"));
+ }
+ }
+ else if (i->first == "listen") {
+ needToListen = ConfigFile::parseYesNo(i, i->first, "tcp");
+ }
+ else if (i->first == "enable_v4") {
+ enableV4 = ConfigFile::parseYesNo(i, i->first, "tcp");
+ }
+ else if (i->first == "enable_v6") {
+ enableV6 = ConfigFile::parseYesNo(i, i->first, "tcp");
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
+ i->first + "\" in \"tcp\" section"));
+ }
+ }
+
+ if (!enableV4 && !enableV6) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
+ " Remove \"tcp\" section to disable TCP channels or"
+ " re-enable at least one channel type."));
+ }
+
+ if (!isDryRun) {
+ if (m_factories.count("tcp") > 0) {
+ return;
}
- if (!enableV4 && !enableV6)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
- " Remove \"tcp\" section to disable TCP channels or"
- " re-enable at least one channel type."));
+ shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(port);
+ m_factories.insert(std::make_pair("tcp", factory));
+
+ if (enableV4) {
+ shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
+ if (needToListen) {
+ // Should acceptFailed callback be used somehow?
+ ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
+ TcpChannel::ConnectFailedCallback());
+ }
+
+ m_factories.insert(std::make_pair("tcp4", factory));
}
- if (!isDryRun)
- {
- if (m_factories.count("tcp") > 0)
- {
- return;
- }
+ if (enableV6) {
+ shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
+ if (needToListen) {
+ // Should acceptFailed callback be used somehow?
+ ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
+ TcpChannel::ConnectFailedCallback());
+ }
- shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(port);
- m_factories.insert(std::make_pair("tcp", factory));
-
- if (enableV4)
- {
- shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
- if (needToListen)
- {
- // Should acceptFailed callback be used somehow?
- ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
- TcpChannel::ConnectFailedCallback());
- }
-
- m_factories.insert(std::make_pair("tcp4", factory));
- }
-
- if (enableV6)
- {
- shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
- if (needToListen)
- {
- // Should acceptFailed callback be used somehow?
- ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
- TcpChannel::ConnectFailedCallback());
- }
-
- m_factories.insert(std::make_pair("tcp6", factory));
- }
+ m_factories.insert(std::make_pair("tcp6", factory));
}
+ }
}
void
@@ -401,221 +552,177 @@
std::string mcastPort = "56363";
- for (ConfigSection::const_iterator i = configSection.begin();
- i != configSection.end();
- ++i)
- {
- if (i->first == "port")
- {
- port = i->second.get_value<std::string>();
- try
- {
- uint16_t portNo = boost::lexical_cast<uint16_t>(port);
- NFD_LOG_TRACE("UDP port set to " << portNo);
- }
- catch (const std::bad_cast& error)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
- i->first + "\" in \"udp\" section"));
- }
- }
- else if (i->first == "enable_v4")
- {
- enableV4 = parseYesNo(i, i->first, "udp");
- }
- else if (i->first == "enable_v6")
- {
- enableV6 = parseYesNo(i, i->first, "udp");
- }
- else if (i->first == "idle_timeout")
- {
- try
- {
- timeout = i->second.get_value<size_t>();
- }
- catch (const std::exception& e)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
- i->first + "\" in \"udp\" section"));
- }
- }
- else if (i->first == "keep_alive_interval")
- {
- try
- {
- keepAliveInterval = i->second.get_value<size_t>();
-
- /// \todo Make use of keepAliveInterval
- (void)(keepAliveInterval);
- }
- catch (const std::exception& e)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
- i->first + "\" in \"udp\" section"));
- }
- }
- else if (i->first == "mcast")
- {
- useMcast = parseYesNo(i, i->first, "udp");
- }
- else if (i->first == "mcast_port")
- {
- mcastPort = i->second.get_value<std::string>();
- try
- {
- uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
- NFD_LOG_TRACE("UDP multicast port set to " << portNo);
- }
- catch (const std::bad_cast& error)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
- i->first + "\" in \"udp\" section"));
- }
- }
- else if (i->first == "mcast_group")
- {
- using namespace boost::asio::ip;
- mcastGroup = i->second.get_value<std::string>();
- try
- {
- address mcastGroupTest = address::from_string(mcastGroup);
- if (!mcastGroupTest.is_v4())
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
- i->first + "\" in \"udp\" section"));
- }
- }
- catch(const std::runtime_error& e)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
- i->first + "\" in \"udp\" section"));
- }
- }
- else
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first + "\" in "
- "\"udp\" section"));
- }
- }
-
- if (!enableV4 && !enableV6)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
- " Remove \"udp\" section to disable UDP channels or"
- " re-enable at least one channel type."));
- }
- else if (useMcast && !enableV4)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
- " have been disabled (conflicting configuration"
- " options set)"));
- }
-
- /// \todo what is keep alive interval used for?
-
- if (!isDryRun)
- {
- shared_ptr<UdpFactory> factory;
- bool isReload = false;
- if (m_factories.count("udp") > 0) {
- isReload = true;
- factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
+ for (auto i = configSection.begin(); i != configSection.end(); ++i) {
+ if (i->first == "port") {
+ port = i->second.get_value<std::string>();
+ try {
+ uint16_t portNo = boost::lexical_cast<uint16_t>(port);
+ NFD_LOG_TRACE("UDP port set to " << portNo);
}
- else {
- factory = make_shared<UdpFactory>(port);
- m_factories.insert(std::make_pair("udp", factory));
+ catch (const std::bad_cast& error) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+ else if (i->first == "enable_v4") {
+ enableV4 = ConfigFile::parseYesNo(i, i->first, "udp");
+ }
+ else if (i->first == "enable_v6") {
+ enableV6 = ConfigFile::parseYesNo(i, i->first, "udp");
+ }
+ else if (i->first == "idle_timeout") {
+ try {
+ timeout = i->second.get_value<size_t>();
+ }
+ catch (const std::exception& e) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+ else if (i->first == "keep_alive_interval") {
+ try {
+ keepAliveInterval = i->second.get_value<size_t>();
+
+ /// \todo Make use of keepAliveInterval
+ /// \todo what is keep alive interval used for?
+ (void)(keepAliveInterval);
+ }
+ catch (const std::exception& e) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+ else if (i->first == "mcast") {
+ useMcast = ConfigFile::parseYesNo(i, i->first, "udp");
+ }
+ else if (i->first == "mcast_port") {
+ mcastPort = i->second.get_value<std::string>();
+ try {
+ uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
+ NFD_LOG_TRACE("UDP multicast port set to " << portNo);
+ }
+ catch (const std::bad_cast& error) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+ else if (i->first == "mcast_group") {
+ using namespace boost::asio::ip;
+ mcastGroup = i->second.get_value<std::string>();
+ try {
+ address mcastGroupTest = address::from_string(mcastGroup);
+ if (!mcastGroupTest.is_v4()) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+ catch(const std::runtime_error& e) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
+ i->first + "\" in \"udp\" section"));
+ }
+ }
+
+ if (!enableV4 && !enableV6) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
+ " Remove \"udp\" section to disable UDP channels or"
+ " re-enable at least one channel type."));
+ }
+ else if (useMcast && !enableV4) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
+ " have been disabled (conflicting configuration options set)"));
+ }
+
+ if (!isDryRun) {
+ shared_ptr<UdpFactory> factory;
+ bool isReload = false;
+ if (m_factories.count("udp") > 0) {
+ isReload = true;
+ factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
+ }
+ else {
+ factory = make_shared<UdpFactory>(port);
+ m_factories.insert(std::make_pair("udp", factory));
+ }
+
+ if (!isReload && enableV4) {
+ shared_ptr<UdpChannel> v4Channel =
+ factory->createChannel("0.0.0.0", port, time::seconds(timeout));
+
+ v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
+ UdpChannel::ConnectFailedCallback());
+
+ m_factories.insert(std::make_pair("udp4", factory));
+ }
+
+ if (!isReload && enableV6) {
+ shared_ptr<UdpChannel> v6Channel =
+ factory->createChannel("::", port, time::seconds(timeout));
+
+ v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
+ UdpChannel::ConnectFailedCallback());
+ m_factories.insert(std::make_pair("udp6", factory));
+ }
+
+ if (useMcast && enableV4) {
+ std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
+ for (const auto& nic : nicList) {
+ if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty()) {
+ ipv4MulticastInterfaces.push_back(nic);
+ }
}
- if (!isReload && enableV4)
- {
- shared_ptr<UdpChannel> v4Channel =
- factory->createChannel("0.0.0.0", port, time::seconds(timeout));
-
- v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
- UdpChannel::ConnectFailedCallback());
-
- m_factories.insert(std::make_pair("udp4", factory));
- }
-
- if (!isReload && enableV6)
- {
- shared_ptr<UdpChannel> v6Channel =
- factory->createChannel("::", port, time::seconds(timeout));
-
- v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
- UdpChannel::ConnectFailedCallback());
- m_factories.insert(std::make_pair("udp6", factory));
- }
-
- if (useMcast && enableV4)
- {
- std::vector<NetworkInterfaceInfo> ipv4MulticastInterfaces;
- for (const auto& nic : nicList)
- {
- if (nic.isUp() && nic.isMulticastCapable() && !nic.ipv4Addresses.empty())
- {
- ipv4MulticastInterfaces.push_back(nic);
- }
- }
-
- bool isNicNameNecessary = false;
+ bool isNicNameNecessary = false;
#if defined(__linux__)
- if (ipv4MulticastInterfaces.size() > 1)
- {
- // On Linux if we have more than one MulticastUdpFace
- // we need to specify the name of the interface
- isNicNameNecessary = true;
- }
+ if (ipv4MulticastInterfaces.size() > 1) {
+ // On Linux if we have more than one MulticastUdpFace
+ // we need to specify the name of the interface
+ isNicNameNecessary = true;
+ }
#endif
- std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
- for (UdpFactory::MulticastFaceMap::const_iterator i =
- factory->getMulticastFaces().begin();
- i != factory->getMulticastFaces().end();
- ++i)
- {
- multicastFacesToRemove.push_back(i->second);
- }
+ std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
+ for (auto i = factory->getMulticastFaces().begin();
+ i != factory->getMulticastFaces().end();
+ ++i) {
+ multicastFacesToRemove.push_back(i->second);
+ }
- for (const auto& nic : ipv4MulticastInterfaces)
- {
- shared_ptr<MulticastUdpFace> newFace;
- newFace = factory->createMulticastFace(nic.ipv4Addresses[0].to_string(),
- mcastGroup,
- mcastPort,
- isNicNameNecessary ? nic.name : "");
- addCreatedFaceToForwarder(newFace);
- multicastFacesToRemove.remove(newFace);
- }
+ for (const auto& nic : ipv4MulticastInterfaces) {
+ shared_ptr<MulticastUdpFace> newFace;
+ newFace = factory->createMulticastFace(nic.ipv4Addresses[0].to_string(),
+ mcastGroup,
+ mcastPort,
+ isNicNameNecessary ? nic.name : "");
+ addCreatedFaceToForwarder(newFace);
+ multicastFacesToRemove.remove(newFace);
+ }
- for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
- multicastFacesToRemove.begin();
- i != multicastFacesToRemove.end();
- ++i)
- {
- (*i)->close();
- }
- }
- else
- {
- std::list<shared_ptr<MulticastUdpFace> > multicastFacesToRemove;
- for (UdpFactory::MulticastFaceMap::const_iterator i =
- factory->getMulticastFaces().begin();
- i != factory->getMulticastFaces().end();
- ++i)
- {
- multicastFacesToRemove.push_back(i->second);
- }
-
- for (std::list<shared_ptr<MulticastUdpFace> >::iterator i =
- multicastFacesToRemove.begin();
- i != multicastFacesToRemove.end();
- ++i)
- {
- (*i)->close();
- }
- }
+ for (auto i = multicastFacesToRemove.begin();
+ i != multicastFacesToRemove.end();
+ ++i) {
+ (*i)->close();
+ }
}
+ else {
+ std::list<shared_ptr<MulticastUdpFace>> multicastFacesToRemove;
+ for (auto i = factory->getMulticastFaces().begin();
+ i != factory->getMulticastFaces().end();
+ ++i) {
+ multicastFacesToRemove.push_back(i->second);
+ }
+
+ for (auto i = multicastFacesToRemove.begin();
+ i != multicastFacesToRemove.end();
+ ++i) {
+ (*i)->close();
+ }
+ }
+ }
}
void
@@ -635,107 +742,82 @@
bool useMcast = true;
ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
- for (ConfigSection::const_iterator i = configSection.begin();
- i != configSection.end();
- ++i)
- {
- if (i->first == "mcast")
- {
- useMcast = parseYesNo(i, i->first, "ether");
- }
+ for (auto i = configSection.begin(); i != configSection.end(); ++i) {
+ if (i->first == "mcast") {
+ useMcast = ConfigFile::parseYesNo(i, i->first, "ether");
+ }
+ else if (i->first == "mcast_group") {
+ mcastGroup = ethernet::Address::fromString(i->second.get_value<std::string>());
+ if (mcastGroup.isNull()) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
+ i->first + "\" in \"ether\" section"));
+ }
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
+ i->first + "\" in \"ether\" section"));
+ }
+ }
- else if (i->first == "mcast_group")
- {
- mcastGroup = ethernet::Address::fromString(i->second.get_value<std::string>());
- if (mcastGroup.isNull())
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
- i->first + "\" in \"ether\" section"));
- }
- }
- else
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i->first +
- "\" in \"ether\" section"));
- }
+ if (!isDryRun) {
+ shared_ptr<EthernetFactory> factory;
+ if (m_factories.count("ether") > 0) {
+ factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
+ }
+ else {
+ factory = make_shared<EthernetFactory>();
+ m_factories.insert(std::make_pair("ether", factory));
}
- if (!isDryRun)
- {
- shared_ptr<EthernetFactory> factory;
- if (m_factories.count("ether") > 0) {
- factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
- }
- else {
- factory = make_shared<EthernetFactory>();
- m_factories.insert(std::make_pair("ether", factory));
+ if (useMcast) {
+ std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
+ for (auto i = factory->getMulticastFaces().begin();
+ i != factory->getMulticastFaces().end();
+ ++i) {
+ multicastFacesToRemove.push_back(i->second);
}
- if (useMcast)
- {
- std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
- for (EthernetFactory::MulticastFaceMap::const_iterator i =
- factory->getMulticastFaces().begin();
- i != factory->getMulticastFaces().end();
- ++i)
- {
- multicastFacesToRemove.push_back(i->second);
- }
+ for (const auto& nic : nicList) {
+ if (nic.isUp() && nic.isMulticastCapable()) {
+ try {
+ shared_ptr<EthernetFace> newFace =
+ factory->createMulticastFace(nic, mcastGroup);
- for (const auto& nic : nicList)
- {
- if (nic.isUp() && nic.isMulticastCapable())
- {
- try
- {
- shared_ptr<EthernetFace> newFace =
- factory->createMulticastFace(nic, mcastGroup);
-
- addCreatedFaceToForwarder(newFace);
- multicastFacesToRemove.remove(newFace);
- }
- catch (const EthernetFactory::Error& factoryError)
- {
- NFD_LOG_ERROR(factoryError.what() << ", continuing");
- }
- catch (const EthernetFace::Error& faceError)
- {
- NFD_LOG_ERROR(faceError.what() << ", continuing");
- }
- }
- }
-
- for (std::list<shared_ptr<EthernetFace> >::iterator i =
- multicastFacesToRemove.begin();
- i != multicastFacesToRemove.end();
- ++i)
- {
- (*i)->close();
- }
+ addCreatedFaceToForwarder(newFace);
+ multicastFacesToRemove.remove(newFace);
+ }
+ catch (const EthernetFactory::Error& factoryError) {
+ NFD_LOG_ERROR(factoryError.what() << ", continuing");
+ }
+ catch (const EthernetFace::Error& faceError) {
+ NFD_LOG_ERROR(faceError.what() << ", continuing");
+ }
}
- else
- {
- std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
- for (EthernetFactory::MulticastFaceMap::const_iterator i =
- factory->getMulticastFaces().begin();
- i != factory->getMulticastFaces().end();
- ++i)
- {
- multicastFacesToRemove.push_back(i->second);
- }
+ }
- for (std::list<shared_ptr<EthernetFace> >::iterator i =
- multicastFacesToRemove.begin();
- i != multicastFacesToRemove.end();
- ++i)
- {
- (*i)->close();
- }
- }
+ for (auto i = multicastFacesToRemove.begin();
+ i != multicastFacesToRemove.end();
+ ++i) {
+ (*i)->close();
+ }
}
+ else {
+ std::list<shared_ptr<EthernetFace> > multicastFacesToRemove;
+ for (auto i = factory->getMulticastFaces().begin();
+ i != factory->getMulticastFaces().end();
+ ++i) {
+ multicastFacesToRemove.push_back(i->second);
+ }
+
+ for (auto i = multicastFacesToRemove.begin();
+ i != multicastFacesToRemove.end();
+ ++i) {
+ (*i)->close();
+ }
+ }
+ }
#else
- BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot "
- "process \"ether\" section"));
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section"));
#endif // HAVE_LIBPCAP
}
@@ -758,442 +840,78 @@
bool enableV4 = true;
bool enableV6 = true;
- for (ConfigSection::const_iterator i = configSection.begin();
- i != configSection.end();
- ++i)
- {
- if (i->first == "port")
- {
- port = i->second.get_value<std::string>();
- try
- {
- uint16_t portNo = boost::lexical_cast<uint16_t>(port);
- NFD_LOG_TRACE("WebSocket port set to " << portNo);
- }
- catch (const std::bad_cast& error)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
- i->first + "\" in \"websocket\" section"));
- }
- }
- else if (i->first == "listen")
- {
- needToListen = parseYesNo(i, i->first, "websocket");
- }
- else if (i->first == "enable_v4")
- {
- enableV4 = parseYesNo(i, i->first, "websocket");
- }
- else if (i->first == "enable_v6")
- {
- enableV6 = parseYesNo(i, i->first, "websocket");
- }
- else
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
- i->first + "\" in \"websocket\" section"));
- }
+ for (auto i = configSection.begin(); i != configSection.end(); ++i) {
+ if (i->first == "port") {
+ port = i->second.get_value<std::string>();
+ try {
+ uint16_t portNo = boost::lexical_cast<uint16_t>(port);
+ NFD_LOG_TRACE("WebSocket port set to " << portNo);
+ }
+ catch (const std::bad_cast& error) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option " +
+ i->first + "\" in \"websocket\" section"));
+ }
+ }
+ else if (i->first == "listen") {
+ needToListen = ConfigFile::parseYesNo(i, i->first, "websocket");
+ }
+ else if (i->first == "enable_v4") {
+ enableV4 = ConfigFile::parseYesNo(i, i->first, "websocket");
+ }
+ else if (i->first == "enable_v6") {
+ enableV6 = ConfigFile::parseYesNo(i, i->first, "websocket");
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
+ i->first + "\" in \"websocket\" section"));
+ }
+ }
+
+ if (!enableV4 && !enableV6) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
+ " Remove \"websocket\" section to disable WebSocket channels or"
+ " re-enable at least one channel type."));
+ }
+
+ if (!enableV4 && enableV6) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
+ }
+
+ if (!isDryRun) {
+ if (m_factories.count("websocket") > 0) {
+ return;
}
- if (!enableV4 && !enableV6)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
- " Remove \"websocket\" section to disable WebSocket"
- " channels or re-enable at least one channel type."));
+ shared_ptr<WebSocketFactory> factory = make_shared<WebSocketFactory>(port);
+ m_factories.insert(std::make_pair("websocket", factory));
+
+ if (enableV6 && enableV4) {
+ shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
+ if (needToListen) {
+ ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
+ }
+
+ m_factories.insert(std::make_pair("websocket46", factory));
}
+ else if (enableV4) {
+ shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
+ if (needToListen) {
+ ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
+ }
- if (!enableV4 && enableV6)
- {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD does not allow pure IPv6 WebSocket channel."));
+ m_factories.insert(std::make_pair("websocket4", factory));
}
-
- if (!isDryRun)
- {
- if (m_factories.count("websocket") > 0)
- {
- return;
- }
-
- shared_ptr<WebSocketFactory> factory = make_shared<WebSocketFactory>(port);
- m_factories.insert(std::make_pair("websocket", factory));
-
- if (enableV6 && enableV4)
- {
- shared_ptr<WebSocketChannel> ip46Channel = factory->createChannel("::", port);
- if (needToListen)
- {
- ip46Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
- }
-
- m_factories.insert(std::make_pair("websocket46", factory));
- }
- else if (enableV4)
- {
- shared_ptr<WebSocketChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
- if (needToListen)
- {
- ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
- }
-
- m_factories.insert(std::make_pair("websocket4", factory));
- }
- }
+ }
#else
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without WebSocket, "
"cannot process \"websocket\" section"));
#endif // HAVE_WEBSOCKET
}
-
void
-FaceManager::onFaceRequest(const Interest& request)
-{
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
-
- if (commandNComps <= COMMAND_PREFIX.size())
- {
- // command is too short to have a verb
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- const Name::Component& verb = command.at(COMMAND_PREFIX.size());
-
- const auto unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
- if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
- {
- NFD_LOG_DEBUG("command result: processing verb: " << verb);
- (unsignedVerbProcessor->second)(this, request);
- }
- else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
- commandNComps < COMMAND_SIGNED_NCOMPS)
- {
- NFD_LOG_DEBUG("command result: unsigned verb: " << command);
- sendResponse(command, 401, "Signature required");
- }
- else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
- !COMMAND_PREFIX.isPrefixOf(command))
- {
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- }
- else
- {
- validate(request,
- bind(&FaceManager::onValidatedFaceRequest, this, _1),
- bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
- }
-}
-
-void
-FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
-{
- const Name& command = request->getName();
- const Name::Component& verb = command[COMMAND_PREFIX.size()];
- const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
-
- SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
- if (signedVerbProcessor != m_signedVerbDispatch.end())
- {
- ControlParameters parameters;
- if (!extractParameters(parameterComponent, parameters))
- {
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- NFD_LOG_DEBUG("command result: processing verb: " << verb);
- (signedVerbProcessor->second)(this, *request, parameters);
- }
- else
- {
- NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
- sendResponse(command, 501, "Unsupported command");
- }
-
-}
-
-void
-FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
+FaceManager::addCreatedFaceToForwarder(shared_ptr<Face> newFace)
{
m_faceTable.add(newFace);
-
- //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
}
-void
-FaceManager::onCreated(const Name& requestName,
- ControlParameters& parameters,
- const shared_ptr<Face>& newFace)
-{
- addCreatedFaceToForwarder(newFace);
- parameters.setFaceId(newFace->getId());
- parameters.setUri(newFace->getRemoteUri().toString());
- parameters.setFacePersistency(newFace->getPersistency());
-
- sendResponse(requestName, 200, "Success", parameters.wireEncode());
-}
-
-void
-FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
-{
- NFD_LOG_DEBUG("Failed to create face: " << reason);
- sendResponse(requestName, 408, reason);
-}
-
-void
-FaceManager::createFace(const Interest& request,
- ControlParameters& parameters)
-{
- const Name& requestName = request.getName();
- ndn::nfd::FaceCreateCommand command;
-
- if (!validateParameters(command, parameters))
- {
- sendResponse(requestName, 400, "Malformed command");
- NFD_LOG_TRACE("invalid control parameters URI");
- return;
- }
-
- FaceUri uri;
- if (!uri.parse(parameters.getUri()))
- {
- sendResponse(requestName, 400, "Malformed command");
- NFD_LOG_TRACE("failed to parse URI");
- return;
- }
-
- if (!uri.isCanonical())
- {
- sendResponse(requestName, 400, "Non-canonical URI");
- NFD_LOG_TRACE("received non-canonical URI");
- return;
- }
-
- FactoryMap::iterator factory = m_factories.find(uri.getScheme());
- if (factory == m_factories.end())
- {
- sendResponse(requestName, 501, "Unsupported protocol");
- return;
- }
-
- try
- {
- factory->second->createFace(uri,
- parameters.getFacePersistency(),
- bind(&FaceManager::onCreated,
- this, requestName, parameters, _1),
- bind(&FaceManager::onConnectFailed,
- this, requestName, _1));
- }
- catch (const std::runtime_error& error)
- {
- std::string errorMessage = "NFD error: ";
- errorMessage += error.what();
-
- NFD_LOG_ERROR(errorMessage);
- sendResponse(requestName, 500, errorMessage);
- }
- catch (const std::logic_error& error)
- {
- std::string errorMessage = "NFD error: ";
- errorMessage += error.what();
-
- NFD_LOG_ERROR(errorMessage);
- sendResponse(requestName, 500, errorMessage);
- }
-}
-
-
-void
-FaceManager::destroyFace(const Interest& request,
- ControlParameters& parameters)
-{
- const Name& requestName = request.getName();
- ndn::nfd::FaceDestroyCommand command;
-
- if (!validateParameters(command, parameters))
- {
- sendResponse(requestName, 400, "Malformed command");
- return;
- }
-
- shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
- if (static_cast<bool>(target))
- {
- target->close();
- }
-
- sendResponse(requestName, 200, "Success", parameters.wireEncode());
-
-}
-
-void
-FaceManager::onAddFace(shared_ptr<Face> face)
-{
- ndn::nfd::FaceEventNotification notification;
- notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
- face->copyStatusTo(notification);
-
- m_notificationStream.postNotification(notification);
-}
-
-void
-FaceManager::onRemoveFace(shared_ptr<Face> face)
-{
- ndn::nfd::FaceEventNotification notification;
- notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
- face->copyStatusTo(notification);
-
- m_notificationStream.postNotification(notification);
-}
-
-bool
-FaceManager::extractLocalControlParameters(const Interest& request,
- ControlParameters& parameters,
- ControlCommand& command,
- shared_ptr<LocalFace>& outFace,
- LocalControlFeature& outFeature)
-{
- if (!validateParameters(command, parameters))
- {
- sendResponse(request.getName(), 400, "Malformed command");
- return false;
- }
-
- shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
-
- if (!static_cast<bool>(face))
- {
- NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
- sendResponse(request.getName(), 410, "Face not found");
- return false;
- }
- else if (!face->isLocal())
- {
- NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
- face->getId());
- sendResponse(request.getName(), 412, "Face is non-local");
- return false;
- }
-
- outFace = dynamic_pointer_cast<LocalFace>(face);
- outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
-
- return true;
-}
-
-void
-FaceManager::enableLocalControl(const Interest& request,
- ControlParameters& parameters)
-{
- ndn::nfd::FaceEnableLocalControlCommand command;
-
-
- shared_ptr<LocalFace> face;
- LocalControlFeature feature;
-
- if (extractLocalControlParameters(request, parameters, command, face, feature))
- {
- face->setLocalControlHeaderFeature(feature, true);
- sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
- }
-}
-
-void
-FaceManager::disableLocalControl(const Interest& request,
- ControlParameters& parameters)
-{
- ndn::nfd::FaceDisableLocalControlCommand command;
- shared_ptr<LocalFace> face;
- LocalControlFeature feature;
-
- if (extractLocalControlParameters(request, parameters, command, face, feature))
- {
- face->setLocalControlHeaderFeature(feature, false);
- sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
- }
-}
-
-void
-FaceManager::listFaces(const Interest& request)
-{
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
-
- if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
- !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
- {
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- m_faceStatusPublisher.publish();
-}
-
-void
-FaceManager::listChannels(const Interest& request)
-{
- NFD_LOG_DEBUG("in listChannels");
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
-
- if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
- !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
- {
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- NFD_LOG_DEBUG("publishing");
- m_channelStatusPublisher.publish();
-}
-
-void
-FaceManager::listQueriedFaces(const Interest& request)
-{
- NFD_LOG_DEBUG("in listQueriedFaces");
- const Name& query = request.getName();
- const size_t queryNComps = query.size();
-
- if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
- !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
- {
- NFD_LOG_DEBUG("query result: malformed");
- sendNack(query);
- return;
- }
-
- ndn::nfd::FaceQueryFilter faceFilter;
- try
- {
- faceFilter.wireDecode(query[-1].blockFromValue());
- }
- catch (tlv::Error&)
- {
- NFD_LOG_DEBUG("query result: malformed filter");
- sendNack(query);
- return;
- }
-
- FaceQueryStatusPublisher
- faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
-
- faceQueryStatusPublisher.publish();
-}
-
-shared_ptr<ProtocolFactory>
-FaceManager::findFactory(const std::string& protocol)
-{
- FactoryMap::iterator factory = m_factories.find(protocol);
- if (factory != m_factories.end())
- return factory->second;
- else
- return shared_ptr<ProtocolFactory>();
-}
-
-} // namespace nfd
+} // namespace
diff --git a/daemon/mgmt/face-manager.hpp b/daemon/mgmt/face-manager.hpp
index 74dc0dd..f5283d6 100644
--- a/daemon/mgmt/face-manager.hpp
+++ b/daemon/mgmt/face-manager.hpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -26,118 +26,105 @@
#ifndef NFD_DAEMON_MGMT_FACE_MANAGER_HPP
#define NFD_DAEMON_MGMT_FACE_MANAGER_HPP
-#include "common.hpp"
-#include "core/notification-stream.hpp"
+#include "manager-base.hpp"
#include "face/local-face.hpp"
-#include "mgmt/manager-base.hpp"
-#include "mgmt/face-status-publisher.hpp"
-#include "mgmt/channel-status-publisher.hpp"
-#include "mgmt/face-query-status-publisher.hpp"
-
-#include <ndn-cxx/management/nfd-control-parameters.hpp>
-#include <ndn-cxx/management/nfd-control-response.hpp>
+#include <ndn-cxx/management/nfd-face-query-filter.hpp>
namespace nfd {
-const std::string FACE_MANAGER_PRIVILEGE = "faces";
-
-class ConfigFile;
-class Face;
class FaceTable;
-class LocalFace;
class NetworkInterfaceInfo;
class ProtocolFactory;
+/**
+ * @brief implement the Face Management of NFD Management Protocol.
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt
+ */
class FaceManager : public ManagerBase
{
public:
- class Error : public ManagerBase::Error
- {
- public:
- Error(const std::string& what) : ManagerBase::Error(what) {}
- };
+ FaceManager(FaceTable& faceTable,
+ Dispatcher& dispatcher,
+ CommandValidator& validator);
/**
- * \throws FaceManager::Error if localPort is an invalid port number
- */
- FaceManager(FaceTable& faceTable,
- shared_ptr<InternalFace> face,
- ndn::KeyChain& keyChain);
-
- virtual
- ~FaceManager();
-
- /** \brief Subscribe to a face management section(s) for the config file
+ * @brief Subscribe to face_system section for the config file
*/
void
setConfigFile(ConfigFile& configFile);
+PUBLIC_WITH_TESTS_ELSE_PRIVATE: // ControlCommand
void
- onFaceRequest(const Interest& request);
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
- void
- listFaces(const Interest& request);
+ createFace(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done);
void
- listChannels(const Interest& request);
+ destroyFace(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done);
void
- listQueriedFaces(const Interest& request);
+ enableLocalControl(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done);
- shared_ptr<ProtocolFactory>
- findFactory(const std::string& protocol);
-
-PROTECTED_WITH_TESTS_ELSE_PRIVATE:
void
- onValidatedFaceRequest(const shared_ptr<const Interest>& request);
+ disableLocalControl(const Name& topPrefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done);
- VIRTUAL_WITH_TESTS void
- createFace(const Interest& request,
- ControlParameters& parameters);
+PUBLIC_WITH_TESTS_ELSE_PRIVATE: // helpers for ControlCommand
+ void
+ afterCreateFaceSuccess(ControlParameters& parameters,
+ const shared_ptr<Face>& newFace,
+ const ndn::mgmt::CommandContinuation& done);
- VIRTUAL_WITH_TESTS void
- destroyFace(const Interest& request,
- ControlParameters& parameters);
+ void
+ afterCreateFaceFailure(const std::string& reason,
+ const ndn::mgmt::CommandContinuation& done);
- VIRTUAL_WITH_TESTS bool
+ struct ExtractLocalControlParametersResult
+ {
+ bool isValid;
+ shared_ptr<LocalFace> face;
+ LocalControlFeature feature;
+ };
+
+ ExtractLocalControlParametersResult
extractLocalControlParameters(const Interest& request,
- ControlParameters& parameters,
- ControlCommand& command,
- shared_ptr<LocalFace>& outFace,
- LocalControlFeature& outFeature);
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation& done);
- VIRTUAL_WITH_TESTS void
- enableLocalControl(const Interest& request,
- ControlParameters& parambeters);
-
- VIRTUAL_WITH_TESTS void
- disableLocalControl(const Interest& request,
- ControlParameters& parameters);
+PUBLIC_WITH_TESTS_ELSE_PRIVATE: // StatusDataset
+ void
+ listFaces(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context);
void
- ignoreUnsignedVerb(const Interest& request);
+ listChannels(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context);
void
- addCreatedFaceToForwarder(const shared_ptr<Face>& newFace);
+ queryFaces(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context);
+
+private: // helpers for StatusDataset handler
+ bool
+ doesMatchFilter(const ndn::nfd::FaceQueryFilter& filter, shared_ptr<Face> face);
+
+private: // NotificationStream
+ void
+ afterFaceAdded(shared_ptr<Face> face,
+ const ndn::mgmt::PostNotification& post);
void
- onCreated(const Name& requestName,
- ControlParameters& parameters,
- const shared_ptr<Face>& newFace);
+ afterFaceRemoved(shared_ptr<Face> face,
+ const ndn::mgmt::PostNotification& post);
+private: // configuration
void
- onConnectFailed(const Name& requestName, const std::string& reason);
-
- void
- onAddFace(shared_ptr<Face> face);
-
- void
- onRemoveFace(shared_ptr<Face> face);
-
-private:
- void
- onConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename);
+ processConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename);
void
processSectionUnix(const ConfigSection& configSection, bool isDryRun);
@@ -158,14 +145,9 @@
void
processSectionWebSocket(const ConfigSection& configSection, bool isDryRun);
- /** \brief parse a config option that can be either "yes" or "no"
- * \throw ConfigFile::Error value is neither "yes" nor "no"
- * \return true if "yes", false if "no"
- */
- bool
- parseYesNo(const ConfigSection::const_iterator& i,
- const std::string& optionName,
- const std::string& sectionName);
+private: // helpers for configuration
+ void
+ addCreatedFaceToForwarder(shared_ptr<Face> newFace);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
typedef std::map<std::string/*protocol*/, shared_ptr<ProtocolFactory>> FactoryMap;
@@ -175,76 +157,8 @@
FaceTable& m_faceTable;
signal::ScopedConnection m_faceAddConn;
signal::ScopedConnection m_faceRemoveConn;
- FaceStatusPublisher m_faceStatusPublisher;
- ChannelStatusPublisher m_channelStatusPublisher;
- NotificationStream<AppFace> m_notificationStream;
-
- typedef function<void(FaceManager*,
- const Interest&,
- ControlParameters&)> SignedVerbProcessor;
-
- typedef std::map<Name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
- typedef std::pair<Name::Component, SignedVerbProcessor> SignedVerbAndProcessor;
-
- typedef function<void(FaceManager*, const Interest&)> UnsignedVerbProcessor;
-
- typedef std::map<Name::Component, UnsignedVerbProcessor> UnsignedVerbDispatchTable;
- typedef std::pair<Name::Component, UnsignedVerbProcessor> UnsignedVerbAndProcessor;
-
- const SignedVerbDispatchTable m_signedVerbDispatch;
- const UnsignedVerbDispatchTable m_unsignedVerbDispatch;
-
- static const Name COMMAND_PREFIX; // /localhost/nfd/faces
-
- // number of components in an invalid signed command (i.e. should be signed, but isn't)
- // (/localhost/nfd/faces + verb + parameters) = 5
- static const size_t COMMAND_UNSIGNED_NCOMPS;
-
- // number of components in a valid signed command.
- // (see UNSIGNED_NCOMPS), 9 with signed Interest support.
- static const size_t COMMAND_SIGNED_NCOMPS;
-
- static const SignedVerbAndProcessor SIGNED_COMMAND_VERBS[];
- static const UnsignedVerbAndProcessor UNSIGNED_COMMAND_VERBS[];
-
- static const Name FACES_LIST_DATASET_PREFIX;
- static const size_t FACES_LIST_DATASET_NCOMPS;
-
- static const Name CHANNELS_LIST_DATASET_PREFIX;
- static const size_t CHANNELS_LIST_DATASET_NCOMPS;
-
- static const Name FACES_QUERY_DATASET_PREFIX;
- static const size_t FACES_QUERY_DATASET_NCOMPS;
-
- static const Name FACE_EVENTS_PREFIX;
};
-inline bool
-FaceManager::parseYesNo(const ConfigSection::const_iterator& i,
- const std::string& optionName,
- const std::string& sectionName)
-{
- const std::string value = i->second.get_value<std::string>();
- if (value == "yes")
- {
- return true;
- }
- else if (value == "no")
- {
- return false;
- }
-
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
- optionName + "\" in \"" +
- sectionName + "\" section"));
-}
-
-inline void
-FaceManager::ignoreUnsignedVerb(const Interest& request)
-{
- // do nothing
-}
-
} // namespace nfd
#endif // NFD_DAEMON_MGMT_FACE_MANAGER_HPP
diff --git a/daemon/mgmt/face-query-status-publisher.cpp b/daemon/mgmt/face-query-status-publisher.cpp
deleted file mode 100644
index e60b949..0000000
--- a/daemon/mgmt/face-query-status-publisher.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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 "face-query-status-publisher.hpp"
-
-#include <boost/range/adaptor/reversed.hpp>
-#include <ndn-cxx/management/nfd-face-status.hpp>
-
-namespace nfd {
-
-FaceQueryStatusPublisher::FaceQueryStatusPublisher(const FaceTable& faceTable,
- AppFace& face,
- const Name& prefix,
- const ndn::nfd::FaceQueryFilter& filter,
- ndn::KeyChain& keyChain)
- : SegmentPublisher(face, prefix, keyChain)
- , m_faceTable(faceTable)
- , m_faceFilter(filter)
-{
-}
-
-FaceQueryStatusPublisher::~FaceQueryStatusPublisher()
-{
-}
-
-bool
-FaceQueryStatusPublisher::doesMatchFilter(const shared_ptr<Face>& face)
-{
- if (m_faceFilter.hasFaceId() &&
- m_faceFilter.getFaceId() != static_cast<uint64_t>(face->getId())) {
- return false;
- }
-
- if (m_faceFilter.hasUriScheme() &&
- (m_faceFilter.getUriScheme() != face->getRemoteUri().getScheme() ||
- m_faceFilter.getUriScheme() != face->getLocalUri().getScheme())) {
- return false;
- }
-
- if (m_faceFilter.hasRemoteUri() &&
- m_faceFilter.getRemoteUri() != face->getRemoteUri().toString()) {
- return false;
- }
-
- if (m_faceFilter.hasLocalUri() && m_faceFilter.getLocalUri() != face->getLocalUri().toString()) {
- return false;
- }
-
- if (m_faceFilter.hasFaceScope() &&
- (m_faceFilter.getFaceScope() == ndn::nfd::FACE_SCOPE_LOCAL) != face->isLocal()) {
- return false;
- }
-
- if (m_faceFilter.hasFacePersistency() &&
- m_faceFilter.getFacePersistency() != face->getPersistency()) {
- return false;
- }
-
- if (m_faceFilter.hasLinkType() &&
- (m_faceFilter.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) != face->isMultiAccess()) {
- return false;
- }
-
- return true;
-}
-
-size_t
-FaceQueryStatusPublisher::generate(ndn::EncodingBuffer& outBuffer)
-{
- size_t totalLength = 0;
-
- for (const shared_ptr<Face>& face : m_faceTable | boost::adaptors::reversed) {
- if (doesMatchFilter(face)) {
- ndn::nfd::FaceStatus status = face->getFaceStatus();
- totalLength += status.wireEncode(outBuffer);
- }
- }
- return totalLength;
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/face-query-status-publisher.hpp b/daemon/mgmt/face-query-status-publisher.hpp
deleted file mode 100644
index 237cecb..0000000
--- a/daemon/mgmt/face-query-status-publisher.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_DAEMON_MGMT_QUERIED_FACE_STATUS_PUBLISHER_HPP
-#define NFD_DAEMON_MGMT_QUERIED_FACE_STATUS_PUBLISHER_HPP
-
-#include "core/segment-publisher.hpp"
-#include "mgmt/app-face.hpp"
-#include "fw/face-table.hpp"
-
-#include <ndn-cxx/management/nfd-face-query-filter.hpp>
-
-namespace nfd {
-
-class FaceQueryStatusPublisher : public SegmentPublisher<AppFace>
-{
-public:
- FaceQueryStatusPublisher(const FaceTable& faceTable,
- AppFace& face,
- const Name& prefix,
- const ndn::nfd::FaceQueryFilter& filter,
- ndn::KeyChain& keyChain);
-
- virtual
- ~FaceQueryStatusPublisher();
-
- bool
- doesMatchFilter(const shared_ptr<Face>& face);
-
-protected:
-
- virtual size_t
- generate(ndn::EncodingBuffer& outBuffer);
-
-private:
- const FaceTable& m_faceTable;
- const ndn::nfd::FaceQueryFilter& m_faceFilter;
-};
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_QUERIED_FACE_STATUS_PUBLISHER_HPP
diff --git a/daemon/mgmt/face-status-publisher.cpp b/daemon/mgmt/face-status-publisher.cpp
deleted file mode 100644
index ff061fa..0000000
--- a/daemon/mgmt/face-status-publisher.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014 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
- *
- * 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 "face-status-publisher.hpp"
-#include "fw/face-table.hpp"
-
-#include <boost/range/adaptor/reversed.hpp>
-#include <ndn-cxx/management/nfd-face-status.hpp>
-
-namespace nfd {
-
-FaceStatusPublisher::FaceStatusPublisher(const FaceTable& faceTable,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain)
- : SegmentPublisher(face, prefix, keyChain)
- , m_faceTable(faceTable)
-{
-}
-
-FaceStatusPublisher::~FaceStatusPublisher()
-{
-}
-
-size_t
-FaceStatusPublisher::generate(ndn::EncodingBuffer& outBuffer)
-{
- size_t totalLength = 0;
-
- for (const shared_ptr<Face>& face : m_faceTable | boost::adaptors::reversed) {
- ndn::nfd::FaceStatus status = face->getFaceStatus();
- totalLength += status.wireEncode(outBuffer);
- }
- return totalLength;
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/face-status-publisher.hpp b/daemon/mgmt/face-status-publisher.hpp
deleted file mode 100644
index 5091165..0000000
--- a/daemon/mgmt/face-status-publisher.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_DAEMON_MGMT_FACE_STATUS_PUBLISHER_HPP
-#define NFD_DAEMON_MGMT_FACE_STATUS_PUBLISHER_HPP
-
-#include "core/segment-publisher.hpp"
-#include "mgmt/app-face.hpp"
-
-namespace nfd {
-
-class FaceTable;
-
-class FaceStatusPublisher : public SegmentPublisher<AppFace>
-{
-public:
- FaceStatusPublisher(const FaceTable& faceTable,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain);
-
- virtual
- ~FaceStatusPublisher();
-
-protected:
-
- virtual size_t
- generate(ndn::EncodingBuffer& outBuffer);
-
-private:
- const FaceTable& m_faceTable;
-};
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_FACE_STATUS_PUBLISHER_HPP
diff --git a/daemon/mgmt/fib-enumeration-publisher.cpp b/daemon/mgmt/fib-enumeration-publisher.cpp
deleted file mode 100644
index 5123a58..0000000
--- a/daemon/mgmt/fib-enumeration-publisher.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014 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
- *
- * 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 "fib-enumeration-publisher.hpp"
-#include "core/logger.hpp"
-#include "table/fib.hpp"
-
-#include <ndn-cxx/management/nfd-fib-entry.hpp>
-
-namespace nfd {
-
-NFD_LOG_INIT("FibEnumerationPublisher");
-
-FibEnumerationPublisher::FibEnumerationPublisher(const Fib& fib,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain)
- : SegmentPublisher(face, prefix, keyChain)
- , m_fib(fib)
-{
-}
-
-FibEnumerationPublisher::~FibEnumerationPublisher()
-{
-}
-
-size_t
-FibEnumerationPublisher::generate(ndn::EncodingBuffer& outBuffer)
-{
- size_t totalLength = 0;
-
- /// \todo Enable use of Fib::const_reverse_iterator (when it is available)
- for (Fib::const_iterator i = m_fib.begin(); i != m_fib.end(); ++i)
- {
- const fib::Entry& entry = *i;
- const Name& prefix = entry.getPrefix();
- size_t fibEntryLength = 0;
-
- ndn::nfd::FibEntry tlvEntry;
- const fib::NextHopList& nextHops = entry.getNextHops();
-
- for (fib::NextHopList::const_iterator j = nextHops.begin();
- j != nextHops.end();
- ++j)
- {
- const fib::NextHop& next = *j;
- ndn::nfd::NextHopRecord nextHopRecord;
- nextHopRecord.setFaceId(next.getFace()->getId());
- nextHopRecord.setCost(next.getCost());
-
- tlvEntry.addNextHopRecord(nextHopRecord);
- }
-
- tlvEntry.setPrefix(prefix);
- fibEntryLength += tlvEntry.wireEncode(outBuffer);
-
- NFD_LOG_DEBUG("generate: fib entry length = " << fibEntryLength);
-
- totalLength += fibEntryLength;
- }
-
- NFD_LOG_DEBUG("generate: Total length = " << totalLength);
- return totalLength;
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/fib-enumeration-publisher.hpp b/daemon/mgmt/fib-enumeration-publisher.hpp
deleted file mode 100644
index 2ff5c31..0000000
--- a/daemon/mgmt/fib-enumeration-publisher.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_DAEMON_MGMT_FIB_ENUMERATION_PUBLISHER_HPP
-#define NFD_DAEMON_MGMT_FIB_ENUMERATION_PUBLISHER_HPP
-
-#include "core/segment-publisher.hpp"
-#include "mgmt/app-face.hpp"
-
-namespace nfd {
-
-class Fib;
-
-class FibEnumerationPublisher : public SegmentPublisher<AppFace>
-{
-public:
- FibEnumerationPublisher(const Fib& fib,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain);
-
- virtual
- ~FibEnumerationPublisher();
-
-protected:
-
- virtual size_t
- generate(ndn::EncodingBuffer& outBuffer);
-
-private:
- const Fib& m_fib;
-};
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_FIB_ENUMERATION_PUBLISHER_HPP
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 3db26e7..12374f1 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -24,171 +24,34 @@
*/
#include "fib-manager.hpp"
-
-#include "core/logger.hpp"
-#include "table/fib.hpp"
-#include "fw/forwarder.hpp"
-#include "mgmt/internal-face.hpp"
-#include "mgmt/app-face.hpp"
-
-#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/management/nfd-fib-entry.hpp>
namespace nfd {
NFD_LOG_INIT("FibManager");
-const Name FibManager::COMMAND_PREFIX = "/localhost/nfd/fib";
-
-const size_t FibManager::COMMAND_UNSIGNED_NCOMPS =
- FibManager::COMMAND_PREFIX.size() +
- 1 + // verb
- 1; // verb parameters
-
-const size_t FibManager::COMMAND_SIGNED_NCOMPS =
- FibManager::COMMAND_UNSIGNED_NCOMPS +
- 4; // (timestamp, nonce, signed info tlv, signature tlv)
-
-const FibManager::SignedVerbAndProcessor FibManager::SIGNED_COMMAND_VERBS[] =
- {
-
- SignedVerbAndProcessor(
- Name::Component("add-nexthop"),
- &FibManager::addNextHop
- ),
-
- SignedVerbAndProcessor(
- Name::Component("remove-nexthop"),
- &FibManager::removeNextHop
- ),
-
- };
-
-const FibManager::UnsignedVerbAndProcessor FibManager::UNSIGNED_COMMAND_VERBS[] =
- {
- UnsignedVerbAndProcessor(
- Name::Component("list"),
- &FibManager::listEntries
- ),
- };
-
-const Name FibManager::LIST_COMMAND_PREFIX("/localhost/nfd/fib/list");
-const size_t FibManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
-
-
FibManager::FibManager(Fib& fib,
function<shared_ptr<Face>(FaceId)> getFace,
- shared_ptr<InternalFace> face,
- ndn::KeyChain& keyChain)
- : ManagerBase(face, FIB_PRIVILEGE, keyChain)
- , m_managedFib(fib)
+ Dispatcher& dispatcher,
+ CommandValidator& validator)
+ : ManagerBase(dispatcher, validator, "fib")
+ , m_fib(fib)
, m_getFace(getFace)
- , m_fibEnumerationPublisher(fib, *face, LIST_COMMAND_PREFIX, keyChain)
- , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
- SIGNED_COMMAND_VERBS +
- (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
- , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
- UNSIGNED_COMMAND_VERBS +
- (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
{
- face->setInterestFilter("/localhost/nfd/fib",
- bind(&FibManager::onFibRequest, this, _2));
-}
+ registerCommandHandler<ndn::nfd::FibAddNextHopCommand>("add-nexthop",
+ bind(&FibManager::addNextHop, this, _2, _3, _4, _5));
+ registerCommandHandler<ndn::nfd::FibRemoveNextHopCommand>("remove-nexthop",
+ bind(&FibManager::removeNextHop, this, _2, _3, _4, _5));
-FibManager::~FibManager()
-{
-
+ registerStatusDatasetHandler("list", bind(&FibManager::listEntries, this, _1, _2, _3));
}
void
-FibManager::onFibRequest(const Interest& request)
+FibManager::addNextHop(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done)
{
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
-
- if (commandNComps <= COMMAND_PREFIX.size())
- {
- // command is too short to have a verb
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- const Name::Component& verb = command.at(COMMAND_PREFIX.size());
-
- const auto unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
- if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
- {
- NFD_LOG_DEBUG("command result: processing verb: " << verb);
- (unsignedVerbProcessor->second)(this, request);
- }
- else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
- commandNComps < COMMAND_SIGNED_NCOMPS)
- {
- NFD_LOG_DEBUG("command result: unsigned verb: " << command);
- sendResponse(command, 401, "Signature required");
- }
- else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
- !COMMAND_PREFIX.isPrefixOf(command))
- {
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- }
- else
- {
- validate(request,
- bind(&FibManager::onValidatedFibRequest, this, _1),
- bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
- }
-}
-
-void
-FibManager::onValidatedFibRequest(const shared_ptr<const Interest>& request)
-{
- const Name& command = request->getName();
- const Name::Component& verb = command[COMMAND_PREFIX.size()];
- const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
-
- SignedVerbDispatchTable::const_iterator verbProcessor = m_signedVerbDispatch.find(verb);
- if (verbProcessor != m_signedVerbDispatch.end())
- {
- ControlParameters parameters;
- if (!extractParameters(parameterComponent, parameters))
- {
- NFD_LOG_DEBUG("command result: malformed verb: " << verb);
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- bool isSelfRegistration = (!parameters.hasFaceId() || parameters.getFaceId() == 0);
- if (isSelfRegistration)
- {
- parameters.setFaceId(request->getIncomingFaceId());
- }
-
- NFD_LOG_DEBUG("command result: processing verb: " << verb);
- ControlResponse response;
- (verbProcessor->second)(this, parameters, response);
- sendResponse(command, response);
- }
- else
- {
- NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
- sendResponse(command, 501, "Unsupported command");
- }
-}
-
-void
-FibManager::addNextHop(ControlParameters& parameters,
- ControlResponse& response)
-{
- ndn::nfd::FibAddNextHopCommand command;
-
- if (!validateParameters(command, parameters))
- {
- NFD_LOG_DEBUG("add-nexthop result: FAIL reason: malformed");
- setResponse(response, 400, "Malformed command");
- return;
- }
+ setFaceForSelfRegistration(interest, parameters);
const Name& prefix = parameters.getName();
FaceId faceId = parameters.getFaceId();
@@ -198,87 +61,89 @@
<< " faceid: " << faceId
<< " cost: " << cost);
- shared_ptr<Face> nextHopFace = m_getFace(faceId);
- if (static_cast<bool>(nextHopFace))
- {
- shared_ptr<fib::Entry> entry = m_managedFib.insert(prefix).first;
+ auto face = m_getFace(faceId);
+ if (static_cast<bool>(face)) {
+ auto entry = m_fib.insert(prefix).first;
- entry->addNextHop(nextHopFace, cost);
+ entry->addNextHop(face, cost);
- NFD_LOG_DEBUG("add-nexthop result: OK"
- << " prefix:" << prefix
- << " faceid: " << faceId
- << " cost: " << cost);
+ NFD_LOG_DEBUG("add-nexthop result: OK"
+ << " prefix:" << prefix
+ << " faceid: " << faceId
+ << " cost: " << cost);
- setResponse(response, 200, "Success", parameters.wireEncode());
- }
- else
- {
- NFD_LOG_DEBUG("add-nexthop result: FAIL reason: unknown-faceid: " << faceId);
- setResponse(response, 410, "Face not found");
- }
+ return done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
+ }
+ else {
+ NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-faceid: " << faceId);
+ return done(ControlResponse(410, "Face not found"));
+ }
}
void
-FibManager::removeNextHop(ControlParameters& parameters,
- ControlResponse& response)
+FibManager::removeNextHop(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done)
{
- ndn::nfd::FibRemoveNextHopCommand command;
- if (!validateParameters(command, parameters))
- {
- NFD_LOG_DEBUG("remove-nexthop result: FAIL reason: malformed");
- setResponse(response, 400, "Malformed command");
- return;
- }
+ setFaceForSelfRegistration(interest, parameters);
NFD_LOG_TRACE("remove-nexthop prefix: " << parameters.getName()
<< " faceid: " << parameters.getFaceId());
- shared_ptr<Face> faceToRemove = m_getFace(parameters.getFaceId());
- if (static_cast<bool>(faceToRemove))
- {
- shared_ptr<fib::Entry> entry = m_managedFib.findExactMatch(parameters.getName());
- if (static_cast<bool>(entry))
- {
- entry->removeNextHop(faceToRemove);
- NFD_LOG_DEBUG("remove-nexthop result: OK prefix: " << parameters.getName()
- << " faceid: " << parameters.getFaceId());
+ auto face = m_getFace(parameters.getFaceId());
+ if (static_cast<bool>(face)) {
+ auto entry = m_fib.findExactMatch(parameters.getName());
+ if (static_cast<bool>(entry)) {
+ entry->removeNextHop(face);
+ NFD_LOG_DEBUG("remove-nexthop result: OK prefix: " << parameters.getName()
+ << " faceid: " << parameters.getFaceId());
- if (!entry->hasNextHops())
- {
- m_managedFib.erase(*entry);
- }
- }
- else
- {
- NFD_LOG_DEBUG("remove-nexthop result: OK, but entry for face id "
- << parameters.getFaceId() << " not found");
- }
+ if (!entry->hasNextHops()) {
+ m_fib.erase(*entry);
+ }
}
- else
- {
- NFD_LOG_DEBUG("remove-nexthop result: OK, but face id "
- << parameters.getFaceId() << " not found");
+ else {
+ NFD_LOG_DEBUG("remove-nexthop result: OK");
}
+ }
+ else {
+ NFD_LOG_DEBUG("remove-nexthop result: OK");
+ }
- setResponse(response, 200, "Success", parameters.wireEncode());
+ done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
}
void
-FibManager::listEntries(const Interest& request)
+FibManager::listEntries(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context)
{
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
+ for (auto&& entry : m_fib) {
+ auto prefix = entry.getPrefix();
+ ndn::nfd::FibEntry record;
+ const auto& nextHops = entry.getNextHops();
- if (commandNComps < LIST_COMMAND_NCOMPS ||
- !LIST_COMMAND_PREFIX.isPrefixOf(command))
- {
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
+ for (auto&& next : nextHops) {
+ ndn::nfd::NextHopRecord nextHopRecord;
+ nextHopRecord.setFaceId(next.getFace()->getId());
+ nextHopRecord.setCost(next.getCost());
+
+ record.addNextHopRecord(nextHopRecord);
}
- m_fibEnumerationPublisher.publish();
+ record.setPrefix(prefix);
+ context.append(record.wireEncode());
+ }
+
+ context.end();
}
-} // namespace nfd
+void
+FibManager::setFaceForSelfRegistration(const Interest& request, ControlParameters& parameters)
+{
+ bool isSelfRegistration = (parameters.getFaceId() == 0);
+ if (isSelfRegistration) {
+ parameters.setFaceId(request.getIncomingFaceId());
+ }
+}
+
+} // namespace
diff --git a/daemon/mgmt/fib-manager.hpp b/daemon/mgmt/fib-manager.hpp
index c8c21ea..7c66138 100644
--- a/daemon/mgmt/fib-manager.hpp
+++ b/daemon/mgmt/fib-manager.hpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -26,87 +26,55 @@
#ifndef NFD_DAEMON_MGMT_FIB_MANAGER_HPP
#define NFD_DAEMON_MGMT_FIB_MANAGER_HPP
-#include "common.hpp"
-#include "mgmt/manager-base.hpp"
-#include "mgmt/fib-enumeration-publisher.hpp"
+#include "manager-base.hpp"
+#include "core/logger.hpp"
+#include "table/fib.hpp"
+#include "fw/forwarder.hpp"
namespace nfd {
-class Face;
-class Forwarder;
-class Fib;
-
-const std::string FIB_PRIVILEGE = "fib"; // config file privilege name
-
+/**
+ * @brief implement the FIB Management of NFD Management Protocol.
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt
+ */
class FibManager : public ManagerBase
{
public:
-
+ /**
+ * @brief construct a FibManger
+ *
+ * @param fib the managed FIB
+ * @param getFace a function used to retrive a face by FaceId from the face table
+ * @param dispatcher the management dispatcher
+ * @param validator the command validator
+ */
FibManager(Fib& fib,
function<shared_ptr<Face>(FaceId)> getFace,
- shared_ptr<InternalFace> face,
- ndn::KeyChain& keyChain);
-
- virtual
- ~FibManager();
-
- void
- onFibRequest(const Interest& request);
+ Dispatcher& dispatcher,
+ CommandValidator& validator);
private:
+ void
+ addNextHop(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done);
void
- onValidatedFibRequest(const shared_ptr<const Interest>& request);
+ removeNextHop(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done);
void
- addNextHop(ControlParameters& parameters,
- ControlResponse& response);
-
- void
- removeNextHop(ControlParameters& parameters,
- ControlResponse& response);
-
- void
- listEntries(const Interest& request);
+ listEntries(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context);
private:
+ void
+ setFaceForSelfRegistration(const Interest& request, ControlParameters& parameters);
- Fib& m_managedFib;
+private:
+ Fib& m_fib;
function<shared_ptr<Face>(FaceId)> m_getFace;
- FibEnumerationPublisher m_fibEnumerationPublisher;
-
- typedef function<void(FibManager*,
- ControlParameters&,
- ControlResponse&)> SignedVerbProcessor;
-
- typedef std::map<Name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
-
- typedef std::pair<Name::Component, SignedVerbProcessor> SignedVerbAndProcessor;
-
- typedef function<void(FibManager*, const Interest&)> UnsignedVerbProcessor;
-
- typedef std::map<Name::Component, UnsignedVerbProcessor> UnsignedVerbDispatchTable;
- typedef std::pair<Name::Component, UnsignedVerbProcessor> UnsignedVerbAndProcessor;
-
-
- const SignedVerbDispatchTable m_signedVerbDispatch;
- const UnsignedVerbDispatchTable m_unsignedVerbDispatch;
-
- static const Name COMMAND_PREFIX; // /localhost/nfd/fib
-
- // number of components in an invalid, but not malformed, unsigned command.
- // (/localhost/nfd/fib + verb + parameters) = 5
- static const size_t COMMAND_UNSIGNED_NCOMPS;
-
- // number of components in a valid signed Interest.
- // UNSIGNED_NCOMPS + 4 command Interest components = 9
- static const size_t COMMAND_SIGNED_NCOMPS;
-
- static const SignedVerbAndProcessor SIGNED_COMMAND_VERBS[];
- static const UnsignedVerbAndProcessor UNSIGNED_COMMAND_VERBS[];
-
- static const Name LIST_COMMAND_PREFIX;
- static const size_t LIST_COMMAND_NCOMPS;
};
} // namespace nfd
diff --git a/daemon/mgmt/forwarder-status-manager.cpp b/daemon/mgmt/forwarder-status-manager.cpp
new file mode 100644
index 0000000..bf2372b
--- /dev/null
+++ b/daemon/mgmt/forwarder-status-manager.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "forwarder-status-manager.hpp"
+#include "fw/forwarder.hpp"
+#include "version.hpp"
+
+namespace nfd {
+
+const time::milliseconds STATUS_SERVER_DEFAULT_FRESHNESS = time::milliseconds(5000);
+
+ForwarderStatusManager::ForwarderStatusManager(Forwarder& forwarder, Dispatcher& dispatcher)
+ : m_forwarder(forwarder)
+ , m_dispatcher(dispatcher)
+ , m_startTimestamp(time::system_clock::now())
+{
+ m_dispatcher.addStatusDataset("status", ndn::mgmt::makeAcceptAllAuthorization(),
+ bind(&ForwarderStatusManager::listStatus, this, _1, _2, _3));
+}
+
+void
+ForwarderStatusManager::listStatus(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context)
+{
+ ndn::nfd::ForwarderStatus status;
+
+ status.setNfdVersion(NFD_VERSION_BUILD_STRING);
+ status.setStartTimestamp(m_startTimestamp);
+ status.setCurrentTimestamp(time::system_clock::now());
+
+ status.setNNameTreeEntries(m_forwarder.getNameTree().size());
+ status.setNFibEntries(m_forwarder.getFib().size());
+ status.setNPitEntries(m_forwarder.getPit().size());
+ status.setNMeasurementsEntries(m_forwarder.getMeasurements().size());
+ status.setNCsEntries(m_forwarder.getCs().size());
+
+ m_forwarder.getCounters().copyTo(status);
+
+ context.setExpiry(STATUS_SERVER_DEFAULT_FRESHNESS);
+
+ status.wireEncode().parse();
+ for (const auto& subblock : status.wireEncode().elements()) {
+ context.append(subblock);
+ }
+ context.end();
+}
+
+} // namespace nfd
diff --git a/daemon/mgmt/forwarder-status-manager.hpp b/daemon/mgmt/forwarder-status-manager.hpp
new file mode 100644
index 0000000..57d89c8
--- /dev/null
+++ b/daemon/mgmt/forwarder-status-manager.hpp
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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/>.
+ */
+
+#ifndef NFD_DAEMON_MGMT_FORWARDER_STATUS_MANAGER_HPP
+#define NFD_DAEMON_MGMT_FORWARDER_STATUS_MANAGER_HPP
+
+#include "manager-base.hpp"
+#include <ndn-cxx/management/nfd-forwarder-status.hpp>
+
+namespace nfd {
+
+class Forwarder;
+
+/**
+ * @brief implement the Forwarder Status of NFD Management Protocol.
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/ForwarderStatus
+ */
+class ForwarderStatusManager : noncopyable
+{
+public:
+ ForwarderStatusManager(Forwarder& forwarder, Dispatcher& dispatcher);
+
+private:
+ void
+ listStatus(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context);
+
+private:
+ Forwarder& m_forwarder;
+ Dispatcher& m_dispatcher;
+ time::system_clock::TimePoint m_startTimestamp;
+};
+
+} // namespace nfd
+
+#endif // NFD_DAEMON_MGMT_FORWARDER_STATUS_MANAGER_HPP
diff --git a/daemon/mgmt/internal-face.cpp b/daemon/mgmt/internal-face.cpp
deleted file mode 100644
index 7569fb9..0000000
--- a/daemon/mgmt/internal-face.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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 "internal-face.hpp"
-#include "core/logger.hpp"
-#include "core/global-io.hpp"
-
-namespace nfd {
-
-NFD_LOG_INIT("InternalFace");
-
-InternalFace::InternalFace()
- : Face(FaceUri("internal://"), FaceUri("internal://"), true)
-{
-}
-
-void
-InternalFace::sendInterest(const Interest& interest)
-{
- this->emitSignal(onSendInterest, interest);
-
- // Invoke .processInterest a bit later,
- // to avoid potential problems in forwarding pipelines.
- getGlobalIoService().post(bind(&InternalFace::processInterest,
- this, interest.shared_from_this()));
-}
-
-void
-InternalFace::processInterest(const shared_ptr<const Interest>& interest)
-{
- if (m_interestFilters.size() == 0)
- {
- NFD_LOG_DEBUG("no Interest filters to match against");
- return;
- }
-
- const Name& interestName(interest->getName());
- NFD_LOG_DEBUG("received Interest: " << interestName);
-
- std::map<Name, OnInterest>::const_iterator filter =
- m_interestFilters.lower_bound(interestName);
-
- // lower_bound gives us the first Name that is
- // an exact match OR ordered after interestName.
- //
- // If we reach the end of the map, then we need
- // only check if the before-end element is a match.
- //
- // If we match an element, then the current
- // position or the previous element are potential
- // matches.
- //
- // If we hit begin, the element is either an exact
- // match or there is no matching prefix in the map.
-
-
- if (filter == m_interestFilters.end() && filter != m_interestFilters.begin())
- {
- // We hit the end, check if the previous element
- // is a match
- --filter;
- if (filter->first.isPrefixOf(interestName))
- {
- NFD_LOG_DEBUG("found Interest filter for " << filter->first << " (before end match)");
- filter->second(interestName, *interest);
- }
- else
- {
- NFD_LOG_DEBUG("no Interest filter found for " << interestName << " (before end)");
- }
- }
- else if (filter->first == interestName)
- {
- NFD_LOG_DEBUG("found Interest filter for " << filter->first << " (exact match)");
- filter->second(interestName, *interest);
- }
- else if (filter != m_interestFilters.begin())
- {
- // the element we found is canonically
- // ordered after interestName.
- // Check the previous element.
- --filter;
- if (filter->first.isPrefixOf(interestName))
- {
- NFD_LOG_DEBUG("found Interest filter for " << filter->first << " (previous match)");
- filter->second(interestName, *interest);
- }
- else
- {
- NFD_LOG_DEBUG("no Interest filter found for " << interestName << " (previous)");
- }
- }
- else
- {
- NFD_LOG_DEBUG("no Interest filter found for " << interestName << " (begin)");
- }
- //Drop Interest
-}
-
-void
-InternalFace::sendData(const Data& data)
-{
- this->emitSignal(onSendData, data);
-}
-
-void
-InternalFace::close()
-{
- BOOST_THROW_EXCEPTION(Error("Internal face cannot be closed"));
-}
-
-void
-InternalFace::setInterestFilter(const Name& filter,
- OnInterest onInterest)
-{
- NFD_LOG_INFO("registering callback for " << filter);
- m_interestFilters[filter] = onInterest;
-}
-
-void
-InternalFace::put(const Data& data)
-{
- this->emitSignal(onReceiveData, data);
-}
-
-InternalFace::~InternalFace()
-{
-
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/internal-face.hpp b/daemon/mgmt/internal-face.hpp
deleted file mode 100644
index c35676f..0000000
--- a/daemon/mgmt/internal-face.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_DAEMON_MGMT_INTERNAL_FACE_HPP
-#define NFD_DAEMON_MGMT_INTERNAL_FACE_HPP
-
-#include "face/face.hpp"
-#include "app-face.hpp"
-
-#include "command-validator.hpp"
-
-namespace nfd {
-
-class InternalFace : public Face, public AppFace
-{
-public:
- /**
- * \brief InternalFace-related error
- */
- class Error : public Face::Error
- {
- public:
- explicit
- Error(const std::string& what)
- : Face::Error(what)
- {
- }
- };
-
- InternalFace();
-
- CommandValidator&
- getValidator();
-
- virtual
- ~InternalFace();
-
- // Overridden Face methods for forwarder
-
- virtual void
- sendInterest(const Interest& interest);
-
- virtual void
- sendData(const Data& data);
-
- virtual void
- close();
-
- // Methods implementing AppFace interface. Do not invoke from forwarder.
-
- virtual void
- setInterestFilter(const Name& filter,
- OnInterest onInterest);
-
- virtual void
- put(const Data& data);
-
-private:
- void
- processInterest(const shared_ptr<const Interest>& interest);
-
-private:
- std::map<Name, OnInterest> m_interestFilters;
- CommandValidator m_validator;
-};
-
-inline CommandValidator&
-InternalFace::getValidator()
-{
- return m_validator;
-}
-
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_INTERNAL_FACE_HPP
diff --git a/daemon/mgmt/manager-base.cpp b/daemon/mgmt/manager-base.cpp
index cf75d04..418c3d6 100644
--- a/daemon/mgmt/manager-base.cpp
+++ b/daemon/mgmt/manager-base.cpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -24,120 +24,96 @@
*/
#include "manager-base.hpp"
-#include "core/logger.hpp"
namespace nfd {
-NFD_LOG_INIT("ManagerBase");
+using ndn::mgmt::ValidateParameters;
+using ndn::mgmt::Authorization;
-ManagerBase::ManagerBase(shared_ptr<InternalFace> face, const std::string& privilege,
- ndn::KeyChain& keyChain)
- : m_face(face)
- , m_keyChain(keyChain)
+ManagerBase::ManagerBase(Dispatcher& dispatcher,
+ CommandValidator& validator,
+ const std::string& module)
+ : m_dispatcher(dispatcher)
+ , m_validator(validator)
+ , m_mgmtModuleName(module)
{
- face->getValidator().addSupportedPrivilege(privilege);
+ m_validator.addSupportedPrivilege(module);
}
-ManagerBase::~ManagerBase()
+void
+ManagerBase::registerStatusDatasetHandler(const std::string& verb,
+ const ndn::mgmt::StatusDatasetHandler& handler)
{
+ m_dispatcher.addStatusDataset(makeRelPrefix(verb),
+ ndn::mgmt::makeAcceptAllAuthorization(),
+ handler);
+}
+ndn::mgmt::PostNotification
+ManagerBase::registerNotificationStream(const std::string& verb)
+{
+ return m_dispatcher.addNotificationStream(makeRelPrefix(verb));
+}
+
+void
+ManagerBase::authorize(const Name& prefix, const Interest& interest,
+ const ndn::mgmt::ControlParameters* params,
+ ndn::mgmt::AcceptContinuation accept,
+ ndn::mgmt::RejectContinuation reject)
+{
+ BOOST_ASSERT(params != nullptr);
+ BOOST_ASSERT(typeid(*params) == typeid(ndn::nfd::ControlParameters));
+
+ m_validator.validate(interest,
+ bind(&ManagerBase::extractRequester, this, interest, accept),
+ bind([&] { reject(ndn::mgmt::RejectReply::STATUS403); }));
+}
+
+void
+ManagerBase::extractRequester(const Interest& interest,
+ ndn::mgmt::AcceptContinuation accept)
+{
+ const Name& interestName = interest.getName();
+
+ try {
+ ndn::SignatureInfo sigInfo(interestName.at(ndn::signed_interest::POS_SIG_INFO).blockFromValue());
+ if (!sigInfo.hasKeyLocator() ||
+ sigInfo.getKeyLocator().getType() != ndn::KeyLocator::KeyLocator_Name) {
+ return accept("");
+ }
+
+ accept(sigInfo.getKeyLocator().getName().toUri());
+ }
+ catch (const tlv::Error&) {
+ accept("");
+ }
}
bool
-ManagerBase::extractParameters(const Name::Component& parameterComponent,
- ControlParameters& extractedParameters)
+ManagerBase::validateParameters(const nfd::ControlCommand& command, const ndn::mgmt::ControlParameters& parameters)
{
- try
- {
- Block rawParameters = parameterComponent.blockFromValue();
- extractedParameters.wireDecode(rawParameters);
- }
- catch (const tlv::Error&)
- {
- return false;
- }
+ BOOST_ASSERT(dynamic_cast<const ControlParameters*>(¶meters) != nullptr);
- NFD_LOG_DEBUG("Parameters parsed OK");
+ try {
+ command.validateRequest(static_cast<const ControlParameters&>(parameters));
+ }
+ catch (const ControlCommand::ArgumentError&) {
+ return false;
+ }
return true;
}
void
-ManagerBase::sendResponse(const Name& name,
- uint32_t code,
- const std::string& text)
+ManagerBase::handleCommand(shared_ptr<nfd::ControlCommand> command,
+ const ControlCommandHandler& handler,
+ const Name& prefix, const Interest& interest,
+ const ndn::mgmt::ControlParameters& params,
+ ndn::mgmt::CommandContinuation done)
{
- ControlResponse response(code, text);
- sendResponse(name, response);
-}
-
-void
-ManagerBase::sendResponse(const Name& name,
- uint32_t code,
- const std::string& text,
- const Block& body)
-{
- ControlResponse response(code, text);
- response.setBody(body);
- sendResponse(name, response);
-}
-
-void
-ManagerBase::sendResponse(const Name& name,
- const ControlResponse& response)
-{
- NFD_LOG_DEBUG("responding"
- << " name: " << name
- << " code: " << response.getCode()
- << " text: " << response.getText());
-
- const Block& encodedControl = response.wireEncode();
-
- shared_ptr<Data> responseData(make_shared<Data>(name));
- responseData->setContent(encodedControl);
-
- m_keyChain.sign(*responseData);
- m_face->put(*responseData);
-}
-
-void
-ManagerBase::sendNack(const Name& name)
-{
- NFD_LOG_DEBUG("responding NACK to " << name);
-
- ndn::MetaInfo meta;
- meta.setType(tlv::ContentType_Nack);
-
- shared_ptr<Data> responseData(make_shared<Data>(name));
- responseData->setMetaInfo(meta);
-
- m_keyChain.sign(*responseData);
- m_face->put(*responseData);
-}
-
-bool
-ManagerBase::validateParameters(const ControlCommand& command,
- ControlParameters& parameters)
-{
- try
- {
- command.validateRequest(parameters);
- }
- catch (const ControlCommand::ArgumentError& error)
- {
- return false;
- }
-
- command.applyDefaultsToRequest(parameters);
-
- return true;
-}
-
-void
-ManagerBase::onCommandValidationFailed(const shared_ptr<const Interest>& command,
- const std::string& error)
-{
- NFD_LOG_DEBUG("command result: unauthorized command: " << *command << " (" << error << ")");
- sendResponse(command->getName(), 403, "Unauthorized command");
+ BOOST_ASSERT(dynamic_cast<const ControlParameters*>(¶ms) != nullptr);
+ ControlParameters parameters = static_cast<const ControlParameters&>(params);
+ command->applyDefaultsToRequest(parameters);
+ handler(*command, prefix, interest, parameters, done);
}
diff --git a/daemon/mgmt/manager-base.hpp b/daemon/mgmt/manager-base.hpp
index 1611615..988fff1 100644
--- a/daemon/mgmt/manager-base.hpp
+++ b/daemon/mgmt/manager-base.hpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -27,143 +27,154 @@
#define NFD_DAEMON_MGMT_MANAGER_BASE_HPP
#include "common.hpp"
-
#include "mgmt/command-validator.hpp"
-#include "mgmt/internal-face.hpp"
+#include <ndn-cxx/mgmt/dispatcher.hpp>
#include <ndn-cxx/management/nfd-control-command.hpp>
#include <ndn-cxx/management/nfd-control-response.hpp>
#include <ndn-cxx/management/nfd-control-parameters.hpp>
namespace nfd {
+using ndn::mgmt::Dispatcher;
+
using ndn::nfd::ControlCommand;
using ndn::nfd::ControlResponse;
using ndn::nfd::ControlParameters;
-class InternalFace;
-
-class ManagerBase
+/**
+ * @brief a collection of common functions shared by all NFD managers,
+ * such as communicating with the dispatcher and command validator.
+ */
+class ManagerBase : public noncopyable
{
public:
-
- struct Error : public std::runtime_error
+ class Error : public std::runtime_error
{
- Error(const std::string& what) : std::runtime_error(what) {}
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
};
- ManagerBase(shared_ptr<InternalFace> face,
- const std::string& privilege,
- ndn::KeyChain& keyChain);
+public:
+ ManagerBase(Dispatcher& dispatcher,
+ CommandValidator& validator,
+ const std::string& module);
- virtual
- ~ManagerBase();
+PUBLIC_WITH_TESTS_ELSE_PROTECTED: // registrations to the dispatcher
+
+ // difference from mgmt::ControlCommand: accepts nfd::ControlParameters
+ typedef function<void(const ControlCommand& command,
+ const Name& prefix, const Interest& interest,
+ const ControlParameters& parameters,
+ const ndn::mgmt::CommandContinuation done)> ControlCommandHandler;
+
+ template<typename Command>
+ void
+ registerCommandHandler(const std::string& verb,
+ const ControlCommandHandler& handler);
void
- onCommandValidationFailed(const shared_ptr<const Interest>& command,
- const std::string& error);
+ registerStatusDatasetHandler(const std::string& verb,
+ const ndn::mgmt::StatusDatasetHandler& handler);
-protected:
+ ndn::mgmt::PostNotification
+ registerNotificationStream(const std::string& verb);
+PUBLIC_WITH_TESTS_ELSE_PRIVATE: // command validation
+ /**
+ * @brief validate a request for ControlCommand.
+ *
+ * This is called by the dispatcher.
+ *
+ * @pre params != null
+ * @pre typeid(*params) == typeid(ndn::nfd::ControlParameters)
+ *
+ * @param prefix the top prefix
+ * @param interest a request for ControlCommand
+ * @param params the parameters for ControlCommand
+ * @param accept callback of successful validation, take the requester string as a argument
+ * @param reject callback of failure in validation, take the action code as a argument
+ */
+ void
+ authorize(const Name& prefix, const Interest& interest,
+ const ndn::mgmt::ControlParameters* params,
+ ndn::mgmt::AcceptContinuation accept,
+ ndn::mgmt::RejectContinuation reject);
+
+ /**
+ * @brief extract a requester from a ControlCommand request
+ *
+ * This is called after the signature is validated.
+ *
+ * @param interest a request for ControlCommand
+ * @param accept callback of successful validation, take the requester string as a argument
+ */
+ void
+ extractRequester(const Interest& interest,
+ ndn::mgmt::AcceptContinuation accept);
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE: // helpers
+ /**
+ * @brief validate the @p parameters for a given @p command
+ *
+ * @param parameters the original ControlParameters
+ *
+ * @return whether the original ControlParameters can be validated
+ */
static bool
- extractParameters(const Name::Component& parameterComponent,
- ControlParameters& extractedParameters);
+ validateParameters(const nfd::ControlCommand& command,
+ const ndn::mgmt::ControlParameters& parameters);
- void
- setResponse(ControlResponse& response,
- uint32_t code,
- const std::string& text);
- void
- setResponse(ControlResponse& response,
- uint32_t code,
- const std::string& text,
- const Block& body);
+ /** @brief Handle control command
+ */
+ static void
+ handleCommand(shared_ptr<nfd::ControlCommand> command,
+ const ControlCommandHandler& handler,
+ const Name& prefix, const Interest& interest,
+ const ndn::mgmt::ControlParameters& params,
+ ndn::mgmt::CommandContinuation done);
- void
- sendResponse(const Name& name,
- const ControlResponse& response);
+ /**
+ * @brief generate the relative prefix for a handler,
+ * by appending the verb name to the module name.
+ *
+ * @param verb the verb name
+ *
+ * @return the generated relative prefix
+ */
+ PartialName
+ makeRelPrefix(const std::string& verb);
- void
- sendResponse(const Name& name,
- uint32_t code,
- const std::string& text);
-
- void
- sendResponse(const Name& name,
- uint32_t code,
- const std::string& text,
- const Block& body);
-
- void
- sendNack(const Name& name);
-
- virtual bool
- validateParameters(const ControlCommand& command,
- ControlParameters& parameters);
-
-PUBLIC_WITH_TESTS_ELSE_PROTECTED:
- void
- addInterestRule(const std::string& regex,
- const ndn::IdentityCertificate& certificate);
-
- void
- addInterestRule(const std::string& regex,
- const Name& keyName,
- const ndn::PublicKey& publicKey);
-
- void
- validate(const Interest& interest,
- const ndn::OnInterestValidated& onValidated,
- const ndn::OnInterestValidationFailed& onValidationFailed);
-
-protected:
- shared_ptr<InternalFace> m_face;
- ndn::KeyChain& m_keyChain;
+private:
+ Dispatcher& m_dispatcher;
+ CommandValidator& m_validator;
+ std::string m_mgmtModuleName;
};
-inline void
-ManagerBase::setResponse(ControlResponse& response,
- uint32_t code,
- const std::string& text)
+inline PartialName
+ManagerBase::makeRelPrefix(const std::string& verb)
{
- response.setCode(code);
- response.setText(text);
+ return PartialName(m_mgmtModuleName).append(verb);
}
+template<typename Command>
inline void
-ManagerBase::setResponse(ControlResponse& response,
- uint32_t code,
- const std::string& text,
- const Block& body)
+ManagerBase::registerCommandHandler(const std::string& verb,
+ const ControlCommandHandler& handler)
{
- setResponse(response, code, text);
- response.setBody(body);
-}
+ auto command = make_shared<Command>();
-inline void
-ManagerBase::addInterestRule(const std::string& regex,
- const ndn::IdentityCertificate& certificate)
-{
- m_face->getValidator().addInterestRule(regex, certificate);
+ m_dispatcher.addControlCommand<ControlParameters>(
+ makeRelPrefix(verb),
+ bind(&ManagerBase::authorize, this, _1, _2, _3, _4, _5),
+ bind(&ManagerBase::validateParameters, cref(*command), _1),
+ bind(&ManagerBase::handleCommand, command, handler, _1, _2, _3, _4));
}
-inline void
-ManagerBase::addInterestRule(const std::string& regex,
- const Name& keyName,
- const ndn::PublicKey& publicKey)
-{
- m_face->getValidator().addInterestRule(regex, keyName, publicKey);
-}
-
-inline void
-ManagerBase::validate(const Interest& interest,
- const ndn::OnInterestValidated& onValidated,
- const ndn::OnInterestValidationFailed& onValidationFailed)
-{
- m_face->getValidator().validate(interest, onValidated, onValidationFailed);
-}
-
-
} // namespace nfd
#endif // NFD_DAEMON_MGMT_MANAGER_BASE_HPP
diff --git a/daemon/mgmt/status-server.cpp b/daemon/mgmt/status-server.cpp
deleted file mode 100644
index c8ce5b4..0000000
--- a/daemon/mgmt/status-server.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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 "status-server.hpp"
-#include "fw/forwarder.hpp"
-#include "version.hpp"
-
-namespace nfd {
-
-const Name StatusServer::DATASET_PREFIX = "ndn:/localhost/nfd/status";
-const time::milliseconds StatusServer::RESPONSE_FRESHNESS = time::milliseconds(5000);
-
-StatusServer::StatusServer(shared_ptr<AppFace> face, Forwarder& forwarder, ndn::KeyChain& keyChain)
- : m_face(face)
- , m_forwarder(forwarder)
- , m_startTimestamp(time::system_clock::now())
- , m_keyChain(keyChain)
-{
- m_face->setInterestFilter(DATASET_PREFIX, bind(&StatusServer::onInterest, this, _2));
-}
-
-void
-StatusServer::onInterest(const Interest& interest) const
-{
- Name name(DATASET_PREFIX);
- name.appendVersion();
- name.appendSegment(0);
-
- shared_ptr<Data> data = make_shared<Data>(name);
- data->setFreshnessPeriod(RESPONSE_FRESHNESS);
-
- shared_ptr<ndn::nfd::ForwarderStatus> status = this->collectStatus();
- data->setContent(status->wireEncode());
-
- m_keyChain.sign(*data);
- m_face->put(*data);
-}
-
-shared_ptr<ndn::nfd::ForwarderStatus>
-StatusServer::collectStatus() const
-{
- shared_ptr<ndn::nfd::ForwarderStatus> status = make_shared<ndn::nfd::ForwarderStatus>();
-
- status->setNfdVersion(NFD_VERSION_BUILD_STRING);
- status->setStartTimestamp(m_startTimestamp);
- status->setCurrentTimestamp(time::system_clock::now());
-
- status->setNNameTreeEntries(m_forwarder.getNameTree().size());
- status->setNFibEntries(m_forwarder.getFib().size());
- status->setNPitEntries(m_forwarder.getPit().size());
- status->setNMeasurementsEntries(m_forwarder.getMeasurements().size());
- status->setNCsEntries(m_forwarder.getCs().size());
-
- m_forwarder.getCounters().copyTo(*status);
-
- return status;
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/status-server.hpp b/daemon/mgmt/status-server.hpp
deleted file mode 100644
index 16dbf8e..0000000
--- a/daemon/mgmt/status-server.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_DAEMON_MGMT_STATUS_SERVER_HPP
-#define NFD_DAEMON_MGMT_STATUS_SERVER_HPP
-
-#include "mgmt/app-face.hpp"
-#include <ndn-cxx/management/nfd-forwarder-status.hpp>
-
-namespace nfd {
-
-class Forwarder;
-
-class StatusServer : noncopyable
-{
-public:
- StatusServer(shared_ptr<AppFace> face, Forwarder& forwarder, ndn::KeyChain& keyChain);
-
-private:
- void
- onInterest(const Interest& interest) const;
-
- shared_ptr<ndn::nfd::ForwarderStatus>
- collectStatus() const;
-
-private:
- static const Name DATASET_PREFIX;
- static const time::milliseconds RESPONSE_FRESHNESS;
-
- shared_ptr<AppFace> m_face;
- Forwarder& m_forwarder;
- time::system_clock::TimePoint m_startTimestamp;
- ndn::KeyChain& m_keyChain;
-};
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_STATUS_SERVER_HPP
diff --git a/daemon/mgmt/strategy-choice-manager.cpp b/daemon/mgmt/strategy-choice-manager.cpp
index 4f2728c..fba7f4c 100644
--- a/daemon/mgmt/strategy-choice-manager.cpp
+++ b/daemon/mgmt/strategy-choice-manager.cpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -25,190 +25,75 @@
#include "strategy-choice-manager.hpp"
#include "table/strategy-choice.hpp"
-#include "core/logger.hpp"
-#include "mgmt/app-face.hpp"
+#include <ndn-cxx/management/nfd-strategy-choice.hpp>
namespace nfd {
NFD_LOG_INIT("StrategyChoiceManager");
-const Name StrategyChoiceManager::COMMAND_PREFIX = "/localhost/nfd/strategy-choice";
-
-const size_t StrategyChoiceManager::COMMAND_UNSIGNED_NCOMPS =
- StrategyChoiceManager::COMMAND_PREFIX.size() +
- 1 + // verb
- 1; // verb parameters
-
-const size_t StrategyChoiceManager::COMMAND_SIGNED_NCOMPS =
- StrategyChoiceManager::COMMAND_UNSIGNED_NCOMPS +
- 4; // (timestamp, nonce, signed info tlv, signature tlv)
-
-const Name StrategyChoiceManager::LIST_DATASET_PREFIX("/localhost/nfd/strategy-choice/list");
-
StrategyChoiceManager::StrategyChoiceManager(StrategyChoice& strategyChoice,
- shared_ptr<InternalFace> face,
- ndn::KeyChain& keyChain)
- : ManagerBase(face, STRATEGY_CHOICE_PRIVILEGE, keyChain)
+ Dispatcher& dispatcher,
+ CommandValidator& validator)
+ : ManagerBase(dispatcher, validator, "strategy-choice")
, m_strategyChoice(strategyChoice)
- , m_listPublisher(strategyChoice, *m_face, LIST_DATASET_PREFIX, keyChain)
{
- face->setInterestFilter("/localhost/nfd/strategy-choice",
- bind(&StrategyChoiceManager::onStrategyChoiceRequest, this, _2));
-}
+ registerCommandHandler<ndn::nfd::StrategyChoiceSetCommand>("set",
+ bind(&StrategyChoiceManager::setStrategy, this, _2, _3, _4, _5));
+ registerCommandHandler<ndn::nfd::StrategyChoiceUnsetCommand>("unset",
+ bind(&StrategyChoiceManager::unsetStrategy, this, _2, _3, _4, _5));
-StrategyChoiceManager::~StrategyChoiceManager()
-{
-
+ registerStatusDatasetHandler("list",
+ bind(&StrategyChoiceManager::listChoices, this, _1, _2, _3));
}
void
-StrategyChoiceManager::onStrategyChoiceRequest(const Interest& request)
+StrategyChoiceManager::setStrategy(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done)
{
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
-
- if (command == LIST_DATASET_PREFIX)
- {
- listStrategies(request);
- return;
- }
- else if (commandNComps <= COMMAND_PREFIX.size())
- {
- // command is too short to have a verb
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
- commandNComps < COMMAND_SIGNED_NCOMPS)
- {
- NFD_LOG_DEBUG("command result: unsigned verb: " << command);
- sendResponse(command, 401, "Signature required");
-
- return;
- }
- else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
- !COMMAND_PREFIX.isPrefixOf(command))
- {
- NFD_LOG_DEBUG("command result: malformed");
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- validate(request,
- bind(&StrategyChoiceManager::onValidatedStrategyChoiceRequest, this, _1),
- bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
-}
-
-void
-StrategyChoiceManager::listStrategies(const Interest& request)
-{
- m_listPublisher.publish();
-}
-
-void
-StrategyChoiceManager::onValidatedStrategyChoiceRequest(const shared_ptr<const Interest>& request)
-{
- static const Name::Component VERB_SET("set");
- static const Name::Component VERB_UNSET("unset");
-
- const Name& command = request->getName();
- const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
-
- ControlParameters parameters;
- if (!extractParameters(parameterComponent, parameters))
- {
- sendResponse(command, 400, "Malformed command");
- return;
- }
-
- const Name::Component& verb = command.at(COMMAND_PREFIX.size());
- ControlResponse response;
- if (verb == VERB_SET)
- {
- setStrategy(parameters, response);
- }
- else if (verb == VERB_UNSET)
- {
- unsetStrategy(parameters, response);
- }
- else
- {
- NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
- setResponse(response, 501, "Unsupported command");
- }
-
- sendResponse(command, response);
-}
-
-void
-StrategyChoiceManager::setStrategy(ControlParameters& parameters,
- ControlResponse& response)
-{
- ndn::nfd::StrategyChoiceSetCommand command;
-
- if (!validateParameters(command, parameters))
- {
- NFD_LOG_DEBUG("strategy-choice result: FAIL reason: malformed");
- setResponse(response, 400, "Malformed command");
- return;
- }
-
const Name& prefix = parameters.getName();
const Name& selectedStrategy = parameters.getStrategy();
- if (!m_strategyChoice.hasStrategy(selectedStrategy))
- {
- NFD_LOG_DEBUG("strategy-choice result: FAIL reason: unknown-strategy: "
- << parameters.getStrategy());
- setResponse(response, 504, "Unsupported strategy");
- return;
- }
+ if (!m_strategyChoice.hasStrategy(selectedStrategy)) {
+ NFD_LOG_DEBUG("strategy-choice result: FAIL reason: unknown-strategy: "
+ << parameters.getStrategy());
+ return done(ControlResponse(504, "Unsupported strategy"));
+ }
- if (m_strategyChoice.insert(prefix, selectedStrategy))
- {
- NFD_LOG_DEBUG("strategy-choice result: SUCCESS");
- auto currentStrategyChoice = m_strategyChoice.get(prefix);
- BOOST_ASSERT(currentStrategyChoice.first);
- parameters.setStrategy(currentStrategyChoice.second);
- setResponse(response, 200, "Success", parameters.wireEncode());
- }
- else
- {
- NFD_LOG_DEBUG("strategy-choice result: FAIL reason: not-installed");
- setResponse(response, 405, "Strategy not installed");
- }
+ if (m_strategyChoice.insert(prefix, selectedStrategy)) {
+ NFD_LOG_DEBUG("strategy-choice result: SUCCESS");
+ auto currentStrategyChoice = m_strategyChoice.get(prefix);
+ BOOST_ASSERT(currentStrategyChoice.first);
+ parameters.setStrategy(currentStrategyChoice.second);
+ return done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
+ }
+ else {
+ NFD_LOG_DEBUG("strategy-choice result: FAIL reason: not-installed");
+ return done(ControlResponse(405, "Strategy not installed"));
+ }
}
void
-StrategyChoiceManager::unsetStrategy(ControlParameters& parameters,
- ControlResponse& response)
+StrategyChoiceManager::unsetStrategy(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done)
{
- ndn::nfd::StrategyChoiceUnsetCommand command;
-
- if (!validateParameters(command, parameters))
- {
- static const Name ROOT_PREFIX;
- if (parameters.hasName() && parameters.getName() == ROOT_PREFIX)
- {
- NFD_LOG_DEBUG("strategy-choice result: FAIL reason: unset-root");
- setResponse(response, 403, "Cannot unset root prefix strategy");
- }
- else
- {
- NFD_LOG_DEBUG("strategy-choice result: FAIL reason: malformed");
- setResponse(response, 400, "Malformed command");
- }
- return;
- }
-
m_strategyChoice.erase(parameters.getName());
NFD_LOG_DEBUG("strategy-choice result: SUCCESS");
- setResponse(response, 200, "Success", parameters.wireEncode());
+ done(ControlResponse(200, "OK").setBody(parameters.wireEncode()));
}
+void
+StrategyChoiceManager::listChoices(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context)
+{
+ for (auto&& i : m_strategyChoice) {
+ ndn::nfd::StrategyChoice entry;
+ entry.setName(i.getPrefix()).setStrategy(i.getStrategyName());
+ context.append(entry.wireEncode());
+ }
+ context.end();
+}
-
-} // namespace nfd
+} // namespace
diff --git a/daemon/mgmt/strategy-choice-manager.hpp b/daemon/mgmt/strategy-choice-manager.hpp
index c2ccd53..74c54db 100644
--- a/daemon/mgmt/strategy-choice-manager.hpp
+++ b/daemon/mgmt/strategy-choice-manager.hpp
@@ -1,12 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014, 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
+ * Copyright (c) 2014-2015, 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.
@@ -26,64 +26,40 @@
#ifndef NFD_DAEMON_MGMT_STRATEGY_CHOICE_MANAGER_HPP
#define NFD_DAEMON_MGMT_STRATEGY_CHOICE_MANAGER_HPP
-#include "mgmt/manager-base.hpp"
-#include "mgmt/strategy-choice-publisher.hpp"
-
-#include <ndn-cxx/management/nfd-control-parameters.hpp>
+#include "manager-base.hpp"
namespace nfd {
-const std::string STRATEGY_CHOICE_PRIVILEGE = "strategy-choice";
-
class StrategyChoice;
+/**
+ * @brief implement the Strategy Choice Management of NFD Management Protocol.
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice
+ */
class StrategyChoiceManager : public ManagerBase
{
public:
StrategyChoiceManager(StrategyChoice& strategyChoice,
- shared_ptr<InternalFace> face,
- ndn::KeyChain& keyChain);
-
- virtual
- ~StrategyChoiceManager();
-
- void
- onStrategyChoiceRequest(const Interest& request);
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-
- void
- listStrategies(const Interest& request);
-
- void
- onValidatedStrategyChoiceRequest(const shared_ptr<const Interest>& request);
-
- void
- setStrategy(ControlParameters& parameters,
- ControlResponse& response);
-
- void
- unsetStrategy(ControlParameters& parameters,
- ControlResponse& response);
+ Dispatcher& dispatcher,
+ CommandValidator& validator);
private:
+ void
+ setStrategy(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done);
+ void
+ unsetStrategy(const Name& topPrefix, const Interest& interest,
+ ControlParameters parameters,
+ const ndn::mgmt::CommandContinuation& done);
+
+ void
+ listChoices(const Name& topPrefix, const Interest& interest,
+ ndn::mgmt::StatusDatasetContext& context);
+
+private:
StrategyChoice& m_strategyChoice;
-
- StrategyChoicePublisher m_listPublisher;
-
- static const Name COMMAND_PREFIX; // /localhost/nfd/strategy-choice
-
- // number of components in an invalid, but not malformed, unsigned command.
- // (/localhost/nfd/strategy-choice + verb + parameters) = 5
- static const size_t COMMAND_UNSIGNED_NCOMPS;
-
- // number of components in a valid signed Interest.
- // (see UNSIGNED_NCOMPS), 9 with signed Interest support.
- static const size_t COMMAND_SIGNED_NCOMPS;
-
- static const Name LIST_DATASET_PREFIX; // /localhost/nfd/strategy-choice/list
-
};
} // namespace nfd
diff --git a/daemon/mgmt/strategy-choice-publisher.cpp b/daemon/mgmt/strategy-choice-publisher.cpp
deleted file mode 100644
index 8db7124..0000000
--- a/daemon/mgmt/strategy-choice-publisher.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014 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 "strategy-choice-publisher.hpp"
-#include "table/strategy-choice.hpp"
-
-#include <ndn-cxx/management/nfd-strategy-choice.hpp>
-
-namespace nfd {
-
-StrategyChoicePublisher::StrategyChoicePublisher(const StrategyChoice& strategyChoice,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain)
- : SegmentPublisher(face, prefix, keyChain)
- , m_strategyChoice(strategyChoice)
-{
-}
-
-StrategyChoicePublisher::~StrategyChoicePublisher()
-{
-}
-
-size_t
-StrategyChoicePublisher::generate(ndn::EncodingBuffer& outBuffer)
-{
- size_t totalLength = 0;
-
- for (StrategyChoice::const_iterator i = m_strategyChoice.begin();
- i != m_strategyChoice.end();
- ++i)
- {
- ndn::nfd::StrategyChoice entry;
-
- entry.setName(i->getPrefix())
- .setStrategy(i->getStrategyName());
-
- totalLength += entry.wireEncode(outBuffer);
- }
-
- return totalLength;
-}
-
-} // namespace nfd
diff --git a/daemon/mgmt/strategy-choice-publisher.hpp b/daemon/mgmt/strategy-choice-publisher.hpp
deleted file mode 100644
index 8322b63..0000000
--- a/daemon/mgmt/strategy-choice-publisher.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014 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/>.
- **/
-
-#ifndef NFD_DAEMON_MGMT_STRATEGY_CHOICE_PUBLISHER_HPP
-#define NFD_DAEMON_MGMT_STRATEGY_CHOICE_PUBLISHER_HPP
-
-#include "core/segment-publisher.hpp"
-#include "mgmt/app-face.hpp"
-
-namespace nfd {
-
-class StrategyChoice;
-
-class StrategyChoicePublisher : public SegmentPublisher<AppFace>
-{
-public:
- StrategyChoicePublisher(const StrategyChoice& strategyChoice,
- AppFace& face,
- const Name& prefix,
- ndn::KeyChain& keyChain);
-
- virtual
- ~StrategyChoicePublisher();
-
-protected:
-
- virtual size_t
- generate(ndn::EncodingBuffer& outBuffer);
-
-private:
-
- const StrategyChoice& m_strategyChoice;
-
-};
-
-} // namespace nfd
-
-#endif // NFD_DAEMON_MGMT_STRATEGY_CHOICE_PUBLISHER_HPP
diff --git a/daemon/nfd.cpp b/daemon/nfd.cpp
index 262bbf5..7d68de3 100644
--- a/daemon/nfd.cpp
+++ b/daemon/nfd.cpp
@@ -31,13 +31,17 @@
#include "core/config-file.hpp"
#include "fw/forwarder.hpp"
#include "face/null-face.hpp"
-#include "mgmt/internal-face.hpp"
+#include "face/internal-face.hpp"
+#include "face/internal-client-face.hpp"
#include "mgmt/fib-manager.hpp"
#include "mgmt/face-manager.hpp"
#include "mgmt/strategy-choice-manager.hpp"
-#include "mgmt/status-server.hpp"
+#include "mgmt/forwarder-status-manager.hpp"
#include "mgmt/general-config-section.hpp"
#include "mgmt/tables-config-section.hpp"
+#include "mgmt/command-validator.hpp"
+
+#include <ndn-cxx/mgmt/dispatcher.hpp>
namespace nfd {
@@ -128,17 +132,26 @@
Nfd::initializeManagement()
{
m_internalFace = make_shared<InternalFace>();
+ m_forwarder->getFaceTable().addReserved(m_internalFace, FACEID_INTERNAL_FACE);
+ m_internalClientFace = makeInternalClientFace(m_internalFace, m_keyChain);
+ m_dispatcher.reset(new ndn::mgmt::Dispatcher(*m_internalClientFace, m_keyChain));
+
+ m_validator.reset(new CommandValidator());
m_fibManager.reset(new FibManager(m_forwarder->getFib(),
bind(&Forwarder::getFace, m_forwarder.get(), _1),
- m_internalFace, m_keyChain));
+ *m_dispatcher,
+ *m_validator));
- m_faceManager.reset(new FaceManager(m_forwarder->getFaceTable(), m_internalFace, m_keyChain));
+ m_faceManager.reset(new FaceManager(m_forwarder->getFaceTable(),
+ *m_dispatcher,
+ *m_validator));
m_strategyChoiceManager.reset(new StrategyChoiceManager(m_forwarder->getStrategyChoice(),
- m_internalFace, m_keyChain));
+ *m_dispatcher,
+ *m_validator));
- m_statusServer.reset(new StatusServer(m_internalFace, *m_forwarder, m_keyChain));
+ m_forwarderStatusManager.reset(new ForwarderStatusManager(*m_forwarder, *m_dispatcher));
ConfigFile config(&ignoreRibAndLogSections);
general::setConfigFile(config);
@@ -151,9 +164,7 @@
m_forwarder->getNetworkRegionTable());
tablesConfig.setConfigFile(config);
- m_internalFace->getValidator().setConfigFile(config);
-
- m_forwarder->getFaceTable().addReserved(m_internalFace, FACEID_INTERNAL_FACE);
+ m_validator->setConfigFile(config);
m_faceManager->setConfigFile(config);
@@ -170,8 +181,10 @@
tablesConfig.ensureTablesAreConfigured();
// add FIB entry for NFD Management Protocol
- shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
+ Name topPrefix("/localhost/nfd");
+ auto entry = m_forwarder->getFib().insert(topPrefix).first;
entry->addNextHop(m_internalFace, 0);
+ m_dispatcher->addTopPrefix(topPrefix, false);
}
void
@@ -195,7 +208,7 @@
tablesConfig.setConfigFile(config);
- m_internalFace->getValidator().setConfigFile(config);
+ m_validator->setConfigFile(config);
m_faceManager->setConfigFile(config);
if (!m_configFile.empty()) {
diff --git a/daemon/nfd.hpp b/daemon/nfd.hpp
index 4710554..34111b3 100644
--- a/daemon/nfd.hpp
+++ b/daemon/nfd.hpp
@@ -33,6 +33,14 @@
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/util/network-monitor.hpp>
+namespace ndn {
+namespace mgmt {
+
+class Dispatcher;
+
+}
+}
+
namespace nfd {
class Forwarder;
@@ -40,7 +48,9 @@
class FibManager;
class FaceManager;
class StrategyChoiceManager;
-class StatusServer;
+class ForwarderStatusManager;
+class InternalClientFace;
+class CommandValidator;
/**
* \brief Class representing NFD instance
@@ -97,16 +107,19 @@
unique_ptr<Forwarder> m_forwarder;
- shared_ptr<InternalFace> m_internalFace;
- unique_ptr<FibManager> m_fibManager;
- unique_ptr<FaceManager> m_faceManager;
- unique_ptr<StrategyChoiceManager> m_strategyChoiceManager;
- unique_ptr<StatusServer> m_statusServer;
+ ndn::KeyChain& m_keyChain;
+ shared_ptr<InternalFace> m_internalFace;
+ shared_ptr<InternalClientFace> m_internalClientFace;
+ unique_ptr<CommandValidator> m_validator;
- ndn::KeyChain& m_keyChain;
+ unique_ptr<ndn::mgmt::Dispatcher> m_dispatcher;
+ unique_ptr<FibManager> m_fibManager;
+ unique_ptr<FaceManager> m_faceManager;
+ unique_ptr<StrategyChoiceManager> m_strategyChoiceManager;
+ unique_ptr<ForwarderStatusManager> m_forwarderStatusManager;
- ndn::util::NetworkMonitor m_networkMonitor;
- scheduler::ScopedEventId m_reloadConfigEvent;
+ ndn::util::NetworkMonitor m_networkMonitor;
+ scheduler::ScopedEventId m_reloadConfigEvent;
};
} // namespace nfd
diff --git a/tests/daemon/face/internal-client-face.t.cpp b/tests/daemon/face/internal-client-face.t.cpp
new file mode 100644
index 0000000..0b2295c
--- /dev/null
+++ b/tests/daemon/face/internal-client-face.t.cpp
@@ -0,0 +1,134 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "face/internal-client-face.hpp"
+#include "face/internal-face.hpp"
+#include "tests/test-common.hpp"
+#include "tests/identity-management-fixture.hpp"
+
+namespace nfd {
+namespace tests {
+
+class InternalClientFaceFixture : public UnitTestTimeFixture
+ , public IdentityManagementFixture
+{
+public:
+ InternalClientFaceFixture()
+ : m_internalFace(make_shared<InternalFace>())
+ , m_face(makeInternalClientFace(m_internalFace, m_keyChain))
+ {
+ }
+
+protected:
+ shared_ptr<InternalFace> m_internalFace;
+ shared_ptr<InternalClientFace> m_face;
+};
+
+BOOST_FIXTURE_TEST_SUITE(FaceInternalClientFace, InternalClientFaceFixture)
+
+BOOST_AUTO_TEST_CASE(ExpressInterest)
+{
+ bool didReceiveDataBack = false;
+ bool didTimeoutCallbackFire = false;
+ Data receivedData;
+
+ auto expressInterest = [&] (shared_ptr<Interest> interest) {
+ didReceiveDataBack = false;
+ didTimeoutCallbackFire = false;
+ m_face->expressInterest(interest->setInterestLifetime(time::milliseconds(100)),
+ [&] (const Interest& interest, Data& data) {
+ didReceiveDataBack = true;
+ receivedData = data;
+ },
+ bind([&] { didTimeoutCallbackFire = true; }));
+ advanceClocks(time::milliseconds(1));
+ };
+
+ expressInterest(makeInterest("/test/timeout"));
+ advanceClocks(time::milliseconds(1), 200); // wait for time out
+ BOOST_CHECK(didTimeoutCallbackFire);
+
+ auto dataToSend = makeData("/test/data")->setContent(Block("\x81\x01\0x01", 3));
+ expressInterest(makeInterest("/test/data"));
+ m_internalFace->sendData(dataToSend); // send data to satisfy the expressed interest
+ advanceClocks(time::milliseconds(1));
+ BOOST_CHECK(didReceiveDataBack);
+ BOOST_CHECK(receivedData.wireEncode() == dataToSend.wireEncode());
+}
+
+BOOST_AUTO_TEST_CASE(InterestFilter)
+{
+ bool didOnInterestCallbackFire = false;
+ Block receivedBlock, expectedBlock;
+
+ auto testSendInterest = [&] (shared_ptr<Interest> interest) {
+ didOnInterestCallbackFire = false;
+ expectedBlock = interest->wireEncode();
+ m_internalFace->sendInterest(*interest);
+ };
+
+ testSendInterest(makeInterest("/test/filter")); // no filter is set now
+ BOOST_CHECK(!didOnInterestCallbackFire);
+
+ // set filter
+ auto filter = m_face->setInterestFilter("/test/filter",
+ bind([&](const Interest& interset) {
+ didOnInterestCallbackFire = true;
+ receivedBlock = interset.wireEncode();
+ }, _2));
+ advanceClocks(time::milliseconds(1));
+
+ testSendInterest(makeInterest("/test/filter"));
+ BOOST_CHECK(didOnInterestCallbackFire);
+ BOOST_CHECK(receivedBlock == expectedBlock);
+
+ // unset filter
+ didOnInterestCallbackFire = false;
+ m_face->unsetInterestFilter(filter);
+ advanceClocks(time::milliseconds(1));
+ testSendInterest(makeInterest("/test/filter"));
+ BOOST_CHECK(!didOnInterestCallbackFire);
+}
+
+BOOST_AUTO_TEST_CASE(PutData)
+{
+ bool didInternalFaceReceiveData = false;
+ Data receivedData;
+ m_internalFace->onReceiveData.connect([&] (const Data& data) {
+ didInternalFaceReceiveData = true;
+ receivedData = data;
+ });
+
+ auto dataToPut = makeData("/test/put/data");
+ m_face->put(*dataToPut);
+ advanceClocks(time::milliseconds(1));
+ BOOST_CHECK(didInternalFaceReceiveData);
+ BOOST_CHECK(receivedData.wireEncode() == dataToPut->wireEncode());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/daemon/face/internal-face.t.cpp b/tests/daemon/face/internal-face.t.cpp
new file mode 100644
index 0000000..44f5e7b
--- /dev/null
+++ b/tests/daemon/face/internal-face.t.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "face/internal-face.hpp"
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+class InternalFaceFixture : protected BaseFixture
+{
+public:
+ InternalFaceFixture()
+ {
+ m_face.onReceiveInterest.connect([this] (const Interest& interest) {
+ inInterests.push_back(interest);
+ });
+ m_face.onSendInterest.connect([this] (const Interest& interest) {
+ outInterests.push_back(interest);
+ });
+ m_face.onReceiveData.connect([this] (const Data& data) {
+ inData.push_back(data);
+ });
+ m_face.onSendData.connect([this] (const Data& data) {
+ outData.push_back(data);
+ });
+ }
+
+protected:
+ InternalFace m_face;
+ std::vector<Interest> inInterests;
+ std::vector<Interest> outInterests;
+ std::vector<Data> inData;
+ std::vector<Data> outData;
+};
+
+BOOST_FIXTURE_TEST_SUITE(FaceInternalFace, InternalFaceFixture)
+
+BOOST_AUTO_TEST_CASE(SendInterest)
+{
+ BOOST_CHECK(outInterests.empty());
+
+ auto interest = makeInterest("/test/send/interest");
+ Block expectedBlock = interest->wireEncode(); // assign a value to nonce
+ m_face.sendInterest(*interest);
+
+ BOOST_CHECK_EQUAL(outInterests.size(), 1);
+ BOOST_CHECK(outInterests[0].wireEncode() == expectedBlock);
+}
+
+BOOST_AUTO_TEST_CASE(SendData)
+{
+ BOOST_CHECK(outData.empty());
+
+ auto data = makeData("/test/send/data");
+ m_face.sendData(*data);
+
+ BOOST_CHECK_EQUAL(outData.size(), 1);
+ BOOST_CHECK(outData[0].wireEncode() == data->wireEncode());
+}
+
+BOOST_AUTO_TEST_CASE(ReceiveInterest)
+{
+ BOOST_CHECK(inInterests.empty());
+
+ auto interest = makeInterest("/test/receive/interest");
+ Block expectedBlock = interest->wireEncode(); // assign a value to nonce
+ m_face.receiveInterest(*interest);
+
+ BOOST_CHECK_EQUAL(inInterests.size(), 1);
+ BOOST_CHECK(inInterests[0].wireEncode() == expectedBlock);
+}
+
+BOOST_AUTO_TEST_CASE(ReceiveData)
+{
+ BOOST_CHECK(inData.empty());
+
+ auto data = makeData("/test/send/data");
+ m_face.receiveData(*data);
+
+ BOOST_CHECK_EQUAL(inData.size(), 1);
+ BOOST_CHECK(inData[0].wireEncode() == data->wireEncode());
+}
+
+BOOST_AUTO_TEST_CASE(ReceiveBlock)
+{
+ BOOST_CHECK(inInterests.empty());
+ BOOST_CHECK(inData.empty());
+
+ Block interestBlock = makeInterest("test/receive/interest")->wireEncode();
+ m_face.receive(interestBlock);
+ BOOST_CHECK_EQUAL(inInterests.size(), 1);
+ BOOST_CHECK(inInterests[0].wireEncode() == interestBlock);
+
+ Block dataBlock = makeData("test/receive/data")->wireEncode();
+ m_face.receive(dataBlock);
+ BOOST_CHECK_EQUAL(inData.size(), 1);
+ BOOST_CHECK(inData[0].wireEncode() == dataBlock);
+}
+
+BOOST_AUTO_TEST_CASE(ExtractPacketFromBlock)
+{
+ {
+ Block block = makeInterest("/test/interest")->wireEncode();
+ const Block& payload = ndn::nfd::LocalControlHeader::getPayload(block);
+ auto interest = m_face.extractPacketFromBlock<Interest>(block, payload);
+ BOOST_CHECK(interest->wireEncode() == block);
+ }
+
+ {
+ Block block = makeData("/test/data")->wireEncode();
+ const Block& payload = ndn::nfd::LocalControlHeader::getPayload(block);
+ auto data = m_face.extractPacketFromBlock<Data>(block, payload);
+ BOOST_CHECK(data->wireEncode() == block);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/daemon/mgmt/channel-status-common.hpp b/tests/daemon/mgmt/channel-status-common.hpp
deleted file mode 100644
index e04c0be..0000000
--- a/tests/daemon/mgmt/channel-status-common.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_TESTS_NFD_MGMT_CHANNEL_STATUS_COMMON_HPP
-#define NFD_TESTS_NFD_MGMT_CHANNEL_STATUS_COMMON_HPP
-
-#include "face/protocol-factory.hpp"
-#include "face/channel.hpp"
-
-#include "tests/test-common.hpp"
-
-#include <ndn-cxx/management/nfd-channel-status.hpp>
-
-
-
-namespace nfd {
-namespace tests {
-
-class DummyChannel : public Channel
-{
-public:
-
- DummyChannel(const std::string& uri)
- {
- setUri(FaceUri(uri));
- }
-
- virtual
- ~DummyChannel()
- {
- }
-};
-
-class DummyProtocolFactory : public ProtocolFactory
-{
-public:
-
- DummyProtocolFactory()
- {
-
- }
-
- virtual void
- createFace(const FaceUri& uri,
- ndn::nfd::FacePersistency persistency,
- const FaceCreatedCallback& onCreated,
- const FaceConnectFailedCallback& onConnectFailed)
- {
- }
-
- virtual void
- addChannel(const std::string& channelUri)
- {
- m_channels.push_back(make_shared<DummyChannel>(channelUri));
- }
-
- virtual std::list<shared_ptr<const Channel> >
- getChannels() const
- {
- return m_channels;
- }
-
- virtual size_t
- getNChannels() const
- {
- return m_channels.size();
- }
-
-private:
- std::list<shared_ptr<const Channel> > m_channels;
-};
-
-} // namespace tests
-} // namespace nfd
-
-#endif // NFD_TESTS_NFD_MGMT_CHANNEL_STATUS_COMMON_HPP
diff --git a/tests/daemon/mgmt/channel-status-publisher.t.cpp b/tests/daemon/mgmt/channel-status-publisher.t.cpp
deleted file mode 100644
index 6027137..0000000
--- a/tests/daemon/mgmt/channel-status-publisher.t.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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 "mgmt/channel-status-publisher.hpp"
-#include "mgmt/internal-face.hpp"
-
-#include "channel-status-common.hpp"
-
-namespace nfd {
-namespace tests {
-
-class ChannelStatusPublisherFixture : BaseFixture
-{
-public:
- ChannelStatusPublisherFixture()
- : m_face(make_shared<InternalFace>())
- , m_publisher(m_factories, *m_face, "/localhost/nfd/faces/channels", m_keyChain)
- , m_finished(false)
- {
- }
-
- virtual
- ~ChannelStatusPublisherFixture()
- {
- }
-
- // virtual shared_ptr<DummyProtocolFactory>
- // addProtocolFactory(const std::string& protocol)
- // {
- // shared_ptr<DummyProtocolFactory> factory(make_shared<DummyProtocolFactory>());
- // m_factories[protocol] = factory;
-
- // return factory;
- // }
-
- void
- validatePublish(const Data& data)
- {
- Block payload = data.getContent();
-
- m_buffer.appendByteArray(payload.value(), payload.value_size());
-
- BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
- if (data.getFinalBlockId() != data.getName()[-1])
- {
- return;
- }
-
- // wrap the Channel Status entries in a single Content TLV for easy parsing
- m_buffer.prependVarNumber(m_buffer.size());
- m_buffer.prependVarNumber(tlv::Content);
-
- ndn::Block parser(m_buffer.buf(), m_buffer.size());
- parser.parse();
-
- BOOST_REQUIRE_EQUAL(parser.elements_size(), m_expectedEntries.size());
-
- for (Block::element_const_iterator i = parser.elements_begin();
- i != parser.elements_end();
- ++i)
- {
- if (i->type() != ndn::tlv::nfd::ChannelStatus)
- {
- BOOST_FAIL("expected ChannelStatus, got type #" << i->type());
- }
-
- ndn::nfd::ChannelStatus entry(*i);
-
- std::map<std::string, ndn::nfd::ChannelStatus>::const_iterator expectedEntryPos =
- m_expectedEntries.find(entry.getLocalUri());
-
- BOOST_REQUIRE(expectedEntryPos != m_expectedEntries.end());
- const ndn::nfd::ChannelStatus& expectedEntry = expectedEntryPos->second;
-
- BOOST_CHECK_EQUAL(entry.getLocalUri(), expectedEntry.getLocalUri());
-
- m_matchedEntries.insert(entry.getLocalUri());
- }
-
- BOOST_CHECK_EQUAL(m_matchedEntries.size(), m_expectedEntries.size());
-
- m_finished = true;
- }
-
-protected:
- ChannelStatusPublisher::FactoryMap m_factories;
- shared_ptr<InternalFace> m_face;
- ChannelStatusPublisher m_publisher;
-
- ndn::EncodingBuffer m_buffer;
-
- std::map<std::string, ndn::nfd::ChannelStatus> m_expectedEntries;
- std::set<std::string> m_matchedEntries;
-
- bool m_finished;
-
- ndn::KeyChain m_keyChain;
-};
-
-BOOST_FIXTURE_TEST_SUITE(MgmtChannelStatusPublisher, ChannelStatusPublisherFixture)
-
-BOOST_AUTO_TEST_CASE(Publish)
-{
- const std::string protocol = "dummy";
-
- shared_ptr<DummyProtocolFactory> factory(make_shared<DummyProtocolFactory>());
- m_factories[protocol] = factory;
-
- for (int i = 0; i < 10; ++i)
- {
- const std::string uri = protocol + "://path" + boost::lexical_cast<std::string>(i);
- factory->addChannel(uri);
-
- ndn::nfd::ChannelStatus expectedEntry;
- expectedEntry.setLocalUri(DummyChannel(uri).getUri().toString());
-
- m_expectedEntries[expectedEntry.getLocalUri()] = expectedEntry;
- }
-
- m_face->onReceiveData.connect(bind(&ChannelStatusPublisherFixture::validatePublish, this, _1));
-
- m_publisher.publish();
- BOOST_REQUIRE(m_finished);
-}
-
-BOOST_AUTO_TEST_CASE(DuplicateFactories)
-{
- const std::string protocol1 = "dummy1";
- const std::string protocol2 = "dummy2";
-
- shared_ptr<DummyProtocolFactory> factory(make_shared<DummyProtocolFactory>());
- m_factories[protocol1] = factory;
- m_factories[protocol2] = factory;
-
- for (int i = 0; i < 10; ++i)
- {
- ndn::nfd::ChannelStatus expectedEntry;
- const std::string uri = protocol1 + "://path" + boost::lexical_cast<std::string>(i);
-
- factory->addChannel(uri);
-
- expectedEntry.setLocalUri(DummyChannel(uri).getUri().toString());
- m_expectedEntries[expectedEntry.getLocalUri()] = expectedEntry;
- }
-
- m_face->onReceiveData.connect(bind(&ChannelStatusPublisherFixture::validatePublish, this, _1));
-
- m_publisher.publish();
- BOOST_REQUIRE(m_finished);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-
-
-
-} // namespace nfd
diff --git a/tests/daemon/mgmt/face-manager/create-face.t.cpp b/tests/daemon/mgmt/face-manager-create-face.t.cpp
similarity index 85%
rename from tests/daemon/mgmt/face-manager/create-face.t.cpp
rename to tests/daemon/mgmt/face-manager-create-face.t.cpp
index 3a70619..ffee5aa 100644
--- a/tests/daemon/mgmt/face-manager/create-face.t.cpp
+++ b/tests/daemon/mgmt/face-manager-create-face.t.cpp
@@ -24,27 +24,34 @@
*/
#include "mgmt/face-manager.hpp"
-#include "mgmt/internal-face.hpp"
#include "fw/forwarder.hpp"
#include "tests/test-common.hpp"
+#include <ndn-cxx/mgmt/dispatcher.hpp>
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
#include <boost/property_tree/info_parser.hpp>
namespace nfd {
namespace tests {
-BOOST_FIXTURE_TEST_SUITE(MgmtFaceManager, BaseFixture)
-BOOST_AUTO_TEST_SUITE(CreateFace)
+BOOST_AUTO_TEST_SUITE(Mgmt)
+BOOST_AUTO_TEST_SUITE(TestFaceManager)
+
+BOOST_FIXTURE_TEST_SUITE(CreateFace, BaseFixture)
class FaceManagerNode
{
public:
FaceManagerNode(ndn::KeyChain& keyChain, const std::string& port = "6363")
- : face(make_shared<InternalFace>())
- , manager(forwarder.getFaceTable(), face, keyChain)
+ : face(ndn::util::makeDummyClientFace(getGlobalIoService(), {true, true}))
+ , dispatcher(*face, keyChain, ndn::security::SigningInfo())
+ , manager(forwarder.getFaceTable(), dispatcher, validator)
{
+ dispatcher.addTopPrefix("/localhost/nfd");
+
std::string basicConfig =
"face_system\n"
"{\n"
@@ -75,7 +82,7 @@
ConfigFile config;
manager.setConfigFile(config);
- face->getValidator().setConfigFile(config);
+ validator.setConfigFile(config);
config.parse(configSection, false, "dummy-config");
}
@@ -92,7 +99,9 @@
public:
Forwarder forwarder;
- shared_ptr<InternalFace> face;
+ shared_ptr<ndn::util::DummyClientFace> face;
+ ndn::mgmt::Dispatcher dispatcher;
+ CommandValidator validator;
FaceManager manager;
};
@@ -103,6 +112,7 @@
: node1(keyChain, "16363")
, node2(keyChain, "26363")
{
+ advanceClocks(time::milliseconds(1), 100);
}
~FaceManagerFixture()
@@ -166,6 +176,18 @@
}
};
+class UdpFaceCannotConnect // face that will cause afterCreateFaceFailure to be invoked
+{
+public:
+ ControlParameters
+ getParameters()
+ {
+ return ControlParameters()
+ .setUri("udp4://0.0.0.0:16363"); // cannot connect to self
+ }
+};
+
+
class UdpFacePersistent
{
public:
@@ -198,7 +220,7 @@
{
return ControlResponse()
.setCode(200)
- .setText("Success");
+ .setText("OK");
}
};
@@ -223,7 +245,8 @@
mpl::pair<TcpFacePermanent, Failure<500>>,
mpl::pair<UdpFaceOnDemand, Failure<500>>,
mpl::pair<UdpFacePersistent, Success>,
- mpl::pair<UdpFacePermanent, Success>> Faces;
+ mpl::pair<UdpFacePermanent, Success>,
+ mpl::pair<UdpFaceCannotConnect, Failure<408>>> Faces;
BOOST_FIXTURE_TEST_CASE_TEMPLATE(NewFace, T, Faces, FaceManagerFixture)
{
@@ -238,7 +261,8 @@
this->keyChain.sign(*command);
bool hasCallbackFired = false;
- this->node1.face->onReceiveData.connect([this, command, &hasCallbackFired] (const Data& response) {
+ this->node1.face->onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
+ // std::cout << response << std::endl;
if (!command->getName().isPrefixOf(response.getName())) {
return;
}
@@ -258,8 +282,8 @@
hasCallbackFired = true;
});
- this->node1.face->sendInterest(*command);
- this->advanceClocks(time::milliseconds(1), 10);
+ this->node1.face->receive(*command);
+ this->advanceClocks(time::milliseconds(1), 100);
BOOST_CHECK(hasCallbackFired);
}
@@ -287,7 +311,7 @@
shared_ptr<Interest> command(make_shared<Interest>(commandName));
this->keyChain.sign(*command);
- this->node1.face->sendInterest(*command);
+ this->node1.face->receive(*command);
this->advanceClocks(time::milliseconds(1), 10);
}
@@ -303,7 +327,7 @@
this->keyChain.sign(*command);
bool hasCallbackFired = false;
- this->node1.face->onReceiveData.connect([this, command, &hasCallbackFired] (const Data& response) {
+ this->node1.face->onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
if (!command->getName().isPrefixOf(response.getName())) {
return;
}
@@ -318,7 +342,7 @@
hasCallbackFired = true;
});
- this->node1.face->sendInterest(*command);
+ this->node1.face->receive(*command);
this->advanceClocks(time::milliseconds(1), 10);
BOOST_CHECK(hasCallbackFired);
@@ -326,18 +350,6 @@
}
-// class TcpFace
-// {
-// public:
-// ControlParameters
-// getParameters()
-// {
-// return ControlParameters()
-// .setUri("tcp4://127.0.0.1:16363")
-// .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
-// }
-// };
-
class UdpFace
{
public:
@@ -376,13 +388,13 @@
this->keyChain.sign(*command);
ndn::util::signal::ScopedConnection connection =
- this->node2.face->onReceiveData.connect([this, command] (const Data& response) {
+ this->node2.face->onSendData.connect([this, command] (const Data& response) {
if (!command->getName().isPrefixOf(response.getName())) {
return;
}
ControlResponse controlResponse(response.getContent().blockFromValue());
- BOOST_REQUIRE_EQUAL(controlResponse.getText(), "Success");
+ BOOST_REQUIRE_EQUAL(controlResponse.getText(), "OK");
BOOST_REQUIRE_EQUAL(controlResponse.getCode(), 200);
uint64_t faceId = ControlParameters(controlResponse.getBody()).getFaceId();
auto face = this->node2.forwarder.getFace(static_cast<FaceId>(faceId));
@@ -392,7 +404,7 @@
face->sendInterest(*dummyInterest);
});
- this->node2.face->sendInterest(*command);
+ this->node2.face->receive(*command);
this->advanceClocks(time::milliseconds(1), 10);
}
@@ -419,7 +431,7 @@
this->keyChain.sign(*command);
bool hasCallbackFired = false;
- this->node1.face->onReceiveData.connect([this, command, &hasCallbackFired] (const Data& response) {
+ this->node1.face->onSendData.connect([this, command, &hasCallbackFired] (const Data& response) {
if (!command->getName().isPrefixOf(response.getName())) {
return;
}
@@ -434,7 +446,7 @@
hasCallbackFired = true;
});
- this->node1.face->sendInterest(*command);
+ this->node1.face->receive(*command);
this->advanceClocks(time::milliseconds(1), 10);
BOOST_CHECK(hasCallbackFired);
@@ -442,8 +454,8 @@
}
BOOST_AUTO_TEST_SUITE_END() // CreateFace
-
-BOOST_AUTO_TEST_SUITE_END() // MgmtFaceManager
+BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
+BOOST_AUTO_TEST_SUITE_END() // Mgmt
} // tests
} // nfd
diff --git a/tests/daemon/mgmt/face-manager-process-config.t.cpp b/tests/daemon/mgmt/face-manager-process-config.t.cpp
new file mode 100644
index 0000000..9463ac4
--- /dev/null
+++ b/tests/daemon/mgmt/face-manager-process-config.t.cpp
@@ -0,0 +1,438 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "mgmt/face-manager.hpp"
+#include "face/udp-factory.hpp"
+
+#ifdef HAVE_LIBPCAP
+#include "face/ethernet-factory.hpp"
+#endif // HAVE_LIBPCAP
+
+#include "manager-common-fixture.hpp"
+
+namespace nfd {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Mgmt)
+BOOST_AUTO_TEST_SUITE(TestFaceManager)
+
+class FaceManagerProcessConfigFixture : public ManagerCommonFixture
+{
+public:
+ FaceManagerProcessConfigFixture()
+ : m_manager(m_forwarder.getFaceTable(), m_dispatcher, m_validator)
+ {
+ m_manager.setConfigFile(m_config);
+ }
+
+public:
+ void
+ parseConfig(const std::string& type, bool isDryRun)
+ {
+ m_config.parse(type, isDryRun, "test-config");
+ }
+
+protected:
+ FaceManager m_manager;
+ ConfigFile m_config;
+};
+
+
+BOOST_FIXTURE_TEST_SUITE(ProcessConfig, FaceManagerProcessConfigFixture)
+
+#ifdef HAVE_UNIX_SOCKETS
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUnix)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " unix\n"
+ " {\n"
+ " path /tmp/nfd.sock\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUnixUnknownOption)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " unix\n"
+ " {\n"
+ " hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+#endif // HAVE_UNIX_SOCKETS
+
+BOOST_AUTO_TEST_CASE(ProcessSectionTcp)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " tcp\n"
+ " {\n"
+ " listen yes\n"
+ " port 16363\n"
+ " enable_v4 yes\n"
+ " enable_v6 yes\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionTcpBadListen)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " tcp\n"
+ " {\n"
+ " listen hello\n"
+ " }\n"
+ "}\n";
+
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionTcpChannelsDisabled)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " tcp\n"
+ " {\n"
+ " port 6363\n"
+ " enable_v4 no\n"
+ " enable_v6 no\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionTcpUnknownOption)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " tcp\n"
+ " {\n"
+ " hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdp)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " port 6363\n"
+ " enable_v4 yes\n"
+ " enable_v6 yes\n"
+ " idle_timeout 30\n"
+ " keep_alive_interval 25\n"
+ " mcast yes\n"
+ " mcast_port 56363\n"
+ " mcast_group 224.0.23.170\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpBadIdleTimeout)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " idle_timeout hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpBadMcast)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " mcast hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpBadMcastGroup)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " mcast no\n"
+ " mcast_port 50\n"
+ " mcast_group hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpBadMcastGroupV6)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " mcast no\n"
+ " mcast_port 50\n"
+ " mcast_group ::1\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpChannelsDisabled)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " port 6363\n"
+ " enable_v4 no\n"
+ " enable_v6 no\n"
+ " idle_timeout 30\n"
+ " keep_alive_interval 25\n"
+ " mcast yes\n"
+ " mcast_port 56363\n"
+ " mcast_group 224.0.23.170\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpConflictingMcast)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " port 6363\n"
+ " enable_v4 no\n"
+ " enable_v6 yes\n"
+ " idle_timeout 30\n"
+ " keep_alive_interval 25\n"
+ " mcast yes\n"
+ " mcast_port 56363\n"
+ " mcast_group 224.0.23.170\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpUnknownOption)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+
+BOOST_AUTO_TEST_CASE(ProcessSectionUdpMulticastReinit)
+{
+ const std::string CONFIG_WITH_MCAST =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " mcast yes\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
+
+ BOOST_REQUIRE(m_manager.m_factories.find("udp") != m_manager.m_factories.end());
+ auto factory = dynamic_pointer_cast<UdpFactory>(m_manager.m_factories.find("udp")->second);
+ BOOST_REQUIRE(factory != nullptr);
+
+ if (factory->getMulticastFaces().size() == 0) {
+ BOOST_TEST_MESSAGE("Destroying multicast faces is not tested because "
+ "no UDP multicast faces are available");
+ return;
+ }
+ BOOST_CHECK_GT(factory->getMulticastFaces().size(), 0);
+
+ const std::string CONFIG_WITHOUT_MCAST =
+ "face_system\n"
+ "{\n"
+ " udp\n"
+ " {\n"
+ " mcast no\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
+ BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
+}
+
+#ifdef HAVE_LIBPCAP
+
+BOOST_AUTO_TEST_CASE(ProcessSectionEther)
+{
+
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " ether\n"
+ " {\n"
+ " mcast yes\n"
+ " mcast_group 01:00:5E:00:17:AA\n"
+ " }\n"
+ "}\n";
+
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionEtherBadMcast)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " ether\n"
+ " {\n"
+ " mcast hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionEtherBadMcastGroup)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " ether\n"
+ " {\n"
+ " mcast yes\n"
+ " mcast_group\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionEtherUnknownOption)
+{
+ const std::string CONFIG =
+ "face_system\n"
+ "{\n"
+ " ether\n"
+ " {\n"
+ " hello\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_CASE(ProcessSectionEtherMulticastReinit)
+{
+ const std::string CONFIG_WITH_MCAST =
+ "face_system\n"
+ "{\n"
+ " ether\n"
+ " {\n"
+ " mcast yes\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
+
+ BOOST_REQUIRE(m_manager.m_factories.find("ether") != m_manager.m_factories.end());
+ auto factory = dynamic_pointer_cast<EthernetFactory>(m_manager.m_factories.find("ether")->second);
+ BOOST_REQUIRE(factory != nullptr);
+
+ if (factory->getMulticastFaces().size() == 0) {
+ BOOST_TEST_MESSAGE("Destroying multicast faces is not tested because "
+ "no Ethernet multicast faces are available");
+ return;
+ }
+ BOOST_CHECK_GT(factory->getMulticastFaces().size(), 0);
+
+ const std::string CONFIG_WITHOUT_MCAST =
+ "face_system\n"
+ "{\n"
+ " ether\n"
+ " {\n"
+ " mcast no\n"
+ " }\n"
+ "}\n";
+ BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
+ BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
+}
+
+#endif // HAVE_LIBPCAP
+
+BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
+BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
+BOOST_AUTO_TEST_SUITE_END() // Mgmt
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/daemon/mgmt/face-manager.t.cpp b/tests/daemon/mgmt/face-manager.t.cpp
index 36e9e8a..db24029 100644
--- a/tests/daemon/mgmt/face-manager.t.cpp
+++ b/tests/daemon/mgmt/face-manager.t.cpp
@@ -24,1853 +24,426 @@
*/
#include "mgmt/face-manager.hpp"
-#include "mgmt/internal-face.hpp"
-#include "mgmt/face-status-publisher.hpp"
-
-#include "face/face.hpp"
+#include "manager-common-fixture.hpp"
#include "../face/dummy-face.hpp"
-#include "fw/face-table.hpp"
-#include "fw/forwarder.hpp"
+#include "face/tcp-factory.hpp"
#include "face/udp-factory.hpp"
-#ifdef HAVE_LIBPCAP
-#include "face/ethernet-factory.hpp"
-#endif // HAVE_LIBPCAP
-
-#include "common.hpp"
-#include "tests/test-common.hpp"
-#include "validation-common.hpp"
-#include "face-status-publisher-common.hpp"
-#include "face-query-status-publisher-common.hpp"
-#include "channel-status-common.hpp"
-
+#include <ndn-cxx/util/random.hpp>
#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/management/nfd-channel-status.hpp>
#include <ndn-cxx/management/nfd-face-event-notification.hpp>
namespace nfd {
namespace tests {
-NFD_LOG_INIT("FaceManagerTest");
-
-class FaceManagerTestFace : public DummyFace
-{
-public:
-
- FaceManagerTestFace()
- : m_closeFired(false)
- {
-
- }
-
- virtual
- ~FaceManagerTestFace()
- {
-
- }
-
- virtual void
- close()
- {
- m_closeFired = true;
- }
-
- bool
- didCloseFire() const
- {
- return m_closeFired;
- }
-
-private:
- bool m_closeFired;
-};
-
-class TestFaceTable : public FaceTable
-{
-public:
- TestFaceTable(Forwarder& forwarder)
- : FaceTable(forwarder),
- m_addFired(false),
- m_getFired(false),
- m_dummy(make_shared<FaceManagerTestFace>())
- {
-
- }
-
- virtual
- ~TestFaceTable()
- {
-
- }
-
- virtual void
- add(shared_ptr<Face> face)
- {
- m_addFired = true;
- }
-
- virtual shared_ptr<Face>
- get(FaceId id) const
- {
- m_getFired = true;
- return m_dummy;
- }
-
- bool
- didAddFire() const
- {
- return m_addFired;
- }
-
- bool
- didGetFire() const
- {
- return m_getFired;
- }
-
- void
- reset()
- {
- m_addFired = false;
- m_getFired = false;
- }
-
- shared_ptr<FaceManagerTestFace>&
- getDummyFace()
- {
- return m_dummy;
- }
-
-private:
- bool m_addFired;
- mutable bool m_getFired;
- shared_ptr<FaceManagerTestFace> m_dummy;
-};
-
-
-class TestFaceTableFixture : public BaseFixture
-{
-public:
- TestFaceTableFixture()
- : m_faceTable(m_forwarder)
- {
-
- }
-
- virtual
- ~TestFaceTableFixture()
- {
-
- }
-
-protected:
- Forwarder m_forwarder;
- TestFaceTable m_faceTable;
-};
-
-class TestFaceManagerCommon
-{
-public:
- TestFaceManagerCommon()
- : m_face(make_shared<InternalFace>()),
- m_callbackFired(false)
- {
-
- }
-
- virtual
- ~TestFaceManagerCommon()
- {
-
- }
-
- shared_ptr<InternalFace>&
- getFace()
- {
- return m_face;
- }
-
- void
- validateControlResponseCommon(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- ControlResponse& control)
- {
- m_callbackFired = true;
- Block controlRaw = response.getContent().blockFromValue();
-
- control.wireDecode(controlRaw);
-
- // NFD_LOG_DEBUG("received control response"
- // << " Name: " << response.getName()
- // << " code: " << control.getCode()
- // << " text: " << control.getText());
-
- BOOST_CHECK_EQUAL(response.getName(), expectedName);
- BOOST_CHECK_EQUAL(control.getCode(), expectedCode);
- BOOST_CHECK_EQUAL(control.getText(), expectedText);
- }
-
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText)
- {
- ControlResponse control;
- validateControlResponseCommon(response, expectedName,
- expectedCode, expectedText, control);
-
- if (!control.getBody().empty())
- {
- BOOST_FAIL("found unexpected control response body");
- }
- }
-
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- const Block& expectedBody)
- {
- ControlResponse control;
- validateControlResponseCommon(response, expectedName,
- expectedCode, expectedText, control);
-
- BOOST_REQUIRE(!control.getBody().empty());
- BOOST_REQUIRE(control.getBody().value_size() == expectedBody.value_size());
-
- BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
- expectedBody.value_size()) == 0);
-
- }
-
- bool
- didCallbackFire() const
- {
- return m_callbackFired;
- }
-
- void
- resetCallbackFired()
- {
- m_callbackFired = false;
- }
-
-protected:
- shared_ptr<InternalFace> m_face;
- bool m_callbackFired;
- ndn::KeyChain m_testKeyChain;
-};
-
-class FaceManagerFixture : public TestFaceTableFixture, public TestFaceManagerCommon
+class FaceManagerFixture : public ManagerCommonFixture
{
public:
FaceManagerFixture()
- : m_manager(m_faceTable, m_face, m_testKeyChain)
+ : m_faceTable(m_forwarder.getFaceTable())
+ , m_manager(m_faceTable, m_dispatcher, m_validator)
{
- m_manager.setConfigFile(m_config);
+ setTopPrefixAndPrivilege("/localhost/nfd", "faces");
}
- virtual
- ~FaceManagerFixture()
+public:
+ template<typename Face>
+ shared_ptr<Face>
+ addFace(bool wantRemoveLastNotification = false)
{
-
- }
-
- void
- parseConfig(const std::string configuration, bool isDryRun)
- {
- m_config.parse(configuration, isDryRun, "dummy-config");
- }
-
- FaceManager&
- getManager()
- {
- return m_manager;
- }
-
- void
- addInterestRule(const std::string& regex,
- ndn::IdentityCertificate& certificate)
- {
- m_manager.addInterestRule(regex, certificate);
- }
-
- bool
- didFaceTableAddFire() const
- {
- return m_faceTable.didAddFire();
- }
-
- bool
- didFaceTableGetFire() const
- {
- return m_faceTable.didGetFire();
- }
-
- void
- resetFaceTable()
- {
- m_faceTable.reset();
+ auto face = make_shared<Face>();
+ m_faceTable.add(face);
+ advanceClocks(time::milliseconds(1), 10); // wait for notification posted
+ if (wantRemoveLastNotification) {
+ m_responses.pop_back();
+ }
+ return face;
}
protected:
+ FaceTable& m_faceTable;
FaceManager m_manager;
- ConfigFile m_config;
};
-BOOST_FIXTURE_TEST_SUITE(MgmtFaceManager, FaceManagerFixture)
+BOOST_FIXTURE_TEST_SUITE(Mgmt, FaceManagerFixture)
+BOOST_AUTO_TEST_SUITE(TestFaceManager)
+
+BOOST_AUTO_TEST_SUITE(DestroyFace)
+
+BOOST_AUTO_TEST_CASE(Existing)
+{
+ auto addedFace = addFace<DummyFace>(true); // clear notification for creation
+
+ auto parameters = ControlParameters().setFaceId(addedFace->getId());
+ auto command = makeControlCommandRequest("/localhost/nfd/faces/destroy", parameters);
+
+ receiveInterest(command);
+
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 2); // one response and one notification
+ // notification is already tested, so ignore it
+
+ BOOST_CHECK_EQUAL(checkResponse(1, command->getName(), makeResponse(200, "OK", parameters)),
+ CheckResponseResult::OK);
+
+ BOOST_CHECK_EQUAL(addedFace->getId(), -1);
+}
+
+BOOST_AUTO_TEST_CASE(NonExisting)
+{
+ auto parameters = ControlParameters().setFaceId(65535);
+ auto command = makeControlCommandRequest("/localhost/nfd/faces/destroy", parameters);
+
+ receiveInterest(command);
+
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+
+ BOOST_CHECK_EQUAL(checkResponse(0, command->getName(), makeResponse(200, "OK", parameters)),
+ CheckResponseResult::OK);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // DestroyFace
+
+BOOST_AUTO_TEST_CASE(FaceEvents)
+{
+ auto addedFace = addFace<DummyFace>(); // trigger FACE_EVENT_CREATED notification
+ BOOST_CHECK_NE(addedFace->getId(), -1);
+ int64_t faceId = addedFace->getId();
+
+ // check notification
+ {
+ Block payload;
+ ndn::nfd::FaceEventNotification notification;
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_NO_THROW(payload = m_responses[0].getContent().blockFromValue());
+ BOOST_CHECK_EQUAL(payload.type(), ndn::tlv::nfd::FaceEventNotification);
+ BOOST_CHECK_NO_THROW(notification.wireDecode(payload));
+ BOOST_CHECK_EQUAL(notification.getKind(), ndn::nfd::FACE_EVENT_CREATED);
+ BOOST_CHECK_EQUAL(notification.getFaceId(), faceId);
+ BOOST_CHECK_EQUAL(notification.getRemoteUri(), addedFace->getRemoteUri().toString());
+ BOOST_CHECK_EQUAL(notification.getLocalUri(), addedFace->getLocalUri().toString());
+ BOOST_CHECK_EQUAL(notification.getFaceScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
+ BOOST_CHECK_EQUAL(notification.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
+ BOOST_CHECK_EQUAL(notification.getLinkType(), ndn::nfd::LinkType::LINK_TYPE_POINT_TO_POINT);
+ }
+
+ addedFace->close(); // trigger FaceDestroy FACE_EVENT_DESTROYED
+ advanceClocks(time::milliseconds(1), 10);
+
+ // check notification
+ {
+ Block payload;
+ ndn::nfd::FaceEventNotification notification;
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 2);
+ BOOST_CHECK_NO_THROW(payload = m_responses[1].getContent().blockFromValue());
+ BOOST_CHECK_EQUAL(payload.type(), ndn::tlv::nfd::FaceEventNotification);
+ BOOST_CHECK_NO_THROW(notification.wireDecode(payload));
+ BOOST_CHECK_EQUAL(notification.getKind(), ndn::nfd::FACE_EVENT_DESTROYED);
+ BOOST_CHECK_EQUAL(notification.getFaceId(), faceId);
+ BOOST_CHECK_EQUAL(notification.getRemoteUri(), addedFace->getRemoteUri().toString());
+ BOOST_CHECK_EQUAL(notification.getLocalUri(), addedFace->getLocalUri().toString());
+ BOOST_CHECK_EQUAL(notification.getFaceScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
+ BOOST_CHECK_EQUAL(notification.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
+ BOOST_CHECK_EQUAL(notification.getLinkType(), ndn::nfd::LinkType::LINK_TYPE_POINT_TO_POINT);
+ }
+ BOOST_CHECK_EQUAL(addedFace->getId(), -1);
+}
+
+BOOST_AUTO_TEST_CASE(EnableDisableLocalControl)
+{
+ auto nonLocalFace = addFace<DummyFace>(true); // clear notification
+ auto localFace = addFace<DummyLocalFace>(true); // clear notification
+ BOOST_CHECK(localFace->isLocal());
+ BOOST_CHECK(!nonLocalFace->isLocal());
+
+ std::vector<Name> commandNames;
+ auto testLocalControl = [&] (const Name& name, const ControlParameters& params, uint64_t faceId) {
+ auto command = makeControlCommandRequest(name, params,
+ [faceId] (shared_ptr<Interest> interest) {
+ interest->setIncomingFaceId(faceId);
+ });
+ receiveInterest(command);
+ commandNames.push_back(command->getName());
+ };
+
+ auto paramsF = ControlParameters().setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+ auto paramsN = ControlParameters().setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
+
+ // non-existing face: 0~3
+ testLocalControl("/localhost/nfd/faces/enable-local-control", paramsF, FACEID_NULL);
+ testLocalControl("/localhost/nfd/faces/disable-local-control", paramsF, FACEID_NULL);
+ testLocalControl("/localhost/nfd/faces/enable-local-control", paramsN, FACEID_NULL);
+ testLocalControl("/localhost/nfd/faces/disable-local-control", paramsN, FACEID_NULL);
+
+ // non-local face: 4~7
+ testLocalControl("/localhost/nfd/faces/enable-local-control", paramsF, nonLocalFace->getId());
+ testLocalControl("/localhost/nfd/faces/disable-local-control", paramsF, nonLocalFace->getId());
+ testLocalControl("/localhost/nfd/faces/enable-local-control", paramsN, nonLocalFace->getId());
+ testLocalControl("/localhost/nfd/faces/disable-local-control", paramsN, nonLocalFace->getId());
+
+ // enableLocalControl for Incoming FaceId on existing local face:
+ testLocalControl("/localhost/nfd/faces/enable-local-control", paramsF, localFace->getId()); // 8
+ BOOST_CHECK(localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+ BOOST_CHECK(!localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+ // disableLocalControl for Incoming FaceId on existing local face
+ testLocalControl("/localhost/nfd/faces/disable-local-control", paramsF, localFace->getId()); // 9
+ BOOST_CHECK(!localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+ BOOST_CHECK(!localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+ // enableLocalControl for NextHop ID on existing local face
+ testLocalControl("/localhost/nfd/faces/enable-local-control", paramsN, localFace->getId()); // 10
+ BOOST_CHECK(!localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+ BOOST_CHECK(localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+ // disableLocalControl for NextHop ID on existing local face
+ testLocalControl("/localhost/nfd/faces/disable-local-control", paramsN, localFace->getId()); // 11
+ BOOST_CHECK(!localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+ BOOST_CHECK(!localFace->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+ // check responses
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 12);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandNames[0], ControlResponse(410, "Face not found")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(1, commandNames[1], ControlResponse(410, "Face not found")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(2, commandNames[2], ControlResponse(410, "Face not found")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(3, commandNames[3], ControlResponse(410, "Face not found")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(4, commandNames[4], ControlResponse(412, "Face is non-local")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(5, commandNames[5], ControlResponse(412, "Face is non-local")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(6, commandNames[6], ControlResponse(412, "Face is non-local")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(7, commandNames[7], ControlResponse(412, "Face is non-local")),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(8, commandNames[8], makeResponse(200, "OK", paramsF)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(9, commandNames[9], makeResponse(200, "OK", paramsF)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(10, commandNames[10], makeResponse(200, "OK", paramsN)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkResponse(11, commandNames[11], makeResponse(200, "OK", paramsN)),
+ CheckResponseResult::OK);
+}
+
+class TestFace : public DummyFace
+{
+public:
+ explicit
+ TestFace(const std::string& uri = "test://")
+ : DummyFace(uri, uri)
+ {
+ getMutableCounters().getNInInterests().set(ndn::random::generateWord64());
+ getMutableCounters().getNInDatas().set(ndn::random::generateWord64());
+ getMutableCounters().getNOutInterests().set(ndn::random::generateWord64());
+ getMutableCounters().getNOutDatas().set(ndn::random::generateWord64());
+ getMutableCounters().getNInBytes().set(ndn::random::generateWord64());
+ getMutableCounters().getNOutBytes().set(ndn::random::generateWord64());
+ }
+};
+
+// @todo Refactor when ndn::nfd::FaceStatus implementes operator!= and operator<<
+class FaceStatus : public ndn::nfd::FaceStatus
+{
+public:
+ FaceStatus(const ndn::nfd::FaceStatus& s)
+ : ndn::nfd::FaceStatus(s)
+ {
+ }
+};
bool
-isExpectedException(const ConfigFile::Error& error, const std::string& expectedMessage)
+operator!=(const FaceStatus& left, const FaceStatus& right)
{
- if (error.what() != expectedMessage)
- {
- NFD_LOG_ERROR("expected: " << expectedMessage << "\tgot: " << error.what());
- }
- return error.what() == expectedMessage;
+ return left.getRemoteUri() != right.getRemoteUri() ||
+ left.getLocalUri() != right.getLocalUri() ||
+ left.getFaceScope() != right.getFaceScope() ||
+ left.getFacePersistency() != right.getFacePersistency() ||
+ left.getLinkType() != right.getLinkType() ||
+ left.getNInInterests() != right.getNInInterests() ||
+ left.getNInDatas() != right.getNInDatas() ||
+ left.getNOutInterests() != right.getNOutInterests() ||
+ left.getNOutDatas() != right.getNOutDatas() ||
+ left.getNInBytes() != right.getNInBytes() ||
+ left.getNOutBytes() != right.getNOutBytes();
}
-#ifdef HAVE_UNIX_SOCKETS
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUnix)
+std::ostream&
+operator<<(std::ostream &os, const FaceStatus& status)
{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " unix\n"
- " {\n"
- " path /tmp/nfd.sock\n"
- " }\n"
- "}\n";
- BOOST_TEST_CHECKPOINT("Calling parse");
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
+ os << "[" << status.getRemoteUri() << ", "
+ << status.getLocalUri() << ", "
+ << status.getFacePersistency() << ", "
+ << status.getLinkType() << ", "
+ << status.getNInInterests() << ", "
+ << status.getNInDatas() << ", "
+ << status.getNOutInterests() << ", "
+ << status.getNOutDatas() << ", "
+ << status.getNInBytes() << ", "
+ << status.getNOutBytes() << "]";
+ return os;
}
-BOOST_AUTO_TEST_CASE(TestProcessSectionUnixDryRun)
+BOOST_AUTO_TEST_CASE(FaceDataset)
{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " unix\n"
- " {\n"
- " path /var/run/nfd.sock\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUnixUnknownOption)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " unix\n"
- " {\n"
- " hello\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Unrecognized option \"hello\" in \"unix\" section"));
-}
-
-#endif // HAVE_UNIX_SOCKETS
-
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionTcp)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " tcp\n"
- " {\n"
- " listen yes\n"
- " port 6363\n"
- " enable_v4 yes\n"
- " enable_v6 yes\n"
- " }\n"
- "}\n";
- try
- {
- parseConfig(CONFIG, false);
- }
- catch (const std::runtime_error& e)
- {
- const std::string reason = e.what();
- if (reason.find("Address in use") != std::string::npos)
- {
- BOOST_FAIL(reason);
- }
- }
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionTcpDryRun)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " tcp\n"
- " {\n"
- " listen yes\n"
- " port 6363\n"
- " enable_v4 yes\n"
- " enable_v6 yes\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionTcpBadListen)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " tcp\n"
- " {\n"
- " listen hello\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"listen\" in \"tcp\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionTcpChannelsDisabled)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " tcp\n"
- " {\n"
- " port 6363\n"
- " enable_v4 no\n"
- " enable_v6 no\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "IPv4 and IPv6 channels have been disabled."
- " Remove \"tcp\" section to disable TCP channels or"
- " re-enable at least one channel type."));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionTcpUnknownOption)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " tcp\n"
- " {\n"
- " hello\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Unrecognized option \"hello\" in \"tcp\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdp)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " port 6363\n"
- " enable_v4 yes\n"
- " enable_v6 yes\n"
- " idle_timeout 30\n"
- " keep_alive_interval 25\n"
- " mcast yes\n"
- " mcast_port 56363\n"
- " mcast_group 224.0.23.170\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpDryRun)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " port 6363\n"
- " idle_timeout 30\n"
- " keep_alive_interval 25\n"
- " mcast yes\n"
- " mcast_port 56363\n"
- " mcast_group 224.0.23.170\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadIdleTimeout)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " idle_timeout hello\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"idle_timeout\" in \"udp\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadMcast)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " mcast hello\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"mcast\" in \"udp\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadMcastGroup)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " mcast no\n"
- " mcast_port 50\n"
- " mcast_group hello\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"mcast_group\" in \"udp\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadMcastGroupV6)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " mcast no\n"
- " mcast_port 50\n"
- " mcast_group ::1\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"mcast_group\" in \"udp\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpChannelsDisabled)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " port 6363\n"
- " enable_v4 no\n"
- " enable_v6 no\n"
- " idle_timeout 30\n"
- " keep_alive_interval 25\n"
- " mcast yes\n"
- " mcast_port 56363\n"
- " mcast_group 224.0.23.170\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "IPv4 and IPv6 channels have been disabled."
- " Remove \"udp\" section to disable UDP channels or"
- " re-enable at least one channel type."));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpConflictingMcast)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " port 6363\n"
- " enable_v4 no\n"
- " enable_v6 yes\n"
- " idle_timeout 30\n"
- " keep_alive_interval 25\n"
- " mcast yes\n"
- " mcast_port 56363\n"
- " mcast_group 224.0.23.170\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "IPv4 multicast requested, but IPv4 channels"
- " have been disabled (conflicting configuration options set)"));
-}
-
-
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpUnknownOption)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " hello\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Unrecognized option \"hello\" in \"udp\" section"));
-}
-
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionUdpMulticastReinit)
-{
- const std::string CONFIG_WITH_MCAST =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " mcast yes\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
-
- shared_ptr<UdpFactory> factory = static_pointer_cast<UdpFactory>(getManager().findFactory("udp"));
- BOOST_REQUIRE(static_cast<bool>(factory));
-
- if (factory->getMulticastFaces().size() == 0) {
- BOOST_TEST_MESSAGE("Destroying multicast faces is not tested because "
- "no UDP multicast faces are available");
+ size_t nEntries = 303;
+ for (size_t i = 0 ; i < nEntries ; i ++) {
+ addFace<TestFace>(true);
}
- const std::string CONFIG_WITHOUT_MCAST =
- "face_system\n"
- "{\n"
- " udp\n"
- " {\n"
- " mcast no\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
- BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
-}
+ receiveInterest(makeInterest("/localhost/nfd/faces/list"));
+ Block content;
+ BOOST_CHECK_NO_THROW(content = concatenateResponses());
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_REQUIRE_EQUAL(content.elements().size(), nEntries);
-#ifdef HAVE_LIBPCAP
+ std::vector<FaceStatus> expectedStatuses, receivedStatuses;
+ std::set<FaceId> faceIds;
+ for (size_t idx = 0; idx < nEntries; ++idx) {
+ BOOST_TEST_MESSAGE("processing element: " << idx);
-BOOST_AUTO_TEST_CASE(TestProcessSectionEther)
-{
-
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " mcast yes\n"
- " mcast_group 01:00:5E:00:17:AA\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionEtherDryRun)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " mcast yes\n"
- " mcast_group 01:00:5E:00:17:AA\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionEtherBadMcast)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " mcast hello\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"mcast\" in \"ether\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionEtherBadMcastGroup)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " mcast yes\n"
- " mcast_group\n"
- " }\n"
- "}\n";
-
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Invalid value for option \"mcast_group\" in \"ether\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionEtherUnknownOption)
-{
- const std::string CONFIG =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " hello\n"
- " }\n"
- "}\n";
- BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
- bind(&isExpectedException, _1,
- "Unrecognized option \"hello\" in \"ether\" section"));
-}
-
-BOOST_AUTO_TEST_CASE(TestProcessSectionEtherMulticastReinit)
-{
- const std::string CONFIG_WITH_MCAST =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " mcast yes\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
-
- shared_ptr<EthernetFactory> factory =
- static_pointer_cast<EthernetFactory>(getManager().findFactory("ether"));
- BOOST_REQUIRE(static_cast<bool>(factory));
-
- if (factory->getMulticastFaces().size() == 0) {
- BOOST_TEST_MESSAGE("Destroying multicast faces is not tested because "
- "no Ethernet multicast faces are available");
+ ndn::nfd::FaceStatus decodedStatus;
+ BOOST_REQUIRE_NO_THROW(decodedStatus.wireDecode(content.elements()[idx]));
+ BOOST_REQUIRE(m_faceTable.get(decodedStatus.getFaceId()) != nullptr);
+ faceIds.insert(decodedStatus.getFaceId());
+ receivedStatuses.push_back(decodedStatus);
+ expectedStatuses.push_back(m_faceTable.get(decodedStatus.getFaceId())->getFaceStatus());
}
- const std::string CONFIG_WITHOUT_MCAST =
- "face_system\n"
- "{\n"
- " ether\n"
- " {\n"
- " mcast no\n"
- " }\n"
- "}\n";
- BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
- BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(faceIds.size(), nEntries);
+ BOOST_CHECK_EQUAL_COLLECTIONS(receivedStatuses.begin(), receivedStatuses.end(),
+ expectedStatuses.begin(), expectedStatuses.end());
}
-#endif // HAVE_LIBPCAP
-
-BOOST_AUTO_TEST_CASE(ShortName)
+BOOST_AUTO_TEST_CASE(FaceQuery)
{
- shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/faces"));
+ auto face1 = addFace<DummyFace>(true); // dummy://
+ auto face2 = addFace<DummyLocalFace>(true); // dummy://, local
+ auto face3 = addFace<TestFace>(true); // test://
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
+ auto generateQueryName = [] (const ndn::nfd::FaceQueryFilter& filter) {
+ return Name("/localhost/nfd/faces/query").append(filter.wireEncode());
+ };
- getFace()->sendInterest(*command);
- g_io.run_one();
+ auto querySchemeName =
+ generateQueryName(ndn::nfd::FaceQueryFilter().setUriScheme("dummy"));
+ auto queryIdName =
+ generateQueryName(ndn::nfd::FaceQueryFilter().setFaceId(face1->getId()));
+ auto queryScopeName =
+ generateQueryName(ndn::nfd::FaceQueryFilter().setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL));
+ auto invalidQueryName =
+ Name("/localhost/nfd/faces/query").append(ndn::makeStringBlock(tlv::Content, "invalid"));
- BOOST_REQUIRE(didCallbackFire());
+ receiveInterest(makeInterest(querySchemeName)); // face1 and face2 expected
+ receiveInterest(makeInterest(queryIdName)); // face1 expected
+ receiveInterest(makeInterest(queryScopeName)); // face1 and face3 expected
+ receiveInterest(makeInterest(invalidQueryName)); // nack expected
+
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 4);
+
+ Block content;
+ ndn::nfd::FaceStatus status;
+
+ content = m_responses[0].getContent();
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_CHECK_EQUAL(content.elements().size(), 2); // face1 and face2
+ BOOST_CHECK_NO_THROW(status.wireDecode(content.elements()[0]));
+ BOOST_CHECK_EQUAL(face1->getId(), status.getFaceId());
+ BOOST_CHECK_NO_THROW(status.wireDecode(content.elements()[1]));
+ BOOST_CHECK_EQUAL(face2->getId(), status.getFaceId());
+
+ content = m_responses[1].getContent();
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_CHECK_EQUAL(content.elements().size(), 1); // face1
+ BOOST_CHECK_NO_THROW(status.wireDecode(content.elements()[0]));
+ BOOST_CHECK_EQUAL(face1->getId(), status.getFaceId());
+
+ content = m_responses[2].getContent();
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_CHECK_EQUAL(content.elements().size(), 2); // face1 and face3
+ BOOST_CHECK_NO_THROW(status.wireDecode(content.elements()[0]));
+ BOOST_CHECK_EQUAL(face1->getId(), status.getFaceId());
+ BOOST_CHECK_NO_THROW(status.wireDecode(content.elements()[1]));
+ BOOST_CHECK_EQUAL(face3->getId(), status.getFaceId());
+
+ ControlResponse expectedResponse(400, "malformed filter"); // nack, 400, malformed filter
+ BOOST_CHECK_EQUAL(checkResponse(3, invalidQueryName, expectedResponse, tlv::ContentType_Nack),
+ CheckResponseResult::OK);
}
-BOOST_AUTO_TEST_CASE(MalformedCommmand)
-{
- shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/faces"));
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getManager().onFaceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(UnsignedCommand)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 401, "Signature required");
- });
-
- getManager().onFaceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand, UnauthorizedCommandFixture<FaceManagerFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 403, "Unauthorized command");
- });
-
- getManager().onFaceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-template <typename T> class AuthorizedCommandFixture : public CommandFixture<T>
+class TestChannel : public Channel
{
public:
- AuthorizedCommandFixture()
+ TestChannel(const std::string& uri)
{
- const std::string regex = "^<localhost><nfd><faces>";
- T::addInterestRule(regex, *CommandFixture<T>::m_certificate);
- }
-
- virtual
- ~AuthorizedCommandFixture()
- {
-
+ setUri(FaceUri(uri));
}
};
-BOOST_FIXTURE_TEST_CASE(UnsupportedCommand, AuthorizedCommandFixture<FaceManagerFixture>)
-{
- ControlParameters parameters;
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("unsupported");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 501, "Unsupported command");
- });
-
- getManager().onFaceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-class ValidatedFaceRequestFixture : public TestFaceTableFixture,
- public TestFaceManagerCommon,
- public FaceManager
+class TestProtocolFactory : public ProtocolFactory
{
public:
-
- ValidatedFaceRequestFixture()
- : FaceManager(TestFaceTableFixture::m_faceTable, getFace(), m_testKeyChain),
- m_createFaceFired(false),
- m_destroyFaceFired(false)
- {
-
- }
-
virtual void
- createFace(const Interest& request,
- ControlParameters& parameters)
+ createFace(const FaceUri& uri,
+ ndn::nfd::FacePersistency persistency,
+ const FaceCreatedCallback& onCreated,
+ const FaceConnectFailedCallback& onConnectFailed) DECL_OVERRIDE
{
- m_createFaceFired = true;
}
- virtual void
- destroyFace(const Interest& request,
- ControlParameters& parameters)
+ virtual std::list<shared_ptr<const Channel>>
+ getChannels() const DECL_OVERRIDE
{
- m_destroyFaceFired = true;
+ return m_channels;
}
- virtual
- ~ValidatedFaceRequestFixture()
+public:
+ shared_ptr<TestChannel>
+ addChannel(const std::string& channelUri)
{
-
- }
-
- bool
- didCreateFaceFire() const
- {
- return m_createFaceFired;
- }
-
- bool
- didDestroyFaceFire() const
- {
- return m_destroyFaceFired;
+ auto channel = make_shared<TestChannel>(channelUri);
+ m_channels.push_back(channel);
+ return channel;
}
private:
- bool m_createFaceFired;
- bool m_destroyFaceFired;
+ std::list<shared_ptr<const Channel> > m_channels;
};
-BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestBadOptionParse,
- AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
+BOOST_AUTO_TEST_CASE(ChannelDataset)
{
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append("NotReallyParameters");
+ auto factory = make_shared<TestProtocolFactory>();
+ m_manager.m_factories["test"] = factory;
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- onValidatedFaceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestCreateFace,
- AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- onValidatedFaceRequest(command);
- BOOST_CHECK(didCreateFaceFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestDestroyFace,
- AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("destroy");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- onValidatedFaceRequest(command);
- BOOST_CHECK(didDestroyFaceFire());
-}
-
-class FaceTableFixture
-{
-public:
- FaceTableFixture()
- : m_faceTable(m_forwarder)
- {
+ std::map<std::string, shared_ptr<TestChannel>> addedChannels;
+ size_t nEntries = 404;
+ for (size_t i = 0 ; i < nEntries ; i ++) {
+ auto channel = factory->addChannel("test" + boost::lexical_cast<std::string>(i) + "://");
+ addedChannels[channel->getUri().toString()] = channel;
}
- virtual
- ~FaceTableFixture()
- {
+ receiveInterest(makeInterest("/localhost/nfd/faces/channels"));
+
+ Block content;
+ BOOST_CHECK_NO_THROW(content = concatenateResponses());
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_REQUIRE_EQUAL(content.elements().size(), nEntries);
+
+ for (size_t idx = 0; idx < nEntries; ++idx) {
+ BOOST_TEST_MESSAGE("processing element: " << idx);
+
+ ndn::nfd::ChannelStatus decodedStatus;
+ BOOST_CHECK_NO_THROW(decodedStatus.wireDecode(content.elements()[idx]));
+ BOOST_CHECK(addedChannels.find(decodedStatus.getLocalUri()) != addedChannels.end());
}
-
-protected:
- Forwarder m_forwarder;
- FaceTable m_faceTable;
-};
-
-class LocalControlFixture : public FaceTableFixture,
- public TestFaceManagerCommon,
- public FaceManager
-{
-public:
- LocalControlFixture()
- : FaceManager(FaceTableFixture::m_faceTable, getFace(), m_testKeyChain)
- {
- }
-};
-
-BOOST_FIXTURE_TEST_CASE(LocalControlInFaceId,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
- BOOST_REQUIRE(dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(),
- 200, "Success", encodedParameters);
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- disable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
- disableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(),
- 200, "Success", encodedParameters);
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
}
-BOOST_FIXTURE_TEST_CASE(LocalControlInFaceIdFaceNotFound,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
- BOOST_REQUIRE(dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId() + 100);
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(), 410, "Face not found");
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- disable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
- disableCommand->setIncomingFaceId(dummy->getId() + 100);
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(), 410, "Face not found");
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
-}
-
-BOOST_FIXTURE_TEST_CASE(LocalControlMissingFeature,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
- BOOST_REQUIRE(dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(),
- 400, "Malformed command");
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- disable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
- disableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(),
- 400, "Malformed command");
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
-}
-
-BOOST_FIXTURE_TEST_CASE(LocalControlInFaceIdNonLocal,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<DummyFace> dummy = make_shared<DummyFace>();
- BOOST_REQUIRE(!dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(),
- 412, "Face is non-local");
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(enable));
- disableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(),
- 412, "Face is non-local");
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceId,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
- BOOST_REQUIRE(dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(),
- 200, "Success", encodedParameters);
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
-
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- disable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
- disableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(),
- 200, "Success", encodedParameters);
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
-}
-
-BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceIdFaceNotFound,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
- BOOST_REQUIRE(dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId() + 100);
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(), 410, "Face not found");
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
-
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- disable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
- disableCommand->setIncomingFaceId(dummy->getId() + 100);
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(),
- 410, "Face not found");
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
- BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
-}
-
-BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceIdNonLocal,
- AuthorizedCommandFixture<LocalControlFixture>)
-{
- shared_ptr<DummyFace> dummy = make_shared<DummyFace>();
- BOOST_REQUIRE(!dummy->isLocal());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name enable("/localhost/nfd/faces/enable-local-control");
- enable.append(encodedParameters);
-
- shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
- enableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*enableCommand);
-
- signal::Connection conn = getFace()->onReceiveData.connect(
- [this, enableCommand] (const Data& response) {
- this->validateControlResponse(response, enableCommand->getName(),
- 412, "Face is non-local");
- });
-
- onValidatedFaceRequest(enableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
-
- conn.disconnect();
- resetCallbackFired();
-
- Name disable("/localhost/nfd/faces/disable-local-control");
- disable.append(encodedParameters);
-
- shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
- disableCommand->setIncomingFaceId(dummy->getId());
-
- generateCommand(*disableCommand);
-
- getFace()->onReceiveData.connect(
- [this, disableCommand] (const Data& response) {
- this->validateControlResponse(response, disableCommand->getName(),
- 412, "Face is non-local");
- });
-
- onValidatedFaceRequest(disableCommand);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-class FaceFixture : public FaceTableFixture,
- public TestFaceManagerCommon,
- public FaceManager
-{
-public:
- FaceFixture()
- : FaceManager(FaceTableFixture::m_faceTable,
- getFace(),
- m_testKeyChain)
- , m_receivedNotification(false)
- {
-
- }
-
- virtual
- ~FaceFixture()
- {
-
- }
-
- void
- callbackDispatch(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- const Block& expectedBody,
- const ndn::nfd::FaceEventNotification& expectedFaceEvent)
- {
- Block payload = response.getContent().blockFromValue();
- if (payload.type() == ndn::tlv::nfd::ControlResponse)
- {
- validateControlResponse(response, expectedName, expectedCode,
- expectedText, expectedBody);
- }
- else if (payload.type() == ndn::tlv::nfd::FaceEventNotification)
- {
- validateFaceEvent(payload, expectedFaceEvent);
- }
- else
- {
- BOOST_FAIL("Received unknown message type: #" << payload.type());
- }
- }
-
- void
- callbackDispatch(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- const ndn::nfd::FaceEventNotification& expectedFaceEvent)
- {
- Block payload = response.getContent().blockFromValue();
- if (payload.type() == ndn::tlv::nfd::ControlResponse)
- {
- validateControlResponse(response, expectedName,
- expectedCode, expectedText);
- }
- else if (payload.type() == ndn::tlv::nfd::FaceEventNotification)
- {
- validateFaceEvent(payload, expectedFaceEvent);
- }
- else
- {
- BOOST_FAIL("Received unknown message type: #" << payload.type());
- }
- }
-
- void
- validateFaceEvent(const Block& wire,
- const ndn::nfd::FaceEventNotification& expectedFaceEvent)
- {
-
- m_receivedNotification = true;
-
- ndn::nfd::FaceEventNotification notification(wire);
-
- BOOST_CHECK_EQUAL(notification.getKind(), expectedFaceEvent.getKind());
- BOOST_CHECK_EQUAL(notification.getFaceId(), expectedFaceEvent.getFaceId());
- BOOST_CHECK_EQUAL(notification.getRemoteUri(), expectedFaceEvent.getRemoteUri());
- BOOST_CHECK_EQUAL(notification.getLocalUri(), expectedFaceEvent.getLocalUri());
- BOOST_CHECK_EQUAL(notification.getFaceScope(), expectedFaceEvent.getFaceScope());
- BOOST_CHECK_EQUAL(notification.getFacePersistency(), expectedFaceEvent.getFacePersistency());
- BOOST_CHECK_EQUAL(notification.getLinkType(), expectedFaceEvent.getLinkType());
- }
-
- bool
- didReceiveNotication() const
- {
- return m_receivedNotification;
- }
-
-protected:
- bool m_receivedNotification;
-};
-
-BOOST_FIXTURE_TEST_CASE(CreateFaceBadUri, AuthorizedCommandFixture<FaceFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4:/127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- createFace(*command, parameters);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-BOOST_FIXTURE_TEST_CASE(CreateFaceNoncanonicalUri, AuthorizedCommandFixture<FaceFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp://127.0.0.1");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Non-canonical URI");
- });
-
- createFace(*command, parameters);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(CreateFaceMissingUri, AuthorizedCommandFixture<FaceFixture>)
-{
- ControlParameters parameters;
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- createFace(*command, parameters);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(CreateFaceUnknownScheme, AuthorizedCommandFixture<FaceFixture>)
-{
- ControlParameters parameters;
- // this will be an unsupported protocol because no factories have been
- // added to the face manager
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 501, "Unsupported protocol");
- });
-
- createFace(*command, parameters);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(OnCreated, AuthorizedCommandFixture<FaceFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- ControlParameters resultParameters;
- resultParameters.setUri("dummy://");
- resultParameters.setFaceId(FACEID_RESERVED_MAX + 1);
- resultParameters.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
-
- shared_ptr<DummyFace> dummy(make_shared<DummyFace>());
-
- ndn::nfd::FaceEventNotification expectedFaceEvent;
- expectedFaceEvent.setKind(ndn::nfd::FACE_EVENT_CREATED)
- .setFaceId(FACEID_RESERVED_MAX + 1)
- .setRemoteUri(dummy->getRemoteUri().toString())
- .setLocalUri(dummy->getLocalUri().toString())
- .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
- .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
-
- Block encodedResultParameters(resultParameters.wireEncode());
-
- getFace()->onReceiveData.connect(
- [this, command, encodedResultParameters, expectedFaceEvent] (const Data& response) {
- this->callbackDispatch(response,command->getName(), 200, "Success",
- encodedResultParameters, expectedFaceEvent);
- });
-
- onCreated(command->getName(), parameters, dummy);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(didReceiveNotication());
-}
-
-BOOST_FIXTURE_TEST_CASE(OnConnectFailed, AuthorizedCommandFixture<FaceFixture>)
-{
- ControlParameters parameters;
- parameters.setUri("tcp4://127.0.0.1:6363");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("create");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 408, "unit-test-reason");
- });
-
- onConnectFailed(command->getName(), "unit-test-reason");
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_CHECK_EQUAL(didReceiveNotication(), false);
-}
-
-
-BOOST_FIXTURE_TEST_CASE(DestroyFace, AuthorizedCommandFixture<FaceFixture>)
-{
- shared_ptr<DummyFace> dummy(make_shared<DummyFace>());
- FaceTableFixture::m_faceTable.add(dummy);
-
- ControlParameters parameters;
- parameters.setFaceId(dummy->getId());
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/faces");
- commandName.append("destroy");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- ndn::nfd::FaceEventNotification expectedFaceEvent;
- expectedFaceEvent.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
- .setFaceId(dummy->getId())
- .setRemoteUri(dummy->getRemoteUri().toString())
- .setLocalUri(dummy->getLocalUri().toString())
- .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
- .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
-
- getFace()->onReceiveData.connect(
- [this, command, encodedParameters, expectedFaceEvent] (const Data& response) {
- this->callbackDispatch(response,command->getName(), 200, "Success",
- encodedParameters, expectedFaceEvent);
- });
-
- destroyFace(*command, parameters);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(didReceiveNotication());
-}
-
-class FaceListFixture : public FaceStatusPublisherFixture
-{
-public:
- FaceListFixture()
- : m_manager(m_table, m_face, m_testKeyChain)
- {
-
- }
-
- virtual
- ~FaceListFixture()
- {
-
- }
-
-protected:
- FaceManager m_manager;
- ndn::KeyChain m_testKeyChain;
-};
-
-BOOST_FIXTURE_TEST_CASE(TestFaceList, FaceListFixture)
-{
- Name commandName("/localhost/nfd/faces/list");
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- // MAX_SEGMENT_SIZE == 4400, FaceStatus size with filler counters is 75
- // use 59 FaceStatuses to force a FaceStatus to span Data packets
- for (int i = 0; i < 59; i++)
- {
- shared_ptr<TestCountersFace> dummy(make_shared<TestCountersFace>());
-
- uint64_t filler = std::numeric_limits<uint64_t>::max() - 1;
- dummy->setCounters(filler, filler, filler, filler, filler, filler);
-
- m_referenceFaces.push_back(dummy);
-
- add(dummy);
- }
-
- ndn::EncodingBuffer buffer;
-
- m_face->onReceiveData.connect(bind(&FaceStatusPublisherFixture::decodeFaceStatusBlock,
- this, _1));
-
- m_manager.listFaces(*command);
- BOOST_REQUIRE(m_finished);
-}
-
-class ChannelStatusFixture : public FaceManagerFixture
-{
-public:
- void
- validatePublish(const Data& data, const ndn::nfd::ChannelStatus& expectedEntry)
- {
- m_callbackFired = true;
- Block b = data.getContent().blockFromValue();
- ndn::nfd::ChannelStatus entry(b);
- BOOST_CHECK_EQUAL(entry.getLocalUri(), expectedEntry.getLocalUri());
- }
-
- virtual shared_ptr<DummyProtocolFactory>
- addProtocolFactory(const std::string& protocol)
- {
- shared_ptr<DummyProtocolFactory> factory(make_shared<DummyProtocolFactory>());
- m_manager.m_factories[protocol] = factory;
-
- return factory;
- }
-};
-
-BOOST_FIXTURE_TEST_CASE(TestChannelStatus, ChannelStatusFixture)
-{
- shared_ptr<DummyProtocolFactory> factory(addProtocolFactory("dummy"));
- factory->addChannel("dummy://");
-
- Name requestName("/localhost/nfd/faces/channels");
- shared_ptr<Interest> request(make_shared<Interest>(requestName));
-
- ndn::nfd::ChannelStatus expectedEntry;
- expectedEntry.setLocalUri(DummyChannel("dummy://").getUri().toString());
-
- m_face->onReceiveData.connect(bind(&ChannelStatusFixture::validatePublish,
- this, _1, expectedEntry));
-
- m_manager.listChannels(*request);
- BOOST_REQUIRE(m_callbackFired);
-}
-
-class FaceQueryListFixture : public FaceQueryStatusPublisherFixture
-{
-public:
- FaceQueryListFixture()
- : m_manager(m_table, m_face, m_testKeyChain)
- {
-
- }
-
- virtual
- ~FaceQueryListFixture()
- {
-
- }
-
-protected:
- FaceManager m_manager;
- ndn::KeyChain m_testKeyChain;
-};
-
-BOOST_FIXTURE_TEST_CASE(TestValidQueryFilter, FaceQueryListFixture)
-{
- Name queryName("/localhost/nfd/faces/query");
- ndn::nfd::FaceQueryFilter queryFilter;
- queryFilter.setUriScheme("dummy");
- queryName.append(queryFilter.wireEncode());
-
- shared_ptr<Interest> query(make_shared<Interest>(queryName));
-
- // add expected faces
- shared_ptr<DummyLocalFace> expectedFace1(make_shared<DummyLocalFace>());
- m_referenceFaces.push_back(expectedFace1);
- add(expectedFace1);
-
- shared_ptr<DummyFace> expectedFace2(make_shared<DummyFace>());
- m_referenceFaces.push_back(expectedFace2);
- add(expectedFace2);
-
- // add other faces
- shared_ptr<DummyFace> face1(make_shared<DummyFace>("udp://", "udp://"));
- add(face1);
- shared_ptr<DummyLocalFace> face2(make_shared<DummyLocalFace>("tcp://", "tcp://"));
- add(face2);
-
- m_face->onReceiveData.connect(bind(&FaceQueryStatusPublisherFixture::decodeFaceStatusBlock,
- this, _1));
-
- m_manager.listQueriedFaces(*query);
- BOOST_REQUIRE(m_finished);
-}
-
-BOOST_FIXTURE_TEST_CASE(TestInvalidQueryFilter, FaceQueryListFixture)
-{
- Name queryName("/localhost/nfd/faces/query");
- ndn::nfd::FaceStatus queryFilter;
- queryName.append(queryFilter.wireEncode());
-
- shared_ptr<Interest> query(make_shared<Interest>(queryName));
-
- shared_ptr<DummyLocalFace> face(make_shared<DummyLocalFace>());
- add(face);
-
- m_face->onReceiveData.connect(bind(&FaceQueryStatusPublisherFixture::decodeNackBlock, this, _1));
-
- m_manager.listQueriedFaces(*query);
- BOOST_REQUIRE(m_finished);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
+BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
+BOOST_AUTO_TEST_SUITE_END() // Mgmt
} // namespace tests
} // namespace nfd
diff --git a/tests/daemon/mgmt/face-query-status-publisher-common.hpp b/tests/daemon/mgmt/face-query-status-publisher-common.hpp
deleted file mode 100644
index 09582c9..0000000
--- a/tests/daemon/mgmt/face-query-status-publisher-common.hpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_TESTS_NFD_MGMT_FACE_QUERY_STATUS_PUBLISHER_COMMON_HPP
-#define NFD_TESTS_NFD_MGMT_FACE_QUERY_STATUS_PUBLISHER_COMMON_HPP
-
-#include "mgmt/face-query-status-publisher.hpp"
-#include "mgmt/app-face.hpp"
-#include "mgmt/internal-face.hpp"
-#include "fw/forwarder.hpp"
-#include "face/udp-factory.hpp"
-
-#include "tests/test-common.hpp"
-#include "tests/daemon/face/dummy-face.hpp"
-
-#include <ndn-cxx/management/nfd-face-status.hpp>
-
-namespace nfd {
-namespace tests {
-
-class FaceQueryStatusPublisherFixture : public BaseFixture
-{
-public:
-
- FaceQueryStatusPublisherFixture()
- : m_table(m_forwarder)
- , m_face(make_shared<InternalFace>())
- , m_dummyFace(make_shared<DummyFace>())
- , m_dummyLocalFace(make_shared<DummyLocalFace>())
- , m_dummyUri(make_shared<DummyFace>("dummy://remoteUri", "dummy://localUri"))
- , m_factory(UdpFactory())
- , m_finished(false)
- {
- }
-
- virtual
- ~FaceQueryStatusPublisherFixture()
- {
- }
-
- void
- add(shared_ptr<Face> face)
- {
- m_table.add(face);
- }
-
- void
- validateFaceStatus(const Block& statusBlock, const shared_ptr<Face>& reference)
- {
- ndn::nfd::FaceStatus status;
- BOOST_REQUIRE_NO_THROW(status.wireDecode(statusBlock));
-
- BOOST_CHECK_EQUAL(status.getFaceId(), reference->getId());
- BOOST_CHECK_EQUAL(status.getRemoteUri(), reference->getRemoteUri().toString());
- BOOST_CHECK_EQUAL(status.getLocalUri(), reference->getLocalUri().toString());
-
- if (reference->isLocal()) {
- BOOST_CHECK_EQUAL(status.getFaceScope(), ndn::nfd::FACE_SCOPE_LOCAL);
- }
- else {
- BOOST_CHECK_EQUAL(status.getFaceScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
- }
-
- BOOST_CHECK_EQUAL(status.getFacePersistency(), reference->getPersistency());
-
- if (reference->isMultiAccess()) {
- BOOST_CHECK_EQUAL(status.getLinkType(), ndn::nfd::LINK_TYPE_MULTI_ACCESS);
- }
- else {
- BOOST_CHECK_EQUAL(status.getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
- }
- }
-
- void
- decodeFaceStatusBlock(const Data& data)
- {
- BOOST_REQUIRE_EQUAL(data.getContentType(), tlv::ContentType_Blob);
-
- Block payload = data.getContent();
- m_buffer.appendByteArray(payload.value(), payload.value_size());
-
- BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
- if (data.getFinalBlockId() != data.getName()[-1]) {
- return;
- }
-
- // wrap the Face Statuses in a single Content TLV for easy parsing
- m_buffer.prependVarNumber(m_buffer.size());
- m_buffer.prependVarNumber(tlv::Content);
-
- ndn::Block parser(m_buffer.buf(), m_buffer.size());
- parser.parse();
-
- BOOST_REQUIRE_EQUAL(parser.elements_size(), m_referenceFaces.size());
-
- std::list<shared_ptr<Face> >::const_iterator iReference = m_referenceFaces.begin();
- for (Block::element_const_iterator i = parser.elements_begin();
- i != parser.elements_end();
- ++i) {
- if (i->type() != ndn::tlv::nfd::FaceStatus) {
- BOOST_FAIL("expected face status, got type #" << i->type());
- }
- validateFaceStatus(*i, *iReference);
- ++iReference;
- }
- m_finished = true;
- }
-
- void
- decodeNackBlock(const Data& data)
- {
- BOOST_REQUIRE_EQUAL(data.getContentType(), tlv::ContentType_Nack);
-
- m_finished = true;
- }
-
-protected:
- Forwarder m_forwarder;
- FaceTable m_table;
- shared_ptr<InternalFace> m_face;
- ndn::EncodingBuffer m_buffer;
- std::list<shared_ptr<Face> > m_referenceFaces;
- ndn::KeyChain m_keyChain;
- shared_ptr<DummyFace> m_dummyFace;
- shared_ptr<DummyLocalFace> m_dummyLocalFace;
- shared_ptr<DummyFace> m_dummyUri;
- UdpFactory m_factory;
-
-protected:
- bool m_finished;
-};
-
-} // namespace tests
-} // namespace nfd
-
-#endif // NFD_TESTS_NFD_MGMT_FACE_QUERY_STATUS_PUBLISHER_COMMON_HPP
diff --git a/tests/daemon/mgmt/face-query-status-publisher.t.cpp b/tests/daemon/mgmt/face-query-status-publisher.t.cpp
deleted file mode 100644
index 09f6804..0000000
--- a/tests/daemon/mgmt/face-query-status-publisher.t.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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 "face-query-status-publisher-common.hpp"
-
-namespace nfd {
-namespace tests {
-
-BOOST_FIXTURE_TEST_SUITE(MgmtFaceQueryStatusPublisher, FaceQueryStatusPublisherFixture)
-
-BOOST_AUTO_TEST_CASE(NoConditionFilter)
-{
- // filter without conditions matches all faces
- ndn::nfd::FaceQueryFilter filter;
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
-
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), true);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyLocalFace), true);
-}
-
-BOOST_AUTO_TEST_CASE(AllConditionFilter)
-{
- ndn::nfd::FaceQueryFilter filter;
- filter.setUriScheme("dummy")
- .setRemoteUri("dummy://")
- .setLocalUri("dummy://")
- .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
- .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
- .setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
-
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), true);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyLocalFace), false);
-}
-
-BOOST_AUTO_TEST_CASE(UriSchemeFilter)
-{
- ndn::nfd::FaceQueryFilter filter;
- filter.setUriScheme("dummyurischeme");
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), false);
- auto dummyUriScheme = make_shared<DummyFace>("dummyurischeme://", "dummyurischeme://");
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(dummyUriScheme), true);
-}
-
-BOOST_AUTO_TEST_CASE(RemoteUriFilter)
-{
- ndn::nfd::FaceQueryFilter filter;
- filter.setRemoteUri("dummy://remoteUri");
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), false);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyUri), true);
-}
-
-BOOST_AUTO_TEST_CASE(LocalUriFilter)
-{
- ndn::nfd::FaceQueryFilter filter;
- filter.setLocalUri("dummy://localUri");
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), false);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyUri), true);
-}
-
-
-BOOST_AUTO_TEST_CASE(LinkTypeFilter)
-{
- shared_ptr<MulticastUdpFace> multicastFace = m_factory.createMulticastFace("0.0.0.0",
- "224.0.0.1",
- "20070");
- ndn::nfd::FaceQueryFilter filter;
- filter.setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS);
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), false);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(multicastFace), true);
-}
-
-BOOST_AUTO_TEST_CASE(PersistencyFilter)
-{
- shared_ptr<MulticastUdpFace> multicastFace = m_factory.createMulticastFace("0.0.0.0",
- "224.0.0.1",
- "20070");
- ndn::nfd::FaceQueryFilter filter;
- filter.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
- FaceQueryStatusPublisher faceQueryStatusPublisher(m_table, *m_face,
- "/localhost/nfd/FaceStatusPublisherFixture",
- filter, m_keyChain);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(m_dummyFace), false);
- multicastFace->setPersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
- BOOST_CHECK_EQUAL(faceQueryStatusPublisher.doesMatchFilter(multicastFace), true);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/daemon/mgmt/face-status-publisher-common.hpp b/tests/daemon/mgmt/face-status-publisher-common.hpp
deleted file mode 100644
index 882c976..0000000
--- a/tests/daemon/mgmt/face-status-publisher-common.hpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_TESTS_NFD_MGMT_FACE_STATUS_PUBLISHER_COMMON_HPP
-#define NFD_TESTS_NFD_MGMT_FACE_STATUS_PUBLISHER_COMMON_HPP
-
-#include "mgmt/face-status-publisher.hpp"
-#include "mgmt/app-face.hpp"
-#include "mgmt/internal-face.hpp"
-#include "fw/forwarder.hpp"
-
-#include "tests/test-common.hpp"
-#include "tests/daemon/face/dummy-face.hpp"
-
-#include <ndn-cxx/management/nfd-face-status.hpp>
-
-namespace nfd {
-namespace tests {
-
-class TestCountersFace : public DummyFace
-{
-public:
-
- TestCountersFace()
- {
- }
-
- virtual
- ~TestCountersFace()
- {
- }
-
- void
- setCounters(PacketCounter::rep nInInterests,
- PacketCounter::rep nInDatas,
- PacketCounter::rep nOutInterests,
- PacketCounter::rep nOutDatas,
- ByteCounter::rep nInBytes,
- ByteCounter::rep nOutBytes)
- {
- FaceCounters& counters = getMutableCounters();
- counters.getNInInterests().set(nInInterests);
- counters.getNInDatas().set(nInDatas);
- counters.getNOutInterests().set(nOutInterests);
- counters.getNOutDatas().set(nOutDatas);
- counters.getNInBytes().set(nInBytes);
- counters.getNOutBytes().set(nOutBytes);
- }
-
-
-};
-
-static inline uint64_t
-readNonNegativeIntegerType(const Block& block,
- uint32_t type)
-{
- if (block.type() == type)
- {
- return readNonNegativeInteger(block);
- }
- std::stringstream error;
- error << "expected type " << type << " got " << block.type();
- BOOST_THROW_EXCEPTION(tlv::Error(error.str()));
-}
-
-static inline uint64_t
-checkedReadNonNegativeIntegerType(Block::element_const_iterator& i,
- Block::element_const_iterator end,
- uint32_t type)
-{
- if (i != end)
- {
- const Block& block = *i;
- ++i;
- return readNonNegativeIntegerType(block, type);
- }
- BOOST_THROW_EXCEPTION(tlv::Error("Unexpected end of FaceStatus"));
-}
-
-class FaceStatusPublisherFixture : public BaseFixture
-{
-public:
-
- FaceStatusPublisherFixture()
- : m_table(m_forwarder)
- , m_face(make_shared<InternalFace>())
- , m_publisher(m_table, *m_face, "/localhost/nfd/FaceStatusPublisherFixture", m_keyChain)
- , m_finished(false)
- {
-
- }
-
- virtual
- ~FaceStatusPublisherFixture()
- {
-
- }
-
- void
- add(shared_ptr<Face> face)
- {
- m_table.add(face);
- }
-
- void
- validateFaceStatus(const Block& statusBlock, const shared_ptr<Face>& reference)
- {
- ndn::nfd::FaceStatus status;
- BOOST_REQUIRE_NO_THROW(status.wireDecode(statusBlock));
- const FaceCounters& counters = reference->getCounters();
-
- BOOST_CHECK_EQUAL(status.getFaceId(), reference->getId());
- BOOST_CHECK_EQUAL(status.getRemoteUri(), reference->getRemoteUri().toString());
- BOOST_CHECK_EQUAL(status.getLocalUri(), reference->getLocalUri().toString());
-
- if (reference->isLocal()) {
- BOOST_CHECK_EQUAL(status.getFaceScope(), ndn::nfd::FACE_SCOPE_LOCAL);
- }
- else {
- BOOST_CHECK_EQUAL(status.getFaceScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
- }
-
- BOOST_CHECK_EQUAL(status.getFacePersistency(), reference->getPersistency());
-
- if (reference->isMultiAccess()) {
- BOOST_CHECK_EQUAL(status.getLinkType(), ndn::nfd::LINK_TYPE_MULTI_ACCESS);
- }
- else {
- BOOST_CHECK_EQUAL(status.getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
- }
-
- BOOST_CHECK_EQUAL(status.getNInInterests(), counters.getNInInterests());
- BOOST_CHECK_EQUAL(status.getNInDatas(), counters.getNInDatas());
- BOOST_CHECK_EQUAL(status.getNOutInterests(), counters.getNOutInterests());
- BOOST_CHECK_EQUAL(status.getNOutDatas(), counters.getNOutDatas());
- BOOST_CHECK_EQUAL(status.getNInBytes(), counters.getNInBytes());
- BOOST_CHECK_EQUAL(status.getNOutBytes(), counters.getNOutBytes());
- }
-
- void
- decodeFaceStatusBlock(const Data& data)
- {
- Block payload = data.getContent();
-
- m_buffer.appendByteArray(payload.value(), payload.value_size());
-
- BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
- if (data.getFinalBlockId() != data.getName()[-1])
- {
- return;
- }
-
- // wrap the Face Statuses in a single Content TLV for easy parsing
- m_buffer.prependVarNumber(m_buffer.size());
- m_buffer.prependVarNumber(tlv::Content);
-
- ndn::Block parser(m_buffer.buf(), m_buffer.size());
- parser.parse();
-
- BOOST_REQUIRE_EQUAL(parser.elements_size(), m_referenceFaces.size());
-
- std::list<shared_ptr<Face> >::const_iterator iReference = m_referenceFaces.begin();
- for (Block::element_const_iterator i = parser.elements_begin();
- i != parser.elements_end();
- ++i)
- {
- if (i->type() != ndn::tlv::nfd::FaceStatus)
- {
- BOOST_FAIL("expected face status, got type #" << i->type());
- }
- validateFaceStatus(*i, *iReference);
- ++iReference;
- }
- m_finished = true;
- }
-
-protected:
- Forwarder m_forwarder;
- FaceTable m_table;
- shared_ptr<InternalFace> m_face;
- FaceStatusPublisher m_publisher;
- ndn::EncodingBuffer m_buffer;
- std::list<shared_ptr<Face> > m_referenceFaces;
- ndn::KeyChain m_keyChain;
-
-protected:
- bool m_finished;
-};
-
-} // namespace tests
-} // namespace nfd
-
-#endif // NFD_TESTS_NFD_MGMT_FACE_STATUS_PUBLISHER_COMMON_HPP
diff --git a/tests/daemon/mgmt/face-status-publisher.t.cpp b/tests/daemon/mgmt/face-status-publisher.t.cpp
deleted file mode 100644
index 383dba8..0000000
--- a/tests/daemon/mgmt/face-status-publisher.t.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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 "face-status-publisher-common.hpp"
-
-namespace nfd {
-namespace tests {
-
-BOOST_FIXTURE_TEST_SUITE(MgmtFaceStatusPublisher, FaceStatusPublisherFixture)
-
-BOOST_AUTO_TEST_CASE(EncodingDecoding)
-{
- Name commandName("/localhost/nfd/faces/list");
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- // MAX_SEGMENT_SIZE == 4400, FaceStatus size with filler counters is 75
- // use 59 FaceStatuses to force a FaceStatus to span Data packets
- for (int i = 0; i < 59; i++)
- {
- shared_ptr<TestCountersFace> dummy(make_shared<TestCountersFace>());
-
- uint64_t filler = std::numeric_limits<uint64_t>::max() - 1;
- dummy->setCounters(filler, filler, filler, filler, filler, filler);
-
- m_referenceFaces.push_back(dummy);
-
- add(dummy);
- }
-
- ndn::EncodingBuffer buffer;
-
- m_face->onReceiveData.connect(
- bind(&FaceStatusPublisherFixture::decodeFaceStatusBlock, this, _1));
-
- m_publisher.publish();
- BOOST_REQUIRE(m_finished);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/daemon/mgmt/fib-enumeration-publisher-common.hpp b/tests/daemon/mgmt/fib-enumeration-publisher-common.hpp
deleted file mode 100644
index 9f9150b..0000000
--- a/tests/daemon/mgmt/fib-enumeration-publisher-common.hpp
+++ /dev/null
@@ -1,221 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, 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/>.
- */
-
-#ifndef NFD_TESTS_NFD_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
-#define NFD_TESTS_NFD_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
-
-#include "mgmt/fib-enumeration-publisher.hpp"
-
-#include "mgmt/app-face.hpp"
-#include "mgmt/internal-face.hpp"
-#include "table/fib.hpp"
-#include "table/name-tree.hpp"
-
-#include "tests/test-common.hpp"
-#include "../face/dummy-face.hpp"
-
-#include <ndn-cxx/encoding/tlv.hpp>
-
-namespace nfd {
-namespace tests {
-
-static inline uint64_t
-readNonNegativeIntegerType(const Block& block,
- uint32_t type)
-{
- if (block.type() == type)
- {
- return readNonNegativeInteger(block);
- }
- std::stringstream error;
- error << "Expected type " << type << " got " << block.type();
- BOOST_THROW_EXCEPTION(tlv::Error(error.str()));
-}
-
-static inline uint64_t
-checkedReadNonNegativeIntegerType(Block::element_const_iterator& i,
- Block::element_const_iterator end,
- uint32_t type)
-{
- if (i != end)
- {
- const Block& block = *i;
- ++i;
- return readNonNegativeIntegerType(block, type);
- }
- std::stringstream error;
- error << "Unexpected end of Block while attempting to read type #"
- << type;
- BOOST_THROW_EXCEPTION(tlv::Error(error.str()));
-}
-
-class FibEnumerationPublisherFixture : public BaseFixture
-{
-public:
-
- FibEnumerationPublisherFixture()
- : m_fib(m_nameTree)
- , m_face(make_shared<InternalFace>())
- , m_publisher(m_fib, *m_face, "/localhost/nfd/FibEnumerationPublisherFixture", m_keyChain)
- , m_finished(false)
- {
- }
-
- virtual
- ~FibEnumerationPublisherFixture()
- {
- }
-
- bool
- hasNextHopWithCost(const fib::NextHopList& nextHops,
- FaceId faceId,
- uint64_t cost)
- {
- for (fib::NextHopList::const_iterator i = nextHops.begin();
- i != nextHops.end();
- ++i)
- {
- if (i->getFace()->getId() == faceId && i->getCost() == cost)
- {
- return true;
- }
- }
- return false;
- }
-
- bool
- entryHasPrefix(const shared_ptr<fib::Entry> entry, const Name& prefix)
- {
- return entry->getPrefix() == prefix;
- }
-
- void
- validateFibEntry(const Block& entry)
- {
- entry.parse();
-
- Block::element_const_iterator i = entry.elements_begin();
- BOOST_REQUIRE(i != entry.elements_end());
-
-
- BOOST_REQUIRE(i->type() == tlv::Name);
- Name prefix(*i);
- ++i;
-
- std::set<shared_ptr<fib::Entry> >::const_iterator referenceIter =
- std::find_if(m_referenceEntries.begin(), m_referenceEntries.end(),
- bind(&FibEnumerationPublisherFixture::entryHasPrefix,
- this, _1, prefix));
-
- BOOST_REQUIRE(referenceIter != m_referenceEntries.end());
-
- const shared_ptr<fib::Entry>& reference = *referenceIter;
- BOOST_REQUIRE_EQUAL(prefix, reference->getPrefix());
-
- // 0 or more next hop records
- size_t nRecords = 0;
- const fib::NextHopList& referenceNextHops = reference->getNextHops();
- for (; i != entry.elements_end(); ++i)
- {
- const ndn::Block& nextHopRecord = *i;
- BOOST_REQUIRE(nextHopRecord.type() == ndn::tlv::nfd::NextHopRecord);
- nextHopRecord.parse();
-
- Block::element_const_iterator j = nextHopRecord.elements_begin();
-
- FaceId faceId =
- checkedReadNonNegativeIntegerType(j,
- entry.elements_end(),
- ndn::tlv::nfd::FaceId);
-
- uint64_t cost =
- checkedReadNonNegativeIntegerType(j,
- entry.elements_end(),
- ndn::tlv::nfd::Cost);
-
- BOOST_REQUIRE(hasNextHopWithCost(referenceNextHops, faceId, cost));
-
- BOOST_REQUIRE(j == nextHopRecord.elements_end());
- nRecords++;
- }
- BOOST_REQUIRE_EQUAL(nRecords, referenceNextHops.size());
-
- BOOST_REQUIRE(i == entry.elements_end());
- m_referenceEntries.erase(referenceIter);
- }
-
- void
- decodeFibEntryBlock(const Data& data)
- {
- Block payload = data.getContent();
-
- m_buffer.appendByteArray(payload.value(), payload.value_size());
-
- BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
- if (data.getFinalBlockId() != data.getName()[-1])
- {
- return;
- }
-
- // wrap the FIB Entry blocks in a single Content TLV for easy parsing
- m_buffer.prependVarNumber(m_buffer.size());
- m_buffer.prependVarNumber(tlv::Content);
-
- ndn::Block parser(m_buffer.buf(), m_buffer.size());
- parser.parse();
-
- BOOST_REQUIRE_EQUAL(parser.elements_size(), m_referenceEntries.size());
-
- for (Block::element_const_iterator i = parser.elements_begin();
- i != parser.elements_end();
- ++i)
- {
- if (i->type() != ndn::tlv::nfd::FibEntry)
- {
- BOOST_FAIL("expected fib entry, got type #" << i->type());
- }
-
- validateFibEntry(*i);
- }
- m_finished = true;
- }
-
-protected:
- NameTree m_nameTree;
- Fib m_fib;
- shared_ptr<InternalFace> m_face;
- FibEnumerationPublisher m_publisher;
- ndn::EncodingBuffer m_buffer;
- std::set<shared_ptr<fib::Entry> > m_referenceEntries;
- ndn::KeyChain m_keyChain;
-
-protected:
- bool m_finished;
-};
-
-} // namespace tests
-} // namespace nfd
-
-#endif // NFD_TESTS_NFD_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
diff --git a/tests/daemon/mgmt/fib-enumeration-publisher.t.cpp b/tests/daemon/mgmt/fib-enumeration-publisher.t.cpp
deleted file mode 100644
index 34cb582..0000000
--- a/tests/daemon/mgmt/fib-enumeration-publisher.t.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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 "mgmt/fib-enumeration-publisher.hpp"
-
-#include "mgmt/app-face.hpp"
-#include "mgmt/internal-face.hpp"
-
-#include "tests/test-common.hpp"
-#include "../face/dummy-face.hpp"
-
-#include "fib-enumeration-publisher-common.hpp"
-
-#include <ndn-cxx/encoding/tlv.hpp>
-
-namespace nfd {
-namespace tests {
-
-BOOST_FIXTURE_TEST_SUITE(MgmtFibEnumerationPublisher, FibEnumerationPublisherFixture)
-
-BOOST_AUTO_TEST_CASE(TestFibEnumerationPublisher)
-{
- for (int i = 0; i < 87; i++)
- {
- Name prefix("/test");
- prefix.appendSegment(i);
-
- shared_ptr<DummyFace> dummy1(make_shared<DummyFace>());
- shared_ptr<DummyFace> dummy2(make_shared<DummyFace>());
-
- shared_ptr<fib::Entry> entry = m_fib.insert(prefix).first;
- entry->addNextHop(dummy1, std::numeric_limits<uint64_t>::max() - 1);
- entry->addNextHop(dummy2, std::numeric_limits<uint64_t>::max() - 2);
-
- m_referenceEntries.insert(entry);
- }
- for (int i = 0; i < 2; i++)
- {
- Name prefix("/test2");
- prefix.appendSegment(i);
-
- shared_ptr<DummyFace> dummy1(make_shared<DummyFace>());
- shared_ptr<DummyFace> dummy2(make_shared<DummyFace>());
-
- shared_ptr<fib::Entry> entry = m_fib.insert(prefix).first;
- entry->addNextHop(dummy1, std::numeric_limits<uint8_t>::max() - 1);
- entry->addNextHop(dummy2, std::numeric_limits<uint8_t>::max() - 2);
-
- m_referenceEntries.insert(entry);
- }
-
- ndn::EncodingBuffer buffer;
-
- m_face->onReceiveData.connect(
- bind(&FibEnumerationPublisherFixture::decodeFibEntryBlock, this, _1));
-
- m_publisher.publish();
- BOOST_REQUIRE(m_finished);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/daemon/mgmt/fib-manager.t.cpp b/tests/daemon/mgmt/fib-manager.t.cpp
index 82e70b9..513536c 100644
--- a/tests/daemon/mgmt/fib-manager.t.cpp
+++ b/tests/daemon/mgmt/fib-manager.t.cpp
@@ -22,904 +22,470 @@
* 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 "mgmt/fib-manager.hpp"
-#include "table/fib.hpp"
+
+#include "manager-common-fixture.hpp"
#include "table/fib-nexthop.hpp"
-#include "face/face.hpp"
-#include "mgmt/internal-face.hpp"
-#include "tests/daemon/face/dummy-face.hpp"
-
-#include "validation-common.hpp"
-#include "tests/test-common.hpp"
-
-#include "fib-enumeration-publisher-common.hpp"
+#include "../face/dummy-face.hpp"
+#include <ndn-cxx/management/nfd-fib-entry.hpp>
namespace nfd {
namespace tests {
-NFD_LOG_INIT("FibManagerTest");
-
-class FibManagerFixture : public FibEnumerationPublisherFixture
+class FibManagerFixture : public ManagerCommonFixture
{
public:
-
- virtual
- ~FibManagerFixture()
- {
- }
-
- shared_ptr<Face>
- getFace(FaceId id)
- {
- if (id > 0 && static_cast<size_t>(id) <= m_faces.size())
- {
- return m_faces[id - 1];
- }
- NFD_LOG_DEBUG("No face found returning NULL");
- return shared_ptr<DummyFace>();
- }
-
- void
- addFace(shared_ptr<Face> face)
- {
- m_faces.push_back(face);
- }
-
- void
- validateControlResponseCommon(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- ControlResponse& control)
- {
- m_callbackFired = true;
- Block controlRaw = response.getContent().blockFromValue();
-
- control.wireDecode(controlRaw);
-
- // NFD_LOG_DEBUG("received control response"
- // << " Name: " << response.getName()
- // << " code: " << control.getCode()
- // << " text: " << control.getText());
-
- BOOST_CHECK_EQUAL(response.getName(), expectedName);
- BOOST_CHECK_EQUAL(control.getCode(), expectedCode);
- BOOST_CHECK_EQUAL(control.getText(), expectedText);
- }
-
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText)
- {
- ControlResponse control;
- validateControlResponseCommon(response, expectedName,
- expectedCode, expectedText, control);
-
- if (!control.getBody().empty())
- {
- BOOST_FAIL("found unexpected control response body");
- }
- }
-
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- const Block& expectedBody)
- {
- ControlResponse control;
- validateControlResponseCommon(response, expectedName,
- expectedCode, expectedText, control);
-
- BOOST_REQUIRE(!control.getBody().empty());
- BOOST_REQUIRE_EQUAL(control.getBody().value_size(), expectedBody.value_size());
-
- BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
- expectedBody.value_size()) == 0);
-
- }
-
- bool
- didCallbackFire()
- {
- return m_callbackFired;
- }
-
- void
- resetCallbackFired()
- {
- m_callbackFired = false;
- }
-
- shared_ptr<InternalFace>
- getInternalFace()
- {
- return m_face;
- }
-
- FibManager&
- getFibManager()
- {
- return m_manager;
- }
-
- Fib&
- getFib()
- {
- return m_fib;
- }
-
- void
- addInterestRule(const std::string& regex,
- ndn::IdentityCertificate& certificate)
- {
- m_manager.addInterestRule(regex, certificate);
- }
-
-protected:
FibManagerFixture()
- : m_manager(ref(m_fib), bind(&FibManagerFixture::getFace, this, _1), m_face, m_keyChain)
- , m_callbackFired(false)
+ : m_fib(m_forwarder.getFib())
+ , m_faceTable(m_forwarder.getFaceTable())
+ , m_manager(m_fib, bind(&Forwarder::getFace, &m_forwarder, _1), m_dispatcher, m_validator)
{
+ setTopPrefixAndPrivilege("/localhost/nfd", "fib");
+ }
+
+public: // for test
+ ControlParameters
+ makeParameters(const Name& name, const FaceId& id)
+ {
+ return ControlParameters().setName(name).setFaceId(id);
+ }
+
+ ControlParameters
+ makeParameters(const Name& name, const FaceId& id, const uint32_t& cost)
+ {
+ return ControlParameters().setName(name).setFaceId(id).setCost(cost);
+ }
+
+ FaceId
+ addFace()
+ {
+ auto face = make_shared<DummyFace>();
+ m_faceTable.add(face);
+ advanceClocks(time::milliseconds(1), 10);
+ m_responses.clear(); // clear all event notifications, if any
+ return face->getId();
+ }
+
+public: // for check
+ enum class CheckNextHopResult
+ {
+ OK,
+ NO_FIB_ENTRY,
+ WRONG_N_NEXTHOPS,
+ NO_NEXTHOP,
+ WRONG_COST
+ };
+
+ /**
+ * @brief check whether the nexthop record is added / removed properly
+ *
+ * @param expectedNNextHops use -1 to skip this check
+ * @param faceId use FACEID_NULL to skip NextHopRecord checks
+ * @param expectedCost use -1 to skip this check
+ *
+ * @retval OK FIB entry is found by exact match and has the expected number of nexthops;
+ * NextHopRe record for faceId is found and has the expected cost
+ * @retval NO_FIB_ENTRY FIB entry is not found
+ * @retval WRONG_N_NEXTHOPS FIB entry is found but has wrong number of nexthops
+ * @retval NO_NEXTHOP NextHopRecord for faceId is not found
+ * @retval WRONG_COST NextHopRecord for faceId has wrong cost
+ */
+ CheckNextHopResult
+ checkNextHop(const Name& prefix, ssize_t expectedNNextHops = -1,
+ FaceId faceId = FACEID_NULL, int32_t expectedCost = -1)
+ {
+ auto entry = m_fib.findExactMatch(prefix);
+ if (!static_cast<bool>(entry)) {
+ return CheckNextHopResult::NO_FIB_ENTRY;
+ }
+
+ auto nextHops = entry->getNextHops();
+ if (expectedNNextHops != -1 && nextHops.size() != static_cast<size_t>(expectedNNextHops)) {
+ return CheckNextHopResult::WRONG_N_NEXTHOPS;
+ }
+
+ if (faceId != FACEID_NULL) {
+ for (auto&& record : nextHops) {
+ if (record.getFace()->getId() == faceId) {
+ return expectedCost != -1 && record.getCost() != static_cast<uint32_t>(expectedCost) ?
+ CheckNextHopResult::WRONG_COST : CheckNextHopResult::OK;
+ }
+ }
+
+ return CheckNextHopResult::NO_NEXTHOP;
+ }
+
+ return CheckNextHopResult::OK;
}
protected:
+ Fib& m_fib;
+ FaceTable& m_faceTable;
FibManager m_manager;
-
- std::vector<shared_ptr<Face> > m_faces;
- bool m_callbackFired;
- ndn::KeyChain m_keyChain;
};
-template <typename T>
-class AuthorizedCommandFixture : public CommandFixture<T>
+std::ostream&
+operator<<(std::ostream &os, const FibManagerFixture::CheckNextHopResult& result)
{
-public:
- AuthorizedCommandFixture()
- {
- const std::string regex = "^<localhost><nfd><fib>";
- T::addInterestRule(regex, *CommandFixture<T>::m_certificate);
- }
+ switch (result) {
+ case FibManagerFixture::CheckNextHopResult::OK:
+ os << "OK";
+ break;
+ case FibManagerFixture::CheckNextHopResult::NO_FIB_ENTRY:
+ os << "NO_FIB_ENTRY";
+ break;
+ case FibManagerFixture::CheckNextHopResult::WRONG_N_NEXTHOPS:
+ os << "WRONG_N_NEXTHOPS";
+ break;
+ case FibManagerFixture::CheckNextHopResult::NO_NEXTHOP:
+ os << "NO_NEXTHOP";
+ break;
+ case FibManagerFixture::CheckNextHopResult::WRONG_COST:
+ os << "WRONG_COST";
+ break;
+ default:
+ break;
+ };
- virtual
- ~AuthorizedCommandFixture()
- {
- }
-};
-
-BOOST_FIXTURE_TEST_SUITE(MgmtFibManager, AuthorizedCommandFixture<FibManagerFixture>)
-
-bool
-foundNextHop(FaceId id, uint32_t cost, const fib::NextHop& next)
-{
- return id == next.getFace()->getId() && next.getCost() == cost;
+ return os;
}
-bool
-addedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
-{
- shared_ptr<fib::Entry> entry = fib.findExactMatch(prefix);
+BOOST_FIXTURE_TEST_SUITE(Mgmt, FibManagerFixture)
+BOOST_AUTO_TEST_SUITE(TestFibManager)
- if (static_cast<bool>(entry))
- {
- const fib::NextHopList& hops = entry->getNextHops();
- return hops.size() == oldSize + 1 &&
- std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) != hops.end();
- }
- return false;
-}
-
-bool
-foundNextHopWithFace(FaceId id, uint32_t cost,
- shared_ptr<Face> face, const fib::NextHop& next)
-{
- return id == next.getFace()->getId() && next.getCost() == cost && face == next.getFace();
-}
-
-bool
-addedNextHopWithFace(const Fib& fib, const Name& prefix, size_t oldSize,
- uint32_t cost, shared_ptr<Face> face)
-{
- shared_ptr<fib::Entry> entry = fib.findExactMatch(prefix);
-
- if (static_cast<bool>(entry))
- {
- const fib::NextHopList& hops = entry->getNextHops();
- return hops.size() == oldSize + 1 &&
- std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) != hops.end();
- }
- return false;
-}
-
-BOOST_AUTO_TEST_CASE(ShortName)
-{
- shared_ptr<InternalFace> face = getInternalFace();
-
- shared_ptr<Interest> command = makeInterest("/localhost/nfd/fib");
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- face->sendInterest(*command);
- g_io.run_one();
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(MalformedCommmand)
-{
- shared_ptr<InternalFace> face = getInternalFace();
-
- BOOST_REQUIRE(didCallbackFire() == false);
-
- Interest command("/localhost/nfd/fib");
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command.getName(), 400, "Malformed command");
- });
-
- getFibManager().onFibRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(UnsupportedVerb)
-{
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
- parameters.setCost(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("unsupported");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 501, "Unsupported command");
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(UnsignedCommand)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
- parameters.setCost(101);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- Interest command(commandName);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command.getName(), 401, "Signature required");
- });
-
- getFibManager().onFibRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!addedNextHopWithCost(getFib(), "/hello", 0, 101));
-}
-
-BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand, UnauthorizedCommandFixture<FibManagerFixture>)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
- parameters.setCost(101);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 403, "Unauthorized command");
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(!addedNextHopWithCost(getFib(), "/hello", 0, 101));
-}
-
-BOOST_AUTO_TEST_CASE(BadOptionParse)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append("NotReallyParameters");
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
+BOOST_AUTO_TEST_SUITE(AddNextHop)
BOOST_AUTO_TEST_CASE(UnknownFaceId)
{
- addFace(make_shared<DummyFace>());
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/add-nexthop",
+ makeParameters("hello", FACEID_NULL, 101));
+ receiveInterest(command);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
- shared_ptr<InternalFace> face = getInternalFace();
+ // check response
+ BOOST_CHECK_EQUAL(checkResponse(0, command->getName(), ControlResponse(410, "Face not found")),
+ CheckResponseResult::OK);
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1000);
- parameters.setCost(101);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 410, "Face not found");
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101) == false);
+ // double check that the next hop was not added
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", -1, FACEID_NULL, 101), CheckNextHopResult::NO_FIB_ENTRY);
}
-BOOST_AUTO_TEST_CASE(AddNextHopVerbImplicitFaceId)
+BOOST_AUTO_TEST_CASE(ImplicitFaceId)
{
- addFace(make_shared<DummyFace>());
+ auto face1 = addFace();
+ auto face2 = addFace();
+ BOOST_REQUIRE(face1 != INVALID_FACEID && face2 != INVALID_FACEID);
- shared_ptr<InternalFace> face = getInternalFace();
+ Name expectedName;
+ ControlResponse expectedResponse;
+ auto testAddNextHop = [&] (ControlParameters parameters, const FaceId& faceId) {
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/add-nexthop", parameters,
+ [&faceId] (shared_ptr<Interest> interest) {
+ interest->setIncomingFaceId(faceId);
+ });
+ m_responses.clear();
+ expectedName = command->getName();
+ expectedResponse = makeResponse(200, "Success", parameters.setFaceId(faceId));
+ receiveInterest(command);
+ };
- std::vector<ControlParameters> testedParameters;
- testedParameters.push_back(ControlParameters().setName("/hello").setCost(101).setFaceId(0));
- testedParameters.push_back(ControlParameters().setName("/hello").setCost(101));
+ testAddNextHop(ControlParameters().setName("/hello").setCost(100).setFaceId(0), face1);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, face1, 100), CheckNextHopResult::OK);
- for (std::vector<ControlParameters>::iterator parameters = testedParameters.begin();
- parameters != testedParameters.end(); ++parameters) {
-
- Block encodedParameters(parameters->wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- ControlParameters expectedParameters;
- expectedParameters.setName("/hello");
- expectedParameters.setFaceId(1);
- expectedParameters.setCost(101);
-
- Block encodedExpectedParameters(expectedParameters.wireEncode());
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- command->setIncomingFaceId(1);
- generateCommand(*command);
-
- signal::Connection conn = face->onReceiveData.connect(
- [this, command, encodedExpectedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedExpectedParameters);
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(addedNextHopWithFace(getFib(), "/hello", 0, 101, getFace(1)));
-
- conn.disconnect();
- getFib().erase("/hello");
- BOOST_REQUIRE_EQUAL(getFib().size(), 0);
- }
+ testAddNextHop(ControlParameters().setName("/hello").setCost(100), face2);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 2, face2, 100), CheckNextHopResult::OK);
}
-BOOST_AUTO_TEST_CASE(AddNextHopVerbInitialAdd)
+BOOST_AUTO_TEST_CASE(InitialAdd)
{
- addFace(make_shared<DummyFace>());
+ FaceId addedFaceId = addFace();
+ BOOST_REQUIRE(addedFaceId != INVALID_FACEID);
- shared_ptr<InternalFace> face = getInternalFace();
+ auto parameters = makeParameters("hello", addedFaceId, 101);
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/add-nexthop", parameters);
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
- parameters.setCost(101);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101));
+ receiveInterest(command);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, command->getName(), makeResponse(200, "Success", parameters)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, addedFaceId, 101), CheckNextHopResult::OK);
}
-BOOST_AUTO_TEST_CASE(AddNextHopVerbImplicitCost)
+BOOST_AUTO_TEST_CASE(ImplicitCost)
{
- addFace(make_shared<DummyFace>());
+ FaceId addedFaceId = addFace();
+ BOOST_REQUIRE(addedFaceId != INVALID_FACEID);
- shared_ptr<InternalFace> face = getInternalFace();
+ auto originalParameters = ControlParameters().setName("/hello").setFaceId(addedFaceId);
+ auto parameters = makeParameters("/hello", addedFaceId, 0);
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/add-nexthop", originalParameters);
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- ControlParameters resultParameters;
- resultParameters.setName("/hello");
- resultParameters.setFaceId(1);
- resultParameters.setCost(0);
-
- face->onReceiveData.connect([this, command, resultParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", resultParameters.wireEncode());
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
- BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 0));
+ receiveInterest(command);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, command->getName(), makeResponse(200, "Success", parameters)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, addedFaceId, 0), CheckNextHopResult::OK);
}
-BOOST_AUTO_TEST_CASE(AddNextHopVerbAddToExisting)
+BOOST_AUTO_TEST_CASE(AddToExisting)
{
- addFace(make_shared<DummyFace>());
- shared_ptr<InternalFace> face = getInternalFace();
+ FaceId face = addFace();
+ BOOST_CHECK(face != INVALID_FACEID);
- for (int i = 1; i <= 2; i++)
- {
+ Name expectedName;
+ ControlResponse expectedResponse;
+ auto testAddNextHop = [&] (const ControlParameters& parameters) {
+ m_responses.clear();
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/add-nexthop", parameters);
+ expectedName = command->getName();
+ expectedResponse = makeResponse(200, "Success", parameters);
+ receiveInterest(command);
+ };
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
- parameters.setCost(100 + i);
+ // add initial, succeeds
+ testAddNextHop(makeParameters("/hello", face, 101));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
- Block encodedParameters(parameters.wireEncode());
+ // add to existing --> update cost, succeeds
+ testAddNextHop(makeParameters("/hello", face, 102));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- signal::Connection conn = face->onReceiveData.connect(
- [this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getFibManager().onFibRequest(*command);
- BOOST_REQUIRE(didCallbackFire());
- resetCallbackFired();
-
- shared_ptr<fib::Entry> entry = getFib().findExactMatch("/hello");
-
- if (static_cast<bool>(entry))
- {
- const fib::NextHopList& hops = entry->getNextHops();
- BOOST_REQUIRE(hops.size() == 1);
- BOOST_REQUIRE(std::find_if(hops.begin(), hops.end(),
- bind(&foundNextHop, -1, 100 + i, _1)) != hops.end());
-
- }
- else
- {
- BOOST_FAIL("Failed to find expected fib entry");
- }
-
- conn.disconnect();
- }
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 2, face, 102), CheckNextHopResult::WRONG_N_NEXTHOPS);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, face, 101), CheckNextHopResult::WRONG_COST);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, face, 102), CheckNextHopResult::OK);
}
-BOOST_AUTO_TEST_CASE(AddNextHopVerbUpdateFaceCost)
+BOOST_AUTO_TEST_SUITE_END() // AddNextHop
+
+BOOST_AUTO_TEST_SUITE(RemoveNextHop)
+
+BOOST_AUTO_TEST_CASE(Basic)
{
- addFace(make_shared<DummyFace>());
- shared_ptr<InternalFace> face = getInternalFace();
+ Name expectedName;
+ ControlResponse expectedResponse;
+ auto testRemoveNextHop = [&] (const ControlParameters& parameters) {
+ m_responses.clear();
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/remove-nexthop", parameters);
+ expectedName = command->getName();
+ expectedResponse = makeResponse(200, "Success", parameters);
+ receiveInterest(command);
+ };
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
+ FaceId face1 = addFace();
+ FaceId face2 = addFace();
+ FaceId face3 = addFace();
+ BOOST_REQUIRE(face1 != INVALID_FACEID && face2 != INVALID_FACEID && face3 != INVALID_FACEID);
+ shared_ptr<fib::Entry> entry = m_fib.insert("/hello").first;
+ entry->addNextHop(m_faceTable.get(face1), 101);
+ entry->addNextHop(m_faceTable.get(face2), 202);
+ entry->addNextHop(m_faceTable.get(face3), 303);
+
+ testRemoveNextHop(makeParameters("/hello", face1));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 2, face1, 101), CheckNextHopResult::NO_NEXTHOP);
+
+ testRemoveNextHop(makeParameters("/hello", face2));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, face2, 202), CheckNextHopResult::NO_NEXTHOP);
+
+ testRemoveNextHop(makeParameters("/hello", face3));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 0, face3, 303), CheckNextHopResult::NO_FIB_ENTRY);
+}
+
+BOOST_AUTO_TEST_CASE(PrefixNotFound)
+{
+ FaceId addedFaceId = addFace();
+ BOOST_CHECK(addedFaceId != INVALID_FACEID);
+
+ auto parameters = makeParameters("hello", addedFaceId);
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/remove-nexthop", parameters);
+ auto response = makeResponse(200, "Success", parameters);
+
+ receiveInterest(command);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, command->getName(), response), CheckResponseResult::OK);
+}
+
+BOOST_AUTO_TEST_CASE(ImplicitFaceId)
+{
+ auto face1 = addFace();
+ auto face2 = addFace();
+ BOOST_REQUIRE(face1 != INVALID_FACEID && face2 != INVALID_FACEID);
+
+ Name expectedName;
+ ControlResponse expectedResponse;
+ auto testWithImplicitFaceId = [&] (ControlParameters parameters, FaceId face) {
+ m_responses.clear();
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/remove-nexthop", parameters,
+ [face] (shared_ptr<Interest> interest) {
+ interest->setIncomingFaceId(face);
+ });
+ expectedName = command->getName();
+ expectedResponse = makeResponse(200, "Success", parameters.setFaceId(face));
+ receiveInterest(command);
+ };
+
+ shared_ptr<fib::Entry> entry = m_fib.insert("/hello").first;
+ entry->addNextHop(m_faceTable.get(face1), 101);
+ entry->addNextHop(m_faceTable.get(face2), 202);
+
+ testWithImplicitFaceId(ControlParameters().setName("/hello").setFaceId(0), face1);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 1, face1, 101), CheckNextHopResult::NO_NEXTHOP);
+
+ testWithImplicitFaceId(ControlParameters().setName("/hello"), face2);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", 0, face2, 202), CheckNextHopResult::NO_FIB_ENTRY);
+}
+
+BOOST_AUTO_TEST_CASE(RecordNotExist)
+{
+ auto face1 = addFace();
+ auto face2 = addFace();
+ BOOST_REQUIRE(face1 != INVALID_FACEID && face2 != INVALID_FACEID);
+
+ Name expectedName;
+ ControlResponse expectedResponse;
+ auto testRemoveNextHop = [&] (ControlParameters parameters) {
+ m_responses.clear();
+ auto command = makeControlCommandRequest("/localhost/nfd/fib/remove-nexthop", parameters);
+ expectedName = command->getName();
+ expectedResponse = makeResponse(200, "Success", parameters);
+ receiveInterest(command);
+ };
+
+ m_fib.insert("/hello").first->addNextHop(m_faceTable.get(face1), 101);
+
+ testRemoveNextHop(makeParameters("/hello", face2 + 100));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1); // face does not exist
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", -1, face2 + 100), CheckNextHopResult::NO_NEXTHOP);
+
+ testRemoveNextHop(makeParameters("/hello", face2));
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1); // record does not exist
+ BOOST_CHECK_EQUAL(checkResponse(0, expectedName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(checkNextHop("/hello", -1, face2), CheckNextHopResult::NO_NEXTHOP);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // RemoveNextHop
+
+// @todo Remove when ndn::nfd::FibEntry implements operator!= and operator<<
+class FibEntry : public ndn::nfd::FibEntry
+{
+public:
+ FibEntry() = default;
+
+ FibEntry(const ndn::nfd::FibEntry& entry)
+ : ndn::nfd::FibEntry(entry)
{
- parameters.setCost(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- signal::Connection conn = face->onReceiveData.connect(
- [this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-
- resetCallbackFired();
- conn.disconnect();
}
-
- {
- parameters.setCost(102);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
- }
-
- shared_ptr<fib::Entry> entry = getFib().findExactMatch("/hello");
-
- // Add faces with cost == FaceID for the name /hello
- // This test assumes:
- // FaceIDs are -1 because we don't add them to a forwarder
- if (static_cast<bool>(entry))
- {
- const fib::NextHopList& hops = entry->getNextHops();
- BOOST_REQUIRE(hops.size() == 1);
- BOOST_REQUIRE(std::find_if(hops.begin(),
- hops.end(),
- bind(&foundNextHop, -1, 102, _1)) != hops.end());
- }
- else
- {
- BOOST_FAIL("Failed to find expected fib entry");
- }
-}
-
-BOOST_AUTO_TEST_CASE(AddNextHopVerbMissingPrefix)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setFaceId(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("add-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
+};
bool
-removedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
+operator!=(const FibEntry& left, const FibEntry& right)
{
- shared_ptr<fib::Entry> entry = fib.findExactMatch(prefix);
+ if (left.getPrefix() != right.getPrefix()) {
+ return true;
+ }
- if (static_cast<bool>(entry))
- {
- const fib::NextHopList& hops = entry->getNextHops();
- return hops.size() == oldSize - 1 &&
- std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) == hops.end();
+ auto leftNextHops = left.getNextHopRecords();
+ auto rightNextHops = right.getNextHopRecords();
+ if (leftNextHops.size() != rightNextHops.size()) {
+ return true;
+ }
+
+ for (auto&& nexthop : leftNextHops) {
+ auto hitEntry =
+ std::find_if(rightNextHops.begin(), rightNextHops.end(), [&] (const ndn::nfd::NextHopRecord& record) {
+ return nexthop.getCost() == record.getCost() && nexthop.getFaceId() == record.getFaceId();
+ });
+
+ if (hitEntry == rightNextHops.end()) {
+ return true;
}
+ }
+
return false;
}
-void
-testRemoveNextHop(CommandFixture<FibManagerFixture>* fixture,
- FibManager& manager,
- Fib& fib,
- shared_ptr<Face> face,
- const Name& targetName,
- FaceId targetFace)
+std::ostream&
+operator<<(std::ostream &os, const FibEntry& entry)
{
- ControlParameters parameters;
- parameters.setName(targetName);
- parameters.setFaceId(targetFace);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("remove-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- fixture->generateCommand(*command);
-
- signal::Connection conn = face->onReceiveData.connect(
- [fixture, command, encodedParameters] (const Data& response) {
- fixture->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- manager.onFibRequest(*command);
-
- BOOST_REQUIRE(fixture->didCallbackFire());
-
- fixture->resetCallbackFired();
- conn.disconnect();
-}
-
-BOOST_AUTO_TEST_CASE(RemoveNextHop)
-{
- shared_ptr<Face> face1 = make_shared<DummyFace>();
- shared_ptr<Face> face2 = make_shared<DummyFace>();
- shared_ptr<Face> face3 = make_shared<DummyFace>();
-
- addFace(face1);
- addFace(face2);
- addFace(face3);
-
- shared_ptr<InternalFace> face = getInternalFace();
- FibManager& manager = getFibManager();
- Fib& fib = getFib();
-
- shared_ptr<fib::Entry> entry = fib.insert("/hello").first;
-
- entry->addNextHop(face1, 101);
- entry->addNextHop(face2, 202);
- entry->addNextHop(face3, 303);
-
- testRemoveNextHop(this, manager, fib, face, "/hello", 2);
- BOOST_REQUIRE(removedNextHopWithCost(fib, "/hello", 3, 202));
-
- testRemoveNextHop(this, manager, fib, face, "/hello", 3);
- BOOST_REQUIRE(removedNextHopWithCost(fib, "/hello", 2, 303));
-
- testRemoveNextHop(this, manager, fib, face, "/hello", 1);
- // BOOST_REQUIRE(removedNextHopWithCost(fib, "/hello", 1, 101));
-
- BOOST_CHECK(!static_cast<bool>(getFib().findExactMatch("/hello")));
-}
-
-BOOST_AUTO_TEST_CASE(RemoveFaceNotFound)
-{
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("remove-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(RemovePrefixNotFound)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setName("/hello");
- parameters.setFaceId(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("remove-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(RemoveMissingPrefix)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- ControlParameters parameters;
- parameters.setFaceId(1);
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("remove-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- face->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(RemoveImplicitFaceId)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face = getInternalFace();
-
- std::vector<ControlParameters> testedParameters;
- testedParameters.push_back(ControlParameters().setName("/hello").setFaceId(0));
- testedParameters.push_back(ControlParameters().setName("/hello"));
-
- for (std::vector<ControlParameters>::iterator parameters = testedParameters.begin();
- parameters != testedParameters.end(); ++parameters) {
- Block encodedParameters(parameters->wireEncode());
-
- Name commandName("/localhost/nfd/fib");
- commandName.append("remove-nexthop");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- command->setIncomingFaceId(1);
- generateCommand(*command);
-
- ControlParameters resultParameters;
- resultParameters.setFaceId(1);
- resultParameters.setName("/hello");
-
- signal::Connection conn = face->onReceiveData.connect(
- [this, command, resultParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", resultParameters.wireEncode());
- });
-
- getFibManager().onFibRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-
- conn.disconnect();
+ const auto& nexthops = entry.getNextHopRecords();
+ os << "[" << entry.getPrefix() << ", " << nexthops.size() << ": ";
+ for (auto record : nexthops) {
+ os << "{" << record.getFaceId() << ", " << record.getCost() << "} ";
}
+ os << "]";
+
+ return os;
}
-BOOST_FIXTURE_TEST_CASE(TestFibEnumerationRequest, FibManagerFixture)
+BOOST_AUTO_TEST_CASE(FibDataset)
{
- for (int i = 0; i < 87; i++)
- {
- Name prefix("/test");
- prefix.appendSegment(i);
+ const size_t nEntries = 108;
+ std::set<Name> actualPrefixes;
+ for (size_t i = 0 ; i < nEntries ; i ++) {
+ Name prefix = Name("test").appendSegment(i);
+ actualPrefixes.insert(prefix);
+ auto fibEntry = m_fib.insert(prefix).first;
+ fibEntry->addNextHop(m_faceTable.get(addFace()), std::numeric_limits<uint8_t>::max() - 1);
+ fibEntry->addNextHop(m_faceTable.get(addFace()), std::numeric_limits<uint8_t>::max() - 2);
+ }
- shared_ptr<DummyFace> dummy1(make_shared<DummyFace>());
- shared_ptr<DummyFace> dummy2(make_shared<DummyFace>());
+ receiveInterest(makeInterest("/localhost/nfd/fib/list"));
- shared_ptr<fib::Entry> entry = m_fib.insert(prefix).first;
- entry->addNextHop(dummy1, std::numeric_limits<uint64_t>::max() - 1);
- entry->addNextHop(dummy2, std::numeric_limits<uint64_t>::max() - 2);
+ Block content;
+ BOOST_CHECK_NO_THROW(content = concatenateResponses());
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_REQUIRE_EQUAL(content.elements().size(), nEntries);
- m_referenceEntries.insert(entry);
+ std::vector<FibEntry> receivedRecords, expectedRecords;
+ for (size_t idx = 0; idx < nEntries; ++idx) {
+ BOOST_TEST_MESSAGE("processing element: " << idx);
+
+ FibEntry decodedEntry;
+ BOOST_REQUIRE_NO_THROW(decodedEntry.wireDecode(content.elements()[idx]));
+ receivedRecords.push_back(decodedEntry);
+
+ actualPrefixes.erase(decodedEntry.getPrefix());
+
+ auto matchedEntry = m_fib.findExactMatch(decodedEntry.getPrefix());
+ BOOST_REQUIRE(matchedEntry != nullptr);
+
+ FibEntry record;
+ record.setPrefix(matchedEntry->getPrefix());
+ const auto& nextHops = matchedEntry->getNextHops();
+ for (auto&& next : nextHops) {
+ ndn::nfd::NextHopRecord nextHopRecord;
+ nextHopRecord.setFaceId(next.getFace()->getId());
+ nextHopRecord.setCost(next.getCost());
+ record.addNextHopRecord(nextHopRecord);
}
- for (int i = 0; i < 2; i++)
- {
- Name prefix("/test2");
- prefix.appendSegment(i);
+ expectedRecords.push_back(record);
+ }
- shared_ptr<DummyFace> dummy1(make_shared<DummyFace>());
- shared_ptr<DummyFace> dummy2(make_shared<DummyFace>());
+ BOOST_CHECK_EQUAL(actualPrefixes.size(), 0);
- shared_ptr<fib::Entry> entry = m_fib.insert(prefix).first;
- entry->addNextHop(dummy1, std::numeric_limits<uint8_t>::max() - 1);
- entry->addNextHop(dummy2, std::numeric_limits<uint8_t>::max() - 2);
-
- m_referenceEntries.insert(entry);
- }
-
- ndn::EncodingBuffer buffer;
-
- m_face->onReceiveData.connect(bind(&FibEnumerationPublisherFixture::decodeFibEntryBlock,
- this, _1));
-
- shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/fib/list"));
-
- m_manager.onFibRequest(*command);
- BOOST_REQUIRE(m_finished);
+ BOOST_CHECK_EQUAL_COLLECTIONS(receivedRecords.begin(), receivedRecords.end(),
+ expectedRecords.begin(), expectedRecords.end());
}
-BOOST_AUTO_TEST_SUITE_END()
+BOOST_AUTO_TEST_SUITE_END() // TestFibManager
+BOOST_AUTO_TEST_SUITE_END() // Mgmt
} // namespace tests
} // namespace nfd
diff --git a/tests/daemon/mgmt/status-server.t.cpp b/tests/daemon/mgmt/forwarder-status-manager.t.cpp
similarity index 78%
rename from tests/daemon/mgmt/status-server.t.cpp
rename to tests/daemon/mgmt/forwarder-status-manager.t.cpp
index 4cf7c13..104adaa 100644
--- a/tests/daemon/mgmt/status-server.t.cpp
+++ b/tests/daemon/mgmt/forwarder-status-manager.t.cpp
@@ -23,39 +23,35 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "mgmt/status-server.hpp"
+#include "mgmt/forwarder-status-manager.hpp"
#include "fw/forwarder.hpp"
#include "version.hpp"
-#include "mgmt/internal-face.hpp"
#include "tests/test-common.hpp"
#include "tests/daemon/face/dummy-face.hpp"
+#include <ndn-cxx/util/dummy-client-face.hpp>
+#include <ndn-cxx/mgmt/dispatcher.hpp>
namespace nfd {
namespace tests {
-BOOST_FIXTURE_TEST_SUITE(MgmtStatusServer, BaseFixture)
-
-shared_ptr<const Data> g_response;
-
-void
-interceptResponse(const Data& data)
-{
- g_response = data.shared_from_this();
-}
+BOOST_FIXTURE_TEST_SUITE(Mgmt, UnitTestTimeFixture)
+BOOST_AUTO_TEST_SUITE(TestForwarderStatusManager)
BOOST_AUTO_TEST_CASE(Status)
{
// initialize
time::system_clock::TimePoint t1 = time::system_clock::now();
Forwarder forwarder;
- shared_ptr<InternalFace> internalFace = make_shared<InternalFace>();
- internalFace->onReceiveData.connect(&interceptResponse);
+ auto face = ndn::util::makeDummyClientFace(g_io, {true, true});
ndn::KeyChain keyChain;
- StatusServer statusServer(internalFace, ref(forwarder), keyChain);
- time::system_clock::TimePoint t2 = time::system_clock::now();
+ ndn::mgmt::Dispatcher dispatcher(*face, ref(keyChain));
+ ForwarderStatusManager statusServer(ref(forwarder), ref(dispatcher));
+ dispatcher.addTopPrefix("/localhost/nfd");
+ advanceClocks(time::milliseconds(1));
// populate tables
+ time::system_clock::TimePoint t2 = time::system_clock::now();
forwarder.getFib().insert("ndn:/fib1");
forwarder.getPit().insert(*makeInterest("ndn:/pit1"));
forwarder.getPit().insert(*makeInterest("ndn:/pit2"));
@@ -69,20 +65,19 @@
BOOST_CHECK_GE(forwarder.getMeasurements().size(), 3);
// request
- shared_ptr<Interest> request = makeInterest("ndn:/localhost/nfd/status");
+ time::system_clock::TimePoint t3 = time::system_clock::now();
+ auto request = makeInterest("ndn:/localhost/nfd/status");
request->setMustBeFresh(true);
request->setChildSelector(1);
- g_response.reset();
- time::system_clock::TimePoint t3 = time::system_clock::now();
- internalFace->sendInterest(*request);
- g_io.run_one();
- time::system_clock::TimePoint t4 = time::system_clock::now();
- BOOST_REQUIRE(static_cast<bool>(g_response));
+ face->receive<Interest>(*request);
+ advanceClocks(time::milliseconds(1));
// verify
+ time::system_clock::TimePoint t4 = time::system_clock::now();
+ BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
ndn::nfd::ForwarderStatus status;
- BOOST_REQUIRE_NO_THROW(status.wireDecode(g_response->getContent()));
+ BOOST_REQUIRE_NO_THROW(status.wireDecode(face->sentDatas[0].getContent()));
BOOST_CHECK_EQUAL(status.getNfdVersion(), NFD_VERSION_BUILD_STRING);
BOOST_CHECK_GE(time::toUnixTimestamp(status.getStartTimestamp()), time::toUnixTimestamp(t1));
@@ -90,7 +85,7 @@
BOOST_CHECK_GE(time::toUnixTimestamp(status.getCurrentTimestamp()), time::toUnixTimestamp(t3));
BOOST_CHECK_LE(time::toUnixTimestamp(status.getCurrentTimestamp()), time::toUnixTimestamp(t4));
- // StatusServer under test isn't added to Forwarder,
+ // Interest/Data toward ForwarderStatusManager don't go through Forwarder,
// so request and response won't affect table size
BOOST_CHECK_EQUAL(status.getNNameTreeEntries(), forwarder.getNameTree().size());
BOOST_CHECK_EQUAL(status.getNFibEntries(), forwarder.getFib().size());
@@ -99,7 +94,8 @@
BOOST_CHECK_EQUAL(status.getNCsEntries(), forwarder.getCs().size());
}
-BOOST_AUTO_TEST_SUITE_END()
+BOOST_AUTO_TEST_SUITE_END() // TestForwarderStatusManager
+BOOST_AUTO_TEST_SUITE_END() // Mgmt
} // namespace tests
} // namespace nfd
diff --git a/tests/daemon/mgmt/internal-face.t.cpp b/tests/daemon/mgmt/internal-face.t.cpp
deleted file mode 100644
index 29b602c..0000000
--- a/tests/daemon/mgmt/internal-face.t.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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 "mgmt/internal-face.hpp"
-#include "tests/daemon/face/dummy-face.hpp"
-
-#include "tests/test-common.hpp"
-
-namespace nfd {
-namespace tests {
-
-class InternalFaceFixture : protected BaseFixture
-{
-public:
-
- InternalFaceFixture()
- : m_onInterestFired(false),
- m_noOnInterestFired(false)
- {
-
- }
-
- void
- validateOnInterestCallback(const Name& name, const Interest& interest)
- {
- m_onInterestFired = true;
- }
-
- void
- validateNoOnInterestCallback(const Name& name, const Interest& interest)
- {
- m_noOnInterestFired = true;
- }
-
- void
- addFace(shared_ptr<Face> face)
- {
- m_faces.push_back(face);
- }
-
- bool
- didOnInterestFire()
- {
- return m_onInterestFired;
- }
-
- bool
- didNoOnInterestFire()
- {
- return m_noOnInterestFired;
- }
-
- void
- resetOnInterestFired()
- {
- m_onInterestFired = false;
- }
-
- void
- resetNoOnInterestFired()
- {
- m_noOnInterestFired = false;
- }
-
-protected:
- ndn::KeyChain m_keyChain;
-
-private:
- std::vector<shared_ptr<Face> > m_faces;
- bool m_onInterestFired;
- bool m_noOnInterestFired;
-};
-
-BOOST_FIXTURE_TEST_SUITE(MgmtInternalFace, InternalFaceFixture)
-
-void
-validatePutData(bool& called, const Name& expectedName, const Data& data)
-{
- called = true;
- BOOST_CHECK_EQUAL(expectedName, data.getName());
-}
-
-BOOST_AUTO_TEST_CASE(PutData)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face(new InternalFace);
-
- bool didPutData = false;
- Name dataName("/hello");
- face->onReceiveData.connect(bind(&validatePutData, ref(didPutData), dataName, _1));
-
- Data testData(dataName);
- m_keyChain.sign(testData);
- face->put(testData);
-
- BOOST_REQUIRE(didPutData);
-
- BOOST_CHECK_THROW(face->close(), InternalFace::Error);
-}
-
-BOOST_AUTO_TEST_CASE(SendInterestHitEnd)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face(new InternalFace);
-
- face->setInterestFilter("/localhost/nfd/fib",
- bind(&InternalFaceFixture::validateOnInterestCallback,
- this, _1, _2));
-
- // generate command whose name is canonically
- // ordered after /localhost/nfd/fib so that
- // we hit the end of the std::map
-
- Name commandName("/localhost/nfd/fib/end");
- shared_ptr<Interest> command = makeInterest(commandName);
- face->sendInterest(*command);
- g_io.run_one();
-
- BOOST_REQUIRE(didOnInterestFire());
- BOOST_REQUIRE(didNoOnInterestFire() == false);
-}
-
-BOOST_AUTO_TEST_CASE(SendInterestHitBegin)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face(new InternalFace);
-
- face->setInterestFilter("/localhost/nfd/fib",
- bind(&InternalFaceFixture::validateNoOnInterestCallback,
- this, _1, _2));
-
- // generate command whose name is canonically
- // ordered before /localhost/nfd/fib so that
- // we hit the beginning of the std::map
-
- Name commandName("/localhost/nfd");
- shared_ptr<Interest> command = makeInterest(commandName);
- face->sendInterest(*command);
- g_io.run_one();
-
- BOOST_REQUIRE(didNoOnInterestFire() == false);
-}
-
-BOOST_AUTO_TEST_CASE(SendInterestHitExact)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face(new InternalFace);
-
- face->setInterestFilter("/localhost/nfd/eib",
- bind(&InternalFaceFixture::validateNoOnInterestCallback,
- this, _1, _2));
-
- face->setInterestFilter("/localhost/nfd/fib",
- bind(&InternalFaceFixture::validateOnInterestCallback,
- this, _1, _2));
-
- face->setInterestFilter("/localhost/nfd/gib",
- bind(&InternalFaceFixture::validateNoOnInterestCallback,
- this, _1, _2));
-
- // generate command whose name exactly matches
- // /localhost/nfd/fib
-
- Name commandName("/localhost/nfd/fib");
- shared_ptr<Interest> command = makeInterest(commandName);
- face->sendInterest(*command);
- g_io.run_one();
-
- BOOST_REQUIRE(didOnInterestFire());
- BOOST_REQUIRE(didNoOnInterestFire() == false);
-}
-
-BOOST_AUTO_TEST_CASE(SendInterestHitPrevious)
-{
- addFace(make_shared<DummyFace>());
-
- shared_ptr<InternalFace> face(new InternalFace);
-
- face->setInterestFilter("/localhost/nfd/fib",
- bind(&InternalFaceFixture::validateOnInterestCallback,
- this, _1, _2));
-
- face->setInterestFilter("/localhost/nfd/fib/zzzzzzzzzzzzz/",
- bind(&InternalFaceFixture::validateNoOnInterestCallback,
- this, _1, _2));
-
- // generate command whose name exactly matches
- // an Interest filter
-
- Name commandName("/localhost/nfd/fib/previous");
- shared_ptr<Interest> command = makeInterest(commandName);
- face->sendInterest(*command);
- g_io.run_one();
-
- BOOST_REQUIRE(didOnInterestFire());
- BOOST_REQUIRE(didNoOnInterestFire() == false);
-}
-
-BOOST_AUTO_TEST_CASE(InterestGone)
-{
- shared_ptr<InternalFace> face = make_shared<InternalFace>();
- shared_ptr<Interest> interest = makeInterest("ndn:/localhost/nfd/gone");
- face->sendInterest(*interest);
-
- interest.reset();
- BOOST_CHECK_NO_THROW(g_io.poll());
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/daemon/mgmt/manager-base.t.cpp b/tests/daemon/mgmt/manager-base.t.cpp
index 1b78175..f3ea152 100644
--- a/tests/daemon/mgmt/manager-base.t.cpp
+++ b/tests/daemon/mgmt/manager-base.t.cpp
@@ -24,177 +24,164 @@
*/
#include "mgmt/manager-base.hpp"
-#include "mgmt/internal-face.hpp"
+#include "manager-common-fixture.hpp"
-#include "tests/test-common.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/management/nfd-control-command.hpp>
namespace nfd {
namespace tests {
NFD_LOG_INIT("ManagerBaseTest");
-class ManagerBaseTest : public ManagerBase, protected BaseFixture
+class TestCommandVoidParameters : public ndn::nfd::ControlCommand
{
-
public:
-
- ManagerBaseTest()
- : ManagerBase(make_shared<InternalFace>(), "TEST-PRIVILEGE", m_keyChain),
- m_callbackFired(false)
+ TestCommandVoidParameters()
+ : ndn::nfd::ControlCommand("test-module", "test-void-parameters")
{
-
}
-
- void
- testSetResponse(ControlResponse& response,
- uint32_t code,
- const std::string& text)
- {
- setResponse(response, code, text);
- }
-
- void
- testSendResponse(const Name& name,
- uint32_t code,
- const std::string& text,
- const Block& body)
- {
- sendResponse(name, code, text, body);
- }
-
- void
- testSendResponse(const Name& name,
- uint32_t code,
- const std::string& text)
- {
- sendResponse(name, code, text);
- }
-
- void
- testSendResponse(const Name& name,
- const ControlResponse& response)
- {
- sendResponse(name, response);
- }
-
- shared_ptr<InternalFace>
- getInternalFace()
- {
- return static_pointer_cast<InternalFace>(m_face);
- }
-
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText)
- {
- m_callbackFired = true;
- Block controlRaw = response.getContent().blockFromValue();
-
- ControlResponse control;
- control.wireDecode(controlRaw);
-
- NFD_LOG_DEBUG("received control response"
- << " name: " << response.getName()
- << " code: " << control.getCode()
- << " text: " << control.getText());
-
- BOOST_REQUIRE(response.getName() == expectedName);
- BOOST_REQUIRE(control.getCode() == expectedCode);
- BOOST_REQUIRE(control.getText() == expectedText);
- }
-
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- const Block& expectedBody)
- {
- m_callbackFired = true;
- Block controlRaw = response.getContent().blockFromValue();
-
- ControlResponse control;
- control.wireDecode(controlRaw);
-
- NFD_LOG_DEBUG("received control response"
- << " name: " << response.getName()
- << " code: " << control.getCode()
- << " text: " << control.getText());
-
- BOOST_REQUIRE(response.getName() == expectedName);
- BOOST_REQUIRE(control.getCode() == expectedCode);
- BOOST_REQUIRE(control.getText() == expectedText);
-
- BOOST_REQUIRE(control.getBody().value_size() == expectedBody.value_size());
-
- BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
- expectedBody.value_size()) == 0);
- }
-
- bool
- didCallbackFire()
- {
- return m_callbackFired;
- }
-
-private:
-
- bool m_callbackFired;
- ndn::KeyChain m_keyChain;
-
};
-BOOST_FIXTURE_TEST_SUITE(MgmtManagerBase, ManagerBaseTest)
-
-BOOST_AUTO_TEST_CASE(SetResponse)
+class TestCommandRequireName : public ndn::nfd::ControlCommand
{
- ControlResponse response(200, "OK");
+public:
+ TestCommandRequireName()
+ : ndn::nfd::ControlCommand("test-module", "test-require-name")
+ {
+ m_requestValidator.required(ndn::nfd::CONTROL_PARAMETER_NAME);
+ }
+};
- BOOST_CHECK_EQUAL(response.getCode(), 200);
- BOOST_CHECK_EQUAL(response.getText(), "OK");
+class ManagerBaseFixture : public ManagerCommonFixture
+{
+public:
+ ManagerBaseFixture()
+ : m_manager(m_dispatcher, m_validator, "test-module")
+ {
+ }
- testSetResponse(response, 100, "test");
+protected:
+ ManagerBase m_manager;
+};
- BOOST_CHECK_EQUAL(response.getCode(), 100);
- BOOST_CHECK_EQUAL(response.getText(), "test");
+BOOST_FIXTURE_TEST_SUITE(MgmtManagerBase, ManagerBaseFixture)
+
+BOOST_AUTO_TEST_CASE(AddSupportedPrivilegeInConstructor)
+{
+ BOOST_CHECK_NO_THROW(m_validator.addSupportedPrivilege("other-module"));
+ // test-module has already been added by the constructor of ManagerBase
+ BOOST_CHECK_THROW(m_validator.addSupportedPrivilege("test-module"), CommandValidator::Error);
}
-BOOST_AUTO_TEST_CASE(SendResponse4Arg)
+BOOST_AUTO_TEST_CASE(RegisterCommandHandler)
{
- ndn::nfd::ControlParameters parameters;
- parameters.setName("/test/body");
+ bool wasCommandHandlerCalled = false;
+ auto handler = bind([&] { wasCommandHandlerCalled = true; });
- getInternalFace()->onReceiveData.connect([this, parameters] (const Data& response) {
- this->validateControlResponse(response, "/response", 100, "test", parameters.wireEncode());
- });
+ m_manager.registerCommandHandler<TestCommandVoidParameters>("test-void", handler);
+ m_manager.registerCommandHandler<TestCommandRequireName>("test-require-name", handler);
+ setTopPrefixAndPrivilege("/localhost/nfd", "test-module");
- testSendResponse("/response", 100, "test", parameters.wireEncode());
- BOOST_REQUIRE(didCallbackFire());
+ auto testRegisterCommandHandler = [&wasCommandHandlerCalled, this] (const Name& commandName) {
+ wasCommandHandlerCalled = false;
+ receiveInterest(makeControlCommandRequest(commandName, ControlParameters()));
+ };
+
+ testRegisterCommandHandler("/localhost/nfd/test-module/test-void");
+ BOOST_CHECK(wasCommandHandlerCalled);
+
+ testRegisterCommandHandler("/localhost/nfd/test-module/test-require-name");
+ BOOST_CHECK(!wasCommandHandlerCalled);
}
-
-BOOST_AUTO_TEST_CASE(SendResponse3Arg)
+BOOST_AUTO_TEST_CASE(RegisterStatusDataset)
{
- getInternalFace()->onReceiveData.connect([this] (const Data& response) {
- this->validateControlResponse(response, "/response", 100, "test");
- });
+ bool isStatusDatasetCalled = false;
+ auto handler = bind([&] { isStatusDatasetCalled = true; });
- testSendResponse("/response", 100, "test");
- BOOST_REQUIRE(didCallbackFire());
+ m_manager.registerStatusDatasetHandler("test-status", handler);
+ m_dispatcher.addTopPrefix("/localhost/nfd");
+ advanceClocks(time::milliseconds(1));
+
+ receiveInterest(makeInterest("/localhost/nfd/test-module/test-status"));
+ BOOST_CHECK(isStatusDatasetCalled);
}
-BOOST_AUTO_TEST_CASE(SendResponse2Arg)
+BOOST_AUTO_TEST_CASE(RegisterNotificationStream)
{
- getInternalFace()->onReceiveData.connect([this] (const Data& response) {
- this->validateControlResponse(response, "/response", 100, "test");
- });
+ auto post = m_manager.registerNotificationStream("test-notification");
+ m_dispatcher.addTopPrefix("/localhost/nfd");
+ advanceClocks(time::milliseconds(1));
- ControlResponse response(100, "test");
+ post(Block("\x82\x01\x02", 3));
+ advanceClocks(time::milliseconds(1));
- testSendResponse("/response", 100, "test");
- BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(m_responses[0].getName(),
+ Name("/localhost/nfd/test-module/test-notification/%FE%00"));
+}
+
+BOOST_AUTO_TEST_CASE(CommandAuthorization)
+{
+ bool didAcceptCallbackFire = false;
+ bool didRejectCallbackFire = false;
+ auto testAuthorization = [&] {
+ didAcceptCallbackFire = false;
+ didRejectCallbackFire = false;
+
+ auto command = makeControlCommandRequest("/localhost/nfd/test-module/test-verb",
+ ControlParameters());
+ ndn::nfd::ControlParameters params;
+ m_manager.authorize("/top/prefix", *command, ¶ms,
+ bind([&] { didAcceptCallbackFire = true; }),
+ bind([&] { didRejectCallbackFire = true; }));
+ };
+
+ testAuthorization();
+ BOOST_CHECK(!didAcceptCallbackFire);
+ BOOST_CHECK(didRejectCallbackFire);
+
+ m_validator.addInterestRule("^<localhost><nfd><test-module>", *m_certificate);
+ testAuthorization();
+ BOOST_CHECK(didAcceptCallbackFire);
+ BOOST_CHECK(!didRejectCallbackFire);
+}
+
+BOOST_AUTO_TEST_CASE(ExtractRequester)
+{
+ std::string requesterName;
+ auto testAccept = [&] (const std::string& requester) { requesterName = requester; };
+
+ auto unsignedCommand = makeInterest("/test/interest/unsigned");
+ auto signedCommand = makeControlCommandRequest("/test/interest/signed", ControlParameters());
+
+ m_manager.extractRequester(*unsignedCommand, testAccept);
+ BOOST_CHECK(requesterName.empty());
+
+ requesterName = "";
+ m_manager.extractRequester(*signedCommand, testAccept);
+ auto keyLocator = m_keyChain.getDefaultCertificateNameForIdentity(m_identityName).getPrefix(-1);
+ BOOST_CHECK_EQUAL(requesterName, keyLocator.toUri());
+}
+
+BOOST_AUTO_TEST_CASE(ValidateParameters)
+{
+ ControlParameters params;
+ TestCommandVoidParameters commandVoidParams;
+ TestCommandRequireName commandRequireName;
+
+ BOOST_CHECK_EQUAL(ManagerBase::validateParameters(commandVoidParams, params), true); // succeeds
+ BOOST_CHECK_EQUAL(ManagerBase::validateParameters(commandRequireName, params), false); // fails
+
+ params.setName("test-name");
+ BOOST_CHECK_EQUAL(ManagerBase::validateParameters(commandRequireName, params), true); // succeeds
+}
+
+BOOST_AUTO_TEST_CASE(MakeRelPrefix)
+{
+ auto generatedRelPrefix = m_manager.makeRelPrefix("test-verb");
+ BOOST_CHECK_EQUAL(generatedRelPrefix, PartialName("/test-module/test-verb"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/daemon/mgmt/manager-common-fixture.cpp b/tests/daemon/mgmt/manager-common-fixture.cpp
new file mode 100644
index 0000000..b03449e
--- /dev/null
+++ b/tests/daemon/mgmt/manager-common-fixture.cpp
@@ -0,0 +1,193 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "manager-common-fixture.hpp"
+
+namespace nfd {
+namespace tests {
+
+ManagerCommonFixture::ManagerCommonFixture()
+ : m_face(ndn::util::makeDummyClientFace(UnitTestTimeFixture::g_io, {true, true}))
+ , m_dispatcher(*m_face, m_keyChain, ndn::security::SigningInfo())
+ , m_responses(m_face->sentDatas)
+ , m_identityName("/unit-test/ManagerCommonFixture/identity")
+ , m_certificate(m_keyChain.getCertificate(m_keyChain.createIdentity(m_identityName)))
+{
+}
+
+void
+ManagerCommonFixture::setTopPrefixAndPrivilege(const Name& topPrefix,
+ const std::string& privilege)
+{
+ m_dispatcher.addTopPrefix(topPrefix); // such that all filters are added
+ advanceClocks(time::milliseconds(1));
+
+ std::string regex("^");
+ for (auto component : topPrefix) {
+ regex += "<" + component.toUri() + ">";
+ }
+ m_validator.addInterestRule(regex + "<" + privilege + ">", *m_certificate);
+}
+
+shared_ptr<Interest>
+ManagerCommonFixture::makeControlCommandRequest(Name commandName,
+ const ControlParameters& parameters,
+ const InterestHandler& beforeSigning)
+{
+ shared_ptr<Interest> command = makeInterest(commandName.append(parameters.wireEncode()));
+
+ if (beforeSigning != nullptr) {
+ beforeSigning(command);
+ }
+
+ m_keyChain.sign(*command, ndn::security::SigningInfo(ndn::security::SigningInfo::SIGNER_TYPE_ID,
+ m_identityName));
+ return command;
+}
+
+void
+ManagerCommonFixture::receiveInterest(shared_ptr<Interest> interest)
+{
+ m_face->receive<Interest>(*interest);
+ advanceClocks(time::milliseconds(1));
+}
+
+ControlResponse
+ManagerCommonFixture::makeResponse(uint32_t code, const std::string& text,
+ const ControlParameters& parameters)
+{
+ return ControlResponse(code, text).setBody(parameters.wireEncode());
+}
+
+ManagerCommonFixture::CheckResponseResult
+ManagerCommonFixture::checkResponse(size_t idx,
+ const Name& expectedName,
+ const ControlResponse& expectedResponse,
+ int expectedContentType /*= -1*/)
+{
+ Data data;
+ try {
+ data = m_responses.at(idx);
+ }
+ catch (const std::out_of_range&) {
+ return CheckResponseResult::OUT_OF_BOUNDARY;
+ }
+
+ if (data.getName() != expectedName) {
+ return CheckResponseResult::WRONG_NAME;
+ }
+
+ if (expectedContentType != -1 &&
+ data.getContentType() != static_cast<uint32_t>(expectedContentType)) {
+ return CheckResponseResult::WRONG_CONTENT_TYPE;
+ }
+
+ ControlResponse response;
+ try {
+ response.wireDecode(data.getContent().blockFromValue());
+ }
+ catch (const tlv::Error&) {
+ return CheckResponseResult::INVALID_RESPONSE;
+ }
+
+ if (response.getCode() != expectedResponse.getCode()) {
+ return CheckResponseResult::WRONG_CODE;
+ }
+
+ if (response.getText() != expectedResponse.getText()) {
+ return CheckResponseResult::WRONG_TEXT;
+ }
+
+ const Block& body = response.getBody();
+ const Block& expectedBody = expectedResponse.getBody();
+ if (body.value_size() != expectedBody.value_size()) {
+ return CheckResponseResult::WRONG_BODY_SIZE;
+ }
+ if (body.value_size() > 0 && memcmp(body.value(), expectedBody.value(), body.value_size()) != 0) {
+ return CheckResponseResult::WRONG_BODY_VALUE;
+ }
+
+ return CheckResponseResult::OK;
+}
+
+Block
+ManagerCommonFixture::concatenateResponses(size_t startIndex, size_t nResponses)
+{
+ size_t endIndex = startIndex + nResponses; // not included
+ if (nResponses == startIndex || endIndex > m_responses.size()) {
+ endIndex = m_responses.size();
+ }
+
+ ndn::EncodingBuffer encoder;
+ size_t valueLength = 0;
+ for (size_t i = startIndex; i < endIndex ; i ++) {
+ valueLength += encoder.appendByteArray(m_responses[i].getContent().value(),
+ m_responses[i].getContent().value_size());
+ }
+ encoder.prependVarNumber(valueLength);
+ encoder.prependVarNumber(tlv::Content);
+ return encoder.block();
+}
+
+std::ostream&
+operator<<(std::ostream &os, const ManagerCommonFixture::CheckResponseResult& result)
+{
+ switch (result) {
+ case ManagerCommonFixture::CheckResponseResult::OK:
+ os << "OK";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::OUT_OF_BOUNDARY:
+ os << "OUT_OF_BOUNDARY";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::WRONG_NAME:
+ os << "WRONG_NAME";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::WRONG_CONTENT_TYPE:
+ os << "WRONG_CONTENT_TYPE";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::INVALID_RESPONSE:
+ os << "INVALID_RESPONSE";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::WRONG_CODE:
+ os << "WRONG_CODE";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::WRONG_TEXT:
+ os << "WRONG_TEXT";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::WRONG_BODY_SIZE:
+ os << "WRONG_BODY_SIZE";
+ break;
+ case ManagerCommonFixture::CheckResponseResult::WRONG_BODY_VALUE:
+ os << "WRONG_BODY_VALUE";
+ break;
+ default:
+ break;
+ };
+
+ return os;
+}
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/daemon/mgmt/manager-common-fixture.hpp b/tests/daemon/mgmt/manager-common-fixture.hpp
new file mode 100644
index 0000000..ffdb579
--- /dev/null
+++ b/tests/daemon/mgmt/manager-common-fixture.hpp
@@ -0,0 +1,163 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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/>.
+ */
+
+#ifndef NFD_TESTS_NFD_MGMT_MANAGER_COMMON_HPP
+#define NFD_TESTS_NFD_MGMT_MANAGER_COMMON_HPP
+
+#include "tests/test-common.hpp"
+#include "tests/identity-management-fixture.hpp"
+#include "mgmt/manager-base.hpp"
+#include "fw/forwarder.hpp"
+
+#include <ndn-cxx/mgmt/dispatcher.hpp>
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
+namespace nfd {
+namespace tests {
+
+/**
+ * @brief a collection of common functions shared by all manager's testing fixtures.
+ */
+class ManagerCommonFixture : public UnitTestTimeFixture
+ , public IdentityManagementFixture
+{
+public: // initialize
+ ManagerCommonFixture();
+
+ /**
+ * @brief set topPrefix to the dispatcher and configure an interest rule for the module.
+ *
+ * after setting @param topPrefix, call advanceClocks to ensure all added filters take effects.
+ *
+ * @param topPrefix top prefix for the dispatcher
+ * @param privilege the module name
+ */
+ void
+ setTopPrefixAndPrivilege(const Name& topPrefix, const std::string& privilege);
+
+public: // test
+ typedef std::function<void(shared_ptr<Interest> interest)> InterestHandler;
+
+ /**
+ * @brief create a ControlCommand request
+ *
+ * step1: append the @param parameters to the @param commandName and make an Interest.
+ * step2: call @param beforeSinging to do something with the Interest.
+ * step3: sign the generated command
+ *
+ * @param commandName the command name
+ * @param parameters the ControlParameters
+ * @param beforeSigning a callback that can modify the Interest before it's signed
+ *
+ * @return the signed ControlCommand request
+ */
+ shared_ptr<Interest>
+ makeControlCommandRequest(Name commandName,
+ const ControlParameters& parameters,
+ const InterestHandler& beforeSigning = nullptr);
+
+ /**
+ * @brief cause management to receive an Interest
+ *
+ * call DummyClientFace::receive to receive Interest and then call advanceClocks to ensure
+ * the Interest dispatched
+ *
+ * @param interest the Interest to receive
+ */
+ void
+ receiveInterest(shared_ptr<Interest> interest);
+
+public: // verify
+ ControlResponse
+ makeResponse(uint32_t code, const std::string& text,
+ const ControlParameters& parameters);
+
+ enum class CheckResponseResult
+ {
+ OK,
+ OUT_OF_BOUNDARY,
+ WRONG_NAME,
+ WRONG_CONTENT_TYPE,
+ INVALID_RESPONSE,
+ WRONG_CODE,
+ WRONG_TEXT,
+ WRONG_BODY_SIZE,
+ WRONG_BODY_VALUE
+ };
+
+ /**
+ * @brief check a specified response data with the expected ControlResponse
+ *
+ * @param idx the index of the specified Data in m_responses
+ * @param expectedDataName the expected name of this Data
+ * @param expectedResponse the expected ControlResponse
+ * @param expectedContentType the expected content type of this Data, use -1 to skip this check
+ *
+ * @retval OK the response at the specified index can be decoded from the response data,
+ * and its code, text and response body are all matched with the expected response
+ * @retval OUT_OF_BOUNDARY the specified index out of boundary
+ * @retval WRONG_NAME the name of the specified response data does not match
+ * @retval WRONG_CONTENT_TYPE the content type of the specified response data does not match
+ * @retval INVALID_RESPONSE the data name matches but it fails in decoding a ControlResponse from
+ * the content of the specified response data
+ * @retval WRONG_CODE a valid ControlResponse can be decoded but has a wrong code
+ * @retval WRONG_TEXT a valid ControlResponse can be decoded but has a wrong text
+ * @retval WRONG_BODY_SIZE the body size of decoded ControlResponse does not match
+ * @retval WRONT_BODY_VALUE the body value of decoded ControlResponse does not match
+ */
+ CheckResponseResult
+ checkResponse(size_t idx,
+ const Name& expectedName,
+ const ControlResponse& expectedResponse,
+ int expectedContentType = -1);
+
+ /**
+ * @brief concatenate specified response Data into a single block
+ *
+ * @param startIndex the start index in m_responses
+ * @param nResponses the number of response to concatenate
+ *
+ * @return the generated block
+ */
+ Block
+ concatenateResponses(size_t startIndex = 0, size_t nResponses = 0);
+
+protected:
+ shared_ptr<ndn::util::DummyClientFace> m_face;
+ ndn::mgmt::Dispatcher m_dispatcher;
+ CommandValidator m_validator;
+ Forwarder m_forwarder;
+ std::vector<Data>& m_responses; // a reference of m_face->sentDatas
+ Name m_identityName; // the identity used to sign request
+ shared_ptr<ndn::IdentityCertificate> m_certificate; // the certificate used to sign request
+};
+
+std::ostream&
+operator<<(std::ostream &os, const ManagerCommonFixture::CheckResponseResult& result);
+
+} // namespace tests
+} // namespace nfd
+
+#endif // NFD_TESTS_NFD_MGMT_MANAGER_COMMON_HPP
diff --git a/tests/daemon/mgmt/strategy-choice-manager.t.cpp b/tests/daemon/mgmt/strategy-choice-manager.t.cpp
index d0c425d..9e7a8c2 100644
--- a/tests/daemon/mgmt/strategy-choice-manager.t.cpp
+++ b/tests/daemon/mgmt/strategy-choice-manager.t.cpp
@@ -24,623 +24,225 @@
*/
#include "mgmt/strategy-choice-manager.hpp"
+#include "manager-common-fixture.hpp"
+
#include "face/face.hpp"
-#include "mgmt/internal-face.hpp"
+#include "face/internal-face.hpp"
#include "table/name-tree.hpp"
#include "table/strategy-choice.hpp"
-#include "fw/forwarder.hpp"
#include "fw/strategy.hpp"
#include "tests/daemon/face/dummy-face.hpp"
#include "tests/daemon/fw/dummy-strategy.hpp"
+#include <ndn-cxx/util/random.hpp>
#include <ndn-cxx/management/nfd-strategy-choice.hpp>
-#include "tests/test-common.hpp"
-#include "validation-common.hpp"
-
namespace nfd {
namespace tests {
-NFD_LOG_INIT("MgmtStrategyChoiceManager");
-
-class StrategyChoiceManagerFixture : protected BaseFixture
+class StrategyChoiceManagerFixture : public ManagerCommonFixture
{
public:
-
StrategyChoiceManagerFixture()
: m_strategyChoice(m_forwarder.getStrategyChoice())
- , m_face(make_shared<InternalFace>())
- , m_manager(m_strategyChoice, m_face, m_keyChain)
- , m_callbackFired(false)
+ , m_manager(m_strategyChoice, m_dispatcher, m_validator)
{
- m_strategyChoice.install(make_shared<DummyStrategy>(ref(m_forwarder),
- "/localhost/nfd/strategy/test-strategy-a"));
- m_strategyChoice.insert("ndn:/", "/localhost/nfd/strategy/test-strategy-a");
+ setTopPrefixAndPrivilege("/localhost/nfd", "strategy-choice");
}
- virtual
- ~StrategyChoiceManagerFixture()
- {
-
- }
-
+public:
void
- validateControlResponseCommon(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- ControlResponse& control)
+ installStrategy(const Name& strategy)
{
- m_callbackFired = true;
- Block controlRaw = response.getContent().blockFromValue();
-
- control.wireDecode(controlRaw);
-
- NFD_LOG_DEBUG("received control response"
- << " Name: " << response.getName()
- << " code: " << control.getCode()
- << " text: " << control.getText());
-
- BOOST_CHECK_EQUAL(response.getName(), expectedName);
- BOOST_CHECK_EQUAL(control.getCode(), expectedCode);
- BOOST_CHECK_EQUAL(control.getText(), expectedText);
+ m_strategyChoice.install(make_shared<DummyStrategy>(ref(m_forwarder), strategy));
}
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText)
+ const Name&
+ findStrategy(const Name& name)
{
- ControlResponse control;
- validateControlResponseCommon(response, expectedName,
- expectedCode, expectedText, control);
-
- if (!control.getBody().empty())
- {
- BOOST_FAIL("found unexpected control response body");
- }
+ return m_strategyChoice.findEffectiveStrategy(name).getName();
}
- void
- validateControlResponse(const Data& response,
- const Name& expectedName,
- uint32_t expectedCode,
- const std::string& expectedText,
- const Block& expectedBody)
+ ControlParameters
+ makeParameters(const Name& name, const Name& strategy)
{
- ControlResponse control;
- validateControlResponseCommon(response, expectedName,
- expectedCode, expectedText, control);
-
- BOOST_REQUIRE(!control.getBody().empty());
- BOOST_REQUIRE(control.getBody().value_size() == expectedBody.value_size());
-
- BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
- expectedBody.value_size()) == 0);
-
- }
-
- void
- validateList(const Data& data, const ndn::nfd::StrategyChoice& expectedChoice)
- {
- m_callbackFired = true;
- ndn::nfd::StrategyChoice choice(data.getContent().blockFromValue());
- BOOST_CHECK_EQUAL(choice.getStrategy(), expectedChoice.getStrategy());
- BOOST_CHECK_EQUAL(choice.getName(), expectedChoice.getName());
- }
-
- bool
- didCallbackFire()
- {
- return m_callbackFired;
- }
-
- void
- resetCallbackFired()
- {
- m_callbackFired = false;
- }
-
- shared_ptr<InternalFace>&
- getFace()
- {
- return m_face;
- }
-
- StrategyChoiceManager&
- getManager()
- {
- return m_manager;
- }
-
- StrategyChoice&
- getStrategyChoice()
- {
- return m_strategyChoice;
- }
-
- void
- addInterestRule(const std::string& regex,
- ndn::IdentityCertificate& certificate)
- {
- m_manager.addInterestRule(regex, certificate);
+ return ControlParameters().setName(name).setStrategy(strategy);
}
protected:
- Forwarder m_forwarder;
StrategyChoice& m_strategyChoice;
- shared_ptr<InternalFace> m_face;
StrategyChoiceManager m_manager;
- ndn::KeyChain m_keyChain;
-
-private:
- bool m_callbackFired;
};
-class AllStrategiesFixture : public StrategyChoiceManagerFixture
+BOOST_FIXTURE_TEST_SUITE(Mgmt, StrategyChoiceManagerFixture)
+BOOST_AUTO_TEST_SUITE(TestStrategyChoiceManager)
+
+BOOST_AUTO_TEST_CASE(SetStrategy)
+{
+ auto testSetStrategy = [this] (const ControlParameters& parameters) -> Name {
+ m_responses.clear();
+ auto command = makeControlCommandRequest("/localhost/nfd/strategy-choice/set", parameters);
+ receiveInterest(command);
+ return command->getName();
+ };
+
+ installStrategy("/localhost/nfd/strategy/test-strategy-a");
+ installStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%01"); // version 1
+ installStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02"); // version 2
+
+ auto parametersA = makeParameters("test", "/localhost/nfd/strategy/test-strategy-a");
+ auto parametersB = makeParameters("test", "/localhost/nfd/strategy/test-strategy-b");
+ auto parametersC1 = makeParameters("test", "/localhost/nfd/strategy/test-strategy-c/%FD%01");
+ auto parametersC = makeParameters("test", "/localhost/nfd/strategy/test-strategy-c");
+
+ auto commandNameA = testSetStrategy(parametersA); // succeed
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandNameA, makeResponse(200, "OK", parametersA)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-a");
+
+ auto commandNameB = testSetStrategy(parametersB); // not installed
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandNameB, ControlResponse(504, "Unsupported strategy")),
+ CheckResponseResult::OK);
+
+ auto commandNameC1 = testSetStrategy(parametersC1); // specified version
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandNameC1, makeResponse(200, "OK", parametersC1)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-c/%FD%01");
+
+ auto commandNameC = testSetStrategy(parametersC); // latest version
+ parametersC.setStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02"); // change to latest
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandNameC, makeResponse(200, "OK", parametersC)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-c/%FD%02");
+}
+
+BOOST_AUTO_TEST_CASE(UnsetStrategy)
+{
+ auto testUnsetStrategy = [this] (const ControlParameters& parameters) -> Name {
+ m_responses.clear();
+ auto command = makeControlCommandRequest("/localhost/nfd/strategy-choice/unset", parameters);
+ receiveInterest(command);
+ return command->getName();
+ };
+
+ installStrategy("/localhost/nfd/strategy/test-strategy-a");
+ installStrategy("/localhost/nfd/strategy/test-strategy-b");
+ installStrategy("/localhost/nfd/strategy/test-strategy-c");
+
+ BOOST_CHECK(m_strategyChoice.insert("ndn:/", "/localhost/nfd/strategy/test-strategy-a")); // root
+ BOOST_CHECK(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b")); // test
+ BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a");
+
+ auto parametersRoot = ControlParameters().setName("ndn:/"); // root prefix
+ auto parametersNone = ControlParameters().setName("/none"); // no such entry
+ auto parametersTest = ControlParameters().setName("/test"); // has such entry
+
+ BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a"); // root
+ auto commandRootName = testUnsetStrategy(parametersRoot);
+ auto expectedResponse = ControlResponse(400, "failed in validating parameters");
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandRootName, expectedResponse), CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a"); // keep as root
+
+ BOOST_CHECK_EQUAL(findStrategy("/none"), "/localhost/nfd/strategy/test-strategy-a"); // root
+ auto commandNoneName = testUnsetStrategy(parametersNone);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandNoneName, makeResponse(200, "OK", parametersNone)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(findStrategy("/none"), "/localhost/nfd/strategy/test-strategy-a"); // root
+
+ BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-b"); // self
+ auto commandTestName = testUnsetStrategy(parametersTest);
+ BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
+ BOOST_CHECK_EQUAL(checkResponse(0, commandTestName, makeResponse(200, "OK", parametersTest)),
+ CheckResponseResult::OK);
+ BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-a"); // parent
+}
+
+// @todo Remove when ndn::nfd::StrategyChoice implements operator!= and operator<<
+class StrategyChoice : public ndn::nfd::StrategyChoice
{
public:
- AllStrategiesFixture()
+ StrategyChoice() = default;
+
+ StrategyChoice(const ndn::nfd::StrategyChoice& entry)
+ : ndn::nfd::StrategyChoice(entry)
{
- m_strategyChoice.install(make_shared<DummyStrategy>(ref(m_forwarder),
- "/localhost/nfd/strategy/test-strategy-b"));
-
- const Name strategyCVersion1("/localhost/nfd/strategy/test-strategy-c/%FD%01");
- m_strategyChoice.install(make_shared<DummyStrategy>(ref(m_forwarder),
- strategyCVersion1));
-
- const Name strategyCVersion2("/localhost/nfd/strategy/test-strategy-c/%FD%02");
- m_strategyChoice.install(make_shared<DummyStrategy>(ref(m_forwarder),
- strategyCVersion2));
- }
-
- virtual
- ~AllStrategiesFixture()
- {
-
}
};
-template <typename T> class AuthorizedCommandFixture : public CommandFixture<T>
+bool
+operator!=(const StrategyChoice& left, const StrategyChoice& right)
{
-public:
- AuthorizedCommandFixture()
- {
- const std::string regex = "^<localhost><nfd><strategy-choice>";
- T::addInterestRule(regex, *CommandFixture<T>::m_certificate);
+ return left.getName() != right.getName() || left.getStrategy() != right.getStrategy();
+}
+
+std::ostream&
+operator<<(std::ostream &os, const StrategyChoice& entry)
+{
+ os << "[ " << entry.getName() << ", " << entry.getStrategy() << " ]";
+ return os;
+}
+
+BOOST_AUTO_TEST_CASE(ListChoices)
+{
+ size_t nPreInsertedStrategies = m_strategyChoice.size(); // the best-route strategy
+ std::set<Name> actualNames, actualStrategies;
+ for (auto&& entry : m_strategyChoice) {
+ actualNames.insert(entry.getPrefix());
+ actualStrategies.insert(entry.getStrategyName());
}
- virtual
- ~AuthorizedCommandFixture()
- {
-
+ size_t nEntries = 1024;
+ for (size_t i = 0 ; i < nEntries ; i++) {
+ auto name = Name("test-name").appendSegment(i);
+ auto strategy = Name("test-strategy").appendSegment(ndn::random::generateWord64());
+ auto entry = ndn::nfd::StrategyChoice().setName(name).setStrategy(strategy);
+ actualNames.insert(name);
+ actualStrategies.insert(strategy);
+ installStrategy(strategy);
+ m_strategyChoice.insert(name, strategy);
}
-};
+ nEntries += nPreInsertedStrategies;
-BOOST_FIXTURE_TEST_SUITE(MgmtStrategyChoiceManager,
- AuthorizedCommandFixture<AllStrategiesFixture>)
+ receiveInterest(makeInterest("/localhost/nfd/strategy-choice/list"));
-BOOST_FIXTURE_TEST_CASE(ShortName, AllStrategiesFixture)
-{
- shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/strategy-choice"));
+ Block content;
+ BOOST_CHECK_NO_THROW(content = concatenateResponses());
+ BOOST_CHECK_NO_THROW(content.parse());
+ BOOST_CHECK_EQUAL(content.elements().size(), nEntries);
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
+ std::vector<StrategyChoice> receivedRecords, expectedRecords;
+ for (size_t idx = 0; idx < nEntries; ++idx) {
+ BOOST_TEST_MESSAGE("processing element: " << idx);
- getFace()->sendInterest(*command);
- g_io.run_one();
+ StrategyChoice decodedEntry;
+ BOOST_REQUIRE_NO_THROW(decodedEntry.wireDecode(content.elements()[idx]));
+ receivedRecords.push_back(decodedEntry);
- BOOST_REQUIRE(didCallbackFire());
-}
+ actualNames.erase(decodedEntry.getName());
+ actualStrategies.erase(decodedEntry.getStrategy());
-BOOST_FIXTURE_TEST_CASE(MalformedCommmand, AllStrategiesFixture)
-{
- shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/strategy-choice"));
+ auto result = m_strategyChoice.get(decodedEntry.getName());
+ BOOST_REQUIRE(result.first);
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getManager().onStrategyChoiceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(UnsignedCommand, AllStrategiesFixture)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/best-route");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 401, "Signature required");
- });
-
- getManager().onStrategyChoiceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand,
- UnauthorizedCommandFixture<StrategyChoiceManagerFixture>)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/best-route");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 403, "Unauthorized command");
- });
-
- getManager().onStrategyChoiceRequest(*command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(UnsupportedVerb)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("unsupported");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 501, "Unsupported command");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(BadOptionParse)
-{
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append("NotReallyParameters");
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(SetStrategies)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- getFace()->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
- fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
- BOOST_REQUIRE_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-b");
-}
-
-BOOST_AUTO_TEST_CASE(SetStrategySpecifiedVersion)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%01");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- getFace()->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
- fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
- BOOST_REQUIRE_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-c/%FD%01");
-}
-
-BOOST_AUTO_TEST_CASE(SetStrategyLatestVersion)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/test-strategy-c");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- ControlParameters responseParameters;
- responseParameters.setName("/test");
- responseParameters.setStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02");
-
- getFace()->onReceiveData.connect([this, command, responseParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", responseParameters.wireEncode());
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
- fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
- BOOST_REQUIRE_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-c/%FD%02");
-}
-
-BOOST_AUTO_TEST_CASE(SetStrategiesMissingName)
-{
- ControlParameters parameters;
- parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_CASE(SetStrategiesMissingStrategy)
-{
- ControlParameters parameters;
- parameters.setName("/test");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
- fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
- BOOST_REQUIRE_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
-}
-
-BOOST_AUTO_TEST_CASE(SetUnsupportedStrategy)
-{
- ControlParameters parameters;
- parameters.setName("/test");
- parameters.setStrategy("/localhost/nfd/strategy/unit-test-doesnotexist");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("set");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 504, "Unsupported strategy");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
- fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
- BOOST_CHECK_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
-}
-
-class DefaultStrategyOnlyFixture : public StrategyChoiceManagerFixture
-{
-public:
- DefaultStrategyOnlyFixture()
- : StrategyChoiceManagerFixture()
- {
-
+ auto record = StrategyChoice().setName(decodedEntry.getName()).setStrategy(result.second);
+ expectedRecords.push_back(record);
}
- virtual
- ~DefaultStrategyOnlyFixture()
- {
+ BOOST_CHECK_EQUAL(actualNames.size(), 0);
+ BOOST_CHECK_EQUAL(actualStrategies.size(), 0);
- }
-};
-
-
-/// \todo I'm not sure this code branch (code 405) can happen. The manager tests for the strategy first and will return 504.
-// BOOST_FIXTURE_TEST_CASE(SetNotInstalled, DefaultStrategyOnlyFixture)
-// {
-// BOOST_REQUIRE(!getStrategyChoice().hasStrategy("/localhost/nfd/strategy/test-strategy-b"));
-// ControlParameters parameters;
-// parameters.setName("/test");
-// parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
-
-// Block encodedParameters(parameters.wireEncode());
-
-// Name commandName("/localhost/nfd/strategy-choice");
-// commandName.append("set");
-// commandName.append(encodedParameters);
-
-// shared_ptr<Interest> command(make_shared<Interest>(commandName));
-// generateCommand(*command);
-
-// getFace()->onReceiveData +=
-// bind(&StrategyChoiceManagerFixture::validateControlResponse, this, _1,
-// command->getName(), 405, "Strategy not installed");
-
-// getManager().onValidatedStrategyChoiceRequest(command);
-
-// BOOST_REQUIRE(didCallbackFire());
-// fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
-// BOOST_CHECK_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
-// }
-
-BOOST_AUTO_TEST_CASE(Unset)
-{
- ControlParameters parameters;
- parameters.setName("/test");
-
- BOOST_REQUIRE(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b"));
- BOOST_REQUIRE_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
- "/localhost/nfd/strategy/test-strategy-b");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("unset");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command, encodedParameters] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 200, "Success", encodedParameters);
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-
- BOOST_CHECK_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
- "/localhost/nfd/strategy/test-strategy-a");
+ BOOST_CHECK_EQUAL_COLLECTIONS(receivedRecords.begin(), receivedRecords.end(),
+ expectedRecords.begin(), expectedRecords.end());
}
-BOOST_AUTO_TEST_CASE(UnsetRoot)
-{
- ControlParameters parameters;
- parameters.setName("/");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("unset");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(),
- 403, "Cannot unset root prefix strategy");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-
- BOOST_CHECK_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
- "/localhost/nfd/strategy/test-strategy-a");
-}
-
-BOOST_AUTO_TEST_CASE(UnsetMissingName)
-{
- ControlParameters parameters;
-
- BOOST_REQUIRE(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b"));
- BOOST_REQUIRE_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
- "/localhost/nfd/strategy/test-strategy-b");
-
- Block encodedParameters(parameters.wireEncode());
-
- Name commandName("/localhost/nfd/strategy-choice");
- commandName.append("unset");
- commandName.append(encodedParameters);
-
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
- generateCommand(*command);
-
- getFace()->onReceiveData.connect([this, command] (const Data& response) {
- this->validateControlResponse(response, command->getName(), 400, "Malformed command");
- });
-
- getManager().onValidatedStrategyChoiceRequest(command);
-
- BOOST_REQUIRE(didCallbackFire());
-
- BOOST_CHECK_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
- "/localhost/nfd/strategy/test-strategy-b");
-}
-
-BOOST_AUTO_TEST_CASE(Publish)
-{
- Name commandName("/localhost/nfd/strategy-choice/list");
- shared_ptr<Interest> command(make_shared<Interest>(commandName));
-
- ndn::nfd::StrategyChoice expectedChoice;
- expectedChoice.setStrategy("/localhost/nfd/strategy/test-strategy-a");
- expectedChoice.setName("/");
-
- getFace()->onReceiveData.connect(bind(&StrategyChoiceManagerFixture::validateList,
- this, _1, expectedChoice));
-
- m_manager.onStrategyChoiceRequest(*command);
- BOOST_REQUIRE(didCallbackFire());
-}
-
-BOOST_AUTO_TEST_SUITE_END()
+BOOST_AUTO_TEST_SUITE_END() // TestStrategyChoiceManager
+BOOST_AUTO_TEST_SUITE_END() // Mgmt
} // namespace tests
} // namespace nfd
diff --git a/tests/daemon/mgmt/strategy-choice-publisher.t.cpp b/tests/daemon/mgmt/strategy-choice-publisher.t.cpp
deleted file mode 100644
index 8f98cb5..0000000
--- a/tests/daemon/mgmt/strategy-choice-publisher.t.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015, 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/>.
- */
-
-#ifndef NFD_TESTS_NFD_MGMT_STRATEGY_CHOICE_PUBLISHER_HPP
-#define NFD_TESTS_NFD_MGMT_STRATEGY_CHOICE_PUBLISHER_HPP
-
-#include "mgmt/strategy-choice-publisher.hpp"
-#include "mgmt/app-face.hpp"
-#include "mgmt/internal-face.hpp"
-#include "fw/forwarder.hpp"
-#include "../fw/dummy-strategy.hpp"
-
-#include "tests/test-common.hpp"
-
-#include <ndn-cxx/management/nfd-strategy-choice.hpp>
-
-namespace nfd {
-namespace tests {
-
-class StrategyChoicePublisherFixture : BaseFixture
-{
-public:
-
- StrategyChoicePublisherFixture()
- : m_strategyChoice(m_forwarder.getStrategyChoice())
- , m_face(make_shared<InternalFace>())
- , m_publisher(m_strategyChoice, *m_face, "/localhost/nfd/strategy-choice/list", m_keyChain)
- , STRATEGY_A(make_shared<DummyStrategy>(boost::ref(m_forwarder),
- "/localhost/nfd/strategy/dummy-strategy-a"))
- , STRATEGY_B(make_shared<DummyStrategy>(boost::ref(m_forwarder),
- "/localhost/nfd/strategy/dummy-strategy-b"))
- , m_finished(false)
- {
- m_strategyChoice.install(STRATEGY_A);
- m_strategyChoice.install(STRATEGY_B);
-
- ndn::nfd::StrategyChoice expectedRootEntry;
- expectedRootEntry.setStrategy(STRATEGY_A->getName());
- expectedRootEntry.setName("/");
-
- m_strategyChoice.insert("/", STRATEGY_A->getName());
- m_expectedEntries["/"] = expectedRootEntry;
- }
-
- void
- validatePublish(const Data& data)
- {
- Block payload = data.getContent();
-
- m_buffer.appendByteArray(payload.value(), payload.value_size());
-
- BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
- if (data.getFinalBlockId() != data.getName()[-1])
- {
- return;
- }
-
- // wrap the Strategy Choice entries in a single Content TLV for easy parsing
- m_buffer.prependVarNumber(m_buffer.size());
- m_buffer.prependVarNumber(tlv::Content);
-
- ndn::Block parser(m_buffer.buf(), m_buffer.size());
- parser.parse();
-
- BOOST_REQUIRE_EQUAL(parser.elements_size(), m_expectedEntries.size());
-
- for (Block::element_const_iterator i = parser.elements_begin();
- i != parser.elements_end();
- ++i)
- {
- if (i->type() != ndn::tlv::nfd::StrategyChoice)
- {
- BOOST_FAIL("expected StrategyChoice, got type #" << i->type());
- }
-
- ndn::nfd::StrategyChoice entry(*i);
-
- std::map<std::string, ndn::nfd::StrategyChoice>::const_iterator expectedEntryPos =
- m_expectedEntries.find(entry.getName().toUri());
-
- BOOST_REQUIRE(expectedEntryPos != m_expectedEntries.end());
- const ndn::nfd::StrategyChoice& expectedEntry = expectedEntryPos->second;
-
- BOOST_CHECK_EQUAL(entry.getStrategy(), expectedEntry.getStrategy());
- BOOST_CHECK_EQUAL(entry.getName(), expectedEntry.getName());
-
- m_matchedEntries.insert(entry.getName().toUri());
- }
-
- BOOST_CHECK_EQUAL(m_matchedEntries.size(), m_expectedEntries.size());
-
- m_finished = true;
- }
-
-protected:
- Forwarder m_forwarder;
- StrategyChoice& m_strategyChoice;
- shared_ptr<InternalFace> m_face;
- StrategyChoicePublisher m_publisher;
-
- shared_ptr<DummyStrategy> STRATEGY_A;
- shared_ptr<DummyStrategy> STRATEGY_B;
-
- ndn::EncodingBuffer m_buffer;
-
- std::map<std::string, ndn::nfd::StrategyChoice> m_expectedEntries;
- std::set<std::string> m_matchedEntries;
-
- bool m_finished;
-
- ndn::KeyChain m_keyChain;
-};
-
-
-
-BOOST_FIXTURE_TEST_SUITE(MgmtStrategyChoicePublisher, StrategyChoicePublisherFixture)
-
-BOOST_AUTO_TEST_CASE(Publish)
-{
- m_strategyChoice.insert("/test/a", STRATEGY_A->getName());
- m_strategyChoice.insert("/test/b", STRATEGY_B->getName());
-
- ndn::nfd::StrategyChoice expectedEntryA;
- expectedEntryA.setStrategy(STRATEGY_A->getName());
- expectedEntryA.setName("/test/a");
-
- ndn::nfd::StrategyChoice expectedEntryB;
- expectedEntryB.setStrategy(STRATEGY_B->getName());
- expectedEntryB.setName("/test/b");
-
- m_expectedEntries["/test/a"] = expectedEntryA;
- m_expectedEntries["/test/b"] = expectedEntryB;
-
- m_face->onReceiveData.connect(bind(&StrategyChoicePublisherFixture::validatePublish, this, _1));
-
- m_publisher.publish();
- BOOST_REQUIRE(m_finished);
-}
-
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace nfd
-
-#endif // NFD_TESTS_NFD_MGMT_STRATEGY_CHOICE_PUBLISHER_HPP
diff --git a/tests/daemon/mgmt/validation-common.cpp b/tests/daemon/mgmt/validation-common.cpp
deleted file mode 100644
index 6065c27..0000000
--- a/tests/daemon/mgmt/validation-common.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014 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
- *
- * 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 "validation-common.hpp"
-
-#include <boost/test/unit_test.hpp>
-
-namespace nfd {
-namespace tests {
-
-const Name CommandIdentityGlobalFixture::s_identityName("/unit-test/CommandFixture/id");
-shared_ptr<ndn::IdentityCertificate> CommandIdentityGlobalFixture::s_certificate;
-
-CommandIdentityGlobalFixture::CommandIdentityGlobalFixture()
-{
- BOOST_ASSERT(!static_cast<bool>(s_certificate));
- s_certificate = m_keys.getCertificate(m_keys.createIdentity(s_identityName));
-}
-
-CommandIdentityGlobalFixture::~CommandIdentityGlobalFixture()
-{
- s_certificate.reset();
- m_keys.deleteIdentity(s_identityName);
-}
-
-BOOST_GLOBAL_FIXTURE(CommandIdentityGlobalFixture)
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/daemon/mgmt/validation-common.hpp b/tests/daemon/mgmt/validation-common.hpp
deleted file mode 100644
index f8b1367..0000000
--- a/tests/daemon/mgmt/validation-common.hpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014 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
- *
- * 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/>.
- **/
-
-#ifndef NFD_TESTS_NFD_MGMT_VALIDATION_COMMON_HPP
-#define NFD_TESTS_NFD_MGMT_VALIDATION_COMMON_HPP
-
-#include "common.hpp"
-#include <ndn-cxx/util/command-interest-generator.hpp>
-
-namespace nfd {
-namespace tests {
-
-// class ValidatedManagementFixture
-// {
-// public:
-// ValidatedManagementFixture()
-// : m_validator(make_shared<ndn::CommandInterestValidator>())
-// {
-// }
-
-// virtual
-// ~ValidatedManagementFixture()
-// {
-// }
-
-// protected:
-// shared_ptr<ndn::CommandInterestValidator> m_validator;
-// };
-
-/// a global fixture that holds the identity for CommandFixture
-class CommandIdentityGlobalFixture
-{
-public:
- CommandIdentityGlobalFixture();
-
- ~CommandIdentityGlobalFixture();
-
- static const Name& getIdentityName()
- {
- return s_identityName;
- }
-
- static shared_ptr<ndn::IdentityCertificate> getCertificate()
- {
- BOOST_ASSERT(static_cast<bool>(s_certificate));
- return s_certificate;
- }
-
-private:
- ndn::KeyChain m_keys;
- static const Name s_identityName;
- static shared_ptr<ndn::IdentityCertificate> s_certificate;
-};
-
-template<typename T>
-class CommandFixture : public T
-{
-public:
- virtual
- ~CommandFixture()
- {
- }
-
- void
- generateCommand(Interest& interest)
- {
- m_generator.generateWithIdentity(interest, getIdentityName());
- }
-
- const Name&
- getIdentityName() const
- {
- return CommandIdentityGlobalFixture::getIdentityName();
- }
-
-protected:
- CommandFixture()
- : m_certificate(CommandIdentityGlobalFixture::getCertificate())
- {
- }
-
-protected:
- shared_ptr<ndn::IdentityCertificate> m_certificate;
- ndn::CommandInterestGenerator m_generator;
-};
-
-template <typename T>
-class UnauthorizedCommandFixture : public CommandFixture<T>
-{
-public:
- UnauthorizedCommandFixture()
- {
- }
-
- virtual
- ~UnauthorizedCommandFixture()
- {
- }
-};
-
-} // namespace tests
-} // namespace nfd
-
-#endif // NFD_TESTS_NFD_MGMT_VALIDATION_COMMON_HPP