Skip to content

Commit

Permalink
Adding listen proxy setting
Browse files Browse the repository at this point in the history
  • Loading branch information
Masong19hippows committed Oct 16, 2024
1 parent 4bf0c21 commit 2db609b
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 50 deletions.
4 changes: 4 additions & 0 deletions include/libtorrent/aux_/proxy_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ namespace aux {
// This is only supported by SOCKS5 and HTTP.
bool proxy_hostnames = true;

// defaults to false for integration compatibility. It means that the
// torrent port is listening with tcp and udp while there is a proxy configured.
bool listen_on_proxy = false;

// determines whether or not to exempt peer and web seed connections
// from using the proxy. This defaults to true, i.e. peer connections are
// proxied by default.
Expand Down
1 change: 1 addition & 0 deletions src/proxy_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void init(proxy_settings& p, Settings const& sett)
p.type = settings_pack::proxy_type_t(sett.get_int(settings_pack::proxy_type));
p.port = std::uint16_t(sett.get_int(settings_pack::proxy_port));
p.proxy_hostnames = sett.get_bool(settings_pack::proxy_hostnames);
p.listen_on_proxy = sett.get_bool(settings_pack::listen_on_proxy);
p.proxy_peer_connections = sett.get_bool(
settings_pack::proxy_peer_connections);
p.proxy_tracker_connections = sett.get_bool(
Expand Down
133 changes: 83 additions & 50 deletions src/session_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2055,70 +2055,86 @@ namespace {

// if we don't proxy peer connections, don't apply the special logic for
// proxies


std::vector<ip_interface> const ifs = enum_net_interfaces(m_io_context, ec);
if (ec && m_alerts.should_post<listen_failed_alert>())
{
m_alerts.emplace_alert<listen_failed_alert>(""
, operation_t::enum_if, ec, socket_type_t::tcp);
if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
&& m_settings.get_bool(settings_pack::proxy_peer_connections)
&& !m_settings.get_bool(settings_pack::listen_on_proxy))
{
// we will be able to accept incoming connections over UDP. so use
// one of the ports the user specified to use a consistent port
// across sessions. If the user did not specify any ports, pick one
// at random
int const port = m_listen_interfaces.empty()
? int(random(63000) + 2000)
: m_listen_interfaces.front().port;
listen_endpoint_t ep(address_v4::any(), port, {}
, transport::plaintext, listen_socket_t::proxy);
eps.emplace_back(ep);
}
auto const routes = enum_routes(m_io_context, ec);
if (ec && m_alerts.should_post<listen_failed_alert>())
else
{
m_alerts.emplace_alert<listen_failed_alert>(""
, operation_t::enum_route, ec, socket_type_t::tcp);
}
std::vector<ip_interface> const ifs = enum_net_interfaces(m_io_context, ec);
if (ec && m_alerts.should_post<listen_failed_alert>())
{
m_alerts.emplace_alert<listen_failed_alert>(""
, operation_t::enum_if, ec, socket_type_t::tcp);
}
auto const routes = enum_routes(m_io_context, ec);
if (ec && m_alerts.should_post<listen_failed_alert>())
{
m_alerts.emplace_alert<listen_failed_alert>(""
, operation_t::enum_route, ec, socket_type_t::tcp);
}

// expand device names and populate eps
for (auto const& iface : m_listen_interfaces)
{
#if !TORRENT_USE_SSL
if (iface.ssl)
// expand device names and populate eps
for (auto const& iface : m_listen_interfaces)
{
#if !TORRENT_USE_SSL
if (iface.ssl)
{
#ifndef TORRENT_DISABLE_LOGGING
session_log("attempted to listen ssl with no library support on device: \"%s\""
, iface.device.c_str());
session_log("attempted to listen ssl with no library support on device: \"%s\""
, iface.device.c_str());
#endif
if (m_alerts.should_post<listen_failed_alert>())
{
m_alerts.emplace_alert<listen_failed_alert>(iface.device
, operation_t::sock_open
, boost::asio::error::operation_not_supported
, socket_type_t::tcp_ssl);
if (m_alerts.should_post<listen_failed_alert>())
{
m_alerts.emplace_alert<listen_failed_alert>(iface.device
, operation_t::sock_open
, boost::asio::error::operation_not_supported
, socket_type_t::tcp_ssl);
}
continue;
}
continue;
}
#endif

// now we have a device to bind to. This device may actually just be an
// IP address or a device name. In case it's a device name, we want to
// (potentially) end up binding a socket for each IP address associated
// with that device.
interface_to_endpoints(iface, listen_socket_t::accept_incoming, ifs, eps);
}
// now we have a device to bind to. This device may actually just be an
// IP address or a device name. In case it's a device name, we want to
// (potentially) end up binding a socket for each IP address associated
// with that device.
interface_to_endpoints(iface, listen_socket_t::accept_incoming, ifs, eps);
}

if (eps.empty())
{
if (eps.empty())
{
#ifndef TORRENT_DISABLE_LOGGING
session_log("no listen sockets");
session_log("no listen sockets");
#endif
}
}

#if defined TORRENT_ANDROID && __ANDROID_API__ >= 24
// For Android API >= 24, enum_routes with the current NETLINK based
// implementation is unsupported (maybe in the future the operation
// will be restore using another implementation). If routes is empty,
// allow using unspecified address is a best effort approach that
// seems to work. The issue with this approach is with the DHTs,
// because for IPv6 this is not following BEP 32 and BEP 45. See:
// https://www.bittorrent.org/beps/bep_0032.html
// https://www.bittorrent.org/beps/bep_0045.html
if (!routes.empty()) expand_unspecified_address(ifs, routes, eps);
// For Android API >= 24, enum_routes with the current NETLINK based
// implementation is unsupported (maybe in the future the operation
// will be restore using another implementation). If routes is empty,
// allow using unspecified address is a best effort approach that
// seems to work. The issue with this approach is with the DHTs,
// because for IPv6 this is not following BEP 32 and BEP 45. See:
// https://www.bittorrent.org/beps/bep_0032.html
// https://www.bittorrent.org/beps/bep_0045.html
if (!routes.empty()) expand_unspecified_address(ifs, routes, eps);
#else
expand_unspecified_address(ifs, routes, eps);
expand_unspecified_address(ifs, routes, eps);
#endif
expand_devices(ifs, eps);
expand_devices(ifs, eps);
}

auto remove_iter = partition_listen_sockets(eps, m_listen_sockets);

Expand Down Expand Up @@ -2804,8 +2820,14 @@ namespace {
}
async_accept(listener, ssl);

// don't accept any connections from our local listen sockets if we're
// using a proxy and the correct setting isn't set.
// This path is only for accepting incoming TCP sockets. The udp_socket
// class also restricts incoming packets based on proxy settings.
if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
&& m_settings.get_bool(settings_pack::proxy_peer_connections)
&& !m_settings.get_bool(settings_pack::listen_on_proxy))
return;

auto listen = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
, [&listener](std::shared_ptr<listen_socket_t> const& l)
Expand Down Expand Up @@ -5504,12 +5526,21 @@ namespace {
// The DHT may use the implied port to make it work, but the port we
// announce here has no relevance for that.

if (sock->flags & listen_socket_t::proxy
&& !m_settings.get_bool(settings_pack::listen_on_proxy))
return 0;

if (!(sock->flags & listen_socket_t::accept_incoming))
return 0;

return std::uint16_t(sock->tcp_external_port());
}

if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
&& m_settings.get_bool(settings_pack::proxy_peer_connections)
&& !m_settings.get_bool(settings_pack::listen_on_proxy))
return 0;

#ifdef TORRENT_SSL_PEERS
for (auto const& s : m_listen_sockets)
{
Expand Down Expand Up @@ -5635,7 +5666,8 @@ namespace {
return;

if (!s->natpmp_mapper
&& !(s->flags & listen_socket_t::local_network))
&& !(s->flags & listen_socket_t::local_network)
&& m_settings.get_bool(settings_pack::listen_on_proxy))
{
// the natpmp constructor may fail and call the callbacks
// into the session_impl.
Expand Down Expand Up @@ -6861,7 +6893,8 @@ namespace {
// there's no point in starting the UPnP mapper for a network that isn't
// connected to the internet. The whole point is to forward ports through
// the gateway
if ((s->flags & listen_socket_t::local_network))
if ((s->flags & listen_socket_t::local_network)
|| (s->flags & !m_settings.get_bool(settings_pack::listen_on_proxy)))
return;

if (!s->upnp_mapper)
Expand Down

0 comments on commit 2db609b

Please sign in to comment.