From 8ee50045caf73554a7cd72d063e5cf63dc5b0ace Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 28 Jun 2009 20:21:55 +0000 Subject: [PATCH] added support for uTorrent interpretation of multi-tracker torrents (off by default) --- ChangeLog | 1 + bindings/python/src/session_settings.cpp | 2 + docs/manual.rst | 14 ++++-- examples/client_test.cpp | 3 +- include/libtorrent/session_settings.hpp | 11 ++++- src/torrent.cpp | 54 ++++++++++++++++++++---- 6 files changed, 71 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 384a645a2..023c878be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * added support for uTorrent interpretation of multi-tracker torrents * handle torrents with duplicate filenames * piece timeouts are adjusted to download rate limits * encodes urls in torrent files that needs to be encoded diff --git a/bindings/python/src/session_settings.cpp b/bindings/python/src/session_settings.cpp index 6372773ef..7b857723c 100644 --- a/bindings/python/src/session_settings.cpp +++ b/bindings/python/src/session_settings.cpp @@ -41,6 +41,7 @@ void bind_session_settings() .def_readwrite("num_want", &session_settings::num_want) .def_readwrite("initial_picker_threshold", &session_settings::initial_picker_threshold) .def_readwrite("allowed_fast_set_size", &session_settings::allowed_fast_set_size) + .def_readwrite("max_queued_disk_bytes", &session_settings::max_queued_disk_bytes) .def_readwrite("handshake_timeout", &session_settings::handshake_timeout) #ifndef TORRENT_DISABLE_DHT .def_readwrite("use_dht_as_fallback", &session_settings::use_dht_as_fallback) @@ -82,6 +83,7 @@ void bind_session_settings() .def_readwrite("auto_manage_startup", &session_settings::auto_manage_startup) .def_readwrite("rate_limit_ip_overhead", &session_settings::rate_limit_ip_overhead) .def_readwrite("announce_to_all_trackers", &session_settings::announce_to_all_trackers) + .def_readwrite("announce_to_all_tiers", &session_settings::announce_to_all_tiers) .def_readwrite("prefer_udp_trackers", &session_settings::prefer_udp_trackers) .def_readwrite("strict_super_seeding", &session_settings::strict_super_seeding) .def_readwrite("seeding_piece_quota", &session_settings::seeding_piece_quota) diff --git a/docs/manual.rst b/docs/manual.rst index d148162ae..d49040ea0 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3486,6 +3486,8 @@ session_settings bool rate_limit_ip_overhead; bool announce_to_all_trackers; + bool announce_to_all_tiers; + bool prefer_udp_trackers; bool strict_super_seeding; @@ -3837,10 +3839,14 @@ drained from the rate limiters, to avoid exceeding the limits with the total tra ``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. +in tier 1 are announced as well. 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. + +``announce_to_all_tiers`` also controls how multi tracker torrents are +treated. When this is set to true, one tracker from each tier is announced +to. This is the uTorrent behavior. This is false by default in order +to comply with the multi-tracker specification. ``prefer_udp_trackers`` is true by default. It means that trackers may be rearranged in a way that udp trackers are always tried before http diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 40a024067..25cc7e9a2 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -763,7 +763,8 @@ int main(int argc, char* argv[]) settings.user_agent = "client_test/" LIBTORRENT_VERSION; settings.auto_upload_slots_rate_based = true; - settings.announce_to_all_trackers = true; + //settings.announce_to_all_tiers = true; + //settings.announce_to_all_trackers = true; settings.optimize_hashing_for_speed = false; settings.disk_cache_algorithm = session_settings::largest_contiguous; diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 61daba2e8..0f32dcb0d 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -154,6 +154,7 @@ namespace libtorrent , auto_manage_startup(120) , rate_limit_ip_overhead(true) , announce_to_all_trackers(false) + , announce_to_all_tiers(false) , prefer_udp_trackers(true) , strict_super_seeding(false) , seeding_piece_quota(3) @@ -526,10 +527,18 @@ namespace libtorrent // the limits with the total traffic bool rate_limit_ip_overhead; + // this announces to all trackers within the current + // tier. Trackers within a tier are supposed to share + // peers, this could be used for trackers that don't, + // and require the clients to announce to all of them. + bool announce_to_all_trackers; + // 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; + // When this is enabled, one tracker from each tier is + // announced + bool announce_to_all_tiers; // when this is set to true, if there is a tracker entry // with udp:// protocol, it is preferred over the same diff --git a/src/torrent.cpp b/src/torrent.cpp index 97a20b56d..9a80a9336 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1157,15 +1157,35 @@ namespace libtorrent ptime now = time_now(); + // the tier is kept as INT_MAX until we find the first + // tracker that works, then it's set to that tracker's + // tier. int tier = INT_MAX; + + // have we sent an announce in this tier yet? + bool sent_announce = false; + for (int i = 0; i < int(m_trackers.size()); ++i) { announce_entry& ae = m_trackers[i]; - if (ae.tier > tier) break; - if (ae.is_working()) tier = ae.tier; + if (m_settings.announce_to_all_tiers + && sent_announce + && ae.tier <= tier + && tier != INT_MAX) + continue; + + if (ae.tier > tier && !m_settings.announce_to_all_tiers) break; + if (ae.is_working()) { tier = ae.tier; sent_announce = false; } if (!ae.can_announce(now)) { - if (ae.is_working() && !m_settings.announce_to_all_trackers) break; + if (ae.is_working()) + { + sent_announce = true; // this counts + + if (!m_settings.announce_to_all_trackers + && !m_settings.announce_to_all_tiers) + break; + } continue; } @@ -1203,7 +1223,11 @@ namespace libtorrent tracker_announce_alert(get_handle(), req.url, req.event)); } - if (ae.is_working() && !m_settings.announce_to_all_trackers) break; + sent_announce = true; + if (ae.is_working() + && !m_settings.announce_to_all_trackers + && !m_settings.announce_to_all_tiers) + break; } update_tracker_timer(); } @@ -4854,15 +4878,29 @@ namespace libtorrent ptime next_announce = max_time(); int tier = INT_MAX; + + bool found_working = false; + for (std::vector::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 (m_settings.announce_to_all_tiers + && found_working + && i->tier <= tier + && tier != INT_MAX) + continue; + + if (i->tier > tier && !m_settings.announce_to_all_tiers) break; + if (i->is_working()) { tier = i->tier; found_working = false; } if (i->fails >= i->fail_limit && i->fail_limit != 0) continue; - if (i->updating) continue; + if (i->updating) { found_working = true; continue; } if (i->next_announce < next_announce) next_announce = i->next_announce; - if (i->is_working() && !m_settings.announce_to_all_trackers) break; + if (i->is_working()) + { + found_working = true; + if (!m_settings.announce_to_all_trackers + && !m_settings.announce_to_all_tiers) break; + } } if (next_announce == max_time()) return;