exclude routers from the same subnet from next hop

This commit is contained in:
orignal
2026-01-22 20:35:00 -05:00
parent a7378a38b2
commit fef25d7579
3 changed files with 111 additions and 91 deletions

View File

@@ -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<NetDbRequests>();
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<std::mutex> 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<std::pair<std::string, std::shared_ptr<RouterInfo::Buffer> > > saveToDisk;
std::list<std::string> removeFromDisk;
std::list<std::string> removeFromDisk;
auto own = i2p::context.GetSharedRouterInfo ();
for (auto [ident, r]: m_RouterInfos)
{
@@ -664,7 +664,7 @@ namespace data
{
std::lock_guard<std::mutex> 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<std::pair<std::string, std::shared_ptr<RouterInfo::Buffer> > >&& update,
void NetDb::PersistRouters (std::list<std::pair<std::string, std::shared_ptr<RouterInfo::Buffer> > >&& update,
std::list<std::string>&& 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<const I2NPMessage> 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<IdentHash> 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<IdentHash> 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<const RouterInfo> 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<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith,
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> 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<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
const std::unordered_set<IdentHash>& excluded, bool nextDay) const
{
@@ -1326,7 +1328,7 @@ namespace data
});
}
std::vector<IdentHash> NetDb::GetExploratoryNonFloodfill (const IdentHash& destination,
std::vector<IdentHash> NetDb::GetExploratoryNonFloodfill (const IdentHash& destination,
size_t num, const std::unordered_set<IdentHash>& excluded)
{
std::vector<IdentHash> ret;
@@ -1337,7 +1339,7 @@ namespace data
// update selection
m_ExploratorySelection.clear ();
std::vector<std::shared_ptr<const RouterInfo> > 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<XORMetric, std::shared_ptr<const RouterInfo> > 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;
}

View File

@@ -971,15 +971,9 @@ namespace data
template<typename Filter>
std::shared_ptr<const RouterInfo::Address> 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 ();

View File

@@ -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<uint8_t, MAX_RI_BUFFER_SIZE>
@@ -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<Addresses> AddressesPtr;
#else
typedef boost::shared_ptr<Addresses> 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<Buffer> GetSharedBuffer () const { return m_Buffer; };
std::shared_ptr<Buffer> GetSharedBuffer () const { return m_Buffer; };
std::shared_ptr<Buffer> 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<Buffer> buf);
std::shared_ptr<RouterProfile> 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<std::string_view, std::string_view, size_t> 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> address, uint64_t ts);
void UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts);
template<typename Filter>
std::shared_ptr<const Address> GetAddress (Filter filter) const;
virtual std::shared_ptr<Buffer> NewBuffer () const;
@@ -358,9 +367,9 @@ namespace data
uint64_t m_Timestamp; // in milliseconds
#ifdef __cpp_lib_atomic_shared_ptr
std::atomic<AddressesPtr> 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);