From ec59308fad2eb06e0cb49fc5f56003b4410907e5 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 2 May 2024 19:16:48 -0400 Subject: [PATCH] return up to 16 hash in expolatory reply --- libi2pd/NetDb.cpp | 74 ++++++++++++++++++++++++++--------------------- libi2pd/NetDb.hpp | 3 +- 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index a86f2f94..9fc561dc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -992,7 +994,7 @@ namespace data char key[48]; int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48); key[l] = 0; - int num = buf[32]; // num + size_t num = buf[32]; // num LogPrint (eLogDebug, "NetDb: DatabaseSearchReply for ", key, " num=", num); IdentHash ident (buf); auto dest = m_Requests.FindRequest (ident); @@ -1012,7 +1014,12 @@ namespace data } // try responses - for (int i = 0; i < num; i++) + if (num > NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES) + { + LogPrint (eLogWarning, "NetDb: Too many peer hashes ", num, " in database search reply, Reduced to ", NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES); + num = NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES; + } + for (size_t i = 0; i < num; i++) { const uint8_t * router = buf + 33 + i*32; char peerHash[48]; @@ -1087,17 +1094,8 @@ namespace data excludedRouters.insert (excluded_ident); excluded_ident += 32; } - std::vector routers; - for (int i = 0; i < 3; i++) - { - auto r = GetClosestNonFloodfill (ident, excludedRouters); - if (r) - { - routers.push_back (r->GetIdentHash ()); - excludedRouters.insert (r->GetIdentHash ()); - } - } - replyMsg = CreateDatabaseSearchReply (ident, routers); + replyMsg = CreateDatabaseSearchReply (ident, GetClosestNonFloodfill (ident, + NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES, excludedRouters)); } else { @@ -1453,29 +1451,39 @@ namespace data }); } - std::shared_ptr NetDb::GetClosestNonFloodfill (const IdentHash& destination, - const std::set& excluded) const + std::vector NetDb::GetClosestNonFloodfill (const IdentHash& destination, + size_t num, const std::set& excluded) const { - std::shared_ptr r; - XORMetric minMetric; - IdentHash destKey = CreateRoutingKey (destination); - minMetric.SetMax (); - // must be called from NetDb thread only - bool checkIsReal = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD; // too low rate - std::lock_guard l(m_RouterInfosMutex); - for (const auto& it: m_RouterInfos) + std::vector ret; + if (!num) return ret; // empty list + // collect eligible + std::vector > eligible; + eligible.reserve (NETDB_NUM_ROUTERS_THRESHOLD); { - if (!it.second->IsDeclaredFloodfill () && (!checkIsReal || (it.second->HasProfile () && it.second->GetProfile ()->IsReal ()))) - { - XORMetric m = destKey ^ it.first; - if (m < minMetric && !excluded.count (it.first)) - { - minMetric = m; - r = it.second; - } - } + bool checkIsReal = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD; // too low rate + std::lock_guard l(m_RouterInfosMutex); + for (const auto& it: m_RouterInfos) + if (!it.second->IsDeclaredFloodfill () && (!checkIsReal || (it.second->HasProfile () && it.second->GetProfile ()->IsReal ()))) + eligible.push_back (it.second); } - return r; + // reduce number of eligible routers if too many + if (eligible.size () > NETDB_NUM_ROUTERS_THRESHOLD) + { + std::shuffle (eligible.begin(), eligible.end(), std::mt19937(std::random_device()())); + eligible.resize (NETDB_NUM_ROUTERS_THRESHOLD); + } + // sort by distance + IdentHash destKey = CreateRoutingKey (destination); + std::map > sorted; + for (const auto& it: eligible) + sorted.emplace (destKey ^ it->GetIdentHash (), it); + // return first num closest routers + for (const auto& it: sorted) + { + ret.push_back (it.second->GetIdentHash ()); + if (ret.size () >= num) break; + } + return ret; } void NetDb::ManageRouterInfos () diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 40447335..d3c7b451 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -53,6 +53,7 @@ namespace data const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 + const size_t NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES = 16; /** function for visiting a leaseset stored in a floodfill */ typedef std::function)> LeaseSetVisitor; @@ -97,7 +98,7 @@ namespace data std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly = false) const; - std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; + std::vector GetClosestNonFloodfill (const IdentHash& destination, size_t num, const std::set& excluded) const; std::shared_ptr GetRandomRouterInFamily (FamilyID fam) const; void SetUnreachable (const IdentHash& ident, bool unreachable); void ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports);