diff --git a/ChangeLog b/ChangeLog index 6fcd57f6a..252840655 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 1.1.0 release + * allow specifying which tracker to scrape in scrape_tracker * tracker response alerts from user initiated announces/scrapes are now posted regardless of alert mask * improve DHT performance when changing external IP (primarily affects diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index ed766e86c..2c9639363 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -722,7 +722,7 @@ namespace libtorrent // forcefully sets next_announce to the current time void force_tracker_request(time_point, int tracker_idx); - void scrape_tracker(bool user_triggered); + void scrape_tracker(int idx, bool user_triggered); void announce_with_tracker(boost::uint8_t e = tracker_request::none , address const& bind_interface = address_v4::any()); diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 36a9d3f63..5a1c6cd37 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -1085,15 +1085,18 @@ namespace libtorrent void force_reannounce(boost::posix_time::time_duration) const; #endif - // ``scrape_tracker()`` will send a scrape request to the tracker. A - // scrape request queries the tracker for statistics such as total number - // of incomplete peers, complete peers, number of downloads etc. + // ``scrape_tracker()`` will send a scrape request to a tracker. By + // default (``idx`` = -1) it will scrape the last working tracker. If + // ``idx`` is >= 0, the tracker with the specified index will scraped. + // + // A scrape request queries the tracker for statistics such as total + // number of incomplete peers, complete peers, number of downloads etc. // // This request will specifically update the ``num_complete`` and // ``num_incomplete`` fields in the torrent_status struct once it // completes. When it completes, it will generate a scrape_reply_alert. // If it fails, it will generate a scrape_failed_alert. - void scrape_tracker() const; + void scrape_tracker(int idx = -1) const; // ``set_upload_limit`` will limit the upload bandwidth used by this // particular torrent to the limit you set. It is given as the number of diff --git a/simulation/test_tracker.cpp b/simulation/test_tracker.cpp index 72fa2479d..e33659c45 100644 --- a/simulation/test_tracker.cpp +++ b/simulation/test_tracker.cpp @@ -363,8 +363,8 @@ TORRENT_TEST(ipv6_support) TEST_EQUAL(v6_announces, 2); } -template -void announce_entry_test(Announce a, Test t) +template +void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = "/announce") { using sim::asio::ip::address_v4; sim_config network_cfg; @@ -375,7 +375,7 @@ void announce_entry_test(Announce a, Test t) // listen on port 8080 sim::http_server http(tracker_ios, 8080); - http.register_handler("/announce", a); + http.register_handler(url_path, a); lt::session_proxy zombie; @@ -393,26 +393,31 @@ void announce_entry_test(Announce a, Test t) p.trackers.push_back("http://tracker.com:8080/announce"); ses->async_add_torrent(p); - // stop the torrent 5 seconds in + // run the test 5 seconds in asio::high_resolution_timer t1(ios); t1.expires_from_now(chrono::seconds(5)); - t1.async_wait([&ses,&t](boost::system::error_code const& ec) + t1.async_wait([&ses,&test1](boost::system::error_code const& ec) { std::vector torrents = ses->get_torrents(); TEST_EQUAL(torrents.size(), 1); torrent_handle h = torrents.front(); + test1(h); + }); - std::vector tr = h.trackers(); - - TEST_EQUAL(tr.size(), 1); - announce_entry const& ae = tr[0]; - t(ae); + asio::high_resolution_timer t2(ios); + t2.expires_from_now(chrono::seconds(9)); + t2.async_wait([&ses,&test2](boost::system::error_code const& ec) + { + std::vector torrents = ses->get_torrents(); + TEST_EQUAL(torrents.size(), 1); + torrent_handle h = torrents.front(); + test2(h); }); // then shut down 10 seconds in - asio::high_resolution_timer t2(ios); - t2.expires_from_now(chrono::seconds(10)); - t2.async_wait([&ses,&zombie](boost::system::error_code const& ec) + asio::high_resolution_timer t3(ios); + t3.expires_from_now(chrono::seconds(10)); + t3.async_wait([&ses,&zombie](boost::system::error_code const& ec) { zombie = ses->abort(); ses->set_alert_notify([]{}); @@ -422,6 +427,21 @@ void announce_entry_test(Announce a, Test t) sim.run(); } +template +void announce_entry_test(Announce a, Test t, char const* url_path = "/announce") +{ + tracker_test(a + , [&t] (torrent_handle h) { + std::vector tr = h.trackers(); + + TEST_EQUAL(tr.size(), 1); + announce_entry const& ae = tr[0]; + t(ae); + } + , [](torrent_handle){} + , url_path); +} + TORRENT_TEST(test_error) { announce_entry_test( @@ -467,7 +487,7 @@ TORRENT_TEST(test_warning) }); } -TORRENT_TEST(test_scrape) +TORRENT_TEST(test_scrape_data_in_announce) { announce_entry_test( [](std::string method, std::string req @@ -493,6 +513,36 @@ TORRENT_TEST(test_scrape) }); } +TORRENT_TEST(test_scrape) +{ + tracker_test( + [](std::string method, std::string req + , std::map& headers) + { + TEST_EQUAL(method, "GET"); + + char response[500]; + int size = snprintf(response, sizeof(response), + "d5:filesd20:ababababababababababd8:completei1e10:downloadedi3e10:incompletei2eeee"); + return sim::send_response(200, "OK", size) + response; + } + , [](torrent_handle h) + { + h.scrape_tracker(); + } + , [](torrent_handle h) + { + std::vector tr = h.trackers(); + + TEST_EQUAL(tr.size(), 1); + announce_entry const& ae = tr[0]; + TEST_EQUAL(ae.scrape_incomplete, 2); + TEST_EQUAL(ae.scrape_complete, 1); + TEST_EQUAL(ae.scrape_downloaded, 3); + } + , "/scrape"); +} + TORRENT_TEST(test_http_status) { announce_entry_test( diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 6f617b86a..47da87682 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -3220,7 +3220,7 @@ retry: // false means it's not triggered by the user, but automatically // by libtorrent - t.scrape_tracker(false); + t.scrape_tracker(-1, false); ++m_next_scrape_torrent; if (m_next_scrape_torrent >= int(want_scrape.size())) diff --git a/src/torrent.cpp b/src/torrent.cpp index 5239b841b..17c3c5fdd 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3279,15 +3279,15 @@ namespace libtorrent update_tracker_timer(now); } - void torrent::scrape_tracker(bool user_triggered) + void torrent::scrape_tracker(int idx, bool user_triggered) { TORRENT_ASSERT(is_single_thread()); m_last_scrape = m_ses.session_time(); if (m_trackers.empty()) return; - int i = m_last_working_tracker; - if (i == -1) i = 0; + if (idx < 0 || idx >= int(m_trackers.size())) idx = m_last_working_tracker; + if (idx < 0) idx = 0; tracker_request req; if (settings().get_bool(settings_pack::apply_ip_filter_to_trackers) @@ -3296,7 +3296,7 @@ namespace libtorrent req.info_hash = m_torrent_file->info_hash(); req.kind |= tracker_request::scrape_request; - req.url = m_trackers[i].url; + req.url = m_trackers[idx].url; #ifndef TORRENT_NO_DEPRECATE req.auth = tracker_login(); #endif diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 623e1792d..33feaa2e5 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -800,9 +800,9 @@ namespace libtorrent ses.disk_thread().files().get_status(&status, &t->storage()); } - void torrent_handle::scrape_tracker() const + void torrent_handle::scrape_tracker(int idx) const { - TORRENT_ASYNC_CALL1(scrape_tracker, true); + TORRENT_ASYNC_CALL2(scrape_tracker, idx, true); } void torrent_handle::super_seeding(bool on) const