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/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.