rib: move config parsing to Service class
This commit also de-duplicates code in Service class constructors
and reduces usage of unique_ptrs.
refs #4650
Change-Id: Ibbf454841b76ffe4d569b51fef3b1d06f7d2fdfc
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index c45aede..1d9873b 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -41,27 +41,20 @@
NFD_LOG_INIT(RibManager);
-const Name RibManager::LOCAL_HOST_TOP_PREFIX = "/localhost/nfd";
-const Name RibManager::LOCAL_HOP_TOP_PREFIX = "/localhop/nfd";
-const std::string RibManager::MGMT_MODULE_NAME = "rib";
-const Name RibManager::FACES_LIST_DATASET_PREFIX = "/localhost/nfd/faces/list";
-const time::seconds RibManager::ACTIVE_FACE_FETCH_INTERVAL = time::seconds(300);
+static const std::string MGMT_MODULE_NAME = "rib";
+static const Name LOCALHOST_TOP_PREFIX = "/localhost/nfd";
+static const Name LOCALHOP_TOP_PREFIX = "/localhop/nfd";
+static const time::seconds ACTIVE_FACE_FETCH_INTERVAL = time::seconds(300);
-RibManager::RibManager(Rib& rib,
- Dispatcher& dispatcher,
- ndn::Face& face,
- ndn::nfd::Controller& controller,
- AutoPrefixPropagator& propagator)
+RibManager::RibManager(Rib& rib, ndn::Face& face, ndn::nfd::Controller& nfdController, Dispatcher& dispatcher)
: ManagerBase(dispatcher, MGMT_MODULE_NAME)
, m_rib(rib)
- , m_nfdController(controller)
+ , m_nfdController(nfdController)
+ , m_dispatcher(dispatcher)
, m_faceMonitor(face)
, m_localhostValidator(face)
, m_localhopValidator(face)
- , m_prefixPropagator(propagator)
- , m_addTopPrefix([&dispatcher] (const Name& topPrefix) {
- dispatcher.addTopPrefix(topPrefix, false);
- })
+ , m_isLocalhopEnabled(false)
{
registerCommandHandler<ndn::nfd::RibRegisterCommand>("register",
bind(&RibManager::registerEntry, this, _2, _3, _4, _5));
@@ -71,15 +64,32 @@
registerStatusDatasetHandler("list", bind(&RibManager::listEntries, this, _1, _2, _3));
}
-RibManager::~RibManager() = default;
+void
+RibManager::applyLocalhostConfig(const ConfigSection& section, const std::string& filename)
+{
+ m_localhostValidator.load(section, filename);
+}
+
+void
+RibManager::enableLocalhop(const ConfigSection& section, const std::string& filename)
+{
+ m_localhopValidator.load(section, filename);
+ m_isLocalhopEnabled = true;
+}
+
+void
+RibManager::disableLocalhop()
+{
+ m_isLocalhopEnabled = false;
+}
void
RibManager::registerWithNfd()
{
- registerTopPrefix(LOCAL_HOST_TOP_PREFIX);
+ registerTopPrefix(LOCALHOST_TOP_PREFIX);
if (m_isLocalhopEnabled) {
- registerTopPrefix(LOCAL_HOP_TOP_PREFIX);
+ registerTopPrefix(LOCALHOP_TOP_PREFIX);
}
NFD_LOG_INFO("Start monitoring face create/destroy events");
@@ -100,13 +110,6 @@
}
void
-RibManager::setConfigFile(ConfigFile& configFile)
-{
- configFile.addSectionHandler("rib",
- bind(&RibManager::onConfig, this, _1, _2, _3));
-}
-
-void
RibManager::onRibUpdateSuccess(const RibUpdate& update)
{
NFD_LOG_DEBUG("RIB update succeeded for " << update);
@@ -123,33 +126,6 @@
}
void
-RibManager::onConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename)
-{
- wantAutoPrefixPropagator = false;
- wantReadvertiseToNlsr = false;
-
- for (const auto& item : configSection) {
- if (item.first == "localhost_security") {
- m_localhostValidator.load(item.second, filename);
- }
- else if (item.first == "localhop_security") {
- m_localhopValidator.load(item.second, filename);
- m_isLocalhopEnabled = true;
- }
- else if (item.first == "auto_prefix_propagate") {
- m_prefixPropagator.loadConfig(item.second);
- wantAutoPrefixPropagator = true;
- }
- else if (item.first == "readvertise_nlsr") {
- wantReadvertiseToNlsr = ConfigFile::parseYesNo(item, "rib.readvertise_nlsr");
- }
- else {
- BOOST_THROW_EXCEPTION(Error("Unrecognized rib property: " + item.first));
- }
- }
-}
-
-void
RibManager::registerTopPrefix(const Name& topPrefix)
{
// register entry to the FIB
@@ -161,7 +137,7 @@
[=] (const auto& res) { this->onCommandPrefixAddNextHopError(topPrefix, res); });
// add top prefix to the dispatcher
- m_addTopPrefix(topPrefix);
+ m_dispatcher.addTopPrefix(topPrefix, false);
}
void
@@ -295,9 +271,9 @@
const ndn::mgmt::RejectContinuation& reject) {
BOOST_ASSERT(params != nullptr);
BOOST_ASSERT(typeid(*params) == typeid(ndn::nfd::ControlParameters));
- BOOST_ASSERT(prefix == LOCAL_HOST_TOP_PREFIX || prefix == LOCAL_HOP_TOP_PREFIX);
+ BOOST_ASSERT(prefix == LOCALHOST_TOP_PREFIX || prefix == LOCALHOP_TOP_PREFIX);
- ndn::ValidatorConfig& validator = prefix == LOCAL_HOST_TOP_PREFIX ?
+ ndn::ValidatorConfig& validator = prefix == LOCALHOST_TOP_PREFIX ?
m_localhostValidator : m_localhopValidator;
validator.validate(interest,
bind([&interest, this, accept] { extractRequester(interest, accept); }),
diff --git a/rib/rib-manager.hpp b/rib/rib-manager.hpp
index be13c44..6ef6d6b 100644
--- a/rib/rib-manager.hpp
+++ b/rib/rib-manager.hpp
@@ -42,37 +42,52 @@
namespace nfd {
namespace rib {
-class AutoPrefixPropagator;
-class Readvertise;
-
+/**
+ * @brief Serve commands and datasets in NFD RIB management protocol.
+ */
class RibManager : public nfd::ManagerBase
{
public:
class Error : public std::runtime_error
{
public:
- explicit
- Error(const std::string& what)
- : std::runtime_error(what)
- {
- }
+ using std::runtime_error::runtime_error;
};
-public:
- RibManager(Rib& rib, Dispatcher& dispatcher, ndn::Face& face,
- ndn::nfd::Controller& controller, AutoPrefixPropagator& propagator);
+ RibManager(Rib& rib, ndn::Face& face, ndn::nfd::Controller& nfdController, Dispatcher& dispatcher);
- ~RibManager() override;
+ /**
+ * @brief Apply localhost_security configuration.
+ */
+ void
+ applyLocalhostConfig(const ConfigSection& section, const std::string& filename);
+ /**
+ * @brief Apply localhop_security configuration and allow accepting commands on
+ * /localhop/nfd/rib prefix.
+ */
+ void
+ enableLocalhop(const ConfigSection& section, const std::string& filename);
+
+ /**
+ * @brief Disallow accepting commands on /localhop/nfd/rib prefix.
+ */
+ void
+ disableLocalhop();
+
+ /**
+ * @brief Start accepting commands and dataset requests.
+ */
void
registerWithNfd();
+ /**
+ * @brief Enable NDNLP IncomingFaceId field in order to support self-registration commands.
+ */
void
enableLocalFields();
- void
- setConfigFile(ConfigFile& configFile);
-
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
void
onRibUpdateSuccess(const RibUpdate& update);
@@ -81,9 +96,6 @@
private: // initialization helpers
void
- onConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename);
-
- void
registerTopPrefix(const Name& topPrefix);
private: // ControlCommand and StatusDataset
@@ -150,33 +162,23 @@
void
onEnableLocalFieldsError(const ControlResponse& response);
-public:
- bool wantAutoPrefixPropagator = false;
- bool wantReadvertiseToNlsr = false;
-
private:
Rib& m_rib;
ndn::nfd::Controller& m_nfdController;
+ Dispatcher& m_dispatcher;
+
ndn::nfd::FaceMonitor m_faceMonitor;
ndn::ValidatorConfig m_localhostValidator;
ndn::ValidatorConfig m_localhopValidator;
- bool m_isLocalhopEnabled = false;
- AutoPrefixPropagator& m_prefixPropagator;
+ bool m_isLocalhopEnabled;
private:
- static const Name LOCAL_HOST_TOP_PREFIX;
- static const Name LOCAL_HOP_TOP_PREFIX;
- static const std::string MGMT_MODULE_NAME;
- static const Name FACES_LIST_DATASET_PREFIX;
- static const time::seconds ACTIVE_FACE_FETCH_INTERVAL;
scheduler::ScopedEventId m_activeFaceFetchEvent;
typedef std::set<uint64_t> FaceIdSet;
/** \brief contains FaceIds with one or more Routes in the RIB
*/
FaceIdSet m_registeredFaces;
-
- std::function<void(const Name& topPrefix)> m_addTopPrefix;
};
} // namespace rib
diff --git a/rib/service.cpp b/rib/service.cpp
index 739883c..ddf13ed 100644
--- a/rib/service.cpp
+++ b/rib/service.cpp
@@ -27,42 +27,89 @@
#include "auto-prefix-propagator.hpp"
#include "fib-updater.hpp"
-#include "rib-manager.hpp"
#include "readvertise/client-to-nlsr-readvertise-policy.hpp"
#include "readvertise/nfd-rib-readvertise-destination.hpp"
#include "readvertise/readvertise.hpp"
#include "core/global-io.hpp"
+#include "core/logger.hpp"
#include <boost/property_tree/info_parser.hpp>
-
#include <ndn-cxx/transport/tcp-transport.hpp>
#include <ndn-cxx/transport/unix-transport.hpp>
namespace nfd {
namespace rib {
-static const std::string INTERNAL_CONFIG = "internal://nfd.conf";
-static const Name READVERTISE_NLSR_PREFIX = "/localhost/nlsr";
+NFD_LOG_INIT(RibService);
Service* Service::s_instance = nullptr;
-Service::Service(const std::string& configFile, ndn::KeyChain& keyChain)
- : m_configFile(configFile)
- , m_keyChain(keyChain)
+static const std::string CFG_SECTION = "rib";
+static const std::string CFG_LOCALHOST_SECURITY = "localhost_security";
+static const std::string CFG_LOCALHOP_SECURITY = "localhop_security";
+static const std::string CFG_PREFIX_PROPAGATE = "auto_prefix_propagate";
+static const std::string CFG_READVERTISE_NLSR = "readvertise_nlsr";
+static const Name READVERTISE_NLSR_PREFIX = "/localhost/nlsr";
+
+static ConfigSection
+loadConfigSectionFromFile(const std::string& filename)
{
- if (s_instance != nullptr) {
- BOOST_THROW_EXCEPTION(std::logic_error("RIB service cannot be instantiated more than once"));
+ ConfigSection config;
+ // Any format errors should have been caught already
+ boost::property_tree::read_info(filename, config);
+ return config;
+}
+
+/**
+ * \brief Look into the config file and construct appropriate transport to communicate with NFD
+ * If NFD-RIB instance was initialized with config file, INFO format is assumed
+ */
+static shared_ptr<ndn::Transport>
+makeLocalNfdTransport(const ConfigSection& config)
+{
+ if (config.get_child_optional("face_system.unix")) {
+ // default socket path should be the same as in UnixStreamFactory::processConfig
+ auto path = config.get<std::string>("face_system.unix.path", "/var/run/nfd.sock");
+ return make_shared<ndn::UnixTransport>(path);
}
- if (&getGlobalIoService() != &getRibIoService()) {
- BOOST_THROW_EXCEPTION(std::logic_error("RIB service must run on RIB thread"));
+ else if (config.get_child_optional("face_system.tcp") &&
+ config.get<std::string>("face_system.tcp.listen", "yes") == "yes") {
+ // default port should be the same as in TcpFactory::processConfig
+ auto port = config.get<std::string>("face_system.tcp.port", "6363");
+ return make_shared<ndn::TcpTransport>("localhost", port);
}
- s_instance = this;
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("No transport is available to communicate with NFD"));
+ }
+}
+
+Service::Service(const std::string& configFile, ndn::KeyChain& keyChain)
+ : Service(keyChain, makeLocalNfdTransport(loadConfigSectionFromFile(configFile)))
+{
+ ConfigFile config(ConfigFile::ignoreUnknownSection);
+ config.addSectionHandler(CFG_SECTION, bind(&Service::processConfig, this, _1, _2, _3));
+ config.parse(configFile, true);
+ config.parse(configFile, false);
}
Service::Service(const ConfigSection& configSection, ndn::KeyChain& keyChain)
- : m_configSection(configSection)
- , m_keyChain(keyChain)
+ : Service(keyChain, makeLocalNfdTransport(configSection))
+{
+ ConfigFile config(ConfigFile::ignoreUnknownSection);
+ config.addSectionHandler(CFG_SECTION, bind(&Service::processConfig, this, _1, _2, _3));
+ const std::string INTERNAL_CONFIG = "internal://nfd.conf";
+ config.parse(configSection, true, INTERNAL_CONFIG);
+ config.parse(configSection, false, INTERNAL_CONFIG);
+}
+
+Service::Service(ndn::KeyChain& keyChain, shared_ptr<ndn::Transport> localNfdTransport)
+ : m_keyChain(keyChain)
+ , m_face(std::move(localNfdTransport), getGlobalIoService(), m_keyChain)
+ , m_nfdController(m_face, m_keyChain)
+ , m_fibUpdater(m_rib, m_nfdController)
+ , m_dispatcher(m_face, m_keyChain)
+ , m_ribManager(m_rib, m_face, m_nfdController, m_dispatcher)
{
if (s_instance != nullptr) {
BOOST_THROW_EXCEPTION(std::logic_error("RIB service cannot be instantiated more than once"));
@@ -91,90 +138,90 @@
}
void
-Service::initialize()
+Service::processConfig(const ConfigSection& section, bool isDryRun, const std::string& filename)
{
- m_face = make_unique<ndn::Face>(getLocalNfdTransport(), getGlobalIoService(), m_keyChain);
- m_nfdController = make_unique<ndn::nfd::Controller>(*m_face, m_keyChain);
- m_fibUpdater = make_unique<FibUpdater>(m_rib, *m_nfdController);
- m_prefixPropagator = make_unique<AutoPrefixPropagator>(*m_nfdController, m_keyChain, m_rib);
- m_dispatcher = make_unique<ndn::mgmt::Dispatcher>(*m_face, m_keyChain);
- m_ribManager = make_unique<RibManager>(m_rib, *m_dispatcher, *m_face, *m_nfdController, *m_prefixPropagator);
+ if (isDryRun) {
+ checkConfig(section, filename);
+ }
+ else {
+ applyConfig(section, filename);
+ }
+}
- ConfigFile config([] (const std::string& filename, const std::string& sectionName,
- const ConfigSection& section, bool isDryRun) {
- // Ignore sections belonging to NFD, but raise an error
- // if we're missing a handler for a "rib" section.
- if (sectionName == "rib") {
- ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
+void
+Service::checkConfig(const ConfigSection& section, const std::string& filename)
+{
+ for (const auto& item : section) {
+ const std::string& key = item.first;
+ if (key == CFG_LOCALHOST_SECURITY || key == CFG_LOCALHOP_SECURITY) {
+ ndn::security::v2::validator_config::ValidationPolicyConfig policy;
+ policy.load(section, filename);
+ }
+ else if (key == CFG_PREFIX_PROPAGATE) {
+ // AutoPrefixPropagator does not support config dry-run
+ }
+ else if (key == CFG_READVERTISE_NLSR) {
+ ConfigFile::parseYesNo(item, CFG_SECTION + "." + CFG_READVERTISE_NLSR);
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option " + CFG_SECTION + "." + key));
+ }
+ }
+}
+
+void
+Service::applyConfig(const ConfigSection& section, const std::string& filename)
+{
+ bool wantPrefixPropagate = false;
+ bool wantReadvertiseNlsr = false;
+
+ for (const auto& item : section) {
+ const std::string& key = item.first;
+ const ConfigSection& value = item.second;
+ if (key == CFG_LOCALHOST_SECURITY) {
+ m_ribManager.applyLocalhostConfig(value, filename);
+ }
+ else if (key == CFG_LOCALHOP_SECURITY) {
+ m_ribManager.enableLocalhop(value, filename);
+ }
+ else if (key == CFG_PREFIX_PROPAGATE) {
+ if (m_prefixPropagator == nullptr) {
+ m_prefixPropagator = make_unique<AutoPrefixPropagator>(m_nfdController, m_keyChain, m_rib);
}
- });
- m_ribManager->setConfigFile(config);
-
- // parse config file
- if (!m_configFile.empty()) {
- config.parse(m_configFile, true);
- config.parse(m_configFile, false);
- }
- else {
- config.parse(m_configSection, true, INTERNAL_CONFIG);
- config.parse(m_configSection, false, INTERNAL_CONFIG);
+ m_prefixPropagator->loadConfig(item.second);
+ m_prefixPropagator->enable();
+ wantPrefixPropagate = true;
+ }
+ else if (key == CFG_READVERTISE_NLSR) {
+ wantReadvertiseNlsr = ConfigFile::parseYesNo(item, CFG_SECTION + "." + CFG_READVERTISE_NLSR);
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option " + CFG_SECTION + "." + key));
+ }
}
- if (m_ribManager->wantAutoPrefixPropagator) {
- m_prefixPropagator->enable();
- }
- else {
+ if (!wantPrefixPropagate && m_prefixPropagator != nullptr) {
m_prefixPropagator->disable();
}
- if (m_ribManager->wantReadvertiseToNlsr && m_readvertiseNlsr == nullptr) {
+ if (wantReadvertiseNlsr && m_readvertiseNlsr == nullptr) {
+ NFD_LOG_DEBUG("Enabling readvertise-to-nlsr");
m_readvertiseNlsr = make_unique<Readvertise>(
m_rib,
make_unique<ClientToNlsrReadvertisePolicy>(),
- make_unique<NfdRibReadvertiseDestination>(*m_nfdController, READVERTISE_NLSR_PREFIX, m_rib));
+ make_unique<NfdRibReadvertiseDestination>(m_nfdController, READVERTISE_NLSR_PREFIX, m_rib));
}
- else if (!m_ribManager->wantReadvertiseToNlsr && m_readvertiseNlsr != nullptr) {
+ else if (!wantReadvertiseNlsr && m_readvertiseNlsr != nullptr) {
+ NFD_LOG_DEBUG("Disabling readvertise-to-nlsr");
m_readvertiseNlsr.reset();
}
-
- m_ribManager->registerWithNfd();
- m_ribManager->enableLocalFields();
}
-shared_ptr<ndn::Transport>
-Service::getLocalNfdTransport()
+void
+Service::initialize()
{
- ConfigSection config;
-
- if (!m_configFile.empty()) {
- // Any format errors should have been caught already
- // If error is thrown at this point, it is development error
- boost::property_tree::read_info(m_configFile, config);
- }
- else {
- config = m_configSection;
- }
-
- if (config.get_child_optional("face_system.unix")) {
- // unix socket enabled
-
- auto socketPath = config.get<std::string>("face_system.unix.path", "/var/run/nfd.sock");
- // default socketPath should be the same as in UnixStreamFactory::processConfig
-
- return make_shared<ndn::UnixTransport>(socketPath);
- }
- else if (config.get_child_optional("face_system.tcp") &&
- config.get<std::string>("face_system.tcp.listen", "yes") == "yes") {
- // tcp is enabled
-
- auto port = config.get<std::string>("face_system.tcp.port", "6363");
- // default port should be the same as in TcpFactory::processConfig
-
- return make_shared<ndn::TcpTransport>("localhost", port);
- }
- else {
- BOOST_THROW_EXCEPTION(Error("No transport is available to communicate with NFD"));
- }
+ m_ribManager.registerWithNfd();
+ m_ribManager.enableLocalFields();
}
} // namespace rib
diff --git a/rib/service.hpp b/rib/service.hpp
index a32d996..b39f5c6 100644
--- a/rib/service.hpp
+++ b/rib/service.hpp
@@ -26,7 +26,8 @@
#ifndef NFD_RIB_SERVICE_HPP
#define NFD_RIB_SERVICE_HPP
-#include "rib.hpp"
+#include "rib-manager.hpp"
+
#include "core/config-file.hpp"
#include <ndn-cxx/face.hpp>
@@ -39,28 +40,17 @@
namespace rib {
class AutoPrefixPropagator;
-class FibUpdater;
class Readvertise;
-class RibManager;
/**
* \brief initializes and executes NFD-RIB service thread
*
- * Only one instance of this class can be created at any time
+ * Only one instance of this class can be created at any time.
+ * After initialization, NFD-RIB instance can be started by running the global io_service.
*/
class Service : noncopyable
{
public:
- class Error : public std::runtime_error
- {
- public:
- explicit
- Error(const std::string& what)
- : std::runtime_error(what)
- {
- }
- };
-
/**
* \brief create NFD-RIB service
* \param configFile absolute or relative path of configuration file
@@ -88,14 +78,6 @@
~Service();
/**
- * \brief Perform initialization of NFD-RIB instance
- *
- * After initialization, NFD-RIB instance can be started by running the global io_service
- */
- void
- initialize();
-
- /**
* \brief Get a reference to the only instance of this class
* \throw std::logic_error No instance has been constructed
* \throw std::logic_error This function is invoked on a thread other than the RIB thread
@@ -104,29 +86,33 @@
get();
private:
- /**
- * \brief Look into the config file and construct appropriate transport to communicate with NFD
- * If NFD-RIB instance was initialized with config file, INFO format is assumed
- */
- shared_ptr<ndn::Transport>
- getLocalNfdTransport();
+ Service(ndn::KeyChain& keyChain, shared_ptr<ndn::Transport> localNfdTransport);
+
+ void
+ processConfig(const ConfigSection& section, bool isDryRun, const std::string& filename);
+
+ void
+ checkConfig(const ConfigSection& section, const std::string& filename);
+
+ void
+ applyConfig(const ConfigSection& section, const std::string& filename);
+
+ void
+ initialize();
private:
static Service* s_instance;
- std::string m_configFile;
- ConfigSection m_configSection;
-
ndn::KeyChain& m_keyChain;
- Rib m_rib;
+ ndn::Face m_face;
+ ndn::nfd::Controller m_nfdController;
- unique_ptr<ndn::Face> m_face;
- unique_ptr<ndn::nfd::Controller> m_nfdController;
- unique_ptr<FibUpdater> m_fibUpdater;
+ Rib m_rib;
+ FibUpdater m_fibUpdater;
unique_ptr<AutoPrefixPropagator> m_prefixPropagator;
unique_ptr<Readvertise> m_readvertiseNlsr;
- unique_ptr<ndn::mgmt::Dispatcher> m_dispatcher;
- unique_ptr<RibManager> m_ribManager;
+ ndn::mgmt::Dispatcher m_dispatcher;
+ RibManager m_ribManager;
};
} // namespace rib