diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 326989626..43e536644 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -69,6 +69,14 @@ namespace libtorrent { namespace dht c.inc_stats_counter(counters::dht_allocated_observers, allocated_observers); } + std::vector concat(std::vector const& v1 + , std::vector const& v2) + { + std::vector r = v1; + r.insert(r.end(), v2.begin(), v2.end()); + return r; + } + } // anonymous namespace // class that puts the networking and the kademlia node in a single @@ -155,9 +163,10 @@ namespace libtorrent { namespace dht m_refresh_timer.expires_from_now(seconds(5), ec); m_refresh_timer.async_wait(std::bind(&dht_tracker::refresh_timeout, self(), _1)); - m_dht.bootstrap(m_state.nodes, f); + // bootstrap with mix of IP protocols via want/nodes/nodes6 + m_dht.bootstrap(concat(m_state.nodes, m_state.nodes6), f); #if TORRENT_USE_IPV6 - m_dht6.bootstrap(m_state.nodes6, f); + m_dht6.bootstrap(concat(m_state.nodes6, m_state.nodes), f); #endif m_state.clear(); } diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index 51cbb51d9..de96115d8 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -220,7 +220,10 @@ void node::bootstrap(std::vector const& nodes for (auto const& n : nodes) { - if (n.protocol() != protocol()) continue; +#if !TORRENT_USE_IPV6 + if (n.protocol() == udp::v6()) continue; +#endif + #ifndef TORRENT_DISABLE_LOGGING ++count; #endif diff --git a/src/kademlia/routing_table.cpp b/src/kademlia/routing_table.cpp index 094a776e4..368142cf1 100644 --- a/src/kademlia/routing_table.cpp +++ b/src/kademlia/routing_table.cpp @@ -198,7 +198,7 @@ std::int64_t routing_table::num_global_nodes() const int deepest_size = 0; for (auto const& i : m_buckets) { - deepest_size = int(i.live_nodes.size()); // + i.replacements.size(); + deepest_size = i.live_nodes.end_index(); // + i.replacements.size(); if (deepest_size < m_bucket_size) break; // this bucket is full ++deepest_bucket; diff --git a/src/kademlia/traversal_algorithm.cpp b/src/kademlia/traversal_algorithm.cpp index 7910ea087..065f07b55 100644 --- a/src/kademlia/traversal_algorithm.cpp +++ b/src/kademlia/traversal_algorithm.cpp @@ -510,7 +510,7 @@ void traversal_algorithm::add_router_entries() void traversal_algorithm::init() { - m_branch_factor = std::int16_t(m_node.branch_factor()); + m_branch_factor = aux::numeric_cast(m_node.branch_factor()); m_node.add_traversal_algorithm(this); } diff --git a/test/test_alert_types.cpp b/test/test_alert_types.cpp index c50e74ade..68865e969 100644 --- a/test/test_alert_types.cpp +++ b/test/test_alert_types.cpp @@ -46,6 +46,7 @@ TORRENT_TEST(alerts_types) TEST_EQUAL(name::alert_type, seq); \ TEST_EQUAL(name::static_category, cat); + TEST_ALERT_TYPE(dht_bootstrap_alert, 62, 0, alert::dht_notification); TEST_ALERT_TYPE(session_stats_alert, 70, 1, alert::stats_notification); TEST_ALERT_TYPE(dht_get_peers_reply_alert, 87, 0, alert::dht_operation_notification); TEST_ALERT_TYPE(session_error_alert, 90, 0, alert::error_notification); diff --git a/test/test_dht.cpp b/test/test_dht.cpp index 245655468..2018bd3f4 100644 --- a/test/test_dht.cpp +++ b/test/test_dht.cpp @@ -1824,6 +1824,75 @@ TORRENT_TEST(bootstrap_v6) } #endif +#if TORRENT_USE_IPV6 +void test_bootstrap_want(address(&rand_addr)()) +{ + dht_test_setup t(udp::endpoint(rand_addr(), 20)); + bdecode_node response; + bool ret; + + dht::key_desc_t const find_node_desc[] = { + {"y", bdecode_node::string_t, 1, 0}, + {"t", bdecode_node::string_t, 2, 0}, + {"q", bdecode_node::string_t, 9, 0}, + {"a", bdecode_node::dict_t, 0, key_desc_t::parse_children}, + {"id", bdecode_node::string_t, 20, 0}, + {"target", bdecode_node::string_t, 20, key_desc_t::optional}, + {"info_hash", bdecode_node::string_t, 20, key_desc_t::optional}, + {"want", bdecode_node::list_t, 0, key_desc_t::last_child}, + }; + + bdecode_node find_node_keys[8]; + + g_sent_packets.clear(); + + std::vector nodesv; + if (t.source.address().is_v4()) + nodesv.push_back(rand_udp_ep(rand_v6)); + else + nodesv.push_back(rand_udp_ep(rand_v4)); + + t.dht_node.bootstrap(nodesv, std::bind(&nop_node)); + + TEST_EQUAL(g_sent_packets.size(), 1); + TEST_EQUAL(g_sent_packets.front().first, nodesv[0]); + + lazy_from_entry(g_sent_packets.front().second, response); + ret = verify_message(response, find_node_desc, find_node_keys, t.error_string); + if (ret) + { + TEST_EQUAL(find_node_keys[0].string_value(), "q"); + TEST_CHECK(find_node_keys[2].string_value() == "find_node" + || find_node_keys[2].string_value() == "get_peers"); + + TEST_EQUAL(find_node_keys[7].list_size(), 1); + if (t.source.address().is_v4()) + { + TEST_EQUAL(find_node_keys[7].list_string_value_at(0), "n4"); + } + else + { + TEST_EQUAL(find_node_keys[7].list_string_value_at(0), "n6"); + } + } + else + { + std::printf(" invalid find_node request: %s\n", print_entry(response).c_str()); + TEST_ERROR(t.error_string); + } +} + +TORRENT_TEST(bootstrap_want_v4) +{ + test_bootstrap_want(rand_v4); +} + +TORRENT_TEST(bootstrap_want_v6) +{ + test_bootstrap_want(rand_v6); +} +#endif + // test that the node ignores a nodes entry which is too short void test_short_nodes(address(&rand_addr)()) {