face: use move semantics for sockets where possible
Change-Id: I2af595073f862c570c1ce0dcb3717f3d2b9cfd71
Refs: #2613
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index fcf1343..ddef35e 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -27,8 +27,10 @@
#include "core/global-io.hpp"
#include "core/network-interface.hpp"
-#if defined(__linux__)
-#include <sys/socket.h>
+#ifdef __linux__
+#include <cerrno> // for errno
+#include <cstring> // for std::strerror()
+#include <sys/socket.h> // for setsockopt()
#endif
namespace nfd {
@@ -147,20 +149,20 @@
shared_ptr<MulticastUdpFace>
UdpFactory::createMulticastFace(const udp::Endpoint& localEndpoint,
const udp::Endpoint& multicastEndpoint,
- const std::string& networkInterfaceName /* "" */)
+ const std::string& networkInterfaceName/* = ""*/)
{
- //checking if the local and multicast endpoint are already in use for a multicast face
- shared_ptr<MulticastUdpFace> multicastFace = findMulticastFace(localEndpoint);
- if (static_cast<bool>(multicastFace)) {
- if (multicastFace->getMulticastGroup() == multicastEndpoint)
- return multicastFace;
+ // checking if the local and multicast endpoints are already in use for a multicast face
+ shared_ptr<MulticastUdpFace> face = findMulticastFace(localEndpoint);
+ if (static_cast<bool>(face)) {
+ if (face->getMulticastGroup() == multicastEndpoint)
+ return face;
else
throw Error("Cannot create the requested UDP multicast face, local "
"endpoint is already allocated for a UDP multicast face "
"on a different multicast group");
}
- //checking if the local endpoint is already in use for an unicast channel
+ // checking if the local endpoint is already in use for a unicast channel
shared_ptr<UdpChannel> unicast = findChannel(localEndpoint);
if (static_cast<bool>(unicast)) {
throw Error("Cannot create the requested UDP multicast face, local "
@@ -186,79 +188,63 @@
"the multicast group given as input is not a multicast address");
}
- shared_ptr<ip::udp::socket> receiveSocket =
- make_shared<ip::udp::socket>(ref(getGlobalIoService()));
+ ip::udp::socket receiveSocket(getGlobalIoService());
+ receiveSocket.open(multicastEndpoint.protocol());
+ receiveSocket.set_option(ip::udp::socket::reuse_address(true));
+ receiveSocket.bind(multicastEndpoint);
- shared_ptr<ip::udp::socket> sendSocket =
- make_shared<ip::udp::socket>(ref(getGlobalIoService()));
+ ip::udp::socket sendSocket(getGlobalIoService());
+ sendSocket.open(multicastEndpoint.protocol());
+ sendSocket.set_option(ip::udp::socket::reuse_address(true));
+ sendSocket.set_option(ip::multicast::enable_loopback(false));
+ sendSocket.bind(udp::Endpoint(ip::address_v4::any(), multicastEndpoint.port()));
+ if (localEndpoint.address() != ALL_V4_ENDPOINT)
+ sendSocket.set_option(ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
- receiveSocket->open(multicastEndpoint.protocol());
- receiveSocket->set_option(ip::udp::socket::reuse_address(true));
-
- sendSocket->open(multicastEndpoint.protocol());
- sendSocket->set_option(ip::udp::socket::reuse_address(true));
- sendSocket->set_option(ip::multicast::enable_loopback(false));
-
- try {
- sendSocket->bind(udp::Endpoint(ip::address_v4::any(), multicastEndpoint.port()));
- receiveSocket->bind(multicastEndpoint);
-
- if (localEndpoint.address() != ip::address::from_string("0.0.0.0")) {
- sendSocket->set_option(ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
- }
- sendSocket->set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
+ sendSocket.set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
+ localEndpoint.address().to_v4()));
+ receiveSocket.set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
localEndpoint.address().to_v4()));
- receiveSocket->set_option(ip::multicast::join_group(multicastEndpoint.address().to_v4(),
- localEndpoint.address().to_v4()));
- }
- catch (boost::system::system_error& e) {
- std::stringstream msg;
- msg << "Failed to properly configure the socket, check the address (" << e.what() << ")";
- throw Error(msg.str());
- }
-
-#if defined(__linux__)
- //On linux system, if there are more than one MulticastUdpFace for the same multicast group but
- //bound on different network interfaces, the socket has to be bound with the specific interface
- //using SO_BINDTODEVICE, otherwise the face will receive packets also from other interfaces.
- //Without SO_BINDTODEVICE every MulticastUdpFace that have joined the same multicast group
- //on different interfaces will receive the same packet.
- //This applies only on linux, for OS X the ip::multicast::join_group is enough to get
- //the desired behaviour
+#ifdef __linux__
+ /*
+ * On Linux, if there is more than one MulticastUdpFace for the same multicast
+ * group but they are bound to different network interfaces, the socket needs
+ * to be bound to the specific interface using SO_BINDTODEVICE, otherwise the
+ * face will receive all packets sent to the other interfaces as well.
+ * This happens only on Linux. On OS X, 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) == -1){
- throw Error("Cannot bind multicast face to " + networkInterfaceName
- + " make sure you have CAP_NET_RAW capability" );
+ if (::setsockopt(receiveSocket.native_handle(), SOL_SOCKET, SO_BINDTODEVICE,
+ networkInterfaceName.c_str(), networkInterfaceName.size() + 1) < 0) {
+ throw Error("Cannot bind multicast face to " + networkInterfaceName +
+ ": " + std::strerror(errno));
}
}
-
#endif
- multicastFace = make_shared<MulticastUdpFace>(receiveSocket, sendSocket,
- localEndpoint, multicastEndpoint);
+ face = make_shared<MulticastUdpFace>(multicastEndpoint, FaceUri(localEndpoint),
+ std::move(receiveSocket), std::move(sendSocket));
- multicastFace->onFail.connectSingleShot(bind(&UdpFactory::afterFaceFailed, this, localEndpoint));
+ face->onFail.connectSingleShot([this, localEndpoint] (const std::string& reason) {
+ m_multicastFaces.erase(localEndpoint);
+ });
+ m_multicastFaces[localEndpoint] = face;
- m_multicastFaces[localEndpoint] = multicastFace;
-
- return multicastFace;
+ return face;
}
shared_ptr<MulticastUdpFace>
UdpFactory::createMulticastFace(const std::string& localIp,
const std::string& multicastIp,
const std::string& multicastPort,
- const std::string& networkInterfaceName /* "" */)
+ const std::string& networkInterfaceName/* = ""*/)
{
- using namespace boost::asio::ip;
- udp::Endpoint localEndpoint(address::from_string(localIp),
+ udp::Endpoint localEndpoint(ip::address::from_string(localIp),
boost::lexical_cast<uint16_t>(multicastPort));
-
- udp::Endpoint multicastEndpoint(address::from_string(multicastIp),
+ udp::Endpoint multicastEndpoint(ip::address::from_string(multicastIp),
boost::lexical_cast<uint16_t>(multicastPort));
-
return createMulticastFace(localEndpoint, multicastEndpoint, networkInterfaceName);
}
@@ -268,6 +254,7 @@
const FaceConnectFailedCallback& onConnectFailed)
{
BOOST_ASSERT(uri.isCanonical());
+
boost::asio::ip::address ipAddress = boost::asio::ip::address::from_string(uri.getHost());
udp::Endpoint endpoint(ipAddress, boost::lexical_cast<uint16_t>(uri.getPort()));
@@ -276,15 +263,13 @@
return;
}
- if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end())
- {
- onConnectFailed("Requested endpoint is prohibited "
- "(reserved by this NFD or disallowed by face management protocol)");
- return;
- }
+ if (m_prohibitedEndpoints.find(endpoint) != m_prohibitedEndpoints.end()) {
+ onConnectFailed("Requested endpoint is prohibited "
+ "(reserved by this NFD or disallowed by face management protocol)");
+ return;
+ }
// very simple logic for now
-
for (ChannelMap::iterator channel = m_channels.begin();
channel != m_channels.end();
++channel)
@@ -296,6 +281,7 @@
return;
}
}
+
onConnectFailed("No channels available to connect to " +
boost::lexical_cast<std::string>(endpoint));
}
@@ -320,17 +306,10 @@
return shared_ptr<MulticastUdpFace>();
}
-void
-UdpFactory::afterFaceFailed(udp::Endpoint& endpoint)
-{
- NFD_LOG_DEBUG("afterFaceFailed: " << endpoint);
- m_multicastFaces.erase(endpoint);
-}
-
-std::list<shared_ptr<const Channel> >
+std::list<shared_ptr<const Channel>>
UdpFactory::getChannels() const
{
- std::list<shared_ptr<const Channel> > channels;
+ std::list<shared_ptr<const Channel>> channels;
for (ChannelMap::const_iterator i = m_channels.begin(); i != m_channels.end(); ++i)
{
channels.push_back(i->second);
@@ -339,6 +318,4 @@
return channels;
}
-
-
} // namespace nfd