fix bind-to-device for UDP sockets

This commit is contained in:
arvidn 2016-12-10 14:31:09 -05:00 committed by Arvid Norberg
parent 6b70ac1f77
commit bbfe58d03c
4 changed files with 34 additions and 15 deletions

View File

@ -579,10 +579,9 @@ namespace libtorrent
bool is_dht_running() const { return (m_dht.get() != nullptr); } bool is_dht_running() const { return (m_dht.get() != nullptr); }
int external_udp_port() const override int external_udp_port() const override
{ {
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin() for (auto const& s : m_listen_sockets)
, end(m_listen_sockets.end()); i != end; ++i)
{ {
if (i->udp_sock) return i->udp_external_port; if (s.udp_sock) return s.udp_external_port;
} }
return -1; return -1;
} }

View File

@ -89,6 +89,7 @@ namespace libtorrent
void send(udp::endpoint const& ep, span<char const> p void send(udp::endpoint const& ep, span<char const> p
, error_code& ec, int flags = 0); , error_code& ec, int flags = 0);
void open(udp const& protocol, error_code& ec);
void bind(udp::endpoint const& ep, error_code& ec); void bind(udp::endpoint const& ep, error_code& ec);
void close(); void close();
int local_port() const { return m_bind_port; } int local_port() const { return m_bind_port; }

View File

@ -1635,8 +1635,28 @@ namespace aux {
= (flags & open_ssl_socket) = (flags & open_ssl_socket)
? socket_type_t::utp_ssl ? socket_type_t::utp_ssl
: socket_type_t::udp; : socket_type_t::udp;
udp::endpoint const udp_bind_ep(bind_ep.address(), bind_ep.port());
ret.udp_sock = std::make_shared<udp_socket>(m_io_service); ret.udp_sock = std::make_shared<udp_socket>(m_io_service);
ret.udp_sock->open(udp_bind_ep.protocol(), ec);
if (ec)
{
#ifndef TORRENT_DISABLE_LOGGING
if (should_log())
{
session_log("failed to open UDP socket: %s: %s"
, device.c_str(), ec.message().c_str());
}
#endif
last_op = listen_failed_alert::open;
if (m_alerts.should_post<listen_failed_alert>())
m_alerts.emplace_alert<listen_failed_alert>(device
, bind_ep, last_op, ec, udp_sock_type);
return ret;
}
#if TORRENT_HAS_BINDTODEVICE #if TORRENT_HAS_BINDTODEVICE
if (!device.empty()) if (!device.empty())
{ {
@ -1661,8 +1681,7 @@ namespace aux {
} }
} }
#endif #endif
ret.udp_sock->bind(udp::endpoint(bind_ep.address(), bind_ep.port()) ret.udp_sock->bind(udp_bind_ep, ec);
, ec);
last_op = listen_failed_alert::bind; last_op = listen_failed_alert::bind;
if (ec) if (ec)
@ -1670,7 +1689,7 @@ namespace aux {
#ifndef TORRENT_DISABLE_LOGGING #ifndef TORRENT_DISABLE_LOGGING
if (should_log()) if (should_log())
{ {
session_log("failed to open UDP socket: %s: %s" session_log("failed to bind UDP socket: %s: %s"
, device.c_str(), ec.message().c_str()); , device.c_str(), ec.message().c_str());
} }
#endif #endif

View File

@ -404,7 +404,7 @@ void udp_socket::close()
m_abort = true; m_abort = true;
} }
void udp_socket::bind(udp::endpoint const& ep, error_code& ec) void udp_socket::open(udp const& protocol, error_code& ec)
{ {
TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(is_single_thread());
@ -413,16 +413,11 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
if (m_socket.is_open()) m_socket.close(ec); if (m_socket.is_open()) m_socket.close(ec);
ec.clear(); ec.clear();
if (ep.address().is_v4()) m_socket.open(protocol, ec);
{
m_socket.open(udp::v4(), ec);
if (ec) return; if (ec) return;
}
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
else if (ep.address().is_v6()) if (protocol == udp::v6())
{ {
m_socket.open(udp::v6(), ec);
if (ec) return;
error_code err; error_code err;
m_socket.set_option(boost::asio::ip::v6_only(true), err); m_socket.set_option(boost::asio::ip::v6_only(true), err);
@ -439,7 +434,12 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
m_socket.set_option(exclusive_address_use(true), err); m_socket.set_option(exclusive_address_use(true), err);
#endif #endif
m_socket.set_option(boost::asio::socket_base::reuse_address(true), err); m_socket.set_option(boost::asio::socket_base::reuse_address(true), err);
}
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
{
if (!m_socket.is_open()) open(ep.protocol(), ec);
if (ec) return;
m_socket.bind(ep, ec); m_socket.bind(ep, ec);
if (ec) return; if (ec) return;
udp::socket::non_blocking_io ioc(true); udp::socket::non_blocking_io ioc(true);