diff --git a/include/libtorrent/announce_entry.hpp b/include/libtorrent/announce_entry.hpp index a8b80d752..ed8210f1f 100644 --- a/include/libtorrent/announce_entry.hpp +++ b/include/libtorrent/announce_entry.hpp @@ -127,7 +127,7 @@ namespace libtorrent { { // the tracker was part of the .torrent file source_torrent = 1, - // the tracker was added programatically via the add_troacker()_ function + // the tracker was added programatically via the add_tracker() function source_client = 2, // the tracker was part of a magnet link source_magnet_link = 4, diff --git a/include/libtorrent/session_handle.hpp b/include/libtorrent/session_handle.hpp index 352fddaac..f61386ab9 100644 --- a/include/libtorrent/session_handle.hpp +++ b/include/libtorrent/session_handle.hpp @@ -776,7 +776,7 @@ namespace libtorrent { // in the download queue is vacated and avery subsequent torrent in the // queue has their queue positions updated. This can potentially cause a // large state_update to be posted. When removing all torrents, it is - // adviced to remove them from the back of the queue, to minimize the + // advised to remove them from the back of the queue, to minimize the // shifting. void remove_torrent(const torrent_handle& h, int options = 0); diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index dca60de7c..f47cc8c90 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -729,6 +729,8 @@ namespace libtorrent { // ``stop_tracker_timeout`` is the number of seconds to wait when // sending a stopped message before considering a tracker to have // timed out. This is usually shorter, to make the client quit faster. + // If the value is set to 0, the connections to trackers with the + // stopped event are suppressed. stop_tracker_timeout, // this is the maximum number of bytes in a tracker response. If a diff --git a/src/torrent.cpp b/src/torrent.cpp index 538af3c81..c966ed9e8 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2584,6 +2584,18 @@ namespace libtorrent { if (m_abort) e = tracker_request::stopped; + // having stop_tracker_timeout <= 0 means that there is + // no need to send any request to trackers or trigger any + // related logic when the event is stopped + if (e == tracker_request::stopped + && settings().get_int(settings_pack::stop_tracker_timeout) <= 0) + { +#ifndef TORRENT_DISABLE_LOGGING + debug_log("*** announce: event == stopped && stop_tracker_timeout <= 0"); +#endif + return; + } + // if we're not announcing to trackers, only allow // stopping if (e != tracker_request::stopped && !m_announce_to_trackers) diff --git a/test/test_settings_pack.cpp b/test/test_settings_pack.cpp index e5939072f..61c6ba7b0 100644 --- a/test/test_settings_pack.cpp +++ b/test/test_settings_pack.cpp @@ -248,6 +248,9 @@ TORRENT_TEST(settings_pack_abi) TEST_EQUAL(settings_pack::proxy_tracker_connections, settings_pack::bool_type_base + 67); // ints + TEST_EQUAL(settings_pack::tracker_completion_timeout, settings_pack::int_type_base + 0); + TEST_EQUAL(settings_pack::tracker_receive_timeout, settings_pack::int_type_base + 1); + TEST_EQUAL(settings_pack::stop_tracker_timeout, settings_pack::int_type_base + 2); TEST_EQUAL(settings_pack::max_suggest_pieces, settings_pack::int_type_base + 66); TEST_EQUAL(settings_pack::connections_slack, settings_pack::int_type_base + 86); TEST_EQUAL(settings_pack::aio_threads, settings_pack::int_type_base + 104); diff --git a/test/test_tracker.cpp b/test/test_tracker.cpp index c7ad57b85..8e9ed21e3 100644 --- a/test/test_tracker.cpp +++ b/test/test_tracker.cpp @@ -619,3 +619,82 @@ TORRENT_TEST(tracker_proxy) test_proxy(true); } +void test_stop_tracker_timeout(bool nostop) +{ + int port = start_web_server(); + + auto count_stopped_events = [](session& ses) + { + int count = 0; + int num = 70; // this number is adjusted per version, an estimate + time_point const end_time = clock_type::now() + seconds(15); + while (true) + { + time_point const now = clock_type::now(); + if (now > end_time) return count; + + ses.wait_for_alert(end_time - now); + std::vector alerts; + ses.pop_alerts(&alerts); + for (auto a : alerts) + { + std::printf("%d: [%s] %s\n", num, a->what(), a->message().c_str()); + if (a->type() == log_alert::alert_type) + { + std::string const msg = a->message(); + if (msg.find("&event=stopped") != std::string::npos) + count++; + } + num--; + } + if (num <= 0) return count; + } + return count; + }; + + settings_pack p = settings(); + p.set_bool(settings_pack::announce_to_all_trackers, true); + p.set_bool(settings_pack::announce_to_all_tiers, true); + p.set_int(settings_pack::alert_mask, alert::all_categories); + if (nostop) + p.set_int(settings_pack::stop_tracker_timeout, 0); + + lt::session s(p); + + error_code ec; + remove_all("tmp4_tracker", ec); + create_directory("tmp4_tracker", ec); + std::ofstream file(combine_path("tmp4_tracker", "temporary").c_str()); + std::shared_ptr t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false); + file.close(); + + add_torrent_params tp; + tp.flags &= ~add_torrent_params::flag_paused; + tp.flags &= ~add_torrent_params::flag_auto_managed; + tp.flags |= add_torrent_params::flag_seed_mode; + tp.ti = t; + tp.save_path = "tmp4_tracker"; + torrent_handle h = s.add_torrent(tp); + + char tracker_url[200]; + std::snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", port); + announce_entry ae{tracker_url}; + // trick to avoid use of tracker immediately + ae.next_announce = aux::time_now32() + seconds32(1); + ae.min_announce = aux::time_now32() + seconds32(1); + h.add_tracker(ae); + + s.remove_torrent(h); + + int const count = count_stopped_events(s); + TEST_EQUAL(count, nostop ? 0 : 1); +} + +TORRENT_TEST(stop_tracker_timeout) +{ + std::printf("\n\nexpect to get ONE request with &event=stopped\n\n"); + test_stop_tracker_timeout(false); + + std::printf("\n\nexpect to NOT get a request with &event=stopped\n\n"); + test_stop_tracker_timeout(true); +}