face: pass the whole NetworkInterface to UdpFactory::createMulticastFace
Instead of just the interface name. This is in preparation
for adding IPv6 support to createMulticastFace.
Change-Id: Ie3c02af4483b041d39d4e85c85cd712368e9bb8f
Refs: #4222
diff --git a/.jenkins.d/20-tests.sh b/.jenkins.d/20-tests.sh
index b5d512a..76d0d34 100755
--- a/.jenkins.d/20-tests.sh
+++ b/.jenkins.d/20-tests.sh
@@ -50,5 +50,5 @@
# Then use sudo to run those tests that need superuser powers
sudo -E ./build/unit-tests-core -t TestPrivilegeHelper $(ut_log_args core-privilege)
sudo -E ./build/unit-tests-daemon -t Face/*Ethernet* $(ut_log_args daemon-ethernet)
-sudo -E ./build/unit-tests-daemon -t Face/*Factory/ProcessConfig $(ut_log_args daemon-face-config)
+sudo -E ./build/unit-tests-daemon -t Face/TestUdpFactory $(ut_log_args daemon-udp-factory)
sudo -E ./build/unit-tests-daemon -t Mgmt/TestGeneralConfigSection/UserAndGroupConfig,NoUserConfig $(ut_log_args daemon-user-config)
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index 7477fb0..7b1f4f0 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -29,7 +29,7 @@
#include "core/global-io.hpp"
#include <ndn-cxx/net/address-converter.hpp>
-#include <boost/range/adaptors.hpp>
+#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
#ifdef __linux__
@@ -42,6 +42,7 @@
namespace face {
namespace ip = boost::asio::ip;
+namespace net = ndn::net;
NFD_LOG_INIT("UdpFactory");
NFD_REGISTER_PROTOCOL_FACTORY(UdpFactory);
@@ -118,7 +119,7 @@
else if (key == "mcast_group") {
const std::string& valueStr = value.get_value<std::string>();
boost::system::error_code ec;
- mcastConfig.group.address(boost::asio::ip::address_v4::from_string(valueStr, ec));
+ mcastConfig.group.address(ip::address_v4::from_string(valueStr, ec));
if (ec) {
BOOST_THROW_EXCEPTION(ConfigFile::Error("face_system.udp.mcast_group: '" +
valueStr + "' cannot be parsed as an IPv4 address"));
@@ -293,9 +294,12 @@
shared_ptr<Face>
UdpFactory::createMulticastFace(const udp::Endpoint& localEndpoint,
const udp::Endpoint& multicastEndpoint,
- const std::string& networkInterfaceName)
+ const net::NetworkInterface& netif)
{
- // checking if the local and multicast endpoints are already in use for a multicast face
+ BOOST_ASSERT(multicastEndpoint.address().is_multicast());
+ BOOST_ASSERT(localEndpoint.port() == multicastEndpoint.port());
+
+ // check if the local and multicast endpoints are already in use for a multicast face
auto it = m_mcastFaces.find(localEndpoint);
if (it != m_mcastFaces.end()) {
if (it->second->getRemoteUri() == FaceUri(multicastEndpoint))
@@ -306,7 +310,7 @@
"on a different multicast group"));
}
- // checking if the local endpoint is already in use for a unicast channel
+ // check if the local endpoint is already used by a unicast channel
if (m_channels.find(localEndpoint) != m_channels.end()) {
BOOST_THROW_EXCEPTION(Error("Cannot create the requested UDP multicast face, local "
"endpoint is already allocated for a UDP unicast channel"));
@@ -317,16 +321,6 @@
"address"));
}
- if (localEndpoint.port() != multicastEndpoint.port()) {
- BOOST_THROW_EXCEPTION(Error("Cannot create the requested UDP multicast face, "
- "both endpoints should have the same port number. "));
- }
-
- if (!multicastEndpoint.address().is_multicast()) {
- BOOST_THROW_EXCEPTION(Error("Cannot create the requested UDP multicast face, "
- "the multicast group given as input is not a multicast address"));
- }
-
ip::udp::socket receiveSocket(getGlobalIoService());
receiveSocket.open(multicastEndpoint.protocol());
receiveSocket.set_option(ip::udp::socket::reuse_address(true));
@@ -352,12 +346,10 @@
// face will receive all packets sent to the other interfaces as well.
// This happens only on Linux. On macOS, the ip::multicast::join_group option
// is enough to get the desired behaviour.
- if (!networkInterfaceName.empty()) {
- if (::setsockopt(receiveSocket.native_handle(), SOL_SOCKET, SO_BINDTODEVICE,
- networkInterfaceName.c_str(), networkInterfaceName.size() + 1) < 0) {
- BOOST_THROW_EXCEPTION(Error("Cannot bind multicast face to " + networkInterfaceName +
- ": " + std::strerror(errno)));
- }
+ if (::setsockopt(receiveSocket.native_handle(), SOL_SOCKET, SO_BINDTODEVICE,
+ netif.getName().data(), netif.getName().size() + 1) < 0) {
+ BOOST_THROW_EXCEPTION(Error("Cannot bind multicast face to " + netif.getName() +
+ ": " + std::strerror(errno)));
}
#endif // __linux__
@@ -374,34 +366,22 @@
return face;
}
-shared_ptr<Face>
-UdpFactory::createMulticastFace(const std::string& localIp,
- const std::string& multicastIp,
- const std::string& multicastPort,
- const std::string& networkInterfaceName)
+static ndn::optional<ip::address>
+getV4Address(const net::NetworkInterface& netif)
{
- udp::Endpoint localEndpoint(ndn::ip::addressFromString(localIp),
- boost::lexical_cast<uint16_t>(multicastPort));
- udp::Endpoint multicastEndpoint(ndn::ip::addressFromString(multicastIp),
- boost::lexical_cast<uint16_t>(multicastPort));
- return createMulticastFace(localEndpoint, multicastEndpoint, networkInterfaceName);
-}
-
-static ndn::optional<ndn::net::NetworkAddress>
-getV4Address(const ndn::net::NetworkInterface& netif)
-{
- using namespace ndn::net;
- for (const NetworkAddress& na : netif.getNetworkAddresses()) {
- if (na.getFamily() == AddressFamily::V4 && na.getScope() != AddressScope::NOWHERE) {
- return na;
+ for (const auto& na : netif.getNetworkAddresses()) {
+ if (na.getFamily() == net::AddressFamily::V4 && na.getScope() != net::AddressScope::NOWHERE) {
+ return na.getIp();
}
}
return ndn::nullopt;
}
shared_ptr<Face>
-UdpFactory::applyMcastConfigToNetif(const shared_ptr<const ndn::net::NetworkInterface>& netif)
+UdpFactory::applyMcastConfigToNetif(const shared_ptr<const net::NetworkInterface>& netif)
{
+ BOOST_ASSERT(netif != nullptr);
+
if (!m_mcastConfig.isEnabled) {
return nullptr;
}
@@ -431,8 +411,8 @@
}
NFD_LOG_DEBUG("Creating multicast face on " << netif->getName());
- udp::Endpoint localEndpoint(address->getIp(), m_mcastConfig.group.port());
- auto face = this->createMulticastFace(localEndpoint, m_mcastConfig.group, netif->getName());
+ udp::Endpoint localEndpoint(*address, m_mcastConfig.group.port());
+ auto face = this->createMulticastFace(localEndpoint, m_mcastConfig.group, *netif);
// ifname is only used on Linux. It is not required if there is only one multicast-capable netif,
// but it is always supplied because a new netif can be added at anytime.
diff --git a/daemon/face/udp-factory.hpp b/daemon/face/udp-factory.hpp
index 55556ab..9e20be4 100644
--- a/daemon/face/udp-factory.hpp
+++ b/daemon/face/udp-factory.hpp
@@ -93,7 +93,7 @@
getChannels() const override;
/**
- * \brief Create multicast UDP face using udp::Endpoint
+ * \brief Create a multicast UDP face
*
* udp::Endpoint is really an alias for boost::asio::ip::udp::endpoint.
*
@@ -102,40 +102,30 @@
* If this method is called twice with the same pair of endpoints, only one
* face will be created. The second call will just return the existing face.
*
- * If an unicast face is already active on the same local NIC and port, the
- * creation fails and an exception is thrown.
+ * If a UDP channel, unicast face, or multicast face already exists on the
+ * same local endpoint, the creation fails and an exception is thrown.
*
- * \param localEndpoint local endpoint
- * \param multicastEndpoint multicast endpoint
- * \param networkInterfaceName name of the network interface on which the face will be bound
- * (Used only on multihomed linux machine with more than one multicast UDP face for
- * the same multicast group. If specified, will require CAP_NET_RAW capability)
- * An empty string can be provided in other system or in linux machine with only one
- * multicast UDP face per multicast group
+ * \param localEndpoint the local endpoint
+ * \param multicastEndpoint the multicast endpoint
+ * \param netif the network interface to which the face will be bound
*
- * \return always a valid pointer to a MulticastUdpFace object, an exception
- * is thrown if it cannot be created.
+ * \return always a valid shared pointer to the created face;
+ * an exception is thrown if the face cannot be created.
* \throw UdpFactory::Error
*/
shared_ptr<Face>
createMulticastFace(const udp::Endpoint& localEndpoint,
const udp::Endpoint& multicastEndpoint,
- const std::string& networkInterfaceName = "");
-
- shared_ptr<Face>
- createMulticastFace(const std::string& localIp,
- const std::string& multicastIp,
- const std::string& multicastPort,
- const std::string& networkInterfaceName = "");
+ const ndn::net::NetworkInterface& netif);
private:
- /** \brief Create UDP multicast face on \p netif if needed by \p m_mcastConfig.
+ /** \brief Create UDP multicast face on \p netif if needed by \p m_mcastConfig
* \return new or existing face, or nullptr if no face should be created
*/
shared_ptr<Face>
applyMcastConfigToNetif(const shared_ptr<const ndn::net::NetworkInterface>& netif);
- /** \brief Create and destroy UDP multicast faces according to \p m_mcastConfig.
+ /** \brief Create and destroy UDP multicast faces according to \p m_mcastConfig
*/
void
applyMcastConfig(const FaceSystem::ConfigContext& context);
diff --git a/tests/daemon/face/udp-factory.t.cpp b/tests/daemon/face/udp-factory.t.cpp
index 36ccba4..84d4529 100644
--- a/tests/daemon/face/udp-factory.t.cpp
+++ b/tests/daemon/face/udp-factory.t.cpp
@@ -40,14 +40,77 @@
{
protected:
shared_ptr<UdpChannel>
- createChannel(const std::string& localIp, const std::string& localPort)
+ createChannel(const std::string& localIp, uint16_t localPort)
{
- udp::Endpoint endpoint(ndn::ip::addressFromString(localIp),
- boost::lexical_cast<uint16_t>(localPort));
+ udp::Endpoint endpoint(ndn::ip::addressFromString(localIp), localPort);
return factory.createChannel(endpoint, time::minutes(5));
}
};
+class UdpFactoryMcastFixture : public UdpFactoryFixture
+{
+protected:
+ UdpFactoryMcastFixture()
+ {
+ for (const auto& netif : collectNetworkInterfaces()) {
+ if (netif->isUp() && netif->canMulticast() &&
+ hasAddressFamily(*netif, ndn::net::AddressFamily::V4)) {
+ netifs.push_back(netif);
+ }
+ }
+
+ this->copyRealNetifsToNetmon();
+ }
+
+ shared_ptr<Face>
+ createMulticastFace(const std::string& localIp, const std::string& mcastIp, uint16_t mcastPort)
+ {
+ BOOST_ASSERT(!netifs.empty());
+ udp::Endpoint localEndpoint(ndn::ip::addressFromString(localIp), mcastPort);
+ udp::Endpoint mcastEndpoint(ndn::ip::addressFromString(mcastIp), mcastPort);
+ return factory.createMulticastFace(localEndpoint, mcastEndpoint, *netifs.front());
+ }
+
+ std::vector<const Face*>
+ listUdp4McastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
+ {
+ return this->listFacesByScheme("udp4", linkType);
+ }
+
+ /** \brief determine whether \p netif has at least one address of the given family
+ */
+ static bool
+ hasAddressFamily(const NetworkInterface& netif, ndn::net::AddressFamily af)
+ {
+ return std::any_of(netif.getNetworkAddresses().begin(), netif.getNetworkAddresses().end(),
+ [af] (const NetworkAddress& a) { return a.getFamily() == af; });
+ }
+
+ /** \brief determine whether a UDP multicast face is created on \p netif
+ */
+ static bool
+ isFaceOnNetif(const Face& face, const shared_ptr<const NetworkInterface>& netif)
+ {
+ auto ip = boost::asio::ip::address_v4::from_string(face.getLocalUri().getHost());
+ return std::any_of(netif->getNetworkAddresses().begin(), netif->getNetworkAddresses().end(),
+ [ip] (const NetworkAddress& a) { return a.getIp() == ip; });
+ }
+
+protected:
+ /** \brief MulticastUdpTransport-capable network interfaces
+ */
+ std::vector<shared_ptr<const NetworkInterface>> netifs;
+};
+
+#define SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(n) \
+ do { \
+ if (this->netifs.size() < (n)) { \
+ BOOST_WARN_MESSAGE(false, "skipping assertions that require " #n \
+ " or more MulticastUdpTransport-capable network interfaces"); \
+ return; \
+ } \
+ } while (false)
+
BOOST_AUTO_TEST_SUITE(Face)
BOOST_FIXTURE_TEST_SUITE(TestUdpFactory, UdpFactoryFixture)
@@ -119,68 +182,7 @@
checkChannelListEqual(factory, {"udp6://[::]:7001"});
}
-class UdpMcastConfigFixture : public UdpFactoryFixture
-{
-protected:
- UdpMcastConfigFixture()
- {
- for (const auto& netif : collectNetworkInterfaces()) {
- if (netif->isUp() && netif->canMulticast() &&
- hasAddressFamily(*netif, ndn::net::AddressFamily::V4)) {
- netifs.push_back(netif);
- }
- }
-
- this->copyRealNetifsToNetmon();
- }
-
- std::vector<const Face*>
- listUdpMcastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
- {
- return this->listFacesByScheme("udp4", linkType);
- }
-
- size_t
- countUdpMcastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
- {
- return this->listUdpMcastFaces(linkType).size();
- }
-
- /** \brief determine whether \p netif has at least one address of the given family
- */
- static bool
- hasAddressFamily(const NetworkInterface& netif, ndn::net::AddressFamily af)
- {
- return std::any_of(netif.getNetworkAddresses().begin(), netif.getNetworkAddresses().end(),
- [af] (const NetworkAddress& a) { return a.getFamily() == af; });
- }
-
- /** \brief determine whether a UDP multicast face is created on \p netif
- */
- static bool
- isFaceOnNetif(const Face& face, const shared_ptr<const NetworkInterface>& netif)
- {
- auto ip = boost::asio::ip::address_v4::from_string(face.getLocalUri().getHost());
- return std::any_of(netif->getNetworkAddresses().begin(), netif->getNetworkAddresses().end(),
- [ip] (const NetworkAddress& a) { return a.getIp() == ip; });
- }
-
-protected:
- /** \brief MulticastUdpTransport-capable network interfaces
- */
- std::vector<shared_ptr<const NetworkInterface>> netifs;
-};
-
-#define SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(n) \
- do { \
- if (this->netifs.size() < (n)) { \
- BOOST_WARN_MESSAGE(false, "skipping assertions that require " #n \
- " or more MulticastUdpTransport-capable network interfaces"); \
- return; \
- } \
- } while (false)
-
-BOOST_FIXTURE_TEST_CASE(EnableDisableMcast, UdpMcastConfigFixture)
+BOOST_FIXTURE_TEST_CASE(EnableDisableMcast, UdpFactoryMcastFixture)
{
#ifdef __linux__
// need superuser privilege for creating multicast faces on Linux
@@ -207,20 +209,20 @@
)CONFIG";
parseConfig(CONFIG_WITHOUT_MCAST, false);
- BOOST_CHECK_EQUAL(this->countUdpMcastFaces(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);
parseConfig(CONFIG_WITH_MCAST, false);
g_io.poll();
- BOOST_CHECK_EQUAL(this->countUdpMcastFaces(), netifs.size());
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), netifs.size());
parseConfig(CONFIG_WITHOUT_MCAST, false);
g_io.poll();
- BOOST_CHECK_EQUAL(this->countUdpMcastFaces(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
}
-BOOST_FIXTURE_TEST_CASE(McastAdHoc, UdpMcastConfigFixture)
+BOOST_FIXTURE_TEST_CASE(McastAdHoc, UdpFactoryMcastFixture)
{
#ifdef __linux__
// need superuser privilege for creating multicast faces on Linux
@@ -239,10 +241,10 @@
)CONFIG";
parseConfig(CONFIG, false);
- BOOST_CHECK_EQUAL(this->countUdpMcastFaces(ndn::nfd::LINK_TYPE_AD_HOC), netifs.size());
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces(ndn::nfd::LINK_TYPE_AD_HOC).size(), netifs.size());
}
-BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpoint, UdpMcastConfigFixture)
+BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpoint, UdpFactoryMcastFixture)
{
#ifdef __linux__
// need superuser privilege for creating multicast faces on Linux
@@ -272,20 +274,20 @@
)CONFIG";
parseConfig(CONFIG1, false);
- auto udpMcastFaces = this->listUdpMcastFaces();
+ auto udpMcastFaces = this->listUdp4McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), netifs.size());
BOOST_CHECK_EQUAL(udpMcastFaces.front()->getRemoteUri(),
FaceUri("udp4://239.66.30.1:7011"));
parseConfig(CONFIG2, false);
g_io.poll();
- udpMcastFaces = this->listUdpMcastFaces();
+ udpMcastFaces = this->listUdp4McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), netifs.size());
BOOST_CHECK_EQUAL(udpMcastFaces.front()->getRemoteUri(),
FaceUri("udp4://239.66.30.2:7012"));
}
-BOOST_FIXTURE_TEST_CASE(Whitelist, UdpMcastConfigFixture)
+BOOST_FIXTURE_TEST_CASE(Whitelist, UdpFactoryMcastFixture)
{
#ifdef __linux__
// need superuser privilege for creating multicast faces on Linux
@@ -308,12 +310,12 @@
boost::replace_first(CONFIG, "%ifname", netifs.front()->getName());
parseConfig(CONFIG, false);
- auto udpMcastFaces = this->listUdpMcastFaces();
+ auto udpMcastFaces = this->listUdp4McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), 1);
BOOST_CHECK(isFaceOnNetif(*udpMcastFaces.front(), netifs.front()));
}
-BOOST_FIXTURE_TEST_CASE(Blacklist, UdpMcastConfigFixture)
+BOOST_FIXTURE_TEST_CASE(Blacklist, UdpFactoryMcastFixture)
{
#ifdef __linux__
// need superuser privilege for creating multicast faces on Linux
@@ -336,14 +338,14 @@
boost::replace_first(CONFIG, "%ifname", netifs.front()->getName());
parseConfig(CONFIG, false);
- auto udpMcastFaces = this->listUdpMcastFaces();
+ auto udpMcastFaces = this->listUdp4McastFaces();
BOOST_CHECK_EQUAL(udpMcastFaces.size(), netifs.size() - 1);
BOOST_CHECK_EQUAL(boost::count_if(udpMcastFaces, [this] (const Face* face) {
return isFaceOnNetif(*face, netifs.front());
}), 0);
}
-BOOST_FIXTURE_TEST_CASE(ChangePredicate, UdpMcastConfigFixture)
+BOOST_FIXTURE_TEST_CASE(ChangePredicate, UdpFactoryMcastFixture)
{
#ifdef __linux__
// need superuser privilege for creating multicast faces on Linux
@@ -368,13 +370,13 @@
boost::replace_first(CONFIG2, "%ifname", netifs.back()->getName());
parseConfig(CONFIG1, false);
- auto udpMcastFaces = this->listUdpMcastFaces();
+ auto udpMcastFaces = this->listUdp4McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), 1);
BOOST_CHECK(isFaceOnNetif(*udpMcastFaces.front(), netifs.front()));
parseConfig(CONFIG2, false);
g_io.poll();
- udpMcastFaces = this->listUdpMcastFaces();
+ udpMcastFaces = this->listUdp4McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), 1);
BOOST_CHECK(isFaceOnNetif(*udpMcastFaces.front(), netifs.back()));
}
@@ -394,6 +396,24 @@
BOOST_CHECK_EQUAL(this->listFacesByScheme("udp4", ndn::nfd::LINK_TYPE_MULTI_ACCESS).size(), 0);
}
+BOOST_AUTO_TEST_CASE(AllDisabled)
+{
+ const std::string CONFIG = R"CONFIG(
+ face_system
+ {
+ udp
+ {
+ enable_v4 no
+ enable_v6 no
+ mcast no
+ }
+ }
+ )CONFIG";
+
+ BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+}
+
BOOST_AUTO_TEST_CASE(BadIdleTimeout)
{
const std::string CONFIG = R"CONFIG(
@@ -428,7 +448,8 @@
BOOST_AUTO_TEST_CASE(BadMcastGroup)
{
- const std::string CONFIG = R"CONFIG(
+ // not an address
+ const std::string CONFIG1 = R"CONFIG(
face_system
{
udp
@@ -438,13 +459,11 @@
}
)CONFIG";
- BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
- BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
-}
+ BOOST_CHECK_THROW(parseConfig(CONFIG1, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG1, false), ConfigFile::Error);
-BOOST_AUTO_TEST_CASE(BadMcastGroupV4Unicast)
-{
- const std::string CONFIG = R"CONFIG(
+ // non-multicast address
+ const std::string CONFIG2 = R"CONFIG(
face_system
{
udp
@@ -454,42 +473,51 @@
}
)CONFIG";
- BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
- BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
-}
+ BOOST_CHECK_THROW(parseConfig(CONFIG2, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG2, false), ConfigFile::Error);
-BOOST_AUTO_TEST_CASE(BadMcastGroupV6)
-{
- const std::string CONFIG = R"CONFIG(
+ // wrong address family
+ const std::string CONFIG3 = R"CONFIG(
face_system
{
udp
{
- mcast_group ff00::1
+ mcast_group ff02::1234
}
}
)CONFIG";
- BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
- BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG3, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG3, false), ConfigFile::Error);
}
-BOOST_AUTO_TEST_CASE(AllDisabled)
+BOOST_AUTO_TEST_CASE(BadMcastPort)
{
- const std::string CONFIG = R"CONFIG(
+ const std::string CONFIG1 = R"CONFIG(
face_system
{
udp
{
- enable_v4 no
- enable_v6 no
- mcast no
+ mcast_port hey
}
}
)CONFIG";
- BOOST_CHECK_THROW(parseConfig(CONFIG, true), ConfigFile::Error);
- BOOST_CHECK_THROW(parseConfig(CONFIG, false), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG1, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG1, false), ConfigFile::Error);
+
+ const std::string CONFIG2 = R"CONFIG(
+ face_system
+ {
+ udp
+ {
+ mcast_port 99999
+ }
+ }
+ )CONFIG";
+
+ BOOST_CHECK_THROW(parseConfig(CONFIG2, true), ConfigFile::Error);
+ BOOST_CHECK_THROW(parseConfig(CONFIG2, false), ConfigFile::Error);
}
BOOST_AUTO_TEST_CASE(UnknownOption)
@@ -515,37 +543,43 @@
BOOST_CHECK_EQUAL(factory.getChannels().empty(), true);
std::set<std::string> expected;
- expected.insert(createChannel("127.0.0.1", "20070")->getUri().toString());
- expected.insert(createChannel("127.0.0.1", "20071")->getUri().toString());
- expected.insert(createChannel("::1", "20071")->getUri().toString());
+ expected.insert(createChannel("127.0.0.1", 20070)->getUri().toString());
+ expected.insert(createChannel("127.0.0.1", 20071)->getUri().toString());
+ expected.insert(createChannel("::1", 20071)->getUri().toString());
checkChannelListEqual(factory, expected);
}
-BOOST_AUTO_TEST_CASE(CreateChannel)
+BOOST_FIXTURE_TEST_CASE(CreateChannel, UdpFactoryMcastFixture)
{
- auto channel1 = createChannel("127.0.0.1", "20070");
- auto channel1a = createChannel("127.0.0.1", "20070");
+ auto channel1 = createChannel("127.0.0.1", 20070);
+ auto channel1a = createChannel("127.0.0.1", 20070);
BOOST_CHECK_EQUAL(channel1, channel1a);
BOOST_CHECK_EQUAL(channel1->getUri().toString(), "udp4://127.0.0.1:20070");
- auto channel2 = createChannel("127.0.0.1", "20071");
+ auto channel2 = createChannel("127.0.0.1", 20071);
BOOST_CHECK_NE(channel1, channel2);
- auto channel3 = createChannel("::1", "20071");
+ auto channel3 = createChannel("::1", 20071);
BOOST_CHECK_NE(channel2, channel3);
BOOST_CHECK_EQUAL(channel3->getUri().toString(), "udp6://[::1]:20071");
// createChannel with multicast address
- BOOST_CHECK_EXCEPTION(createChannel("224.0.0.1", "20070"), UdpFactory::Error,
+ BOOST_CHECK_EXCEPTION(createChannel("224.0.0.1", 20070), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
return strcmp(e.what(),
"createChannel is only for unicast channels. The provided endpoint "
"is multicast. Use createMulticastFace to create a multicast face") == 0;
});
+#ifdef __linux__
+ // need superuser privilege for creating multicast faces on Linux
+ SKIP_IF_NOT_SUPERUSER();
+#endif // __linux__
+ SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);
+
// createChannel with a local endpoint that has already been allocated for a UDP multicast face
- auto multicastFace = factory.createMulticastFace("127.0.0.1", "224.0.0.1", "20072");
- BOOST_CHECK_EXCEPTION(createChannel("127.0.0.1", "20072"), UdpFactory::Error,
+ auto multicastFace = createMulticastFace("127.0.0.1", "224.0.0.1", 20072);
+ BOOST_CHECK_EXCEPTION(createChannel("127.0.0.1", 20072), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
return strcmp(e.what(),
"Cannot create the requested UDP unicast channel, local "
@@ -553,24 +587,30 @@
});
}
-BOOST_AUTO_TEST_CASE(CreateMulticastFace)
+BOOST_FIXTURE_TEST_CASE(CreateMulticastFace, UdpFactoryMcastFixture)
{
- auto multicastFace1 = factory.createMulticastFace("127.0.0.1", "224.0.0.1", "20070");
- auto multicastFace1a = factory.createMulticastFace("127.0.0.1", "224.0.0.1", "20070");
+#ifdef __linux__
+ // need superuser privilege for creating multicast faces on Linux
+ SKIP_IF_NOT_SUPERUSER();
+#endif // __linux__
+ SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);
+
+ auto multicastFace1 = createMulticastFace("127.0.0.1", "224.0.0.1", 20070);
+ auto multicastFace1a = createMulticastFace("127.0.0.1", "224.0.0.1", 20070);
BOOST_CHECK_EQUAL(multicastFace1, multicastFace1a);
- // createMulticastFace with a local endpoint that is already used by a channel
- auto channel = createChannel("127.0.0.1", "20071");
- BOOST_CHECK_EXCEPTION(factory.createMulticastFace("127.0.0.1", "224.0.0.1", "20071"), UdpFactory::Error,
+ // createMulticastFace with an IPv4 local endpoint already used by a channel
+ auto channel = createChannel("127.0.0.1", 20071);
+ BOOST_CHECK_EXCEPTION(createMulticastFace("127.0.0.1", "224.0.0.1", 20071), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
return strcmp(e.what(),
"Cannot create the requested UDP multicast face, local "
"endpoint is already allocated for a UDP unicast channel") == 0;
});
- // createMulticastFace with a local endpoint that is already
+ // createMulticastFace with an IPv4 local endpoint already
// used by a multicast face on a different multicast group
- BOOST_CHECK_EXCEPTION(factory.createMulticastFace("127.0.0.1", "224.0.0.42", "20070"), UdpFactory::Error,
+ BOOST_CHECK_EXCEPTION(createMulticastFace("127.0.0.1", "224.0.0.42", 20070), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
return strcmp(e.what(),
"Cannot create the requested UDP multicast face, local "
@@ -578,31 +618,13 @@
"on a different multicast group") == 0;
});
- // createMulticastFace with an IPv4 unicast address
- BOOST_CHECK_EXCEPTION(factory.createMulticastFace("127.0.0.1", "192.168.10.15", "20072"), UdpFactory::Error,
- [] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create the requested UDP multicast face, "
- "the multicast group given as input is not a multicast address") == 0;
- });
-
// createMulticastFace with an IPv6 multicast address
- BOOST_CHECK_EXCEPTION(factory.createMulticastFace("::1", "ff01::114", "20073"), UdpFactory::Error,
+ BOOST_CHECK_EXCEPTION(createMulticastFace("::1", "ff01::114", 20073), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
return strcmp(e.what(),
"IPv6 multicast is not supported yet. Please provide an IPv4 "
"address") == 0;
});
-
- // createMulticastFace with different local and remote port numbers
- udp::Endpoint localEndpoint(boost::asio::ip::address_v4::loopback(), 20074);
- udp::Endpoint multicastEndpoint(boost::asio::ip::address::from_string("224.0.0.1"), 20075);
- BOOST_CHECK_EXCEPTION(factory.createMulticastFace(localEndpoint, multicastEndpoint), UdpFactory::Error,
- [] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create the requested UDP multicast face, "
- "both endpoints should have the same port number. ") == 0;
- });
}
BOOST_AUTO_TEST_CASE(CreateFace)
@@ -615,7 +637,7 @@
false,
{CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
- createChannel("127.0.0.1", "20071");
+ createChannel("127.0.0.1", 20071);
createFace(factory,
FaceUri("udp4://127.0.0.1:6363"),
@@ -641,7 +663,6 @@
false,
{CreateFaceExpectedResult::SUCCESS, 0, ""});
-
createFace(factory,
FaceUri("udp4://127.0.0.1:20073"),
{},
@@ -653,7 +674,7 @@
BOOST_AUTO_TEST_CASE(UnsupportedCreateFace)
{
- createChannel("127.0.0.1", "20071");
+ createChannel("127.0.0.1", 20071);
createFace(factory,
FaceUri("udp4://127.0.0.1:20072"),