forked from premiere/premiere-libtorrent
generalize SSL support to also include web seeds (and in theory regular peers)
This commit is contained in:
parent
43b29c3627
commit
7bd25edc9d
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -91,6 +91,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/peer_connection.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#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;
|
||||
|
||||
|
|
|
@ -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 <boost/asio/ssl/context.hpp>
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
|
@ -90,6 +89,9 @@ struct TORRENT_EXPORT http_connection : boost::enable_shared_from_this<http_conn
|
|||
, m_last_receive(time_now())
|
||||
, m_bottled(bottled)
|
||||
, m_called(false)
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
, m_ssl_ctx(ios, asio::ssl::context::sslv23_client)
|
||||
#endif
|
||||
, m_rate_limit(0)
|
||||
, m_download_quota(0)
|
||||
, m_limiter_timer_active(false)
|
||||
|
@ -102,6 +104,10 @@ struct TORRENT_EXPORT http_connection : boost::enable_shared_from_this<http_conn
|
|||
, m_abort(false)
|
||||
{
|
||||
TORRENT_ASSERT(!m_handler.empty());
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
error_code ec;
|
||||
m_ssl_ctx.set_verify_mode(asio::ssl::context::verify_none, ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rate_limit(int limit);
|
||||
|
@ -130,11 +136,7 @@ struct TORRENT_EXPORT http_connection : boost::enable_shared_from_this<http_conn
|
|||
|
||||
void close();
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
variant_stream<socket_type, ssl_stream<socket_type> > const& socket() const { return m_sock; }
|
||||
#else
|
||||
socket_type const& socket() const { return m_sock; }
|
||||
#endif
|
||||
|
||||
std::list<tcp::endpoint> 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<char> 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<socket_type, ssl_stream<socket_type> > 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<tcp::endpoint> m_endpoints;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
asio::ssl::context m_ssl_ctx;
|
||||
#endif
|
||||
|
||||
// the current download limit, in bytes per second
|
||||
// 0 is unlimited.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -81,6 +81,18 @@ namespace libtorrent
|
|||
value = max3<temp1, temp2, temp3>::value
|
||||
};
|
||||
};
|
||||
|
||||
template<int v1, int v2, int v3, int v4, int v5, int v6, int v7>
|
||||
struct max7
|
||||
{
|
||||
enum
|
||||
{
|
||||
temp1 = max<v1,v2>::value,
|
||||
temp2 = max<v3,v4>::value,
|
||||
temp3 = max3<v5,v6,v7>::value,
|
||||
value = max3<temp1, temp2, temp3>::value
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,6 +73,12 @@ public:
|
|||
return m_sock.read_some(buffers, ec);
|
||||
}
|
||||
|
||||
template <class Const_Buffers>
|
||||
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 <class Const_Buffers>
|
||||
std::size_t write_some(Const_Buffers const& buffers)
|
||||
{
|
||||
return m_sock.write_some(buffers);
|
||||
}
|
||||
|
||||
template <class IO_Control_Command>
|
||||
void io_control(IO_Control_Command& ioc)
|
||||
{
|
||||
|
|
|
@ -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<stream_socket>::value: \
|
||||
get<stream_socket>()->x; break; \
|
||||
case socket_type_int_impl<socks5_stream>::value: \
|
||||
get<socks5_stream>()->x; break; \
|
||||
case socket_type_int_impl<http_stream>::value: \
|
||||
get<http_stream>()->x; break; \
|
||||
#define TORRENT_SOCKTYPE_I2P_FORWARD(x) \
|
||||
case socket_type_int_impl<i2p_stream>::value: \
|
||||
get<i2p_stream>()->x; break; \
|
||||
default: TORRENT_ASSERT(false); \
|
||||
}
|
||||
get<i2p_stream>()->x; break;
|
||||
|
||||
#define TORRENT_SOCKTYPE_FORWARD_RET(x, def) \
|
||||
switch (m_type) { \
|
||||
case socket_type_int_impl<stream_socket>::value: \
|
||||
return get<stream_socket>()->x; \
|
||||
case socket_type_int_impl<socks5_stream>::value: \
|
||||
return get<socks5_stream>()->x; \
|
||||
case socket_type_int_impl<http_stream>::value: \
|
||||
return get<http_stream>()->x; \
|
||||
#define TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def) \
|
||||
case socket_type_int_impl<i2p_stream>::value: \
|
||||
return get<i2p_stream>()->x; \
|
||||
default: TORRENT_ASSERT(false); return def; \
|
||||
}
|
||||
return get<i2p_stream>()->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<ssl_stream<stream_socket> >::value: \
|
||||
get<ssl_stream<stream_socket> >()->x; break; \
|
||||
case socket_type_int_impl<ssl_stream<socks5_stream> >::value: \
|
||||
get<ssl_stream<socks5_stream> >()->x; break; \
|
||||
case socket_type_int_impl<ssl_stream<http_stream> >::value: \
|
||||
get<ssl_stream<http_stream> >()->x; break;
|
||||
|
||||
#define TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def) \
|
||||
case socket_type_int_impl<ssl_stream<stream_socket> >::value: \
|
||||
return get<ssl_stream<stream_socket> >()->x; \
|
||||
case socket_type_int_impl<ssl_stream<socks5_stream> >::value: \
|
||||
return get<ssl_stream<socks5_stream> >()->x; \
|
||||
case socket_type_int_impl<ssl_stream<http_stream> >::value: \
|
||||
return get<ssl_stream<http_stream> >()->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<stream_socket>::value: \
|
||||
|
@ -80,6 +96,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
get<socks5_stream>()->x; break; \
|
||||
case socket_type_int_impl<http_stream>::value: \
|
||||
get<http_stream>()->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<socks5_stream>()->x; \
|
||||
case socket_type_int_impl<http_stream>::value: \
|
||||
return get<http_stream>()->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<ssl_stream<stream_socket> >
|
||||
{ enum { value = 5 }; };
|
||||
|
||||
template <>
|
||||
struct socket_type_int_impl<ssl_stream<socks5_stream> >
|
||||
{ enum { value = 6 }; };
|
||||
|
||||
template <>
|
||||
struct socket_type_int_impl<ssl_stream<http_stream> >
|
||||
{ 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 <class Const_Buffers>
|
||||
std::size_t write_some(Const_Buffers const& buffers, error_code& ec)
|
||||
{ TORRENT_SOCKTYPE_FORWARD_RET(write_some(buffers, ec), 0) }
|
||||
|
||||
template <class Const_Buffers, class Handler>
|
||||
void async_write_some(Const_Buffers const& buffers, Handler const& handler)
|
||||
{ TORRENT_SOCKTYPE_FORWARD(async_write_some(buffers, handler)) }
|
||||
|
@ -193,10 +228,10 @@ namespace libtorrent
|
|||
{ TORRENT_SOCKTYPE_FORWARD_RET(set_option(opt, ec), ec) }
|
||||
|
||||
template <class S>
|
||||
void instantiate(io_service& ios)
|
||||
void instantiate(io_service& ios, void* userdata = 0)
|
||||
{
|
||||
TORRENT_ASSERT(&ios == &m_io_service);
|
||||
construct(socket_type_int_impl<S>::value);
|
||||
construct(socket_type_int_impl<S>::value, userdata);
|
||||
}
|
||||
|
||||
template <class S> S* get()
|
||||
|
@ -214,15 +249,29 @@ namespace libtorrent
|
|||
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<sizeof(stream_socket), sizeof(socks5_stream), sizeof(http_stream), sizeof(i2p_stream)>::value };
|
||||
, sizeof(i2p_stream)
|
||||
#else
|
||||
enum { storage_size = max3<sizeof(stream_socket), sizeof(socks5_stream), sizeof(http_stream)>::value };
|
||||
, 0
|
||||
#endif
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
, sizeof(ssl_stream<stream_socket>)
|
||||
, sizeof(ssl_stream<socks5_stream>)
|
||||
, sizeof(ssl_stream<http_stream>)
|
||||
#else
|
||||
, 0, 0, 0
|
||||
#endif
|
||||
>::value
|
||||
};
|
||||
|
||||
size_type m_data[(storage_size + sizeof(size_type) - 1) / sizeof(size_type)];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<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 <class SettableSocketOption>
|
||||
void set_option(SettableSocketOption const& opt)
|
||||
{
|
||||
m_sock.next_layer().set_option(opt);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class SettableSocketOption>
|
||||
error_code set_option(SettableSocketOption const& opt, error_code& ec)
|
||||
{
|
||||
return m_sock.next_layer().set_option(opt, ec);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
template <class Mutable_Buffers>
|
||||
std::size_t read_some(Mutable_Buffers const& buffers)
|
||||
|
@ -120,6 +131,20 @@ public:
|
|||
m_sock.async_write_some(buffers, handler);
|
||||
}
|
||||
|
||||
template <class Const_Buffers>
|
||||
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<sock_type&>(m_sock).next_layer().available(); }
|
||||
#endif
|
||||
|
||||
std::size_t available(error_code& ec) const
|
||||
{ return const_cast<sock_type&>(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<Stream> m_sock;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 <boost/variant.hpp>
|
||||
|
||||
# include <boost/mpl/vector.hpp>
|
||||
# include <boost/mpl/void.hpp>
|
||||
# include <boost/mpl/remove.hpp>
|
||||
# include <boost/mpl/transform.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
|
||||
# include <boost/type_traits/add_pointer.hpp>
|
||||
# include <boost/noncopyable.hpp>
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/io_service.hpp>
|
||||
#else
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#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 <class T>
|
||||
void operator()(T* p) const
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
void operator()(boost::blank) const
|
||||
{}
|
||||
};
|
||||
|
||||
// -------------- io_control -----------
|
||||
|
||||
template<class IO_Control_Command>
|
||||
struct io_control_visitor_ec: boost::static_visitor<>
|
||||
{
|
||||
io_control_visitor_ec(IO_Control_Command& io, error_code& e)
|
||||
: ioc(io), ec(e) {}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{
|
||||
p->io_control(ioc, ec);
|
||||
}
|
||||
|
||||
void operator()(boost::blank) const
|
||||
{}
|
||||
|
||||
IO_Control_Command& ioc;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template<class IO_Control_Command>
|
||||
struct io_control_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
io_control_visitor(IO_Control_Command& io)
|
||||
: ioc(io) {}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{
|
||||
p->io_control(ioc);
|
||||
}
|
||||
|
||||
void operator()(boost::blank) const
|
||||
{}
|
||||
|
||||
IO_Control_Command& ioc;
|
||||
};
|
||||
// -------------- async_connect -----------
|
||||
|
||||
template <class EndpointType, class Handler>
|
||||
struct async_connect_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
async_connect_visitor(EndpointType const& ep, Handler const& h)
|
||||
: endpoint(ep)
|
||||
, handler(h)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{
|
||||
p->async_connect(endpoint, handler);
|
||||
}
|
||||
|
||||
void operator()(boost::blank) const
|
||||
{}
|
||||
|
||||
EndpointType const& endpoint;
|
||||
Handler const& handler;
|
||||
};
|
||||
|
||||
// -------------- bind -----------
|
||||
|
||||
template <class EndpointType>
|
||||
struct bind_visitor_ec
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
bind_visitor_ec(EndpointType const& ep, error_code& ec_)
|
||||
: endpoint(ep)
|
||||
, ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{ p->bind(endpoint, ec); }
|
||||
|
||||
void operator()(boost::blank) const {}
|
||||
|
||||
EndpointType const& endpoint;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template <class EndpointType>
|
||||
struct bind_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
bind_visitor(EndpointType const& ep)
|
||||
: endpoint(ep)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{ p->bind(endpoint); }
|
||||
|
||||
void operator()(boost::blank) const {}
|
||||
|
||||
EndpointType const& endpoint;
|
||||
};
|
||||
|
||||
// -------------- open -----------
|
||||
|
||||
template <class Protocol>
|
||||
struct open_visitor_ec
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
open_visitor_ec(Protocol const& p, error_code& ec_)
|
||||
: proto(p)
|
||||
, ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{ p->open(proto, ec); }
|
||||
|
||||
void operator()(boost::blank) const {}
|
||||
|
||||
Protocol const& proto;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template <class Protocol>
|
||||
struct open_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
open_visitor(Protocol const& p)
|
||||
: proto(p)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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<bool>
|
||||
{
|
||||
is_open_visitor() {}
|
||||
|
||||
template <class T>
|
||||
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 <class T>
|
||||
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 <class T>
|
||||
void operator()(T* p) const
|
||||
{ p->close(); }
|
||||
|
||||
void operator()(boost::blank) const {}
|
||||
};
|
||||
#endif
|
||||
|
||||
// -------------- remote_endpoint -----------
|
||||
|
||||
template <class EndpointType>
|
||||
struct remote_endpoint_visitor_ec
|
||||
: boost::static_visitor<EndpointType>
|
||||
{
|
||||
remote_endpoint_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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 <class EndpointType>
|
||||
struct remote_endpoint_visitor
|
||||
: boost::static_visitor<EndpointType>
|
||||
{
|
||||
template <class T>
|
||||
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 <class SettableSocketOption>
|
||||
struct set_option_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
set_option_visitor(SettableSocketOption const& opt)
|
||||
: opt_(opt)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
void operator()(T* p) const
|
||||
{ p->set_option(opt_); }
|
||||
|
||||
void operator()(boost::blank) const {}
|
||||
|
||||
SettableSocketOption const& opt_;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class SettableSocketOption>
|
||||
struct set_option_visitor_ec
|
||||
: boost::static_visitor<error_code>
|
||||
{
|
||||
set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec)
|
||||
: opt_(opt)
|
||||
, ec_(ec)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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 <class EndpointType>
|
||||
struct local_endpoint_visitor_ec
|
||||
: boost::static_visitor<EndpointType>
|
||||
{
|
||||
local_endpoint_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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 <class EndpointType>
|
||||
struct local_endpoint_visitor
|
||||
: boost::static_visitor<EndpointType>
|
||||
{
|
||||
template <class T>
|
||||
EndpointType operator()(T const* p) const
|
||||
{
|
||||
return p->local_endpoint();
|
||||
}
|
||||
|
||||
EndpointType operator()(boost::blank) const
|
||||
{
|
||||
return EndpointType();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// -------------- async_read_some -----------
|
||||
|
||||
template <class Mutable_Buffers, class Handler>
|
||||
struct async_read_some_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
async_read_some_visitor(Mutable_Buffers const& bufs, Handler const& h)
|
||||
: buffers(bufs)
|
||||
, handler(h)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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 <class Mutable_Buffers>
|
||||
struct read_some_visitor
|
||||
: boost::static_visitor<std::size_t>
|
||||
{
|
||||
read_some_visitor(Mutable_Buffers const& bufs)
|
||||
: buffers(bufs)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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 <class Mutable_Buffers>
|
||||
struct read_some_visitor_ec
|
||||
: boost::static_visitor<std::size_t>
|
||||
{
|
||||
read_some_visitor_ec(Mutable_Buffers const& bufs, error_code& e)
|
||||
: buffers(bufs)
|
||||
, ec(e)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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 <class Const_Buffers, class Handler>
|
||||
struct async_write_some_visitor
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
async_write_some_visitor(Const_Buffers const& bufs, Handler const& h)
|
||||
: buffers(bufs)
|
||||
, handler(h)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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<std::size_t>
|
||||
{
|
||||
in_avail_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
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<std::size_t>
|
||||
{
|
||||
template <class T>
|
||||
std::size_t operator()(T const* p) const
|
||||
{
|
||||
return p->in_avail();
|
||||
}
|
||||
|
||||
void operator()(boost::blank) const
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
// -------------- io_service -----------
|
||||
|
||||
template <class IOService>
|
||||
struct io_service_visitor
|
||||
: boost::static_visitor<IOService&>
|
||||
{
|
||||
template <class T>
|
||||
IOService& operator()(T* p) const
|
||||
{
|
||||
return p->get_io_service();
|
||||
}
|
||||
|
||||
IOService& operator()(boost::blank) const
|
||||
{
|
||||
return *(IOService*)0;
|
||||
}
|
||||
};
|
||||
|
||||
// -------------- lowest_layer -----------
|
||||
|
||||
template <class LowestLayer>
|
||||
struct lowest_layer_visitor
|
||||
: boost::static_visitor<LowestLayer&>
|
||||
{
|
||||
template <class T>
|
||||
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<types0, boost::mpl::void_>::type types;
|
||||
|
||||
typedef typename boost::make_variant_over<
|
||||
typename boost::mpl::push_back<
|
||||
typename boost::mpl::transform<
|
||||
types
|
||||
, boost::add_pointer<boost::mpl::_>
|
||||
>::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 <class S>
|
||||
void instantiate(io_service& ios)
|
||||
{
|
||||
TORRENT_ASSERT(&ios == &m_io_service);
|
||||
std::auto_ptr<S> owned(new S(ios));
|
||||
boost::apply_visitor(aux::delete_visitor(), m_variant);
|
||||
m_variant = owned.get();
|
||||
owned.release();
|
||||
}
|
||||
|
||||
template <class S>
|
||||
S* get()
|
||||
{
|
||||
S** ret = boost::get<S*>(&m_variant);
|
||||
if (!ret) return 0;
|
||||
return *ret;
|
||||
}
|
||||
|
||||
bool instantiated() const
|
||||
{
|
||||
return m_variant.which() != boost::mpl::size<types>::value;
|
||||
}
|
||||
|
||||
~variant_stream()
|
||||
{
|
||||
boost::apply_visitor(aux::delete_visitor(), m_variant);
|
||||
}
|
||||
|
||||
template <class Mutable_Buffers>
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
aux::read_some_visitor_ec<Mutable_Buffers>(buffers, ec)
|
||||
, m_variant
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
template <class Mutable_Buffers>
|
||||
std::size_t read_some(Mutable_Buffers const& buffers)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
aux::read_some_visitor<Mutable_Buffers>(buffers)
|
||||
, m_variant
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Mutable_Buffers, class Handler>
|
||||
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::async_read_some_visitor<Mutable_Buffers, Handler>(buffers, handler)
|
||||
, m_variant
|
||||
);
|
||||
}
|
||||
|
||||
template <class Const_Buffers, class Handler>
|
||||
void async_write_some(Const_Buffers const& buffers, Handler const& handler)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::async_write_some_visitor<Const_Buffers, Handler>(buffers, handler)
|
||||
, m_variant
|
||||
);
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::async_connect_visitor<endpoint_type, Handler>(endpoint, handler), m_variant
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
template <class IO_Control_Command>
|
||||
void io_control(IO_Control_Command& ioc)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::io_control_visitor<IO_Control_Command>(ioc), m_variant
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class IO_Control_Command>
|
||||
void io_control(IO_Control_Command& ioc, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::io_control_visitor_ec<IO_Control_Command>(ioc, ec)
|
||||
, m_variant
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
void bind(endpoint_type const& endpoint)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_variant);
|
||||
}
|
||||
#endif
|
||||
|
||||
void bind(endpoint_type const& endpoint, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::bind_visitor_ec<endpoint_type>(endpoint, ec), m_variant
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
void open(protocol_type const& p)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant);
|
||||
}
|
||||
#endif
|
||||
|
||||
void open(protocol_type const& p, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
aux::open_visitor_ec<protocol_type>(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<endpoint_type>(), m_variant);
|
||||
}
|
||||
#endif
|
||||
|
||||
endpoint_type remote_endpoint(error_code& ec) const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
aux::remote_endpoint_visitor_ec<endpoint_type>(ec), m_variant
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
template <class SettableSocketOption>
|
||||
void set_option(SettableSocketOption const& opt)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(aux::set_option_visitor<SettableSocketOption>(opt)
|
||||
, m_variant);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class SettableSocketOption>
|
||||
error_code set_option(SettableSocketOption const& opt, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSocketOption>(opt, ec)
|
||||
, m_variant);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
endpoint_type local_endpoint() const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
||||
}
|
||||
#endif
|
||||
|
||||
endpoint_type local_endpoint(error_code& ec) const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
aux::local_endpoint_visitor_ec<endpoint_type>(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<lowest_layer_type>(), m_variant
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
io_service& m_io_service;
|
||||
variant_type m_variant;
|
||||
};
|
||||
|
||||
} // namespace libtorrent
|
||||
|
||||
#endif // VARIANT_STREAM_070211_HPP
|
||||
|
|
@ -158,6 +158,9 @@ namespace libtorrent
|
|||
// 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.
|
||||
int m_body_start;
|
||||
|
|
|
@ -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<ssl_stream<socket_type> >(m_resolver.get_io_service());
|
||||
ssl_stream<socket_type>* s = m_sock.get<ssl_stream<socket_type> >();
|
||||
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<socket_type>(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<socket_type>());
|
||||
TORRENT_ASSERT(m_sock.get<socket_type>());
|
||||
TORRENT_ASSERT(m_sock.get<socket_type>()->get<i2p_stream>());
|
||||
}
|
||||
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<socket_type>());
|
||||
}
|
||||
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<socket_type>()->get<socks5_stream>());
|
||||
m_sock.get<socket_type>()->get<socks5_stream>()->set_dst_name(m_hostname);
|
||||
TORRENT_ASSERT(m_sock.get<ssl_stream<socks5_stream> >());
|
||||
m_sock.get<ssl_stream<socks5_stream> >()->next_layer().next_layer().set_dst_name(m_hostname);
|
||||
}
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
TORRENT_ASSERT(m_sock.get<socks5_stream>());
|
||||
m_sock.get<socks5_stream>()->set_dst_name(m_hostname);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect
|
||||
, shared_from_this(), _1));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (ssl_context)
|
||||
s.instantiate<ssl_stream<stream_socket> >(ios, ssl_context);
|
||||
else
|
||||
#endif
|
||||
s.instantiate<stream_socket>(ios);
|
||||
}
|
||||
else if (ps.type == proxy_settings::http
|
||||
|| ps.type == proxy_settings::http_pw)
|
||||
{
|
||||
http_stream* str;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (ssl_context)
|
||||
{
|
||||
s.instantiate<ssl_stream<http_stream> >(ios, ssl_context);
|
||||
str = &s.get<ssl_stream<http_stream> >()->next_layer().next_layer();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
s.instantiate<http_stream>(ios);
|
||||
s.get<http_stream>()->set_proxy(ps.hostname, ps.port);
|
||||
str = s.get<http_stream>();
|
||||
}
|
||||
|
||||
str->set_proxy(ps.hostname, ps.port);
|
||||
if (ps.type == proxy_settings::http_pw)
|
||||
s.get<http_stream>()->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)
|
||||
{
|
||||
socks5_stream* str;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (ssl_context)
|
||||
{
|
||||
s.instantiate<ssl_stream<socks5_stream> >(ios, ssl_context);
|
||||
str = &s.get<ssl_stream<socks5_stream> >()->next_layer().next_layer();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
s.instantiate<socks5_stream>(ios);
|
||||
s.get<socks5_stream>()->set_proxy(ps.hostname, ps.port);
|
||||
str = s.get<socks5_stream>();
|
||||
}
|
||||
str->set_proxy(ps.hostname, ps.port);
|
||||
if (ps.type == proxy_settings::socks5_pw)
|
||||
s.get<socks5_stream>()->set_username(ps.username, ps.password);
|
||||
str->set_username(ps.username, ps.password);
|
||||
if (ps.type == proxy_settings::socks4)
|
||||
s.get<socks5_stream>()->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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
|
@ -53,12 +57,23 @@ namespace libtorrent
|
|||
case socket_type_int_impl<i2p_stream>::value:
|
||||
get<i2p_stream>()->~i2p_stream();
|
||||
break;
|
||||
#endif
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
case socket_type_int_impl<ssl_stream<stream_socket> >::value:
|
||||
get<ssl_stream<stream_socket> >()->~ssl_stream();
|
||||
break;
|
||||
case socket_type_int_impl<ssl_stream<socks5_stream> >::value:
|
||||
get<ssl_stream<socks5_stream> >()->~ssl_stream();
|
||||
break;
|
||||
case socket_type_int_impl<ssl_stream<http_stream> >::value:
|
||||
get<ssl_stream<http_stream> >()->~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<i2p_stream>::value:
|
||||
new ((i2p_stream*)m_data) i2p_stream(m_io_service);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
case socket_type_int_impl<ssl_stream<stream_socket> >::value:
|
||||
TORRENT_ASSERT(userdata);
|
||||
new ((ssl_stream<stream_socket>*)m_data) ssl_stream<stream_socket>(m_io_service
|
||||
, *((boost::asio::ssl::context*)userdata));
|
||||
break;
|
||||
case socket_type_int_impl<ssl_stream<socks5_stream> >::value:
|
||||
TORRENT_ASSERT(userdata);
|
||||
new ((ssl_stream<socks5_stream>*)m_data) ssl_stream<socks5_stream>(m_io_service
|
||||
, *((boost::asio::ssl::context*)userdata));
|
||||
break;
|
||||
case socket_type_int_impl<ssl_stream<http_stream> >::value:
|
||||
TORRENT_ASSERT(userdata);
|
||||
new ((ssl_stream<http_stream>*)m_data) ssl_stream<http_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)) }
|
||||
|
||||
|
|
|
@ -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 <iostream>
|
||||
#endif
|
||||
|
@ -3532,13 +3536,19 @@ namespace libtorrent
|
|||
boost::shared_ptr<socket_type> 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<socks5_stream>());
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
socks5_stream* str = ssl
|
||||
? &s->get<ssl_stream<socks5_stream> >()->next_layer().next_layer()
|
||||
: s->get<socks5_stream>();
|
||||
#else
|
||||
socks5_stream* str = s->get<socks5_stream>();
|
||||
#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<socks5_stream>()->set_dst_name(hostname);
|
||||
str->set_dst_name(hostname);
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<peer_connection> c;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#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 <tmp");
|
||||
}
|
||||
|
||||
int port = 0;
|
||||
|
||||
web_server.reset(new libtorrent::thread(boost::bind(&web_server_thread, &port, ssl)));
|
||||
|
@ -532,7 +552,7 @@ int start_web_server(bool ssl)
|
|||
return port;
|
||||
}
|
||||
|
||||
void send_response(stream_socket& s, error_code& ec
|
||||
void send_response(socket_type& s, error_code& ec
|
||||
, int code, char const* status_message, char const* extra_header
|
||||
, int len)
|
||||
{
|
||||
|
@ -565,8 +585,6 @@ void on_accept(error_code const& ec)
|
|||
|
||||
void web_server_thread(int* port, bool ssl)
|
||||
{
|
||||
// TODO: support SSL
|
||||
|
||||
io_service ios;
|
||||
socket_acceptor acceptor(ios);
|
||||
error_code ec;
|
||||
|
@ -617,8 +635,19 @@ void web_server_thread(int* port, bool ssl)
|
|||
int len = 0;
|
||||
int offset = 0;
|
||||
bool connection_close = false;
|
||||
stream_socket s(ios);
|
||||
socket_type s(ios);
|
||||
void* ctx = 0;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
boost::asio::ssl::context ssl_ctx(ios, boost::asio::ssl::context::sslv2_server);
|
||||
ssl_ctx.use_certificate_chain_file("server.pem");
|
||||
ssl_ctx.use_private_key_file("server.pem", asio::ssl::context::pem);
|
||||
ssl_ctx.set_verify_mode(boost::asio::ssl::context::verify_none);
|
||||
|
||||
if (ssl) ctx = &ssl_ctx;
|
||||
#endif
|
||||
|
||||
proxy_settings p;
|
||||
instantiate_connection(ios, p, s, ctx);
|
||||
for (;;)
|
||||
{
|
||||
if (connection_close)
|
||||
|
@ -632,16 +661,31 @@ void web_server_thread(int* port, bool ssl)
|
|||
len = 0;
|
||||
offset = 0;
|
||||
|
||||
error_code ec;
|
||||
stream_socket* sock;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (ssl) sock = &s.get<ssl_stream<stream_socket> >()->next_layer().next_layer();
|
||||
else
|
||||
#endif
|
||||
sock = s.get<stream_socket>();
|
||||
|
||||
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<ssl_stream<stream_socket> >()->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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_info> torrent_file, int proxy, int port)
|
||||
void test_transfer(boost::intrusive_ptr<torrent_info> torrent_file
|
||||
, int proxy, int port, char const* protocol)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
|
@ -62,7 +63,7 @@ void test_transfer(boost::intrusive_ptr<torrent_info> 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_info> 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_info> 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue