face: process face_system.tcp config section in TcpFactory
refs #3904
Change-Id: I509f07e6835a96c7ba05137529f29da76a6514fd
diff --git a/daemon/face/channel.hpp b/daemon/face/channel.hpp
index 19beb7f..1c0452d 100644
--- a/daemon/face/channel.hpp
+++ b/daemon/face/channel.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -43,7 +43,12 @@
*/
typedef function<void(uint32_t status, const std::string& reason)> FaceCreationFailedCallback;
-
+/** \brief represent a channel that communicates on a local endpoint
+ * \sa FaceSystem
+ *
+ * A channel can listen on a local endpoint and initiate outgoing connection from a local endpoint.
+ * A channel creates Face objects and retains shared ownership of them.
+ */
class Channel : noncopyable
{
public:
diff --git a/daemon/face/face-system.cpp b/daemon/face/face-system.cpp
index 0d4a308..8433a16 100644
--- a/daemon/face/face-system.cpp
+++ b/daemon/face/face-system.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,8 +25,6 @@
#include "face-system.hpp"
#include "core/logger.hpp"
-#include "core/network-interface.hpp"
-#include "core/network-interface-predicate.hpp"
#include "fw/face-table.hpp"
// ProtocolFactory includes, sorted alphabetically
@@ -51,25 +49,34 @@
FaceSystem::FaceSystem(FaceTable& faceTable)
: m_faceTable(faceTable)
{
+ ///\todo #3904 make a registry, and construct instances from registry
+ m_factories["tcp"] = make_shared<TcpFactory>();
}
std::set<const ProtocolFactory*>
FaceSystem::listProtocolFactories() const
{
std::set<const ProtocolFactory*> factories;
- for (const auto& p : m_factories) {
+ for (const auto& p : m_factoryByScheme) {
factories.insert(p.second.get());
}
return factories;
}
ProtocolFactory*
-FaceSystem::getProtocolFactory(const std::string& scheme)
+FaceSystem::getFactoryById(const std::string& id)
{
- auto found = m_factories.find(scheme);
+ auto found = m_factories.find(id);
return found == m_factories.end() ? nullptr : found->second.get();
}
+ProtocolFactory*
+FaceSystem::getFactoryByScheme(const std::string& scheme)
+{
+ auto found = m_factoryByScheme.find(scheme);
+ return found == m_factoryByScheme.end() ? nullptr : found->second.get();
+}
+
void
FaceSystem::setConfigFile(ConfigFile& configFile)
{
@@ -79,31 +86,61 @@
void
FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename)
{
+ ConfigContext context;
+ context.isDryRun = isDryRun;
+ context.addFace = bind(&FaceTable::add, &m_faceTable, _1);
+ context.m_nicList = listNetworkInterfaces();
+
+ // process sections in protocol factories
+ for (const auto& pair : m_factories) {
+ const std::string& sectionName = pair.first;
+ shared_ptr<ProtocolFactory> factory = pair.second;
+
+ std::set<std::string> oldProvidedSchemes = factory->getProvidedSchemes();
+ factory->processConfig(configSection.get_child_optional(sectionName), context);
+
+ if (!isDryRun) {
+ for (const std::string& scheme : factory->getProvidedSchemes()) {
+ m_factoryByScheme[scheme] = factory;
+ oldProvidedSchemes.erase(scheme);
+ }
+ for (const std::string& scheme : oldProvidedSchemes) {
+ m_factoryByScheme.erase(scheme);
+ }
+ }
+ }
+
+ // process other sections
std::set<std::string> seenSections;
- auto nicList = listNetworkInterfaces();
+ for (const auto& pair : configSection) {
+ const std::string& sectionName = pair.first;
+ const ConfigSection& subSection = pair.second;
- for (const auto& item : configSection) {
- if (!seenSections.insert(item.first).second) {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Duplicate \"" + item.first + "\" section"));
+ if (!seenSections.insert(sectionName).second) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Duplicate section face_system." + sectionName));
}
- if (item.first == "unix") {
- processSectionUnix(item.second, isDryRun);
+ if (m_factories.count(sectionName) > 0) {
+ continue;
}
- else if (item.first == "tcp") {
- processSectionTcp(item.second, isDryRun);
+
+ ///\todo #3521 nicfaces
+
+ ///\todo #3904 process these in protocol factory
+ if (sectionName == "unix") {
+ processSectionUnix(subSection, isDryRun);
}
- else if (item.first == "udp") {
- processSectionUdp(item.second, isDryRun, nicList);
+ else if (sectionName == "udp") {
+ processSectionUdp(subSection, isDryRun, context.m_nicList);
}
- else if (item.first == "ether") {
- processSectionEther(item.second, isDryRun, nicList);
+ else if (sectionName == "ether") {
+ processSectionEther(subSection, isDryRun, context.m_nicList);
}
- else if (item.first == "websocket") {
- processSectionWebSocket(item.second, isDryRun);
+ else if (sectionName == "websocket") {
+ processSectionWebSocket(subSection, isDryRun);
}
else {
- BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + item.first + "\""));
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system." + sectionName));
}
}
}
@@ -131,12 +168,12 @@
}
if (!isDryRun) {
- if (m_factories.count("unix") > 0) {
+ if (m_factoryByScheme.count("unix") > 0) {
return;
}
auto factory = make_shared<UnixStreamFactory>();
- m_factories.emplace("unix", factory);
+ m_factoryByScheme.emplace("unix", factory);
auto channel = factory->createChannel(path);
channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
@@ -148,77 +185,6 @@
}
void
-FaceSystem::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
-{
- // ; the tcp section contains settings of TCP faces and channels
- // tcp
- // {
- // listen yes ; set to 'no' to disable TCP listener, default 'yes'
- // port 6363 ; TCP listener port number
- // }
-
- uint16_t port = 6363;
- bool needToListen = true;
- bool enableV4 = true;
- bool enableV6 = true;
-
- for (const auto& i : configSection) {
- if (i.first == "port") {
- port = ConfigFile::parseNumber<uint16_t>(i, "tcp");
- NFD_LOG_TRACE("TCP port set to " << port);
- }
- else if (i.first == "listen") {
- needToListen = ConfigFile::parseYesNo(i, "tcp");
- }
- else if (i.first == "enable_v4") {
- enableV4 = ConfigFile::parseYesNo(i, "tcp");
- }
- else if (i.first == "enable_v6") {
- enableV6 = ConfigFile::parseYesNo(i, "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 TCP 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;
- }
-
- auto factory = make_shared<TcpFactory>();
- m_factories.emplace("tcp", factory);
-
- if (enableV4) {
- tcp::Endpoint endpoint(boost::asio::ip::tcp::v4(), port);
- shared_ptr<TcpChannel> v4Channel = factory->createChannel(endpoint);
- if (needToListen) {
- v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
- }
-
- m_factories.emplace("tcp4", factory);
- }
-
- if (enableV6) {
- tcp::Endpoint endpoint(boost::asio::ip::tcp::v6(), port);
- shared_ptr<TcpChannel> v6Channel = factory->createChannel(endpoint);
- if (needToListen) {
- v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
- }
-
- m_factories.emplace("tcp6", factory);
- }
- }
-}
-
-void
FaceSystem::processSectionUdp(const ConfigSection& configSection, bool isDryRun,
const std::vector<NetworkInterfaceInfo>& nicList)
{
@@ -310,13 +276,13 @@
if (!isDryRun) {
shared_ptr<UdpFactory> factory;
bool isReload = false;
- if (m_factories.count("udp") > 0) {
+ if (m_factoryByScheme.count("udp") > 0) {
isReload = true;
- factory = static_pointer_cast<UdpFactory>(m_factories["udp"]);
+ factory = static_pointer_cast<UdpFactory>(m_factoryByScheme["udp"]);
}
else {
factory = make_shared<UdpFactory>();
- m_factories.emplace("udp", factory);
+ m_factoryByScheme.emplace("udp", factory);
}
if (!isReload && enableV4) {
@@ -324,7 +290,7 @@
shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
- m_factories.emplace("udp4", factory);
+ m_factoryByScheme.emplace("udp4", factory);
}
if (!isReload && enableV6) {
@@ -332,7 +298,7 @@
shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
- m_factories.emplace("udp6", factory);
+ m_factoryByScheme.emplace("udp6", factory);
}
std::set<shared_ptr<Face>> multicastFacesToRemove;
@@ -416,12 +382,12 @@
if (!isDryRun) {
shared_ptr<EthernetFactory> factory;
- if (m_factories.count("ether") > 0) {
- factory = static_pointer_cast<EthernetFactory>(m_factories["ether"]);
+ if (m_factoryByScheme.count("ether") > 0) {
+ factory = static_pointer_cast<EthernetFactory>(m_factoryByScheme["ether"]);
}
else {
factory = make_shared<EthernetFactory>();
- m_factories.emplace("ether", factory);
+ m_factoryByScheme.emplace("ether", factory);
}
std::set<shared_ptr<Face>> multicastFacesToRemove;
@@ -505,12 +471,12 @@
}
if (!isDryRun) {
- if (m_factories.count("websocket") > 0) {
+ if (m_factoryByScheme.count("websocket") > 0) {
return;
}
auto factory = make_shared<WebSocketFactory>();
- m_factories.emplace("websocket", factory);
+ m_factoryByScheme.emplace("websocket", factory);
shared_ptr<WebSocketChannel> channel;
@@ -518,13 +484,13 @@
websocket::Endpoint endpoint(boost::asio::ip::address_v6::any(), port);
channel = factory->createChannel(endpoint);
- m_factories.emplace("websocket46", factory);
+ m_factoryByScheme.emplace("websocket46", factory);
}
else if (enableV4) {
websocket::Endpoint endpoint(boost::asio::ip::address_v4::any(), port);
channel = factory->createChannel(endpoint);
- m_factories.emplace("websocket4", factory);
+ m_factoryByScheme.emplace("websocket4", factory);
}
if (channel && needToListen) {
diff --git a/daemon/face/face-system.hpp b/daemon/face/face-system.hpp
index 22b2a14..48e3ea2 100644
--- a/daemon/face/face-system.hpp
+++ b/daemon/face/face-system.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -26,20 +26,23 @@
#ifndef NFD_DAEMON_FACE_FACE_SYSTEM_HPP
#define NFD_DAEMON_FACE_FACE_SYSTEM_HPP
+#include "channel.hpp"
#include "core/config-file.hpp"
-#include "protocol-factory.hpp"
+#include "core/network-interface.hpp"
+#include "core/network-interface-predicate.hpp"
namespace nfd {
class FaceTable;
-class NetworkInterfaceInfo;
namespace face {
+class ProtocolFactory;
+
/** \brief entry point of the face system
*
- * FaceSystem class is the entry point of NFD's face system.
- * It owns ProtocolFactory objects that are created from face_system section of NFD configuration file.
+ * NFD's face system is organized as a FaceSystem-ProtocolFactory-Channel-Face hierarchy.
+ * FaceSystem class is the entry point of NFD's face system and owns ProtocolFactory objects.
*/
class FaceSystem : noncopyable
{
@@ -52,16 +55,44 @@
std::set<const ProtocolFactory*>
listProtocolFactories() const;
- /** \return ProtocolFactory for specified protocol scheme, or nullptr if not found
+ /** \return ProtocolFactory for the specified registered factory id or nullptr if not found
*/
ProtocolFactory*
- getProtocolFactory(const std::string& scheme);
+ getFactoryById(const std::string& id);
+
+ /** \return ProtocolFactory for the specified FaceUri scheme or nullptr if not found
+ */
+ ProtocolFactory*
+ getFactoryByScheme(const std::string& scheme);
/** \brief register handler for face_system section of NFD configuration file
*/
void
setConfigFile(ConfigFile& configFile);
+ /** \brief context for processing a config section in ProtocolFactory
+ */
+ class ConfigContext : noncopyable
+ {
+ public:
+ const std::vector<NetworkInterfaceInfo>&
+ listNics() const
+ {
+ ///\todo get NIC list from NetworkMonitor
+ return m_nicList;
+ }
+
+ public:
+ bool isDryRun;
+ FaceCreatedCallback addFace;
+ ///\todo add NetworkMonitor
+
+ private:
+ std::vector<NetworkInterfaceInfo> m_nicList;
+
+ friend class FaceSystem;
+ };
+
private:
void
processConfig(const ConfigSection& configSection, bool isDryRun,
@@ -71,9 +102,6 @@
processSectionUnix(const ConfigSection& configSection, bool isDryRun);
void
- processSectionTcp(const ConfigSection& configSection, bool isDryRun);
-
- void
processSectionUdp(const ConfigSection& configSection, bool isDryRun,
const std::vector<NetworkInterfaceInfo>& nicList);
@@ -85,11 +113,18 @@
processSectionWebSocket(const ConfigSection& configSection, bool isDryRun);
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /** \brief config section name => protocol factory
+ *
+ * \todo #3904 store unique_ptr<ProtocolFactory> here, and reference_wrapper<ProtocolFactory>
+ * in m_factoryByScheme
+ */
+ std::map<std::string, shared_ptr<ProtocolFactory>> m_factories;
+
/** \brief scheme => protocol factory
*
* The same protocol factory may be available under multiple schemes.
*/
- std::map<std::string, shared_ptr<ProtocolFactory>> m_factories;
+ std::map<std::string, shared_ptr<ProtocolFactory>> m_factoryByScheme;
FaceTable& m_faceTable;
};
diff --git a/daemon/face/protocol-factory.hpp b/daemon/face/protocol-factory.hpp
index ee19063..328d46e 100644
--- a/daemon/face/protocol-factory.hpp
+++ b/daemon/face/protocol-factory.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -27,14 +27,22 @@
#define NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
#include "channel.hpp"
+#include "face-system.hpp"
#include <ndn-cxx/encoding/nfd-constants.hpp>
+#include <boost/range/adaptor/map.hpp>
+#include <boost/range/algorithm/copy.hpp>
namespace nfd {
+namespace face {
-/**
- * \brief Abstract base class for all protocol factories
+/** \brief provide support for an underlying protocol
+ * \sa FaceSystem
+ *
+ * A protocol factory provides support for an underlying protocol and owns Channel objects.
+ * It can process a subsection of face_system config section and create channels and multicast
+ * faces accordingly.
*/
-class ProtocolFactory
+class ProtocolFactory : noncopyable
{
public:
/**
@@ -50,6 +58,29 @@
}
};
+ /** \brief process face_system subsection that corresponds to this ProtocolFactory type
+ * \param configSection the configuration section or boost::null to indicate it is omitted
+ * \param context provides access to data structures and contextual information
+ * \throw ConfigFile::Error invalid configuration
+ *
+ * This function updates \p providedSchemes
+ */
+ virtual void
+ processConfig(OptionalConfigSection configSection,
+ FaceSystem::ConfigContext& context)
+ {
+ ///\todo implement in every subclass and make this pure-virtual
+ BOOST_THROW_EXCEPTION(Error("processConfig is not implemented"));
+ }
+
+ /** \return FaceUri schemes accepted by this ProtocolFactory
+ */
+ const std::set<std::string>&
+ getProvidedSchemes()
+ {
+ return providedSchemes;
+ }
+
/** \brief Try to create Face using the supplied FaceUri
*
* This method should automatically choose channel, based on supplied FaceUri
@@ -72,8 +103,27 @@
virtual std::vector<shared_ptr<const Channel>>
getChannels() const = 0;
+
+protected:
+ template<typename ChannelMap>
+ static std::vector<shared_ptr<const Channel>>
+ getChannelsFromMap(const ChannelMap& channelMap)
+ {
+ std::vector<shared_ptr<const Channel>> channels;
+ boost::copy(channelMap | boost::adaptors::map_values, std::back_inserter(channels));
+ return channels;
+ }
+
+protected:
+ /** \brief FaceUri schemes provided by this ProtocolFactory
+ */
+ std::set<std::string> providedSchemes;
};
+} // namespace face
+
+using face::ProtocolFactory;
+
} // namespace nfd
#endif // NFD_DAEMON_FACE_PROTOCOL_FACTORY_HPP
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index 8ae2337..a3028b5 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -25,77 +25,93 @@
#include "tcp-factory.hpp"
#include "core/logger.hpp"
-#include "core/network-interface.hpp"
namespace nfd {
+namespace face {
namespace ip = boost::asio::ip;
NFD_LOG_INIT("TcpFactory");
void
-TcpFactory::prohibitEndpoint(const tcp::Endpoint& endpoint)
+TcpFactory::processConfig(OptionalConfigSection configSection,
+ FaceSystem::ConfigContext& context)
{
- if (endpoint.address().is_v4() &&
- endpoint.address() == ip::address_v4::any()) {
- prohibitAllIpv4Endpoints(endpoint.port());
- }
- else if (endpoint.address().is_v6() &&
- endpoint.address() == ip::address_v6::any()) {
- prohibitAllIpv6Endpoints(endpoint.port());
+ // tcp
+ // {
+ // listen yes
+ // port 6363
+ // enable_v4 yes
+ // enable_v6 yes
+ // }
+
+ if (!configSection) {
+ if (!context.isDryRun && !m_channels.empty()) {
+ NFD_LOG_WARN("Cannot disable tcp4 and tcp6 channels after initialization");
+ }
+ return;
}
- NFD_LOG_TRACE("prohibiting TCP " << endpoint);
- m_prohibitedEndpoints.insert(endpoint);
-}
+ bool wantListen = true;
+ uint16_t port = 6363;
+ bool enableV4 = true;
+ bool enableV6 = true;
-void
-TcpFactory::prohibitAllIpv4Endpoints(uint16_t port)
-{
- for (const NetworkInterfaceInfo& nic : listNetworkInterfaces()) {
- for (const auto& addr : nic.ipv4Addresses) {
- if (addr != ip::address_v4::any()) {
- prohibitEndpoint(tcp::Endpoint(addr, port));
- }
+ for (const auto& pair : *configSection) {
+ const std::string& key = pair.first;
+
+ if (key == "listen") {
+ wantListen = ConfigFile::parseYesNo(pair, "face_system.tcp");
+ }
+ else if (key == "port") {
+ port = ConfigFile::parseNumber<uint16_t>(pair, "face_system.tcp");
+ }
+ else if (key == "enable_v4") {
+ enableV4 = ConfigFile::parseYesNo(pair, "face_system.tcp");
+ }
+ else if (key == "enable_v6") {
+ enableV6 = ConfigFile::parseYesNo(pair, "face_system.tcp");
+ }
+ else {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.tcp." + key));
}
}
-}
-void
-TcpFactory::prohibitAllIpv6Endpoints(uint16_t port)
-{
- for (const NetworkInterfaceInfo& nic : listNetworkInterfaces()) {
- for (const auto& addr : nic.ipv6Addresses) {
- if (addr != ip::address_v6::any()) {
- prohibitEndpoint(tcp::Endpoint(addr, port));
+ if (!enableV4 && !enableV6) {
+ BOOST_THROW_EXCEPTION(ConfigFile::Error(
+ "IPv4 and IPv6 TCP channels have been disabled. Remove face_system.tcp section to disable "
+ "TCP channels or enable at least one channel type."));
+ }
+
+ if (!context.isDryRun) {
+ providedSchemes.insert("tcp");
+
+ if (enableV4) {
+ tcp::Endpoint endpoint(ip::tcp::v4(), port);
+ shared_ptr<TcpChannel> v4Channel = this->createChannel(endpoint);
+ if (wantListen && !v4Channel->isListening()) {
+ v4Channel->listen(context.addFace, nullptr);
}
+ providedSchemes.insert("tcp4");
+ }
+ else if (providedSchemes.count("tcp4") > 0) {
+ NFD_LOG_WARN("Cannot close tcp4 channel after its creation");
+ }
+
+ if (enableV6) {
+ tcp::Endpoint endpoint(ip::tcp::v6(), port);
+ shared_ptr<TcpChannel> v6Channel = this->createChannel(endpoint);
+ if (wantListen && !v6Channel->isListening()) {
+ v6Channel->listen(context.addFace, nullptr);
+ }
+ providedSchemes.insert("tcp6");
+ }
+ else if (providedSchemes.count("tcp6") > 0) {
+ NFD_LOG_WARN("Cannot close tcp6 channel after its creation");
}
}
}
-shared_ptr<TcpChannel>
-TcpFactory::createChannel(const tcp::Endpoint& endpoint)
-{
- auto channel = findChannel(endpoint);
- if (channel)
- return channel;
-
- channel = make_shared<TcpChannel>(endpoint);
- m_channels[endpoint] = channel;
- prohibitEndpoint(endpoint);
-
- NFD_LOG_DEBUG("Channel [" << endpoint << "] created");
- return channel;
-}
-
-shared_ptr<TcpChannel>
-TcpFactory::createChannel(const std::string& localIp, const std::string& localPort)
-{
- tcp::Endpoint endpoint(ip::address::from_string(localIp),
- boost::lexical_cast<uint16_t>(localPort));
- return createChannel(endpoint);
-}
-
void
TcpFactory::createFace(const FaceUri& uri,
ndn::nfd::FacePersistency persistency,
@@ -146,16 +162,75 @@
onFailure(504, "No channels available to connect");
}
+void
+TcpFactory::prohibitEndpoint(const tcp::Endpoint& endpoint)
+{
+ if (endpoint.address().is_v4() &&
+ endpoint.address() == ip::address_v4::any()) {
+ prohibitAllIpv4Endpoints(endpoint.port());
+ }
+ else if (endpoint.address().is_v6() &&
+ endpoint.address() == ip::address_v6::any()) {
+ prohibitAllIpv6Endpoints(endpoint.port());
+ }
+
+ NFD_LOG_TRACE("prohibiting TCP " << endpoint);
+ m_prohibitedEndpoints.insert(endpoint);
+}
+
+void
+TcpFactory::prohibitAllIpv4Endpoints(uint16_t port)
+{
+ ///\todo prohibited endpoints need to react to dynamic NIC changes
+ for (const NetworkInterfaceInfo& nic : listNetworkInterfaces()) {
+ for (const auto& addr : nic.ipv4Addresses) {
+ if (addr != ip::address_v4::any()) {
+ prohibitEndpoint(tcp::Endpoint(addr, port));
+ }
+ }
+ }
+}
+
+void
+TcpFactory::prohibitAllIpv6Endpoints(uint16_t port)
+{
+ ///\todo prohibited endpoints need to react to dynamic NIC changes
+ for (const NetworkInterfaceInfo& nic : listNetworkInterfaces()) {
+ for (const auto& addr : nic.ipv6Addresses) {
+ if (addr != ip::address_v6::any()) {
+ prohibitEndpoint(tcp::Endpoint(addr, port));
+ }
+ }
+ }
+}
+
+shared_ptr<TcpChannel>
+TcpFactory::createChannel(const tcp::Endpoint& endpoint)
+{
+ auto channel = findChannel(endpoint);
+ if (channel)
+ return channel;
+
+ channel = make_shared<TcpChannel>(endpoint);
+ m_channels[endpoint] = channel;
+ prohibitEndpoint(endpoint);
+
+ NFD_LOG_DEBUG("Channel [" << endpoint << "] created");
+ return channel;
+}
+
+shared_ptr<TcpChannel>
+TcpFactory::createChannel(const std::string& localIp, const std::string& localPort)
+{
+ tcp::Endpoint endpoint(ip::address::from_string(localIp),
+ boost::lexical_cast<uint16_t>(localPort));
+ return createChannel(endpoint);
+}
+
std::vector<shared_ptr<const Channel>>
TcpFactory::getChannels() const
{
- std::vector<shared_ptr<const Channel>> channels;
- channels.reserve(m_channels.size());
-
- for (const auto& i : m_channels)
- channels.push_back(i.second);
-
- return channels;
+ return getChannelsFromMap(m_channels);
}
shared_ptr<TcpChannel>
@@ -168,4 +243,5 @@
return nullptr;
}
+} // namespace face
} // namespace nfd
diff --git a/daemon/face/tcp-factory.hpp b/daemon/face/tcp-factory.hpp
index 2ed6ad1..161c490 100644
--- a/daemon/face/tcp-factory.hpp
+++ b/daemon/face/tcp-factory.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -30,10 +30,26 @@
#include "tcp-channel.hpp"
namespace nfd {
+namespace face {
+/** \brief protocol factory for TCP over IPv4 and IPv6
+ */
class TcpFactory : public ProtocolFactory
{
public:
+ /** \brief process face_system.tcp config section
+ */
+ void
+ processConfig(OptionalConfigSection configSection,
+ FaceSystem::ConfigContext& context) override;
+
+ void
+ createFace(const FaceUri& uri,
+ ndn::nfd::FacePersistency persistency,
+ bool wantLocalFieldsEnabled,
+ const FaceCreatedCallback& onCreated,
+ const FaceCreationFailedCallback& onFailure) override;
+
/**
* \brief Create TCP-based channel using tcp::Endpoint
*
@@ -63,15 +79,7 @@
shared_ptr<TcpChannel>
createChannel(const std::string& localIp, const std::string& localPort);
-public: // from ProtocolFactory
- virtual void
- createFace(const FaceUri& uri,
- ndn::nfd::FacePersistency persistency,
- bool wantLocalFieldsEnabled,
- const FaceCreatedCallback& onCreated,
- const FaceCreationFailedCallback& onFailure) override;
-
- virtual std::vector<shared_ptr<const Channel>>
+ std::vector<shared_ptr<const Channel>>
getChannels() const override;
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
@@ -101,6 +109,7 @@
std::set<tcp::Endpoint> m_prohibitedEndpoints;
};
+} // namespace face
} // namespace nfd
#endif // NFD_DAEMON_FACE_TCP_FACTORY_HPP