diff --git a/include/opendht/dht.h b/include/opendht/dht.h index 9a21b308b2589041837b486048f03457da164df6..ecb85d878d03456358ceba4c842d50b6e20b667c 100644 --- a/include/opendht/dht.h +++ b/include/opendht/dht.h @@ -169,7 +169,7 @@ public: * Initialise the Dht with two open sockets (for IPv4 and IP6) * and an ID for the node. */ - Dht(int s, int s6, const InfoHash& id); + Dht(int s, int s6, const InfoHash& id, bool bootstrap = false); virtual ~Dht(); /** @@ -413,6 +413,8 @@ private: */ InfoHash randomId(const RoutingTable::const_iterator& bucket) const; + unsigned depth(const RoutingTable::const_iterator& bucket) const; + /** * Split a bucket in two equal parts. */ @@ -699,6 +701,12 @@ private: // cache of nodes not in the main routing table but used for searches NodeCache cache; + // are we a bootstrap node ? + // note: Any running node can be used as a bootstrap node. + // Only nodes running only as bootstrap nodes should + // be put in bootstrap mode. + const bool is_bootstrap {false}; + // the stuff RoutingTable buckets {}; RoutingTable buckets6 {}; diff --git a/include/opendht/infohash.h b/include/opendht/infohash.h index e3d735e3b3224b10702115432fd063d7f1360a18..4a98a23138936745262301b61a319be9c8e96b86 100644 --- a/include/opendht/infohash.h +++ b/include/opendht/infohash.h @@ -152,7 +152,7 @@ public: void setBit(unsigned nbit, bool b) { - auto& num = *(begin()+(nbit/8)); + auto& num = (*this)[nbit/8]; unsigned bit = 7 - (nbit % 8); num ^= (-b ^ num) & (1 << bit); } diff --git a/src/dht.cpp b/src/dht.cpp index 1279386d52682e7136c7e16543d86f47fae27a26..f6ea0fef972a85c06535117baf73a0bd809425dc 100644 --- a/src/dht.cpp +++ b/src/dht.cpp @@ -261,18 +261,23 @@ Dht::RoutingTable::randomId(const Dht::RoutingTable::const_iterator& it) const InfoHash Dht::RoutingTable::middle(const RoutingTable::const_iterator& it) const { - int bit1 = it->first.lowbit(); - int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1; - int bit = std::max(bit1, bit2) + 1; - - if (bit >= 8*(int)HASH_LEN) + unsigned bit = depth(it); + if (bit >= 8*HASH_LEN) throw std::out_of_range("End of table"); InfoHash id = it->first; - id[bit / 8] |= (0x80 >> (bit % 8)); + id.setBit(bit, 1); return id; } +unsigned +Dht::RoutingTable::depth(const RoutingTable::const_iterator& it) const +{ + int bit1 = it->first.lowbit(); + int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1; + return std::max(bit1, bit2)+1; +} + Dht::RoutingTable::iterator Dht::RoutingTable::findBucket(const InfoHash& id) { @@ -609,11 +614,10 @@ Dht::newNode(const InfoHash& id, const sockaddr *sa, socklen_t salen, int confir } } - if (mybucket && (!dubious || list.size() == 1)) { - DHT_DEBUG("Splitting."); + if ((mybucket || (is_bootstrap and list.depth(b) < 6)) && (!dubious || list.size() == 1)) { + DHT_DEBUG("Splitting from depth %u", list.depth(b)); sendCachedPing(*b); list.split(b); - //dumpTables(); return newNode(id, sa, salen, confirm); } @@ -1967,8 +1971,9 @@ Dht::getSearchesLog(sa_family_t af) const return out.str(); } -Dht::Dht(int s, int s6, const InfoHash& id) - : dht_socket(s), dht_socket6(s6), myid(id), now(clock::now()), mybucket_grow_time(now), mybucket6_grow_time(now) +Dht::Dht(int s, int s6, const InfoHash& id, bool bootstrap) + : dht_socket(s), dht_socket6(s6), myid(id), is_bootstrap(bootstrap), + now(clock::now()), mybucket_grow_time(now), mybucket6_grow_time(now) { if (s < 0 && s6 < 0) return;