From 5cb12318c516ba07eddd38659863d3f0c27479cb Mon Sep 17 00:00:00 2001 From: arvidn Date: Tue, 7 Mar 2017 20:17:35 -0500 Subject: [PATCH 1/8] fix bug where settings_pack::file_pool_size setting was not being honored --- ChangeLog | 1 + include/libtorrent/settings_pack.hpp | 4 +-- simulation/test_file_pool.cpp | 53 ++++++++++++++++++++++++++++ src/disk_io_thread.cpp | 7 ++-- src/session_impl.cpp | 18 ---------- 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f9a48279..45552b0d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * fix bug where settings_pack::file_pool_size setting was not being honored * add feature to periodically close files (to make windows clear disk cache) * fix bug in torrent_handle::file_status * fix issue with peers not updated on metadata from magnet links diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 6938a200d..76b4baae0 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -786,9 +786,7 @@ namespace libtorrent // for viruses. deferring the closing of the files will be the // difference between a usable system and a completely hogged down // system. Most operating systems also has a limit on the total number - // of file descriptors a process may have open. It is usually a good - // idea to find this limit and set the number of connections and the - // number of files limits so their sum is slightly below it. + // of file descriptors a process may have open. file_pool_size, // ``max_failcount`` is the maximum times we try to connect to a peer diff --git a/simulation/test_file_pool.cpp b/simulation/test_file_pool.cpp index 16d8eb051..8dff42d59 100644 --- a/simulation/test_file_pool.cpp +++ b/simulation/test_file_pool.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session.hpp" #include "libtorrent/session_stats.hpp" #include "libtorrent/file.hpp" +#include "libtorrent/torrent_info.hpp" using namespace libtorrent; @@ -84,3 +85,55 @@ TORRENT_TEST(close_file_interval) TEST_CHECK(ran_to_completion); } +TORRENT_TEST(file_pool_size) +{ + bool ran_to_completion = false; + int max_files = 0; + + setup_swarm(2, swarm_test::download + // add session + , [](lt::settings_pack& pack) + { + pack.set_int(lt::settings_pack::file_pool_size, 5); + } + // add torrent + , [](lt::add_torrent_params& atp) { + // we need a torrent with lots of files in it, to hit the + // file_size_limit we set. + file_storage fs; + for (int i = 0; i < 0x10 * 9; ++i) + { + char filename[50]; + snprintf(filename, sizeof(filename), "root/file-%d", i); + fs.add_file(filename, 0x400); + } + atp.ti = boost::make_shared(*atp.ti); + atp.ti->remap_files(fs); + } + // on alert + , [&](lt::alert const* a, lt::session&) + {} + // terminate + , [&](int ticks, lt::session& ses) -> bool + { + if (ticks > 80) + { + TEST_ERROR("timeout"); + return true; + } + + std::vector status; + ses.get_torrents().at(0).file_status(status); + printf("open files: %d\n", int(status.size())); + max_files = std::max(max_files, int(status.size())); + if (!is_seed(ses)) return false; + printf("completed in %d ticks\n", ticks); + ran_to_completion = true; + return true; + }); + + TEST_CHECK(max_files <= 5); + TEST_CHECK(max_files >= 4); + TEST_CHECK(ran_to_completion); +} + diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 2d4d284fa..f5812984c 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -57,10 +57,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/debug.hpp" -#if TORRENT_USE_RLIMIT -#include -#endif - #define DEBUG_DISK_THREAD 0 #if __cplusplus >= 201103L || defined __clang__ @@ -172,7 +168,7 @@ namespace libtorrent // futexes, shared objects etc. // 80% of the available file descriptors should go to connections // 20% goes towards regular files - const int max_files = (std::min)((std::max)(5 + const int max_files = std::min((std::max)(5 , (max_open_files() - 20) * 2 / 10) , m_file_pool.size_limit()); m_file_pool.resize(max_files); @@ -282,6 +278,7 @@ namespace libtorrent apply_pack(pack, m_settings); error_code ec; m_disk_cache.set_settings(m_settings, ec); + m_file_pool.resize(m_settings.get_int(settings_pack::file_pool_size)); #ifndef TORRENT_NO_DEPRECATE if (ec && alerts.should_post()) { diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 10d632263..a088dc7ca 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -57,24 +57,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#if TORRENT_USE_RLIMIT - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlong-long" -#endif // __GNUC__ - -#include - -// capture this here where warnings are disabled (the macro generates warnings) -const rlim_t rlim_infinity = RLIM_INFINITY; - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif // __GNUC__ - -#endif // TORRENT_USE_RLIMIT - #include "libtorrent/aux_/disable_warnings_pop.hpp" #include "libtorrent/aux_/openssl.hpp" From dec8c853e3b6454e6ff485c64130a7e33325ca99 Mon Sep 17 00:00:00 2001 From: arvidn Date: Thu, 9 Mar 2017 19:26:19 -0500 Subject: [PATCH 2/8] fix default file pool size on windows --- ChangeLog | 1 + src/disk_io_thread.cpp | 9 --------- src/session_impl.cpp | 6 +++--- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45552b0d9..f54e84cba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * fix default file pool size on windows * fix bug where settings_pack::file_pool_size setting was not being honored * add feature to periodically close files (to make windows clear disk cache) * fix bug in torrent_handle::file_status diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index f5812984c..10261aaf5 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -163,15 +163,6 @@ namespace libtorrent error_code ec; m_disk_cache.set_settings(m_settings, ec); TORRENT_ASSERT(!ec); - - // deduct some margin for epoll/kqueue, log files, - // futexes, shared objects etc. - // 80% of the available file descriptors should go to connections - // 20% goes towards regular files - const int max_files = std::min((std::max)(5 - , (max_open_files() - 20) * 2 / 10) - , m_file_pool.size_limit()); - m_file_pool.resize(max_files); } disk_io_thread::~disk_io_thread() diff --git a/src/session_impl.cpp b/src/session_impl.cpp index a088dc7ca..ae5fa93ce 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -520,13 +520,13 @@ namespace aux { #endif // TORRENT_DISABLE_LOGGING // ---- auto-cap max connections ---- - int max_files = max_open_files(); + int const max_files = max_open_files(); // deduct some margin for epoll/kqueue, log files, // futexes, shared objects etc. // 80% of the available file descriptors should go to connections - m_settings.set_int(settings_pack::connections_limit, (std::min)( + m_settings.set_int(settings_pack::connections_limit, std::min( m_settings.get_int(settings_pack::connections_limit) - , (std::max)(5, (max_files - 20) * 8 / 10))); + , std::max(5, (max_files - 20) * 8 / 10))); // 20% goes towards regular files (see disk_io_thread) #ifndef TORRENT_DISABLE_LOGGING session_log(" max connections: %d", m_settings.get_int(settings_pack::connections_limit)); From 08c05b9693497dfae3782584de2867906d42e9bd Mon Sep 17 00:00:00 2001 From: arvidn Date: Thu, 9 Mar 2017 19:09:10 -0500 Subject: [PATCH 3/8] correctly URL encode the IPv6 argument to trackers --- ChangeLog | 1 + simulation/test_tracker.cpp | 3 +++ src/http_tracker_connection.cpp | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f54e84cba..d66c92f33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * correctly URL encode the IPv6 argument to trackers * fix default file pool size on windows * fix bug where settings_pack::file_pool_size setting was not being honored * add feature to periodically close files (to make windows clear disk cache) diff --git a/simulation/test_tracker.cpp b/simulation/test_tracker.cpp index e3466c4be..50730e066 100644 --- a/simulation/test_tracker.cpp +++ b/simulation/test_tracker.cpp @@ -744,6 +744,9 @@ TORRENT_TEST(tracker_ipv6_argument) std::string::size_type pos = req.find("&ipv6="); TEST_CHECK(pos != std::string::npos); got_ipv6 = pos != std::string::npos; + // make sure the IPv6 argument is url encoded + TEST_CHECK(req.substr(pos + 6, req.find_first_of(pos + 6, '&')) + == "ffff%3a%3a1337"); return sim::send_response(200, "OK", 11) + "d5:peers0:e"; } , [](torrent_handle h) {} diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index cf891bf92..b1aad94bd 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -194,7 +194,7 @@ namespace libtorrent if (!err) { url += "&ipv6="; - url += ip; + url += escape_string(ip.c_str(), ip.size()); } } #endif From 3f90501934b7d04a8ad720ac8ecf9b29765f4016 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 11 Mar 2017 02:46:51 -0500 Subject: [PATCH 4/8] add support for IPv6 peers from udp trackers (#1802) add support for IPv6 peers from udp trackers --- ChangeLog | 1 + src/udp_tracker_connection.cpp | 42 ++++++++++++++++++++++++++-------- test/setup_transfer.cpp | 2 +- test/setup_transfer.hpp | 3 ++- test/test_tracker.cpp | 39 +++++++++++++++++++++++-------- test/udp_tracker.cpp | 38 +++++++++++++++++++++++------- test/udp_tracker.hpp | 4 +++- 7 files changed, 99 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index d66c92f33..8edd7bb0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * add support for IPv6 peers from udp trackers * correctly URL encode the IPv6 argument to trackers * fix default file pool size on windows * fix bug where settings_pack::file_pool_size setting was not being honored diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 3e1430884..141f81b34 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -598,8 +598,15 @@ namespace libtorrent resp.min_interval = 60; resp.incomplete = detail::read_int32(buf); resp.complete = detail::read_int32(buf); - int num_peers = (size - 20) / 6; - if ((size - 20) % 6 != 0) + + std::size_t const ip_stride = +#if TORRENT_USE_IPV6 + m_target.address().is_v6() ? 18 : +#endif + 6; + + int const num_peers = (size - 20) / ip_stride; + if ((size - 20) % ip_stride != 0) { fail(error_code(errors::invalid_tracker_response_length)); return false; @@ -619,14 +626,31 @@ namespace libtorrent return true; } - resp.peers4.reserve(num_peers); - for (int i = 0; i < num_peers; ++i) +#if TORRENT_USE_IPV6 + if (m_target.address().is_v6()) { - ipv4_peer_entry e; - memcpy(&e.ip[0], buf, 4); - buf += 4; - e.port = detail::read_uint16(buf); - resp.peers4.push_back(e); + resp.peers6.reserve(std::size_t(num_peers)); + for (int i = 0; i < num_peers; ++i) + { + ipv6_peer_entry e; + std::memcpy(&e.ip[0], buf, 16); + buf += 16; + e.port = detail::read_uint16(buf); + resp.peers6.push_back(e); + } + } + else +#endif + { + resp.peers4.reserve(std::size_t(num_peers)); + for (int i = 0; i < num_peers; ++i) + { + ipv4_peer_entry e; + memcpy(&e.ip[0], buf, 4); + buf += 4; + e.port = detail::read_uint16(buf); + resp.peers4.push_back(e); + } } std::list
ip_list; diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index 3cbcda4df..4615b5dc3 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -264,7 +264,7 @@ void save_file(char const* filename, char const* data, int size) bool print_alerts(lt::session& ses, char const* name , bool allow_disconnects, bool allow_no_torrents, bool allow_failed_fastresume - , bool (*predicate)(libtorrent::alert const*), bool no_output) + , boost::function predicate, bool no_output) { bool ret = false; std::vector handles = ses.get_torrents(); diff --git a/test/setup_transfer.hpp b/test/setup_transfer.hpp index 3b5ece736..bbb5e3fb6 100644 --- a/test/setup_transfer.hpp +++ b/test/setup_transfer.hpp @@ -75,7 +75,8 @@ EXPORT bool print_alerts(libtorrent::session& ses, char const* name , bool allow_disconnects = false , bool allow_no_torrents = false , bool allow_failed_fastresume = false - , bool (*)(libtorrent::alert const*) = 0 + , boost::function predicate + = boost::function() , bool no_output = false); EXPORT void wait_for_listen(libtorrent::session& ses, char const* name); diff --git a/test/test_tracker.cpp b/test/test_tracker.cpp index 0f25c4570..1c980632f 100644 --- a/test/test_tracker.cpp +++ b/test/test_tracker.cpp @@ -312,17 +312,23 @@ TORRENT_TEST(extract_peer_missing_port) , errors::invalid_tracker_response, false); } -TORRENT_TEST(udp_tracker) +bool connect_alert(libtorrent::alert const* a, tcp::endpoint& ep) { - int http_port = start_web_server(); - int udp_port = start_udp_tracker(); + if (peer_connect_alert const* pc = alert_cast(a)) + ep = pc->ip; + return true; +} + +void test_udp_tracker(std::string const& iface, address tracker, tcp::endpoint const& expected_peer) +{ + int const udp_port = start_udp_tracker(tracker); int prev_udp_announces = num_udp_announces(); settings_pack pack = settings(); pack.set_bool(settings_pack::announce_to_all_trackers, true); pack.set_bool(settings_pack::announce_to_all_tiers, true); - pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:48875"); + pack.set_str(settings_pack::listen_interfaces, iface + ":48875"); boost::scoped_ptr s(new lt::session(pack)); @@ -334,12 +340,9 @@ TORRENT_TEST(udp_tracker) file.close(); char tracker_url[200]; - snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port); + snprintf(tracker_url, sizeof(tracker_url), "udp://%s:%d/announce", iface.c_str(), udp_port); t->add_tracker(tracker_url, 0); - snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port); - t->add_tracker(tracker_url, 1); - add_torrent_params addp; addp.flags &= ~add_torrent_params::flag_paused; addp.flags &= ~add_torrent_params::flag_auto_managed; @@ -348,9 +351,11 @@ TORRENT_TEST(udp_tracker) addp.save_path = "tmp1_tracker"; torrent_handle h = s->add_torrent(addp); + tcp::endpoint peer_ep; for (int i = 0; i < 50; ++i) { - print_alerts(*s, "s"); + print_alerts(*s, "s", false, false, false, boost::bind(&connect_alert, _1, boost::ref(peer_ep))); + if (num_udp_announces() == prev_udp_announces + 1) break; @@ -370,7 +375,7 @@ TORRENT_TEST(udp_tracker) for (int i = 0; i < 50; ++i) { - print_alerts(*s, "s", true, true); + print_alerts(*s, "s", true, true, false, boost::bind(&connect_alert, _1, boost::ref(peer_ep))); if (num_udp_announces() == prev_udp_announces + 2) break; @@ -379,6 +384,8 @@ TORRENT_TEST(udp_tracker) , int(prev_udp_announces) + 1); } + TEST_CHECK(peer_ep == expected_peer); + fprintf(stderr, "destructing session\n"); s.reset(); fprintf(stderr, "done\n"); @@ -387,6 +394,18 @@ TORRENT_TEST(udp_tracker) TEST_EQUAL(num_udp_announces(), prev_udp_announces + 2); } +TORRENT_TEST(udp_tracker_v4) +{ + test_udp_tracker("127.0.0.1", address_v4::any(), ep("1.3.3.7", 1337)); +} + +#if TORRENT_USE_IPV6 +TORRENT_TEST(udp_tracker_v6) +{ + test_udp_tracker("[::1]", address_v6::any(), ep("::1.3.3.7", 1337)); +} +#endif + TORRENT_TEST(http_peers) { int http_port = start_web_server(); diff --git a/test/udp_tracker.cpp b/test/udp_tracker.cpp index 5d5a59fdd..922dbfe55 100644 --- a/test/udp_tracker.cpp +++ b/test/udp_tracker.cpp @@ -120,9 +120,30 @@ struct udp_tracker detail::write_uint32(1800, ptr); // interval detail::write_uint32(1, ptr); // incomplete detail::write_uint32(1, ptr); // complete - // 0 peers - m_socket.send_to(boost::asio::buffer(buffer, 20), *from, 0, e); - if (e) fprintf(stderr, "%s: UDP send_to failed. ERROR: %s\n" + // 1 peers +#if TORRENT_USE_IPV6 + if (from->address().is_v6()) + { + detail::write_uint32(0, ptr); + detail::write_uint32(0, ptr); + detail::write_uint32(0, ptr); + detail::write_uint8(1, ptr); + detail::write_uint8(3, ptr); + detail::write_uint8(3, ptr); + detail::write_uint8(7, ptr); + detail::write_uint16(1337, ptr); + } + else +#endif + { + detail::write_uint8(1, ptr); + detail::write_uint8(3, ptr); + detail::write_uint8(3, ptr); + detail::write_uint8(7, ptr); + detail::write_uint16(1337, ptr); + } + m_socket.send_to(boost::asio::buffer(buffer, ptr - buffer), *from, 0, e); + if (e) std::printf("%s: UDP send_to failed. ERROR: %s\n" , time_now_string(), e.message().c_str()); else fprintf(stderr, "%s: UDP sent response to: %s\n" , time_now_string(), print_endpoint(*from).c_str()); @@ -142,21 +163,21 @@ struct udp_tracker , boost::bind(&udp_tracker::on_udp_receive, this, _1, _2, from, buffer, size)); } - udp_tracker() + udp_tracker(address iface) : m_udp_announces(0) , m_socket(m_ios) , m_port(0) , m_abort(false) { error_code ec; - m_socket.open(udp::v4(), ec); + m_socket.open(iface.is_v4() ? udp::v4() : udp::v6(), ec); if (ec) { fprintf(stderr, "UDP Error opening listen UDP tracker socket: %s\n", ec.message().c_str()); return; } - m_socket.bind(udp::endpoint(address_v4::any(), 0), ec); + m_socket.bind(udp::endpoint(iface, 0), ec); if (ec) { fprintf(stderr, "UDP Error binding UDP tracker socket to port 0: %s\n", ec.message().c_str()); @@ -176,6 +197,7 @@ struct udp_tracker void stop() { + std::printf("%s: UDP tracker, stop\n", time_now_string()); m_abort = true; m_socket.cancel(); m_socket.close(); @@ -222,9 +244,9 @@ struct udp_tracker boost::shared_ptr g_udp_tracker; -int start_udp_tracker() +int start_udp_tracker(address iface) { - g_udp_tracker.reset(new udp_tracker); + g_udp_tracker.reset(new udp_tracker(iface)); return g_udp_tracker->port(); } diff --git a/test/udp_tracker.hpp b/test/udp_tracker.hpp index d27258da1..56dc07eed 100644 --- a/test/udp_tracker.hpp +++ b/test/udp_tracker.hpp @@ -31,9 +31,11 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "test.hpp" // for EXPORT +#include "libtorrent/address.hpp" // returns the port the udp tracker is running on -int EXPORT start_udp_tracker(); +int EXPORT start_udp_tracker(libtorrent::address iface + = libtorrent::address_v4::any()); // the number of udp tracker announces received int EXPORT num_udp_announces(); From 4ded26de3305cb5375500057b24bbe67fe3cb490 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sat, 11 Mar 2017 19:59:53 -0500 Subject: [PATCH 5/8] fix issue with load/unload torrents --- simulation/libsimulator | 2 +- src/torrent.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/simulation/libsimulator b/simulation/libsimulator index 36b46fc2c..60d786b8f 160000 --- a/simulation/libsimulator +++ b/simulation/libsimulator @@ -1 +1 @@ -Subproject commit 36b46fc2c316d34714315c04c87cf74de6efae90 +Subproject commit 60d786b8fa6ddaacdc98bdf691220660bc194494 diff --git a/src/torrent.cpp b/src/torrent.cpp index a447f271e..76f038458 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1364,6 +1364,7 @@ namespace libtorrent if (m_file_progress.empty()) { TORRENT_ASSERT(has_picker()); + if (!need_loaded()) return; m_file_progress.init(picker(), m_torrent_file->files()); } From e37e4bfe8abccd0af275b9131cf0ddcb9cc15e80 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 12 Mar 2017 12:49:41 -0400 Subject: [PATCH 6/8] include user-agent in tracker announces in anonymous_mode for private torrents --- ChangeLog | 1 + include/libtorrent/tracker_manager.hpp | 5 +++ simulation/test_tracker.cpp | 55 ++++++++++++++++++++++++++ src/http_tracker_connection.cpp | 12 ++++-- src/rss.cpp | 5 ++- src/session_impl.cpp | 4 +- src/torrent.cpp | 6 +++ src/web_connection_base.cpp | 24 ++++++----- 8 files changed, 94 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8edd7bb0f..e9efb3ada 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * include user-agent in tracker announces in anonymous_mode for private torrents * add support for IPv6 peers from udp trackers * correctly URL encode the IPv6 argument to trackers * fix default file pool size on windows diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index 49cd84e77..8ec129df5 100644 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -99,6 +99,7 @@ namespace libtorrent , key(0) , num_want(0) , send_stats(true) + , private_torrent(false) , triggered_manually(false) #ifdef TORRENT_USE_OPENSSL , ssl_ctx(0) @@ -159,6 +160,10 @@ namespace libtorrent bool send_stats; + // set to true if the .torrent file this tracker announce is for is marked + // as private (i.e. has the "priv": 1 key) + bool private_torrent; + // this is set to true if this request was triggered by a "manual" call to // scrape_tracker() or force_reannounce() bool triggered_manually; diff --git a/simulation/test_tracker.cpp b/simulation/test_tracker.cpp index 50730e066..36fa89162 100644 --- a/simulation/test_tracker.cpp +++ b/simulation/test_tracker.cpp @@ -813,6 +813,61 @@ TORRENT_TEST(tracker_ipv6_argument_privacy_mode) TEST_EQUAL(got_ipv6, false); } +TORRENT_TEST(tracker_user_agent_privacy_mode_public_torrent) +{ + bool got_announce = false; + tracker_test( + [](lt::add_torrent_params& p, lt::session& ses) + { + settings_pack pack; + pack.set_bool(settings_pack::anonymous_mode, true); + pack.set_str(settings_pack::user_agent, "test_agent/1.2.3"); + ses.apply_settings(pack); + p.ti = make_torrent(false); + return 60; + }, + [&](std::string method, std::string req + , std::map& headers) + { + got_announce = true; + + // in anonymous mode we should not send a user agent + TEST_CHECK(headers["user-agent"] == ""); + return sim::send_response(200, "OK", 11) + "d5:peers0:e"; + } + , [](torrent_handle h) {} + , [](torrent_handle h) {}); + TEST_EQUAL(got_announce, true); +} + +TORRENT_TEST(tracker_user_agent_privacy_mode_private_torrent) +{ + bool got_announce = false; + tracker_test( + [](lt::add_torrent_params& p, lt::session& ses) + { + settings_pack pack; + pack.set_bool(settings_pack::anonymous_mode, true); + pack.set_str(settings_pack::user_agent, "test_agent/1.2.3"); + ses.apply_settings(pack); + p.ti = make_torrent(true); + return 60; + }, + [&](std::string method, std::string req + , std::map& headers) + { + got_announce = true; + + // in anonymous mode we should still send the user agent for private + // torrents (since private trackers sometimes require it) + TEST_CHECK(headers["user-agent"] == "test_agent/1.2.3"); + return sim::send_response(200, "OK", 11) + "d5:peers0:e"; + } + , [](torrent_handle h) {} + , [](torrent_handle h) {}); + TEST_EQUAL(got_announce, true); +} + // TODO: test external IP // TODO: test with different queuing settings // TODO: test when a torrent transitions from downloading to finished and diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index b1aad94bd..472c1714c 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -209,10 +209,16 @@ namespace libtorrent #endif )); - int timeout = tracker_req().event==tracker_request::stopped + int const timeout = tracker_req().event==tracker_request::stopped ?settings.get_int(settings_pack::stop_tracker_timeout) :settings.get_int(settings_pack::tracker_completion_timeout); + // in anonymous mode we omit the user agent to mitigate fingerprinting of + // the client. Private torrents is an exception because some private + // trackers may requre the user agent + std::string const user_agent = settings.get_bool(settings_pack::anonymous_mode) + && !tracker_req().private_torrent ? "" : settings.get_str(settings_pack::user_agent); + // when sending stopped requests, prefer the cached DNS entry // to avoid being blocked for slow or failing responses. Chances // are that we're shutting down, and this should be a best-effort @@ -221,9 +227,7 @@ namespace libtorrent m_tracker_connection->get(url, seconds(timeout) , tracker_req().event == tracker_request::stopped ? 2 : 1 , ps.proxy_tracker_connections ? &ps : NULL - , 5, settings.get_bool(settings_pack::anonymous_mode) - ? "" : settings.get_str(settings_pack::user_agent) - , bind_interface() + , 5, user_agent, bind_interface() , tracker_req().event == tracker_request::stopped ? resolver_interface::prefer_cache : resolver_interface::abort_on_shutdown diff --git a/src/rss.cpp b/src/rss.cpp index 9f909383b..8198f1bb3 100644 --- a/src/rss.cpp +++ b/src/rss.cpp @@ -629,9 +629,10 @@ int feed::update_feed() , boost::bind(&feed::on_feed, shared_from_this() , _1, _2, _3, _4))); + std::string const user_agent = m_ses.settings().get_bool(settings_pack::anonymous_mode) + ? "" : m_ses.settings().get_str(settings_pack::user_agent); m_updating = true; - feed->get(m_settings.url, seconds(30), 0, 0, 5 - , m_ses.settings().get_str(settings_pack::user_agent)); + feed->get(m_settings.url, seconds(30), 0, 0, 5, user_agent); return 60 + m_failures * m_failures * 60; } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index ae5fa93ce..40f52f2b0 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -6555,9 +6555,7 @@ retry: return; } - if (m_upnp) - m_upnp->set_user_agent(""); - m_settings.set_str(settings_pack::user_agent, ""); + if (m_upnp) m_upnp->set_user_agent(""); url_random(m_peer_id.data(), m_peer_id.data() + 20); } diff --git a/src/torrent.cpp b/src/torrent.cpp index 76f038458..eca8110d5 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3137,6 +3137,8 @@ namespace libtorrent && m_apply_ip_filter) req.filter = m_ip_filter; + req.private_torrent = m_torrent_file->priv(); + req.info_hash = m_torrent_file->info_hash(); req.pid = m_ses.get_peer_id(); req.downloaded = m_stat.total_payload_download() - m_total_failed_bytes; @@ -3342,6 +3344,7 @@ namespace libtorrent req.info_hash = m_torrent_file->info_hash(); req.kind |= tracker_request::scrape_request; req.url = m_trackers[idx].url; + req.private_torrent = m_torrent_file->priv(); #ifndef TORRENT_NO_DEPRECATE req.auth = tracker_login(); #endif @@ -3639,6 +3642,9 @@ namespace libtorrent // and they should be announced to in parallel tracker_request req = r; + + req.private_torrent = m_torrent_file->priv(); + // tell the tracker to bind to the opposite protocol type req.bind_ip = tracker_ip.is_v4() ? m_ses.get_ipv6_interface().address() diff --git a/src/web_connection_base.cpp b/src/web_connection_base.cpp index a3f0683d6..9ad70b513 100644 --- a/src/web_connection_base.cpp +++ b/src/web_connection_base.cpp @@ -145,28 +145,34 @@ namespace libtorrent request += "Host: "; request += m_host; if ((m_first_request || m_settings.get_bool(settings_pack::always_send_user_agent)) - && !m_settings.get_bool(settings_pack::anonymous_mode)) { + && !m_settings.get_bool(settings_pack::anonymous_mode)) + { request += "\r\nUser-Agent: "; request += m_settings.get_str(settings_pack::user_agent); } - if (!m_external_auth.empty()) { + if (!m_external_auth.empty()) + { request += "\r\nAuthorization: "; request += m_external_auth; - } else if (!m_basic_auth.empty()) { + } + else if (!m_basic_auth.empty()) + { request += "\r\nAuthorization: Basic "; request += m_basic_auth; } - if (sett.get_int(settings_pack::proxy_type) == settings_pack::http_pw) { + if (sett.get_int(settings_pack::proxy_type) == settings_pack::http_pw) + { request += "\r\nProxy-Authorization: Basic "; request += base64encode(sett.get_str(settings_pack::proxy_username) + ":" + sett.get_str(settings_pack::proxy_password)); } for (web_seed_entry::headers_t::const_iterator it = m_extra_headers.begin(); - it != m_extra_headers.end(); ++it) { - request += "\r\n"; - request += it->first; - request += ": "; - request += it->second; + it != m_extra_headers.end(); ++it) + { + request += "\r\n"; + request += it->first; + request += ": "; + request += it->second; } if (using_proxy) { request += "\r\nProxy-Connection: keep-alive"; From 6d2d736cecce0af274dd651dd1f562716b625d92 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 12 Mar 2017 13:03:26 -0400 Subject: [PATCH 7/8] fix test_ssl.cpp build with newer versions of boost --- test/test_ssl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_ssl.cpp b/test/test_ssl.cpp index 01c5bc7c7..2903332dd 100644 --- a/test/test_ssl.cpp +++ b/test/test_ssl.cpp @@ -51,7 +51,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #ifdef TORRENT_USE_OPENSSL -#include // for asio::error::get_ssl_category() #include #include "libtorrent/aux_/disable_warnings_pop.hpp" From 6f650aa7d9936221f603278965a3b86ba95ebeb5 Mon Sep 17 00:00:00 2001 From: arvidn Date: Mon, 13 Mar 2017 01:54:21 -0400 Subject: [PATCH 8/8] document deprecation of dynamic loading/unloading of torrents --- ChangeLog | 1 + examples/client_test.cpp | 15 --------------- include/libtorrent/session_handle.hpp | 3 +++ src/session_impl.cpp | 5 ++++- src/settings_pack.cpp | 2 +- 5 files changed, 9 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9efb3ada..6084d1a4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * document deprecation of dynamic loading/unloading of torrents * include user-agent in tracker announces in anonymous_mode for private torrents * add support for IPv6 peers from udp trackers * correctly URL encode the IPv6 argument to trackers diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 0b4cbe502..413388d57 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -641,20 +641,6 @@ void signal_handler(int signo) quit = true; } -void load_torrent(libtorrent::sha1_hash const& ih, std::vector& buf, libtorrent::error_code& ec) -{ - files_t::iterator i = hash_to_filename.find(ih); - if (i == hash_to_filename.end()) - { - // for magnet links and torrents downloaded via - // URL, the metadata is saved in the resume file - // TODO: pick up metadata from the resume file - ec.assign(boost::system::errc::no_such_file_or_directory, boost::system::generic_category()); - return; - } - load_file(i->second, buf, ec); -} - // if non-empty, a peer that will be added to all torrents std::string peer; @@ -1586,7 +1572,6 @@ int main(int argc, char* argv[]) } ses.set_ip_filter(loaded_ip_filter); - ses.set_load_function(&load_torrent); error_code ec; diff --git a/include/libtorrent/session_handle.hpp b/include/libtorrent/session_handle.hpp index c2c32d23e..f56773b2e 100644 --- a/include/libtorrent/session_handle.hpp +++ b/include/libtorrent/session_handle.hpp @@ -259,6 +259,9 @@ namespace libtorrent void resume(); bool is_paused() const; + // *the feature of dynamically loading/unloading torrents is deprecated + // and discouraged* + // // This function enables dynamic-loading-of-torrent-files_. When a // torrent is unloaded but needs to be availabe in memory, this function // is called **from within the libtorrent network thread**. From within diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 40f52f2b0..077c8a218 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -3791,6 +3791,7 @@ retry: else { t->resume(); + if (!t->should_check_files()) continue; t->start_checking(); --limit; } @@ -7127,7 +7128,9 @@ retry: TORRENT_ASSERT(is_single_thread()); int loaded_limit = m_settings.get_int(settings_pack::active_loaded_limit); - TORRENT_ASSERT(m_num_save_resume <= loaded_limit); + TORRENT_ASSERT(loaded_limit == 0 + || !m_user_load_torrent + || m_num_save_resume <= loaded_limit); // if (m_num_save_resume < loaded_limit) // TORRENT_ASSERT(m_save_resume_queue.empty()); diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 8513d5132..8be2a279a 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -276,7 +276,7 @@ namespace libtorrent SET(active_tracker_limit, 1600, 0), SET(active_lsd_limit, 60, 0), SET(active_limit, 15, &session_impl::trigger_auto_manage), - SET_NOPREV(active_loaded_limit, 100, &session_impl::trigger_auto_manage), + SET_NOPREV(active_loaded_limit, 0, &session_impl::trigger_auto_manage), SET(auto_manage_interval, 30, 0), SET(seed_time_limit, 24 * 60 * 60, 0), SET(auto_scrape_interval, 1800, 0),