From d705dc295332b186cb3032c5941f16b698925f6c Mon Sep 17 00:00:00 2001 From: arvidn Date: Wed, 24 Feb 2016 23:20:42 -0500 Subject: [PATCH 1/3] attempt to fix issue with binding udp sockets on windows --- src/udp_socket.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index a923a8af6..3229ee223 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -694,22 +694,13 @@ void udp_socket::close() TORRENT_ASSERT(m_magic == 0x1337); error_code ec; - // if we close the socket here, we can't shut down - // utp connections or NAT-PMP. We need to cancel the - // outstanding operations - m_ipv4_sock.cancel(ec); - if (ec == error::operation_not_supported) - m_ipv4_sock.close(ec); + m_ipv4_sock.close(ec); TORRENT_ASSERT_VAL(!ec || ec == error::bad_descriptor, ec); #if TORRENT_USE_IPV6 - m_ipv6_sock.cancel(ec); - if (ec == error::operation_not_supported) - m_ipv6_sock.close(ec); + m_ipv6_sock.close(ec); TORRENT_ASSERT_VAL(!ec || ec == error::bad_descriptor, ec); #endif - m_socks5_sock.cancel(ec); - if (ec == error::operation_not_supported) - m_socks5_sock.close(ec); + m_socks5_sock.close(ec); TORRENT_ASSERT_VAL(!ec || ec == error::bad_descriptor, ec); m_resolver.cancel(); m_timer.cancel(); From e9a5985609383f0a881ad6530c8ef6bd2be3fac6 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sat, 5 Mar 2016 15:42:29 -0500 Subject: [PATCH 2/3] if a udp socket is already bound to the IP and port we want to bind it to, don't reopen it --- src/session_impl.cpp | 134 +++++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 61 deletions(-) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index d5dc33629..1de8400c6 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -2069,83 +2069,96 @@ retry: #ifdef TORRENT_USE_OPENSSL int const ssl_port = m_settings.get_int(settings_pack::ssl_listen); udp::endpoint ssl_bind_if(m_listen_interface.address(), ssl_port); + tcp::endpoint ssl_bind_ep(m_listen_interface.address(), ssl_port); // if ssl port is 0, we don't want to listen on an SSL port if (ssl_port != 0) { - // TODO: 2 use bind_to_device in udp_socket - m_ssl_udp_socket.bind(ssl_bind_if, ec); - if (ec) + // if the socket is already open with the port we want, just leave it + error_code err; + if (!m_ssl_udp_socket.is_open() + || m_ssl_udp_socket.local_endpoint(err) != ssl_bind_ep + || err) { -#ifndef TORRENT_DISABLE_LOGGING - session_log("SSL: cannot bind to UDP interface \"%s\": %s" - , print_endpoint(m_listen_interface).c_str(), ec.message().c_str()); -#endif - if (m_alerts.should_post()) + m_ssl_udp_socket.bind(ssl_bind_if, ec); + if (ec) { - error_code err; - m_alerts.emplace_alert(ssl_bind_if.address().to_string() - , ssl_port, listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl); +#ifndef TORRENT_DISABLE_LOGGING + session_log("SSL: cannot bind to UDP interface \"%s\": %s" + , print_endpoint(m_listen_interface).c_str(), ec.message().c_str()); +#endif + if (m_alerts.should_post()) + { + m_alerts.emplace_alert(ssl_bind_if.address().to_string() + , ssl_port, listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl); + } + ec.clear(); + } + else + { + maybe_update_udp_mapping(0, true, ssl_port, ssl_port); + maybe_update_udp_mapping(1, true, ssl_port, ssl_port); } - ec.clear(); } else { - maybe_update_udp_mapping(0, true, ssl_port, ssl_port); - maybe_update_udp_mapping(1, true, ssl_port, ssl_port); - } - } - else - { - m_ssl_udp_socket.close(); + m_ssl_udp_socket.close(); - // if there are mappings for the SSL socket, delete them now - if (m_ssl_udp_mapping[0] != -1 && m_natpmp) - { - m_natpmp->delete_mapping(m_ssl_udp_mapping[0]); - m_ssl_udp_mapping[0] = -1; - } - if (m_ssl_udp_mapping[1] != -1 && m_upnp) - { - m_upnp->delete_mapping(m_ssl_udp_mapping[1]); - m_ssl_udp_mapping[1] = -1; + // if there are mappings for the SSL socket, delete them now + if (m_ssl_udp_mapping[0] != -1 && m_natpmp) + { + m_natpmp->delete_mapping(m_ssl_udp_mapping[0]); + m_ssl_udp_mapping[0] = -1; + } + if (m_ssl_udp_mapping[1] != -1 && m_upnp) + { + m_upnp->delete_mapping(m_ssl_udp_mapping[1]); + m_ssl_udp_mapping[1] = -1; + } } } #endif // TORRENT_USE_OPENSSL - // TODO: 2 use bind_to_device in udp_socket - m_udp_socket.bind(udp::endpoint(m_listen_interface.address() - , m_listen_interface.port()), ec); - if (ec) + udp::endpoint const udp_bind_ep(m_listen_interface.address() + , m_listen_interface.port()); + + // if the socket is already open with the port we want, just leave it + error_code err; + if (!m_udp_socket.is_open() + || m_udp_socket.local_endpoint(err) != m_listen_interface + || err) { + m_udp_socket.bind(udp_bind_ep, ec); + if (ec) + { #ifndef TORRENT_DISABLE_LOGGING - session_log("cannot bind to UDP interface \"%s\": %s" - , print_endpoint(m_listen_interface).c_str(), ec.message().c_str()); + session_log("cannot bind to UDP interface \"%s\": %s" + , print_endpoint(m_listen_interface).c_str(), ec.message().c_str()); #endif - if (m_alerts.should_post()) - { - error_code err; - m_alerts.emplace_alert(m_listen_interface.address().to_string() - , m_listen_interface.port() - , listen_failed_alert::bind - , ec, listen_failed_alert::udp); + if (m_alerts.should_post()) + { + m_alerts.emplace_alert(m_listen_interface.address().to_string() + , m_listen_interface.port() + , listen_failed_alert::bind + , ec, listen_failed_alert::udp); + } + if (listen_port_retries > 0) + { + m_listen_interface.port(m_listen_interface.port() + 1); + // update the actual port m_listen_interface was derived from also + if (!m_listen_interfaces.empty()) + m_listen_interfaces[0].second += 1; + --listen_port_retries; + goto retry; + } + return; } - if (listen_port_retries > 0) + else { - m_listen_interface.port(m_listen_interface.port() + 1); - // update the actual port m_listen_interface was derived from also - if (!m_listen_interfaces.empty()) - m_listen_interfaces[0].second += 1; - --listen_port_retries; - goto retry; + m_external_udp_port = m_udp_socket.local_port(); + maybe_update_udp_mapping(0, false, m_listen_interface.port(), m_listen_interface.port()); + maybe_update_udp_mapping(1, false, m_listen_interface.port(), m_listen_interface.port()); } - return; - } - else - { - m_external_udp_port = m_udp_socket.local_port(); - maybe_update_udp_mapping(0, false, m_listen_interface.port(), m_listen_interface.port()); - maybe_update_udp_mapping(1, false, m_listen_interface.port(), m_listen_interface.port()); } // we made it! now post all the listen_succeeded_alerts @@ -2159,9 +2172,9 @@ retry: if (!m_alerts.should_post()) continue; - error_code err; - tcp::endpoint bind_ep = i->sock->local_endpoint(err); - if (err) continue; + error_code error; + tcp::endpoint bind_ep = i->sock->local_endpoint(error); + if (error) continue; m_alerts.emplace_alert(bind_ep, socket_type); } @@ -2171,8 +2184,7 @@ retry: { if (m_alerts.should_post()) m_alerts.emplace_alert( - tcp::endpoint(ssl_bind_if.address(), ssl_bind_if.port()) - , listen_succeeded_alert::utp_ssl); + ssl_bind_ep, listen_succeeded_alert::utp_ssl); } #endif From 53b5e964d208f390d51bd9793346e58fbba6fd6f Mon Sep 17 00:00:00 2001 From: arvidn Date: Fri, 18 Mar 2016 23:32:57 -0400 Subject: [PATCH 3/3] fix merge issue and properly close ssl udp socket when disabled, prevents the extra listen_succeeded alert for the ssl udp socket --- src/session_impl.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 1de8400c6..dfd4762ce 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -2092,6 +2092,7 @@ retry: m_alerts.emplace_alert(ssl_bind_if.address().to_string() , ssl_port, listen_failed_alert::bind, ec, listen_failed_alert::utp_ssl); } + m_ssl_udp_socket.close(); ec.clear(); } else @@ -2100,21 +2101,21 @@ retry: maybe_update_udp_mapping(1, true, ssl_port, ssl_port); } } - else - { - m_ssl_udp_socket.close(); + } + else + { + m_ssl_udp_socket.close(); - // if there are mappings for the SSL socket, delete them now - if (m_ssl_udp_mapping[0] != -1 && m_natpmp) - { - m_natpmp->delete_mapping(m_ssl_udp_mapping[0]); - m_ssl_udp_mapping[0] = -1; - } - if (m_ssl_udp_mapping[1] != -1 && m_upnp) - { - m_upnp->delete_mapping(m_ssl_udp_mapping[1]); - m_ssl_udp_mapping[1] = -1; - } + // if there are mappings for the SSL socket, delete them now + if (m_ssl_udp_mapping[0] != -1 && m_natpmp) + { + m_natpmp->delete_mapping(m_ssl_udp_mapping[0]); + m_ssl_udp_mapping[0] = -1; + } + if (m_ssl_udp_mapping[1] != -1 && m_upnp) + { + m_upnp->delete_mapping(m_ssl_udp_mapping[1]); + m_ssl_udp_mapping[1] = -1; } } #endif // TORRENT_USE_OPENSSL @@ -2142,6 +2143,7 @@ retry: , listen_failed_alert::bind , ec, listen_failed_alert::udp); } + m_udp_socket.close(); if (listen_port_retries > 0) { m_listen_interface.port(m_listen_interface.port() + 1); @@ -2166,7 +2168,7 @@ retry: for (std::list::iterator i = m_listen_sockets.begin() , end(m_listen_sockets.end()); i != end; ++i) { - listen_succeeded_alert::socket_type_t socket_type = i->ssl + listen_succeeded_alert::socket_type_t const socket_type = i->ssl ? listen_succeeded_alert::tcp_ssl : listen_succeeded_alert::tcp;