experimental support for incoming connections over socks (untested)

This commit is contained in:
Arvid Norberg 2009-04-09 01:04:49 +00:00
parent a956265be4
commit 41be942ae7
4 changed files with 146 additions and 14 deletions

View File

@ -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

View File

@ -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;
};
}

View File

@ -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)
{

View File

@ -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;
}
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 skip_bytes = 0;
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,10 +392,11 @@ 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)
, boost::bind(&socks5_stream::connect3, this, _1, h));
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)
{
std::vector<char>().swap(m_buffer);
(*h)(e);
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);
}