diff --git a/bindings/python/test.py b/bindings/python/test.py index 250ed6b3c..fd20dabbb 100644 --- a/bindings/python/test.py +++ b/bindings/python/test.py @@ -169,10 +169,16 @@ class test_torrent_handle(unittest.TestCase): # wait a bit until the endpoints list gets populated while len(self.h.trackers()[0]['endpoints']) == 0: time.sleep(0.1) - pickled_trackers = pickle.dumps(self.h.trackers()) + + trackers = self.h.trackers() + self.assertEqual(trackers[0]['url'], 'udp://tracker1.com') + # this is not necessarily 0, it could also be (EHOSTUNREACH) if the + # local machine doesn't support the address family + expect_value = trackers[0]['endpoints'][0]['last_error']['value'] + pickled_trackers = pickle.dumps(trackers) unpickled_trackers = pickle.loads(pickled_trackers) self.assertEqual(unpickled_trackers[0]['url'], 'udp://tracker1.com') - self.assertEqual(unpickled_trackers[0]['endpoints'][0]['last_error']['value'], 0) + self.assertEqual(unpickled_trackers[0]['endpoints'][0]['last_error']['value'], expect_value) def test_file_status(self): self.setup() diff --git a/include/libtorrent/aux_/listen_socket_handle.hpp b/include/libtorrent/aux_/listen_socket_handle.hpp index 066256560..88f7b44d9 100644 --- a/include/libtorrent/aux_/listen_socket_handle.hpp +++ b/include/libtorrent/aux_/listen_socket_handle.hpp @@ -58,6 +58,7 @@ namespace libtorrent { namespace aux { address get_external_address() const; tcp::endpoint get_local_endpoint() const; + bool can_route(address const&) const; bool is_ssl() const; diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index f86d8978b..0a45f6ea3 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -154,6 +154,12 @@ namespace aux { listen_socket_t& operator=(listen_socket_t const&) = delete; listen_socket_t& operator=(listen_socket_t&&) = delete; + // returns true if this listen socket/interface can reach and be reached + // by the given address. This is useful to know whether it should be + // annoucned to a tracker (given the tracker's IP) or whether it should + // have a SOCKS5 UDP tunnel set up (given the IP of the socks proxy) + bool can_route(address const&) const; + // this may be empty but can be set // to the WAN IP address of a NAT router ip_voter external_address; @@ -161,6 +167,8 @@ namespace aux { // this is a cached local endpoint for the listen TCP socket tcp::endpoint local_endpoint; + address netmask; + // the name of the device the socket is bound to, may be empty // if the socket is not bound to a device std::string device; @@ -229,8 +237,8 @@ namespace aux { struct TORRENT_EXTRA_EXPORT listen_endpoint_t { listen_endpoint_t(address const& adr, int p, std::string dev, transport s - , listen_socket_flags_t f) - : addr(adr), port(p), device(std::move(dev)), ssl(s), flags(f) {} + , listen_socket_flags_t f, address const& nmask = address{}) + : addr(adr), netmask(nmask), port(p), device(std::move(dev)), ssl(s), flags(f) {} bool operator==(listen_endpoint_t const& o) const { @@ -238,6 +246,10 @@ namespace aux { } address addr; + // if this listen endpoint/interface doesn't have a gateway, we cannot + // route outside of our network, this netmask defines the range of our + // local network + address netmask; int port; std::string device; transport ssl; @@ -258,6 +270,10 @@ namespace aux { span ifs , std::vector& eps); + TORRENT_EXTRA_EXPORT void expand_devices(span + , span routes + , std::vector& eps); + // this is the link between the main thread and the // thread started to run the main downloader loop struct TORRENT_EXTRA_EXPORT session_impl final diff --git a/include/libtorrent/aux_/session_udp_sockets.hpp b/include/libtorrent/aux_/session_udp_sockets.hpp index 1687665f7..02956ea8b 100644 --- a/include/libtorrent/aux_/session_udp_sockets.hpp +++ b/include/libtorrent/aux_/session_udp_sockets.hpp @@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/utp_socket_manager.hpp" #include "libtorrent/config.hpp" #include "libtorrent/aux_/allocating_handler.hpp" +#include "libtorrent/aux_/listen_socket_handle.hpp" #include #include @@ -47,13 +48,14 @@ namespace aux { struct listen_endpoint_t; struct proxy_settings; + struct listen_socket_t; enum class transport : std::uint8_t { plaintext, ssl }; struct session_udp_socket : utp_socket_interface { - explicit session_udp_socket(io_service& ios) - : sock(ios) {} + explicit session_udp_socket(io_service& ios, listen_socket_handle ls) + : sock(ios, std::move(ls)) {} udp::endpoint local_endpoint() override { return sock.local_endpoint(); } @@ -73,7 +75,7 @@ namespace aux { struct outgoing_udp_socket final : session_udp_socket { outgoing_udp_socket(io_service& ios, std::string const& dev, transport ssl_) - : session_udp_socket(ios), device(dev), ssl(ssl_) {} + : session_udp_socket(ios, listen_socket_handle{}), device(dev), ssl(ssl_) {} // the name of the device the socket is bound to, may be empty // if the socket is not bound to a device diff --git a/include/libtorrent/udp_socket.hpp b/include/libtorrent/udp_socket.hpp index 0b18b85c6..4272eede9 100644 --- a/include/libtorrent/udp_socket.hpp +++ b/include/libtorrent/udp_socket.hpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/debug.hpp" #include "libtorrent/span.hpp" #include "libtorrent/flags.hpp" +#include "libtorrent/aux_/listen_socket_handle.hpp" #include #include @@ -54,7 +55,7 @@ namespace libtorrent { class TORRENT_EXTRA_EXPORT udp_socket : single_threaded { public: - explicit udp_socket(io_service& ios); + explicit udp_socket(io_service& ios, aux::listen_socket_handle ls); static constexpr udp_send_flags_t peer_connection = 0_bit; static constexpr udp_send_flags_t tracker_connection = 1_bit; @@ -145,6 +146,7 @@ namespace libtorrent { using receive_buffer = std::array; std::unique_ptr m_buf; + aux::listen_socket_handle m_listen_socket; std::uint16_t m_bind_port; diff --git a/simulation/test_dht_rate_limit.cpp b/simulation/test_dht_rate_limit.cpp index 667ae5dab..cc5f20a46 100644 --- a/simulation/test_dht_rate_limit.cpp +++ b/simulation/test_dht_rate_limit.cpp @@ -104,7 +104,7 @@ TORRENT_TEST(dht_rate_limit) asio::io_service dht_ios(sim, address_v4::from_string("40.30.20.10")); // receiver (the DHT under test) - lt::udp_socket sock(dht_ios); + lt::udp_socket sock(dht_ios, lt::aux::listen_socket_handle{}); obs o; auto ls = std::make_shared(); ls->external_address.cast_vote(address_v4::from_string("40.30.20.10") @@ -230,7 +230,7 @@ TORRENT_TEST(dht_delete_socket) sim::simulation sim(cfg); sim::asio::io_service dht_ios(sim, lt::address_v4::from_string("40.30.20.10")); - lt::udp_socket sock(dht_ios); + lt::udp_socket sock(dht_ios, lt::aux::listen_socket_handle{}); error_code ec; sock.bind(udp::endpoint(address_v4::from_string("40.30.20.10"), 8888), ec); diff --git a/src/enum_net.cpp b/src/enum_net.cpp index 665dd4016..68ee3c914 100644 --- a/src/enum_net.cpp +++ b/src/enum_net.cpp @@ -472,6 +472,8 @@ int _System __libsocket_sysctl(int* mib, u_int namelen, void *oldp, size_t *oldl if (a1.is_v6()) { + if (a1.to_v6().scope_id() != a2.to_v6().scope_id()) return false; + address_v6::bytes_type b1 = a1.to_v6().to_bytes(); address_v6::bytes_type b2 = a2.to_v6().to_bytes(); address_v6::bytes_type m = mask.to_v6().to_bytes(); diff --git a/src/http_connection.cpp b/src/http_connection.cpp index 901efd535..ca75b569a 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -529,21 +529,9 @@ void http_connection::on_resolve(error_code const& e // only connect to addresses of the same family if (m_bind_addr) { - auto new_end = std::partition(m_endpoints.begin(), m_endpoints.end() - , [this] (tcp::endpoint const& ep) - { - if (is_v4(ep) != m_bind_addr->is_v4()) - return false; - if (is_v4(ep) && m_bind_addr->is_v4()) - return true; - TORRENT_ASSERT(is_v6(ep) && m_bind_addr->is_v6()); - // don't try to connect to a global address with a local source address - // this is mainly needed to prevent attempting to connect to a global - // address using a ULA as the source - if (!is_local(ep.address()) && is_local(*m_bind_addr)) - return false; - return ep.address().to_v6().scope_id() == m_bind_addr->to_v6().scope_id(); - }); + auto const new_end = std::remove_if(m_endpoints.begin(), m_endpoints.end() + , [&](tcp::endpoint const& ep) { return is_v4(ep) != m_bind_addr->is_v4(); }); + m_endpoints.erase(new_end, m_endpoints.end()); if (m_endpoints.empty()) { diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index e9d4c5ff0..15048d08c 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -272,6 +272,20 @@ namespace libtorrent { void http_tracker_connection::on_filter(http_connection& c , std::vector& endpoints) { + // filter all endpoints we cannot reach from this listen socket, which may + // be all of them, in which case we should not announce this listen socket + // to this tracker + auto const ls = bind_socket(); + endpoints.erase(std::remove_if(endpoints.begin(), endpoints.end() + , [&](tcp::endpoint const& ep) { return !ls.can_route(ep.address()); }) + , endpoints.end()); + + if (endpoints.empty()) + { + fail(error_code(boost::system::errc::host_unreachable, system_category())); + return; + } + TORRENT_UNUSED(c); if (!tracker_req().filter) return; diff --git a/src/listen_socket_handle.cpp b/src/listen_socket_handle.cpp index 0309caace..c72a9abc4 100644 --- a/src/listen_socket_handle.cpp +++ b/src/listen_socket_handle.cpp @@ -64,4 +64,11 @@ namespace libtorrent { namespace aux { return m_sock.lock().get(); } + bool listen_socket_handle::can_route(address const& a) const + { + auto s = m_sock.lock(); + if (!s) return false; + return s->can_route(a); + } + } } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 0f99cca1a..e0d6839e7 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -283,6 +283,70 @@ namespace aux { } } + void expand_devices(span const ifs + , span const routes + , std::vector& eps) + { + for (auto& ep : eps) + { + auto const iface = ep.device.empty() + ? std::find_if(ifs.begin(), ifs.end(), [&](ip_interface const& ipface) + { + return match_addr_mask(ipface.interface_address, ep.addr, ipface.netmask); + }) + : std::find_if(ifs.begin(), ifs.end(), [&](ip_interface const& ipface) + { + return ipface.name == ep.device + && match_addr_mask(ipface.interface_address, ep.addr, ipface.netmask); + }); + + if (iface == ifs.end()) + { + // we can't find which device this is for, just assume we can't + // reach anything on it + ep.netmask = build_netmask(0, ep.addr.is_v4() ? AF_INET : AF_INET6); + continue; + } + + ep.netmask = iface->netmask; + + bool const v4 = iface->interface_address.is_v4(); + + // also record whether the device has a gateway associated with it + // (which indicates it can be used to reach the internet) + // only gateways inside the interface's network count + bool const has_gateway = std::find_if(routes.begin(), routes.end(), [&](ip_route const& r) + { + return r.destination.is_unspecified() + && r.destination.is_v4() == v4 + && !r.gateway.is_unspecified() + && match_addr_mask(r.gateway, iface->interface_address, iface->netmask) + && strcmp(r.name, iface->name) == 0; + }) != routes.end(); + + if (has_gateway) + ep.flags |= listen_socket_t::has_gateway; + + ep.device = iface->name; + } + } + + bool listen_socket_t::can_route(address const& addr) const + { + if (local_endpoint.address().is_v4() != addr.is_v4()) return false; + + if (local_endpoint.address().is_v6() + && local_endpoint.address().to_v6().scope_id() != addr.to_v6().scope_id()) + return false; + + if (flags & has_gateway) return true; + if (local_endpoint.address() == addr) return true; + if (local_endpoint.address().is_unspecified()) return true; + if (match_addr_mask(addr, local_endpoint.address(), netmask)) return true; + + return false; + } + void session_impl::init_peer_class_filter(bool unlimited_local) { // set the default peer_class_filter to use the local peer class @@ -1328,6 +1392,7 @@ namespace aux { ret->ssl = lep.ssl; ret->original_port = bind_ep.port(); ret->flags = lep.flags; + ret->netmask = lep.netmask; operation_t last_op = operation_t::unknown; socket_type_t const sock_type = (lep.ssl == transport::ssl) @@ -1535,7 +1600,7 @@ namespace aux { : socket_type_t::udp; udp::endpoint udp_bind_ep(bind_ep.address(), bind_ep.port()); - ret->udp_sock = std::make_shared(m_io_service); + ret->udp_sock = std::make_shared(m_io_service, ret); ret->udp_sock->sock.open(udp_bind_ep.protocol(), ec); if (ec) { @@ -1798,6 +1863,8 @@ namespace aux { if (!ec) { expand_unspecified_address(ifs, eps); + auto const routes = enum_routes(m_io_service, ec); + if (!ec) expand_devices(ifs, routes, eps); } // if no listen interfaces are specified, create sockets to use diff --git a/src/torrent.cpp b/src/torrent.cpp index 74254d493..5f6cff268 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -10988,7 +10988,8 @@ bool is_downloading_state(int const st) debug_log("*** increment tracker fail count [%d]", aep->fails); #endif // don't try to announce from this endpoint again - if (ec == boost::system::errc::address_family_not_supported) + if (ec == boost::system::errc::address_family_not_supported + || ec == boost::system::errc::host_unreachable) { aep->enabled = false; #ifndef TORRENT_DISABLE_LOGGING diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index d5405562f..685d74660 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -69,14 +69,14 @@ std::size_t const max_header_size = 255; // the common case cheaper by not allocating this space unconditionally struct socks5 : std::enable_shared_from_this { - explicit socks5(io_service& ios, alert_manager& alerts) + explicit socks5(io_service& ios, aux::listen_socket_handle ls + , alert_manager& alerts) : m_socks5_sock(ios) , m_resolver(ios) , m_timer(ios) , m_retry_timer(ios) , m_alerts(alerts) - , m_abort(false) - , m_active(false) + , m_listen_socket(std::move(ls)) {} void start(aux::proxy_settings const& ps); @@ -107,6 +107,7 @@ private: deadline_timer m_timer; deadline_timer m_retry_timer; alert_manager& m_alerts; + aux::listen_socket_handle m_listen_socket; std::array m_tmp_buf; aux::proxy_settings m_proxy_settings; @@ -123,10 +124,10 @@ private: udp::endpoint m_udp_proxy_addr; // set to true when we've been asked to shut down - bool m_abort; + bool m_abort = false; // set to true once the tunnel is established - bool m_active; + bool m_active = false; }; #ifdef TORRENT_HAS_DONT_FRAGMENT @@ -159,9 +160,10 @@ struct set_dont_frag { set_dont_frag(udp::socket&, int) {} }; #endif -udp_socket::udp_socket(io_service& ios) +udp_socket::udp_socket(io_service& ios, aux::listen_socket_handle ls) : m_socket(ios) , m_buf(new receive_buffer()) + , m_listen_socket(std::move(ls)) , m_bind_port(0) , m_abort(true) {} @@ -495,7 +497,8 @@ void udp_socket::set_proxy_settings(aux::proxy_settings const& ps || ps.type == settings_pack::socks5_pw) { // connect to socks5 server and open up the UDP tunnel - m_socks5_connection = std::make_shared(lt::get_io_service(m_socket), alerts); + m_socks5_connection = std::make_shared(lt::get_io_service(m_socket) + , m_listen_socket, alerts); m_socks5_connection->start(ps); } } @@ -528,6 +531,27 @@ void socks5::on_name_lookup(error_code const& e, tcp::resolver::iterator i) return; } + // only set up a SOCKS5 tunnel for sockets with the same address family + // as the proxy + // this is a hack to mitigate excessive SOCKS5 tunnels, until this can get + // fixed properly. + for (;;) + { + if (i == tcp::resolver::iterator{}) + { + if (m_alerts.should_post()) + m_alerts.emplace_alert(tcp::endpoint() + , operation_t::hostname_lookup + , error_code(boost::system::errc::host_unreachable, generic_category())); + return; + } + + // we found a match + if (m_listen_socket.can_route(i->endpoint().address())) + break; + ++i; + } + m_proxy_addr = i->endpoint(); error_code ec; diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 9fbadfb34..163946ecc 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -45,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/time.hpp" #include "libtorrent/aux_/io.hpp" #include "libtorrent/peer.hpp" +#include "libtorrent/error_code.hpp" #ifndef TORRENT_DISABLE_LOGGING #include "libtorrent/socket_io.hpp" @@ -203,24 +204,20 @@ namespace libtorrent { return; } - auto bind_address = bind_interface(); + auto const listen_socket = bind_socket(); - // look for an address that has the same kind as the one - // we're listening on. To make sure the tracker get our - // correct listening address. - bool is_v4 = bind_address.is_v4(); - auto scope = is_v4 ? 0 : bind_address.to_v6().scope_id(); + // filter all endpoints we cannot reach from this listen socket, which may + // be all of them, in which case we should not announce this listen socket + // to this tracker for (auto const& addr : addresses) { - if (addr.is_v4() != is_v4) continue; - if (addr.is_v6() && addr.to_v6().scope_id() != scope) - continue; + if (!listen_socket.can_route(addr)) continue; m_endpoints.emplace_back(addr, std::uint16_t(port)); } if (m_endpoints.empty()) { - fail(error_code(boost::asio::error::address_family_not_supported)); + fail(error_code(boost::system::errc::host_unreachable, generic_category())); return; } diff --git a/test/test_enum_net.cpp b/test/test_enum_net.cpp index 49c3fedc2..7ffe6f348 100644 --- a/test/test_enum_net.cpp +++ b/test/test_enum_net.cpp @@ -76,24 +76,36 @@ TORRENT_TEST(is_any) TORRENT_TEST(match_addr_mask) { - error_code ec; TEST_CHECK(match_addr_mask( - address::from_string("10.0.1.176", ec), - address::from_string("10.0.1.176", ec), - address::from_string("255.255.255.0", ec))); - TEST_CHECK(!ec); + address::from_string("10.0.1.176"), + address::from_string("10.0.1.176"), + address::from_string("255.255.255.0"))); TEST_CHECK(match_addr_mask( - address::from_string("10.0.1.3", ec), - address::from_string("10.0.3.3", ec), - address::from_string("255.255.0.0", ec))); - TEST_CHECK(!ec); + address::from_string("10.0.1.3"), + address::from_string("10.0.3.3"), + address::from_string("255.255.0.0"))); TEST_CHECK(!match_addr_mask( - address::from_string("10.0.1.3", ec), - address::from_string("10.1.3.3", ec), - address::from_string("255.255.0.0", ec))); - TEST_CHECK(!ec); + address::from_string("10.0.1.3"), + address::from_string("10.1.3.3"), + address::from_string("255.255.0.0"))); + + TEST_CHECK(match_addr_mask( + address::from_string("ff00:1234::"), + address::from_string("ff00:5678::"), + address::from_string("ffff::"))); + + TEST_CHECK(!match_addr_mask( + address::from_string("ff00:1234::"), + address::from_string("ff00:5678::"), + address::from_string("ffff:f000::"))); + + // different scope IDs always means a mismatch + TEST_CHECK(!match_addr_mask( + address::from_string("ff00:1234::%1"), + address::from_string("ff00:1234::%2"), + address::from_string("ffff::"))); } TORRENT_TEST(is_ip_address) diff --git a/test/test_listen_socket.cpp b/test/test_listen_socket.cpp index 4661130ea..d10246fb8 100644 --- a/test/test_listen_socket.cpp +++ b/test/test_listen_socket.cpp @@ -57,14 +57,25 @@ namespace TEST_EQUAL(e1.device, dev); } - ip_interface ifc(char const* ip, char const* device) + ip_interface ifc(char const* ip, char const* device, char const* netmask = nullptr) { ip_interface ipi; ipi.interface_address = address::from_string(ip); + if (netmask) ipi.netmask = address::from_string(netmask); strncpy(ipi.name, device, sizeof(ipi.name)); return ipi; } + ip_route rt(char const* ip, char const* device, char const* gateway) + { + ip_route ret; + ret.destination = address::from_string(ip); + ret.gateway = address::from_string(gateway); + std::strncpy(ret.name, device, sizeof(ret.name)); + ret.name[sizeof(ret.name) - 1] = '\0'; + return ret; + } + aux::listen_endpoint_t ep(char const* ip, int port , tp ssl = tp::plaintext , std::string device = {}) @@ -229,6 +240,59 @@ TORRENT_TEST(partition_listen_sockets_op_ports) TEST_EQUAL(eps.size(), 2); } +TORRENT_TEST(expand_devices) +{ + + // this causes us to only expand IPv6 addresses on eth0 + std::vector const routes = { + rt("0.0.0.0", "eth0", "1.2.3.4"), + rt("::", "eth0", "1234:5678::1"), + }; + + std::vector const ifs = { + ifc("127.0.0.1", "lo", "255.0.0.0") + , ifc("192.168.1.2", "eth0", "255.255.255.0") + , ifc("24.172.48.90", "eth1", "255.255.255.0") + , ifc("::1", "lo", "ffff:ffff:ffff:ffff::") + , ifc("fe80::d250:99ff:fe0c:9b74", "eth0", "ffff:ffff:ffff:ffff::") + , ifc("2601:646:c600:a3:d250:99ff:fe0c:9b74", "eth0", "ffff:ffff:ffff:ffff::") + }; + + std::vector eps = { + { + address::from_string("127.0.0.1"), + 6881, // port + "", // device + aux::transport::plaintext, + aux::listen_socket_flags_t{} }, + { + address::from_string("192.168.1.2"), + 6881, // port + "", // device + aux::transport::plaintext, + aux::listen_socket_flags_t{} } + }; + + expand_devices(ifs, routes, eps); + + TEST_CHECK((eps == std::vector{ + { + address::from_string("127.0.0.1"), + 6881, // port + "lo", // device + aux::transport::plaintext, + aux::listen_socket_flags_t{}, + address::from_string("255.0.0.0") }, + { + address::from_string("192.168.1.2"), + 6881, // port + "eth0", // device + aux::transport::plaintext, + aux::listen_socket_flags_t{}, + address::from_string("255.255.255.0") }, + })); +} + TORRENT_TEST(expand_unspecified) { std::vector const ifs = { @@ -237,7 +301,7 @@ TORRENT_TEST(expand_unspecified) , ifc("24.172.48.90", "eth1") , ifc("::1", "lo") , ifc("fe80::d250:99ff:fe0c:9b74", "eth0") - , ifc( "2601:646:c600:a3:d250:99ff:fe0c:9b74", "eth0") + , ifc("2601:646:c600:a3:d250:99ff:fe0c:9b74", "eth0") }; auto v4_nossl = ep("0.0.0.0", 6881); diff --git a/test/test_tracker.cpp b/test/test_tracker.cpp index c5c028a89..4f4a181b8 100644 --- a/test/test_tracker.cpp +++ b/test/test_tracker.cpp @@ -345,7 +345,6 @@ void test_udp_tracker(std::string const& iface, address tracker, tcp::endpoint c settings_pack pack = settings(); pack.set_bool(settings_pack::announce_to_all_trackers, true); pack.set_bool(settings_pack::announce_to_all_tiers, true); - pack.set_str(settings_pack::listen_interfaces, iface + ":48875"); std::unique_ptr s(new lt::session(pack)); @@ -420,7 +419,10 @@ TORRENT_TEST(udp_tracker_v6) { if (supports_ipv6()) { - test_udp_tracker("[::1]", address_v6::any(), ep("::1.3.3.7", 1337)); + // if the machine running the test doesn't have an actual IPv6 connection + // the test would fail with any other address than loopback (because it + // would be unreachable) + test_udp_tracker("[::1]", address_v6::any(), ep("::1", 1337)); } } diff --git a/test/udp_tracker.cpp b/test/udp_tracker.cpp index e0a1d11c6..a4176f51a 100644 --- a/test/udp_tracker.cpp +++ b/test/udp_tracker.cpp @@ -138,10 +138,10 @@ struct udp_tracker detail::write_uint32(0, ptr); detail::write_uint32(0, ptr); detail::write_uint32(0, ptr); + detail::write_uint8(0, ptr); + detail::write_uint8(0, ptr); + detail::write_uint8(0, ptr); detail::write_uint8(1, ptr); - detail::write_uint8(3, ptr); - detail::write_uint8(3, ptr); - detail::write_uint8(7, ptr); detail::write_uint16(1337, ptr); } else