From 0e04ab8d72270c03e7ccb5a6d1201a6c26007b93 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 3 Mar 2014 05:09:53 +0000 Subject: [PATCH] reorder the node-list in the DHT traversal algorithm if a node updates its ID --- include/libtorrent/kademlia/observer.hpp | 2 +- .../kademlia/traversal_algorithm.hpp | 1 + src/kademlia/find_data.cpp | 4 -- src/kademlia/rpc_manager.cpp | 7 +++ src/kademlia/traversal_algorithm.cpp | 47 +++++++++++++++++++ 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/include/libtorrent/kademlia/observer.hpp b/include/libtorrent/kademlia/observer.hpp index 174db7ebf..61c6d714e 100644 --- a/include/libtorrent/kademlia/observer.hpp +++ b/include/libtorrent/kademlia/observer.hpp @@ -115,7 +115,7 @@ struct observer : boost::noncopyable address target_addr() const; udp::endpoint target_ep() const; - void set_id(node_id const& id) { m_id = id; } + void set_id(node_id const& id); node_id const& id() const { return m_id; } void set_transaction_id(boost::uint16_t tid) diff --git a/include/libtorrent/kademlia/traversal_algorithm.hpp b/include/libtorrent/kademlia/traversal_algorithm.hpp index 92b98d4b9..1abd13d56 100644 --- a/include/libtorrent/kademlia/traversal_algorithm.hpp +++ b/include/libtorrent/kademlia/traversal_algorithm.hpp @@ -77,6 +77,7 @@ struct traversal_algorithm : boost::noncopyable node_id const& target() const { return m_target; } + void resort_results(); void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags); traversal_algorithm(node_impl& node, node_id target); diff --git a/src/kademlia/find_data.cpp b/src/kademlia/find_data.cpp index 39814f55a..3e4d4e9d2 100644 --- a/src/kademlia/find_data.cpp +++ b/src/kademlia/find_data.cpp @@ -80,10 +80,6 @@ void find_data_observer::reply(msg const& m) node_id(id->string_ptr()), token->string_value()); } - // in case we didn't know the id of this peer when we sent the message to - // it. For instance if it's a bootstrap node. - set_id(node_id(id->string_ptr())); - traversal_observer::reply(m); done(); } diff --git a/src/kademlia/rpc_manager.cpp b/src/kademlia/rpc_manager.cpp index ea02fda7d..bf322d0c4 100644 --- a/src/kademlia/rpc_manager.cpp +++ b/src/kademlia/rpc_manager.cpp @@ -151,6 +151,13 @@ void observer::timeout() m_algorithm->failed(observer_ptr(this)); } +void observer::set_id(node_id const& id) +{ + if (m_id == id) return; + m_id = id; + if (m_algorithm) m_algorithm->resort_results(); +} + enum { observer_size = max3< sizeof(find_data_observer) , sizeof(announce_observer) diff --git a/src/kademlia/traversal_algorithm.cpp b/src/kademlia/traversal_algorithm.cpp index a9f6cf86b..f108a1aeb 100644 --- a/src/kademlia/traversal_algorithm.cpp +++ b/src/kademlia/traversal_algorithm.cpp @@ -42,6 +42,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/broadcast_socket.hpp" // for cidr_distance #include // for read_*_endpoint +#if TORRENT_USE_ASSERTS +#include // for is_sorted +#endif + #include namespace libtorrent { namespace dht @@ -100,6 +104,20 @@ bool compare_ip_cidr(observer_ptr const& lhs, observer_ptr const& rhs) return dist <= cutoff; } +void traversal_algorithm::resort_results() +{ + std::sort( + m_results.begin() + , m_results.end() + , boost::bind( + compare_ref + , boost::bind(&observer::id, _1) + , boost::bind(&observer::id, _2) + , m_target + ) + ); +} + void traversal_algorithm::add_entry(node_id const& id, udp::endpoint addr, unsigned char flags) { TORRENT_ASSERT(m_node.m_rpc.allocation_size() >= sizeof(find_data_observer)); @@ -121,6 +139,14 @@ void traversal_algorithm::add_entry(node_id const& id, udp::endpoint addr, unsig o->flags |= flags; + TORRENT_ASSERT(boost::algorithm::is_sorted(m_results.begin(), m_results.end() + , boost::bind( + compare_ref + , boost::bind(&observer::id, _1) + , boost::bind(&observer::id, _2) + , m_target) + )); + std::vector::iterator i = std::lower_bound( m_results.begin() , m_results.end() @@ -172,6 +198,14 @@ void traversal_algorithm::add_entry(node_id const& id, udp::endpoint addr, unsig ; #endif i = m_results.insert(i, o); + + TORRENT_ASSERT(boost::algorithm::is_sorted(m_results.begin(), m_results.end() + , boost::bind( + compare_ref + , boost::bind(&observer::id, _1) + , boost::bind(&observer::id, _2) + , m_target) + )); } if (m_results.size() > 100) @@ -512,6 +546,19 @@ void traversal_observer::reply(msg const& m) m_algorithm->traverse(id, read_v4_endpoint(nodes)); } } + + lazy_entry const* id = r->dict_find_string("id"); + if (!id || id->string_length() != 20) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(traversal) << "[" << m_algorithm.get() << "] invalid id in response"; +#endif + return; + } + + // in case we didn't know the id of this peer when we sent the message to + // it. For instance if it's a bootstrap node. + set_id(node_id(id->string_ptr())); } void traversal_algorithm::abort()