From 0d9d632465a24981d6228c9d985ee1f974bc889f Mon Sep 17 00:00:00 2001 From: arvidn Date: Tue, 25 Aug 2015 04:18:10 +0200 Subject: [PATCH 1/2] initial support for disabling proxy for tracker connections --- CMakeLists.txt | 3 +- Jamfile | 1 + include/libtorrent/Makefile.am | 1 + include/libtorrent/aux_/proxy_settings.hpp | 145 ++++++++++++++++++ include/libtorrent/aux_/session_interface.hpp | 2 +- include/libtorrent/export.hpp | 2 +- include/libtorrent/http_connection.hpp | 6 +- include/libtorrent/i2p_stream.hpp | 2 +- include/libtorrent/instantiate_connection.hpp | 15 +- include/libtorrent/session_settings.hpp | 104 +------------ include/libtorrent/settings_pack.hpp | 4 + include/libtorrent/udp_socket.hpp | 13 +- src/Makefile.am | 1 + src/http_connection.cpp | 15 +- src/http_tracker_connection.cpp | 5 +- src/i2p_stream.cpp | 4 +- src/instantiate_connection.cpp | 10 +- src/proxy_settings.cpp | 78 ++++++++++ src/session_impl.cpp | 29 +--- src/settings_pack.cpp | 1 + src/torrent.cpp | 16 +- src/udp_socket.cpp | 12 +- src/udp_tracker_connection.cpp | 19 ++- src/utp_socket_manager.cpp | 4 +- test/test_http_connection.cpp | 4 +- 25 files changed, 318 insertions(+), 178 deletions(-) create mode 100644 include/libtorrent/aux_/proxy_settings.hpp create mode 100644 src/proxy_settings.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8870c1b04..ff0e20512 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,10 +69,11 @@ set(sources session_handle session_impl session_settings + proxy_settings session_stats settings_pack socket_io - socket_type + socket_type socks5_stream stat stat_cache diff --git a/Jamfile b/Jamfile index 742a76009..93ccf158d 100644 --- a/Jamfile +++ b/Jamfile @@ -694,6 +694,7 @@ SOURCES = performance_counters resolver session_settings + proxy_settings file_progress # -- extensions -- diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index e7a2b7402..e927b7eb5 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -166,6 +166,7 @@ nobase_include_HEADERS = \ aux_/session_call.hpp \ aux_/session_impl.hpp \ aux_/session_settings.hpp \ + aux_/proxy_settings.hpp \ aux_/session_interface.hpp \ aux_/time.hpp \ aux_/file_progress.hpp \ diff --git a/include/libtorrent/aux_/proxy_settings.hpp b/include/libtorrent/aux_/proxy_settings.hpp new file mode 100644 index 000000000..dbaa15467 --- /dev/null +++ b/include/libtorrent/aux_/proxy_settings.hpp @@ -0,0 +1,145 @@ +/* + +Copyright (c) 2003-2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_PROXY_SETTINGS_HPP_INCLUDED +#define TORRENT_PROXY_SETTINGS_HPP_INCLUDED + +#include "libtorrent/version.hpp" +#include "libtorrent/config.hpp" + +#include +#include + +namespace libtorrent { +struct settings_pack; +namespace aux { + + struct session_settings; + + // The ``proxy_settings`` structs contains the information needed to + // direct certain traffic to a proxy. + struct TORRENT_DEPRECATED_EXPORT proxy_settings + { + // defaults constructs proxy settings, initializing it to the default + // settings. + proxy_settings(); + + // construct the proxy_settings object from the settings + // this constructor is implemented in session_impl.cpp + proxy_settings(settings_pack const& sett); + proxy_settings(aux::session_settings const& sett); + + // the name or IP of the proxy server. ``port`` is the port number the + // proxy listens to. If required, ``username`` and ``password`` can be + // set to authenticate with the proxy. + std::string hostname; + + // when using a proy type that requires authentication, the username + // and password fields must be set to the credentials for the proxy. + std::string username; + std::string password; + +#ifndef TORRENT_NO_DEPRECATE + // the type of proxy to use. Assign one of these to the + // proxy_settings::type field. + enum proxy_type + { + // This is the default, no proxy server is used, all other fields are + // ignored. + none, + + // The server is assumed to be a `SOCKS4 server`_ that requires a + // username. + // + // .. _`SOCKS4 server`: http://www.ufasoft.com/doc/socks4_protocol.htm + socks4, + + // The server is assumed to be a SOCKS5 server (`RFC 1928`_) that does + // not require any authentication. The username and password are + // ignored. + // + // .. _`RFC 1928`: http://www.faqs.org/rfcs/rfc1928.html + socks5, + + // The server is assumed to be a SOCKS5 server that supports plain + // text username and password authentication (`RFC 1929`_). The + // username and password specified may be sent to the proxy if it + // requires. + // + // .. _`RFC 1929`: http://www.faqs.org/rfcs/rfc1929.html + socks5_pw, + + // The server is assumed to be an HTTP proxy. If the transport used + // for the connection is non-HTTP, the server is assumed to support + // the CONNECT_ method. i.e. for web seeds and HTTP trackers, a plain + // proxy will suffice. The proxy is assumed to not require + // authorization. The username and password will not be used. + // + // .. _CONNECT: http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 + http, + + // The server is assumed to be an HTTP proxy that requires user + // authorization. The username and password will be sent to the proxy. + http_pw, + + // route through an i2p SAM proxy + i2p_proxy + }; +#endif + + // tells libtorrent what kind of proxy server it is. See proxy_type + // enum for options + boost::uint8_t type; + + // the port the proxy server is running on + boost::uint16_t port; + + // defaults to true. It means that hostnames should be attempted to be + // resolved through the proxy instead of using the local DNS service. + // This is only supported by SOCKS5 and HTTP. + bool proxy_hostnames; + + // determines whether or not to excempt peer and web seed connections + // from using the proxy. This defaults to true, i.e. peer connections are + // proxied by default. + bool proxy_peer_connections; + + // if true, tracker connections are subject to the proxy settings + bool proxy_tracker_connections; + }; + + +} +} + +#endif + diff --git a/include/libtorrent/aux_/session_interface.hpp b/include/libtorrent/aux_/session_interface.hpp index 7d1e0a5db..4d6a8b9cd 100644 --- a/include/libtorrent/aux_/session_interface.hpp +++ b/include/libtorrent/aux_/session_interface.hpp @@ -64,7 +64,6 @@ namespace libtorrent { class peer_connection; class torrent; - struct proxy_settings; struct socket_job; #ifndef TORRENT_NO_DEPRECATE struct pe_settings; @@ -101,6 +100,7 @@ namespace libtorrent namespace libtorrent { namespace aux { + struct proxy_settings; struct session_settings; #if !defined TORRENT_DISABLE_LOGGING || TORRENT_USE_ASSERTS diff --git a/include/libtorrent/export.hpp b/include/libtorrent/export.hpp index 2bafcdc76..618ab51c9 100644 --- a/include/libtorrent/export.hpp +++ b/include/libtorrent/export.hpp @@ -87,7 +87,7 @@ POSSIBILITY OF SUCH DAMAGE. // only export this type if deprecated functions are enabled #ifdef TORRENT_NO_DEPRECATE -#define TORRENT_DEPRECATED_EXPORT +#define TORRENT_DEPRECATED_EXPORT TORRENT_EXTRA_EXPORT #else #define TORRENT_DEPRECATED_EXPORT TORRENT_EXPORT #endif diff --git a/include/libtorrent/http_connection.hpp b/include/libtorrent/http_connection.hpp index d6945e6e0..07b817144 100644 --- a/include/libtorrent/http_connection.hpp +++ b/include/libtorrent/http_connection.hpp @@ -104,7 +104,7 @@ struct TORRENT_EXTRA_EXPORT http_connection std::string m_sendbuffer; void get(std::string const& url, time_duration timeout = seconds(30) - , int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5 + , int prio = 0, aux::proxy_settings const* ps = 0, int handle_redirects = 5 , std::string const& user_agent = std::string() , address const& bind_addr = address_v4::any() , int resolve_flags = 0, std::string const& auth_ = std::string() @@ -114,7 +114,7 @@ struct TORRENT_EXTRA_EXPORT http_connection ); void start(std::string const& hostname, int port - , time_duration timeout, int prio = 0, proxy_settings const* ps = 0 + , time_duration timeout, int prio = 0, aux::proxy_settings const* ps = 0 , bool ssl = false, int handle_redirect = 5 , address const& bind_addr = address_v4::any() , int resolve_flags = 0 @@ -186,7 +186,7 @@ private: // specifies whether or not the connection is // configured to use a proxy - proxy_settings m_proxy; + aux::proxy_settings m_proxy; // the address to bind to. address_v4::any() // means do not bind diff --git a/include/libtorrent/i2p_stream.hpp b/include/libtorrent/i2p_stream.hpp index 4f52691ea..f55e68f4c 100644 --- a/include/libtorrent/i2p_stream.hpp +++ b/include/libtorrent/i2p_stream.hpp @@ -169,7 +169,7 @@ public: i2p_connection(io_service& ios); ~i2p_connection(); - proxy_settings proxy() const; + aux::proxy_settings proxy() const; bool is_open() const { diff --git a/include/libtorrent/instantiate_connection.hpp b/include/libtorrent/instantiate_connection.hpp index 7355ffd30..78ee64698 100644 --- a/include/libtorrent/instantiate_connection.hpp +++ b/include/libtorrent/instantiate_connection.hpp @@ -34,20 +34,23 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_INSTANTIATE_CONNECTION #include "libtorrent/socket_type.hpp" -#include namespace libtorrent { - struct proxy_settings; + namespace aux { + struct proxy_settings; + } + struct utp_socket_manager; struct socket_type; // instantiate a socket_type (s) according to the specified criteria TORRENT_EXTRA_EXPORT bool instantiate_connection(io_service& ios - , proxy_settings const& ps, socket_type& s - , void* ssl_context = 0 - , utp_socket_manager* sm = 0 - , bool peer_connection = false); + , aux::proxy_settings const& ps, socket_type& s + , void* ssl_context + , utp_socket_manager* sm + , bool peer_connection + , bool tracker_connection); } #endif diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index b1b3a3e37..973022efc 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/version.hpp" #include "libtorrent/config.hpp" #include "libtorrent/settings_pack.hpp" +#include "libtorrent/aux_/proxy_settings.hpp" #include #include @@ -46,109 +47,8 @@ namespace libtorrent { #ifndef TORRENT_NO_DEPRECATE -#define TORRENT_EXPORT_DEPRECATED TORRENT_EXPORT -#else -#define TORRENT_EXPORT_DEPRECATED -#endif - namespace aux { struct session_settings; } - - // TODO: 2 this type is only used internally now. move it to an internal - // header and make this type properly deprecated. - - // The ``proxy_settings`` structs contains the information needed to - // direct certain traffic to a proxy. - struct TORRENT_EXPORT_DEPRECATED proxy_settings - { - // defaults constructs proxy settings, initializing it to the default - // settings. - proxy_settings() : type(0) - , port(0), proxy_hostnames(true) - , proxy_peer_connections(true) - {} - - // construct the proxy_settings object from the settings - // this constructor is implemented in session_impl.cpp - proxy_settings(settings_pack const& sett); - proxy_settings(aux::session_settings const& sett); - - // the name or IP of the proxy server. ``port`` is the port number the - // proxy listens to. If required, ``username`` and ``password`` can be - // set to authenticate with the proxy. - std::string hostname; - - // when using a proy type that requires authentication, the username - // and password fields must be set to the credentials for the proxy. - std::string username; - std::string password; - -#ifndef TORRENT_NO_DEPRECATE - // the type of proxy to use. Assign one of these to the - // proxy_settings::type field. - enum proxy_type - { - // This is the default, no proxy server is used, all other fields are - // ignored. - none, - - // The server is assumed to be a `SOCKS4 server`_ that requires a - // username. - // - // .. _`SOCKS4 server`: http://www.ufasoft.com/doc/socks4_protocol.htm - socks4, - - // The server is assumed to be a SOCKS5 server (`RFC 1928`_) that does - // not require any authentication. The username and password are - // ignored. - // - // .. _`RFC 1928`: http://www.faqs.org/rfcs/rfc1928.html - socks5, - - // The server is assumed to be a SOCKS5 server that supports plain - // text username and password authentication (`RFC 1929`_). The - // username and password specified may be sent to the proxy if it - // requires. - // - // .. _`RFC 1929`: http://www.faqs.org/rfcs/rfc1929.html - socks5_pw, - - // The server is assumed to be an HTTP proxy. If the transport used - // for the connection is non-HTTP, the server is assumed to support - // the CONNECT_ method. i.e. for web seeds and HTTP trackers, a plain - // proxy will suffice. The proxy is assumed to not require - // authorization. The username and password will not be used. - // - // .. _CONNECT: http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 - http, - - // The server is assumed to be an HTTP proxy that requires user - // authorization. The username and password will be sent to the proxy. - http_pw, - - // route through an i2p SAM proxy - i2p_proxy - }; -#endif - - // tells libtorrent what kind of proxy server it is. See proxy_type - // enum for options - boost::uint8_t type; - - // the port the proxy server is running on - boost::uint16_t port; - - // defaults to true. It means that hostnames should be attempted to be - // resolved through the proxy instead of using the local DNS service. - // This is only supported by SOCKS5 and HTTP. - bool proxy_hostnames; - - // determines whether or not to excempt peer and web seed connections - // from using the proxy. This defaults to true, i.e. peer connections are - // proxied by default. - bool proxy_peer_connections; - }; - -#ifndef TORRENT_NO_DEPRECATE + typedef aux::proxy_settings proxy_settings; // This holds most of the session-wide settings in libtorrent. Pass this // to session::set_settings() to change the settings, initialize it from diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 98264799a..8236ff3d9 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -644,6 +644,10 @@ namespace libtorrent // unlikely to matter anyway auto_sequential, + // if true, trackerconnections are made over the configured proxy, if + // any. + proxy_tracker_connections, + max_bool_setting_internal }; diff --git a/include/libtorrent/udp_socket.hpp b/include/libtorrent/udp_socket.hpp index 17ac07ece..cb3c47c2a 100644 --- a/include/libtorrent/udp_socket.hpp +++ b/include/libtorrent/udp_socket.hpp @@ -71,7 +71,12 @@ namespace libtorrent udp_socket(io_service& ios); ~udp_socket(); - enum flags_t { dont_drop = 1, peer_connection = 2, dont_queue = 4 }; + enum flags_t { + dont_drop = 1 + , peer_connection = 2 + , tracker_connection = 4 + , dont_queue = 8 + }; bool is_open() const { @@ -96,8 +101,8 @@ namespace libtorrent void close(); int local_port() const { return m_bind_port; } - void set_proxy_settings(proxy_settings const& ps); - proxy_settings const& get_proxy_settings() { return m_proxy_settings; } + 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; } @@ -236,7 +241,7 @@ namespace libtorrent #endif tcp::socket m_socks5_sock; - proxy_settings m_proxy_settings; + aux::proxy_settings m_proxy_settings; tcp::resolver m_resolver; char m_tmp_buf[270]; bool m_queue_packets; diff --git a/src/Makefile.am b/src/Makefile.am index cf04bd518..8ddfb8d52 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -108,6 +108,7 @@ libtorrent_rasterbar_la_SOURCES = \ session_handle.cpp \ session_impl.cpp \ session_settings.cpp \ + proxy_settings.cpp \ settings_pack.cpp \ sha1.cpp \ smart_ban.cpp \ diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 4f6c375cc..e7cebbb86 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -108,7 +108,7 @@ http_connection::~http_connection() } void http_connection::get(std::string const& url, time_duration timeout, int prio - , proxy_settings const* ps, int handle_redirects, std::string const& user_agent + , aux::proxy_settings const* ps, int handle_redirects, std::string const& user_agent , address const& bind_addr, int resolve_flags, std::string const& auth_ #if TORRENT_USE_I2P , i2p_connection* i2p_conn @@ -223,7 +223,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri } void http_connection::start(std::string const& hostname, int port - , time_duration timeout, int prio, proxy_settings const* ps, bool ssl + , time_duration timeout, int prio, aux::proxy_settings const* ps, bool ssl , int handle_redirects , address const& bind_addr , int resolve_flags @@ -307,9 +307,9 @@ void http_connection::start(std::string const& hostname, int port } #endif - proxy_settings const* proxy = ps; + aux::proxy_settings const* proxy = ps; #if TORRENT_USE_I2P - proxy_settings i2p_proxy; + aux::proxy_settings i2p_proxy; if (is_i2p) { i2p_proxy = i2p_conn->proxy(); @@ -326,7 +326,7 @@ void http_connection::start(std::string const& hostname, int port { proxy = 0; } - proxy_settings null_proxy; + aux::proxy_settings null_proxy; void* userdata = 0; #ifdef TORRENT_USE_OPENSSL @@ -347,8 +347,11 @@ void http_connection::start(std::string const& hostname, int port userdata = m_ssl_ctx; } #endif + // assume this is not a tracker connection. Tracker connections that + // shouldn't be subject to the proxy should pass in NULL as the proxy + // pointer. instantiate_connection(m_timer.get_io_service() - , proxy ? *proxy : null_proxy, m_sock, userdata); + , proxy ? *proxy : null_proxy, m_sock, userdata, NULL, false, false); if (m_bind_addr != address_v4::any()) { diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index 694d546b8..f02908ae9 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -215,10 +215,11 @@ namespace libtorrent // to avoid being blocked for slow or failing responses. Chances // are that we're shutting down, and this should be a best-effort // attempt. It's not worth stalling shutdown. - proxy_settings ps(settings); + aux::proxy_settings ps(settings); m_tracker_connection->get(url, seconds(timeout) , tracker_req().event == tracker_request::stopped ? 2 : 1 - , &ps, 5, settings.get_bool(settings_pack::anonymous_mode) + , ps.proxy_tracker_connections ? &ps : NULL + , 5, settings.get_bool(settings_pack::anonymous_mode) ? "" : settings.get_str(settings_pack::user_agent) , bind_interface() , tracker_req().event == tracker_request::stopped diff --git a/src/i2p_stream.cpp b/src/i2p_stream.cpp index a33123e97..efac7b964 100644 --- a/src/i2p_stream.cpp +++ b/src/i2p_stream.cpp @@ -105,9 +105,9 @@ namespace libtorrent if (m_sam_socket) m_sam_socket->close(e); } - proxy_settings i2p_connection::proxy() const + aux::proxy_settings i2p_connection::proxy() const { - proxy_settings ret; + aux::proxy_settings ret; ret.hostname = m_hostname; ret.port = m_port; ret.type = settings_pack::i2p_proxy; diff --git a/src/instantiate_connection.cpp b/src/instantiate_connection.cpp index 07180f002..97271540d 100644 --- a/src/instantiate_connection.cpp +++ b/src/instantiate_connection.cpp @@ -40,11 +40,14 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { + // TODO: 2 peer_connection and tracker_connection should probably be flags + // TODO: 2 move this function into libtorrent::aux namespace bool instantiate_connection(io_service& ios - , proxy_settings const& ps, socket_type& s + , aux::proxy_settings const& ps, socket_type& s , void* ssl_context , utp_socket_manager* sm - , bool peer_connection) + , bool peer_connection + , bool tracker_connection) { #ifndef TORRENT_USE_OPENSSL TORRENT_UNUSED(ssl_context); @@ -77,7 +80,8 @@ namespace libtorrent } #endif else if (ps.type == settings_pack::none - || (peer_connection && !ps.proxy_peer_connections)) + || (peer_connection && !ps.proxy_peer_connections) + || (tracker_connection && !ps.proxy_tracker_connections)) { #ifdef TORRENT_USE_OPENSSL if (ssl_context) diff --git a/src/proxy_settings.cpp b/src/proxy_settings.cpp new file mode 100644 index 000000000..85e1bda6d --- /dev/null +++ b/src/proxy_settings.cpp @@ -0,0 +1,78 @@ +/* + +Copyright (c) 2003-2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "libtorrent/aux_/proxy_settings.hpp" +#include "libtorrent/settings_pack.hpp" +#include "libtorrent/aux_/session_settings.hpp" + +namespace libtorrent { +namespace aux { + +proxy_settings::proxy_settings() + : type(0) + , port(0) + , proxy_hostnames(true) + , proxy_peer_connections(true) + , proxy_tracker_connections(true) +{} + +proxy_settings::proxy_settings(settings_pack const& sett) +{ + hostname = sett.get_str(settings_pack::proxy_hostname); + username = sett.get_str(settings_pack::proxy_username); + password = sett.get_str(settings_pack::proxy_password); + type = sett.get_int(settings_pack::proxy_type); + port = sett.get_int(settings_pack::proxy_port); + proxy_hostnames = sett.get_bool(settings_pack::proxy_hostnames); + proxy_peer_connections = sett.get_bool( + settings_pack::proxy_peer_connections); + proxy_tracker_connections = sett.get_bool( + settings_pack::proxy_tracker_connections); +} + +proxy_settings::proxy_settings(aux::session_settings const& sett) +{ + hostname = sett.get_str(settings_pack::proxy_hostname); + username = sett.get_str(settings_pack::proxy_username); + password = sett.get_str(settings_pack::proxy_password); + type = sett.get_int(settings_pack::proxy_type); + port = sett.get_int(settings_pack::proxy_port); + proxy_hostnames = sett.get_bool(settings_pack::proxy_hostnames); + proxy_peer_connections = sett.get_bool( + settings_pack::proxy_peer_connections); + proxy_tracker_connections = sett.get_bool( + settings_pack::proxy_tracker_connections); +} + +} // namespace aux +} // namespace libtorrent + diff --git a/src/session_impl.cpp b/src/session_impl.cpp index dd9640098..527d6fdac 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -220,31 +220,6 @@ void network_thread_pool::process_job(socket_job const& j, bool post) } } -// TODO: 2 find a better place for this function -proxy_settings::proxy_settings(settings_pack const& sett) -{ - hostname = sett.get_str(settings_pack::proxy_hostname); - username = sett.get_str(settings_pack::proxy_username); - password = sett.get_str(settings_pack::proxy_password); - type = sett.get_int(settings_pack::proxy_type); - port = sett.get_int(settings_pack::proxy_port); - proxy_hostnames = sett.get_bool(settings_pack::proxy_hostnames); - proxy_peer_connections = sett.get_bool( - settings_pack::proxy_peer_connections); -} - -proxy_settings::proxy_settings(aux::session_settings const& sett) -{ - hostname = sett.get_str(settings_pack::proxy_hostname); - username = sett.get_str(settings_pack::proxy_username); - password = sett.get_str(settings_pack::proxy_password); - type = sett.get_int(settings_pack::proxy_type); - port = sett.get_int(settings_pack::proxy_port); - proxy_hostnames = sett.get_bool(settings_pack::proxy_hostnames); - proxy_peer_connections = sett.get_bool( - settings_pack::proxy_peer_connections); -} - namespace aux { void session_impl::init_peer_class_filter(bool unlimited_local) @@ -2125,7 +2100,7 @@ retry: m_socks_listen_socket = boost::shared_ptr(new socket_type(m_io_service)); bool ret = instantiate_connection(m_io_service, proxy() - , *m_socks_listen_socket); + , *m_socks_listen_socket, NULL, NULL, false, false); TORRENT_ASSERT_VAL(ret, ret); TORRENT_UNUSED(ret); @@ -2197,7 +2172,7 @@ retry: m_i2p_listen_socket = boost::shared_ptr(new socket_type(m_io_service)); bool ret = instantiate_connection(m_io_service, m_i2p_conn.proxy() - , *m_i2p_listen_socket); + , *m_i2p_listen_socket, NULL, NULL, true, false); TORRENT_ASSERT_VAL(ret, ret); TORRENT_UNUSED(ret); diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 491b00391..071998343 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -211,6 +211,7 @@ namespace libtorrent SET_NOPREV(proxy_hostnames, true, 0), SET_NOPREV(proxy_peer_connections, true, 0), SET_NOPREV(auto_sequential, true, &session_impl::update_auto_sequential), + SET_NOPREV(proxy_tracker_connections, true, 0), }; int_setting_entry_t int_settings[settings_pack::num_int_settings] = diff --git a/src/torrent.cpp b/src/torrent.cpp index 8843bb7af..9aafa1d3b 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -863,7 +863,7 @@ namespace libtorrent , m_ssl_ctx.get() #endif )); - proxy_settings ps = m_ses.proxy(); + aux::proxy_settings ps = m_ses.proxy(); conn->get(m_url, seconds(30), 0, &ps , 5, settings().get_str(settings_pack::user_agent)); set_state(torrent_status::downloading_metadata); @@ -6198,7 +6198,7 @@ namespace libtorrent return; } - proxy_settings const& ps = m_ses.proxy(); + aux::proxy_settings const& ps = m_ses.proxy(); if (ps.type == settings_pack::http || ps.type == settings_pack::http_pw) { @@ -6410,7 +6410,8 @@ namespace libtorrent if (!userdata) userdata = m_ses.ssl_ctx(); } #endif - bool ret = instantiate_connection(m_ses.get_io_service(), m_ses.proxy(), *s, userdata, 0, true); + bool ret = instantiate_connection(m_ses.get_io_service(), m_ses.proxy() + , *s, userdata, 0, true, false); (void)ret; TORRENT_ASSERT(ret); @@ -7515,7 +7516,12 @@ namespace libtorrent return false; } - bool ret = instantiate_connection(m_ses.get_io_service(), m_ses.i2p_proxy(), *s); + // It's not entirely obvious why this peer connection is not marked as + // one. The main feature of a peer connection is that whether or not we + // proxy it is configurable. When we use i2p, we want to always prox + // everything via i2p. + bool ret = instantiate_connection(m_ses.get_io_service() + , m_ses.i2p_proxy(), *s, NULL, NULL, false, false); (void)ret; TORRENT_ASSERT(ret); s->get()->set_destination(static_cast(peerinfo)->destination); @@ -7556,7 +7562,7 @@ namespace libtorrent #endif bool ret = instantiate_connection(m_ses.get_io_service() - , m_ses.proxy(), *s, userdata, sm, true); + , m_ses.proxy(), *s, userdata, sm, true, false); (void)ret; TORRENT_ASSERT(ret); diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 16c378729..d8453b3f0 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -180,7 +180,13 @@ void udp_socket::send(udp::endpoint const& ep, char const* p, int len return; } - if (!(flags & peer_connection) || m_proxy_settings.proxy_peer_connections) + const bool allow_proxy + = ((flags & peer_connection) && m_proxy_settings.proxy_peer_connections) + || ((flags & tracker_connection) && m_proxy_settings.proxy_tracker_connections) + || (flags & (tracker_connection | peer_connection)) == 0 + ; + + if (allow_proxy) { if (m_tunnel_packets) { @@ -770,7 +776,7 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec) m_bind_port = ep.port(); } -void udp_socket::set_proxy_settings(proxy_settings const& ps) +void udp_socket::set_proxy_settings(aux::proxy_settings const& ps) { CHECK_MAGIC; TORRENT_ASSERT(is_single_thread()); @@ -838,7 +844,7 @@ void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) // if we can't connect to the proxy, and // we're not in privacy mode, try to just // not use a proxy - m_proxy_settings = proxy_settings(); + m_proxy_settings = aux::proxy_settings(); m_tunnel_packets = false; } diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 92cbb44e6..eb23a2ab3 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -504,12 +504,13 @@ namespace libtorrent if (!m_hostname.empty()) { m_man.get_udp_socket().send_hostname(m_hostname.c_str() - , m_target.port(), buf, 16, ec); + , m_target.port(), buf, 16, ec + , udp_socket::tracker_connection); } else { - m_man.get_udp_socket().send(m_target, buf, 16, ec); - + m_man.get_udp_socket().send(m_target, buf, 16, ec + , udp_socket::tracker_connection); } ++m_attempts; @@ -566,11 +567,13 @@ namespace libtorrent error_code ec; if (!m_hostname.empty()) { - m_man.get_udp_socket().send_hostname(m_hostname.c_str(), m_target.port(), buf, sizeof(buf), ec); + m_man.get_udp_socket().send_hostname(m_hostname.c_str(), m_target.port() + , buf, sizeof(buf), ec, udp_socket::tracker_connection); } else { - m_man.get_udp_socket().send(m_target, buf, sizeof(buf), ec); + m_man.get_udp_socket().send(m_target, buf, sizeof(buf), ec + , udp_socket::tracker_connection); } m_state = action_scrape; sent_bytes(sizeof(buf) + 28); // assuming UDP/IP header @@ -764,11 +767,13 @@ namespace libtorrent if (!m_hostname.empty()) { m_man.get_udp_socket().send_hostname(m_hostname.c_str() - , m_target.port(), buf, out - buf, ec); + , m_target.port(), buf, out - buf, ec + , udp_socket::tracker_connection); } else { - m_man.get_udp_socket().send(m_target, buf, out - buf, ec); + m_man.get_udp_socket().send(m_target, buf, out - buf, ec + , udp_socket::tracker_connection); } m_state = action_announce; sent_bytes(out - buf + 28); // assuming UDP/IP header diff --git a/src/utp_socket_manager.cpp b/src/utp_socket_manager.cpp index a84d1b9f6..d5705c01e 100644 --- a/src/utp_socket_manager.cpp +++ b/src/utp_socket_manager.cpp @@ -292,8 +292,8 @@ namespace libtorrent // create the new socket with this ID m_new_connection = id; - instantiate_connection(m_sock.get_io_service(), proxy_settings(), *c - , m_ssl_context, this, true); + instantiate_connection(m_sock.get_io_service(), aux::proxy_settings(), *c + , m_ssl_context, this, true, false); utp_stream* str = NULL; diff --git a/test/test_http_connection.cpp b/test/test_http_connection.cpp index 7f0018581..a69172a26 100644 --- a/test/test_http_connection.cpp +++ b/test/test_http_connection.cpp @@ -106,7 +106,7 @@ void reset_globals() } void run_test(std::string const& url, int size, int status, int connected - , boost::optional ec, proxy_settings const& ps + , boost::optional ec, aux::proxy_settings const& ps , std::string const& auth = std::string()) { reset_globals(); @@ -174,7 +174,7 @@ void run_suite(std::string const& protocol , flags & flag_chunked_encoding , flags & flag_keepalive); - proxy_settings ps; + aux::proxy_settings ps; ps.hostname = "127.0.0.1"; ps.username = "testuser"; ps.password = "testpass"; From 1142903d90c2c2521c2b6f53abfe0b852b03ec47 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sat, 29 Aug 2015 16:25:00 -0400 Subject: [PATCH 2/2] add unit test for new tracker proxy option --- ChangeLog | 1 + test/test_tracker.cpp | 76 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0461d05e2..488ab6c59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * add option to not proxy tracker connections through proxy * removed sparse-regions feature * support using 0 disk threads (to perform disk I/O in network thread) * removed deprecated handle_alert template diff --git a/test/test_tracker.cpp b/test/test_tracker.cpp index 363dfa012..a8af5fd1b 100644 --- a/test/test_tracker.cpp +++ b/test/test_tracker.cpp @@ -471,12 +471,13 @@ TORRENT_TEST(try_next) TEST_EQUAL(tr[1].fails, 1); TEST_EQUAL(tr[1].verified, false); - TEST_CHECK(tr[1].last_error == boost::asio::error::timed_out + const bool tracker_error = tr[1].last_error == boost::asio::error::timed_out || tr[1].last_error == boost::system::error_condition(boost::system::errc::connection_refused) #ifdef TORRENT_WINDOWS - || tr[1].last_error == boost::system::error_code(boost::system::system_category(), ERROR_CONNECTION_REFUSED) + || tr[1].last_error == boost::system::error_code(ERROR_CONNECTION_REFUSED, boost::system::system_category()) #endif - ); + ; + TEST_EQUAL(tracker_error, true); TEST_EQUAL(tr[2].fails, 0); TEST_EQUAL(tr[2].verified, true); @@ -567,3 +568,72 @@ TORRENT_TEST(http_peers) fprintf(stderr, "done\n"); } +void test_proxy(bool proxy_trackers) +{ + int http_port = start_web_server(); + + settings_pack pack = settings(); + pack.set_bool(settings_pack::announce_to_all_trackers, true); + pack.set_bool(settings_pack::announce_to_all_tiers, false); + 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); + pack.set_int(settings_pack::proxy_port, 4444); + pack.set_bool(settings_pack::proxy_tracker_connections, proxy_trackers); + + boost::scoped_ptr s(new lt::session(pack)); + + error_code ec; + remove_all("tmp2_tracker", ec); + create_directory("tmp2_tracker", ec); + std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str()); + boost::shared_ptr t = ::create_torrent(&file, 16 * 1024, 13, false); + file.close(); + + char tracker_url[200]; + // and this should not be announced to (since the one before it succeeded) + snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce" + , http_port); + t->add_tracker(tracker_url, 0); + + add_torrent_params addp; + addp.flags &= ~add_torrent_params::flag_paused; + addp.flags &= ~add_torrent_params::flag_auto_managed; + addp.flags |= add_torrent_params::flag_seed_mode; + addp.ti = t; + addp.save_path = "tmp2_tracker"; + torrent_handle h = s->add_torrent(addp); + + // wait to hit the tracker + const alert* a = wait_for_alert(*s, tracker_reply_alert::alert_type, "s"); + if (proxy_trackers) + { + TEST_CHECK(a == NULL); + } + else + { + TEST_CHECK(a != NULL); + } + + fprintf(stderr, "destructing session\n"); + s.reset(); + fprintf(stderr, "done\n"); + + fprintf(stderr, "stop_web_server\n"); + stop_web_server(); + fprintf(stderr, "done\n"); +} + +TORRENT_TEST(tracker_proxy) +{ + fprintf(stderr, "\n\nnot proxying tracker connections (expect to reach the tracker)\n\n"); + test_proxy(false); + + fprintf(stderr, "\n\nproxying tracker connections through non-existent proxy (do not expect to reach the tracker)\n\n"); + test_proxy(true); +} +