diff --git a/libtorrent/include/libtorrent/udp_socket.hpp b/libtorrent/include/libtorrent/udp_socket.hpp index d25d46ca..e9cb2e86 100644 --- a/libtorrent/include/libtorrent/udp_socket.hpp +++ b/libtorrent/include/libtorrent/udp_socket.hpp @@ -176,7 +176,7 @@ namespace libtorrent void on_name_lookup(error_code const& e, tcp::resolver::iterator i); void on_timeout(); void on_connect(int ticket); - void on_connected(error_code const& ec); + void on_connected(error_code const& ec, int ticket); void handshake1(error_code const& e); void handshake2(error_code const& e); void handshake3(error_code const& e); diff --git a/libtorrent/src/udp_socket.cpp b/libtorrent/src/udp_socket.cpp index e5445350..cf18b7f5 100644 --- a/libtorrent/src/udp_socket.cpp +++ b/libtorrent/src/udp_socket.cpp @@ -873,6 +873,13 @@ void udp_socket::on_connect(int ticket) if (m_abort) return; if (is_closed()) return; + if (m_connection_ticket != -1) + { + // there's already an outstanding connect. Cancel it. + m_socks5_sock.close(); + m_connection_ticket = -1; + } + #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("udp_socket::on_connected"); #endif @@ -885,10 +892,10 @@ void udp_socket::on_connect(int ticket) ++m_outstanding_connect; #endif m_socks5_sock.async_connect(tcp::endpoint(m_proxy_addr.address(), m_proxy_addr.port()) - , boost::bind(&udp_socket::on_connected, this, _1)); + , boost::bind(&udp_socket::on_connected, this, _1, ticket)); } -void udp_socket::on_connected(error_code const& e) +void udp_socket::on_connected(error_code const& e, int ticket) { #if defined TORRENT_ASIO_DEBUGGING complete_async("udp_socket::on_connected"); @@ -904,14 +911,15 @@ void udp_socket::on_connected(error_code const& e) + m_outstanding_resolve + m_outstanding_connect_queue + m_outstanding_socks); - if (m_abort) return; - CHECK_MAGIC; - if (e == asio::error::operation_aborted) return; + CHECK_MAGIC; TORRENT_ASSERT(is_single_thread()); - m_cc.done(m_connection_ticket); - m_connection_ticket = -1; + m_cc.done(ticket); + // if the tickets mismatch, another connection attempt + // was initiated while waiting for this one to complete. + if (ticket == m_connection_ticket) + m_connection_ticket = -1; // we just called done, which means on_timeout // won't be called. Decrement the outstanding @@ -927,6 +935,14 @@ void udp_socket::on_connected(error_code const& e) + m_outstanding_resolve + m_outstanding_connect_queue + m_outstanding_socks); + + if (e == asio::error::operation_aborted) return; + + // if ticket != m_connection_ticket, it means m_connection_ticket + // will not have been reset, and it means we are still waiting + // for a connection attempt. + if (m_connection_ticket != -1) return; + if (m_abort) return; if (e)