experimental support for incoming connections over socks (untested)
This commit is contained in:
parent
a956265be4
commit
41be942ae7
|
@ -153,8 +153,12 @@ namespace libtorrent
|
|||
tcp::endpoint get_ipv6_interface() const;
|
||||
|
||||
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
|
||||
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
|
||||
void on_accept_connection(boost::shared_ptr<socket_type> const& s
|
||||
, boost::weak_ptr<socket_acceptor> listener, error_code const& e);
|
||||
void on_socks_accept(boost::shared_ptr<socket_type> const& s
|
||||
, error_code const& e);
|
||||
|
||||
void incoming_connection(boost::shared_ptr<socket_type> const& s);
|
||||
|
||||
// must be locked to access the data
|
||||
// in this struct
|
||||
|
@ -254,7 +258,12 @@ namespace libtorrent
|
|||
void announce_lsd(sha1_hash const& ih);
|
||||
|
||||
void set_peer_proxy(proxy_settings const& s)
|
||||
{ m_peer_proxy = s; }
|
||||
{
|
||||
m_peer_proxy = s;
|
||||
// in case we just set a socks proxy, we might have to
|
||||
// open the socks incoming connection
|
||||
if (!m_socks_listen_socket) open_new_incoming_socks_connection();
|
||||
}
|
||||
void set_web_seed_proxy(proxy_settings const& s)
|
||||
{ m_web_seed_proxy = s; }
|
||||
void set_tracker_proxy(proxy_settings const& s)
|
||||
|
@ -442,6 +451,12 @@ namespace libtorrent
|
|||
// we might need more than one listen socket
|
||||
std::list<listen_socket_t> m_listen_sockets;
|
||||
|
||||
// when as a socks proxy is used for peers, also
|
||||
// listen for incoming connections on a socks connection
|
||||
boost::shared_ptr<socket_type> m_socks_listen_socket;
|
||||
|
||||
void open_new_incoming_socks_connection();
|
||||
|
||||
listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false);
|
||||
|
||||
// the settings for the client
|
||||
|
|
|
@ -74,10 +74,13 @@ public:
|
|||
: proxy_base(io_service)
|
||||
, m_version(5)
|
||||
, m_command(1)
|
||||
, m_listen(0)
|
||||
{}
|
||||
|
||||
void set_version(int v) { m_version = v; }
|
||||
|
||||
void set_command(int c) { m_command = c; }
|
||||
|
||||
void set_username(std::string const& user
|
||||
, std::string const& password)
|
||||
{
|
||||
|
@ -134,6 +137,9 @@ private:
|
|||
std::string m_password;
|
||||
int m_version;
|
||||
int m_command;
|
||||
// set to one when we're waiting for the
|
||||
// second message to accept an incoming connection
|
||||
int m_listen;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/upnp.hpp"
|
||||
#include "libtorrent/natpmp.hpp"
|
||||
#include "libtorrent/lsd.hpp"
|
||||
#include "libtorrent/instantiate_connection.hpp"
|
||||
|
||||
#ifndef TORRENT_WINDOWS
|
||||
#include <sys/resource.h>
|
||||
|
@ -766,8 +767,14 @@ namespace aux {
|
|||
}
|
||||
}
|
||||
|
||||
open_new_incoming_socks_connection();
|
||||
|
||||
// figure out which IPv6 address we're listening on
|
||||
// or at least one of them. This is used to announce
|
||||
// to the tracker
|
||||
m_ipv6_interface = tcp::endpoint();
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
|
||||
, end(m_listen_sockets.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -798,6 +805,7 @@ namespace aux {
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif // TORRENT_USE_IPV6
|
||||
|
||||
if (!m_listen_sockets.empty())
|
||||
{
|
||||
|
@ -825,6 +833,25 @@ namespace aux {
|
|||
#endif
|
||||
}
|
||||
|
||||
void session_impl::open_new_incoming_socks_connection()
|
||||
{
|
||||
if (m_peer_proxy.type != proxy_settings::socks5
|
||||
&& m_peer_proxy.type != proxy_settings::socks5_pw
|
||||
&& m_peer_proxy.type != proxy_settings::socks4)
|
||||
return;
|
||||
|
||||
if (m_socks_listen_socket) return;
|
||||
|
||||
bool ret = instantiate_connection(m_io_service, m_peer_proxy
|
||||
, *m_socks_listen_socket);
|
||||
TORRENT_ASSERT(ret);
|
||||
|
||||
socks5_stream& s = *m_socks_listen_socket->get<socks5_stream>();
|
||||
s.set_command(2); // 2 means BIND (as opposed to CONNECT)
|
||||
s.async_connect(tcp::endpoint(address_v4::any(), m_listen_interface.port())
|
||||
, boost::bind(&session_impl::on_socks_accept, this, m_socks_listen_socket, _1));
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
||||
void session_impl::on_receive_udp(error_code const& e
|
||||
|
@ -856,11 +883,11 @@ namespace aux {
|
|||
shared_ptr<socket_type> c(new socket_type(m_io_service));
|
||||
c->instantiate<stream_socket>(m_io_service);
|
||||
listener->async_accept(*c->get<stream_socket>()
|
||||
, bind(&session_impl::on_incoming_connection, this, c
|
||||
, bind(&session_impl::on_accept_connection, this, c
|
||||
, boost::weak_ptr<socket_acceptor>(listener), _1));
|
||||
}
|
||||
|
||||
void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
|
||||
void session_impl::on_accept_connection(shared_ptr<socket_type> const& s
|
||||
, weak_ptr<socket_acceptor> listen_socket, error_code const& e)
|
||||
{
|
||||
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
|
||||
|
@ -904,6 +931,12 @@ namespace aux {
|
|||
}
|
||||
async_accept(listener);
|
||||
|
||||
incoming_connection(s);
|
||||
}
|
||||
|
||||
void session_impl::incoming_connection(boost::shared_ptr<socket_type> const& s)
|
||||
{
|
||||
error_code ec;
|
||||
// we got a connection request!
|
||||
tcp::endpoint endp = s->remote_endpoint(ec);
|
||||
|
||||
|
@ -988,6 +1021,23 @@ namespace aux {
|
|||
c->start();
|
||||
}
|
||||
}
|
||||
|
||||
void session_impl::on_socks_accept(boost::shared_ptr<socket_type> const& s
|
||||
, error_code const& e)
|
||||
{
|
||||
m_socks_listen_socket.reset();
|
||||
if (e == asio::error::operation_aborted) return;
|
||||
if (e)
|
||||
{
|
||||
if (m_alerts.should_post<listen_failed_alert>())
|
||||
m_alerts.post_alert(listen_failed_alert(tcp::endpoint(
|
||||
address_v4::any(), m_listen_interface.port()), e));
|
||||
return;
|
||||
}
|
||||
open_new_incoming_socks_connection();
|
||||
incoming_connection(s);
|
||||
}
|
||||
|
||||
void session_impl::close_connection(peer_connection const* p
|
||||
, char const* message)
|
||||
{
|
||||
|
|
|
@ -356,18 +356,34 @@ namespace libtorrent
|
|||
// we ignore the proxy IP it was bound to
|
||||
if (atyp == 1)
|
||||
{
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
if (m_command == 2)
|
||||
{
|
||||
if (m_listen == 0)
|
||||
{
|
||||
m_listen = 1;
|
||||
connect1(e, h);
|
||||
return;
|
||||
}
|
||||
int skip_bytes = 0;
|
||||
m_remote_endpoint.address(read_v4_address(p));
|
||||
m_remote_endpoint.port(read_uint16(p));
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
int extra_bytes = 0;
|
||||
if (atyp == 4)
|
||||
{
|
||||
skip_bytes = 12;
|
||||
extra_bytes = 12;
|
||||
}
|
||||
else if (atyp == 3)
|
||||
{
|
||||
skip_bytes = read_uint8(p) - 3;
|
||||
extra_bytes = read_uint8(p) - 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -376,9 +392,10 @@ namespace libtorrent
|
|||
close(ec);
|
||||
return;
|
||||
}
|
||||
m_buffer.resize(skip_bytes);
|
||||
m_buffer.resize(m_buffer.size() + extra_bytes);
|
||||
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
TORRENT_ASSERT(extra_bytes > 0);
|
||||
async_read(m_sock, asio::buffer(&m_buffer[m_buffer.size() - extra_bytes], extra_bytes)
|
||||
, boost::bind(&socks5_stream::connect3, this, _1, h));
|
||||
}
|
||||
else if (m_version == 4)
|
||||
|
@ -394,8 +411,24 @@ namespace libtorrent
|
|||
// access granted
|
||||
if (response == 90)
|
||||
{
|
||||
if (m_command == 2)
|
||||
{
|
||||
if (m_listen == 0)
|
||||
{
|
||||
m_listen = 1;
|
||||
connect1(e, h);
|
||||
return;
|
||||
}
|
||||
m_remote_endpoint.address(read_v4_address(p));
|
||||
m_remote_endpoint.port(read_uint16(p));
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -414,6 +447,8 @@ namespace libtorrent
|
|||
|
||||
void socks5_stream::connect3(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
|
@ -422,6 +457,32 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_command == 2)
|
||||
{
|
||||
if (m_listen == 0)
|
||||
{
|
||||
m_listen = 1;
|
||||
connect1(e, h);
|
||||
return;
|
||||
}
|
||||
|
||||
char* p = &m_buffer[0];
|
||||
p += 2; // version and response code
|
||||
int atyp = read_uint8(p);
|
||||
TORRENT_ASSERT(atyp == 3 || atyp == 4);
|
||||
if (atyp == 4)
|
||||
{
|
||||
// we don't support resolving the endpoint address
|
||||
// if we receive a domain name, just set the remote
|
||||
// endpoint to INADDR_ANY
|
||||
m_remote_endpoint = tcp::endpoint();
|
||||
}
|
||||
else if (atyp == 3)
|
||||
{
|
||||
m_remote_endpoint.address(read_v4_address(p));
|
||||
m_remote_endpoint.port(read_uint16(p));
|
||||
}
|
||||
}
|
||||
std::vector<char>().swap(m_buffer);
|
||||
(*h)(e);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue