diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index cab40e43..16657b24 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2025, The PurpleI2P Project +* Copyright (c) 2013-2026, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -37,7 +37,7 @@ namespace data { NetDb netdb; - NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), + NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true), m_LastExploratorySelectionUpdateTime (0), m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL) { @@ -58,11 +58,11 @@ namespace data Load (); if (!m_Requests) - { + { m_Requests = std::make_shared(); m_Requests->Start (); } - + uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); if (m_RouterInfos.size () < threshold || m_Floodfills.GetSize () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils { @@ -84,7 +84,7 @@ namespace data m_Floodfills.Insert (i2p::context.GetSharedRouterInfo ()); i2p::config::GetOption("persist.profiles", m_PersistProfiles); - + m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); } @@ -118,7 +118,7 @@ namespace data i2p::util::SetThreadName("NetDB"); uint64_t lastManage = 0; - uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (), + uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (), lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplyingProfileUpdates = lastProfilesCleanup; int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0, applyingProfileUpdatesVariance = 0; @@ -150,7 +150,7 @@ namespace data } } if (!m_IsRunning) break; - if (!i2p::transport::transports.IsOnline () || !i2p::transport::transports.IsRunning ()) + if (!i2p::transport::transports.IsOnline () || !i2p::transport::transports.IsRunning ()) continue; // don't manage netdb when offline or transports are not running uint64_t mts = i2p::util::GetMonotonicMilliseconds (); @@ -168,18 +168,18 @@ namespace data { m_RouterProfilesPool.CleanUpMt (); if (m_PersistProfiles) - { + { bool isSaving = m_SavingProfiles.valid (); if (isSaving && m_SavingProfiles.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active? { m_SavingProfiles.get (); isSaving = false; - } + } if (!isSaving) m_SavingProfiles = PersistProfiles (); else LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk"); - } + } lastProfilesCleanup = mts; profilesCleanupVariance = m_Rng () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE; } @@ -191,14 +191,14 @@ namespace data { m_DeletingProfiles.get (); isDeleting = false; - } + } if (!isDeleting) - m_DeletingProfiles = DeleteObsoleteProfiles (); + m_DeletingProfiles = DeleteObsoleteProfiles (); else LogPrint (eLogWarning, "NetDb: Can't delete profiles. Profiles are being deleted from disk"); lastObsoleteProfilesCleanup = mts; obsoleteProfilesCleanVariance = m_Rng () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE; - } + } if (mts >= lastApplyingProfileUpdates + i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT + applyingProfileUpdatesVariance) { bool isApplying = m_ApplyingProfileUpdates.valid (); @@ -206,12 +206,12 @@ namespace data { m_ApplyingProfileUpdates.get (); isApplying = false; - } + } if (!isApplying) m_ApplyingProfileUpdates = i2p::data::FlushPostponedRouterProfileUpdates (); lastApplyingProfileUpdates = mts; applyingProfileUpdatesVariance = m_Rng () % i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE; - } + } } catch (std::exception& ex) { @@ -238,7 +238,7 @@ namespace data bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { bool updated; - if (!AddRouterInfo (ident, buf, len, updated)) + if (!AddRouterInfo (ident, buf, len, updated)) updated = false; return updated; } @@ -311,7 +311,7 @@ namespace data (mts < r->GetTimestamp () + NETDB_MAX_EXPIRATION_TIMEOUT*1000LL || // too old context.GetUptime () < NETDB_CHECK_FOR_EXPIRATION_UPTIME/10); // enough uptime } - if (isValid) + if (isValid) { bool inserted = false; { @@ -455,17 +455,17 @@ namespace data r->SetUnreachable (unreachable); auto profile = r->GetProfile (); if (profile) - { + { profile->Unreachable (unreachable); - if (!unreachable && r->IsDeclaredFloodfill () && !r->IsFloodfill () && + if (!unreachable && r->IsDeclaredFloodfill () && !r->IsFloodfill () && r->IsEligibleFloodfill () && profile->IsReal ()) { // enable previously disabled floodfill r->SetFloodfill (); std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Insert (r); - } - } + } + } } } @@ -631,11 +631,11 @@ namespace data if (m_PersistingRouters.wait_for(std::chrono::seconds(0)) == std::future_status::ready) m_PersistingRouters.get (); else - { + { LogPrint (eLogWarning, "NetDb: Can't save updated routers. Routers are being saved to disk"); return; - } - } + } + } int updatedCount = 0, deletedCount = 0, deletedFloodfillsCount = 0; auto total = m_RouterInfos.size (); @@ -652,10 +652,10 @@ namespace data expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; bool isOffline = checkForExpiration && i2p::transport::transports.GetNumPeers () < NETDB_MIN_TRANSPORTS; // enough routers and uptime, but no transports - + std::list > > saveToDisk; - std::list removeFromDisk; - + std::list removeFromDisk; + auto own = i2p::context.GetSharedRouterInfo (); for (auto [ident, r]: m_RouterInfos) { @@ -664,7 +664,7 @@ namespace data { std::lock_guard l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update r->DeleteBuffer (); - } + } if (r->IsUpdated ()) { if (r->GetBuffer () && !r->IsUnreachable ()) @@ -687,7 +687,7 @@ namespace data else if (r->GetBuffer () && ts > r->GetTimestamp () + NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // since update was long time ago we assume that router is not connected anymore r->ScheduleBufferToDelete (); - + if (r->HasProfile () && r->GetProfile ()->IsUnreachable ()) r->SetUnreachable (true); // make router reachable back if too few routers or floodfills @@ -704,22 +704,22 @@ namespace data LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (r->GetTimestamp () - ts)/1000LL, " seconds"); r->SetUnreachable (true); } - else if (checkForExpiration) - { + else if (checkForExpiration) + { if (ts > r->GetTimestamp () + expirationTimeout) r->SetUnreachable (true); else if ((ts > r->GetTimestamp () + expirationTimeout/2) && // more than half of expiration total > NETDB_NUM_ROUTERS_THRESHOLD && !r->IsHighBandwidth() && // low bandwidth - !r->IsFloodfill() && (!i2p::context.IsFloodfill () || // non floodfill - (CreateRoutingKey (ident) ^ i2p::context.GetIdentHash ()).metric[0] >= 0x02)) // different first 7 bits + !r->IsFloodfill() && (!i2p::context.IsFloodfill () || // non floodfill + (CreateRoutingKey (ident) ^ i2p::context.GetIdentHash ()).metric[0] >= 0x02)) // different first 7 bits r->SetUnreachable (true); - } + } } // make router reachable back if connected now or trusted router if (r->IsUnreachable () && (i2p::transport::transports.IsConnected (ident) || i2p::transport::transports.IsTrustedRouter (ident))) r->SetUnreachable (false); - + if (r->IsUnreachable ()) { if (r->IsFloodfill ()) deletedFloodfillsCount++; @@ -734,8 +734,8 @@ namespace data { m_PersistingRouters = std::async (std::launch::async, &NetDb::PersistRouters, this, std::move (saveToDisk), std::move (removeFromDisk)); - } - + } + m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt (); m_RouterInfoAddressVectorsPool.CleanUpMt (); @@ -771,18 +771,18 @@ namespace data } } - void NetDb::PersistRouters (std::list > >&& update, + void NetDb::PersistRouters (std::list > >&& update, std::list&& remove) { for (auto it: update) RouterInfo::SaveToFile (m_Storage.Path(it.first), it.second); for (auto it: remove) m_Storage.Remove (it); - } - + } + void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct) { - if (direct && (i2p::transport::transports.RoutesRestricted () || i2p::context.IsLimitedConnectivity ())) + if (direct && (i2p::transport::transports.RoutesRestricted () || i2p::context.IsLimitedConnectivity ())) direct = false; // always use tunnels for restricted routes or limited connectivity if (m_Requests) m_Requests->PostRequestDestination (destination, requestComplete, direct); @@ -842,11 +842,11 @@ namespace data auto r = FindRouter (replyIdent); if (r && !r->IsReachableFrom (i2p::context.GetRouterInfo ())) direct = false; - } + } if (direct) // send response directly to IBGW transports.SendMessage (replyIdent, i2p::CreateTunnelGatewayMsg (tunnelID, deliveryStatus)); else - { + { // send response through exploratory tunnel auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; @@ -854,7 +854,7 @@ namespace data outbound->SendTunnelDataMsgTo (replyIdent, tunnelID, deliveryStatus); else LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); - } + } } } offset += 32; @@ -941,7 +941,7 @@ namespace data LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len); } } - + void NetDb::HandleDatabaseLookupMsg (std::shared_ptr msg) { const uint8_t * buf = msg->GetPayload (); @@ -982,7 +982,7 @@ namespace data { LogPrint (eLogWarning, "NetDb: Exploratory lookup to non-floodfill dropped"); return; - } + } LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded"); std::unordered_set excludedRouters; const uint8_t * excluded_ident = excluded; @@ -991,7 +991,7 @@ namespace data excludedRouters.insert (excluded_ident); excluded_ident += 32; } - replyMsg = CreateDatabaseSearchReply (ident, GetExploratoryNonFloodfill (ident, + replyMsg = CreateDatabaseSearchReply (ident, GetExploratoryNonFloodfill (ident, NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES, excludedRouters)); } else @@ -1014,7 +1014,7 @@ namespace data { // try to find leaseset if (context.IsFloodfill ()) - { + { auto leaseSet = FindLeaseSet (ident); if (!leaseSet) { @@ -1026,12 +1026,12 @@ namespace data LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found"); replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); } - } + } else if (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP) { LogPrint (eLogWarning, "NetDb: Explicit LeaseSet lookup to non-floodfill dropped"); return; - } + } } if (!replyMsg) @@ -1085,18 +1085,18 @@ namespace data auto r = FindRouter (replyIdent); if (r && !r->IsReachableFrom (i2p::context.GetRouterInfo ())) direct = false; - } + } if (direct) transports.SendMessage (replyIdent, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg)); else - { + { auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; if (outbound) outbound->SendTunnelDataMsgTo (replyIdent, replyTunnelID, replyMsg); else LogPrint (eLogWarning, "NetDb: Can't send lookup reply to ", replyIdent.ToBase64 (), ". Non reachable and no outbound tunnels"); - } + } } else transports.SendMessage (replyIdent, replyMsg); @@ -1122,7 +1122,7 @@ namespace data } if (andNextDay) { - // flood to two more closest flodfills for next day + // flood to two more closest flodfills for next day std::unordered_set excluded1; excluded1.insert (i2p::context.GetIdentHash ()); // don't flood to itself excluded1.insert (ident); // don't flood back @@ -1138,8 +1138,8 @@ namespace data } else return; - } - } + } + } } std::shared_ptr NetDb::GetRandomRouter () const @@ -1163,6 +1163,7 @@ namespace data (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): router->IsReachableFrom (*compatibleWith)) && !router->IsNAT2NATOnly (*compatibleWith) && router->IsECIES () && !router->IsHighCongestion (clientTunnel) && + !router->IsSameSubnet (*compatibleWith) && (!checkIsReal || router->GetProfile ()->IsReal ()) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) }); @@ -1188,7 +1189,7 @@ namespace data }); } - std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const { bool checkIsReal = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD && // too low rate @@ -1202,6 +1203,7 @@ namespace data (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && router->IsECIES () && !router->IsHighCongestion (true) && + !router->IsSameSubnet (*compatibleWith) && (!checkIsReal || router->GetProfile ()->IsReal ()) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) @@ -1277,8 +1279,8 @@ namespace data { if (msg && m_Requests) m_Requests->PostDatabaseSearchReplyMsg (msg); - } - + } + std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, const std::unordered_set& excluded, bool nextDay) const { @@ -1326,7 +1328,7 @@ namespace data }); } - std::vector NetDb::GetExploratoryNonFloodfill (const IdentHash& destination, + std::vector NetDb::GetExploratoryNonFloodfill (const IdentHash& destination, size_t num, const std::unordered_set& excluded) { std::vector ret; @@ -1337,7 +1339,7 @@ namespace data // update selection m_ExploratorySelection.clear (); std::vector > eligible; - eligible.reserve (m_RouterInfos.size ()); + eligible.reserve (m_RouterInfos.size ()); { // collect eligible from current netdb bool checkIsReal = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < NETDB_TUNNEL_CREATION_RATE_THRESHOLD; // too low rate @@ -1351,24 +1353,24 @@ namespace data { std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection), NETDB_MAX_EXPLORATORY_SELECTION_SIZE, m_Rng); - } + } else - std::swap (m_ExploratorySelection, eligible); + std::swap (m_ExploratorySelection, eligible); m_LastExploratorySelectionUpdateTime = ts; - } - + } + // sort by distance IdentHash destKey = CreateRoutingKey (destination); std::map > sorted; for (const auto& it: m_ExploratorySelection) - if (!excluded.count (it->GetIdentHash ())) + if (!excluded.count (it->GetIdentHash ())) 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; } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 2c88aee8..d2a3fbca 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -971,15 +971,9 @@ namespace data template std::shared_ptr RouterInfo::GetAddress (Filter filter) const { - // TODO: make it more generic using comparator -#ifdef __cpp_lib_atomic_shared_ptr - AddressesPtr addresses = m_Addresses; -#else - auto addresses = boost::atomic_load (&m_Addresses); -#endif + auto addresses = GetAddresses (); for (const auto& address : *addresses) if (address && filter (address)) return address; - return nullptr; } @@ -1211,6 +1205,21 @@ namespace data } } + bool RouterInfo::IsSameSubnet (const RouterInfo& other) const + { + auto transports = m_SupportedTransports & other.m_SupportedTransports; + if (!transports) return false; + auto addresses1 = GetAddresses (), addresses2 = other.GetAddresses ();; + for (int i = 0; i < eNumTransports; i++) + if (i != eNTCP2V6MeshIdx && (transports & (1 << i))) + { + auto addr1 = (*addresses1)[i], addr2 = (*addresses2)[i]; + if (addr1 && addr2 && !addr1->host.is_unspecified () && !addr2->host.is_unspecified ()) + return addr1->IsSameSubnet (*addr2); // first adddess with IPs + } + return false; + } + void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) { RefreshTimestamp (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index f4687054..bb3300a8 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2025, The PurpleI2P Project +* Copyright (c) 2013-2026, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -52,12 +52,12 @@ namespace data // bandwidth limits in kBps const uint32_t LOW_BANDWIDTH_LIMIT = 48; const uint32_t HIGH_BANDWIDTH_LIMIT = 256; - const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048; + const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048; // congesion flags const char CAPS_FLAG_MEDIUM_CONGESTION = 'D'; const char CAPS_FLAG_HIGH_CONGESTION = 'E'; const char CAPS_FLAG_REJECT_ALL_CONGESTION = 'G'; - + const char CAPS_FLAG_V4 = '4'; const char CAPS_FLAG_V6 = '6'; const char CAPS_FLAG_SSU2_TESTING = 'B'; @@ -71,7 +71,7 @@ namespace data const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later const int HIGH_CONGESTION_INTERVAL = 15*60; // in seconds, 15 minutes const int INTRODUCER_UPDATE_INTERVAL = 20*60*1000; // in milliseconds, 20 minutes - + class RouterInfo: public RoutingDestination { public: @@ -116,7 +116,7 @@ namespace data eHighCongestion, eRejectAll }; - + enum AddressCaps { eV4 = 0x01, @@ -186,6 +186,14 @@ namespace data bool IsV4 () const { return (caps & AddressCaps::eV4) || (host.is_v4 () && !host.is_unspecified ()); }; bool IsV6 () const { return (caps & AddressCaps::eV6) || (host.is_v6 () && !host.is_unspecified ()); }; + + bool IsSameSubnet (const Address& other) + { + if (host.is_unspecified () || other.host.is_unspecified ()) return false; + if (host.is_v4 () && other.host.is_v4 ()) return !std::memcmp (host.to_v4 ().to_bytes ().data (), other.host.to_v4 ().to_bytes ().data (), 3); // /24 + if (host.is_v6 () && other.host.is_v6 ()) return !std::memcmp (host.to_v6 ().to_bytes ().data (), other.host.to_v6 ().to_bytes ().data (), 7); // /56 + return false; + } }; class Buffer: public std::array @@ -198,7 +206,7 @@ namespace data size_t GetBufferLen () const { return m_BufferLen; }; void SetBufferLen (size_t len) { m_BufferLen = len; }; - + private: size_t m_BufferLen = 0; @@ -209,7 +217,7 @@ namespace data typedef std::shared_ptr AddressesPtr; #else typedef boost::shared_ptr AddressesPtr; -#endif +#endif RouterInfo (const std::string& fullPath); RouterInfo (const RouterInfo& ) = delete; RouterInfo& operator=(const RouterInfo& ) = delete; @@ -263,10 +271,11 @@ namespace data void EnableMesh (); void DisableMesh (); bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; + bool IsSameSubnet (const RouterInfo& other) const; bool IsReachableFrom (const RouterInfo& other) const { return m_ReachableTransports & other.m_SupportedTransports; }; bool IsReachableBy (CompatibleTransports transports) const { return m_ReachableTransports & transports; }; CompatibleTransports GetCompatibleTransports (bool incoming) const { return incoming ? m_ReachableTransports : m_SupportedTransports; }; - CompatibleTransports GetPublishedTransports () const { return m_PublishedTransports; }; + CompatibleTransports GetPublishedTransports () const { return m_PublishedTransports; }; bool HasValidAddresses () const { return m_SupportedTransports; }; bool IsHidden () const { return m_Caps & eHidden; }; bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; @@ -285,7 +294,7 @@ namespace data void SetCaps (uint8_t caps) { m_Caps = caps; }; Congestion GetCongestion () const { return m_Congestion; }; - + void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; void ExcludeReachableTransports (CompatibleTransports transports) { m_ReachableTransports &= ~transports; }; @@ -294,7 +303,7 @@ namespace data const uint8_t * LoadBuffer (const std::string& fullPath); // load if necessary size_t GetBufferLen () const { return m_Buffer ? m_Buffer->GetBufferLen () : 0; }; void DeleteBuffer () { m_Buffer = nullptr; m_IsBufferScheduledToDelete = false; }; - std::shared_ptr GetSharedBuffer () const { return m_Buffer; }; + std::shared_ptr GetSharedBuffer () const { return m_Buffer; }; std::shared_ptr CopyBuffer () const; void ScheduleBufferToDelete () { m_IsBufferScheduledToDelete = true; }; void CancelBufferToDelete () { m_IsBufferScheduledToDelete = false; }; @@ -304,10 +313,10 @@ namespace data void SetUpdated (bool updated) { m_IsUpdated = updated; }; bool SaveToFile (const std::string& fullPath); static bool SaveToFile (const std::string& fullPath, std::shared_ptr buf); - + std::shared_ptr GetProfile () const; void DropProfile () { m_Profile = nullptr; }; - bool HasProfile () const { return (bool)m_Profile; }; + bool HasProfile () const { return (bool)m_Profile; }; bool Update (const uint8_t * buf, size_t len); bool IsNewer (const uint8_t * buf, size_t len) const; @@ -331,7 +340,7 @@ namespace data CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; }; void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; }; void SetCongestion (Congestion c) { m_Congestion = c; }; - + private: bool LoadFile (const std::string& fullPath); @@ -342,7 +351,7 @@ namespace data std::tuple ExtractParam (const uint8_t * buf, size_t len) const; void ExtractCaps (std::string_view value); uint8_t ExtractAddressCaps (std::string_view value) const; - void UpdateIntroducers (std::shared_ptr
address, uint64_t ts); + void UpdateIntroducers (std::shared_ptr
address, uint64_t ts); template std::shared_ptr GetAddress (Filter filter) const; virtual std::shared_ptr NewBuffer () const; @@ -358,9 +367,9 @@ namespace data uint64_t m_Timestamp; // in milliseconds #ifdef __cpp_lib_atomic_shared_ptr std::atomic m_Addresses; -#else +#else AddressesPtr m_Addresses; -#endif +#endif bool m_IsUpdated, m_IsUnreachable, m_IsFloodfill, m_IsBufferScheduledToDelete; CompatibleTransports m_SupportedTransports, m_ReachableTransports, m_PublishedTransports; uint8_t m_Caps; @@ -388,7 +397,7 @@ namespace data std::string GetProperty (const std::string& key) const; void ClearProperties () override { m_Properties.clear (); }; void UpdateFloodfillProperty (bool floodfill); - + bool AddSSU2Introducer (const Introducer& introducer, bool v4); bool RemoveSSU2Introducer (const IdentHash& h, bool v4); bool UpdateSSU2Introducer (const IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp);