face: FaceSystem class
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. This responsibility is split from FaceManager. This commit also adds test coverage for face_system.websocket config section processing routine. refs #3904 Change-Id: If9a23c23b81f03d2b76c29febb3f29e6007d595b
This commit is contained in:
1 parent
81a9a86305
commit
b859031855
8 files changed
+1255
-1003
No files matched your search
@@ -50,5 +50,5 @@ export ASAN_OPTIONS
|
||||
# Then use sudo to run those tests that need superuser powers
|
||||
sudo ./build/unit-tests-core -t TestPrivilegeHelper $(ut_log_args core-privilege)
|
||||
sudo ./build/unit-tests-daemon -t Face/TestEthernetFactory,TestEthernetTransport $(ut_log_args daemon-ethernet)
|
||||
sudo ./build/unit-tests-daemon -t Face/TestFaceSystem/Config* $(ut_log_args daemon-face-config)
|
||||
sudo ./build/unit-tests-daemon -t Mgmt/TestGeneralConfigSection/UserAndGroupConfig,NoUserConfig $(ut_log_args daemon-user-config)
|
||||
sudo ./build/unit-tests-daemon -t Mgmt/TestFaceManager/ProcessConfig/ProcessSectionUdp,ProcessSectionUdpMulticastReinit,ProcessSectionEther,ProcessSectionEtherMulticastReinit $(ut_log_args daemon-face-manager-config)
|
||||
@@ -0,0 +1,541 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2016, 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-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
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#include "ethernet-factory.hpp"
|
||||
#include "ethernet-transport.hpp"
|
||||
#endif // HAVE_LIBPCAP
|
||||
#include "tcp-factory.hpp"
|
||||
#include "udp-factory.hpp"
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
#include "unix-stream-factory.hpp"
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
#ifdef HAVE_WEBSOCKET
|
||||
#include "websocket-factory.hpp"
|
||||
#endif // HAVE_WEBSOCKET
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
|
||||
NFD_LOG_INIT("FaceSystem");
|
||||
|
||||
FaceSystem::FaceSystem(FaceTable& faceTable)
|
||||
: m_faceTable(faceTable)
|
||||
{
|
||||
}
|
||||
|
||||
std::set<const ProtocolFactory*>
|
||||
FaceSystem::listProtocolFactories() const
|
||||
{
|
||||
std::set<const ProtocolFactory*> factories;
|
||||
for (const auto& p : m_factories) {
|
||||
factories.insert(p.second.get());
|
||||
}
|
||||
return factories;
|
||||
}
|
||||
|
||||
ProtocolFactory*
|
||||
FaceSystem::getProtocolFactory(const std::string& scheme)
|
||||
{
|
||||
auto found = m_factories.find(scheme);
|
||||
return found == m_factories.end() ? nullptr : found->second.get();
|
||||
}
|
||||
|
||||
void
|
||||
FaceSystem::setConfigFile(ConfigFile& configFile)
|
||||
{
|
||||
configFile.addSectionHandler("face_system", bind(&FaceSystem::processConfig, this, _1, _2, _3));
|
||||
}
|
||||
|
||||
void
|
||||
FaceSystem::processConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename)
|
||||
{
|
||||
std::set<std::string> seenSections;
|
||||
auto nicList = listNetworkInterfaces();
|
||||
|
||||
for (const auto& item : configSection) {
|
||||
if (!seenSections.insert(item.first).second) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Duplicate \"" + item.first + "\" section"));
|
||||
}
|
||||
|
||||
if (item.first == "unix") {
|
||||
processSectionUnix(item.second, isDryRun);
|
||||
}
|
||||
else if (item.first == "tcp") {
|
||||
processSectionTcp(item.second, isDryRun);
|
||||
}
|
||||
else if (item.first == "udp") {
|
||||
processSectionUdp(item.second, isDryRun, nicList);
|
||||
}
|
||||
else if (item.first == "ether") {
|
||||
processSectionEther(item.second, isDryRun, nicList);
|
||||
}
|
||||
else if (item.first == "websocket") {
|
||||
processSectionWebSocket(item.second, isDryRun);
|
||||
}
|
||||
else {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + item.first + "\""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FaceSystem::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
|
||||
{
|
||||
// ; the unix section contains settings of Unix stream faces and channels
|
||||
// unix
|
||||
// {
|
||||
// path /var/run/nfd.sock ; Unix stream listener path
|
||||
// }
|
||||
|
||||
#if defined(HAVE_UNIX_SOCKETS)
|
||||
std::string path = "/var/run/nfd.sock";
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
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;
|
||||
}
|
||||
|
||||
auto factory = make_shared<UnixStreamFactory>();
|
||||
m_factories.emplace("unix", factory);
|
||||
|
||||
auto channel = factory->createChannel(path);
|
||||
channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
|
||||
}
|
||||
#else
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
|
||||
"cannot process \"unix\" section"));
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// ; the udp section contains settings of UDP faces and channels
|
||||
// udp
|
||||
// {
|
||||
// port 6363 ; UDP unicast port number
|
||||
// idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
|
||||
// keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
|
||||
|
||||
// ; NFD creates one UDP multicast face per NIC
|
||||
// mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
|
||||
// mcast_port 56363 ; UDP multicast port number
|
||||
// mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
|
||||
// }
|
||||
|
||||
uint16_t port = 6363;
|
||||
bool enableV4 = true;
|
||||
bool enableV6 = true;
|
||||
size_t timeout = 600;
|
||||
size_t keepAliveInterval = 25;
|
||||
bool useMcast = true;
|
||||
auto mcastGroup = boost::asio::ip::address_v4::from_string("224.0.23.170");
|
||||
uint16_t mcastPort = 56363;
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
if (i.first == "port") {
|
||||
port = ConfigFile::parseNumber<uint16_t>(i, "udp");
|
||||
NFD_LOG_TRACE("UDP unicast port set to " << port);
|
||||
}
|
||||
else if (i.first == "enable_v4") {
|
||||
enableV4 = ConfigFile::parseYesNo(i, "udp");
|
||||
}
|
||||
else if (i.first == "enable_v6") {
|
||||
enableV6 = ConfigFile::parseYesNo(i, "udp");
|
||||
}
|
||||
else if (i.first == "idle_timeout") {
|
||||
try {
|
||||
timeout = i.second.get_value<size_t>();
|
||||
}
|
||||
catch (const boost::property_tree::ptree_bad_data&) {
|
||||
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 boost::property_tree::ptree_bad_data&) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
|
||||
i.first + "\" in \"udp\" section"));
|
||||
}
|
||||
}
|
||||
else if (i.first == "mcast") {
|
||||
useMcast = ConfigFile::parseYesNo(i, "udp");
|
||||
}
|
||||
else if (i.first == "mcast_port") {
|
||||
mcastPort = ConfigFile::parseNumber<uint16_t>(i, "udp");
|
||||
NFD_LOG_TRACE("UDP multicast port set to " << mcastPort);
|
||||
}
|
||||
else if (i.first == "mcast_group") {
|
||||
boost::system::error_code ec;
|
||||
mcastGroup = boost::asio::ip::address_v4::from_string(i.second.get_value<std::string>(), ec);
|
||||
if (ec) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
|
||||
i.first + "\" in \"udp\" section"));
|
||||
}
|
||||
NFD_LOG_TRACE("UDP multicast group set to " << mcastGroup);
|
||||
}
|
||||
else {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
|
||||
i.first + "\" in \"udp\" section"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!enableV4 && !enableV6) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 UDP 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>();
|
||||
m_factories.emplace("udp", factory);
|
||||
}
|
||||
|
||||
if (!isReload && enableV4) {
|
||||
udp::Endpoint endpoint(boost::asio::ip::udp::v4(), port);
|
||||
shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
|
||||
v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
|
||||
|
||||
m_factories.emplace("udp4", factory);
|
||||
}
|
||||
|
||||
if (!isReload && enableV6) {
|
||||
udp::Endpoint endpoint(boost::asio::ip::udp::v6(), port);
|
||||
shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
|
||||
v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
|
||||
|
||||
m_factories.emplace("udp6", factory);
|
||||
}
|
||||
|
||||
std::set<shared_ptr<Face>> multicastFacesToRemove;
|
||||
for (const auto& i : factory->getMulticastFaces()) {
|
||||
multicastFacesToRemove.insert(i.second);
|
||||
}
|
||||
|
||||
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;
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
udp::Endpoint mcastEndpoint(mcastGroup, mcastPort);
|
||||
for (const auto& nic : ipv4MulticastInterfaces) {
|
||||
udp::Endpoint localEndpoint(nic.ipv4Addresses[0], mcastPort);
|
||||
auto newFace = factory->createMulticastFace(localEndpoint, mcastEndpoint,
|
||||
isNicNameNecessary ? nic.name : "");
|
||||
m_faceTable.add(newFace);
|
||||
multicastFacesToRemove.erase(newFace);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& face : multicastFacesToRemove) {
|
||||
face->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FaceSystem::processSectionEther(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::vector<NetworkInterfaceInfo>& nicList)
|
||||
{
|
||||
// ; the ether section contains settings of Ethernet faces and channels
|
||||
// ether
|
||||
// {
|
||||
// ; NFD creates one Ethernet multicast face per NIC
|
||||
// mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
|
||||
// mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
|
||||
// }
|
||||
|
||||
#if defined(HAVE_LIBPCAP)
|
||||
NetworkInterfacePredicate nicPredicate;
|
||||
bool useMcast = true;
|
||||
ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
if (i.first == "mcast") {
|
||||
useMcast = ConfigFile::parseYesNo(i, "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"));
|
||||
}
|
||||
NFD_LOG_TRACE("Ethernet multicast group set to " << mcastGroup);
|
||||
}
|
||||
else if (i.first == "whitelist") {
|
||||
nicPredicate.parseWhitelist(i.second);
|
||||
}
|
||||
else if (i.first == "blacklist") {
|
||||
nicPredicate.parseBlacklist(i.second);
|
||||
}
|
||||
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.emplace("ether", factory);
|
||||
}
|
||||
|
||||
std::set<shared_ptr<Face>> multicastFacesToRemove;
|
||||
for (const auto& i : factory->getMulticastFaces()) {
|
||||
multicastFacesToRemove.insert(i.second);
|
||||
}
|
||||
|
||||
if (useMcast) {
|
||||
for (const auto& nic : nicList) {
|
||||
if (nic.isUp() && nic.isMulticastCapable() && nicPredicate(nic)) {
|
||||
try {
|
||||
auto newFace = factory->createMulticastFace(nic, mcastGroup);
|
||||
m_faceTable.add(newFace);
|
||||
multicastFacesToRemove.erase(newFace);
|
||||
}
|
||||
catch (const EthernetFactory::Error& factoryError) {
|
||||
NFD_LOG_ERROR(factoryError.what() << ", continuing");
|
||||
}
|
||||
catch (const EthernetTransport::Error& faceError) {
|
||||
NFD_LOG_ERROR(faceError.what() << ", continuing");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& face : multicastFacesToRemove) {
|
||||
face->close();
|
||||
}
|
||||
}
|
||||
#else
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section"));
|
||||
#endif // HAVE_LIBPCAP
|
||||
}
|
||||
|
||||
void
|
||||
FaceSystem::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
|
||||
{
|
||||
// ; the websocket section contains settings of WebSocket faces and channels
|
||||
// websocket
|
||||
// {
|
||||
// listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
|
||||
// port 9696 ; WebSocket listener port number
|
||||
// enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
|
||||
// enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
|
||||
// }
|
||||
|
||||
#if defined(HAVE_WEBSOCKET)
|
||||
uint16_t port = 9696;
|
||||
bool needToListen = true;
|
||||
bool enableV4 = true;
|
||||
bool enableV6 = true;
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
if (i.first == "port") {
|
||||
port = ConfigFile::parseNumber<uint16_t>(i, "websocket");
|
||||
NFD_LOG_TRACE("WebSocket port set to " << port);
|
||||
}
|
||||
else if (i.first == "listen") {
|
||||
needToListen = ConfigFile::parseYesNo(i, "websocket");
|
||||
}
|
||||
else if (i.first == "enable_v4") {
|
||||
enableV4 = ConfigFile::parseYesNo(i, "websocket");
|
||||
}
|
||||
else if (i.first == "enable_v6") {
|
||||
enableV6 = ConfigFile::parseYesNo(i, "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 WebSocket 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;
|
||||
}
|
||||
|
||||
auto factory = make_shared<WebSocketFactory>();
|
||||
m_factories.emplace("websocket", factory);
|
||||
|
||||
shared_ptr<WebSocketChannel> channel;
|
||||
|
||||
if (enableV6 && enableV4) {
|
||||
websocket::Endpoint endpoint(boost::asio::ip::address_v6::any(), port);
|
||||
channel = factory->createChannel(endpoint);
|
||||
|
||||
m_factories.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);
|
||||
}
|
||||
|
||||
if (channel && needToListen) {
|
||||
channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
|
||||
}
|
||||
}
|
||||
#else
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without WebSocket, "
|
||||
"cannot process \"websocket\" section"));
|
||||
#endif // HAVE_WEBSOCKET
|
||||
}
|
||||
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -0,0 +1,103 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2016, 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_FACE_SYSTEM_HPP
|
||||
#define NFD_DAEMON_FACE_FACE_SYSTEM_HPP
|
||||
|
||||
#include "core/config-file.hpp"
|
||||
#include "protocol-factory.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class FaceTable;
|
||||
class NetworkInterfaceInfo;
|
||||
|
||||
namespace face {
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
class FaceSystem : noncopyable
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
FaceSystem(FaceTable& faceTable);
|
||||
|
||||
/** \return ProtocolFactory objects owned by the FaceSystem
|
||||
*/
|
||||
std::set<const ProtocolFactory*>
|
||||
listProtocolFactories() const;
|
||||
|
||||
/** \return ProtocolFactory for specified protocol scheme, or nullptr if not found
|
||||
*/
|
||||
ProtocolFactory*
|
||||
getProtocolFactory(const std::string& scheme);
|
||||
|
||||
/** \brief register handler for face_system section of NFD configuration file
|
||||
*/
|
||||
void
|
||||
setConfigFile(ConfigFile& configFile);
|
||||
|
||||
private:
|
||||
void
|
||||
processConfig(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::string& filename);
|
||||
|
||||
void
|
||||
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);
|
||||
|
||||
void
|
||||
processSectionEther(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::vector<NetworkInterfaceInfo>& nicList);
|
||||
|
||||
void
|
||||
processSectionWebSocket(const ConfigSection& configSection, bool isDryRun);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
/** \brief scheme => protocol factory
|
||||
*
|
||||
* The same protocol factory may be available under multiple schemes.
|
||||
*/
|
||||
std::map<std::string, shared_ptr<ProtocolFactory>> m_factories;
|
||||
|
||||
FaceTable& m_faceTable;
|
||||
};
|
||||
|
||||
} // namespace face
|
||||
|
||||
using face::FaceSystem;
|
||||
|
||||
} // namespace nfd
|
||||
|
||||
#endif // NFD_DAEMON_FACE_FACE_SYSTEM_HPP
|
||||
+17
-530
@@ -24,35 +24,20 @@
|
||||
*/
|
||||
|
||||
#include "face-manager.hpp"
|
||||
#include "core/network-interface.hpp"
|
||||
#include "core/network-interface-predicate.hpp"
|
||||
#include "face/generic-link-service.hpp"
|
||||
#include "face/tcp-factory.hpp"
|
||||
#include "face/udp-factory.hpp"
|
||||
#include "face/protocol-factory.hpp"
|
||||
#include "fw/face-table.hpp"
|
||||
|
||||
#include <ndn-cxx/lp/tags.hpp>
|
||||
#include <ndn-cxx/mgmt/nfd/channel-status.hpp>
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
#include "face/unix-stream-factory.hpp"
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#include "face/ethernet-factory.hpp"
|
||||
#include "face/ethernet-transport.hpp"
|
||||
#endif // HAVE_LIBPCAP
|
||||
|
||||
#ifdef HAVE_WEBSOCKET
|
||||
#include "face/websocket-factory.hpp"
|
||||
#endif // HAVE_WEBSOCKET
|
||||
|
||||
namespace nfd {
|
||||
|
||||
NFD_LOG_INIT("FaceManager");
|
||||
|
||||
FaceManager::FaceManager(FaceTable& faceTable, Dispatcher& dispatcher, CommandAuthenticator& authenticator)
|
||||
: NfdManagerBase(dispatcher, authenticator, "faces")
|
||||
, m_faceSystem(faceTable)
|
||||
, m_faceTable(faceTable)
|
||||
{
|
||||
registerCommandHandler<ndn::nfd::FaceCreateCommand>("create",
|
||||
@@ -87,7 +72,7 @@ FaceManager::FaceManager(FaceTable& faceTable, Dispatcher& dispatcher, CommandAu
|
||||
void
|
||||
FaceManager::setConfigFile(ConfigFile& configFile)
|
||||
{
|
||||
configFile.addSectionHandler("face_system", bind(&FaceManager::processConfig, this, _1, _2, _3));
|
||||
m_faceSystem.setConfigFile(configFile);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -108,22 +93,20 @@ FaceManager::createFace(const Name& topPrefix, const Interest& interest,
|
||||
return;
|
||||
}
|
||||
|
||||
auto factory = m_factories.find(uri.getScheme());
|
||||
if (factory == m_factories.end()) {
|
||||
ProtocolFactory* factory = m_faceSystem.getProtocolFactory(uri.getScheme());
|
||||
if (factory == nullptr) {
|
||||
NFD_LOG_TRACE("received create request for unsupported protocol");
|
||||
done(ControlResponse(406, "Unsupported protocol"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
factory->second->createFace(uri,
|
||||
parameters.getFacePersistency(),
|
||||
parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) ?
|
||||
parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) : false,
|
||||
bind(&FaceManager::afterCreateFaceSuccess,
|
||||
this, parameters, _1, done),
|
||||
bind(&FaceManager::afterCreateFaceFailure,
|
||||
this, _1, _2, done));
|
||||
factory->createFace(uri,
|
||||
parameters.getFacePersistency(),
|
||||
parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
|
||||
parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED),
|
||||
bind(&FaceManager::afterCreateFaceSuccess, this, parameters, _1, done),
|
||||
bind(&FaceManager::afterCreateFaceFailure, this, _1, _2, done));
|
||||
}
|
||||
catch (const std::runtime_error& error) {
|
||||
NFD_LOG_ERROR("Face creation failed: " << error.what());
|
||||
@@ -386,22 +369,14 @@ void
|
||||
FaceManager::listChannels(const Name& topPrefix, const Interest& interest,
|
||||
ndn::mgmt::StatusDatasetContext& context)
|
||||
{
|
||||
std::set<const ProtocolFactory*> seenFactories;
|
||||
|
||||
for (const auto& kv : m_factories) {
|
||||
const ProtocolFactory* factory = kv.second.get();
|
||||
bool inserted;
|
||||
std::tie(std::ignore, inserted) = seenFactories.insert(factory);
|
||||
|
||||
if (inserted) {
|
||||
for (const auto& channel : factory->getChannels()) {
|
||||
ndn::nfd::ChannelStatus entry;
|
||||
entry.setLocalUri(channel->getUri().toString());
|
||||
context.append(entry.wireEncode());
|
||||
}
|
||||
std::set<const ProtocolFactory*> factories = m_faceSystem.listProtocolFactories();
|
||||
for (const ProtocolFactory* factory : factories) {
|
||||
for (const auto& channel : factory->getChannels()) {
|
||||
ndn::nfd::ChannelStatus entry;
|
||||
entry.setLocalUri(channel->getUri().toString());
|
||||
context.append(entry.wireEncode());
|
||||
}
|
||||
}
|
||||
|
||||
context.end();
|
||||
}
|
||||
|
||||
@@ -548,492 +523,4 @@ FaceManager::connectFaceStateChangeSignal(const Face& face)
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
FaceManager::processConfig(const ConfigSection& configSection,
|
||||
bool isDryRun,
|
||||
const std::string& filename)
|
||||
{
|
||||
bool hasSeenUnix = false;
|
||||
bool hasSeenTcp = false;
|
||||
bool hasSeenUdp = false;
|
||||
bool hasSeenEther = false;
|
||||
bool hasSeenWebSocket = false;
|
||||
auto nicList = listNetworkInterfaces();
|
||||
|
||||
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 + "\""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
|
||||
{
|
||||
// ; the unix section contains settings of Unix stream faces and channels
|
||||
// unix
|
||||
// {
|
||||
// path /var/run/nfd.sock ; Unix stream listener path
|
||||
// }
|
||||
|
||||
#if defined(HAVE_UNIX_SOCKETS)
|
||||
std::string path = "/var/run/nfd.sock";
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
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;
|
||||
}
|
||||
|
||||
auto factory = make_shared<UnixStreamFactory>();
|
||||
m_factories.insert(std::make_pair("unix", factory));
|
||||
|
||||
auto channel = factory->createChannel(path);
|
||||
channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
|
||||
}
|
||||
#else
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
|
||||
"cannot process \"unix\" section"));
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
}
|
||||
|
||||
void
|
||||
FaceManager::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.insert(std::make_pair("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.insert(std::make_pair("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.insert(std::make_pair("tcp6", factory));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FaceManager::processSectionUdp(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::vector<NetworkInterfaceInfo>& nicList)
|
||||
{
|
||||
// ; the udp section contains settings of UDP faces and channels
|
||||
// udp
|
||||
// {
|
||||
// port 6363 ; UDP unicast port number
|
||||
// idle_timeout 600 ; idle time (seconds) before closing a UDP unicast face
|
||||
// keep_alive_interval 25 ; interval (seconds) between keep-alive refreshes
|
||||
|
||||
// ; NFD creates one UDP multicast face per NIC
|
||||
// mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
|
||||
// mcast_port 56363 ; UDP multicast port number
|
||||
// mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
|
||||
// }
|
||||
|
||||
uint16_t port = 6363;
|
||||
bool enableV4 = true;
|
||||
bool enableV6 = true;
|
||||
size_t timeout = 600;
|
||||
size_t keepAliveInterval = 25;
|
||||
bool useMcast = true;
|
||||
auto mcastGroup = boost::asio::ip::address_v4::from_string("224.0.23.170");
|
||||
uint16_t mcastPort = 56363;
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
if (i.first == "port") {
|
||||
port = ConfigFile::parseNumber<uint16_t>(i, "udp");
|
||||
NFD_LOG_TRACE("UDP unicast port set to " << port);
|
||||
}
|
||||
else if (i.first == "enable_v4") {
|
||||
enableV4 = ConfigFile::parseYesNo(i, "udp");
|
||||
}
|
||||
else if (i.first == "enable_v6") {
|
||||
enableV6 = ConfigFile::parseYesNo(i, "udp");
|
||||
}
|
||||
else if (i.first == "idle_timeout") {
|
||||
try {
|
||||
timeout = i.second.get_value<size_t>();
|
||||
}
|
||||
catch (const boost::property_tree::ptree_bad_data&) {
|
||||
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 boost::property_tree::ptree_bad_data&) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
|
||||
i.first + "\" in \"udp\" section"));
|
||||
}
|
||||
}
|
||||
else if (i.first == "mcast") {
|
||||
useMcast = ConfigFile::parseYesNo(i, "udp");
|
||||
}
|
||||
else if (i.first == "mcast_port") {
|
||||
mcastPort = ConfigFile::parseNumber<uint16_t>(i, "udp");
|
||||
NFD_LOG_TRACE("UDP multicast port set to " << mcastPort);
|
||||
}
|
||||
else if (i.first == "mcast_group") {
|
||||
boost::system::error_code ec;
|
||||
mcastGroup = boost::asio::ip::address_v4::from_string(i.second.get_value<std::string>(), ec);
|
||||
if (ec) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"" +
|
||||
i.first + "\" in \"udp\" section"));
|
||||
}
|
||||
NFD_LOG_TRACE("UDP multicast group set to " << mcastGroup);
|
||||
}
|
||||
else {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
|
||||
i.first + "\" in \"udp\" section"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!enableV4 && !enableV6) {
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("IPv4 and IPv6 UDP 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>();
|
||||
m_factories.insert(std::make_pair("udp", factory));
|
||||
}
|
||||
|
||||
if (!isReload && enableV4) {
|
||||
udp::Endpoint endpoint(boost::asio::ip::udp::v4(), port);
|
||||
shared_ptr<UdpChannel> v4Channel = factory->createChannel(endpoint, time::seconds(timeout));
|
||||
v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
|
||||
|
||||
m_factories.insert(std::make_pair("udp4", factory));
|
||||
}
|
||||
|
||||
if (!isReload && enableV6) {
|
||||
udp::Endpoint endpoint(boost::asio::ip::udp::v6(), port);
|
||||
shared_ptr<UdpChannel> v6Channel = factory->createChannel(endpoint, time::seconds(timeout));
|
||||
v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
|
||||
|
||||
m_factories.insert(std::make_pair("udp6", factory));
|
||||
}
|
||||
|
||||
std::set<shared_ptr<Face>> multicastFacesToRemove;
|
||||
for (const auto& i : factory->getMulticastFaces()) {
|
||||
multicastFacesToRemove.insert(i.second);
|
||||
}
|
||||
|
||||
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;
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
udp::Endpoint mcastEndpoint(mcastGroup, mcastPort);
|
||||
for (const auto& nic : ipv4MulticastInterfaces) {
|
||||
udp::Endpoint localEndpoint(nic.ipv4Addresses[0], mcastPort);
|
||||
auto newFace = factory->createMulticastFace(localEndpoint, mcastEndpoint,
|
||||
isNicNameNecessary ? nic.name : "");
|
||||
m_faceTable.add(newFace);
|
||||
multicastFacesToRemove.erase(newFace);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& face : multicastFacesToRemove) {
|
||||
face->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FaceManager::processSectionEther(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::vector<NetworkInterfaceInfo>& nicList)
|
||||
{
|
||||
// ; the ether section contains settings of Ethernet faces and channels
|
||||
// ether
|
||||
// {
|
||||
// ; NFD creates one Ethernet multicast face per NIC
|
||||
// mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
|
||||
// mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
|
||||
// }
|
||||
|
||||
#if defined(HAVE_LIBPCAP)
|
||||
NetworkInterfacePredicate nicPredicate;
|
||||
bool useMcast = true;
|
||||
ethernet::Address mcastGroup(ethernet::getDefaultMulticastAddress());
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
if (i.first == "mcast") {
|
||||
useMcast = ConfigFile::parseYesNo(i, "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"));
|
||||
}
|
||||
NFD_LOG_TRACE("Ethernet multicast group set to " << mcastGroup);
|
||||
}
|
||||
else if (i.first == "whitelist") {
|
||||
nicPredicate.parseWhitelist(i.second);
|
||||
}
|
||||
else if (i.first == "blacklist") {
|
||||
nicPredicate.parseBlacklist(i.second);
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
std::set<shared_ptr<Face>> multicastFacesToRemove;
|
||||
for (const auto& i : factory->getMulticastFaces()) {
|
||||
multicastFacesToRemove.insert(i.second);
|
||||
}
|
||||
|
||||
if (useMcast) {
|
||||
for (const auto& nic : nicList) {
|
||||
if (nic.isUp() && nic.isMulticastCapable() && nicPredicate(nic)) {
|
||||
try {
|
||||
auto newFace = factory->createMulticastFace(nic, mcastGroup);
|
||||
m_faceTable.add(newFace);
|
||||
multicastFacesToRemove.erase(newFace);
|
||||
}
|
||||
catch (const EthernetFactory::Error& factoryError) {
|
||||
NFD_LOG_ERROR(factoryError.what() << ", continuing");
|
||||
}
|
||||
catch (const face::EthernetTransport::Error& faceError) {
|
||||
NFD_LOG_ERROR(faceError.what() << ", continuing");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& face : multicastFacesToRemove) {
|
||||
face->close();
|
||||
}
|
||||
}
|
||||
#else
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section"));
|
||||
#endif // HAVE_LIBPCAP
|
||||
}
|
||||
|
||||
void
|
||||
FaceManager::processSectionWebSocket(const ConfigSection& configSection, bool isDryRun)
|
||||
{
|
||||
// ; the websocket section contains settings of WebSocket faces and channels
|
||||
// websocket
|
||||
// {
|
||||
// listen yes ; set to 'no' to disable WebSocket listener, default 'yes'
|
||||
// port 9696 ; WebSocket listener port number
|
||||
// enable_v4 yes ; set to 'no' to disable listening on IPv4 socket, default 'yes'
|
||||
// enable_v6 yes ; set to 'no' to disable listening on IPv6 socket, default 'yes'
|
||||
// }
|
||||
|
||||
#if defined(HAVE_WEBSOCKET)
|
||||
uint16_t port = 9696;
|
||||
bool needToListen = true;
|
||||
bool enableV4 = true;
|
||||
bool enableV6 = true;
|
||||
|
||||
for (const auto& i : configSection) {
|
||||
if (i.first == "port") {
|
||||
port = ConfigFile::parseNumber<uint16_t>(i, "websocket");
|
||||
NFD_LOG_TRACE("WebSocket port set to " << port);
|
||||
}
|
||||
else if (i.first == "listen") {
|
||||
needToListen = ConfigFile::parseYesNo(i, "websocket");
|
||||
}
|
||||
else if (i.first == "enable_v4") {
|
||||
enableV4 = ConfigFile::parseYesNo(i, "websocket");
|
||||
}
|
||||
else if (i.first == "enable_v6") {
|
||||
enableV6 = ConfigFile::parseYesNo(i, "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 WebSocket 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;
|
||||
}
|
||||
|
||||
auto factory = make_shared<WebSocketFactory>();
|
||||
m_factories.insert(std::make_pair("websocket", factory));
|
||||
|
||||
shared_ptr<WebSocketChannel> channel;
|
||||
|
||||
if (enableV6 && enableV4) {
|
||||
websocket::Endpoint endpoint(boost::asio::ip::address_v6::any(), port);
|
||||
channel = factory->createChannel(endpoint);
|
||||
|
||||
m_factories.insert(std::make_pair("websocket46", factory));
|
||||
}
|
||||
else if (enableV4) {
|
||||
websocket::Endpoint endpoint(boost::asio::ip::address_v4::any(), port);
|
||||
channel = factory->createChannel(endpoint);
|
||||
|
||||
m_factories.insert(std::make_pair("websocket4", factory));
|
||||
}
|
||||
|
||||
if (channel && needToListen) {
|
||||
channel->listen(bind(&FaceTable::add, &m_faceTable, _1));
|
||||
}
|
||||
}
|
||||
#else
|
||||
BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without WebSocket, "
|
||||
"cannot process \"websocket\" section"));
|
||||
#endif // HAVE_WEBSOCKET
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
@@ -27,17 +27,13 @@
|
||||
#define NFD_DAEMON_MGMT_FACE_MANAGER_HPP
|
||||
|
||||
#include "nfd-manager-base.hpp"
|
||||
#include "face/face-system.hpp"
|
||||
#include <ndn-cxx/mgmt/nfd/face-status.hpp>
|
||||
#include <ndn-cxx/mgmt/nfd/face-query-filter.hpp>
|
||||
#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
|
||||
#include "face/face.hpp"
|
||||
|
||||
namespace nfd {
|
||||
|
||||
class FaceTable;
|
||||
class NetworkInterfaceInfo;
|
||||
class ProtocolFactory;
|
||||
|
||||
/**
|
||||
* @brief implement the Face Management of NFD Management Protocol.
|
||||
* @sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt
|
||||
@@ -144,30 +140,8 @@ private: // NotificationStream
|
||||
void
|
||||
connectFaceStateChangeSignal(const Face& face);
|
||||
|
||||
private: // configuration
|
||||
void
|
||||
processConfig(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::string& filename);
|
||||
|
||||
void
|
||||
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);
|
||||
|
||||
void
|
||||
processSectionEther(const ConfigSection& configSection, bool isDryRun,
|
||||
const std::vector<NetworkInterfaceInfo>& nicList);
|
||||
|
||||
void
|
||||
processSectionWebSocket(const ConfigSection& configSection, bool isDryRun);
|
||||
|
||||
PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
std::map<std::string /*protocol*/, shared_ptr<ProtocolFactory>> m_factories;
|
||||
FaceSystem m_faceSystem; ///\todo #3904 accept FaceSystem& in constructor; don't own FaceSystem
|
||||
FaceTable& m_faceTable;
|
||||
std::map<FaceId, signal::ScopedConnection> m_faceStateChangeConn;
|
||||
|
||||
|
||||
@@ -0,0 +1,590 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2016, 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/face-system.hpp"
|
||||
#include "fw/face-table.hpp"
|
||||
|
||||
// ProtocolFactory includes, sorted alphabetically
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#include "face/ethernet-factory.hpp"
|
||||
#endif // HAVE_LIBPCAP
|
||||
#include "face/tcp-factory.hpp"
|
||||
#include "face/udp-factory.hpp"
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
#include "face/unix-stream-factory.hpp"
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
#ifdef HAVE_WEBSOCKET
|
||||
#include "face/websocket-factory.hpp"
|
||||
#endif // HAVE_WEBSOCKET
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace face {
|
||||
namespace tests {
|
||||
|
||||
using namespace nfd::tests;
|
||||
|
||||
class FaceSystemFixture : public BaseFixture
|
||||
{
|
||||
public:
|
||||
FaceSystemFixture()
|
||||
: faceSystem(faceTable)
|
||||
{
|
||||
faceSystem.setConfigFile(configFile);
|
||||
}
|
||||
|
||||
void
|
||||
parseConfig(const std::string& text, bool isDryRun)
|
||||
{
|
||||
configFile.parse(text, isDryRun, "test-config");
|
||||
}
|
||||
|
||||
protected:
|
||||
FaceTable faceTable;
|
||||
FaceSystem faceSystem;
|
||||
ConfigFile configFile;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Face)
|
||||
BOOST_FIXTURE_TEST_SUITE(TestFaceSystem, FaceSystemFixture)
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
BOOST_AUTO_TEST_SUITE(ConfigUnix)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Normal)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
unix
|
||||
{
|
||||
path /tmp/nfd.sock
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
|
||||
|
||||
auto factory = dynamic_cast<UnixStreamFactory*>(faceSystem.getProtocolFactory("unix"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
BOOST_CHECK_EQUAL(factory->getChannels().size(), 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UnknownOption)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
unix
|
||||
{
|
||||
hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // ConfigUnix
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(ConfigTcp)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Normal)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
tcp
|
||||
{
|
||||
listen yes
|
||||
port 16363
|
||||
enable_v4 yes
|
||||
enable_v6 yes
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
|
||||
|
||||
auto factory = dynamic_cast<TcpFactory*>(faceSystem.getProtocolFactory("tcp"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
BOOST_CHECK_EQUAL(factory->getChannels().size(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadListen)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
tcp
|
||||
{
|
||||
listen hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChannelsDisabled)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
tcp
|
||||
{
|
||||
port 6363
|
||||
enable_v4 no
|
||||
enable_v6 no
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UnknownOption)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
tcp
|
||||
{
|
||||
hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // ConfigTcp
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(ConfigUdp)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Normal)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
port 6363
|
||||
enable_v4 yes
|
||||
enable_v6 yes
|
||||
idle_timeout 30
|
||||
keep_alive_interval 25
|
||||
mcast yes
|
||||
mcast_port 56363
|
||||
mcast_group 224.0.23.170
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
|
||||
|
||||
auto factory = dynamic_cast<UdpFactory*>(faceSystem.getProtocolFactory("udp"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
BOOST_CHECK_EQUAL(factory->getChannels().size(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadIdleTimeout)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
idle_timeout hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadMcast)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
mcast hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadMcastGroup)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
mcast no
|
||||
mcast_port 50
|
||||
mcast_group hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadMcastGroupV6)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
mcast no
|
||||
mcast_port 50
|
||||
mcast_group ::1
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChannelsDisabled)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
port 6363
|
||||
enable_v4 no
|
||||
enable_v6 no
|
||||
idle_timeout 30
|
||||
keep_alive_interval 25
|
||||
mcast yes
|
||||
mcast_port 56363
|
||||
mcast_group 224.0.23.170
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ConflictingMcast)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
port 6363
|
||||
enable_v4 no
|
||||
enable_v6 yes
|
||||
idle_timeout 30
|
||||
keep_alive_interval 25
|
||||
mcast yes
|
||||
mcast_port 56363
|
||||
mcast_group 224.0.23.170
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UnknownOption)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MulticastReinit)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
const std::string CONFIG_WITH_MCAST = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
mcast yes
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
|
||||
|
||||
auto factory = dynamic_cast<UdpFactory*>(faceSystem.getProtocolFactory("udp"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
|
||||
if (factory->getMulticastFaces().empty()) {
|
||||
BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one UDP multicast face");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
udp
|
||||
{
|
||||
mcast no
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
|
||||
BOOST_REQUIRE_NO_THROW(g_io.poll());
|
||||
BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE_END() // ConfigUdp
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
BOOST_AUTO_TEST_SUITE(ConfigEther)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Normal)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
ether
|
||||
{
|
||||
mcast yes
|
||||
mcast_group 01:00:5E:00:17:AA
|
||||
whitelist
|
||||
{
|
||||
*
|
||||
}
|
||||
blacklist
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
|
||||
|
||||
auto factory = dynamic_cast<EthernetFactory*>(faceSystem.getProtocolFactory("ether"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
BOOST_CHECK_EQUAL(factory->getChannels().size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadMcast)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
ether
|
||||
{
|
||||
mcast hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BadMcastGroup)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
ether
|
||||
{
|
||||
mcast yes
|
||||
mcast_group
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UnknownOption)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
ether
|
||||
{
|
||||
hello
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MulticastReinit)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
const std::string CONFIG_WITH_MCAST = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
ether
|
||||
{
|
||||
mcast yes
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));
|
||||
|
||||
auto factory = dynamic_cast<EthernetFactory*>(faceSystem.getProtocolFactory("ether"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
|
||||
if (factory->getMulticastFaces().empty()) {
|
||||
BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one Ethernet multicast face");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string CONFIG_WITHOUT_MCAST = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
ether
|
||||
{
|
||||
mcast no
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
|
||||
BOOST_REQUIRE_NO_THROW(g_io.poll());
|
||||
BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // ConfigEther
|
||||
#endif // HAVE_LIBPCAP
|
||||
|
||||
#ifdef HAVE_WEBSOCKET
|
||||
BOOST_AUTO_TEST_SUITE(ConfigWebSocket)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Normal)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
websocket
|
||||
{
|
||||
listen yes
|
||||
port 9696
|
||||
enable_v4 yes
|
||||
enable_v6 yes
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
|
||||
BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
|
||||
|
||||
auto factory = dynamic_cast<WebSocketFactory*>(faceSystem.getProtocolFactory("websocket"));
|
||||
BOOST_REQUIRE(factory != nullptr);
|
||||
BOOST_CHECK_EQUAL(factory->getChannels().size(), 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ChannelsDisabled)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
websocket
|
||||
{
|
||||
listen yes
|
||||
port 9696
|
||||
enable_v4 no
|
||||
enable_v6 no
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Ipv4ChannelDisabled)
|
||||
{
|
||||
const std::string CONFIG = R"CONFIG(
|
||||
face_system
|
||||
{
|
||||
websocket
|
||||
{
|
||||
listen yes
|
||||
port 9696
|
||||
enable_v4 no
|
||||
enable_v6 yes
|
||||
}
|
||||
}
|
||||
)CONFIG";
|
||||
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
|
||||
BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // ConfigWebSocket
|
||||
#endif // HAVE_WEBSOCKET
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // TestFaceSystem
|
||||
BOOST_AUTO_TEST_SUITE_END() // Mgmt
|
||||
|
||||
} // namespace tests
|
||||
} // namespace face
|
||||
} // namespace nfd
|
||||
@@ -1,443 +0,0 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/**
|
||||
* Copyright (c) 2014-2016, 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 "nfd-manager-common-fixture.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace tests {
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Mgmt)
|
||||
BOOST_AUTO_TEST_SUITE(TestFaceManager)
|
||||
|
||||
class FaceManagerProcessConfigFixture : public NfdManagerCommonFixture
|
||||
{
|
||||
public:
|
||||
FaceManagerProcessConfigFixture()
|
||||
: m_manager(m_forwarder.getFaceTable(), m_dispatcher, *m_authenticator)
|
||||
{
|
||||
m_manager.setConfigFile(m_config);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
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)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
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().empty()) {
|
||||
BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one UDP multicast face");
|
||||
return;
|
||||
}
|
||||
|
||||
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_REQUIRE_NO_THROW(g_io.poll());
|
||||
BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ProcessSectionEther)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
const std::string CONFIG =
|
||||
"face_system\n"
|
||||
"{\n"
|
||||
" ether\n"
|
||||
" {\n"
|
||||
" mcast yes\n"
|
||||
" mcast_group 01:00:5E:00:17:AA\n"
|
||||
" whitelist\n"
|
||||
" {\n"
|
||||
" *\n"
|
||||
" }\n"
|
||||
" blacklist\n"
|
||||
" {\n"
|
||||
" }\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)
|
||||
{
|
||||
SKIP_IF_NOT_SUPERUSER();
|
||||
|
||||
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().empty()) {
|
||||
BOOST_WARN_MESSAGE(false, "skipping assertions that require at least one Ethernet multicast face");
|
||||
return;
|
||||
}
|
||||
|
||||
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_REQUIRE_NO_THROW(g_io.poll());
|
||||
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
|
||||
@@ -281,7 +281,7 @@ private:
|
||||
BOOST_AUTO_TEST_CASE(ChannelDataset)
|
||||
{
|
||||
auto factory = make_shared<TestProtocolFactory>();
|
||||
m_manager.m_factories["test"] = factory;
|
||||
m_manager.m_faceSystem.m_factories["test"] = factory;
|
||||
|
||||
std::map<std::string, shared_ptr<TestChannel>> addedChannels;
|
||||
size_t nEntries = 404;
|
||||
|
||||
Reference in new issue
Block a user