reorder the node-list in the DHT traversal algorithm if a node updates its ID

This commit is contained in:
Arvid Norberg 2014-03-03 05:09:53 +00:00
parent fd26cc026b
commit 0e04ab8d72
5 changed files with 56 additions and 5 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -42,6 +42,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/broadcast_socket.hpp" // for cidr_distance
#include <libtorrent/socket_io.hpp> // for read_*_endpoint
#if TORRENT_USE_ASSERTS
#include <boost/algorithm/cxx11/is_sorted.hpp> // for is_sorted
#endif
#include <boost/bind.hpp>
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<observer_ptr>::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<udp::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()