simplify natpmp by requiring it to be tied to a specific network, and use get_gateway() and remove unused get_default_route() functions
This commit is contained in:
parent
a53d3a8746
commit
f5ebd4e354
|
@ -107,13 +107,6 @@ namespace libtorrent {
|
||||||
TORRENT_EXTRA_EXPORT boost::optional<address> get_gateway(
|
TORRENT_EXTRA_EXPORT boost::optional<address> get_gateway(
|
||||||
ip_interface const& iface, span<ip_route const> routes);
|
ip_interface const& iface, span<ip_route const> routes);
|
||||||
|
|
||||||
TORRENT_EXTRA_EXPORT boost::optional<ip_route> get_default_route(io_service& ios
|
|
||||||
, string_view device, bool v6, error_code& ec);
|
|
||||||
|
|
||||||
// returns the first default gateway found if device is empty
|
|
||||||
TORRENT_EXTRA_EXPORT address get_default_gateway(io_service& ios
|
|
||||||
, string_view device, bool v6, error_code& ec);
|
|
||||||
|
|
||||||
// attempt to bind socket to the device with the specified name. For systems
|
// attempt to bind socket to the device with the specified name. For systems
|
||||||
// that don't support SO_BINDTODEVICE the socket will be bound to one of the
|
// that don't support SO_BINDTODEVICE the socket will be bound to one of the
|
||||||
// IP addresses of the specified device. In this case it is necessary to
|
// IP addresses of the specified device. In this case it is necessary to
|
||||||
|
|
|
@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/debug.hpp"
|
#include "libtorrent/debug.hpp"
|
||||||
#include "libtorrent/aux_/portmap.hpp"
|
#include "libtorrent/aux_/portmap.hpp"
|
||||||
#include "libtorrent/aux_/vector.hpp"
|
#include "libtorrent/aux_/vector.hpp"
|
||||||
|
#include "libtorrent/enum_net.hpp" // for ip_interface
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent {
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ struct TORRENT_EXTRA_EXPORT natpmp
|
||||||
{
|
{
|
||||||
natpmp(io_service& ios, aux::portmap_callback& cb);
|
natpmp(io_service& ios, aux::portmap_callback& cb);
|
||||||
|
|
||||||
void start(address local_address, std::string device);
|
void start(ip_interface const& ip);
|
||||||
|
|
||||||
// maps the ports, if a port is set to 0
|
// maps the ports, if a port is set to 0
|
||||||
// it will not be mapped
|
// it will not be mapped
|
||||||
|
|
|
@ -817,28 +817,6 @@ int _System __libsocket_sysctl(int* mib, u_int namelen, void *oldp, size_t *oldl
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<ip_route> get_default_route(io_service& ios
|
|
||||||
, string_view const device, bool const v6, error_code& ec)
|
|
||||||
{
|
|
||||||
std::vector<ip_route> const ret = enum_routes(ios, ec);
|
|
||||||
auto const i = std::find_if(ret.begin(), ret.end()
|
|
||||||
, [device,v6](ip_route const& r)
|
|
||||||
{
|
|
||||||
return r.destination.is_unspecified()
|
|
||||||
&& r.destination.is_v6() == v6
|
|
||||||
&& (device.empty() || r.name == device);
|
|
||||||
});
|
|
||||||
if (i == ret.end()) return boost::none;
|
|
||||||
return *i;
|
|
||||||
}
|
|
||||||
|
|
||||||
address get_default_gateway(io_service& ios
|
|
||||||
, string_view const device, bool const v6, error_code& ec)
|
|
||||||
{
|
|
||||||
auto const default_route = get_default_route(ios, device, v6, ec);
|
|
||||||
return default_route ? default_route->gateway : address();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ip_route> enum_routes(io_service& ios, error_code& ec)
|
std::vector<ip_route> enum_routes(io_service& ios, error_code& ec)
|
||||||
{
|
{
|
||||||
std::vector<ip_route> ret;
|
std::vector<ip_route> ret;
|
||||||
|
|
|
@ -146,28 +146,31 @@ natpmp::natpmp(io_service& ios
|
||||||
m_mappings.reserve(10);
|
m_mappings.reserve(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void natpmp::start(address local_address, std::string device)
|
void natpmp::start(ip_interface const& ip)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
|
|
||||||
error_code ec;
|
|
||||||
|
|
||||||
// assume servers support PCP and fall back to NAT-PMP
|
// assume servers support PCP and fall back to NAT-PMP
|
||||||
// if necessary
|
// if necessary
|
||||||
m_version = version_pcp;
|
m_version = version_pcp;
|
||||||
|
|
||||||
// we really want a device name to get the right default gateway
|
address const& local_address = ip.interface_address;
|
||||||
// try to find one even if the listen socket isn't bound to a device
|
|
||||||
if (device.empty())
|
error_code ec;
|
||||||
|
auto const routes = enum_routes(get_io_service(m_socket), ec);
|
||||||
|
if (ec)
|
||||||
{
|
{
|
||||||
device = device_for_address(local_address, get_io_service(m_socket), ec);
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
// if this fails fall back to using the first default gateway in the
|
if (should_log())
|
||||||
// routing table
|
{
|
||||||
ec.clear();
|
log("failed to enumerate routes: %s"
|
||||||
|
, convert_from_native(ec.message()).c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
disable(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const route = get_default_route(get_io_service(m_socket)
|
auto const route = get_gateway(ip, routes);
|
||||||
, device, local_address.is_v6(), ec);
|
|
||||||
|
|
||||||
if (!route)
|
if (!route)
|
||||||
{
|
{
|
||||||
|
@ -175,7 +178,7 @@ void natpmp::start(address local_address, std::string device)
|
||||||
if (should_log())
|
if (should_log())
|
||||||
{
|
{
|
||||||
log("failed to find default route for \"%s\" %s: %s"
|
log("failed to find default route for \"%s\" %s: %s"
|
||||||
, device.c_str(), local_address.to_string().c_str()
|
, ip.name, local_address.to_string().c_str()
|
||||||
, convert_from_native(ec.message()).c_str());
|
, convert_from_native(ec.message()).c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -183,65 +186,16 @@ void natpmp::start(address local_address, std::string device)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device.empty()) device = route->name;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(!device.empty());
|
|
||||||
|
|
||||||
// PCP requires reporting the source address at the application
|
|
||||||
// layer so the socket MUST be bound to a specific address
|
|
||||||
// if the caller didn't specify one then get the first suitable
|
|
||||||
// address from the OS
|
|
||||||
if (local_address.is_unspecified())
|
|
||||||
{
|
|
||||||
std::vector<ip_interface> const net = enum_net_interfaces(
|
|
||||||
get_io_service(m_socket), ec);
|
|
||||||
|
|
||||||
auto const it = std::find_if(net.begin(), net.end(), [&](ip_interface const& i)
|
|
||||||
{
|
|
||||||
return i.interface_address.is_v4() == local_address.is_v4()
|
|
||||||
&& (i.interface_address.is_v4() || !is_local(i.interface_address))
|
|
||||||
&& i.name == device;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (it != net.end())
|
|
||||||
{
|
|
||||||
local_address = it->interface_address;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if we can't get a specific address to bind to we'll have
|
|
||||||
// to fall back to NAT-PMP
|
|
||||||
// but NAT-PMP doesn't support IPv6 so if that's what is being
|
|
||||||
// requested we can't do anything
|
|
||||||
if (local_address.is_v6())
|
|
||||||
{
|
|
||||||
if (!ec) ec = boost::asio::error::address_family_not_supported;
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
if (should_log())
|
|
||||||
{
|
|
||||||
log("cannot map IPv6 without a local address, %s"
|
|
||||||
, convert_from_native(ec.message()).c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
disable(ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_version = version_natpmp;
|
|
||||||
ec.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_disabled = false;
|
m_disabled = false;
|
||||||
|
|
||||||
udp::endpoint const nat_endpoint(route->gateway, 5351);
|
udp::endpoint const nat_endpoint(*route, 5351);
|
||||||
if (nat_endpoint == m_nat_endpoint) return;
|
if (nat_endpoint == m_nat_endpoint) return;
|
||||||
m_nat_endpoint = nat_endpoint;
|
m_nat_endpoint = nat_endpoint;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
if (should_log())
|
if (should_log())
|
||||||
{
|
{
|
||||||
log("found router at: %s"
|
log("found gateway at: %s"
|
||||||
, print_address(m_nat_endpoint.address()).c_str());
|
, print_address(m_nat_endpoint.address()).c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5464,7 +5464,11 @@ namespace aux {
|
||||||
// the natpmp constructor may fail and call the callbacks
|
// the natpmp constructor may fail and call the callbacks
|
||||||
// into the session_impl.
|
// into the session_impl.
|
||||||
s.natpmp_mapper = std::make_shared<natpmp>(m_io_service, *this);
|
s.natpmp_mapper = std::make_shared<natpmp>(m_io_service, *this);
|
||||||
s.natpmp_mapper->start(s.local_endpoint.address(), s.device);
|
ip_interface ip;
|
||||||
|
ip.interface_address = s.local_endpoint.address();
|
||||||
|
ip.netmask = s.netmask;
|
||||||
|
std::strncpy(ip.name, s.device.c_str(), sizeof(ip.name));
|
||||||
|
s.natpmp_mapper->start(ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,15 +42,6 @@ int main()
|
||||||
io_service ios;
|
io_service ios;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
|
||||||
address def_gw = get_default_gateway(ios, "", false, ec);
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
std::printf("%s\n", ec.message().c_str());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::printf("Default gateway: %s\n", def_gw.to_string(ec).c_str());
|
|
||||||
|
|
||||||
std::printf("=========== Routes ===========\n");
|
std::printf("=========== Routes ===========\n");
|
||||||
auto const routes = enum_routes(ios, ec);
|
auto const routes = enum_routes(ios, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
|
|
Loading…
Reference in New Issue