don't enable reuse-address for UDP sockets, as it will always succeed and not get any incoming packets. It's better to detect a port conflict and try a different port. Also implement port-retry logic for the UDP sockets

This commit is contained in:
Arvid Norberg 2018-05-13 16:52:32 +02:00 committed by Arvid Norberg
parent fe612ca167
commit 17055ad4d1
2 changed files with 39 additions and 6 deletions

View File

@ -1516,7 +1516,6 @@ namespace aux {
return ret;
}
ret->local_endpoint = ret->sock->local_endpoint(ec);
ret->device = lep.device;
last_op = operation_t::getname;
if (ec)
{
@ -1534,7 +1533,6 @@ namespace aux {
}
return ret;
}
ret->tracker_key = get_tracker_key(ret->local_endpoint.address());
ret->tcp_external_port = ret->local_endpoint.port();
TORRENT_ASSERT(ret->tcp_external_port == bind_ep.port()
@ -1565,7 +1563,7 @@ namespace aux {
= (lep.ssl == transport::ssl)
? socket_type_t::utp_ssl
: socket_type_t::udp;
udp::endpoint const udp_bind_ep(bind_ep.address(), bind_ep.port());
udp::endpoint udp_bind_ep(bind_ep.address(), bind_ep.port());
ret->udp_sock = std::make_shared<session_udp_socket>(m_io_service);
ret->udp_sock->sock.open(udp_bind_ep.protocol(), ec);
@ -1613,6 +1611,36 @@ namespace aux {
#endif
ret->udp_sock->sock.bind(udp_bind_ep, ec);
while (ec == error_code(error::address_in_use) && retries > 0)
{
TORRENT_ASSERT_VAL(ec, ec);
#ifndef TORRENT_DISABLE_LOGGING
if (should_log())
{
session_log("failed to bind udp socket to: %s on device: %s :"
" [%s] (%d) %s (retries: %d)"
, print_endpoint(bind_ep).c_str()
, lep.device.c_str()
, ec.category().name(), ec.value(), ec.message().c_str()
, retries);
}
#endif
ec.clear();
--retries;
udp_bind_ep.port(udp_bind_ep.port() + 1);
ret->udp_sock->sock.bind(udp_bind_ep, ec);
}
if (ec == error_code(error::address_in_use)
&& m_settings.get_bool(settings_pack::listen_system_port_fallback)
&& udp_bind_ep.port() != 0)
{
// instead of giving up, try let the OS pick a port
udp_bind_ep.port(0);
ec.clear();
ret->udp_sock->sock.bind(udp_bind_ep, ec);
}
last_op = operation_t::sock_bind;
if (ec)
{
@ -1640,6 +1668,9 @@ namespace aux {
ret->local_endpoint = tcp::endpoint(udp_ep.address(), udp_ep.port());
}
ret->tracker_key = get_tracker_key(ret->local_endpoint.address());
ret->device = lep.device;
error_code err;
set_socket_buffer_size(ret->udp_sock->sock, m_settings, err);
if (err)
@ -2584,6 +2615,10 @@ namespace aux {
}
async_accept(listener, ssl);
// don't accept any connections from our local sockets
if (m_settings.get_bool(settings_pack::force_proxy))
return;
#ifdef TORRENT_USE_OPENSSL
if (ssl == transport::ssl)
{

View File

@ -434,11 +434,9 @@ void udp_socket::open(udp const& protocol, error_code& ec)
#endif
// this is best-effort. ignore errors
error_code err;
#ifdef TORRENT_WINDOWS
error_code err;
m_socket.set_option(exclusive_address_use(true), err);
#else
m_socket.set_option(boost::asio::socket_base::reuse_address(true), err);
#endif
}