improve obfuscated get_peers

This commit is contained in:
Arvid Norberg 2013-10-26 22:59:55 +00:00
parent 9e610dca46
commit 1d55894bef
4 changed files with 62 additions and 7 deletions

View File

@ -57,7 +57,7 @@ class node_impl;
// -------- find data -----------
//TODO: 3 rename this class to find_peers, since that's what it does
//TODO: 3 rename this class to get_peers, since that's what it does
// find_data is an unnecessarily generic name
class find_data : public traversal_algorithm
{
@ -112,6 +112,10 @@ protected:
observer_ptr new_observer(void* ptr, udp::endpoint const& ep, node_id const& id);
virtual bool invoke(observer_ptr o);
virtual void done();
private:
// when set to false, we no longer obfuscate
// the target hash, and send regular get_peers
bool m_obfuscated;
};
class find_data_observer : public observer

View File

@ -146,6 +146,11 @@ public:
boost::tuple<int, int> size() const;
size_type num_global_nodes() const;
// the number of bits down we have full buckets
// i.e. essentially the number of full buckets
// we have
int depth() const;
// returns true if there are no working nodes
// in the routing table

View File

@ -267,10 +267,11 @@ obfuscated_get_peers::obfuscated_get_peers(
, nodes_callback const& ncallback
, bool noseeds)
: find_data(node, info_hash, dcallback, ncallback, noseeds)
, m_obfuscated(true)
{
}
char const* obfuscated_get_peers::name() const { return "get_peers [obfuscated]"; }
char const* obfuscated_get_peers::name() const { return !m_obfuscated ? find_data::name() : "get_peers [obfuscated]"; }
observer_ptr obfuscated_get_peers::new_observer(void* ptr
, udp::endpoint const& ep, node_id const& id)
@ -284,6 +285,34 @@ observer_ptr obfuscated_get_peers::new_observer(void* ptr
bool obfuscated_get_peers::invoke(observer_ptr o)
{
if (!m_obfuscated) return find_data::invoke(o);
node_id id = o->id();
int shared_prefix = 160 - distance_exp(id, m_target);
// when we get close to the target zone in the DHT
// start using the correct info-hash, in order to
// start receiving peers
if (shared_prefix > m_node.m_table.depth() - 10)
{
m_obfuscated = false;
// clear the queried bits on all successful nodes in
// our node-list for this traversal algorithm, to
// allow the get_peers traversal to regress in case
// nodes further down end up being dead
for (std::vector<observer_ptr>::iterator i = m_results.begin()
, end(m_results.end()); i != end; ++i)
{
observer* o = i->get();
// don't re-request from nodes that didn't respond
if (o->flags & observer::flag_failed) continue;
// don't interrupt with queries that are already in-flight
if ((o->flags & observer::flag_alive) == 0) continue;
o->flags &= ~(observer::flag_queried | observer::flag_alive);
}
return find_data::invoke(o);
}
entry e;
e["y"] = "q";
e["q"] = "find_node";
@ -295,9 +324,6 @@ bool obfuscated_get_peers::invoke(observer_ptr o)
// bits in the info-hash for the node we're querying to
// give a good answer, but not more.
node_id id = o->id();
int shared_prefix = 160 - distance_exp(id, m_target);
// now, obfuscate the bits past shared_prefix + 5
node_id obfuscated_target = generate_random_id();
obfuscated_target >>= shared_prefix + 3;
@ -309,6 +335,11 @@ bool obfuscated_get_peers::invoke(observer_ptr o)
void obfuscated_get_peers::done()
{
if (!m_obfuscated) return find_data::done();
// oops, we failed to switch over to the non-obfuscated
// mode early enough. do it now
boost::intrusive_ptr<find_data> ta(new find_data(m_node, m_target
, m_data_callback
, m_nodes_callback
@ -327,11 +358,11 @@ void obfuscated_get_peers::done()
int num_added = 0;
for (std::vector<observer_ptr>::iterator i = m_results.begin()
, end(m_results.end()); i != end && num_added < 10; ++i)
, end(m_results.end()); i != end && num_added < 16; ++i)
{
observer_ptr o = *i;
// only add nodes whose node ID we knoe and that
// only add nodes whose node ID we know and that
// we know are alive
if (o->flags & observer::flag_no_id) continue;
if ((o->flags & observer::flag_alive) == 0) continue;

View File

@ -126,6 +126,21 @@ size_type routing_table::num_global_nodes() const
else return (size_type(2) << deepest_bucket) * deepest_size;
}
int routing_table::depth() const
{
// TODO: 3 cache the depth!
int deepest_bucket = 0;
for (table_t::const_iterator i = m_buckets.begin()
, end(m_buckets.end()); i != end; ++i)
{
if (i->live_nodes.size() < m_bucket_size)
break;
// this bucket is full
++deepest_bucket;
}
return deepest_bucket;
}
#if (defined TORRENT_DHT_VERBOSE_LOGGING || defined TORRENT_DEBUG) && TORRENT_USE_IOSTREAM
void routing_table::print_state(std::ostream& os) const