41
40
#include <boost/bind.hpp>
43
42
#include "libtorrent/kademlia/routing_table.hpp"
43
#include "libtorrent/session_status.hpp"
44
44
#include "libtorrent/kademlia/node_id.hpp"
45
45
#include "libtorrent/session_settings.hpp"
59
59
: m_bucket_size(bucket_size)
60
60
, m_settings(settings)
62
, m_last_bootstrap(min_time())
62
63
, m_lowest_active_bucket(160)
64
65
// distribute the refresh times for the buckets in an
65
// attempt do even out the network load
66
// attempt to even out the network load
66
67
for (int i = 0; i < 160; ++i)
67
68
m_bucket_activity[i] = time_now() - milliseconds(i*5625);
68
69
m_bucket_activity[0] = time_now() - minutes(15);
72
void routing_table::status(session_status& s) const
74
boost::tie(s.dht_nodes, s.dht_node_cache) = size();
75
s.dht_global_nodes = num_global_nodes();
71
78
boost::tuple<int, int> routing_table::size() const
142
149
for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end());
152
if (i->first.empty()) continue;
145
153
int bucket_index = int(i - m_buckets.begin());
146
154
os << "=== BUCKET = " << bucket_index
147
155
<< " = " << (bucket_index >= m_lowest_active_bucket?"active":"inactive")
148
156
<< " = " << total_seconds(time_now() - m_bucket_activity[bucket_index])
149
<< " s ago ===== \n";
157
<< " seconds ago ===== \n";
150
158
for (bucket_t::const_iterator j = i->first.begin()
151
159
, end(i->first.end()); j != end; ++j)
153
os << "ip: " << j->addr << " fails: " << j->fail_count
154
<< " id: " << j->id << "\n";
161
os << " id: " << j->id
162
<< " ip: " << j->ep()
163
<< " fails: " << j->fail_count()
164
<< " pinged: " << j->pinged()
187
bool routing_table::need_node(node_id const& id)
198
void routing_table::heard_about(node_id const& id, udp::endpoint const& ep)
189
200
int bucket_index = distance_exp(m_id, id);
190
201
TORRENT_ASSERT(bucket_index < (int)m_buckets.size());
195
206
// if the replacement cache is full, we don't
196
207
// need another node. The table is fine the
198
if ((int)rb.size() >= m_bucket_size) return false;
209
if ((int)rb.size() >= m_bucket_size) return;
200
211
// if the node already exists, we don't need it
201
212
if (std::find_if(b.begin(), b.end(), bind(&node_entry::id, _1) == id)
202
!= b.end()) return false;
204
215
if (std::find_if(rb.begin(), rb.end(), bind(&node_entry::id, _1) == id)
205
!= rb.end()) return false;
218
if (b.size() < m_bucket_size)
220
if (bucket_index < m_lowest_active_bucket
222
m_lowest_active_bucket = bucket_index;
223
b.push_back(node_entry(id, ep, false));
227
if (rb.size() < m_bucket_size)
228
rb.push_back(node_entry(id, ep, false));
210
231
void routing_table::node_failed(node_id const& id)
230
251
#ifdef TORRENT_DHT_VERBOSE_LOGGING
231
252
TORRENT_LOG(table) << " NODE FAILED"
233
" ip: " << i->addr <<
234
" fails: " << i->fail_count <<
254
" ip: " << i->ep() <<
255
" fails: " << i->fail_count() <<
256
" pinged: " << i->pinged() <<
235
257
" up-time: " << total_seconds(time_now() - i->first_seen);
238
if (i->fail_count >= m_settings.max_fail_count)
260
// if this node has failed too many times, or if this node
261
// has never responded at all, remove it
262
if (i->fail_count() >= m_settings.max_fail_count || !i->pinged())
241
265
TORRENT_ASSERT(m_lowest_active_bucket <= bucket_index);
252
b.push_back(rb.back());
253
rb.erase(rb.end() - 1);
277
i = std::find_if(rb.begin(), rb.end(), bind(&node_entry::pinged, _1) == true);
278
if (i == rb.end()) i = rb.begin();
256
283
void routing_table::add_router_node(udp::endpoint router)
283
310
if (i != b.end())
285
// TODO: what do we do if we see a node with
286
// the same id as a node at a different address?
287
// TORRENT_ASSERT(i->addr == addr);
289
312
// we already have the node in our bucket
290
313
// just move it to the back since it was
291
314
// the last node we had any contact with
292
315
// in this bucket
294
b.push_back(node_entry(id, addr));
295
// TORRENT_LOG(table) << "replacing node: " << id << " " << addr;
317
i->reset_fail_count();
318
i->addr = addr.address();
319
i->port = addr.port();
320
// TORRENT_LOG(table) << "updating node: " << id << " " << addr;
303
328
if ((int)b.size() < m_bucket_size)
305
330
if (b.empty()) b.reserve(m_bucket_size);
306
b.push_back(node_entry(id, addr));
331
b.push_back(node_entry(id, addr, true));
307
332
// if bucket index is 0, the node is ourselves
308
333
// don't updated m_lowest_active_bucket
309
334
if (bucket_index < m_lowest_active_bucket
316
// if there is no room, we look for nodes marked as stale
341
// if there is no room, we look for nodes that are not 'pinged',
342
// i.e. we haven't confirmed that they respond to messages.
343
// Then we look for nodes marked as stale
317
344
// in the k-bucket. If we find one, we can replace it.
346
i = std::find_if(b.begin(), b.end(), bind(&node_entry::pinged, _1) == false);
348
if (i != b.end() && !i->pinged())
350
// i points to a node that has not been pinged.
351
// Replace it with this new one
353
b.push_back(node_entry(id, addr, true));
354
// TORRENT_LOG(table) << "replacing unpinged node: " << id << " " << addr;
318
358
// A node is considered stale if it has failed at least one
319
359
// time. Here we choose the node that has failed most times.
320
360
// If we don't find one, place this node in the replacement-
325
365
, bind(&node_entry::fail_count, _1)
326
366
< bind(&node_entry::fail_count, _2));
328
if (i != b.end() && i->fail_count > 0)
368
if (i != b.end() && i->fail_count() > 0)
330
370
// i points to a node that has been marked
331
371
// as stale. Replace it with this new one
333
b.push_back(node_entry(id, addr));
373
b.push_back(node_entry(id, addr, true));
334
374
// TORRENT_LOG(table) << "replacing stale node: " << id << " " << addr;
348
388
// if the node is already in the replacement bucket
350
if (i != rb.end()) return ret;
392
// make sure we mark this node as pinged
393
// and if its address has changed, update
396
i->reset_fail_count();
397
i->addr = addr.address();
398
i->port = addr.port();
352
if ((int)rb.size() > m_bucket_size) rb.erase(rb.begin());
402
if ((int)rb.size() >= m_bucket_size)
404
// if the replacement bucket is full, remove the oldest entry
405
// but prefer nodes that haven't been pinged, since they are
406
// less reliable than this one, that has been pinged
407
i = std::find_if(rb.begin(), rb.end(), bind(&node_entry::pinged, _1) == false);
408
rb.erase(i != rb.end() ? i : rb.begin());
353
410
if (rb.empty()) rb.reserve(m_bucket_size);
354
rb.push_back(node_entry(id, addr));
411
rb.push_back(node_entry(id, addr, true));
355
412
// TORRENT_LOG(table) << "inserting node in replacement cache: " << id << " " << addr;
359
416
bool routing_table::need_bootstrap() const
418
ptime now = time_now();
419
if (now - m_last_bootstrap < seconds(30)) return false;
361
421
for (const_iterator i = begin(); i != end(); ++i)
363
if (i->fail_count == 0) return false;
423
if (i->confirmed()) return false;
425
m_last_bootstrap = now;
442
template <class SrcIter, class DstIter>
443
DstIter copy_n(SrcIter begin, SrcIter end, DstIter target, size_t n)
445
for (; n > 0 && begin != end; ++begin)
381
454
// fills the vector with the k nodes from our buckets that
382
455
// are nearest to the given id.
383
456
void routing_table::find_node(node_id const& target
384
, std::vector<node_entry>& l, bool include_self, int count)
457
, std::vector<node_entry>& l, int options, int count)
387
460
if (count == 0) count = m_bucket_size;
393
466
// copy all nodes that hasn't failed into the target
395
copy_if_n(b.begin(), b.end(), std::back_inserter(l)
396
, (std::min)(size_t(count), b.size()), bind(&node_entry::fail_count, _1) == 0);
468
if (options & include_failed)
470
copy_n(b.begin(), b.end(), std::back_inserter(l)
471
, (std::min)(size_t(count), b.size()));
475
copy_if_n(b.begin(), b.end(), std::back_inserter(l)
476
, (std::min)(size_t(count), b.size())
477
, bind(&node_entry::confirmed, _1));
397
479
TORRENT_ASSERT((int)l.size() <= count);
399
if ((int)l.size() == count)
481
if (int(l.size()) == count)
401
TORRENT_ASSERT(std::count_if(l.begin(), l.end()
402
, boost::bind(&node_entry::fail_count, _1) != 0) == 0);
483
TORRENT_ASSERT((options & include_failed)
484
|| std::count_if(l.begin(), l.end()
485
, !boost::bind(&node_entry::confirmed, _1)) == 0);
409
492
// [0, bucket_index) if we are to include ourself
410
493
// or [1, bucket_index) if not.
412
for (int i = include_self?0:1; i < bucket_index; ++i)
495
for (int i = (options & include_self)?0:1; i < bucket_index; ++i)
414
497
bucket_t& b = m_buckets[i].first;
415
std::remove_copy_if(b.begin(), b.end(), std::back_inserter(tmpb)
416
, bind(&node_entry::fail_count, _1));
498
if (options & include_failed)
500
copy(b.begin(), b.end(), std::back_inserter(tmpb));
504
std::remove_copy_if(b.begin(), b.end(), std::back_inserter(tmpb)
505
, !bind(&node_entry::confirmed, _1));
419
509
if (count - l.size() < tmpb.size())
432
522
// return if we have enough nodes or if the bucket index
433
523
// is the biggest index available (there are no more buckets)
435
if ((int)l.size() == count)
525
if (int(l.size()) == count)
437
TORRENT_ASSERT(std::count_if(l.begin(), l.end()
438
, boost::bind(&node_entry::fail_count, _1) != 0) == 0);
527
TORRENT_ASSERT((options & include_failed)
528
|| std::count_if(l.begin(), l.end()
529
, !boost::bind(&node_entry::confirmed, _1)) == 0);
444
535
bucket_t& b = m_buckets[i].first;
446
537
size_t to_copy = (std::min)(count - l.size(), b.size());
447
copy_if_n(b.begin(), b.end(), std::back_inserter(l)
448
, to_copy, bind(&node_entry::fail_count, _1) == 0);
538
if (options & include_failed)
540
copy_n(b.begin(), b.end(), std::back_inserter(l), to_copy);
544
copy_if_n(b.begin(), b.end(), std::back_inserter(l)
545
, to_copy, bind(&node_entry::confirmed, _1));
449
547
TORRENT_ASSERT((int)l.size() <= count);
450
if ((int)l.size() == count)
548
if (int(l.size()) == count)
452
TORRENT_ASSERT(std::count_if(l.begin(), l.end()
453
, boost::bind(&node_entry::fail_count, _1) != 0) == 0);
550
TORRENT_ASSERT((options & include_failed)
551
|| std::count_if(l.begin(), l.end()
552
, !boost::bind(&node_entry::confirmed, _1)) == 0);
457
556
TORRENT_ASSERT((int)l.size() <= count);
459
TORRENT_ASSERT(std::count_if(l.begin(), l.end()
460
, boost::bind(&node_entry::fail_count, _1) != 0) == 0);
558
TORRENT_ASSERT((options & include_failed)
559
|| std::count_if(l.begin(), l.end()
560
, !boost::bind(&node_entry::confirmed, _1)) == 0);
463
563
routing_table::iterator routing_table::begin() const