diff --git a/include/opendht/network_engine.h b/include/opendht/network_engine.h index 04afdecf..7398fac6 100644 --- a/include/opendht/network_engine.h +++ b/include/opendht/network_engine.h @@ -362,10 +362,14 @@ public: void blacklistNode(const std::shared_ptr& n); + std::vector> getCachedNodes(const InfoHash& id, sa_family_t sa_f); + private: /*************** * Constants * ***************/ + /* Total number of node needed from cache */ + static constexpr unsigned MAX_CACHE_NODE {14}; static constexpr long unsigned MAX_REQUESTS_PER_SEC {1600}; /* the length of a node info buffer in ipv4 format */ static const constexpr size_t NODE4_INFO_BUF_LEN {26}; @@ -379,6 +383,7 @@ private: /* TODO */ static const std::string my_v; + /* DHT info */ const InfoHash& myid; const NetId network {0}; diff --git a/include/opendht/node_cache.h b/include/opendht/node_cache.h index cbddd0be..4d63fd09 100644 --- a/include/opendht/node_cache.h +++ b/include/opendht/node_cache.h @@ -29,6 +29,7 @@ namespace dht { struct NodeCache { std::shared_ptr getNode(const InfoHash& id, sa_family_t family); std::shared_ptr getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, bool confirmed); + std::vector> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t total); /** * Reset the connectivity state of every node, diff --git a/src/dht.cpp b/src/dht.cpp index 9fbd422f..ab3e8720 100644 --- a/src/dht.cpp +++ b/src/dht.cpp @@ -1238,24 +1238,14 @@ void Dht::bootstrapSearch(Dht::Search& sr) { const auto& now = scheduler.time(); - auto& list = (sr.af == AF_INET) ? buckets : buckets6; - if (list.empty() || (list.size() == 1 && list.front().nodes.empty())) - return; - auto b = list.findBucket(sr.id); - if (b == list.end()) { - DHT_LOG.ERR("No bucket"); + const auto& list = network_engine.getCachedNodes(sr.id, sr.af); + if ( list.empty() ) { + DHT_LOG.ERR("No node found from cache"); return; } - sr.insertBucket(*b, now); - if (sr.nodes.size() < SEARCH_NODES) { - if (std::next(b) != list.end()) - sr.insertBucket(*std::next(b), now); - if (b != list.begin()) - sr.insertBucket(*std::prev(b), now); - } - if (sr.nodes.size() < SEARCH_NODES) - sr.insertBucket(*list.findBucket(myid), now); + for ( auto& i : list) + sr.insertNode(i, now); sr.refill_time = now; } diff --git a/src/network_engine.cpp b/src/network_engine.cpp index 75d05b06..ef3366c4 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -275,6 +275,11 @@ NetworkEngine::isNodeBlacklisted(const sockaddr *sa, socklen_t salen) const return false; } +std::vector> +NetworkEngine::getCachedNodes(const InfoHash& id, sa_family_t sa_f) { + return cache.getCachedNodes(id, sa_f, MAX_CACHE_NODE); +} + void NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) { diff --git a/src/node_cache.cpp b/src/node_cache.cpp index 31ee1d64..386b44ad 100644 --- a/src/node_cache.cpp +++ b/src/node_cache.cpp @@ -33,6 +33,40 @@ NodeCache::getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, tim return (sa->sa_family == AF_INET ? cache_4 : cache_6).getNode(id, sa, sa_len, now, confirm); } +std::vector> +NodeCache::getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t total) { + auto c = (sa_f == AF_INET ? cache_4 : cache_6); + auto it_p = c.lower_bound(id), + it_n = it_p; + + std::vector> nodes; + nodes.reserve(std::min(c.size(), total)); + decltype(c)::iterator it; + + if (it_p != c.begin()) /* Create 2 separate iterator if we could */ + --it_p; + + while ( nodes.size() != total + or (it_n == c.end() and it_p == c.end()) ) { + + /* If one of the iterator is at the end, then take the other one + If they are both in middle of somewhere comapre both and take + the closest to the id. */ + if (it_p == c.end()) it = it_n++; + else if (it_n == c.end()) it = it_p--; + else it = id.xorCmp(it_p->first, it_n->first) < 0 ? it_p-- : it_n++; + + if (it == c.begin()) + it_p = c.end(); + + if (auto n = it->second.lock()) + if ( not n->isExpired() ) + nodes.emplace_back(std::move(n)); + } + + return nodes; +} + void NodeCache::clearBadNodes(sa_family_t family) {