From acdb647eca2ef63dbe825034a429ac5e64ffb49c Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 1 Oct 2012 00:13:58 +0000 Subject: [PATCH] merged udp tracker fix from RC_0_16 --- ChangeLog | 2 + include/libtorrent/tracker_manager.hpp | 2 +- include/libtorrent/udp_tracker_connection.hpp | 6 +++ src/tracker_manager.cpp | 2 +- src/udp_tracker_connection.cpp | 44 +++++++++++++++---- 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5be44733..764f056be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,8 @@ * fix uTP edge case where udp socket buffer fills up * fix nagle implementation in uTP + * fix UDP trackers trying all endpoints behind the hostname + 0.16.4 release * raise the default number of torrents allowed to announce to trackers to 1600 diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index d0f68f85c..60d391553 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -225,7 +225,7 @@ namespace libtorrent , io_service& ios , boost::weak_ptr r); - boost::shared_ptr requester(); + boost::shared_ptr requester() const; virtual ~tracker_connection() {} tracker_request const& tracker_req() const { return m_req; } diff --git a/include/libtorrent/udp_tracker_connection.hpp b/include/libtorrent/udp_tracker_connection.hpp index cd19b669c..671848fef 100644 --- a/include/libtorrent/udp_tracker_connection.hpp +++ b/include/libtorrent/udp_tracker_connection.hpp @@ -108,12 +108,18 @@ namespace libtorrent bool on_announce_response(char const* buf, int size); bool on_scrape_response(char const* buf, int size); + // wraps tracker_connection::fail + void fail(error_code const& ec, int code = -1 + , char const* msg = "", int interval = 0, int min_interval = 0); + void send_udp_connect(); void send_udp_announce(); void send_udp_scrape(); virtual void on_timeout(error_code const& ec); + udp::endpoint pick_target_endpoint() const; + // tracker_manager& m_man; bool m_abort; diff --git a/src/tracker_manager.cpp b/src/tracker_manager.cpp index db7d90891..cc671181a 100644 --- a/src/tracker_manager.cpp +++ b/src/tracker_manager.cpp @@ -156,7 +156,7 @@ namespace libtorrent , m_req(req) {} - boost::shared_ptr tracker_connection::requester() + boost::shared_ptr tracker_connection::requester() const { return m_requester.lock(); } diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 964400f74..88b4e7387 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -132,6 +132,26 @@ namespace libtorrent , settings.tracker_receive_timeout); } + void udp_tracker_connection::fail(error_code const& ec, int code + , char const* msg, int interval, int min_interval) + { + // m_target failed. remove it from the endpoint list + std::list::iterator i = std::find(m_endpoints.begin() + , m_endpoints.end(), tcp::endpoint(m_target.address(), m_target.port())); + + if (i != m_endpoints.end()) m_endpoints.erase(i); + + // if that was the last one, fail the whole announce + if (m_endpoints.empty()) + tracker_connection::fail(ec, code, msg, interval, min_interval); + + // pick another target endpoint and try again + m_target = pick_target_endpoint(); + + m_ses.m_io_service.post(boost::bind( + &udp_tracker_connection::start_announce, self())); + } + void udp_tracker_connection::name_lookup(error_code const& error , tcp::resolver::iterator i) { @@ -191,8 +211,17 @@ namespace libtorrent return; } - std::list::iterator iter = m_endpoints.begin(); - m_target = udp::endpoint(iter->address(), iter->port()); + m_target = pick_target_endpoint(); + + if (cb) cb->m_tracker_address = tcp::endpoint(m_target.address(), m_target.port()); + + start_announce(); + } + + udp::endpoint udp_tracker_connection::pick_target_endpoint() const + { + std::list::const_iterator iter = m_endpoints.begin(); + udp::endpoint target = udp::endpoint(iter->address(), iter->port()); if (bind_interface() != address_v4::any()) { @@ -202,10 +231,11 @@ namespace libtorrent if (iter == m_endpoints.end()) { - TORRENT_ASSERT(m_target.address().is_v4() != bind_interface().is_v4()); + TORRENT_ASSERT(target.address().is_v4() != bind_interface().is_v4()); + boost::shared_ptr cb = requester(); if (cb) { - char const* tracker_address_type = m_target.address().is_v4() ? "IPv4" : "IPv6"; + char const* tracker_address_type = target.address().is_v4() ? "IPv4" : "IPv6"; char const* bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; char msg[200]; snprintf(msg, sizeof(msg) @@ -219,13 +249,11 @@ namespace libtorrent } else { - m_target = udp::endpoint(iter->address(), iter->port()); + target = udp::endpoint(iter->address(), iter->port()); } } - if (cb) cb->m_tracker_address = tcp::endpoint(m_target.address(), m_target.port()); - - start_announce(); + return target; } void udp_tracker_connection::start_announce()