From b750b6cc2c7719ecbd43bbdde37ccd78f192dc25 Mon Sep 17 00:00:00 2001 From: arvidn Date: Wed, 4 Jul 2018 14:49:51 +0200 Subject: [PATCH] deprecate (and disable) the force-proxy setting. Instead, always use the proxy when set, never fall back on circumventing it --- ChangeLog | 1 + include/libtorrent/aux_/session_impl.hpp | 1 - include/libtorrent/settings_pack.hpp | 4 + include/libtorrent/udp_socket.hpp | 3 - simulation/test_session.cpp | 54 ------ simulation/test_socks5.cpp | 4 +- simulation/utils.cpp | 1 - src/bt_peer_connection.cpp | 5 +- src/http_connection.cpp | 3 +- src/session_impl.cpp | 106 ++++------- src/settings_pack.cpp | 2 +- src/torrent.cpp | 42 ----- src/udp_socket.cpp | 65 ++++--- src/udp_tracker_connection.cpp | 6 +- test/test_privacy.cpp | 230 +++++++++++------------ test/test_tracker.cpp | 1 - test/test_transfer.cpp | 1 - 17 files changed, 208 insertions(+), 321 deletions(-) diff --git a/ChangeLog b/ChangeLog index ecc19f032..0690fb7e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * deprecated force_proxy setting (when set, the proxy is always used) * add support for Port Control Protocol (PCP) * deliver notification of alerts being dropped via alerts_dropped_alert * deprecated alert::progress_notification alert category, split into diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 826e9cf7e..2b10f2a3c 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -752,7 +752,6 @@ namespace aux { void update_socket_buffer_size(); void update_dht_announce_interval(); void update_anonymous_mode(); - void update_force_proxy(); void update_download_rate(); void update_upload_rate(); void update_connections_limit(); diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 31017ff72..e5e3036e0 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -621,6 +621,7 @@ namespace libtorrent { // same write cache line as is configured in the disk cache. allow_partial_disk_writes, +#if TORRENT_ABI_VERSION == 1 // If true, disables any communication that's not going over a proxy. // Enabling this requires a proxy to be configured as well, see // proxy_type and proxy_hostname settings. The listen sockets are @@ -630,6 +631,9 @@ namespace libtorrent { // country lookups, since those are done via DNS lookups that aren't // supported by proxies. force_proxy, +#else + deprecated_force_proxy, +#endif // if false, prevents libtorrent to advertise share-mode support support_share_mode, diff --git a/include/libtorrent/udp_socket.hpp b/include/libtorrent/udp_socket.hpp index bea504187..d1ca85795 100644 --- a/include/libtorrent/udp_socket.hpp +++ b/include/libtorrent/udp_socket.hpp @@ -97,7 +97,6 @@ namespace libtorrent { void set_proxy_settings(aux::proxy_settings const& ps); aux::proxy_settings const& get_proxy_settings() { return m_proxy_settings; } - void set_force_proxy(bool f) { m_force_proxy = f; } bool is_closed() const { return m_abort; } udp::endpoint local_endpoint(error_code& ec) const @@ -152,8 +151,6 @@ namespace libtorrent { std::shared_ptr m_socks5_connection; - // TODO: 3 add a unit test for force-proxy - bool m_force_proxy:1; bool m_abort:1; #if TORRENT_USE_ASSERTS diff --git a/simulation/test_session.cpp b/simulation/test_session.cpp index f22b4b9c0..0fa2a5adf 100644 --- a/simulation/test_session.cpp +++ b/simulation/test_session.cpp @@ -117,60 +117,6 @@ TORRENT_TEST(ip_notifier_setting) } #endif -TORRENT_TEST(force_proxy) -{ - // setup the simulation - sim::default_config network_cfg; - sim::simulation sim{network_cfg}; - std::unique_ptr ios{new sim::asio::io_service(sim - , address_v4::from_string("50.0.0.1"))}; - lt::session_proxy zombie; - - lt::settings_pack pack = settings(); - pack.set_bool(settings_pack::force_proxy, true); - // create session - std::shared_ptr ses = std::make_shared(pack, *ios); - - // disable force proxy in 3 seconds (this should make us open up listen - // sockets) - sim::timer t1(sim, lt::seconds(3), [&](boost::system::error_code const& ec) - { - lt::settings_pack p; - p.set_bool(settings_pack::force_proxy, false); - ses->apply_settings(p); - }); - - int num_listen_tcp = 0; - int num_listen_udp = 0; - print_alerts(*ses, [&](lt::session& ses, lt::alert const* a) { - if (auto la = alert_cast(a)) - { - if (la->socket_type == socket_type_t::tcp) - ++num_listen_tcp; - else if (la->socket_type == socket_type_t::udp) - ++num_listen_udp; - } - }); - - // run for 10 seconds. - sim::timer t2(sim, lt::seconds(10), [&](boost::system::error_code const& ec) - { - fprintf(stderr, "shutting down\n"); - // shut down - zombie = ses->abort(); - ses.reset(); - }); - sim.run(); - - // on session construction, we won't listen to TCP since we're in force-proxy - // mode. We will open up the UDP sockets though, since they are used for - // outgoing connections too. - // when we disable force-proxy, we'll re-open the sockets and listen on TCP - // connections this time, so we'll get a tcp_listen and a udp_listen. - TEST_EQUAL(num_listen_tcp, 1); - TEST_EQUAL(num_listen_udp, 2); -} - #ifndef TORRENT_DISABLE_EXTENSIONS struct test_plugin : lt::torrent_plugin { diff --git a/simulation/test_socks5.cpp b/simulation/test_socks5.cpp index a467cd2a1..483522663 100644 --- a/simulation/test_socks5.cpp +++ b/simulation/test_socks5.cpp @@ -153,10 +153,8 @@ TORRENT_TEST(socks5_tcp_announce) } ); - // since force_proxy is enabled, don't send the port - TEST_EQUAL(tracker_port, 0); + TEST_EQUAL(tracker_port, 6881); TEST_CHECK(alert_port != -1); - TEST_CHECK(tracker_port != -1); } TORRENT_TEST(udp_tracker) diff --git a/simulation/utils.cpp b/simulation/utils.cpp index fe3c8c577..501a06f6a 100644 --- a/simulation/utils.cpp +++ b/simulation/utils.cpp @@ -114,7 +114,6 @@ void set_proxy(lt::session& ses, int proxy_type, int flags, bool proxy_peer_conn p.set_bool(settings_pack::proxy_hostnames, true); p.set_bool(settings_pack::proxy_peer_connections, proxy_peer_connections); p.set_bool(settings_pack::proxy_tracker_connections, true); - p.set_bool(settings_pack::force_proxy, true); ses.apply_settings(p); } diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 800de5d31..b39eb251d 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -2086,8 +2086,9 @@ namespace { // if we're using a proxy, our listen port won't be useful // anyway. - if (!m_settings.get_bool(settings_pack::force_proxy) && is_outgoing()) - handshake["p"] = m_ses.listen_port(); + auto const port = m_ses.listen_port(); + if (port != 0 && is_outgoing()) + handshake["p"] = port; // only send the port in case we bade the connection // on incoming connections the other end already knows diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 2ff1c5bf7..bf476d282 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -167,8 +167,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri TORRENT_ASSERT(prio >= 0 && prio < 3); - bool ssl = false; - if (protocol == "https") ssl = true; + bool const ssl = (protocol == "https"); std::stringstream request; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 49d17599e..c0e504098 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1272,10 +1272,7 @@ namespace aux { != m_settings.get_int(settings_pack::ssl_listen)) || #endif - (pack.has_val(settings_pack::force_proxy) - && !pack.get_bool(settings_pack::force_proxy) - && m_settings.get_bool(settings_pack::force_proxy)) - || (pack.has_val(settings_pack::listen_interfaces) + (pack.has_val(settings_pack::listen_interfaces) && pack.get_str(settings_pack::listen_interfaces) != m_settings.get_str(settings_pack::listen_interfaces)); @@ -1660,7 +1657,6 @@ namespace aux { , operation_t::alloc_recvbuf, err); } - ret->udp_sock->sock.set_force_proxy(m_settings.get_bool(settings_pack::force_proxy)); // this call is necessary here because, unless the settings actually // change after the session is up and listening, at no other point // set_proxy_settings is called with the correct proxy configuration, @@ -1785,7 +1781,7 @@ namespace aux { // of a new socket failing to bind due to a conflict with a stale socket std::vector eps; - duplex const incoming = m_settings.get_bool(settings_pack::force_proxy) + duplex const incoming = m_settings.get_int(settings_pack::proxy_type) != settings_pack::none ? duplex::only_outgoing : duplex::accept_incoming; @@ -2071,7 +2067,6 @@ namespace aux { , operation_t::alloc_recvbuf, err); } - udp_sock->sock.set_force_proxy(m_settings.get_bool(settings_pack::force_proxy)); // this call is necessary here because, unless the settings actually // change after the session is up and listening, at no other point // set_proxy_settings is called with the correct proxy configuration, @@ -2604,8 +2599,9 @@ namespace aux { } async_accept(listener, ssl); - // don't accept any connections from our local sockets - if (m_settings.get_bool(settings_pack::force_proxy)) + // don't accept any connections from our local sockets if we're using a + // proxy + if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none) return; #ifdef TORRENT_USE_OPENSSL @@ -5387,12 +5383,17 @@ namespace aux { std::uint16_t session_impl::listen_port(listen_socket_t* sock) const { - // if not, don't tell the tracker anything if we're in force_proxy - // mode. We don't want to leak our listen port since it can - // potentially identify us if it is leaked elsewhere - if (m_settings.get_bool(settings_pack::force_proxy)) return 0; if (m_listen_sockets.empty()) return 0; - if (sock) return std::uint16_t(sock->tcp_external_port); + if (sock) + { + // if we're using a proxy, we won't be able to accept any TCP + // connections. We may be able to accept uTP connections though, so + // announce the UDP port instead + if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none) + return std::uint16_t(sock->udp_external_port); + else + return std::uint16_t(sock->tcp_external_port); + } return std::uint16_t(m_listen_sockets.front()->tcp_external_port); } @@ -5406,15 +5407,30 @@ namespace aux { std::uint16_t session_impl::ssl_listen_port(listen_socket_t* sock) const { #ifdef TORRENT_USE_OPENSSL - if (sock) return std::uint16_t(sock->tcp_external_port); - // if not, don't tell the tracker anything if we're in force_proxy - // mode. We don't want to leak our listen port since it can - // potentially identify us if it is leaked elsewhere - if (m_settings.get_bool(settings_pack::force_proxy)) return 0; + if (sock) + { + // if we're using a proxy, we won't be able to accept any TCP + // connections. We may be able to accept uTP connections though, so + // announce the UDP port instead + if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none) + return std::uint16_t(sock->udp_external_port); + else + return std::uint16_t(sock->tcp_external_port); + } + + if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none) + return 0; + for (auto const& s : m_listen_sockets) { - if (s->ssl == transport::ssl) return std::uint16_t(s->tcp_external_port); + if (s->ssl == transport::ssl) + { + if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none) + return std::uint16_t(s->udp_external_port); + else + return std::uint16_t(s->tcp_external_port); + } } #else TORRENT_UNUSED(sock); @@ -6411,56 +6427,6 @@ namespace aux { if (m_upnp) m_upnp->set_user_agent(""); } - void session_impl::update_force_proxy() - { - if (!m_settings.get_bool(settings_pack::force_proxy)) - { -#ifndef TORRENT_DISABLE_LOGGING - session_log("force-proxy disabled"); -#endif - // we need to close and remove all listen sockets during a transition - // from force-proxy to not-force-proxy. reopen_listen_sockets() won't - // do anything with half-opened sockets. - error_code ec; - for (auto& i : m_listen_sockets) - { - if (i->udp_sock) i->udp_sock->sock.close(); - if (i->sock) i->sock->close(ec); - } - m_listen_sockets.clear(); - return; - } - -#ifndef TORRENT_DISABLE_LOGGING - session_log("force-proxy enabled"); -#endif - - // when enabling force-proxy, we no longer wand to accept connections via - // a regular listen socket, only via a proxy. We also want to enable - // force-proxy on all udp sockets - for (auto& i : m_listen_sockets) - { - i->udp_sock->sock.set_force_proxy(m_settings.get_bool(settings_pack::force_proxy)); - - // close the TCP listen sockets - if (i->sock) - { - error_code ec; - i->sock->close(ec); - i->sock.reset(); - } - } - - // enable force_proxy mode. We don't want to accept any incoming - // connections, except through a proxy. - stop_lsd(); - stop_upnp(); - stop_natpmp(); -#ifndef TORRENT_DISABLE_DHT - stop_dht(); -#endif - } - #if TORRENT_ABI_VERSION == 1 void session_impl::update_local_download_rate() { diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index b0e2ceae1..37d3a84e2 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -192,7 +192,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0; DEPRECATED_SET(contiguous_recv_buffer, true, nullptr), SET(ban_web_seeds, true, nullptr), SET(allow_partial_disk_writes, true, nullptr), - SET(force_proxy, false, &session_impl::update_force_proxy), + DEPRECATED_SET(force_proxy, false, nullptr), SET(support_share_mode, true, nullptr), SET(support_merkle_torrents, true, nullptr), SET(report_redundant_bytes, true, nullptr), diff --git a/src/torrent.cpp b/src/torrent.cpp index 5d2db5437..f22d03b11 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2889,48 +2889,6 @@ bool is_downloading_state(int const st) req.triggered_manually = aep.triggered_manually; aep.triggered_manually = false; - if (settings().get_bool(settings_pack::force_proxy)) - { - // in force_proxy mode we don't talk directly to trackers - // we only allow trackers if there is a proxy and issue - // a warning if there isn't one - std::string const protocol = req.url.substr(0, req.url.find(':')); - int const proxy_type = settings().get_int(settings_pack::proxy_type); - - // http can run over any proxy, so as long as one is used - // it's OK. If no proxy is configured, skip this tracker - if ((protocol == "http" || protocol == "https") - && proxy_type == settings_pack::none) - { - aep.next_announce = now + minutes32(10); - if (m_ses.alerts().should_post() - || req.triggered_manually) - { - m_ses.alerts().emplace_alert(get_handle() - , anonymous_mode_alert::tracker_not_anonymous, req.url); - } - continue; - } - - // for UDP, only socks5 and i2p proxies will work. - // if we're not using one of those proxies with a UDP - // tracker, skip it - if (protocol == "udp" - && proxy_type != settings_pack::socks5 - && proxy_type != settings_pack::socks5_pw - && proxy_type != settings_pack::i2p_proxy) - { - aep.next_announce = now + minutes32(10); - if (m_ses.alerts().should_post() - || req.triggered_manually) - { - m_ses.alerts().emplace_alert(get_handle() - , anonymous_mode_alert::tracker_not_anonymous, req.url); - } - continue; - } - } - #if TORRENT_ABI_VERSION == 1 req.auth = tracker_login(); #endif diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index a9f244d44..442e06270 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -153,7 +153,6 @@ udp_socket::udp_socket(io_service& ios) : m_socket(ios) , m_buf(new receive_buffer()) , m_bind_port(0) - , m_force_proxy(false) , m_abort(true) {} @@ -186,9 +185,7 @@ int udp_socket::read(span pkts, error_code& ec) // SOCKS5 cannot wrap ICMP errors. And even if it could, they certainly // would not arrive as unwrapped (regular) ICMP errors. If we're using // a proxy we must ignore these - if (m_force_proxy - || (m_socks5_connection - && m_socks5_connection->active())) continue; + if (m_proxy_settings.type != settings_pack::none) continue; p.error = ec; p.data = span(); @@ -202,11 +199,22 @@ int udp_socket::read(span pkts, error_code& ec) { // if the source IP doesn't match the proxy's, ignore the packet if (p.from != m_socks5_connection->target()) continue; + // if we failed to unwrap, silently ignore the packet if (!unwrap(p.from, p.data)) continue; } - // block incoming packets that aren't coming via the proxy - // if force proxy mode is enabled - else if (m_force_proxy) continue; + else + { + // if we don't proxy trackers or peers, we may be receiving unwrapped + // packets and we must let them through. + bool const proxy_only + = m_proxy_settings.proxy_peer_connections + && m_proxy_settings.proxy_tracker_connections + ; + + // if we proxy everything, block all packets that aren't coming from + // the proxy + if (m_proxy_settings.type != settings_pack::none && proxy_only) continue; + } } pkts[aux::numeric_cast(ret)] = p; @@ -233,22 +241,29 @@ void udp_socket::send_hostname(char const* hostname, int const port return; } - if (m_socks5_connection && m_socks5_connection->active()) - { - // send udp packets through SOCKS5 server - wrap(hostname, port, p, ec, flags); - return; - } + bool const use_proxy + = ((flags & peer_connection) && m_proxy_settings.proxy_peer_connections) + || ((flags & tracker_connection) && m_proxy_settings.proxy_tracker_connections) + || !(flags & (tracker_connection | peer_connection)) + ; - if (m_force_proxy) + if (use_proxy && m_proxy_settings.type != settings_pack::none) { - ec = error_code(boost::system::errc::permission_denied, generic_category()); + if (m_socks5_connection && m_socks5_connection->active()) + { + // send udp packets through SOCKS5 server + wrap(hostname, port, p, ec, flags); + } + else + { + ec = error_code(boost::system::errc::permission_denied, generic_category()); + } return; } // the overload that takes a hostname is really only supported when we're // using a proxy - address target = make_address(hostname, ec); + address const target = make_address(hostname, ec); if (!ec) send(udp::endpoint(target, std::uint16_t(port)), p, ec, flags); } @@ -264,21 +279,26 @@ void udp_socket::send(udp::endpoint const& ep, span p return; } - const bool allow_proxy + bool const use_proxy = ((flags & peer_connection) && m_proxy_settings.proxy_peer_connections) || ((flags & tracker_connection) && m_proxy_settings.proxy_tracker_connections) || !(flags & (tracker_connection | peer_connection)) ; - if (allow_proxy && m_socks5_connection && m_socks5_connection->active()) + if (use_proxy && m_proxy_settings.type != settings_pack::none) { - // send udp packets through SOCKS5 server - wrap(ep, p, ec, flags); + if (m_socks5_connection && m_socks5_connection->active()) + { + // send udp packets through SOCKS5 server + wrap(ep, p, ec, flags); + } + else + { + ec = error_code(boost::system::errc::permission_denied, generic_category()); + } return; } - if (m_force_proxy) return; - // set the DF flag for the socket and clear it again in the destructor set_dont_frag df(m_socket, (flags & dont_fragment) && is_v4(ep)); @@ -314,7 +334,6 @@ void udp_socket::wrap(udp::endpoint const& ep, span p void udp_socket::wrap(char const* hostname, int const port, span p , error_code& ec, udp_send_flags_t const flags) { - TORRENT_UNUSED(flags); using namespace libtorrent::detail; std::array header; diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index a829ab0b4..9fa8d1589 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -91,9 +91,11 @@ namespace libtorrent { aux::session_settings const& settings = m_man.settings(); + int const proxy_type = settings.get_int(settings_pack::proxy_type); + if (settings.get_bool(settings_pack::proxy_hostnames) - && (settings.get_int(settings_pack::proxy_type) == settings_pack::socks5 - || settings.get_int(settings_pack::proxy_type) == settings_pack::socks5_pw)) + && (proxy_type == settings_pack::socks5 + || proxy_type == settings_pack::socks5_pw)) { m_hostname = hostname; m_target.port(std::uint16_t(port)); diff --git a/test/test_privacy.cpp b/test/test_privacy.cpp index 843491320..468eb6139 100644 --- a/test/test_privacy.cpp +++ b/test/test_privacy.cpp @@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/alert_types.hpp" #include "libtorrent/torrent_info.hpp" #include "libtorrent/aux_/path.hpp" +#include "libtorrent/flags.hpp" #include @@ -60,40 +61,25 @@ char const* proxy_name[] = { "i2p_proxy" }; -std::vector rejected_trackers; +using flags_t = flags::bitfield_flag; -bool alert_predicate(lt::alert const* a) -{ - anonymous_mode_alert const* am = alert_cast(a); - if (am == nullptr) return false; +constexpr flags_t expect_http_connection = 1_bit; +constexpr flags_t expect_udp_connection = 2_bit; +//constexpr flags_t expect_http_reject = 3_bit; +//constexpr flags_t expect_udp_reject = 4_bit; +constexpr flags_t expect_dht_msg = 5_bit; +constexpr flags_t expect_peer_connection = 6_bit; - if (am->kind == anonymous_mode_alert::tracker_not_anonymous) - rejected_trackers.push_back(am->str); +constexpr flags_t dont_proxy_peers = 10_bit; +constexpr flags_t dont_proxy_trackers = 11_bit; - return false; -} - -enum flags_t -{ - force_proxy_mode = 1, - expect_http_connection = 2, - expect_udp_connection = 4, - expect_http_reject = 8, - expect_udp_reject = 16, - expect_dht_msg = 32, - expect_peer_connection = 64, - expect_possible_udp_connection = 128, - expect_possible_dht_msg = 256, -}; - -session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags) +session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, flags_t const flags) { #ifdef TORRENT_DISABLE_DHT // if DHT is disabled, we won't get any requests to it flags &= ~expect_dht_msg; #endif - std::printf("\n=== TEST == proxy: %s anonymous-mode: %s\n\n" - , proxy_name[proxy_type], (flags & force_proxy_mode) ? "yes" : "no"); + std::printf("\n=== TEST == proxy: %s \n\n", proxy_name[proxy_type]); int const http_port = start_web_server(); int const udp_port = start_udp_tracker(); int const dht_port = start_dht(); @@ -114,7 +100,6 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags) sett.set_int(settings_pack::tracker_receive_timeout, 2); sett.set_bool(settings_pack::announce_to_all_trackers, true); sett.set_bool(settings_pack::announce_to_all_tiers, true); - sett.set_bool(settings_pack::force_proxy, flags & force_proxy_mode); sett.set_int(settings_pack::alert_mask, alert_mask); sett.set_bool(settings_pack::enable_upnp, false); sett.set_bool(settings_pack::enable_natpmp, false); @@ -138,9 +123,11 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags) // wheras in anonymous mode, we just fail sett.set_str(settings_pack::proxy_hostname, "non-existing.com"); sett.set_int(settings_pack::proxy_type, proxy_type); + sett.set_bool(settings_pack::proxy_peer_connections, !(flags & dont_proxy_peers)); + sett.set_bool(settings_pack::proxy_tracker_connections, !(flags & dont_proxy_trackers)); sett.set_int(settings_pack::proxy_port, 4444); - lt::session* s = new lt::session(sett); + std::unique_ptr s(new lt::session(sett)); error_code ec; remove_all("tmp1_privacy", ec); @@ -153,11 +140,13 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags) std::snprintf(http_tracker_url, sizeof(http_tracker_url) , "http://127.0.0.1:%d/announce", http_port); t->add_tracker(http_tracker_url, 0); + std::printf("http tracker: %s\n", http_tracker_url); char udp_tracker_url[200]; std::snprintf(udp_tracker_url, sizeof(udp_tracker_url) , "udp://127.0.0.1:%d/announce", udp_port); t->add_tracker(udp_tracker_url, 1); + std::printf("udp tracker: %s\n", udp_tracker_url); add_torrent_params addp; addp.flags &= ~torrent_flags::paused; @@ -175,50 +164,38 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags) std::printf("connect_peer: 127.0.0.1:%d\n", peer_port); h.connect_peer({address_v4::from_string("127.0.0.1"), std::uint16_t(peer_port)}); - rejected_trackers.clear(); + std::vector accepted_trackers; - const int timeout = 20; + const int timeout = 30; for (int i = 0; i < timeout; ++i) { - print_alerts(*s, "s", false, false, &alert_predicate); + print_alerts(*s, "s", false, false + , [&](lt::alert const* a) + { + if (auto const* ta = alert_cast(a)) + accepted_trackers.push_back(ta->tracker_url()); + return false; + }); std::this_thread::sleep_for(lt::milliseconds(100)); if (num_udp_announces() >= prev_udp_announces + 1 - && num_peer_hits() > 0) + && num_peer_hits() > 0 + && !accepted_trackers.empty()) break; } // we should have announced to the tracker by now - if (flags & expect_possible_udp_connection) - { - // this flag is true if we may fail open, but also might not have had - // enough time to fail yet - TEST_CHECK(num_udp_announces() == prev_udp_announces - || num_udp_announces() == prev_udp_announces + 1); - } - else - { - TEST_EQUAL(num_udp_announces(), prev_udp_announces - + ((flags & expect_udp_connection) != 0 ? 1 : 0)); - } + TEST_EQUAL(num_udp_announces(), prev_udp_announces + + ((flags & expect_udp_connection) ? 1 : 0)); - if (flags & expect_possible_udp_connection) + if (flags & expect_dht_msg) { - // this flag is true if we may fail open, but also might not have had - // enough time to fail yet - TEST_CHECK(num_dht_hits() == 0 || num_dht_hits() == 1); + TEST_CHECK(num_dht_hits() > 0); } else { - if (flags & expect_dht_msg) - { - TEST_CHECK(num_dht_hits() > 0); - } - else - { - TEST_EQUAL(num_dht_hits(), 0); - } + TEST_EQUAL(num_dht_hits(), 0); } if (flags & expect_peer_connection) @@ -230,17 +207,31 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags) TEST_EQUAL(num_peer_hits(), 0); } - if (flags & expect_udp_reject) - TEST_CHECK(std::find(rejected_trackers.begin(), rejected_trackers.end() - , udp_tracker_url) != rejected_trackers.end()); + if (flags & expect_http_connection) + { + TEST_CHECK(std::find(accepted_trackers.begin(), accepted_trackers.end() + , http_tracker_url) != accepted_trackers.end()); + } + else + { + TEST_CHECK(std::find(accepted_trackers.begin(), accepted_trackers.end() + , http_tracker_url) == accepted_trackers.end()); + } - if (flags & expect_http_reject) - TEST_CHECK(std::find(rejected_trackers.begin(), rejected_trackers.end() - , http_tracker_url) != rejected_trackers.end()); + if (flags & expect_udp_connection) + { + TEST_CHECK(std::find(accepted_trackers.begin(), accepted_trackers.end() + , udp_tracker_url) != accepted_trackers.end()); + } + else + { + TEST_CHECK(std::find(accepted_trackers.begin(), accepted_trackers.end() + , udp_tracker_url) == accepted_trackers.end()); + } std::printf("%s: ~session\n", time_now_string()); session_proxy pr = s->abort(); - delete s; + s.reset(); stop_peer(); stop_dht(); @@ -261,79 +252,88 @@ TORRENT_TEST(no_proxy) | expect_http_connection | expect_dht_msg | expect_peer_connection); } +// since we don't actually have a proxy in this test, make sure libtorrent +// doesn't send any outgoing packets to either tracker or the peer TORRENT_TEST(socks4) { - test_proxy(settings_pack::socks4, expect_udp_connection | expect_dht_msg); + test_proxy(settings_pack::socks4, {}); } TORRENT_TEST(socks5) { - test_proxy(settings_pack::socks5, expect_possible_udp_connection - | expect_possible_dht_msg); + test_proxy(settings_pack::socks5, {}); } TORRENT_TEST(socks5_pw) { - test_proxy(settings_pack::socks5_pw,expect_possible_udp_connection - | expect_possible_dht_msg); + test_proxy(settings_pack::socks5_pw, {}); } TORRENT_TEST(http) { - test_proxy(settings_pack::http, expect_udp_connection | expect_dht_msg); + test_proxy(settings_pack::http, {}); } -TORRENT_TEST(http_pt) +TORRENT_TEST(http_pw) { - test_proxy(settings_pack::http_pw, expect_udp_connection | expect_dht_msg); + test_proxy(settings_pack::http_pw, {}); +} + +// if we configure trackers to not be proxied, they should be let through +TORRENT_TEST(socks4_tracker) +{ + test_proxy(settings_pack::socks4, dont_proxy_trackers | expect_http_connection | expect_udp_connection); +} + +TORRENT_TEST(socks5_tracker) +{ + test_proxy(settings_pack::socks5, dont_proxy_trackers | expect_http_connection | expect_udp_connection); +} + +TORRENT_TEST(socks5_pw_tracker) +{ + test_proxy(settings_pack::socks5_pw, dont_proxy_trackers | expect_http_connection | expect_udp_connection); +} + +TORRENT_TEST(http_tracker) +{ + test_proxy(settings_pack::http, dont_proxy_trackers | expect_http_connection | expect_udp_connection); +} + +TORRENT_TEST(http_pw_tracker) +{ + test_proxy(settings_pack::http_pw, dont_proxy_trackers | expect_http_connection | expect_udp_connection); +} + +// if we configure peers to not be proxied, they should be let through +TORRENT_TEST(socks4_peer) +{ + test_proxy(settings_pack::socks4, dont_proxy_peers | expect_peer_connection); +} + +TORRENT_TEST(socks5_peer) +{ + test_proxy(settings_pack::socks5, dont_proxy_peers | expect_peer_connection); +} + +TORRENT_TEST(socks5_pw_peer) +{ + test_proxy(settings_pack::socks5_pw, dont_proxy_peers | expect_peer_connection); +} + +TORRENT_TEST(http_peer) +{ + test_proxy(settings_pack::http, dont_proxy_peers | expect_peer_connection); +} + +TORRENT_TEST(http_pw_peer) +{ + test_proxy(settings_pack::http_pw, dont_proxy_peers | expect_peer_connection); } #if TORRENT_USE_I2P TORRENT_TEST(i2p) { - test_proxy(settings_pack::i2p_proxy, expect_udp_connection | expect_dht_msg); -} -#endif - -// using anonymous mode - -// anonymous mode doesn't require a proxy when one isn't configured. It could be -// used with a VPN for instance. This will all changed in 1.0, where anonymous -// mode is separated from force_proxy - -TORRENT_TEST(anon_no_proxy) -{ - test_proxy(settings_pack::none, force_proxy_mode | expect_peer_connection); -} - -TORRENT_TEST(anon_socks4) -{ - test_proxy(settings_pack::socks4, force_proxy_mode | expect_udp_reject); -} - -TORRENT_TEST(anon_socks5) -{ - test_proxy(settings_pack::socks5, force_proxy_mode); -} - -TORRENT_TEST(anon_socks5_pw) -{ - test_proxy(settings_pack::socks5_pw, force_proxy_mode); -} - -TORRENT_TEST(anon_http) -{ - test_proxy(settings_pack::http, force_proxy_mode | expect_udp_reject); -} - -TORRENT_TEST(anon_http_pw) -{ - test_proxy(settings_pack::http_pw, force_proxy_mode | expect_udp_reject); -} - -#if TORRENT_USE_I2P -TORRENT_TEST(anon_i2p) -{ - test_proxy(settings_pack::i2p_proxy, force_proxy_mode); + test_proxy(settings_pack::i2p_proxy, {}); } #endif diff --git a/test/test_tracker.cpp b/test/test_tracker.cpp index 35c0aa55b..04ecddf19 100644 --- a/test/test_tracker.cpp +++ b/test/test_tracker.cpp @@ -568,7 +568,6 @@ void test_proxy(bool proxy_trackers) pack.set_int(settings_pack::tracker_completion_timeout, 2); pack.set_int(settings_pack::tracker_receive_timeout, 1); pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:39775"); - pack.set_bool(settings_pack::force_proxy, true); pack.set_str(settings_pack::proxy_hostname, "non-existing.com"); pack.set_int(settings_pack::proxy_type, settings_pack::socks5); diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index ea5c75985..98668a25b 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -181,7 +181,6 @@ void test_transfer(int proxy_type, settings_pack const& sett pack_p.set_str(settings_pack::proxy_password, "testpass"); pack_p.set_int(settings_pack::proxy_type, proxy_type); pack_p.set_int(settings_pack::proxy_port, proxy_port); - pack_p.set_bool(settings_pack::force_proxy, true); // test resetting the proxy in quick succession. // specifically the udp_socket connecting to a new