diff --git a/include/opendht/callbacks.h b/include/opendht/callbacks.h index 3a4007257a76908f2a6c1064420945f583b68f2f..12d9f02392f3323d842bcb80d270cfbb73d993ca 100644 --- a/include/opendht/callbacks.h +++ b/include/opendht/callbacks.h @@ -39,6 +39,16 @@ enum class NodeStatus { Connected // 1+ good nodes }; +struct OPENDHT_PUBLIC NodeStats { + unsigned good_nodes, + dubious_nodes, + cached_nodes, + incoming_nodes; + unsigned table_depth; + unsigned getKnownNodes() const { return good_nodes + dubious_nodes; } + std::string toString() const; +}; + /** * Dht configuration. */ diff --git a/include/opendht/dht.h b/include/opendht/dht.h index 82e7136daa69ebccc33cb521ebf3e22089cc242c..00ec6b8340519039e582eaa9a5959de87331997d 100644 --- a/include/opendht/dht.h +++ b/include/opendht/dht.h @@ -270,8 +270,8 @@ public: std::vector<ValuesExport> exportValues() const; void importValues(const std::vector<ValuesExport>&); - unsigned getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, - unsigned *incoming_return) const; + NodeStats getNodesStats(sa_family_t af) const; + std::string getStorageLog() const; std::string getStorageLog(const InfoHash&) const; diff --git a/include/opendht/dhtrunner.h b/include/opendht/dhtrunner.h index 1a7eecfe2d9b6a02e95ffde6b8a15a1d73fc941d..86042c4058d390c98a642969adb9bcf522654ed6 100644 --- a/include/opendht/dhtrunner.h +++ b/include/opendht/dhtrunner.h @@ -276,7 +276,8 @@ public: return running; } - int getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const; + NodeStats getNodesStats(sa_family_t af) const; + unsigned getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const; std::vector<unsigned> getNodeMessageStats(bool in = false) const; std::string getStorageLog() const; diff --git a/src/callbacks.cpp b/src/callbacks.cpp index bcdaf6fb7d1577c8602797aa59d7ddd9cf532c06..8908a2dff2405223e1c2715e6c2b2b1262cbbfaf 100644 --- a/src/callbacks.cpp +++ b/src/callbacks.cpp @@ -55,4 +55,17 @@ bindDoneCbSimple(DoneCallbackSimpleRaw raw_cb, void* user_data) { }; } -} \ No newline at end of file +std::string +NodeStats::toString() const +{ + std::stringstream ss; + ss << "Known nodes: " << good_nodes << " good, " << dubious_nodes << " dubious, " << incoming_nodes << " incoming." << std::endl; + if (table_depth > 1) { + ss << "Routing table depth: " << table_depth << std::endl; + unsigned long tot_nodes = 8 * std::exp2(table_depth); + ss << "Network size estimation: " << tot_nodes << " nodes" << std::endl; + } + return ss.str(); +} + +} diff --git a/src/dht.cpp b/src/dht.cpp index 72a29ffd3233a7340b0c27c28832033397b4c759..d357c115508eb0cca888b774c8d1de698a96fc64 100644 --- a/src/dht.cpp +++ b/src/dht.cpp @@ -728,12 +728,11 @@ Dht::setLoggers(LogMethod error, LogMethod warn, LogMethod debug) NodeStatus Dht::getStatus(sa_family_t af) const { - unsigned good = 0, dubious = 0, cached = 0, incoming = 0; - unsigned tot = getNodesStats(af, &good, &dubious, &cached, &incoming); + const auto& stats = getNodesStats(af); auto& ping = af == AF_INET ? pending_pings4 : pending_pings6; - if (good) + if (stats.good_nodes) return NodeStatus::Connected; - if (ping or tot) + if (ping or stats.getKnownNodes()) return NodeStatus::Connecting; return NodeStatus::Disconnected; } @@ -2479,32 +2478,26 @@ Dht::tokenMatch(const Blob& token, const sockaddr *sa) const return false; } -unsigned -Dht::getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const +NodeStats +Dht::getNodesStats(sa_family_t af) const { + NodeStats stats {}; const auto& now = scheduler.time(); - unsigned good = 0, dubious = 0, cached = 0, incoming = 0; - for (const auto& b : buckets(af)) { + const auto& bcks = buckets(af); + for (const auto& b : bcks) { for (auto& n : b.nodes) { if (n->isGood(now)) { - good++; + stats.good_nodes++; if (n->time > n->reply_time) - incoming++; + stats.incoming_nodes++; } else if (not n->isExpired()) - dubious++; + stats.dubious_nodes++; } if (b.cached) - cached++; - } - if (good_return) - *good_return = good; - if (dubious_return) - *dubious_return = dubious; - if (cached_return) - *cached_return = cached; - if (incoming_return) - *incoming_return = incoming; - return good + dubious; + stats.cached_nodes++; + } + stats.table_depth = bcks.depth(bcks.findBucket(myid)); + return stats; } void diff --git a/src/dhtrunner.cpp b/src/dhtrunner.cpp index bd8a5b23a3c616c6164370cfaf5dc6797a1dac33..21f670a2c5525fb944cabfb97fc510fcbbea5013 100644 --- a/src/dhtrunner.cpp +++ b/src/dhtrunner.cpp @@ -233,11 +233,27 @@ DhtRunner::importValues(const std::vector<ValuesExport>& values) { dht_->importValues(values); } -int +unsigned DhtRunner::getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const { std::lock_guard<std::mutex> lck(dht_mtx); - return dht_->getNodesStats(af, good_return, dubious_return, cached_return, incoming_return); + const auto stats = dht_->getNodesStats(af); + if (good_return) + *good_return = stats.good_nodes; + if (dubious_return) + *dubious_return = stats.dubious_nodes; + if (cached_return) + *cached_return = stats.cached_nodes; + if (incoming_return) + *incoming_return = stats.incoming_nodes; + return stats.good_nodes + stats.dubious_nodes; +} + +NodeStats +DhtRunner::getNodesStats(sa_family_t af) const +{ + std::lock_guard<std::mutex> lck(dht_mtx); + return dht_->getNodesStats(af); } std::vector<unsigned> diff --git a/src/network_engine.cpp b/src/network_engine.cpp index ba157a168183db8561ae22dc7fe4216de4ca732a..761b32898df719e6bd539dc93d4fc9c4750e306e 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -594,7 +594,7 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro } void -packToken(msgpack::packer<msgpack::sbuffer>& pk, Blob token) +packToken(msgpack::packer<msgpack::sbuffer>& pk, const Blob& token) { pk.pack_bin(token.size()); pk.pack_bin_body((char*)token.data(), token.size()); diff --git a/src/routing_table.cpp b/src/routing_table.cpp index 576b3d14cfe4aa9df11190455ac169e1d593ffee..54b08897cdbe326c80d9c70fc35f6a529807a7b2 100644 --- a/src/routing_table.cpp +++ b/src/routing_table.cpp @@ -70,6 +70,8 @@ RoutingTable::middle(const RoutingTable::const_iterator& it) const unsigned RoutingTable::depth(const RoutingTable::const_iterator& it) const { + if (it == end()) + return 0; int bit1 = it->first.lowbit(); int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1; return std::max(bit1, bit2)+1; diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp index 4d61b12656527c573d57f0e509a8395a96229008..24955c0406625b92d4c8742d5575cbaf8e953b09 100644 --- a/tools/dhtnode.cpp +++ b/tools/dhtnode.cpp @@ -101,12 +101,10 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params) continue; } else if (op == "ll") { print_node_info(dht, params); - unsigned good4, dubious4, cached4, incoming4; - unsigned good6, dubious6, cached6, incoming6; - dht->getNodesStats(AF_INET, &good4, &dubious4, &cached4, &incoming4); - dht->getNodesStats(AF_INET6, &good6, &dubious6, &cached6, &incoming6); - std::cout << "IPv4 nodes : " << good4 << " good, " << dubious4 << " dubious, " << incoming4 << " incoming." << std::endl; - std::cout << "IPv6 nodes : " << good6 << " good, " << dubious6 << " dubious, " << incoming6 << " incoming." << std::endl; + std::cout << "IPv4 stats:" << std::endl; + std::cout << dht->getNodesStats(AF_INET).toString() << std::endl; + std::cout << "IPv6 stats:" << std::endl; + std::cout << dht->getNodesStats(AF_INET6).toString() << std::endl; continue; } else if (op == "lr") { std::cout << "IPv4 routing table:" << std::endl;