initial https support for trackers and http_connection. Added support for proxies to http_connection
This commit is contained in:
parent
69f9a5b5fc
commit
61bbc6e58f
3
Jamfile
3
Jamfile
|
@ -45,7 +45,7 @@ rule linking ( properties * )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result += <library>crypto ;
|
result += <library>crypto <library>ssl ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +210,7 @@ lib thread : : <name>boost_thread $(library-search-path) ;
|
||||||
|
|
||||||
# openssl on linux/bsd/macos etc.
|
# openssl on linux/bsd/macos etc.
|
||||||
lib crypto : : <name>crypto ;
|
lib crypto : : <name>crypto ;
|
||||||
|
lib ssl : : <name>ssl ;
|
||||||
|
|
||||||
# time functions used on linux require librt
|
# time functions used on linux require librt
|
||||||
lib librt : : <name>rt ;
|
lib librt : : <name>rt ;
|
||||||
|
|
|
@ -45,6 +45,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/http_tracker_connection.hpp"
|
#include "libtorrent/http_tracker_connection.hpp"
|
||||||
#include "libtorrent/time.hpp"
|
#include "libtorrent/time.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
#include "libtorrent/socket_type.hpp"
|
||||||
|
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
#include "libtorrent/ssl_stream.hpp"
|
||||||
|
#include "libtorrent/variant_stream.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -57,6 +63,7 @@ typedef boost::function<void(asio::error_code const&
|
||||||
typedef boost::function<void(http_connection&)> http_connect_handler;
|
typedef boost::function<void(http_connection&)> http_connect_handler;
|
||||||
|
|
||||||
// TODO: add bind interface
|
// TODO: add bind interface
|
||||||
|
// TODO: add gzip support
|
||||||
|
|
||||||
// when bottled, the last two arguments to the handler
|
// when bottled, the last two arguments to the handler
|
||||||
// will always be 0
|
// will always be 0
|
||||||
|
@ -81,6 +88,7 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
||||||
, m_redirects(5)
|
, m_redirects(5)
|
||||||
, m_connection_ticket(-1)
|
, m_connection_ticket(-1)
|
||||||
, m_cc(cc)
|
, m_cc(cc)
|
||||||
|
, m_ssl(false)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!m_handler.empty());
|
TORRENT_ASSERT(!m_handler.empty());
|
||||||
}
|
}
|
||||||
|
@ -93,14 +101,20 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
||||||
std::string sendbuffer;
|
std::string sendbuffer;
|
||||||
|
|
||||||
void get(std::string const& url, time_duration timeout = seconds(30)
|
void get(std::string const& url, time_duration timeout = seconds(30)
|
||||||
, int handle_redirects = 5);
|
, proxy_settings const* ps = 0, int handle_redirects = 5);
|
||||||
|
|
||||||
void start(std::string const& hostname, std::string const& port
|
void start(std::string const& hostname, std::string const& port
|
||||||
, time_duration timeout, int handle_redirect = 5);
|
, time_duration timeout, proxy_settings const* ps = 0, bool ssl = false
|
||||||
|
, int handle_redirect = 5);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
tcp::socket const& socket() const { return m_sock; }
|
#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
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void on_resolve(asio::error_code const& e
|
void on_resolve(asio::error_code const& e
|
||||||
|
@ -118,7 +132,11 @@ private:
|
||||||
void callback(asio::error_code const& e, char const* data = 0, int size = 0);
|
void callback(asio::error_code const& e, char const* data = 0, int size = 0);
|
||||||
|
|
||||||
std::vector<char> m_recvbuffer;
|
std::vector<char> m_recvbuffer;
|
||||||
tcp::socket m_sock;
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
variant_stream<socket_type, ssl_stream<socket_type> > m_sock;
|
||||||
|
#else
|
||||||
|
socket_type m_sock;
|
||||||
|
#endif
|
||||||
int m_read_pos;
|
int m_read_pos;
|
||||||
tcp::resolver m_resolver;
|
tcp::resolver m_resolver;
|
||||||
http_parser m_parser;
|
http_parser m_parser;
|
||||||
|
@ -158,6 +176,13 @@ private:
|
||||||
|
|
||||||
int m_connection_ticket;
|
int m_connection_ticket;
|
||||||
connection_queue& m_cc;
|
connection_queue& m_cc;
|
||||||
|
|
||||||
|
// specifies whether or not the connection is
|
||||||
|
// configured to use a proxy
|
||||||
|
proxy_settings m_proxy;
|
||||||
|
|
||||||
|
// true if the connection is using ssl
|
||||||
|
bool m_ssl;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/connection_queue.hpp"
|
#include "libtorrent/connection_queue.hpp"
|
||||||
#include "libtorrent/http_parser.hpp"
|
#include "libtorrent/http_parser.hpp"
|
||||||
|
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
#include "libtorrent/ssl_stream.hpp"
|
||||||
|
#include "libtorrent/variant_stream.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -77,6 +82,7 @@ namespace libtorrent
|
||||||
, connection_queue& cc
|
, connection_queue& cc
|
||||||
, tracker_manager& man
|
, tracker_manager& man
|
||||||
, tracker_request const& req
|
, tracker_request const& req
|
||||||
|
, std::string const& protocol
|
||||||
, std::string const& hostname
|
, std::string const& hostname
|
||||||
, unsigned short port
|
, unsigned short port
|
||||||
, std::string request
|
, std::string request
|
||||||
|
@ -116,7 +122,12 @@ namespace libtorrent
|
||||||
|
|
||||||
tcp::resolver m_name_lookup;
|
tcp::resolver m_name_lookup;
|
||||||
int m_port;
|
int m_port;
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
variant_stream<socket_type, ssl_stream<socket_type> > m_socket;
|
||||||
|
bool m_ssl;
|
||||||
|
#else
|
||||||
socket_type m_socket;
|
socket_type m_socket;
|
||||||
|
#endif
|
||||||
int m_recv_pos;
|
int m_recv_pos;
|
||||||
std::vector<char> m_buffer;
|
std::vector<char> m_buffer;
|
||||||
std::string m_send_buffer;
|
std::string m_send_buffer;
|
||||||
|
@ -124,7 +135,7 @@ namespace libtorrent
|
||||||
session_settings const& m_settings;
|
session_settings const& m_settings;
|
||||||
proxy_settings const& m_proxy;
|
proxy_settings const& m_proxy;
|
||||||
std::string m_password;
|
std::string m_password;
|
||||||
|
|
||||||
bool m_timed_out;
|
bool m_timed_out;
|
||||||
|
|
||||||
int m_connection_ticket;
|
int m_connection_ticket;
|
||||||
|
|
|
@ -141,25 +141,25 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
endpoint_type remote_endpoint()
|
endpoint_type remote_endpoint() const
|
||||||
{
|
{
|
||||||
return m_remote_endpoint;
|
return m_remote_endpoint;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
endpoint_type remote_endpoint(asio::error_code& ec)
|
endpoint_type remote_endpoint(asio::error_code& ec) const
|
||||||
{
|
{
|
||||||
return m_remote_endpoint;
|
return m_remote_endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
endpoint_type local_endpoint()
|
endpoint_type local_endpoint() const
|
||||||
{
|
{
|
||||||
return m_sock.local_endpoint();
|
return m_sock.local_endpoint();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
endpoint_type local_endpoint(asio::error_code& ec)
|
endpoint_type local_endpoint(asio::error_code& ec) const
|
||||||
{
|
{
|
||||||
return m_sock.local_endpoint(ec);
|
return m_sock.local_endpoint(ec);
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,8 @@ public:
|
||||||
{
|
{
|
||||||
return m_sock.lowest_layer();
|
return m_sock.lowest_layer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_open() const { return m_sock.is_open(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2008, Arvid Norberg
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TORRENT_SSL_STREAM_HPP_INCLUDED
|
||||||
|
#define TORRENT_SSL_STREAM_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "libtorrent/socket.hpp"
|
||||||
|
#include <asio/ssl.hpp>
|
||||||
|
|
||||||
|
// openssl seems to believe it owns
|
||||||
|
// this name in every single scope
|
||||||
|
#undef set_key
|
||||||
|
|
||||||
|
namespace libtorrent {
|
||||||
|
|
||||||
|
template <class Stream>
|
||||||
|
class ssl_stream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ssl_stream(asio::io_service& io_service)
|
||||||
|
: m_context(io_service, asio::ssl::context::sslv23_client)
|
||||||
|
, m_sock(io_service, m_context)
|
||||||
|
{
|
||||||
|
m_context.set_verify_mode(asio::ssl::context::verify_none);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef 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;
|
||||||
|
typedef typename asio::ssl::stream<Stream> sock_type;
|
||||||
|
|
||||||
|
typedef boost::function<void(asio::error_code const&)> handler_type;
|
||||||
|
|
||||||
|
template <class Handler>
|
||||||
|
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||||
|
{
|
||||||
|
// the connect is split up in the following steps:
|
||||||
|
// 1. connect to peer
|
||||||
|
// 2. perform SSL client handshake
|
||||||
|
|
||||||
|
// to avoid unnecessary copying of the handler,
|
||||||
|
// store it in a shaed_ptr
|
||||||
|
boost::shared_ptr<handler_type> h(new handler_type(handler));
|
||||||
|
|
||||||
|
m_sock.next_layer().async_connect(endpoint
|
||||||
|
, boost::bind(&ssl_stream::connected, this, _1, h));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Mutable_Buffers, class Handler>
|
||||||
|
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
|
||||||
|
{
|
||||||
|
m_sock.async_read_some(buffers, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Mutable_Buffers>
|
||||||
|
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
return m_sock.read_some(buffers, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
template <class Mutable_Buffers>
|
||||||
|
std::size_t read_some(Mutable_Buffers const& buffers)
|
||||||
|
{
|
||||||
|
return m_sock.read_some(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class IO_Control_Command>
|
||||||
|
void io_control(IO_Control_Command& ioc)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().io_control(ioc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class IO_Control_Command>
|
||||||
|
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().io_control(ioc, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Const_Buffers, class Handler>
|
||||||
|
void async_write_some(Const_Buffers const& buffers, Handler const& handler)
|
||||||
|
{
|
||||||
|
m_sock.async_write_some(buffers, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
void bind(endpoint_type const& endpoint)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().bind(endpoint);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void bind(endpoint_type const& endpoint, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().bind(endpoint, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
void open(protocol_type const& p)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().open(p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void open(protocol_type const& p, asio::error_code& ec)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().open(p, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_open() const
|
||||||
|
{
|
||||||
|
return const_cast<sock_type&>(m_sock).next_layer().is_open();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
m_sock.next_layer().close();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void close(asio::error_code& ec)
|
||||||
|
{
|
||||||
|
m_sock.next_layer().close(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
endpoint_type remote_endpoint() const
|
||||||
|
{
|
||||||
|
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
endpoint_type remote_endpoint(asio::error_code& ec) const
|
||||||
|
{
|
||||||
|
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
|
endpoint_type local_endpoint() const
|
||||||
|
{
|
||||||
|
return const_cast<sock_type&>(m_sock).next_layer().local_endpoint();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
endpoint_type local_endpoint(asio::error_code& ec) const
|
||||||
|
{
|
||||||
|
return const_cast<sock_type&>(m_sock).next_layer().local_endpoint(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
asio::io_service& io_service()
|
||||||
|
{
|
||||||
|
return m_sock.io_service();
|
||||||
|
}
|
||||||
|
|
||||||
|
lowest_layer_type& lowest_layer()
|
||||||
|
{
|
||||||
|
return m_sock.lowest_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
next_layer_type& next_layer()
|
||||||
|
{
|
||||||
|
return m_sock.next_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||||
|
{
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
(*h)(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sock.async_handshake(asio::ssl::stream_base::client
|
||||||
|
, boost::bind(&ssl_stream::handshake, this, _1, h));
|
||||||
|
}
|
||||||
|
|
||||||
|
void handshake(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||||
|
{
|
||||||
|
(*h)(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
asio::ssl::context m_context;
|
||||||
|
asio::ssl::stream<Stream> m_sock;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -182,6 +182,20 @@ namespace aux
|
||||||
Protocol const& proto;
|
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 -----------
|
// -------------- close -----------
|
||||||
|
|
||||||
struct close_visitor_ec
|
struct close_visitor_ec
|
||||||
|
@ -221,7 +235,7 @@ namespace aux
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T* p) const
|
EndpointType operator()(T const* p) const
|
||||||
{ return p->remote_endpoint(error_code); }
|
{ return p->remote_endpoint(error_code); }
|
||||||
|
|
||||||
EndpointType operator()(boost::blank) const
|
EndpointType operator()(boost::blank) const
|
||||||
|
@ -235,7 +249,7 @@ namespace aux
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T* p) const
|
EndpointType operator()(T const* p) const
|
||||||
{ return p->remote_endpoint(); }
|
{ return p->remote_endpoint(); }
|
||||||
|
|
||||||
EndpointType operator()(boost::blank) const
|
EndpointType operator()(boost::blank) const
|
||||||
|
@ -253,7 +267,7 @@ namespace aux
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T* p) const
|
EndpointType operator()(T const* p) const
|
||||||
{
|
{
|
||||||
return p->local_endpoint(error_code);
|
return p->local_endpoint(error_code);
|
||||||
}
|
}
|
||||||
|
@ -271,7 +285,7 @@ namespace aux
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T* p) const
|
EndpointType operator()(T const* p) const
|
||||||
{
|
{
|
||||||
return p->local_endpoint();
|
return p->local_endpoint();
|
||||||
}
|
}
|
||||||
|
@ -379,7 +393,7 @@ namespace aux
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
std::size_t operator()(T* p) const
|
std::size_t operator()(T const* p) const
|
||||||
{
|
{
|
||||||
return p->in_avail(ec);
|
return p->in_avail(ec);
|
||||||
}
|
}
|
||||||
|
@ -396,7 +410,7 @@ namespace aux
|
||||||
: boost::static_visitor<std::size_t>
|
: boost::static_visitor<std::size_t>
|
||||||
{
|
{
|
||||||
template <class T>
|
template <class T>
|
||||||
std::size_t operator()(T* p) const
|
std::size_t operator()(T const* p) const
|
||||||
{
|
{
|
||||||
return p->in_avail();
|
return p->in_avail();
|
||||||
}
|
}
|
||||||
|
@ -414,7 +428,7 @@ namespace aux
|
||||||
template <class T>
|
template <class T>
|
||||||
IOService& operator()(T* p) const
|
IOService& operator()(T* p) const
|
||||||
{
|
{
|
||||||
return p->io_service();
|
return p->get_io_service();
|
||||||
}
|
}
|
||||||
|
|
||||||
IOService& operator()(boost::blank) const
|
IOService& operator()(boost::blank) const
|
||||||
|
@ -471,11 +485,13 @@ public:
|
||||||
typedef typename S0::endpoint_type endpoint_type;
|
typedef typename S0::endpoint_type endpoint_type;
|
||||||
typedef typename S0::protocol_type protocol_type;
|
typedef typename S0::protocol_type protocol_type;
|
||||||
|
|
||||||
explicit variant_stream() : m_variant(boost::blank()) {}
|
explicit variant_stream(asio::io_service& ios)
|
||||||
|
: m_io_service(ios), m_variant(boost::blank()) {}
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
void instantiate(asio::io_service& ios)
|
void instantiate(asio::io_service& ios)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(&ios == &m_io_service);
|
||||||
std::auto_ptr<S> owned(new S(ios));
|
std::auto_ptr<S> owned(new S(ios));
|
||||||
boost::apply_visitor(aux::delete_visitor(), m_variant);
|
boost::apply_visitor(aux::delete_visitor(), m_variant);
|
||||||
m_variant = owned.get();
|
m_variant = owned.get();
|
||||||
|
@ -594,6 +610,11 @@ public:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_open() const
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(aux::is_open_visitor(), m_variant);
|
||||||
|
}
|
||||||
|
|
||||||
void close()
|
void close()
|
||||||
{
|
{
|
||||||
if (!instantiated()) return;
|
if (!instantiated()) return;
|
||||||
|
@ -608,13 +629,13 @@ public:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t in_avail()
|
std::size_t in_avail() const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
|
return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t in_avail(asio::error_code& ec)
|
std::size_t in_avail(asio::error_code& ec) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
|
@ -622,13 +643,13 @@ public:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint_type remote_endpoint()
|
endpoint_type remote_endpoint() const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
|
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint_type remote_endpoint(asio::error_code& ec)
|
endpoint_type remote_endpoint(asio::error_code& ec) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
|
@ -636,13 +657,13 @@ public:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint_type local_endpoint()
|
endpoint_type local_endpoint() const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint_type local_endpoint(asio::error_code& ec)
|
endpoint_type local_endpoint(asio::error_code& ec) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
|
@ -650,12 +671,9 @@ public:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::io_service& io_service()
|
asio::io_service& get_io_service()
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
return m_io_service;
|
||||||
return boost::apply_visitor(
|
|
||||||
aux::io_service_visitor<asio::io_service>(), m_variant
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lowest_layer_type& lowest_layer()
|
lowest_layer_type& lowest_layer()
|
||||||
|
@ -667,6 +685,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
asio::io_service& m_io_service;
|
||||||
variant_type m_variant;
|
variant_type m_variant;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1742,7 +1742,7 @@ namespace libtorrent
|
||||||
|
|
||||||
// vc,crypto_select,len(pad),pad, encrypt(handshake)
|
// vc,crypto_select,len(pad),pad, encrypt(handshake)
|
||||||
// 8+4+2+0+handshake_len
|
// 8+4+2+0+handshake_len
|
||||||
reset_recv_buffer(8+4+2+0+handshake_len);
|
reset_recv_buffer(8+4+2+0+handshake_len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "libtorrent/http_connection.hpp"
|
#include "libtorrent/http_connection.hpp"
|
||||||
#include "libtorrent/escape_string.hpp"
|
#include "libtorrent/escape_string.hpp"
|
||||||
|
#include "libtorrent/instantiate_connection.hpp"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
@ -46,7 +47,7 @@ namespace libtorrent
|
||||||
enum { max_bottled_buffer = 1024 * 1024 };
|
enum { max_bottled_buffer = 1024 * 1024 };
|
||||||
|
|
||||||
void http_connection::get(std::string const& url, time_duration timeout
|
void http_connection::get(std::string const& url, time_duration timeout
|
||||||
, int handle_redirects)
|
, proxy_settings const* ps, int handle_redirects)
|
||||||
{
|
{
|
||||||
std::string protocol;
|
std::string protocol;
|
||||||
std::string auth;
|
std::string auth;
|
||||||
|
@ -54,21 +55,55 @@ void http_connection::get(std::string const& url, time_duration timeout
|
||||||
std::string path;
|
std::string path;
|
||||||
int port;
|
int port;
|
||||||
boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url);
|
boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url);
|
||||||
|
|
||||||
|
bool ssl = false;
|
||||||
|
if (protocol == "https") ssl = true;
|
||||||
|
#ifndef TORRENT_USE_OPENSSL
|
||||||
|
if (ssl)
|
||||||
|
{
|
||||||
|
callback(asio::error::not_supported);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::stringstream headers;
|
std::stringstream headers;
|
||||||
headers << "GET " << path << " HTTP/1.0\r\n"
|
if (ps && (ps->type == proxy_settings::http
|
||||||
"Host:" << hostname <<
|
|| ps->type == proxy_settings::http_pw)
|
||||||
"\r\nConnection: close\r\n";
|
&& !ssl)
|
||||||
|
{
|
||||||
|
// if we're using an http proxy and not an ssl
|
||||||
|
// connection, just do a regular http proxy request
|
||||||
|
headers << "GET " << url << " HTTP/1.0\r\n"
|
||||||
|
"Connection: close\r\n";
|
||||||
|
if (ps->type == proxy_settings::http_pw)
|
||||||
|
headers << "Proxy-Authorization: Basic " << base64encode(
|
||||||
|
ps->username + ":" + ps->password) << "\r\n";
|
||||||
|
hostname = ps->hostname;
|
||||||
|
port = ps->port;
|
||||||
|
ps = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headers << "GET " << path << " HTTP/1.0\r\n"
|
||||||
|
"Host:" << hostname << "\r\n"
|
||||||
|
"Connection: close\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (!auth.empty())
|
if (!auth.empty())
|
||||||
headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
|
headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
|
||||||
headers << "\r\n";
|
headers << "\r\n";
|
||||||
sendbuffer = headers.str();
|
sendbuffer = headers.str();
|
||||||
start(hostname, boost::lexical_cast<std::string>(port), timeout, handle_redirects);
|
start(hostname, boost::lexical_cast<std::string>(port), timeout, ps
|
||||||
|
, ssl, handle_redirects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_connection::start(std::string const& hostname, std::string const& port
|
void http_connection::start(std::string const& hostname, std::string const& port
|
||||||
, time_duration timeout, int handle_redirects)
|
, time_duration timeout, proxy_settings const* ps, bool ssl, int handle_redirects)
|
||||||
{
|
{
|
||||||
m_redirects = handle_redirects;
|
m_redirects = handle_redirects;
|
||||||
|
if (ps) m_proxy = *ps;
|
||||||
|
|
||||||
|
m_ssl = ssl;
|
||||||
m_timeout = timeout;
|
m_timeout = timeout;
|
||||||
asio::error_code ec;
|
asio::error_code ec;
|
||||||
m_timer.expires_from_now(m_timeout, ec);
|
m_timer.expires_from_now(m_timeout, ec);
|
||||||
|
@ -78,6 +113,7 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
||||||
m_parser.reset();
|
m_parser.reset();
|
||||||
m_recvbuffer.clear();
|
m_recvbuffer.clear();
|
||||||
m_read_pos = 0;
|
m_read_pos = 0;
|
||||||
|
|
||||||
if (m_sock.is_open() && m_hostname == hostname && m_port == port)
|
if (m_sock.is_open() && m_hostname == hostname && m_port == port)
|
||||||
{
|
{
|
||||||
asio::async_write(m_sock, asio::buffer(sendbuffer)
|
asio::async_write(m_sock, asio::buffer(sendbuffer)
|
||||||
|
@ -87,6 +123,27 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
asio::error_code ec;
|
||||||
m_sock.close(ec);
|
m_sock.close(ec);
|
||||||
|
|
||||||
|
#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> >();
|
||||||
|
bool ret = instantiate_connection(m_resolver.get_io_service(), m_proxy, s.next_layer());
|
||||||
|
TORRENT_ASSERT(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sock.instantiate<socket_type>(m_resolver.get_io_service());
|
||||||
|
bool ret = instantiate_connection(m_resolver.get_io_service()
|
||||||
|
, m_proxy, m_sock.get<socket_type>());
|
||||||
|
TORRENT_ASSERT(ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool ret = instantiate_connection(m_resolver.get_io_service(), m_proxy, m_sock);
|
||||||
|
TORRENT_ASSERT(ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
tcp::resolver::query query(hostname, port);
|
tcp::resolver::query query(hostname, port);
|
||||||
m_resolver.async_resolve(query, bind(&http_connection::on_resolve
|
m_resolver.async_resolve(query, bind(&http_connection::on_resolve
|
||||||
, shared_from_this(), _1, _2));
|
, shared_from_this(), _1, _2));
|
||||||
|
@ -295,7 +352,7 @@ void http_connection::on_read(asio::error_code const& e
|
||||||
|
|
||||||
asio::error_code ec;
|
asio::error_code ec;
|
||||||
m_sock.close(ec);
|
m_sock.close(ec);
|
||||||
get(url, m_timeout, m_redirects - 1);
|
get(url, m_timeout, &m_proxy, m_redirects - 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,7 @@ namespace libtorrent
|
||||||
, connection_queue& cc
|
, connection_queue& cc
|
||||||
, tracker_manager& man
|
, tracker_manager& man
|
||||||
, tracker_request const& req
|
, tracker_request const& req
|
||||||
|
, std::string const& protocol
|
||||||
, std::string const& hostname
|
, std::string const& hostname
|
||||||
, unsigned short port
|
, unsigned short port
|
||||||
, std::string request
|
, std::string request
|
||||||
|
@ -112,6 +113,10 @@ namespace libtorrent
|
||||||
, m_man(man)
|
, m_man(man)
|
||||||
, m_name_lookup(ios)
|
, m_name_lookup(ios)
|
||||||
, m_port(port)
|
, m_port(port)
|
||||||
|
, m_socket(ios)
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
, m_ssl(protocol == "https")
|
||||||
|
#endif
|
||||||
, m_recv_pos(0)
|
, m_recv_pos(0)
|
||||||
, m_buffer(http_buffer_size)
|
, m_buffer(http_buffer_size)
|
||||||
, m_settings(stn)
|
, m_settings(stn)
|
||||||
|
@ -390,9 +395,25 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb) cb->m_tracker_address = target_address;
|
if (cb) cb->m_tracker_address = target_address;
|
||||||
bool ret = instantiate_connection(m_name_lookup.get_io_service(), m_proxy, m_socket);
|
asio::io_service& ios = m_name_lookup.io_service();
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
if (m_ssl)
|
||||||
|
{
|
||||||
|
m_socket.instantiate<ssl_stream<socket_type> >(ios);
|
||||||
|
ssl_stream<socket_type>& s = m_socket.get<ssl_stream<socket_type> >();
|
||||||
|
bool ret = instantiate_connection(ios, m_proxy, s.next_layer());
|
||||||
|
TORRENT_ASSERT(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_socket.instantiate<socket_type>(ios);
|
||||||
|
bool ret = instantiate_connection(ios, m_proxy, m_socket.get<socket_type>());
|
||||||
|
TORRENT_ASSERT(ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool ret = instantiate_connection(ios, m_proxy, m_socket);
|
||||||
TORRENT_ASSERT(ret);
|
TORRENT_ASSERT(ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (m_proxy.type == proxy_settings::http
|
if (m_proxy.type == proxy_settings::http
|
||||||
|| m_proxy.type == proxy_settings::http_pw)
|
|| m_proxy.type == proxy_settings::http_pw)
|
||||||
|
|
|
@ -698,7 +698,7 @@ namespace detail
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " aborting all torrents\n";
|
(*m_logger) << time_now_string() << " aborting all torrents (" << m_torrents.size() << ")\n";
|
||||||
#endif
|
#endif
|
||||||
// abort all torrents
|
// abort all torrents
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
for (torrent_map::iterator i = m_torrents.begin()
|
||||||
|
@ -1006,7 +1006,7 @@ namespace detail
|
||||||
|
|
||||||
void session_impl::async_accept(boost::shared_ptr<socket_acceptor> const& listener)
|
void session_impl::async_accept(boost::shared_ptr<socket_acceptor> const& listener)
|
||||||
{
|
{
|
||||||
shared_ptr<socket_type> c(new socket_type);
|
shared_ptr<socket_type> c(new socket_type(m_io_service));
|
||||||
c->instantiate<stream_socket>(m_io_service);
|
c->instantiate<stream_socket>(m_io_service);
|
||||||
listener->async_accept(c->get<stream_socket>()
|
listener->async_accept(c->get<stream_socket>()
|
||||||
, bind(&session_impl::on_incoming_connection, this, c
|
, bind(&session_impl::on_incoming_connection, this, c
|
||||||
|
@ -1622,8 +1622,9 @@ namespace detail
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " locking mutex\n";
|
(*m_logger) << time_now_string() << " locking mutex\n";
|
||||||
#endif
|
#endif
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
|
||||||
|
|
||||||
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
|
/*
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for (torrent_map::iterator i = m_torrents.begin();
|
for (torrent_map::iterator i = m_torrents.begin();
|
||||||
i != m_torrents.end(); ++i)
|
i != m_torrents.end(); ++i)
|
||||||
|
@ -1631,7 +1632,7 @@ namespace detail
|
||||||
TORRENT_ASSERT(i->second->num_peers() == 0);
|
TORRENT_ASSERT(i->second->num_peers() == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " cleaning up torrents\n";
|
(*m_logger) << time_now_string() << " cleaning up torrents\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -520,7 +520,7 @@ namespace libtorrent
|
||||||
// tracker request
|
// tracker request
|
||||||
bool torrent::should_request()
|
bool torrent::should_request()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
if (m_trackers.empty()) return false;
|
if (m_trackers.empty()) return false;
|
||||||
|
|
||||||
|
@ -1782,7 +1782,7 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<socket_type> s(new socket_type);
|
boost::shared_ptr<socket_type> s(new socket_type(m_ses.m_io_service));
|
||||||
|
|
||||||
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s);
|
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s);
|
||||||
TORRENT_ASSERT(ret);
|
TORRENT_ASSERT(ret);
|
||||||
|
@ -2087,7 +2087,7 @@ namespace libtorrent
|
||||||
tcp::endpoint const& a(peerinfo->ip);
|
tcp::endpoint const& a(peerinfo->ip);
|
||||||
TORRENT_ASSERT((m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) == 0);
|
TORRENT_ASSERT((m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) == 0);
|
||||||
|
|
||||||
boost::shared_ptr<socket_type> s(new socket_type);
|
boost::shared_ptr<socket_type> s(new socket_type(m_ses.m_io_service));
|
||||||
|
|
||||||
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
|
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
|
||||||
TORRENT_ASSERT(ret);
|
TORRENT_ASSERT(ret);
|
||||||
|
|
|
@ -355,7 +355,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
std::string hostname; // hostname only
|
std::string hostname; // hostname only
|
||||||
std::string auth; // user:pass
|
std::string auth; // user:pass
|
||||||
std::string protocol; // should be http
|
std::string protocol; // http or https for instance
|
||||||
int port = 80;
|
int port = 80;
|
||||||
|
|
||||||
std::string::iterator at;
|
std::string::iterator at;
|
||||||
|
@ -371,6 +371,8 @@ namespace libtorrent
|
||||||
= std::find(url.begin(), url.end(), ':');
|
= std::find(url.begin(), url.end(), ':');
|
||||||
protocol.assign(start, end);
|
protocol.assign(start, end);
|
||||||
|
|
||||||
|
if (protocol == "https") port = 443;
|
||||||
|
|
||||||
if (end == url.end()) goto exit;
|
if (end == url.end()) goto exit;
|
||||||
++end;
|
++end;
|
||||||
if (end == url.end()) goto exit;
|
if (end == url.end()) goto exit;
|
||||||
|
@ -453,13 +455,18 @@ exit:
|
||||||
|
|
||||||
boost::intrusive_ptr<tracker_connection> con;
|
boost::intrusive_ptr<tracker_connection> con;
|
||||||
|
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
if (protocol == "http" || protocol == "https")
|
||||||
|
#else
|
||||||
if (protocol == "http")
|
if (protocol == "http")
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
con = new http_tracker_connection(
|
con = new http_tracker_connection(
|
||||||
ios
|
ios
|
||||||
, cc
|
, cc
|
||||||
, *this
|
, *this
|
||||||
, req
|
, req
|
||||||
|
, protocol
|
||||||
, hostname
|
, hostname
|
||||||
, port
|
, port
|
||||||
, request_string
|
, request_string
|
||||||
|
|
|
@ -67,17 +67,34 @@ void stop_web_server(int port)
|
||||||
system(cmd.str().c_str());
|
system(cmd.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_web_server(int port)
|
void start_web_server(int port, bool ssl)
|
||||||
{
|
{
|
||||||
stop_web_server(port);
|
stop_web_server(port);
|
||||||
std::ofstream f("./lighty_config");
|
|
||||||
|
if (ssl)
|
||||||
|
{
|
||||||
|
system("echo -e \"AU\\ntest province\\ntest city\\ntest company\\n"
|
||||||
|
"test department\\ntester\\ntest@test.com\" | "
|
||||||
|
"openssl req -new -x509 -keyout server.pem -out server.pem "
|
||||||
|
"-days 365 -nodes");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream f("lighty_config");
|
||||||
f << "server.modules = (\"mod_access\", \"mod_redirect\")\n"
|
f << "server.modules = (\"mod_access\", \"mod_redirect\")\n"
|
||||||
"server.document-root = \"" << boost::filesystem::initial_path().string() << "\"\n"
|
"server.document-root = \"" << boost::filesystem::initial_path().string() << "\"\n"
|
||||||
"server.range-requests = \"enable\"\n"
|
"server.range-requests = \"enable\"\n"
|
||||||
"server.port = " << port << "\n"
|
"server.port = " << port << "\n"
|
||||||
"server.pid-file = \"./lighty" << port << ".pid\"\n"
|
"server.pid-file = \"./lighty" << port << ".pid\"\n"
|
||||||
"url.redirect = (\"^/redirect$\" => \"http://127.0.0.1:" << port << "/test_file\", "
|
"url.redirect = (\"^/redirect$\" => \""
|
||||||
"\"^/infinite_redirect$\" => \"http://127.0.0.1:" << port << "/infinite_redirect\")";
|
<< (ssl?"https":"http") << "://127.0.0.1:" << port << "/test_file\", "
|
||||||
|
"\"^/infinite_redirect$\" => \""
|
||||||
|
<< (ssl?"https":"http") << "://127.0.0.1:" << port << "/infinite_redirect\")\n";
|
||||||
|
// this requires lighttpd to be built with ssl support.
|
||||||
|
// The port distribution for mac is not built with ssl
|
||||||
|
// support by default.
|
||||||
|
if (ssl)
|
||||||
|
f << "ssl.engine = \"enable\"\n"
|
||||||
|
"ssl.pemfile = \"server.pem\"\n";
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
system("lighttpd -f lighty_config &");
|
system("lighttpd -f lighty_config &");
|
||||||
|
@ -98,7 +115,8 @@ void start_proxy(int port, int proxy_type)
|
||||||
stop_proxy(port);
|
stop_proxy(port);
|
||||||
std::stringstream cmd;
|
std::stringstream cmd;
|
||||||
// we need to echo n since dg will ask us to configure it
|
// we need to echo n since dg will ask us to configure it
|
||||||
cmd << "echo n | delegated -P" << port << " ADMIN=test@test.com";
|
cmd << "echo n | delegated -P" << port << " ADMIN=test@test.com "
|
||||||
|
"PERMIT=\"*:*:localhost\" REMITTABLE=+,https RELAY=proxy,delegate";
|
||||||
switch (proxy_type)
|
switch (proxy_type)
|
||||||
{
|
{
|
||||||
case proxy_settings::socks4:
|
case proxy_settings::socks4:
|
||||||
|
@ -118,6 +136,7 @@ void start_proxy(int port, int proxy_type)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
system(cmd.str().c_str());
|
system(cmd.str().c_str());
|
||||||
|
test_sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
|
@ -18,7 +18,7 @@ setup_transfer(libtorrent::session* ses1, libtorrent::session* ses2
|
||||||
, libtorrent::session* ses3, bool clear_files, bool use_metadata_transfer = true
|
, libtorrent::session* ses3, bool clear_files, bool use_metadata_transfer = true
|
||||||
, bool connect = true, std::string suffix = "");
|
, bool connect = true, std::string suffix = "");
|
||||||
|
|
||||||
void start_web_server(int port);
|
void start_web_server(int port, bool ssl = false);
|
||||||
void stop_web_server(int port);
|
void stop_web_server(int port);
|
||||||
void start_proxy(int port, int type);
|
void start_proxy(int port, int type);
|
||||||
void stop_proxy(int port);
|
void stop_proxy(int port);
|
||||||
|
|
|
@ -66,7 +66,8 @@ void reset_globals()
|
||||||
error_code = asio::error_code();
|
error_code = asio::error_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_test(char const* url, int size, int status, int connected, boost::optional<asio::error_code> ec)
|
void run_test(std::string const& url, int size, int status, int connected
|
||||||
|
, boost::optional<asio::error_code> ec, proxy_settings const& ps)
|
||||||
{
|
{
|
||||||
reset_globals();
|
reset_globals();
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ void run_test(char const* url, int size, int status, int connected, boost::optio
|
||||||
|
|
||||||
boost::shared_ptr<http_connection> h(new http_connection(ios, cq
|
boost::shared_ptr<http_connection> h(new http_connection(ios, cq
|
||||||
, &::http_handler, true, &::http_connect_handler));
|
, &::http_handler, true, &::http_connect_handler));
|
||||||
h->get(url);
|
h->get(url, seconds(30), &ps);
|
||||||
ios.reset();
|
ios.reset();
|
||||||
ios.run();
|
ios.run();
|
||||||
|
|
||||||
|
@ -90,19 +91,63 @@ void run_test(char const* url, int size, int status, int connected, boost::optio
|
||||||
TEST_CHECK(http_status == status || status == -1);
|
TEST_CHECK(http_status == status || status == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void run_suite(std::string const& protocol, proxy_settings const& ps)
|
||||||
|
{
|
||||||
|
if (ps.type != proxy_settings::none)
|
||||||
|
{
|
||||||
|
start_proxy(ps.port, ps.type);
|
||||||
|
}
|
||||||
|
char const* test_name[] = {"no", "SOCKS4", "SOCKS5"
|
||||||
|
, "SOCKS5 password protected", "HTTP", "HTTP password protected"};
|
||||||
|
std::cout << "\n\n********************** using " << test_name[ps.type]
|
||||||
|
<< " proxy **********************\n" << std::endl;
|
||||||
|
|
||||||
|
typedef boost::optional<asio::error_code> err;
|
||||||
|
run_test(protocol + "://127.0.0.1:8001/redirect", 3216, 200, 2, asio::error_code(), ps);
|
||||||
|
run_test(protocol + "://127.0.0.1:8001/infinite_redirect", 0, 301, 6, asio::error_code(), ps);
|
||||||
|
run_test(protocol + "://127.0.0.1:8001/test_file", 3216, 200, 1, asio::error_code(), ps);
|
||||||
|
run_test(protocol + "://127.0.0.1:8001/non-existing-file", -1, 404, 1, err(), ps);
|
||||||
|
// if we're going through an http proxy, we won't get the same error as if the hostname
|
||||||
|
// resolution failed
|
||||||
|
if ((ps.type == proxy_settings::http || ps.type == proxy_settings::http_pw) && protocol != "https")
|
||||||
|
run_test(protocol + "://non-existent-domain.se/non-existing-file", -1, 502, 1, err(), ps);
|
||||||
|
else
|
||||||
|
run_test(protocol + "://non-existent-domain.se/non-existing-file", -1, -1, 0, err(asio::error::host_not_found), ps);
|
||||||
|
|
||||||
|
if (ps.type != proxy_settings::none)
|
||||||
|
stop_proxy(ps.port);
|
||||||
|
}
|
||||||
|
|
||||||
int test_main()
|
int test_main()
|
||||||
{
|
{
|
||||||
typedef boost::optional<asio::error_code> err;
|
|
||||||
start_web_server(8001);
|
|
||||||
std::srand(std::time(0));
|
std::srand(std::time(0));
|
||||||
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
||||||
std::ofstream("test_file").write(data_buffer, 3216);
|
std::ofstream("test_file").write(data_buffer, 3216);
|
||||||
run_test("http://127.0.0.1:8001/redirect", 3216, 200, 2, asio::error_code());
|
|
||||||
run_test("http://127.0.0.1:8001/infinite_redirect", 0, 301, 6, asio::error_code());
|
proxy_settings ps;
|
||||||
run_test("http://127.0.0.1:8001/test_file", 3216, 200, 1, asio::error_code());
|
ps.hostname = "127.0.0.1";
|
||||||
run_test("http://127.0.0.1:8001/non-existing-file", -1, 404, 1, err());
|
ps.port = 8034;
|
||||||
run_test("http://non-existent-domain.se/non-existing-file", -1, -1, 0, err(asio::error::host_not_found));
|
ps.username = "testuser";
|
||||||
|
ps.password = "testpass";
|
||||||
|
|
||||||
|
start_web_server(8001);
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
ps.type = (proxy_settings::proxy_type)i;
|
||||||
|
run_suite("http", ps);
|
||||||
|
}
|
||||||
stop_web_server(8001);
|
stop_web_server(8001);
|
||||||
|
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
start_web_server(8001, true);
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
ps.type = (proxy_settings::proxy_type)i;
|
||||||
|
run_suite("https", ps);
|
||||||
|
}
|
||||||
|
stop_web_server(8001);
|
||||||
|
#endif
|
||||||
|
|
||||||
std::remove("test_file");
|
std::remove("test_file");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue