diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 117e9adfd..bb9bb5f8c 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -139,9 +139,17 @@ namespace aux { struct TORRENT_EXTRA_EXPORT listen_socket_t : utp_socket_interface { + // we accept incoming connections on this interface static constexpr listen_socket_flags_t accept_incoming = 0_bit; + + // this interface has a gateway associated with it, and can + // route to the internet (of the same address family) static constexpr listen_socket_flags_t has_gateway = 1_bit; + // this interface was expanded from the user requesting to + // listen on an unspecified address (either IPv4 or IPv6) + static constexpr listen_socket_flags_t was_expanded = 2_bit; + listen_socket_t() = default; // listen_socket_t should not be copied or moved because diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index e39105c9b..356b5b211 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -116,14 +116,7 @@ namespace libtorrent { namespace dht { void dht_tracker::new_socket(aux::listen_socket_handle const& s) { - if (s.is_ssl()) return; - address const local_address = s.get_local_endpoint().address(); - // don't try to start dht nodes on non-global IPv6 addresses - // with IPv4 the interface might be behind NAT so we can't skip them based on the scope of the local address - // and we might not have the external address yet - if (local_address.is_v6() && is_local(local_address)) - return; auto stored_nid = std::find_if(m_state.nids.begin(), m_state.nids.end() , [&](node_ids_t::value_type const& nid) { return nid.first == local_address; }); node_id const nid = stored_nid != m_state.nids.end() ? stored_nid->second : node_id(); @@ -157,13 +150,6 @@ namespace libtorrent { namespace dht { void dht_tracker::delete_socket(aux::listen_socket_handle const& s) { - if (s.is_ssl()) return; - - address local_address = s.get_local_endpoint().address(); - // since we don't start nodes on local IPv6 interfaces we don't need to remove them either - if (local_address.is_v6() && is_local(local_address)) - return; - TORRENT_ASSERT(m_nodes.count(s) == 1); m_nodes.erase(s); } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 24ae737c1..8e1a980e5 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -200,6 +200,7 @@ namespace aux { constexpr listen_socket_flags_t listen_socket_t::accept_incoming; constexpr listen_socket_flags_t listen_socket_t::has_gateway; + constexpr listen_socket_flags_t listen_socket_t::was_expanded; constexpr ip_source_t session_interface::source_dht; constexpr ip_source_t session_interface::source_peer; @@ -273,7 +274,7 @@ namespace aux { } eps.emplace_back(ipface.interface_address, uep.port, uep.device - , uep.ssl, uep.flags); + , uep.ssl, uep.flags | listen_socket_t::was_expanded); } } } @@ -1897,8 +1898,18 @@ namespace aux { m_listen_sockets.emplace_back(s); #ifndef TORRENT_DISABLE_DHT - if (m_dht) + // addresses that we expanded from an + // unspecified address don't get a DHT running + // on them, unless they have a gateway (in + // which case we believe they can reach the + // internet) + if (m_dht + && s->ssl != transport::ssl + && ((s->flags & listen_socket_t::has_gateway) + || !(s->flags & listen_socket_t::was_expanded))) + { m_dht->new_socket(m_listen_sockets.back()); + } #endif TORRENT_ASSERT(bool(s->flags & listen_socket_t::accept_incoming) == bool(s->sock)); @@ -5745,7 +5756,14 @@ namespace aux { , std::move(m_dht_state)); for (auto& s : m_listen_sockets) - m_dht->new_socket(s); + { + if (s->ssl != transport::ssl + && ((s->flags & listen_socket_t::has_gateway) + || !(s->flags & listen_socket_t::was_expanded))) + { + m_dht->new_socket(s); + } + } for (auto const& n : m_dht_router_nodes) { diff --git a/test/test_session_params.cpp b/test/test_session_params.cpp index 8981016f0..986560a1b 100644 --- a/test/test_session_params.cpp +++ b/test/test_session_params.cpp @@ -121,6 +121,8 @@ TORRENT_TEST(dht_state) params.dht_settings = sett; params.dht_state = s; + params.settings.set_str(settings_pack::listen_interfaces, "127.0.0.1:6881"); + lt::session ses1(params); TEST_CHECK(ses1.is_dht_running() == true); entry e; @@ -138,11 +140,10 @@ TORRENT_TEST(dht_state) TEST_EQUAL(params1.dht_settings.max_dht_items, 10000); TEST_EQUAL(params1.dht_settings.max_peers, 20000); + TEST_EQUAL(params1.dht_state.nids.size(), 1); + // not a chance the nid will be the fake initial ones TEST_CHECK(params1.dht_state.nids[0].second != s.nids[0].second); - // the host machine may not have IPv6 support in which case there will only be one entry - if (params1.dht_state.nids.size() > 1) - TEST_CHECK(params1.dht_state.nids[1].second != s.nids[1].second); } #endif