improved natpmp, upnp and lsd
This commit is contained in:
parent
674e1f96b1
commit
633f174947
|
@ -51,6 +51,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
|
bool is_local(address const& a);
|
||||||
|
|
||||||
// int: external tcp port
|
// int: external tcp port
|
||||||
// int: external udp port
|
// int: external udp port
|
||||||
// std::string: error message
|
// std::string: error message
|
||||||
|
|
35
src/lsd.cpp
35
src/lsd.cpp
|
@ -72,36 +72,11 @@ lsd::~lsd() {}
|
||||||
|
|
||||||
void lsd::rebind(address const& listen_interface)
|
void lsd::rebind(address const& listen_interface)
|
||||||
{
|
{
|
||||||
address_v4 local_ip;
|
address_v4 local_ip = address_v4::any();
|
||||||
if (listen_interface.is_v4() && listen_interface != address_v4::from_string("0.0.0.0"))
|
if (listen_interface.is_v4() && listen_interface != address_v4::any())
|
||||||
{
|
{
|
||||||
local_ip = listen_interface.to_v4();
|
local_ip = listen_interface.to_v4();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// make a best guess of the interface we're using and its IP
|
|
||||||
udp::resolver r(m_socket.io_service());
|
|
||||||
udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0"));
|
|
||||||
for (;i != udp::resolver_iterator(); ++i)
|
|
||||||
{
|
|
||||||
// ignore the loopback
|
|
||||||
if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue;
|
|
||||||
// ignore non-IPv4 addresses
|
|
||||||
if (i->endpoint().address().is_v4()) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == udp::resolver_iterator())
|
|
||||||
{
|
|
||||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
|
||||||
m_log << "local host name did not resolve to an IPv4 address. "
|
|
||||||
"disabling local service discovery" << std::endl;
|
|
||||||
#endif
|
|
||||||
m_disabled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
local_ip = i->endpoint().address().to_v4();
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -123,8 +98,12 @@ void lsd::rebind(address const& listen_interface)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_socket.set_option(join_group(lsd_multicast_address));
|
m_socket.set_option(join_group(lsd_multicast_address));
|
||||||
m_socket.set_option(outbound_interface(address_v4()));
|
m_socket.set_option(outbound_interface(local_ip));
|
||||||
|
#ifdef NDEBUG
|
||||||
m_socket.set_option(enable_loopback(false));
|
m_socket.set_option(enable_loopback(false));
|
||||||
|
#else
|
||||||
|
m_socket.set_option(enable_loopback(true));
|
||||||
|
#endif
|
||||||
m_socket.set_option(hops(255));
|
m_socket.set_option(hops(255));
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|
|
@ -42,6 +42,11 @@ using namespace libtorrent;
|
||||||
|
|
||||||
enum { num_mappings = 2 };
|
enum { num_mappings = 2 };
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
bool is_local(address const& a);
|
||||||
|
}
|
||||||
|
|
||||||
natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb)
|
natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb)
|
||||||
: m_callback(cb)
|
: m_callback(cb)
|
||||||
, m_currently_mapping(-1)
|
, m_currently_mapping(-1)
|
||||||
|
@ -62,8 +67,8 @@ natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callbac
|
||||||
|
|
||||||
void natpmp::rebind(address const& listen_interface) try
|
void natpmp::rebind(address const& listen_interface) try
|
||||||
{
|
{
|
||||||
address_v4 local;
|
address_v4 local = address_v4::any();
|
||||||
if (listen_interface.is_v4() && listen_interface != address_v4::from_string("0.0.0.0"))
|
if (listen_interface.is_v4() && listen_interface != address_v4::any())
|
||||||
{
|
{
|
||||||
local = listen_interface.to_v4();
|
local = listen_interface.to_v4();
|
||||||
}
|
}
|
||||||
|
@ -76,30 +81,27 @@ void natpmp::rebind(address const& listen_interface) try
|
||||||
{
|
{
|
||||||
// ignore the loopback
|
// ignore the loopback
|
||||||
if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue;
|
if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue;
|
||||||
|
// ignore addresses that are not on a local network
|
||||||
|
if (!is_local(i->endpoint().address())) continue;
|
||||||
// ignore non-IPv4 addresses
|
// ignore non-IPv4 addresses
|
||||||
if (i->endpoint().address().is_v4()) break;
|
if (i->endpoint().address().is_v4()) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == udp::resolver_iterator())
|
if (i == udp::resolver_iterator())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("local host name did not resolve to an "
|
throw std::runtime_error("local host is probably not on a NATed "
|
||||||
"IPv4 address. disabling NAT-PMP");
|
"network. disabling NAT-PMP");
|
||||||
}
|
}
|
||||||
|
|
||||||
local = i->endpoint().address().to_v4();
|
local = i->endpoint().address().to_v4();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_socket.open(udp::v4());
|
|
||||||
m_socket.bind(udp::endpoint(local, 0));
|
|
||||||
|
|
||||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " local ip: " << local.to_string() << std::endl;
|
<< " local ip: " << local.to_string() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((local.to_ulong() & 0xff000000) != 0x0a000000
|
if (!is_local(local))
|
||||||
&& (local.to_ulong() & 0xfff00000) != 0xac100000
|
|
||||||
&& (local.to_ulong() & 0xffff0000) != 0xc0a80000)
|
|
||||||
{
|
{
|
||||||
// the local address seems to be an external
|
// the local address seems to be an external
|
||||||
// internet address. Assume it is not behind a NAT
|
// internet address. Assume it is not behind a NAT
|
||||||
|
@ -108,13 +110,13 @@ void natpmp::rebind(address const& listen_interface) try
|
||||||
|
|
||||||
m_disabled = false;
|
m_disabled = false;
|
||||||
|
|
||||||
|
// assume the router is located on the local
|
||||||
|
// network as x.x.x.1
|
||||||
udp::endpoint nat_endpoint(
|
udp::endpoint nat_endpoint(
|
||||||
address_v4((local.to_ulong() & 0xffffff00) | 1), 5351);
|
address_v4((local.to_ulong() & 0xffffff00) | 1), 5351);
|
||||||
|
|
||||||
if (nat_endpoint == m_nat_endpoint) return;
|
if (nat_endpoint == m_nat_endpoint) return;
|
||||||
|
|
||||||
// assume the router is located on the local
|
|
||||||
// network as x.x.x.1
|
|
||||||
// TODO: find a better way to figure out the router IP
|
// TODO: find a better way to figure out the router IP
|
||||||
m_nat_endpoint = nat_endpoint;
|
m_nat_endpoint = nat_endpoint;
|
||||||
|
|
||||||
|
@ -122,6 +124,9 @@ void natpmp::rebind(address const& listen_interface) try
|
||||||
m_log << "assuming router is at: " << m_nat_endpoint.address().to_string() << std::endl;
|
m_log << "assuming router is at: " << m_nat_endpoint.address().to_string() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_socket.open(udp::v4());
|
||||||
|
m_socket.bind(udp::endpoint(address_v4::any(), 0));
|
||||||
|
|
||||||
for (int i = 0; i < num_mappings; ++i)
|
for (int i = 0; i < num_mappings; ++i)
|
||||||
{
|
{
|
||||||
if (m_mappings[i].local_port == 0)
|
if (m_mappings[i].local_port == 0)
|
||||||
|
|
24
src/upnp.cpp
24
src/upnp.cpp
|
@ -52,6 +52,18 @@ using namespace libtorrent;
|
||||||
address_v4 upnp::upnp_multicast_address;
|
address_v4 upnp::upnp_multicast_address;
|
||||||
udp::endpoint upnp::upnp_multicast_endpoint;
|
udp::endpoint upnp::upnp_multicast_endpoint;
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
bool is_local(address const& a)
|
||||||
|
{
|
||||||
|
if (a.is_v6()) return false;
|
||||||
|
address_v4 a4 = a.to_v4();
|
||||||
|
return ((a4.to_ulong() & 0xff000000) == 0x0a000000
|
||||||
|
|| (a4.to_ulong() & 0xfff00000) == 0xac100000
|
||||||
|
|| (a4.to_ulong() & 0xffff0000) == 0xc0a80000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
upnp::upnp(io_service& ios, connection_queue& cc
|
upnp::upnp(io_service& ios, connection_queue& cc
|
||||||
, address const& listen_interface, std::string const& user_agent
|
, address const& listen_interface, std::string const& user_agent
|
||||||
, portmap_callback_t const& cb)
|
, portmap_callback_t const& cb)
|
||||||
|
@ -84,7 +96,7 @@ upnp::~upnp()
|
||||||
|
|
||||||
void upnp::rebind(address const& listen_interface) try
|
void upnp::rebind(address const& listen_interface) try
|
||||||
{
|
{
|
||||||
if (listen_interface.is_v4() && listen_interface != address_v4::from_string("0.0.0.0"))
|
if (listen_interface.is_v4() && listen_interface != address_v4::any())
|
||||||
{
|
{
|
||||||
m_local_ip = listen_interface.to_v4();
|
m_local_ip = listen_interface.to_v4();
|
||||||
}
|
}
|
||||||
|
@ -97,14 +109,16 @@ void upnp::rebind(address const& listen_interface) try
|
||||||
{
|
{
|
||||||
// ignore the loopback
|
// ignore the loopback
|
||||||
if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue;
|
if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue;
|
||||||
|
// ignore addresses that are not on a local network
|
||||||
|
if (!is_local(i->endpoint().address())) continue;
|
||||||
// ignore non-IPv4 addresses
|
// ignore non-IPv4 addresses
|
||||||
if (i->endpoint().address().is_v4()) break;
|
if (i->endpoint().address().is_v4()) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == udp::resolver_iterator())
|
if (i == udp::resolver_iterator())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("local host name did not resolve to an "
|
throw std::runtime_error("local host is probably not on a NATed "
|
||||||
"IPv4 address. disabling UPnP");
|
"network. disabling UPnP");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_local_ip = i->endpoint().address().to_v4();
|
m_local_ip = i->endpoint().address().to_v4();
|
||||||
|
@ -115,9 +129,7 @@ void upnp::rebind(address const& listen_interface) try
|
||||||
<< " local ip: " << m_local_ip.to_string() << std::endl;
|
<< " local ip: " << m_local_ip.to_string() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((m_local_ip.to_ulong() & 0xff000000) != 0x0a000000
|
if (!is_local(m_local_ip))
|
||||||
&& (m_local_ip.to_ulong() & 0xfff00000) != 0xac100000
|
|
||||||
&& (m_local_ip.to_ulong() & 0xffff0000) != 0xc0a80000)
|
|
||||||
{
|
{
|
||||||
// the local address seems to be an external
|
// the local address seems to be an external
|
||||||
// internet address. Assume it is not behind a NAT
|
// internet address. Assume it is not behind a NAT
|
||||||
|
|
Loading…
Reference in New Issue