changed how trackers are handled. Implements #297 by setting session_settings::announce_to_all_trackers to true
This commit is contained in:
parent
acbdbfc1ef
commit
d1a2b774e6
|
@ -1482,11 +1482,42 @@ ones with lower tier will always be tried before the one with higher tier number
|
|||
std::string url;
|
||||
boost::uint8_t tier;
|
||||
boost::uint8_t fail_limit;
|
||||
boost::uint8_t fails;
|
||||
|
||||
enum tracker_source
|
||||
{
|
||||
source_torrent = 1,
|
||||
source_client = 2,
|
||||
source_magnet_link = 4,
|
||||
source_tex = 8
|
||||
};
|
||||
boost::uint8_t source;
|
||||
|
||||
bool verified:1;
|
||||
bool updating:1;
|
||||
bool start_sent:1;
|
||||
bool complete_sent:1;
|
||||
};
|
||||
|
||||
``fail_limit`` is the max number of failures to announce to this tracker in
|
||||
a row, before this tracker is not used anymore.
|
||||
|
||||
``fails`` is the number of times in a row we have failed to announce to this
|
||||
tracker.
|
||||
|
||||
``source`` is a bitmask specifying which sources we got this tracker from.
|
||||
|
||||
``verified`` is set to true the first time we receive a valid response
|
||||
from this tracker.
|
||||
|
||||
``updating`` is true while we're waiting for a response from the tracker.
|
||||
|
||||
``start_sent`` is set to true when we get a valid response from an announce
|
||||
with event=started. If it is set, we won't send start in the subsequent
|
||||
announces.
|
||||
|
||||
``complete_sent`` is set to true when we send a event=completed.
|
||||
|
||||
|
||||
total_size() piece_length() piece_size() num_pieces()
|
||||
-----------------------------------------------------
|
||||
|
@ -3057,6 +3088,8 @@ that will be sent to the tracker. The user-agent is a good way to identify your
|
|||
int auto_manage_startup;
|
||||
|
||||
bool rate_limit_ip_overhead;
|
||||
|
||||
bool announce_to_all_trackers;
|
||||
};
|
||||
|
||||
``user_agent`` this is the client identification to the tracker.
|
||||
|
@ -3341,6 +3374,14 @@ have a fair chance to start downloading.
|
|||
If ``rate_limit_ip_overhead`` is set to true, the estimated TCP/IP overhead is
|
||||
drained from the rate limiters, to avoid exceeding the limits with the total traffic
|
||||
|
||||
``announce_to_all_trackers`` controls how multi tracker torrents are
|
||||
treated. If this is set to true, all trackers in the same tier are
|
||||
announced to in parallel. If all trackers in tier 0 fails, all trackers
|
||||
in tier 1 are announced as well. This is the uTorrent behavior. If it's
|
||||
set to false, the behavior is as defined by the multi tracker
|
||||
specification. It defaults to false, which is the same behavior previous
|
||||
versions of libtorrent has had as well.
|
||||
|
||||
|
||||
pe_settings
|
||||
===========
|
||||
|
|
|
@ -154,6 +154,7 @@ void clear_home()
|
|||
|
||||
#endif
|
||||
|
||||
bool print_trackers = false;
|
||||
bool print_peers = false;
|
||||
bool print_log = false;
|
||||
bool print_downloads = false;
|
||||
|
@ -849,6 +850,7 @@ int main(int ac, char* av[])
|
|||
|
||||
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
|
||||
settings.urlseed_wait_retry = wait_retry;
|
||||
settings.announce_to_all_trackers = true;
|
||||
|
||||
settings.outgoing_ports.first = bind_port_start;
|
||||
settings.outgoing_ports.second = bind_port_end;
|
||||
|
@ -1214,6 +1216,7 @@ int main(int ac, char* av[])
|
|||
}
|
||||
|
||||
// toggle displays
|
||||
if (c == 't') print_trackers = !print_trackers;
|
||||
if (c == 'i') print_peers = !print_peers;
|
||||
if (c == 'l') print_log = !print_log;
|
||||
if (c == 'd') print_downloads = !print_downloads;
|
||||
|
@ -1348,7 +1351,7 @@ int main(int ac, char* av[])
|
|||
<< std::hex << s.seed_rank << std::dec << " "
|
||||
<< s.last_scrape << "\n" << esc("0");
|
||||
|
||||
if (torrent_index != active_torrent && s.state != torrent_status::seeding) continue;
|
||||
if (torrent_index != active_torrent && s.state == torrent_status::seeding) continue;
|
||||
char const* progress_bar_color = "33"; // yellow
|
||||
if (s.state == torrent_status::checking_files
|
||||
|| s.state == torrent_status::downloading_metadata)
|
||||
|
@ -1388,6 +1391,7 @@ int main(int ac, char* av[])
|
|||
<< to_string(t.seconds(), 2) << esc("0") << " ";
|
||||
out << "tracker: " << esc("36") << s.current_tracker << esc("0") << "\n";
|
||||
|
||||
if (torrent_index != active_torrent) continue;
|
||||
active_handle = h;
|
||||
}
|
||||
|
||||
|
@ -1451,6 +1455,23 @@ int main(int ac, char* av[])
|
|||
if (print_peers && !peers.empty())
|
||||
print_peer_info(out, peers);
|
||||
|
||||
if (print_trackers)
|
||||
{
|
||||
std::vector<announce_entry> tr = h.trackers();
|
||||
ptime now = time_now();
|
||||
for (std::vector<announce_entry>::iterator i = tr.begin()
|
||||
, end(tr.end()); i != end; ++i)
|
||||
{
|
||||
std::string url = i->url;
|
||||
url.resize(55, ' ');
|
||||
out << to_string(i->tier, 2) << " " << url << " "
|
||||
<< to_string(i->fails, 3) << " " << (i->verified?"OK ":"- ");
|
||||
if (i->updating) out << "updating";
|
||||
else out << to_string(total_seconds(i->next_announce - now), 8);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (print_downloads)
|
||||
{
|
||||
h.get_download_queue(queue);
|
||||
|
|
|
@ -144,6 +144,7 @@ namespace libtorrent
|
|||
, prioritize_partial_pieces(false)
|
||||
, auto_manage_startup(120)
|
||||
, rate_limit_ip_overhead(true)
|
||||
, announce_to_all_trackers(false)
|
||||
{}
|
||||
|
||||
// this is the user agent that will be sent to the tracker
|
||||
|
@ -456,6 +457,11 @@ namespace libtorrent
|
|||
// drained from the rate limiters, to avoid exceeding
|
||||
// the limits with the total traffic
|
||||
bool rate_limit_ip_overhead;
|
||||
|
||||
// if set to true, multi tracker torrents are treated
|
||||
// the same way uTorrent treats them. It defaults to
|
||||
// false in order to comply with the extension definition.
|
||||
bool announce_to_all_trackers;
|
||||
};
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
|
|
@ -81,6 +81,8 @@ namespace libtorrent
|
|||
class piece_manager;
|
||||
struct torrent_plugin;
|
||||
struct bitfield;
|
||||
struct announce_entry;
|
||||
struct tracker_request;
|
||||
|
||||
namespace aux
|
||||
{
|
||||
|
@ -409,6 +411,8 @@ namespace libtorrent
|
|||
// announce ourself at the last time we tried to announce
|
||||
const tcp::endpoint& current_tracker() const;
|
||||
|
||||
announce_entry* find_tracker(tracker_request const& r);
|
||||
|
||||
// --------------------------------------------
|
||||
// PIECE MANAGEMENT
|
||||
|
||||
|
@ -586,7 +590,7 @@ namespace libtorrent
|
|||
{ return m_trackers; }
|
||||
|
||||
void replace_trackers(std::vector<announce_entry> const& urls);
|
||||
void add_tracker(announce_entry const& urls);
|
||||
void add_tracker(announce_entry const& url);
|
||||
|
||||
torrent_handle get_handle();
|
||||
|
||||
|
@ -656,8 +660,9 @@ namespace libtorrent
|
|||
void on_piece_verified(int ret, disk_io_job const& j
|
||||
, boost::function<void(int)> f);
|
||||
|
||||
void try_next_tracker(tracker_request const& req);
|
||||
int prioritize_tracker(int tracker_index);
|
||||
int deprioritize_tracker(int tracker_index);
|
||||
|
||||
void on_country_lookup(error_code const& error, tcp::resolver::iterator i
|
||||
, boost::intrusive_ptr<peer_connection> p) const;
|
||||
bool request_bandwidth_from_session(int channel) const;
|
||||
|
@ -718,9 +723,6 @@ namespace libtorrent
|
|||
// the object.
|
||||
piece_manager* m_storage;
|
||||
|
||||
// the time of next tracker announce
|
||||
ptime m_next_tracker_announce;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
#endif
|
||||
|
@ -757,7 +759,7 @@ namespace libtorrent
|
|||
// used for tracker announces
|
||||
deadline_timer m_tracker_timer;
|
||||
|
||||
void restart_tracker_timer(ptime announce_at);
|
||||
void update_tracker_timer();
|
||||
|
||||
static void on_tracker_announce_disp(boost::weak_ptr<torrent> p
|
||||
, error_code const& e);
|
||||
|
@ -895,10 +897,6 @@ namespace libtorrent
|
|||
// torrent object, these points are called connect_points.
|
||||
int m_deficit_counter;
|
||||
|
||||
// the number number of seconds between requests
|
||||
// from the tracker
|
||||
boost::int16_t m_duration;
|
||||
|
||||
// the sequence number for this torrent, this is a
|
||||
// monotonically increasing number for each added torrent
|
||||
boost::int16_t m_sequence_number;
|
||||
|
@ -906,10 +904,6 @@ namespace libtorrent
|
|||
// the index to the last tracker that worked
|
||||
boost::int8_t m_last_working_tracker;
|
||||
|
||||
// the tracker that is currently (or was last)
|
||||
// tried
|
||||
boost::int8_t m_currently_trying_tracker;
|
||||
|
||||
// the number of connection attempts that has
|
||||
// failed in a row, this is currently used to
|
||||
// determine the timeout until next try.
|
||||
|
@ -979,27 +973,30 @@ namespace libtorrent
|
|||
// this is true while tracker announcing is enabled
|
||||
// is is disabled while paused and checking files
|
||||
bool m_announcing:1;
|
||||
|
||||
// this is true if event start has been sent to the tracker
|
||||
bool m_start_sent:1;
|
||||
|
||||
// this is true if event completed has been sent to the tracker
|
||||
bool m_complete_sent:1;
|
||||
};
|
||||
|
||||
inline ptime torrent::next_announce() const
|
||||
{
|
||||
return m_next_tracker_announce;
|
||||
return m_tracker_timer.expires_at();
|
||||
}
|
||||
|
||||
inline void torrent::force_tracker_request()
|
||||
{
|
||||
if (!is_paused()) announce_with_tracker();
|
||||
if (is_paused()) return;
|
||||
ptime now = time_now();
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
i->next_announce = now;
|
||||
update_tracker_timer();
|
||||
}
|
||||
|
||||
inline void torrent::force_tracker_request(ptime t)
|
||||
{
|
||||
if (!is_paused()) restart_tracker_timer(t);
|
||||
if (is_paused()) return;
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
i->next_announce = t;
|
||||
update_tracker_timer();
|
||||
}
|
||||
|
||||
inline void torrent::set_tracker_login(
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace libtorrent
|
|||
|
||||
void clear_error() const;
|
||||
|
||||
std::vector<announce_entry> const& trackers() const;
|
||||
std::vector<announce_entry> trackers() const;
|
||||
void replace_trackers(std::vector<announce_entry> const&) const;
|
||||
void add_tracker(announce_entry const&) const;
|
||||
|
||||
|
|
|
@ -66,15 +66,34 @@ namespace libtorrent
|
|||
namespace gr = boost::gregorian;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
enum
|
||||
{
|
||||
// wait 60 seconds before retrying a failed tracker
|
||||
tracker_retry_delay_min = 10
|
||||
// when tracker_failed_max trackers
|
||||
// has failed, wait 60 minutes instead
|
||||
, tracker_retry_delay_max = 60 * 60
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT announce_entry
|
||||
{
|
||||
announce_entry(std::string const& u)
|
||||
: url(u), tier(0)
|
||||
, fail_limit(3), fails(0)
|
||||
: url(u)
|
||||
, tier(0)
|
||||
, fail_limit(3)
|
||||
, fails(0)
|
||||
, source(0)
|
||||
, verified(false)
|
||||
, updating(false)
|
||||
, start_sent(false)
|
||||
, complete_sent(false)
|
||||
{}
|
||||
|
||||
std::string url;
|
||||
|
||||
// the time of next tracker announce
|
||||
ptime next_announce;
|
||||
|
||||
boost::uint8_t tier;
|
||||
// the number of times this tracker can fail
|
||||
// in a row before it's removed. 0 means unlimited
|
||||
|
@ -83,12 +102,56 @@ namespace libtorrent
|
|||
// the number of times in a row this tracker has failed
|
||||
boost::uint8_t fails;
|
||||
|
||||
enum tracker_source
|
||||
{
|
||||
source_torrent = 1,
|
||||
source_client = 2,
|
||||
source_magnet_link = 4,
|
||||
source_tex = 8
|
||||
};
|
||||
// where did we get this tracker from
|
||||
boost::uint8_t source;
|
||||
|
||||
// is set to true if we have ever received a response from
|
||||
// this tracker
|
||||
bool verified:1;
|
||||
|
||||
bool can_announce() const
|
||||
{ return fails < fail_limit || fail_limit == 0; }
|
||||
// true if we're currently trying to announce with
|
||||
// this tracker
|
||||
bool updating:1;
|
||||
|
||||
// this is true if event start has been sent to the tracker
|
||||
bool start_sent:1;
|
||||
|
||||
// this is true if event completed has been sent to the tracker
|
||||
bool complete_sent:1;
|
||||
|
||||
void reset()
|
||||
{
|
||||
start_sent = false;
|
||||
next_announce = min_time();
|
||||
}
|
||||
|
||||
void failed()
|
||||
{
|
||||
++fails;
|
||||
int delay = (std::min)(tracker_retry_delay_min + int(fails) * int(fails) * tracker_retry_delay_min
|
||||
, int(tracker_retry_delay_max));
|
||||
next_announce = time_now() + seconds(delay);
|
||||
updating = false;
|
||||
}
|
||||
|
||||
bool can_announce(ptime now) const
|
||||
{
|
||||
return now >= next_announce
|
||||
&& (fails < fail_limit || fail_limit == 0)
|
||||
&& !updating;
|
||||
}
|
||||
|
||||
bool is_working() const
|
||||
{
|
||||
return fails == 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
|
|
|
@ -221,6 +221,7 @@ namespace libtorrent { namespace
|
|||
announce_entry e(added->list_string_value_at(i));
|
||||
if (e.url.empty()) continue;
|
||||
e.fail_limit = 3;
|
||||
e.source = announce_entry::source_tex;
|
||||
m_torrent.add_tracker(e);
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
log_line << e.url << " ";
|
||||
|
|
314
src/torrent.cpp
314
src/torrent.cpp
|
@ -86,16 +86,6 @@ using libtorrent::aux::session_impl;
|
|||
namespace
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
// wait 60 seconds before retrying a failed tracker
|
||||
tracker_retry_delay_min = 60
|
||||
// when tracker_failed_max trackers
|
||||
// has failed, wait 10 minutes instead
|
||||
, tracker_retry_delay_max = 10 * 60
|
||||
, tracker_failed_max = 5
|
||||
};
|
||||
|
||||
struct find_peer_by_ip
|
||||
{
|
||||
find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
|
||||
|
@ -156,7 +146,6 @@ namespace libtorrent
|
|||
, m_last_scrape(min_time())
|
||||
, m_torrent_file(tf)
|
||||
, m_storage(0)
|
||||
, m_next_tracker_announce(time_now())
|
||||
, m_host_resolver(ses.m_io_service)
|
||||
, m_lsd_announce_timer(ses.m_io_service)
|
||||
, m_tracker_timer(ses.m_io_service)
|
||||
|
@ -182,11 +171,8 @@ namespace libtorrent
|
|||
, m_complete(-1)
|
||||
, m_incomplete(-1)
|
||||
, m_deficit_counter(0)
|
||||
, m_duration(1800)
|
||||
, m_sequence_number(seq)
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(-1)
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
|
@ -201,8 +187,6 @@ namespace libtorrent
|
|||
, m_has_incoming(false)
|
||||
, m_files_checked(false)
|
||||
, m_announcing(false)
|
||||
, m_start_sent(false)
|
||||
, m_complete_sent(false)
|
||||
{
|
||||
if (resume_data) m_resume_data.swap(*resume_data);
|
||||
|
||||
|
@ -237,7 +221,6 @@ namespace libtorrent
|
|||
, m_last_scrape(min_time())
|
||||
, m_torrent_file(new torrent_info(info_hash))
|
||||
, m_storage(0)
|
||||
, m_next_tracker_announce(time_now())
|
||||
, m_host_resolver(ses.m_io_service)
|
||||
, m_lsd_announce_timer(ses.m_io_service)
|
||||
, m_tracker_timer(ses.m_io_service)
|
||||
|
@ -262,11 +245,8 @@ namespace libtorrent
|
|||
, m_complete(-1)
|
||||
, m_incomplete(-1)
|
||||
, m_deficit_counter(0)
|
||||
, m_duration(1800)
|
||||
, m_sequence_number(seq)
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(-1)
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
|
@ -281,8 +261,6 @@ namespace libtorrent
|
|||
, m_has_incoming(false)
|
||||
, m_files_checked(false)
|
||||
, m_announcing(false)
|
||||
, m_start_sent(false)
|
||||
, m_complete_sent(false)
|
||||
{
|
||||
if (resume_data) m_resume_data.swap(*resume_data);
|
||||
|
||||
|
@ -304,6 +282,7 @@ namespace libtorrent
|
|||
{
|
||||
m_trackers.push_back(announce_entry(tracker_url));
|
||||
m_trackers.back().fail_limit = 0;
|
||||
m_trackers.back().source = announce_entry::source_magnet_link;
|
||||
m_torrent_file->add_tracker(tracker_url);
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +334,12 @@ namespace libtorrent
|
|||
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
|
||||
if (m_trackers.empty()) return true;
|
||||
|
||||
return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback;
|
||||
int verified_trackers = 0;
|
||||
for (std::vector<announce_entry>::const_iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
if (i->verified) ++verified_trackers;
|
||||
|
||||
return verified_trackers == 0 || !m_settings.use_dht_as_fallback;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -919,16 +903,8 @@ namespace libtorrent
|
|||
|
||||
if (m_trackers.empty()) return;
|
||||
|
||||
restart_tracker_timer(time_now() + seconds(tracker_retry_delay_max));
|
||||
|
||||
if (m_abort) e = tracker_request::stopped;
|
||||
|
||||
if (e == tracker_request::none)
|
||||
{
|
||||
if (!m_start_sent) e = tracker_request::started;
|
||||
if (!m_complete_sent && is_seed()) e = tracker_request::completed;
|
||||
}
|
||||
|
||||
tracker_request req;
|
||||
req.info_hash = m_torrent_file->info_hash();
|
||||
req.pid = m_ses.get_peer_id();
|
||||
|
@ -942,11 +918,6 @@ namespace libtorrent
|
|||
if (ep != tcp::endpoint())
|
||||
req.ipv6 = ep.address().to_string(ec);
|
||||
|
||||
if (m_currently_trying_tracker == -1) m_currently_trying_tracker = 0;
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
req.url = m_trackers[m_currently_trying_tracker].url;
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].can_announce());
|
||||
// if we are aborting. we don't want any new peers
|
||||
req.num_want = (req.event == tracker_request::stopped)
|
||||
?0:m_settings.num_want;
|
||||
|
@ -955,6 +926,28 @@ namespace libtorrent
|
|||
?0:m_ses.m_listen_sockets.front().external_port;
|
||||
req.key = m_ses.m_key;
|
||||
|
||||
ptime now = time_now();
|
||||
|
||||
int tier = INT_MAX;
|
||||
for (int i = 0; i < m_trackers.size(); ++i)
|
||||
{
|
||||
announce_entry& ae = m_trackers[i];
|
||||
if (ae.tier > tier) break;
|
||||
if (ae.is_working()) tier = ae.tier;
|
||||
if (!ae.can_announce(now))
|
||||
{
|
||||
if (ae.is_working() && !m_settings.announce_to_all_trackers) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
req.url = ae.url;
|
||||
req.event = e;
|
||||
if (req.event == tracker_request::none)
|
||||
{
|
||||
if (!ae.start_sent) req.event = tracker_request::started;
|
||||
if (!ae.complete_sent && is_seed()) req.event = tracker_request::completed;
|
||||
}
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (m_abort)
|
||||
{
|
||||
|
@ -967,12 +960,17 @@ namespace libtorrent
|
|||
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
|
||||
, tracker_login(), m_ses.m_listen_interface.address()
|
||||
, m_abort?boost::shared_ptr<torrent>():shared_from_this());
|
||||
ae.updating = true;
|
||||
|
||||
if (m_ses.m_alerts.should_post<tracker_announce_alert>())
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
tracker_announce_alert(get_handle(), req.url, req.event));
|
||||
}
|
||||
|
||||
if (ae.is_working() && !m_settings.announce_to_all_trackers) break;
|
||||
}
|
||||
update_tracker_timer();
|
||||
}
|
||||
|
||||
void torrent::scrape_tracker()
|
||||
|
@ -980,7 +978,6 @@ namespace libtorrent
|
|||
if (m_trackers.empty()) return;
|
||||
|
||||
int i = m_last_working_tracker;
|
||||
if (i == -1) i = m_currently_trying_tracker;
|
||||
if (i == -1) i = 0;
|
||||
|
||||
tracker_request req;
|
||||
|
@ -1037,42 +1034,36 @@ namespace libtorrent
|
|||
if (external_ip != address())
|
||||
m_ses.set_external_address(external_ip);
|
||||
|
||||
if (!m_start_sent && r.event == tracker_request::started)
|
||||
m_start_sent = true;
|
||||
if (!m_complete_sent && r.event == tracker_request::completed)
|
||||
m_complete_sent = true;
|
||||
ptime now = time_now();
|
||||
|
||||
m_failed_trackers = 0;
|
||||
if (interval < m_settings.min_announce_interval)
|
||||
interval = m_settings.min_announce_interval;
|
||||
|
||||
if (interval < m_ses.settings().min_announce_interval)
|
||||
interval = m_ses.settings().min_announce_interval;
|
||||
|
||||
if (m_currently_trying_tracker != -1)
|
||||
announce_entry* ae = find_tracker(r);
|
||||
if (ae)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
m_trackers[m_currently_trying_tracker].verified = true;
|
||||
|
||||
m_last_working_tracker
|
||||
= prioritize_tracker(m_currently_trying_tracker);
|
||||
m_currently_trying_tracker = 0;
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
if (!ae->start_sent && r.event == tracker_request::started)
|
||||
ae->start_sent = true;
|
||||
if (!ae->complete_sent && r.event == tracker_request::completed)
|
||||
ae->complete_sent = true;
|
||||
ae->verified = true;
|
||||
ae->updating = false;
|
||||
ae->fails = 0;
|
||||
ae->next_announce = now + seconds(interval);
|
||||
int tracker_index = ae - &m_trackers[0];
|
||||
m_last_working_tracker = prioritize_tracker(tracker_index);
|
||||
}
|
||||
|
||||
m_duration = interval;
|
||||
restart_tracker_timer(time_now() + seconds(m_duration));
|
||||
update_tracker_timer();
|
||||
|
||||
if (complete >= 0) m_complete = complete;
|
||||
if (incomplete >= 0) m_incomplete = incomplete;
|
||||
if (complete >= 0 && incomplete >= 0)
|
||||
m_last_scrape = time_now();
|
||||
m_last_scrape = now;
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||
std::stringstream s;
|
||||
s << "TRACKER RESPONSE:\n"
|
||||
"interval: " << m_duration << "\n"
|
||||
"interval: " << interval << "\n"
|
||||
"peers:\n";
|
||||
for (std::vector<peer_entry>::const_iterator i = peer_list.begin();
|
||||
i != peer_list.end(); ++i)
|
||||
|
@ -1117,16 +1108,6 @@ namespace libtorrent
|
|||
get_handle(), peer_list.size(), r.url));
|
||||
}
|
||||
m_got_tracker_response = true;
|
||||
|
||||
// when the tracker succeeds, reset the fails-in-a-row counter
|
||||
if (m_currently_trying_tracker != -1)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
m_trackers[m_currently_trying_tracker].fails = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
|
||||
|
@ -2083,7 +2064,10 @@ namespace libtorrent
|
|||
{
|
||||
m_trackers = urls;
|
||||
m_last_working_tracker = -1;
|
||||
m_currently_trying_tracker = -1;
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
if (i->source == 0) i->source = announce_entry::source_client;
|
||||
|
||||
if (!m_trackers.empty()) start_announcing();
|
||||
else stop_announcing();
|
||||
}
|
||||
|
@ -2092,12 +2076,16 @@ namespace libtorrent
|
|||
{
|
||||
std::vector<announce_entry>::iterator k = std::find_if(m_trackers.begin()
|
||||
, m_trackers.end(), boost::bind(&announce_entry::url, _1) == url.url);
|
||||
if (k != m_trackers.end()) return;
|
||||
if (k != m_trackers.end())
|
||||
{
|
||||
k->source |= url.source;
|
||||
return;
|
||||
}
|
||||
k = std::upper_bound(m_trackers.begin(), m_trackers.end(), url
|
||||
, boost::bind(&announce_entry::tier, _1) < boost::bind(&announce_entry::tier, _2));
|
||||
if (k - m_trackers.begin() < m_currently_trying_tracker) ++m_currently_trying_tracker;
|
||||
if (k - m_trackers.begin() < m_last_working_tracker) ++m_last_working_tracker;
|
||||
m_trackers.insert(k, url);
|
||||
k = m_trackers.insert(k, url);
|
||||
if (k->source == 0) k->source = announce_entry::source_client;
|
||||
if (!m_trackers.empty()) start_announcing();
|
||||
}
|
||||
|
||||
|
@ -3454,7 +3442,16 @@ namespace libtorrent
|
|||
m_picker.reset();
|
||||
|
||||
set_state(torrent_status::seeding);
|
||||
if (!m_complete_sent && m_announcing) announce_with_tracker();
|
||||
if (!m_announcing) return;
|
||||
|
||||
ptime now = time_now();
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
{
|
||||
if (i->complete_sent) continue;
|
||||
i->next_announce = now;
|
||||
}
|
||||
announce_with_tracker();
|
||||
}
|
||||
|
||||
// this will move the tracker with the given index
|
||||
|
@ -3470,67 +3467,30 @@ namespace libtorrent
|
|||
|
||||
while (index > 0 && m_trackers[index].tier == m_trackers[index-1].tier)
|
||||
{
|
||||
std::swap(m_trackers[index].url, m_trackers[index-1].url);
|
||||
using std::swap;
|
||||
swap(m_trackers[index], m_trackers[index-1]);
|
||||
if (m_last_working_tracker == index) ++m_last_working_tracker;
|
||||
--index;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void torrent::try_next_tracker(tracker_request const& req)
|
||||
int torrent::deprioritize_tracker(int index)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_trackers.empty())
|
||||
TORRENT_ASSERT(index >= 0);
|
||||
TORRENT_ASSERT(index < m_trackers.size());
|
||||
if (index >= (int)m_trackers.size()) return -1;
|
||||
|
||||
while (index < m_trackers.size() - 1 && m_trackers[index].tier == m_trackers[index + 1].tier)
|
||||
{
|
||||
m_currently_trying_tracker = -1;
|
||||
return;
|
||||
using std::swap;
|
||||
swap(m_trackers[index], m_trackers[index + 1]);
|
||||
if (m_last_working_tracker == index) --m_last_working_tracker;
|
||||
++index;
|
||||
}
|
||||
|
||||
// increase tracker index until we find a tracker we can use
|
||||
// or until we reach the end of the tracker list
|
||||
do
|
||||
{
|
||||
++m_currently_trying_tracker;
|
||||
} while (m_currently_trying_tracker < m_trackers.size()
|
||||
&& !m_trackers[m_currently_trying_tracker].can_announce());
|
||||
|
||||
if (m_currently_trying_tracker < int(m_trackers.size()))
|
||||
{
|
||||
announce_with_tracker(req.event);
|
||||
return;
|
||||
}
|
||||
|
||||
int delay = tracker_retry_delay_min
|
||||
+ (std::min)(int(m_failed_trackers), int(tracker_failed_max))
|
||||
* (tracker_retry_delay_max - tracker_retry_delay_min)
|
||||
/ tracker_failed_max;
|
||||
|
||||
++m_failed_trackers;
|
||||
// if we've looped the tracker list, wait a bit before retrying
|
||||
m_currently_trying_tracker = -1;
|
||||
|
||||
// if we're stopping, just give up. Don't bother retrying
|
||||
if (req.event == tracker_request::stopped)
|
||||
return;
|
||||
|
||||
restart_tracker_timer(time_now() + seconds(delay));
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (m_abort) return;
|
||||
|
||||
// only start the announce if we want to announce with the dht
|
||||
ptime now = time_now();
|
||||
if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
|
||||
{
|
||||
// force the DHT to reannounce
|
||||
m_last_dht_announce = now;
|
||||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
m_ses.m_dht->announce(m_torrent_file->info_hash()
|
||||
, m_ses.m_listen_sockets.front().external_port
|
||||
, bind(&torrent::on_dht_announce_response_disp, self, _1));
|
||||
}
|
||||
#endif
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void torrent::files_checked()
|
||||
|
@ -3562,7 +3522,9 @@ namespace libtorrent
|
|||
}
|
||||
else
|
||||
{
|
||||
m_complete_sent = true;
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
i->complete_sent = true;
|
||||
if (m_state != torrent_status::finished) finished();
|
||||
}
|
||||
|
||||
|
@ -4206,14 +4168,31 @@ namespace libtorrent
|
|||
start_announcing();
|
||||
}
|
||||
|
||||
void torrent::restart_tracker_timer(ptime announce_at)
|
||||
void torrent::update_tracker_timer()
|
||||
{
|
||||
if (!m_announcing) return;
|
||||
|
||||
m_next_tracker_announce = announce_at;
|
||||
ptime next_announce = max_time();
|
||||
int tier = INT_MAX;
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
{
|
||||
if (i->tier > tier) break;
|
||||
if (i->is_working()) tier = i->tier;
|
||||
if (i->fails >= i->fail_limit && i->fail_limit != 0) continue;
|
||||
if (i->updating) continue;
|
||||
if (i->next_announce < next_announce) next_announce = i->next_announce;
|
||||
if (i->is_working() && !m_settings.announce_to_all_trackers) break;
|
||||
}
|
||||
if (next_announce == max_time()) return;
|
||||
|
||||
// since we don't know if we have to re-issue the async_wait or not
|
||||
// always do it
|
||||
// if (m_tracker_timer.expires_at() <= next_announce) return;
|
||||
|
||||
error_code ec;
|
||||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
m_tracker_timer.expires_at(m_next_tracker_announce, ec);
|
||||
m_tracker_timer.expires_at(next_announce, ec);
|
||||
m_tracker_timer.async_wait(bind(&torrent::on_tracker_announce_disp, self, _1));
|
||||
}
|
||||
|
||||
|
@ -4231,7 +4210,8 @@ namespace libtorrent
|
|||
if (!m_trackers.empty())
|
||||
{
|
||||
// tell the tracker that we're back
|
||||
m_start_sent = false;
|
||||
std::for_each(m_trackers.begin(), m_trackers.end()
|
||||
, bind(&announce_entry::reset, _1));
|
||||
m_stat.clear();
|
||||
announce_with_tracker();
|
||||
}
|
||||
|
@ -4258,7 +4238,10 @@ namespace libtorrent
|
|||
|
||||
m_announcing = false;
|
||||
|
||||
if (!m_trackers.empty())
|
||||
ptime now = time_now();
|
||||
for (std::vector<announce_entry>::iterator i = m_trackers.begin()
|
||||
, end(m_trackers.end()); i != end; ++i)
|
||||
i->next_announce = now;
|
||||
announce_with_tracker(tracker_request::stopped);
|
||||
}
|
||||
|
||||
|
@ -4447,6 +4430,15 @@ namespace libtorrent
|
|||
return m_tracker_address;
|
||||
}
|
||||
|
||||
announce_entry* torrent::find_tracker(tracker_request const& r)
|
||||
{
|
||||
std::vector<announce_entry>::iterator i = std::find_if(
|
||||
m_trackers.begin(), m_trackers.end()
|
||||
, bind(&announce_entry::url, _1) == r.url);
|
||||
if (i == m_trackers.end()) return 0;
|
||||
return &*i;
|
||||
}
|
||||
|
||||
void torrent::file_progress(std::vector<float>& fp) const
|
||||
{
|
||||
fp.clear();
|
||||
|
@ -4683,19 +4675,19 @@ namespace libtorrent
|
|||
if (st.next_announce.is_negative() || is_paused())
|
||||
st.next_announce = boost::posix_time::seconds(0);
|
||||
|
||||
st.announce_interval = boost::posix_time::seconds(m_duration);
|
||||
st.announce_interval = boost::posix_time::seconds(0);
|
||||
|
||||
if (m_last_working_tracker >= 0)
|
||||
{
|
||||
TORRENT_ASSERT(m_last_working_tracker < m_trackers.size());
|
||||
st.current_tracker
|
||||
= m_trackers[m_last_working_tracker].url;
|
||||
st.current_tracker = m_trackers[m_last_working_tracker].url;
|
||||
}
|
||||
else if (m_currently_trying_tracker >= 0)
|
||||
else
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < m_trackers.size());
|
||||
st.current_tracker
|
||||
= m_trackers[m_currently_trying_tracker].url;
|
||||
std::vector<announce_entry>::const_iterator i;
|
||||
for (i = m_trackers.begin(); i != m_trackers.end(); ++i)
|
||||
if (i->updating) break;
|
||||
if (i != m_trackers.end()) st.current_tracker = i->url;
|
||||
}
|
||||
|
||||
st.num_uploads = m_num_uploads;
|
||||
|
@ -4797,18 +4789,17 @@ namespace libtorrent
|
|||
|
||||
if (r.kind == tracker_request::announce_request)
|
||||
{
|
||||
announce_entry* ae = find_tracker(r);
|
||||
if (ae)
|
||||
{
|
||||
ae->failed();
|
||||
int tracker_index = ae - &m_trackers[0];
|
||||
deprioritize_tracker(tracker_index);
|
||||
}
|
||||
if (m_ses.m_alerts.should_post<tracker_error_alert>())
|
||||
{
|
||||
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
|
||||
, m_failed_trackers + 1, 0, r.url, "tracker timed out"));
|
||||
}
|
||||
if (m_currently_trying_tracker != -1)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
++m_trackers[m_currently_trying_tracker].fails;
|
||||
, ae?ae->fails:0, 0, r.url, "tracker timed out"));
|
||||
}
|
||||
}
|
||||
else if (r.kind == tracker_request::scrape_request)
|
||||
|
@ -4819,9 +4810,7 @@ namespace libtorrent
|
|||
, r.url, "tracker timed out"));
|
||||
}
|
||||
}
|
||||
|
||||
if (r.kind == tracker_request::announce_request)
|
||||
try_next_tracker(r);
|
||||
update_tracker_timer();
|
||||
}
|
||||
|
||||
// TODO: with some response codes, we should just consider
|
||||
|
@ -4839,18 +4828,17 @@ namespace libtorrent
|
|||
#endif
|
||||
if (r.kind == tracker_request::announce_request)
|
||||
{
|
||||
announce_entry* ae = find_tracker(r);
|
||||
if (ae)
|
||||
{
|
||||
ae->failed();
|
||||
int tracker_index = ae - &m_trackers[0];
|
||||
deprioritize_tracker(tracker_index);
|
||||
}
|
||||
if (m_ses.m_alerts.should_post<tracker_error_alert>())
|
||||
{
|
||||
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
|
||||
, m_failed_trackers + 1, response_code, r.url, str));
|
||||
}
|
||||
if (m_currently_trying_tracker != -1)
|
||||
{
|
||||
TORRENT_ASSERT(m_currently_trying_tracker >= 0);
|
||||
TORRENT_ASSERT(m_currently_trying_tracker < int(m_trackers.size()));
|
||||
TORRENT_ASSERT(m_trackers[m_currently_trying_tracker].url == r.url);
|
||||
|
||||
++m_trackers[m_currently_trying_tracker].fails;
|
||||
, ae?ae->fails:0, response_code, r.url, str));
|
||||
}
|
||||
}
|
||||
else if (r.kind == tracker_request::scrape_request)
|
||||
|
@ -4860,9 +4848,7 @@ namespace libtorrent
|
|||
m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, str));
|
||||
}
|
||||
}
|
||||
|
||||
if (r.kind == tracker_request::announce_request)
|
||||
try_next_tracker(r);
|
||||
update_tracker_timer();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@ namespace libtorrent
|
|||
// ============ end deprecation ===============
|
||||
#endif
|
||||
|
||||
std::vector<announce_entry> const& torrent_handle::trackers() const
|
||||
std::vector<announce_entry> torrent_handle::trackers() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
const static std::vector<announce_entry> empty;
|
||||
|
|
|
@ -540,6 +540,7 @@ namespace libtorrent
|
|||
if (e.url.empty()) continue;
|
||||
e.tier = j;
|
||||
e.fail_limit = 0;
|
||||
e.source = announce_entry::source_torrent;
|
||||
m_urls.push_back(e);
|
||||
}
|
||||
}
|
||||
|
@ -565,6 +566,7 @@ namespace libtorrent
|
|||
{
|
||||
announce_entry e(torrent_file.dict_find_string_value("announce"));
|
||||
e.fail_limit = 0;
|
||||
e.source = announce_entry::source_torrent;
|
||||
if (!e.url.empty()) m_urls.push_back(e);
|
||||
}
|
||||
|
||||
|
@ -638,11 +640,12 @@ namespace libtorrent
|
|||
{
|
||||
announce_entry e(url);
|
||||
e.tier = tier;
|
||||
e.source = announce_entry::source_client;
|
||||
m_urls.push_back(e);
|
||||
|
||||
using boost::bind;
|
||||
std::sort(m_urls.begin(), m_urls.end(), boost::bind<bool>(std::less<int>()
|
||||
, bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2)));
|
||||
std::sort(m_urls.begin(), m_urls.end(), bind(&announce_entry::tier, _1)
|
||||
< bind(&announce_entry::tier, _2));
|
||||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
|
|
Loading…
Reference in New Issue