diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 510a0f857..2587b50df 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -1062,6 +1062,15 @@ namespace libtorrent // the timer used to fire the tick deadline_timer m_timer; + aux::handler_storage m_tick_handler_storage; + + template + aux::allocating_handler + make_tick_handler(Handler const& handler) + { + return aux::allocating_handler( + handler, m_tick_handler_storage); + } // torrents are announced on the local network in a // round-robin fashion. All torrents are cycled through diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 32cf2491f..0255bb57a 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -985,7 +985,6 @@ namespace libtorrent // have sent to it int m_outstanding_bytes; - // TODO: 3 use handler storage for second_tick and udp_packet handler too aux::handler_storage m_read_handler_storage; aux::handler_storage m_write_handler_storage; diff --git a/include/libtorrent/udp_socket.hpp b/include/libtorrent/udp_socket.hpp index 83442e970..23f6c8a07 100644 --- a/include/libtorrent/udp_socket.hpp +++ b/include/libtorrent/udp_socket.hpp @@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/thread.hpp" #include "libtorrent/deadline_timer.hpp" #include "libtorrent/debug.hpp" +#include "libtorrent/aux_/allocating_handler.hpp" #include @@ -179,6 +180,26 @@ namespace libtorrent std::vector m_observers; std::vector m_added_observers; + template + aux::allocating_handler + make_read_handler4(Handler const& handler) + { + return aux::allocating_handler( + handler, m_v4_read_handler_storage + ); + } + +#if TORRENT_USE_IPV6 + template + aux::allocating_handler + make_read_handler6(Handler const& handler) + { + return aux::allocating_handler( + handler, m_v6_read_handler_storage + ); + } +#endif + // this is true while iterating over the observers // vector, invoking observer hooks. We may not // add new observers during this time, since it @@ -219,6 +240,7 @@ namespace libtorrent void unwrap(error_code const& e, char const* buf, int size); udp::socket m_ipv4_sock; + aux::handler_storage m_v4_read_handler_storage; deadline_timer m_timer; int m_buf_size; @@ -232,12 +254,15 @@ namespace libtorrent #if TORRENT_USE_IPV6 udp::socket m_ipv6_sock; + aux::handler_storage m_v6_read_handler_storage; #endif boost::uint16_t m_bind_port; boost::uint8_t m_v4_outstanding; + boost::uint8_t m_restart_v4; #if TORRENT_USE_IPV6 boost::uint8_t m_v6_outstanding; + boost::uint8_t m_restart_v6; #endif tcp::socket m_socks5_sock; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 03fd963b5..0dac584fe 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1730,9 +1730,10 @@ namespace aux { { TORRENT_ASSERT_VAL(ec, ec); #ifndef TORRENT_DISABLE_LOGGING + error_code ignore; session_log("failed to bind to interface [%s %d] \"%s\" : %s (%d) : %s " "(retries: %d)" - , device.c_str(), port, bind_ip.to_string(ec).c_str() + , device.c_str(), port, bind_ip.to_string(ignore).c_str() , ec.category().name(), ec.value(), ec.message().c_str(), retries); #endif ec.clear(); @@ -1755,6 +1756,8 @@ namespace aux { } if (ec) { + TORRENT_ASSERT_VAL(ec.value() != 0, ec); + // not even that worked, give up if (m_alerts.should_post()) m_alerts.emplace_alert(device, last_op, ec, sock_type); @@ -2958,7 +2961,7 @@ retry: #endif error_code ec; m_timer.expires_at(now + milliseconds(m_settings.get_int(settings_pack::tick_interval)), ec); - m_timer.async_wait(boost::bind(&session_impl::on_tick, this, _1)); + m_timer.async_wait(make_tick_handler(boost::bind(&session_impl::on_tick, this, _1))); m_download_rate.update_quotas(now - m_last_tick); m_upload_rate.update_quotas(now - m_last_tick); diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 9a2481119..5703fbc5b 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -67,8 +67,10 @@ udp_socket::udp_socket(io_service& ios) #endif , m_bind_port(0) , m_v4_outstanding(0) + , m_restart_v4(0) #if TORRENT_USE_IPV6 , m_v6_outstanding(0) + , m_restart_v6(false) #endif , m_socks5_sock(ios) , m_resolver(ios) @@ -284,7 +286,26 @@ void udp_socket::on_read(error_code const& ec, udp::socket* s) --m_v4_outstanding; } - if (ec == boost::asio::error::operation_aborted) return; + if (ec == boost::asio::error::operation_aborted) + { +#if TORRENT_USE_IPV6 + if (s == &m_ipv6_sock) + { + if (m_restart_v6) { + --m_restart_v6; + setup_read(s); + } + } + else +#endif + { + if (m_restart_v4) { + --m_restart_v4; + setup_read(s); + } + } + return; + } if (m_abort) return; CHECK_MAGIC; @@ -498,10 +519,26 @@ void udp_socket::setup_read(udp::socket* s) #if TORRENT_USE_IPV6 if (s == &m_ipv6_sock) + { + if (m_v6_outstanding) + { + ++m_restart_v6; + m_ipv6_sock.cancel(); + return; + } ++m_v6_outstanding; + } else #endif + { + if (m_v4_outstanding) + { + ++m_restart_v4; + m_ipv4_sock.cancel(); + return; + } ++m_v4_outstanding; + } #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("udp_socket::on_read"); @@ -510,8 +547,18 @@ void udp_socket::setup_read(udp::socket* s) udp::endpoint ep; TORRENT_TRY { - s->async_receive_from(null_buffers() - , ep, boost::bind(&udp_socket::on_read, this, _1, s)); +#if TORRENT_USE_IPV6 + if (s == &m_ipv6_sock) + { + s->async_receive_from(null_buffers() + , ep, make_read_handler6(boost::bind(&udp_socket::on_read, this, _1, s))); + } + else +#endif + { + s->async_receive_from(null_buffers() + , ep, make_read_handler4(boost::bind(&udp_socket::on_read, this, _1, s))); + } } TORRENT_CATCH(boost::system::system_error& e) {