diff --git a/include/opendht/network_engine.h b/include/opendht/network_engine.h index 547e641a..3a5ab8fe 100644 --- a/include/opendht/network_engine.h +++ b/include/opendht/network_engine.h @@ -275,7 +275,8 @@ public: * @return the request with information concerning its success. */ Sp - sendPing(Sp n, RequestCb&& on_done, RequestExpiredCb&& on_expired); + sendPing(Sp n, RequestCb&& on_done, RequestExpiredCb&& on_expired); + /** * Send a "ping" request to a given node. * @@ -287,11 +288,12 @@ public: * @return the request with information concerning its success. */ Sp - sendPing(SockAddr&& sa, RequestCb&& on_done, RequestExpiredCb&& on_expired) { - return sendPing(std::make_shared(zeroes, std::move(sa)), - std::forward(on_done), - std::forward(on_expired)); - } + sendPing(SockAddr&& sa, RequestCb&& on_done, RequestExpiredCb&& on_expired) { + return sendPing(std::make_shared(zeroes, std::move(sa), rd), + std::forward(on_done), + std::forward(on_expired)); + } + /** * Send a "find node" request to a given node. * @@ -529,7 +531,7 @@ private: Sp logger_; std::mt19937_64& rd; - NodeCache cache {}; + NodeCache cache; // global limiting should be triggered by at least 8 different IPs using IpLimiter = RateLimiter; diff --git a/include/opendht/node.h b/include/opendht/node.h index 97946919..47c443b3 100644 --- a/include/opendht/node.h +++ b/include/opendht/node.h @@ -47,10 +47,10 @@ struct Socket { struct Node { const InfoHash id; - Node(const InfoHash& id, const SockAddr& addr, bool client=false); - Node(const InfoHash& id, SockAddr&& addr, bool client=false); - Node(const InfoHash& id, const sockaddr* sa, socklen_t salen) - : Node(id, SockAddr(sa, salen)) {} + Node(const InfoHash& id, const SockAddr& addr, std::mt19937_64& rd, bool client=false); + Node(const InfoHash& id, SockAddr&& addr, std::mt19937_64& rd, bool client=false); + Node(const InfoHash& id, const sockaddr* sa, socklen_t salen, std::mt19937_64& rd) + : Node(id, SockAddr(sa, salen), rd) {} InfoHash getId() const { return id; diff --git a/include/opendht/node_cache.h b/include/opendht/node_cache.h index e3e4226b..c85d9ad6 100644 --- a/include/opendht/node_cache.h +++ b/include/opendht/node_cache.h @@ -37,13 +37,14 @@ struct NodeCache { */ void clearBadNodes(sa_family_t family = 0); + NodeCache(std::mt19937_64& r) : rd(r) {}; ~NodeCache(); private: class NodeMap : private std::map> { public: Sp getNode(const InfoHash& id); - Sp getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client); + Sp getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client, std::mt19937_64& rd); std::vector> getCachedNodes(const InfoHash& id, size_t count) const; void clearBadNodes(); void setExpired(); @@ -56,6 +57,7 @@ private: NodeMap& cache(sa_family_t af) { return af == AF_INET ? cache_4 : cache_6; } NodeMap cache_4; NodeMap cache_6; + std::mt19937_64& rd; }; } diff --git a/include/opendht/routing_table.h b/include/opendht/routing_table.h index 3aa61b3e..234488d5 100644 --- a/include/opendht/routing_table.h +++ b/include/opendht/routing_table.h @@ -39,7 +39,7 @@ struct Bucket { Sp cached; /* the address of a likely candidate */ /** Return a random node in a bucket. */ - Sp randomNode(); + Sp randomNode(std::mt19937_64& rd); void sendCachedPing(net::NetworkEngine& ne); void connectivityChanged() { @@ -89,7 +89,7 @@ public: /** * Return a random id in the bucket's range. */ - InfoHash randomId(const RoutingTable::const_iterator& bucket) const; + InfoHash randomId(const RoutingTable::const_iterator& bucket, std::mt19937_64& rd) const; unsigned depth(const RoutingTable::const_iterator& bucket) const; diff --git a/src/dht.cpp b/src/dht.cpp index 535d05d2..315742c4 100644 --- a/src/dht.cpp +++ b/src/dht.cpp @@ -1409,10 +1409,7 @@ void Dht::rotateSecrets() { oldsecret = secret; - { - crypto::random_device rdev; - secret = std::uniform_int_distribution{}(rdev); - } + secret = std::uniform_int_distribution{}(rd); uniform_duration_distribution<> time_dist(std::chrono::minutes(15), std::chrono::minutes(45)); auto rotate_secrets_time = scheduler.time() + time_dist(rd); scheduler.add(rotate_secrets_time, std::bind(&Dht::rotateSecrets, this)); @@ -1781,10 +1778,7 @@ Dht::Dht(std::unique_ptr&& sock, const Config& config, cons nextNodesConfirmation = scheduler.add(scheduler.time() + time_dis(rd), std::bind(&Dht::confirmNodes, this)); // Fill old secret - { - crypto::random_device rdev; - secret = std::uniform_int_distribution{}(rdev); - } + secret = std::uniform_int_distribution{}(rd); rotateSecrets(); expire(); @@ -1822,7 +1816,7 @@ Dht::neighbourhoodMaintenance(RoutingTable& list) q = r; } - auto n = q->randomNode(); + auto n = q->randomNode(rd); if (n) { if (logger_) logger_->d(id, n->id, "[node %s] sending [find %s] for neighborhood maintenance", @@ -1847,7 +1841,7 @@ Dht::bucketMaintenance(RoutingTable& list) /* This bucket hasn't seen any positive confirmation for a long time. Pick a random id in this bucket's range, and send a request to a random node. */ - InfoHash id = list.randomId(b); + InfoHash id = list.randomId(b, rd); auto q = b; /* If the bucket is empty, we try to fill it from a neighbour. We also sometimes do it gratuitiously to recover from @@ -1860,7 +1854,7 @@ Dht::bucketMaintenance(RoutingTable& list) q = r; } - auto n = q->randomNode(); + auto n = q->randomNode(rd); if (n and not n->isPendingMessage()) { want_t want = -1; diff --git a/src/network_engine.cpp b/src/network_engine.cpp index d6a3129e..6f02742c 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -100,7 +100,7 @@ RequestAnswer::RequestAnswer(ParsedMessage&& msg) {} NetworkEngine::NetworkEngine(const Sp& log, std::mt19937_64& rand, Scheduler& scheduler, std::unique_ptr&& sock) - : myid(zeroes), dht_socket(std::move(sock)), logger_(log), rd(rand), rate_limiter((size_t)-1), scheduler(scheduler) + : myid(zeroes), dht_socket(std::move(sock)), logger_(log), rd(rand), cache(rd), rate_limiter((size_t)-1), scheduler(scheduler) {} NetworkEngine::NetworkEngine(InfoHash& myid, NetworkConfig c, @@ -127,6 +127,7 @@ NetworkEngine::NetworkEngine(InfoHash& myid, NetworkConfig c, onAnnounce(std::move(onAnnounce)), onRefresh(std::move(onRefresh)), myid(myid), config(c), dht_socket(std::move(sock)), logger_(log), rd(rand), + cache(rd), rate_limiter(config.max_req_per_sec), scheduler(scheduler) {} diff --git a/src/node.cpp b/src/node.cpp index e45bfc89..41829e6c 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -30,17 +30,15 @@ constexpr std::chrono::minutes Node::NODE_EXPIRE_TIME; constexpr std::chrono::minutes Node::NODE_GOOD_TIME; constexpr std::chrono::seconds Node::MAX_RESPONSE_TIME; -Node::Node(const InfoHash& id, const SockAddr& addr, bool client) +Node::Node(const InfoHash& id, const SockAddr& addr, std::mt19937_64& rd, bool client) : id(id), addr(addr), is_client(client), sockets_() { - thread_local crypto::random_device rd {}; transaction_id = std::uniform_int_distribution{1}(rd); } -Node::Node(const InfoHash& id, SockAddr&& addr, bool client) +Node::Node(const InfoHash& id, SockAddr&& addr, std::mt19937_64& rd, bool client) : id(id), addr(std::move(addr)), is_client(client), sockets_() { - thread_local crypto::random_device rd {}; transaction_id = std::uniform_int_distribution{1}(rd); } diff --git a/src/node_cache.cpp b/src/node_cache.cpp index 56685238..dc25b386 100644 --- a/src/node_cache.cpp +++ b/src/node_cache.cpp @@ -37,8 +37,8 @@ NodeCache::getNode(const InfoHash& id, sa_family_t family) { Sp NodeCache::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) { if (not id) - return std::make_shared(id, addr); - return cache(addr.getFamily()).getNode(id, addr, now, confirm, client); + return std::make_shared(id, addr, rd, client); + return cache(addr.getFamily()).getNode(id, addr, now, confirm, client, rd); } std::vector> @@ -104,13 +104,13 @@ NodeCache::NodeMap::getNode(const InfoHash& id) } Sp -NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) +NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client, std::mt19937_64& rd) { - auto it = emplace(id, std::weak_ptr{}); - auto node = it.first->second.lock(); + auto& nref = (*this)[id]; + auto node = nref.lock(); if (not node) { - node = std::make_shared(id, addr, client); - it.first->second = node; + node = std::make_shared(id, addr, rd, client); + nref = node; if (cleanup_counter++ == CLEANUP_FREQ) { cleanup(); cleanup_counter = 0; diff --git a/src/routing_table.cpp b/src/routing_table.cpp index 13b33145..e8b9ea6d 100644 --- a/src/routing_table.cpp +++ b/src/routing_table.cpp @@ -25,15 +25,8 @@ namespace dht { -static std::mt19937 rd{ dht::crypto::random_device{}() }; -#ifdef _WIN32 -static std::uniform_int_distribution rand_byte{ 0, std::numeric_limits::max() }; -#else -static std::uniform_int_distribution rand_byte; -#endif - Sp -Bucket::randomNode() +Bucket::randomNode(std::mt19937_64& rd) { if (nodes.empty()) return nullptr; @@ -65,7 +58,7 @@ void Bucket::sendCachedPing(net::NetworkEngine& ne) } InfoHash -RoutingTable::randomId(const RoutingTable::const_iterator& it) const +RoutingTable::randomId(const RoutingTable::const_iterator& it, std::mt19937_64& rd) const { int bit1 = it->first.lowbit(); int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1; @@ -74,6 +67,12 @@ RoutingTable::randomId(const RoutingTable::const_iterator& it) const if (bit >= 8*(int)HASH_LEN) return it->first; +#ifdef _WIN32 + std::uniform_int_distribution rand_byte{ 0, std::numeric_limits::max() }; +#else + std::uniform_int_distribution rand_byte; +#endif + int b = bit/8; InfoHash id_return; std::copy_n(it->first.cbegin(), b, id_return.begin());