32 #include <boost/asio/ip/multicast.hpp>
33 #include <boost/asio/ip/v6_only.hpp>
38 #include <sys/socket.h>
43 namespace ip = boost::asio::ip;
48 ip::udp::socket&& recvSocket,
49 ip::udp::socket&& sendSocket,
50 ndn::nfd::LinkType linkType)
52 , m_multicastGroup(multicastGroup)
53 , m_sendSocket(std::move(sendSocket))
55 this->
setLocalUri(FaceUri(m_sendSocket.local_endpoint()));
57 this->
setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
62 boost::asio::socket_base::send_buffer_size sendBufferSizeOption;
63 boost::system::error_code error;
64 m_sendSocket.get_option(sendBufferSizeOption);
66 NFD_LOG_FACE_WARN(
"Failed to obtain send queue capacity from socket: " << error.message());
81 NFD_LOG_FACE_WARN(
"Failed to obtain send queue length from socket: " << std::strerror(errno));
87 MulticastUdpTransport::doSend(
const Block& packet)
91 m_sendSocket.async_send_to(boost::asio::buffer(packet), m_multicastGroup,
93 [
this, packet] (
auto&&... args) {
94 this->
handleSend(std::forward<decltype(args)>(args)...);
99 MulticastUdpTransport::doClose()
101 if (m_sendSocket.is_open()) {
106 boost::system::error_code error;
107 m_sendSocket.cancel(error);
108 m_sendSocket.close(error);
126 #if defined(__linux__) && !defined(__ANDROID__)
128 if (::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname.data(), ifname.size() + 1) < 0) {
129 NDN_THROW_ERRNO(MulticastUdpTransport::Error(
"Cannot bind multicast rx socket to " + ifname));
137 const ip::udp::endpoint& multicastGroup,
138 const ip::address& localAddress,
139 const ndn::net::NetworkInterface* netif)
141 BOOST_ASSERT(!sock.is_open());
143 sock.open(multicastGroup.protocol());
144 sock.set_option(boost::asio::socket_base::reuse_address(
true));
146 if (multicastGroup.address().is_v4()) {
147 BOOST_ASSERT(localAddress.is_v4());
148 sock.bind(multicastGroup);
149 sock.set_option(ip::multicast::join_group(multicastGroup.address().to_v4(), localAddress.to_v4()));
152 BOOST_ASSERT(multicastGroup.address().to_v6().scope_id() != 0);
153 sock.set_option(ip::v6_only(
true));
154 sock.bind(multicastGroup);
155 sock.set_option(ip::multicast::join_group(multicastGroup.address().to_v6()));
164 const ip::udp::endpoint& localEndpoint,
165 const ndn::net::NetworkInterface* netif,
168 BOOST_ASSERT(!sock.is_open());
170 sock.open(localEndpoint.protocol());
171 sock.set_option(boost::asio::socket_base::reuse_address(
true));
172 sock.set_option(ip::multicast::enable_loopback(enableLoopback));
174 if (localEndpoint.address().is_v4()) {
175 sock.bind(localEndpoint);
176 if (!localEndpoint.address().is_unspecified())
177 sock.set_option(ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
180 sock.set_option(ip::v6_only(
true));
181 sock.bind(localEndpoint);
183 sock.set_option(ip::multicast::outbound_interface(netif->getIndex()));
static void runElevated(F &&f)
Implements a Transport for datagram-based protocols.
void handleSend(const boost::system::error_code &error, size_t nBytesSent)
void doClose() override
Performs Transport specific operations to close the transport.
MulticastUdpTransport(const boost::asio::ip::udp::endpoint &multicastGroup, boost::asio::ip::udp::socket &&recvSocket, boost::asio::ip::udp::socket &&sendSocket, ndn::nfd::LinkType linkType)
Creates a UDP-based transport for multicast communication.
static void openRxSocket(boost::asio::ip::udp::socket &sock, const boost::asio::ip::udp::endpoint &multicastGroup, const boost::asio::ip::address &localAddress={}, const ndn::net::NetworkInterface *netif=nullptr)
Opens and configures the receive-side socket.
ssize_t getSendQueueLength() final
Returns the current send queue length of the transport (in octets).
static void openTxSocket(boost::asio::ip::udp::socket &sock, const boost::asio::ip::udp::endpoint &localEndpoint, const ndn::net::NetworkInterface *netif=nullptr, bool enableLoopback=false)
Opens and configures the transmit-side socket.
void setScope(ndn::nfd::FaceScope scope) noexcept
void setPersistency(ndn::nfd::FacePersistency newPersistency)
Changes the persistency setting of the transport.
void setMtu(ssize_t mtu) noexcept
void setSendQueueCapacity(ssize_t sendQueueCapacity) noexcept
void setLocalUri(const FaceUri &uri) noexcept
void setLinkType(ndn::nfd::LinkType linkType) noexcept
void setRemoteUri(const FaceUri &uri) noexcept
#define NFD_LOG_FACE_DEBUG(msg)
Log a message at DEBUG level.
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
#define NFD_LOG_MEMBER_INIT_SPECIALIZED(cls, name)
static void bindToDevice(int fd, const std::string &ifname)
constexpr ssize_t QUEUE_ERROR
Indicates that the transport was unable to retrieve the queue capacity/length.
ssize_t getTxQueueLength(int fd)
Obtain send queue length from a specified system socket.
ssize_t computeMtu(const Endpoint &localEndpoint)
Computes the maximum payload size in a UDP packet.