mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-03-29 06:39:59 +00:00
exclude routers from the same subnet from next hop
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user