From 7bd25edc9d1396ce1dc42898dd9e13ee5bbae261 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 12 Oct 2010 08:57:43 +0000 Subject: [PATCH] generalize SSL support to also include web seeds (and in theory regular peers) --- ChangeLog | 1 + include/libtorrent/Makefile.am | 1 - include/libtorrent/aux_/session_impl.hpp | 8 + include/libtorrent/http_connection.hpp | 29 +- include/libtorrent/instantiate_connection.hpp | 3 +- include/libtorrent/max.hpp | 12 + include/libtorrent/proxy_base.hpp | 12 + include/libtorrent/socket_type.hpp | 113 ++- include/libtorrent/ssl_stream.hpp | 40 +- include/libtorrent/variant_stream.hpp | 790 ------------------ include/libtorrent/web_connection_base.hpp | 3 + src/http_connection.cpp | 65 +- src/http_seed_connection.cpp | 4 +- src/instantiate_connection.cpp | 50 +- src/session_impl.cpp | 11 +- src/socket_type.cpp | 51 +- src/torrent.cpp | 25 +- src/web_connection_base.cpp | 5 + src/web_peer_connection.cpp | 4 +- test/setup_transfer.cpp | 59 +- test/test_web_seed.cpp | 25 +- 21 files changed, 374 insertions(+), 937 deletions(-) delete mode 100644 include/libtorrent/variant_stream.hpp diff --git a/ChangeLog b/ChangeLog index 155ee6d55..0bb9c06c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * support SSL for web seeds, through all proxies * support extending web seeds with custom authorization and extra headers * settings that are not changed from the default values are not saved in the session state diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 92033b0bb..34b232dac 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -100,7 +100,6 @@ nobase_include_HEADERS = \ union_endpoint.hpp \ upnp.hpp \ utf8.hpp \ - variant_stream.hpp \ version.hpp \ web_peer_connection.hpp \ xml_parse.hpp \ diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 2d1ae599a..717f46d08 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -91,6 +91,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/peer_connection.hpp" #endif +#ifdef TORRENT_USE_OPENSSL +#include +#endif + namespace libtorrent { @@ -476,6 +480,10 @@ namespace libtorrent // them mutable io_service m_io_service; +#ifdef TORRENT_USE_OPENSSL + asio::ssl::context m_ssl_ctx; +#endif + // handles delayed alerts alert_manager m_alerts; diff --git a/include/libtorrent/http_connection.hpp b/include/libtorrent/http_connection.hpp index f40798426..ba76c6cd3 100644 --- a/include/libtorrent/http_connection.hpp +++ b/include/libtorrent/http_connection.hpp @@ -52,13 +52,12 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket_type.hpp" #include "libtorrent/session_settings.hpp" -#ifdef TORRENT_USE_OPENSSL -#include "libtorrent/ssl_stream.hpp" -#include "libtorrent/variant_stream.hpp" -#endif - #include "libtorrent/i2p_stream.hpp" +#ifdef TORRENT_USE_OPENSSL +#include +#endif + namespace libtorrent { @@ -90,6 +89,9 @@ struct TORRENT_EXPORT http_connection : boost::enable_shared_from_this > const& socket() const { return m_sock; } -#else socket_type const& socket() const { return m_sock; } -#endif std::list const& endpoints() const { return m_endpoints; } @@ -159,13 +161,7 @@ private: void callback(error_code const& e, char const* data = 0, int size = 0); std::vector m_recvbuffer; -#ifdef TORRENT_USE_OPENSSL - // TODO: for proxies to work correctly over SSL, the - // ssl_stream needs to be wrapped inside the socket_type - variant_stream > m_sock; -#else socket_type m_sock; -#endif #if TORRENT_USE_I2P i2p_connection* m_i2p_conn; #endif @@ -190,6 +186,9 @@ private: std::string m_url; std::list m_endpoints; +#ifdef TORRENT_USE_OPENSSL + asio::ssl::context m_ssl_ctx; +#endif // the current download limit, in bytes per second // 0 is unlimited. diff --git a/include/libtorrent/instantiate_connection.hpp b/include/libtorrent/instantiate_connection.hpp index 26efcd6cf..d0719f38e 100644 --- a/include/libtorrent/instantiate_connection.hpp +++ b/include/libtorrent/instantiate_connection.hpp @@ -41,7 +41,8 @@ namespace libtorrent struct proxy_settings; bool instantiate_connection(io_service& ios - , proxy_settings const& ps, socket_type& s); + , proxy_settings const& ps, socket_type& s + , void* ssl_context = 0); } #endif diff --git a/include/libtorrent/max.hpp b/include/libtorrent/max.hpp index 09de9b173..64d12cd95 100644 --- a/include/libtorrent/max.hpp +++ b/include/libtorrent/max.hpp @@ -81,6 +81,18 @@ namespace libtorrent value = max3::value }; }; + + template + struct max7 + { + enum + { + temp1 = max::value, + temp2 = max::value, + temp3 = max3::value, + value = max3::value + }; + }; } #endif diff --git a/include/libtorrent/proxy_base.hpp b/include/libtorrent/proxy_base.hpp index 9ff726cde..701de8101 100644 --- a/include/libtorrent/proxy_base.hpp +++ b/include/libtorrent/proxy_base.hpp @@ -73,6 +73,12 @@ public: return m_sock.read_some(buffers, ec); } + template + std::size_t write_some(Const_Buffers const& buffers, error_code& ec) + { + return m_sock.write_some(buffers, ec); + } + std::size_t available(error_code& ec) const { return m_sock.available(ec); } @@ -86,6 +92,12 @@ public: return m_sock.read_some(buffers); } + template + std::size_t write_some(Const_Buffers const& buffers) + { + return m_sock.write_some(buffers); + } + template void io_control(IO_Control_Command& ioc) { diff --git a/include/libtorrent/socket_type.hpp b/include/libtorrent/socket_type.hpp index 8df54abb5..26ddcee78 100644 --- a/include/libtorrent/socket_type.hpp +++ b/include/libtorrent/socket_type.hpp @@ -42,36 +42,52 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/max.hpp" #include "libtorrent/assert.hpp" +#ifdef TORRENT_USE_OPENSSL +#include "libtorrent/ssl_stream.hpp" +#endif + #if TORRENT_USE_I2P -#define TORRENT_SOCKTYPE_FORWARD(x) \ - switch (m_type) { \ - case socket_type_int_impl::value: \ - get()->x; break; \ - case socket_type_int_impl::value: \ - get()->x; break; \ - case socket_type_int_impl::value: \ - get()->x; break; \ +#define TORRENT_SOCKTYPE_I2P_FORWARD(x) \ case socket_type_int_impl::value: \ - get()->x; break; \ - default: TORRENT_ASSERT(false); \ - } + get()->x; break; -#define TORRENT_SOCKTYPE_FORWARD_RET(x, def) \ - switch (m_type) { \ - case socket_type_int_impl::value: \ - return get()->x; \ - case socket_type_int_impl::value: \ - return get()->x; \ - case socket_type_int_impl::value: \ - return get()->x; \ +#define TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def) \ case socket_type_int_impl::value: \ - return get()->x; \ - default: TORRENT_ASSERT(false); return def; \ - } + return get()->x; #else // TORRENT_USE_I2P +#define TORRENT_SOCKTYPE_I2P_FORWARD(x) +#define TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def) + +#endif + +#ifdef TORRENT_USE_OPENSSL + +#define TORRENT_SOCKTYPE_SSL_FORWARD(x) \ + case socket_type_int_impl >::value: \ + get >()->x; break; \ + case socket_type_int_impl >::value: \ + get >()->x; break; \ + case socket_type_int_impl >::value: \ + get >()->x; break; + +#define TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def) \ + case socket_type_int_impl >::value: \ + return get >()->x; \ + case socket_type_int_impl >::value: \ + return get >()->x; \ + case socket_type_int_impl >::value: \ + return get >()->x; + +#else + +#define TORRENT_SOCKTYPE_SSL_FORWARD(x) +#define TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def) + +#endif + #define TORRENT_SOCKTYPE_FORWARD(x) \ switch (m_type) { \ case socket_type_int_impl::value: \ @@ -80,6 +96,8 @@ POSSIBILITY OF SUCH DAMAGE. get()->x; break; \ case socket_type_int_impl::value: \ get()->x; break; \ + TORRENT_SOCKTYPE_I2P_FORWARD(x) \ + TORRENT_SOCKTYPE_SSL_FORWARD(x) \ default: TORRENT_ASSERT(false); \ } @@ -91,11 +109,11 @@ POSSIBILITY OF SUCH DAMAGE. return get()->x; \ case socket_type_int_impl::value: \ return get()->x; \ + TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def) \ + TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def) \ default: TORRENT_ASSERT(false); return def; \ } -#endif // TORRENT_USE_I2P - namespace libtorrent { @@ -121,6 +139,20 @@ namespace libtorrent { enum { value = 4 }; }; #endif +#ifdef TORRENT_USE_OPENSSL + template <> + struct socket_type_int_impl > + { enum { value = 5 }; }; + + template <> + struct socket_type_int_impl > + { enum { value = 6 }; }; + + template <> + struct socket_type_int_impl > + { enum { value = 7 }; }; +#endif + struct TORRENT_EXPORT socket_type { typedef stream_socket::lowest_layer_type lowest_layer_type; @@ -134,7 +166,6 @@ namespace libtorrent io_service& get_io_service() const; bool is_open() const; - #ifndef BOOST_NO_EXCEPTIONS void open(protocol_type const& p); void close(); @@ -160,6 +191,10 @@ namespace libtorrent void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) { TORRENT_SOCKTYPE_FORWARD(async_read_some(buffers, handler)) } + template + std::size_t write_some(Const_Buffers const& buffers, error_code& ec) + { TORRENT_SOCKTYPE_FORWARD_RET(write_some(buffers, ec), 0) } + template void async_write_some(Const_Buffers const& buffers, Handler const& handler) { TORRENT_SOCKTYPE_FORWARD(async_write_some(buffers, handler)) } @@ -193,36 +228,50 @@ namespace libtorrent { TORRENT_SOCKTYPE_FORWARD_RET(set_option(opt, ec), ec) } template - void instantiate(io_service& ios) + void instantiate(io_service& ios, void* userdata = 0) { TORRENT_ASSERT(&ios == &m_io_service); - construct(socket_type_int_impl::value); + construct(socket_type_int_impl::value, userdata); } template S* get() { - if (m_type != socket_type_int_impl::value) return 0; + if (m_type != socket_type_int_impl::value) return 0; return (S*)m_data; } template S const* get() const { - if (m_type != socket_type_int_impl::value) return 0; + if (m_type != socket_type_int_impl::value) return 0; return (S const*)m_data; } private: void destruct(); - void construct(int type); + void construct(int type, void* userdata); io_service& m_io_service; int m_type; + enum { storage_size = max7< + sizeof(stream_socket) + , sizeof(socks5_stream) + , sizeof(http_stream) #if TORRENT_USE_I2P - enum { storage_size = max4::value }; + , sizeof(i2p_stream) #else - enum { storage_size = max3::value }; + , 0 #endif +#ifdef TORRENT_USE_OPENSSL + , sizeof(ssl_stream) + , sizeof(ssl_stream) + , sizeof(ssl_stream) +#else + , 0, 0, 0 +#endif + >::value + }; + size_type m_data[(storage_size + sizeof(size_type) - 1) / sizeof(size_type)]; }; } diff --git a/include/libtorrent/ssl_stream.hpp b/include/libtorrent/ssl_stream.hpp index a0965903d..8a8a07e95 100644 --- a/include/libtorrent/ssl_stream.hpp +++ b/include/libtorrent/ssl_stream.hpp @@ -51,15 +51,12 @@ class ssl_stream { public: - explicit ssl_stream(io_service& io_service) - : m_context(io_service, asio::ssl::context::sslv23_client) - , m_sock(io_service, m_context) + explicit ssl_stream(io_service& io_service, asio::ssl::context& ctx) + : m_sock(io_service, ctx) { - error_code ec; - m_context.set_verify_mode(asio::ssl::context::verify_none, ec); } - typedef Stream next_layer_type; + typedef asio::ssl::stream next_layer_type; typedef typename Stream::lowest_layer_type lowest_layer_type; typedef typename Stream::endpoint_type endpoint_type; typedef typename Stream::protocol_type protocol_type; @@ -94,6 +91,20 @@ public: return m_sock.read_some(buffers, ec); } +#ifndef BOOST_NO_EXCEPTIONS + template + void set_option(SettableSocketOption const& opt) + { + m_sock.next_layer().set_option(opt); + } +#endif + + template + error_code set_option(SettableSocketOption const& opt, error_code& ec) + { + return m_sock.next_layer().set_option(opt, ec); + } + #ifndef BOOST_NO_EXCEPTIONS template std::size_t read_some(Mutable_Buffers const& buffers) @@ -120,6 +131,20 @@ public: m_sock.async_write_some(buffers, handler); } + template + std::size_t write_some(Const_Buffers const& buffers, error_code& ec) + { + return m_sock.write_some(buffers, ec); + } + +#ifndef BOOST_NO_EXCEPTIONS + std::size_t available() const + { return const_cast(m_sock).next_layer().available(); } +#endif + + std::size_t available(error_code& ec) const + { return const_cast(m_sock).next_layer().available(ec); } + #ifndef BOOST_NO_EXCEPTIONS void bind(endpoint_type const& endpoint) { @@ -197,7 +222,7 @@ public: next_layer_type& next_layer() { - return m_sock.next_layer(); + return m_sock; } private: @@ -219,7 +244,6 @@ private: (*h)(e); } - asio::ssl::context m_context; asio::ssl::stream m_sock; }; diff --git a/include/libtorrent/variant_stream.hpp b/include/libtorrent/variant_stream.hpp deleted file mode 100644 index 74104784a..000000000 --- a/include/libtorrent/variant_stream.hpp +++ /dev/null @@ -1,790 +0,0 @@ -// Copyright Daniel Wallin and Arvid Norberg 2007. -// Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef VARIANT_STREAM_070211_HPP -# define VARIANT_STREAM_070211_HPP - -# include - -# include -# include -# include -# include -# include - -# include -# include -# include - -# include -# include - -#if BOOST_VERSION < 103500 -#include -#else -#include -#endif - -#include "libtorrent/config.hpp" -#include "libtorrent/error_code.hpp" -#include "libtorrent/assert.hpp" - -# define NETWORK_VARIANT_STREAM_LIMIT 5 - -namespace libtorrent { - -namespace aux -{ - - struct delete_visitor - : boost::static_visitor<> - { - template - void operator()(T* p) const - { - delete p; - } - - void operator()(boost::blank) const - {} - }; - -// -------------- io_control ----------- - - template - struct io_control_visitor_ec: boost::static_visitor<> - { - io_control_visitor_ec(IO_Control_Command& io, error_code& e) - : ioc(io), ec(e) {} - - template - void operator()(T* p) const - { - p->io_control(ioc, ec); - } - - void operator()(boost::blank) const - {} - - IO_Control_Command& ioc; - error_code& ec; - }; - - template - struct io_control_visitor - : boost::static_visitor<> - { - io_control_visitor(IO_Control_Command& io) - : ioc(io) {} - - template - void operator()(T* p) const - { - p->io_control(ioc); - } - - void operator()(boost::blank) const - {} - - IO_Control_Command& ioc; - }; -// -------------- async_connect ----------- - - template - struct async_connect_visitor - : boost::static_visitor<> - { - async_connect_visitor(EndpointType const& ep, Handler const& h) - : endpoint(ep) - , handler(h) - {} - - template - void operator()(T* p) const - { - p->async_connect(endpoint, handler); - } - - void operator()(boost::blank) const - {} - - EndpointType const& endpoint; - Handler const& handler; - }; - -// -------------- bind ----------- - - template - struct bind_visitor_ec - : boost::static_visitor<> - { - bind_visitor_ec(EndpointType const& ep, error_code& ec_) - : endpoint(ep) - , ec(ec_) - {} - - template - void operator()(T* p) const - { p->bind(endpoint, ec); } - - void operator()(boost::blank) const {} - - EndpointType const& endpoint; - error_code& ec; - }; - - template - struct bind_visitor - : boost::static_visitor<> - { - bind_visitor(EndpointType const& ep) - : endpoint(ep) - {} - - template - void operator()(T* p) const - { p->bind(endpoint); } - - void operator()(boost::blank) const {} - - EndpointType const& endpoint; - }; - -// -------------- open ----------- - - template - struct open_visitor_ec - : boost::static_visitor<> - { - open_visitor_ec(Protocol const& p, error_code& ec_) - : proto(p) - , ec(ec_) - {} - - template - void operator()(T* p) const - { p->open(proto, ec); } - - void operator()(boost::blank) const {} - - Protocol const& proto; - error_code& ec; - }; - - template - struct open_visitor - : boost::static_visitor<> - { - open_visitor(Protocol const& p) - : proto(p) - {} - - template - void operator()(T* p) const - { p->open(proto); } - - void operator()(boost::blank) const {} - - Protocol const& proto; - }; - -// -------------- is_open ----------- - - struct is_open_visitor - : boost::static_visitor - { - is_open_visitor() {} - - template - bool operator()(T const* p) const - { return p->is_open(); } - - bool operator()(boost::blank) const { return false; } - }; - -// -------------- close ----------- - - struct close_visitor_ec - : boost::static_visitor<> - { - close_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - void operator()(T* p) const - { p->close(ec); } - - void operator()(boost::blank) const {} - - error_code& ec; - }; - -#ifndef BOOST_NO_EXCEPTIONS - struct close_visitor - : boost::static_visitor<> - { - template - void operator()(T* p) const - { p->close(); } - - void operator()(boost::blank) const {} - }; -#endif - -// -------------- remote_endpoint ----------- - - template - struct remote_endpoint_visitor_ec - : boost::static_visitor - { - remote_endpoint_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - EndpointType operator()(T const* p) const - { return p->remote_endpoint(ec); } - - EndpointType operator()(boost::blank) const - { return EndpointType(); } - - error_code& ec; - }; - -#ifndef BOOST_NO_EXCEPTIONS - template - struct remote_endpoint_visitor - : boost::static_visitor - { - template - EndpointType operator()(T const* p) const - { return p->remote_endpoint(); } - - EndpointType operator()(boost::blank) const - { return EndpointType(); } - }; -#endif - -// -------------- set_option ----------- - -#ifndef BOOST_NO_EXCEPTIONS - template - struct set_option_visitor - : boost::static_visitor<> - { - set_option_visitor(SettableSocketOption const& opt) - : opt_(opt) - {} - - template - void operator()(T* p) const - { p->set_option(opt_); } - - void operator()(boost::blank) const {} - - SettableSocketOption const& opt_; - }; -#endif - - template - struct set_option_visitor_ec - : boost::static_visitor - { - set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec) - : opt_(opt) - , ec_(ec) - {} - - template - error_code operator()(T* p) const - { return p->set_option(opt_, ec_); } - - error_code operator()(boost::blank) const - { return ec_; } - - SettableSocketOption const& opt_; - error_code& ec_; - }; - -// -------------- local_endpoint ----------- - - template - struct local_endpoint_visitor_ec - : boost::static_visitor - { - local_endpoint_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - EndpointType operator()(T const* p) const - { - return p->local_endpoint(ec); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - - error_code& ec; - }; - -#ifndef BOOST_NO_EXCEPTIONS - template - struct local_endpoint_visitor - : boost::static_visitor - { - template - EndpointType operator()(T const* p) const - { - return p->local_endpoint(); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - }; -#endif - -// -------------- async_read_some ----------- - - template - struct async_read_some_visitor - : boost::static_visitor<> - { - async_read_some_visitor(Mutable_Buffers const& bufs, Handler const& h) - : buffers(bufs) - , handler(h) - {} - - template - void operator()(T* p) const - { - p->async_read_some(buffers, handler); - } - void operator()(boost::blank) const - {} - - Mutable_Buffers const& buffers; - Handler const& handler; - }; - -// -------------- read_some ----------- - -#ifndef BOOST_NO_EXCEPTIONS - template - struct read_some_visitor - : boost::static_visitor - { - read_some_visitor(Mutable_Buffers const& bufs) - : buffers(bufs) - {} - - template - std::size_t operator()(T* p) const - { return p->read_some(buffers); } - - std::size_t operator()(boost::blank) const - { return 0; } - - Mutable_Buffers const& buffers; - }; -#endif - - template - struct read_some_visitor_ec - : boost::static_visitor - { - read_some_visitor_ec(Mutable_Buffers const& bufs, error_code& e) - : buffers(bufs) - , ec(e) - {} - - template - std::size_t operator()(T* p) const - { return p->read_some(buffers, ec); } - - std::size_t operator()(boost::blank) const - { return 0; } - - Mutable_Buffers const& buffers; - error_code& ec; - }; - -// -------------- async_write_some ----------- - - template - struct async_write_some_visitor - : boost::static_visitor<> - { - async_write_some_visitor(Const_Buffers const& bufs, Handler const& h) - : buffers(bufs) - , handler(h) - {} - - template - void operator()(T* p) const - { - p->async_write_some(buffers, handler); - } - - void operator()(boost::blank) const - {} - - Const_Buffers const& buffers; - Handler const& handler; - }; - -// -------------- in_avail ----------- - - struct in_avail_visitor_ec - : boost::static_visitor - { - in_avail_visitor_ec(error_code& ec_) - : ec(ec_) - {} - - template - std::size_t operator()(T const* p) const - { - return p->in_avail(ec); - } - - std::size_t operator()(boost::blank) const - { - return 0; - } - - error_code& ec; - }; - -#ifndef BOOST_NO_EXCEPTIONS - struct in_avail_visitor - : boost::static_visitor - { - template - std::size_t operator()(T const* p) const - { - return p->in_avail(); - } - - void operator()(boost::blank) const - {} - }; -#endif - -// -------------- io_service ----------- - - template - struct io_service_visitor - : boost::static_visitor - { - template - IOService& operator()(T* p) const - { - return p->get_io_service(); - } - - IOService& operator()(boost::blank) const - { - return *(IOService*)0; - } - }; - -// -------------- lowest_layer ----------- - - template - struct lowest_layer_visitor - : boost::static_visitor - { - template - LowestLayer& operator()(T* p) const - { - return p->lowest_layer(); - } - - LowestLayer& operator()(boost::blank) const - { - return *(LowestLayer*)0; - } - }; - -} // namespace aux - -template < - BOOST_PP_ENUM_BINARY_PARAMS( - NETWORK_VARIANT_STREAM_LIMIT, class S, = boost::mpl::void_ BOOST_PP_INTERCEPT - ) -> -class variant_stream : boost::noncopyable -{ -public: - typedef BOOST_PP_CAT(boost::mpl::vector, NETWORK_VARIANT_STREAM_LIMIT)< - BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT, S) - > types0; - - typedef typename boost::mpl::remove::type types; - - typedef typename boost::make_variant_over< - typename boost::mpl::push_back< - typename boost::mpl::transform< - types - , boost::add_pointer - >::type - , boost::blank - >::type - >::type variant_type; - - typedef typename S0::lowest_layer_type lowest_layer_type; - typedef typename S0::endpoint_type endpoint_type; - typedef typename S0::protocol_type protocol_type; - - explicit variant_stream(io_service& ios) - : m_io_service(ios), m_variant(boost::blank()) {} - - template - void instantiate(io_service& ios) - { - TORRENT_ASSERT(&ios == &m_io_service); - std::auto_ptr owned(new S(ios)); - boost::apply_visitor(aux::delete_visitor(), m_variant); - m_variant = owned.get(); - owned.release(); - } - - template - S* get() - { - S** ret = boost::get(&m_variant); - if (!ret) return 0; - return *ret; - } - - bool instantiated() const - { - return m_variant.which() != boost::mpl::size::value; - } - - ~variant_stream() - { - boost::apply_visitor(aux::delete_visitor(), m_variant); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::read_some_visitor_ec(buffers, ec) - , m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::read_some_visitor(buffers) - , m_variant - ); - } -#endif - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::async_read_some_visitor(buffers, handler) - , m_variant - ); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::async_write_some_visitor(buffers, handler) - , m_variant - ); - } - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::async_connect_visitor(endpoint, handler), m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - template - void io_control(IO_Control_Command& ioc) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::io_control_visitor(ioc), m_variant - ); - } -#endif - - template - void io_control(IO_Control_Command& ioc, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::io_control_visitor_ec(ioc, ec) - , m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - void bind(endpoint_type const& endpoint) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor(aux::bind_visitor(endpoint), m_variant); - } -#endif - - void bind(endpoint_type const& endpoint, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::bind_visitor_ec(endpoint, ec), m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - void open(protocol_type const& p) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor(aux::open_visitor(p), m_variant); - } -#endif - - void open(protocol_type const& p, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor( - aux::open_visitor_ec(p, ec), m_variant - ); - } - - bool is_open() const - { - return boost::apply_visitor(aux::is_open_visitor(), m_variant); - } - -#ifndef BOOST_NO_EXCEPTIONS - void close() - { - if (!instantiated()) return; - boost::apply_visitor(aux::close_visitor(), m_variant); - } -#endif - - void close(error_code& ec) - { - if (!instantiated()) return; - boost::apply_visitor( - aux::close_visitor_ec(ec), m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - std::size_t in_avail() const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::in_avail_visitor(), m_variant); - } -#endif - - std::size_t in_avail(error_code& ec) const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::in_avail_visitor_ec(ec), m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - endpoint_type remote_endpoint() const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::remote_endpoint_visitor(), m_variant); - } -#endif - - endpoint_type remote_endpoint(error_code& ec) const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::remote_endpoint_visitor_ec(ec), m_variant - ); - } - -#ifndef BOOST_NO_EXCEPTIONS - template - void set_option(SettableSocketOption const& opt) - { - TORRENT_ASSERT(instantiated()); - boost::apply_visitor(aux::set_option_visitor(opt) - , m_variant); - } -#endif - - template - error_code set_option(SettableSocketOption const& opt, error_code& ec) - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::set_option_visitor_ec(opt, ec) - , m_variant); - } - -#ifndef BOOST_NO_EXCEPTIONS - endpoint_type local_endpoint() const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor(aux::local_endpoint_visitor(), m_variant); - } -#endif - - endpoint_type local_endpoint(error_code& ec) const - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::local_endpoint_visitor_ec(ec), m_variant - ); - } - - io_service& get_io_service() - { - return m_io_service; - } - - lowest_layer_type& lowest_layer() - { - TORRENT_ASSERT(instantiated()); - return boost::apply_visitor( - aux::lowest_layer_visitor(), m_variant - ); - } - -private: - io_service& m_io_service; - variant_type m_variant; -}; - -} // namespace libtorrent - -#endif // VARIANT_STREAM_070211_HPP - diff --git a/include/libtorrent/web_connection_base.hpp b/include/libtorrent/web_connection_base.hpp index 0722f0383..2aa01c28c 100644 --- a/include/libtorrent/web_connection_base.hpp +++ b/include/libtorrent/web_connection_base.hpp @@ -157,6 +157,9 @@ namespace libtorrent // than subsequent ones, things that aren't critical are left // out to save bandwidth. bool m_first_request; + + // true if we're using ssl + bool m_ssl; // the number of bytes into the receive buffer where // current read cursor is. diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 71f5f840c..8380a0cc7 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -102,6 +102,8 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri #define APPEND_FMT1(fmt, arg) ptr += snprintf(ptr, end - ptr, fmt, arg) #define APPEND_FMT2(fmt, arg1, arg2) ptr += snprintf(ptr, end - ptr, fmt, arg1, arg2) + // exclude ssl here, because SSL assumes CONNECT support in the + // proxy and is handled at the lower layer if (ps && (ps->type == proxy_settings::http || ps->type == proxy_settings::http_pw) && !ssl) @@ -227,53 +229,18 @@ void http_connection::start(std::string const& hostname, std::string const& port } proxy_settings null_proxy; -#ifdef TORRENT_USE_OPENSSL - if (m_ssl) - { - m_sock.instantiate >(m_resolver.get_io_service()); - ssl_stream* s = m_sock.get >(); - TORRENT_ASSERT(s); - bool ret = false; + proxy_settings const* proxy = ps; #if TORRENT_USE_I2P - if (is_i2p) - { - ret = instantiate_connection(m_resolver.get_io_service(), i2p_conn->proxy() - , s->next_layer()); - } - else + if (is_i2p) proxy = &i2p_conn->proxy(); #endif - { - ret = instantiate_connection(m_resolver.get_io_service() - , ps ? *ps : null_proxy, s->next_layer()); - } - TORRENT_ASSERT(ret); - } - else - { - m_sock.instantiate(m_resolver.get_io_service()); - bool ret = false; -#if TORRENT_USE_I2P - if (is_i2p) - { - ret = instantiate_connection(m_resolver.get_io_service(), i2p_conn->proxy() - , *m_sock.get()); - TORRENT_ASSERT(m_sock.get()); - TORRENT_ASSERT(m_sock.get()->get()); - } - else + void* userdata = 0; +#ifdef TORRENT_USE_OPENSSL + if (m_ssl) userdata = &m_ssl_ctx; #endif - { - ret = instantiate_connection(m_resolver.get_io_service() - , ps ? *ps : null_proxy, *m_sock.get()); - } - TORRENT_ASSERT(ret); - } -#else bool ret = instantiate_connection(m_resolver.get_io_service() - , ps ? *ps : null_proxy, m_sock); - TORRENT_ASSERT(ret); -#endif + , ps ? *ps : null_proxy, m_sock, userdata); + if (m_bind_addr != address_v4::any()) { error_code ec; @@ -468,15 +435,17 @@ void http_connection::connect(int ticket, tcp::endpoint target_address) // we're using a socks proxy and we're resolving // hostnames through it #ifdef TORRENT_USE_OPENSSL - if (!m_ssl) + if (m_ssl) { - TORRENT_ASSERT(m_sock.get()->get()); - m_sock.get()->get()->set_dst_name(m_hostname); + TORRENT_ASSERT(m_sock.get >()); + m_sock.get >()->next_layer().next_layer().set_dst_name(m_hostname); } -#else - TORRENT_ASSERT(m_sock.get()); - m_sock.get()->set_dst_name(m_hostname); + else #endif + { + TORRENT_ASSERT(m_sock.get()); + m_sock.get()->set_dst_name(m_hostname); + } } m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect , shared_from_this(), _1)); diff --git a/src/http_seed_connection.cpp b/src/http_seed_connection.cpp index 84aba9aab..2bf1d7fa7 100644 --- a/src/http_seed_connection.cpp +++ b/src/http_seed_connection.cpp @@ -156,8 +156,8 @@ namespace libtorrent } proxy_settings const& ps = m_ses.proxy(); - bool using_proxy = ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw; + bool using_proxy = (ps.type == proxy_settings::http + || ps.type == proxy_settings::http_pw) && !m_ssl; request += "GET "; request += using_proxy ? m_url : m_path; diff --git a/src/instantiate_connection.cpp b/src/instantiate_connection.cpp index a6eab35cf..81a8cbc7a 100644 --- a/src/instantiate_connection.cpp +++ b/src/instantiate_connection.cpp @@ -42,30 +42,61 @@ namespace libtorrent { bool instantiate_connection(io_service& ios - , proxy_settings const& ps, socket_type& s) + , proxy_settings const& ps, socket_type& s + , void* ssl_context) { if (ps.type == proxy_settings::none) { - s.instantiate(ios); +#ifdef TORRENT_USE_OPENSSL + if (ssl_context) + s.instantiate >(ios, ssl_context); + else +#endif + s.instantiate(ios); } else if (ps.type == proxy_settings::http || ps.type == proxy_settings::http_pw) { - s.instantiate(ios); - s.get()->set_proxy(ps.hostname, ps.port); + http_stream* str; +#ifdef TORRENT_USE_OPENSSL + if (ssl_context) + { + s.instantiate >(ios, ssl_context); + str = &s.get >()->next_layer().next_layer(); + } + else +#endif + { + s.instantiate(ios); + str = s.get(); + } + + str->set_proxy(ps.hostname, ps.port); if (ps.type == proxy_settings::http_pw) - s.get()->set_username(ps.username, ps.password); + str->set_username(ps.username, ps.password); } else if (ps.type == proxy_settings::socks5 || ps.type == proxy_settings::socks5_pw || ps.type == proxy_settings::socks4) { - s.instantiate(ios); - s.get()->set_proxy(ps.hostname, ps.port); + socks5_stream* str; +#ifdef TORRENT_USE_OPENSSL + if (ssl_context) + { + s.instantiate >(ios, ssl_context); + str = &s.get >()->next_layer().next_layer(); + } + else +#endif + { + s.instantiate(ios); + str = s.get(); + } + str->set_proxy(ps.hostname, ps.port); if (ps.type == proxy_settings::socks5_pw) - s.get()->set_username(ps.username, ps.password); + str->set_username(ps.username, ps.password); if (ps.type == proxy_settings::socks4) - s.get()->set_version(4); + str->set_version(4); } #if TORRENT_USE_I2P else if (ps.type == proxy_settings::i2p_proxy) @@ -76,6 +107,7 @@ namespace libtorrent #endif else { + TORRENT_ASSERT_VAL(false, ps.type); return false; } return true; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 438510747..97da08750 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -373,7 +373,9 @@ namespace aux { { session_settings m_settings; proxy_settings m_proxy; +#ifndef TORRENT_DISABLE_ENCRYPTION pe_settings m_pe_settings; +#endif #ifndef TORRENT_DISABLE_DHT dht_settings m_dht_settings; #endif @@ -422,6 +424,9 @@ namespace aux { #endif , m_files(40) , m_io_service() +#ifdef TORRENT_USE_OPENSSL + , m_ssl_ctx(m_io_service, asio::ssl::context::sslv23_client) +#endif , m_alerts(m_io_service) , m_disk_thread(m_io_service, boost::bind(&session_impl::on_disk_queue, this), m_files) , m_half_open(m_io_service) @@ -481,6 +486,11 @@ namespace aux { (*m_logger) << time_now_string() << "\n"; #endif + error_code ec; +#ifdef TORRENT_USE_OPENSSL + m_ssl_ctx.set_verify_mode(asio::ssl::context::verify_none, ec); +#endif + #ifndef TORRENT_DISABLE_DHT m_next_dht_torrent = m_torrents.begin(); #endif @@ -488,7 +498,6 @@ namespace aux { m_next_connect_torrent = m_torrents.begin(); TORRENT_ASSERT_VAL(listen_interface, listen_interface); - error_code ec; m_listen_interface = tcp::endpoint(address::from_string(listen_interface, ec), listen_port_range.first); TORRENT_ASSERT_VAL(!ec, ec); diff --git a/src/socket_type.cpp b/src/socket_type.cpp index e6c4ce32c..86be2fce5 100644 --- a/src/socket_type.cpp +++ b/src/socket_type.cpp @@ -32,6 +32,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket_type.hpp" +#ifdef TORRENT_USE_OPENSSL +#include +#endif + namespace libtorrent { @@ -41,24 +45,35 @@ namespace libtorrent { case 0: break; case socket_type_int_impl::value: - get()->~stream_socket(); - break; + get()->~stream_socket(); + break; case socket_type_int_impl::value: - get()->~socks5_stream(); - break; + get()->~socks5_stream(); + break; case socket_type_int_impl::value: - get()->~http_stream(); - break; + get()->~http_stream(); + break; #if TORRENT_USE_I2P case socket_type_int_impl::value: - get()->~i2p_stream(); - break; + get()->~i2p_stream(); + break; +#endif +#ifdef TORRENT_USE_OPENSSL + case socket_type_int_impl >::value: + get >()->~ssl_stream(); + break; + case socket_type_int_impl >::value: + get >()->~ssl_stream(); + break; + case socket_type_int_impl >::value: + get >()->~ssl_stream(); + break; #endif } m_type = 0; } - void socket_type::construct(int type) + void socket_type::construct(int type, void* userdata) { destruct(); switch (type) @@ -77,6 +92,23 @@ namespace libtorrent case socket_type_int_impl::value: new ((i2p_stream*)m_data) i2p_stream(m_io_service); break; +#endif +#ifdef TORRENT_USE_OPENSSL + case socket_type_int_impl >::value: + TORRENT_ASSERT(userdata); + new ((ssl_stream*)m_data) ssl_stream(m_io_service + , *((boost::asio::ssl::context*)userdata)); + break; + case socket_type_int_impl >::value: + TORRENT_ASSERT(userdata); + new ((ssl_stream*)m_data) ssl_stream(m_io_service + , *((boost::asio::ssl::context*)userdata)); + break; + case socket_type_int_impl >::value: + TORRENT_ASSERT(userdata); + new ((ssl_stream*)m_data) ssl_stream(m_io_service + , *((boost::asio::ssl::context*)userdata)); + break; #endif } @@ -98,7 +130,6 @@ namespace libtorrent socket_type::lowest_layer_type& socket_type::lowest_layer() { TORRENT_SOCKTYPE_FORWARD_RET(lowest_layer(), *((lowest_layer_type*)m_data)) } - void socket_type::open(protocol_type const& p, error_code& ec) { TORRENT_SOCKTYPE_FORWARD(open(p, ec)) } diff --git a/src/torrent.cpp b/src/torrent.cpp index 2923950d1..6461899ae 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -79,6 +79,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/peer_info.hpp" #include "libtorrent/enum_net.hpp" +#ifdef TORRENT_USE_OPENSSL +#include "libtorrent/ssl_stream.hpp" +#endif + #if TORRENT_USE_IOSTREAM #include #endif @@ -3532,13 +3536,19 @@ namespace libtorrent boost::shared_ptr s(new (std::nothrow) socket_type(m_ses.m_io_service)); if (!s) return; - bool ret = instantiate_connection(m_ses.m_io_service, m_ses.proxy(), *s); + bool ssl = string_begins_no_case("https://", web->url.c_str()); + void* userdata = 0; +#ifdef TORRENT_USE_OPENSSL + if (ssl) userdata = &m_ses.m_ssl_ctx; +#endif + bool ret = instantiate_connection(m_ses.m_io_service, m_ses.proxy(), *s, userdata); (void)ret; TORRENT_ASSERT(ret); proxy_settings const& ps = m_ses.proxy(); - if (ps.type == proxy_settings::http + if ((ps.type == proxy_settings::http || ps.type == proxy_settings::http_pw) + && !ssl) { // the web seed connection will talk immediately to // the proxy, without requiring CONNECT support @@ -3551,14 +3561,21 @@ namespace libtorrent { // we're using a socks proxy and we're resolving // hostnames through it - TORRENT_ASSERT(s->get()); +#ifdef TORRENT_USE_OPENSSL + socks5_stream* str = ssl + ? &s->get >()->next_layer().next_layer() + : s->get(); +#else + socks5_stream* str = s->get(); +#endif + TORRENT_ASSERT(str); using boost::tuples::ignore; std::string hostname; error_code ec; boost::tie(ignore, ignore, hostname, ignore, ignore) = parse_url_components(web->url, ec); - s->get()->set_dst_name(hostname); + str->set_dst_name(hostname); } boost::intrusive_ptr c; diff --git a/src/web_connection_base.cpp b/src/web_connection_base.cpp index c740b0fcc..f10122131 100644 --- a/src/web_connection_base.cpp +++ b/src/web_connection_base.cpp @@ -66,6 +66,7 @@ namespace libtorrent , web_seed_entry::headers_t const& extra_headers) : peer_connection(ses, t, s, remote, peerinfo) , m_first_request(true) + , m_ssl(false) , m_external_auth(auth) , m_extra_headers(extra_headers) { @@ -88,6 +89,10 @@ namespace libtorrent = parse_url_components(url, ec); TORRENT_ASSERT(!ec); +#ifdef TORRENT_USE_OPENSSL + if (protocol == "https") m_ssl = true; +#endif + if (!m_basic_auth.empty()) m_basic_auth = base64encode(m_basic_auth); diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index 8dca306cb..2e2f28eb5 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -172,8 +172,8 @@ namespace libtorrent } proxy_settings const& ps = m_ses.proxy(); - bool using_proxy = ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw; + bool using_proxy = (ps.type == proxy_settings::http + || ps.type == proxy_settings::http_pw) && !m_ssl; if (single_file_request) { diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index 44675640d..d950e597a 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -46,6 +46,13 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/alert_types.hpp" #include "libtorrent/create_torrent.hpp" #include "libtorrent/socket_io.hpp" // print_endpoint +#include "libtorrent/socket_type.hpp" +#include "libtorrent/instantiate_connection.hpp" + +#ifdef TORRENT_USE_OPENSSL +#include +#include +#endif using namespace libtorrent; @@ -515,6 +522,19 @@ int start_web_server(bool ssl) web_initialized.clear(l); } + if (ssl) + { + system("echo . > tmp"); + system("echo test province >>tmp"); + system("echo test city >> tmp"); + system("echo test company >> tmp"); + system("echo test department >> tmp"); + system("echo tester >> tmp"); + system("echo test@test.com >> tmp"); + system("openssl req -new -x509 -keyout server.pem -out server.pem " + "-days 365 -nodes >()->next_layer().next_layer(); + else +#endif + sock = s.get(); + accept_done = false; - acceptor.async_accept(s, &on_accept); + acceptor.async_accept(*sock, &on_accept); ios.reset(); ios.run_one(); if (!accept_done) { - fprintf(stderr, "accept failed\n"); + fprintf(stderr, "accept failed: %s\n", ec.message().c_str()); return; } + fprintf(stderr, "accepting incoming connection\n"); if (!s.is_open()) continue; + +#ifdef TORRENT_USE_OPENSSL + if (ssl) + s.get >()->next_layer().handshake(asio::ssl::stream_base::server); +#endif + } http_parser p; @@ -666,6 +710,7 @@ void web_server_thread(int* port, bool ssl) { size_t received = s.read_some(boost::asio::buffer(&buf[len] , sizeof(buf) - len), ec); +// fprintf(stderr, "read: %d\n", int(received)); if (ec || received <= 0) { @@ -700,7 +745,7 @@ void web_server_thread(int* port, bool ssl) if (failed) { - s.close(ec); + connection_close = true; break; } diff --git a/test/test_web_seed.cpp b/test/test_web_seed.cpp index 3c5228a48..a560cd15e 100644 --- a/test/test_web_seed.cpp +++ b/test/test_web_seed.cpp @@ -47,7 +47,8 @@ POSSIBILITY OF SUCH DAMAGE. using namespace libtorrent; // proxy: 0=none, 1=socks4, 2=socks5, 3=socks5_pw 4=http 5=http_pw -void test_transfer(boost::intrusive_ptr torrent_file, int proxy, int port) +void test_transfer(boost::intrusive_ptr torrent_file + , int proxy, int port, char const* protocol) { using namespace libtorrent; @@ -62,7 +63,7 @@ void test_transfer(boost::intrusive_ptr torrent_file, int proxy, i char const* test_name[] = {"no", "SOCKS4", "SOCKS5", "SOCKS5 password", "HTTP", "HTTP password"}; - fprintf(stderr, "\n\n ==== TESTING %s proxy ====\n\n\n", test_name[proxy]); + fprintf(stderr, "\n\n ==== TESTING %s proxy ==== %s ====\n\n\n", test_name[proxy], protocol); if (proxy) { @@ -152,7 +153,7 @@ void test_transfer(boost::intrusive_ptr torrent_file, int proxy, i remove_all("./tmp2_web_seed", ec); } -int test_main() +int run_suite(char const* protocol) { using namespace libtorrent; @@ -191,11 +192,11 @@ int test_main() file_storage fs; add_files(fs, "./tmp1_web_seed/test_torrent_dir"); - int port = start_web_server(); + int port = start_web_server(strcmp(protocol, "https") == 0); libtorrent::create_torrent t(fs, 16); char tmp[512]; - snprintf(tmp, sizeof(tmp), "http://127.0.0.1:%d/tmp1_web_seed", port); + snprintf(tmp, sizeof(tmp), "%s://127.0.0.1:%d/tmp1_web_seed", protocol, port); t.add_url_seed(tmp); // calculate the hash for all pieces @@ -205,13 +206,23 @@ int test_main() boost::intrusive_ptr torrent_file(new torrent_info(&buf[0], buf.size(), ec)); for (int i = 0; i < 6; ++i) - test_transfer(torrent_file, i, port); + test_transfer(torrent_file, i, port, protocol); torrent_file->rename_file(0, "./tmp2_web_seed/test_torrent_dir/renamed_test1"); - test_transfer(torrent_file, 0, port); + test_transfer(torrent_file, 0, port, protocol); stop_web_server(); remove_all("./tmp1_web_seed", ec); return 0; } +int test_main() +{ + int ret = 0; +#ifdef TORRENT_USE_OPENSSL + ret += run_suite("https"); +#endif + ret += run_suite("http"); + return ret; +} +