allow DHT bootstrap to use nodes of both IP protocols

This commit is contained in:
Alden Torres 2017-03-16 08:40:00 -04:00 committed by Arvid Norberg
parent 9efb72197c
commit 014a07a5c8
6 changed files with 87 additions and 5 deletions

View File

@ -69,6 +69,14 @@ namespace libtorrent { namespace dht
c.inc_stats_counter(counters::dht_allocated_observers, allocated_observers);
}
std::vector<udp::endpoint> concat(std::vector<udp::endpoint> const& v1
, std::vector<udp::endpoint> const& v2)
{
std::vector<udp::endpoint> 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();
}

View File

@ -220,7 +220,10 @@ void node::bootstrap(std::vector<udp::endpoint> 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

View File

@ -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;

View File

@ -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<std::int16_t>(m_node.branch_factor());
m_node.add_traversal_algorithm(this);
}

View File

@ -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);

View File

@ -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<udp::endpoint> 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)())
{