Compare commits

..

1 Commits

Author SHA1 Message Date
self-related
1145f1feca Merge 32a70562c4 into c600b834e3 2025-01-19 12:46:21 +03:00
16 changed files with 99 additions and 164 deletions

View File

@@ -27,15 +27,18 @@ namespace data
size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
{
if (len < DEFAULT_IDENTITY_SIZE) return 0; // buffer too small, don't overflow
memcpy (this, buf, DEFAULT_IDENTITY_SIZE);
if ( len < DEFAULT_IDENTITY_SIZE ) {
// buffer too small, don't overflow
return 0;
}
memcpy (publicKey, buf, DEFAULT_IDENTITY_SIZE);
return DEFAULT_IDENTITY_SIZE;
}
IdentHash Identity::Hash () const
{
IdentHash hash;
SHA256((const uint8_t *)this, DEFAULT_IDENTITY_SIZE, hash);
SHA256(publicKey, DEFAULT_IDENTITY_SIZE, hash);
return hash;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -819,20 +819,15 @@ namespace transport
Terminate ();
return;
}
bool isOlder = false;
std::shared_ptr<i2p::data::RouterProfile> profile; // not null if older
if (ri.GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
{
// received RouterInfo is older than one in netdb
isOlder = true;
if (ri1->HasProfile ())
profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
if (profile && profile->IsDuplicated ())
{
auto profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
if (profile && profile->IsDuplicated ())
{
SendTerminationAndTerminate (eNTCP2Banned);
return;
}
SendTerminationAndTerminate (eNTCP2Banned);
return;
}
}
@@ -849,12 +844,8 @@ namespace transport
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data () + 1, addr->host.to_v6 ().to_bytes ().data () + 1, 7) : // from the same yggdrasil subnet
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address
{
if (isOlder) // older router?
i2p::data::UpdateRouterProfile (ri1->GetIdentHash (),
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Duplicated (); // mark router as duplicated in profile
});
if (profile) // older router?
profile->Duplicated (); // mark router as duplicated in profile
else
LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ());
SendTerminationAndTerminate (eNTCP2Banned);

View File

@@ -10,6 +10,7 @@
#include <fstream>
#include <vector>
#include <map>
#include <random>
#include <boost/asio.hpp>
#include <stdexcept>
@@ -39,7 +40,7 @@ namespace data
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)
m_LastExploratorySelectionUpdateTime (0)
{
}
@@ -119,8 +120,8 @@ namespace data
uint64_t lastManage = 0;
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (),
lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplyingProfileUpdates = lastProfilesCleanup;
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0, applyingProfileUpdatesVariance = 0;
lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplingProfileUpdates = lastProfilesCleanup;
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0, applingProfileUpdatesVariance = 0;
std::list<std::shared_ptr<const I2NPMessage> > msgs;
while (m_IsRunning)
@@ -181,7 +182,7 @@ namespace data
LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk");
}
lastProfilesCleanup = mts;
profilesCleanupVariance = m_Rng () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
profilesCleanupVariance = rand () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
}
if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000)
@@ -197,20 +198,20 @@ namespace data
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;
obsoleteProfilesCleanVariance = rand () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE;
}
if (mts >= lastApplyingProfileUpdates + i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT + applyingProfileUpdatesVariance)
if (mts >= lastApplingProfileUpdates + i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT + applingProfileUpdatesVariance)
{
bool isApplying = m_ApplyingProfileUpdates.valid ();
if (isApplying && m_ApplyingProfileUpdates.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active?
bool isAppling = m_ApplingProfileUpdates.valid ();
if (isAppling && m_ApplingProfileUpdates.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active?
{
m_ApplyingProfileUpdates.get ();
isApplying = false;
m_ApplingProfileUpdates.get ();
isAppling = false;
}
if (!isApplying)
m_ApplyingProfileUpdates = i2p::data::FlushPostponedRouterProfileUpdates ();
lastApplyingProfileUpdates = mts;
applyingProfileUpdatesVariance = m_Rng () % i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE;
if (!isAppling)
m_ApplingProfileUpdates = i2p::data::FlushPostponedRouterProfileUpdates ();
lastApplingProfileUpdates = mts;
applingProfileUpdatesVariance = rand () % i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE;
}
}
catch (std::exception& ex)
@@ -294,7 +295,6 @@ namespace data
}
else
{
r->CancelBufferToDelete (); // since an update received
if (CheckLogLevel (eLogDebug))
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
updated = false;
@@ -571,7 +571,7 @@ namespace data
while(n > 0)
{
std::lock_guard<std::mutex> lock(m_RouterInfosMutex);
uint32_t idx = m_Rng () % m_RouterInfos.size ();
uint32_t idx = rand () % m_RouterInfos.size ();
uint32_t i = 0;
for (const auto & it : m_RouterInfos) {
if(i >= idx) // are we at the random start point?
@@ -674,20 +674,15 @@ namespace data
{
std::lock_guard<std::mutex> l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update
buffer = r->CopyBuffer ();
}
if (!i2p::transport::transports.IsConnected (ident))
r->ScheduleBufferToDelete ();
}
if (buffer)
saveToDisk.emplace_back(ident.ToBase64 (), buffer);
saveToDisk.push_back(std::make_pair(ident.ToBase64 (), buffer));
}
r->SetUpdated (false);
updatedCount++;
continue;
}
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->GetProfile ()->IsUnreachable ())
r->SetUnreachable (true);
// make router reachable back if too few routers or floodfills
@@ -715,15 +710,18 @@ namespace data
r->SetUnreachable (true);
}
}
// make router reachable back if connected now
if (r->IsUnreachable () && i2p::transport::transports.IsConnected (ident))
// make router reachable back and don't delete buffer if connected now
if ((r->IsUnreachable () || r->IsBufferScheduledToDelete ()) && i2p::transport::transports.IsConnected (ident))
{
r->SetUnreachable (false);
r->CancelBufferToDelete ();
}
if (r->IsUnreachable ())
{
if (r->IsFloodfill ()) deletedFloodfillsCount++;
// delete RI file
removeFromDisk.emplace_back (ident.ToBase64());
removeFromDisk.push_back (ident.ToBase64());
deletedCount++;
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
}
@@ -1350,7 +1348,7 @@ namespace data
if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE)
{
std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection),
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, m_Rng);
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, std::mt19937(ts));
}
else
std::swap (m_ExploratorySelection, eligible);

View File

@@ -16,7 +16,6 @@
#include <thread>
#include <mutex>
#include <future>
#include <random>
#include "Base.h"
#include "Gzip.h"
@@ -186,11 +185,10 @@ namespace data
std::shared_ptr<NetDbRequests> m_Requests;
bool m_PersistProfiles;
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_ApplyingProfileUpdates, m_PersistingRouters;
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_ApplingProfileUpdates, m_PersistingRouters;
std::vector<std::shared_ptr<const RouterInfo> > m_ExploratorySelection;
uint64_t m_LastExploratorySelectionUpdateTime; // in monotonic seconds
std::mt19937 m_Rng;
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -20,10 +20,8 @@ namespace i2p
namespace data
{
RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct):
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct),
m_IsActive (true), m_IsSentDirectly (false),
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()),
m_LastRequestTime (0), m_NumAttempts (0)
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_IsActive (true),
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()), m_LastRequestTime (0), m_NumAttempts (0)
{
if (i2p::context.IsFloodfill ())
m_ExcludedPeers.insert (i2p::context.GetIdentHash ()); // exclude self if floodfill
@@ -48,7 +46,6 @@ namespace data
m_ExcludedPeers.insert (router->GetIdentHash ());
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
m_NumAttempts++;
m_IsSentDirectly = false;
return msg;
}
@@ -59,7 +56,6 @@ namespace data
m_ExcludedPeers.insert (floodfill);
m_NumAttempts++;
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
m_IsSentDirectly = true;
return msg;
}
@@ -226,8 +222,7 @@ namespace data
bool done = false;
if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME)
{
if (ts > dest->GetLastRequestTime () + (dest->IsSentDirectly () ? MIN_DIRECT_REQUEST_TIME : MIN_REQUEST_TIME))
// try next floodfill if no response after min interval
if (ts > dest->GetLastRequestTime () + MIN_REQUEST_TIME) // try next floodfill if no response after min interval
done = !SendNextRequest (dest);
}
else // request is expired

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -28,7 +28,6 @@ namespace data
const uint64_t MANAGE_REQUESTS_INTERVAL_VARIANCE = 300; // in milliseconds
const uint64_t MIN_REQUEST_TIME = 1200; // in milliseconds
const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS * (MIN_REQUEST_TIME + MANAGE_REQUESTS_INTERVAL + MANAGE_REQUESTS_INTERVAL_VARIANCE);
const uint64_t MIN_DIRECT_REQUEST_TIME = 600; // in milliseconds
const uint64_t EXPLORATORY_REQUEST_INTERVAL = 55; // in seconds
const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds
const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds
@@ -53,7 +52,6 @@ namespace data
bool IsExploratory () const { return m_IsExploratory; };
bool IsDirect () const { return m_IsDirect; };
bool IsActive () const { return m_IsActive; };
bool IsSentDirectly () const { return m_IsSentDirectly; };
bool IsExcluded (const IdentHash& ident) const;
uint64_t GetCreationTime () const { return m_CreationTime; };
uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
@@ -72,7 +70,7 @@ namespace data
private:
IdentHash m_Destination;
bool m_IsExploratory, m_IsDirect, m_IsActive, m_IsSentDirectly;
bool m_IsExploratory, m_IsDirect, m_IsActive;
std::unordered_set<IdentHash> m_ExcludedPeers;
uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds
std::list<RequestComplete> m_RequestComplete;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -1136,12 +1136,12 @@ namespace data
void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len)
{
m_IsBufferScheduledToDelete = false;
if (!m_Buffer)
m_Buffer = NewBuffer ();
if (len > m_Buffer->size ()) len = m_Buffer->size ();
memcpy (m_Buffer->data (), buf, len);
m_Buffer->SetBufferLen (len);
m_IsBufferScheduledToDelete = false;
}
std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const

View File

@@ -890,7 +890,7 @@ namespace transport
}
auto session = std::make_shared<SSU2Session> (*this, router, address);
if (!isValidEndpoint && router->HasProfile () && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
if (!isValidEndpoint && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
{
// router doesn't publish endpoint, but we connected before and hole punch might be alive
auto ep = router->GetProfile ()->GetLastEndpoint ();

View File

@@ -1178,18 +1178,13 @@ namespace transport
LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb");
return false;
}
bool isOlder = false;
std::shared_ptr<i2p::data::RouterProfile> profile; // not null if older
if (ri->GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
{
// received RouterInfo is older than one in netdb
isOlder = true;
if (ri->HasProfile ())
{
auto profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
if (profile && profile->IsDuplicated ())
return false;
}
profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
if (profile && profile->IsDuplicated ())
return false;
}
ri = ri1;
@@ -1203,12 +1198,8 @@ namespace transport
(!m_RemoteEndpoint.address ().is_v6 () ||
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address
{
if (isOlder) // older router?
i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Duplicated (); // mark router as duplicated in profile
});
if (profile) // older router?
profile->Duplicated (); // mark router as duplicated in profile
else
LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host,
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -101,13 +101,13 @@ namespace tunnel
TunnelMessageBlock block;
block.deliveryType = eDeliveryTypeLocal;
block.data = msg;
std::lock_guard<std::mutex> l(m_SendMutex);
std::unique_lock<std::mutex> l(m_SendMutex);
m_Gateway.PutTunnelDataMsg (block);
}
void TransitTunnelGateway::FlushTunnelDataMsgs ()
{
std::lock_guard<std::mutex> l(m_SendMutex);
std::unique_lock<std::mutex> l(m_SendMutex);
m_Gateway.SendBuffer ();
}
@@ -130,22 +130,14 @@ namespace tunnel
EncryptTunnelMsg (tunnelMsg, newMsg);
LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ());
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
}
void TransitTunnelEndpoint::FlushTunnelDataMsgs ()
{
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint.FlushI2NPMsgs ();
}
void TransitTunnelEndpoint::Cleanup ()
{
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint.Cleanup ();
}
std::string TransitTunnelEndpoint::GetNextPeerName () const
{
auto hash = m_Endpoint.GetCurrentHash ();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -100,7 +100,7 @@ namespace tunnel
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
m_Endpoint (false) {}; // transit endpoint is always outbound
void Cleanup () override;
void Cleanup () override { m_Endpoint.Cleanup (); }
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
void FlushTunnelDataMsgs () override;
@@ -109,7 +109,6 @@ namespace tunnel
private:
std::mutex m_HandleMutex;
TunnelEndpoint m_Endpoint;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -160,8 +160,7 @@ namespace transport
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0),
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0)
{
}
@@ -339,7 +338,7 @@ namespace transport
if (m_IsNAT)
{
m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
}
}
@@ -561,14 +560,7 @@ namespace transport
bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer)
{
if (!peer->router) // reconnect
{
auto r = netdb.FindRouter (ident); // try to get new one from netdb
if (r)
{
peer->SetRouter (r);
r->CancelBufferToDelete ();
}
}
peer->SetRouter (netdb.FindRouter (ident)); // try to get new one from netdb
if (peer->router) // we have RI already
{
if (peer->priority.empty ())
@@ -655,7 +647,7 @@ namespace transport
return true;
}
void Transports::SetPriority (std::shared_ptr<Peer> peer)
void Transports::SetPriority (std::shared_ptr<Peer> peer) const
{
static const std::vector<i2p::data::RouterInfo::SupportedTransports>
ntcp2Priority =
@@ -681,7 +673,7 @@ namespace transport
peer->numAttempts = 0;
peer->priority.clear ();
bool isReal = peer->router->GetProfile ()->IsReal ();
bool ssu2 = isReal ? (m_Rng () & 1) : false; // try NTCP2 if router is not confirmed real
bool ssu2 = isReal ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
if (directTransports)
{
@@ -709,8 +701,7 @@ namespace transport
// try recently connected SSU2 if any
auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
peer->router->GetCompatibleTransports (false);
if ((supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6)) &&
peer->router->HasProfile ())
if (supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6))
{
auto ep = peer->router->GetProfile ()->GetLastEndpoint ();
if (!ep.address ().is_unspecified () && ep.port ())
@@ -800,7 +791,7 @@ namespace transport
}
else
{
testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
if (m_Service)
{
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
@@ -838,7 +829,7 @@ namespace transport
}
else
{
testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
if (m_Service)
{
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
@@ -895,11 +886,7 @@ namespace transport
auto transport = peer->priority[peer->numAttempts-1];
if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
i2p::data::UpdateRouterProfile (ident,
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Connected (); // outgoing NTCP2 connection if always real
});
peer->router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
}
peer->numAttempts = 0;
@@ -934,11 +921,7 @@ namespace transport
session->SendI2NPMessages (msgs); // send DatabaseStore
}
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
i2p::data::UpdateRouterProfile (ident,
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Connected ();
});
if (r) r->GetProfile ()->Connected ();
auto ts = i2p::util::GetSecondsSinceEpoch ();
auto peer = std::make_shared<Peer>(r, ts);
peer->sessions.push_back (session);
@@ -972,13 +955,8 @@ namespace transport
}
else
{
{
std::lock_guard<std::mutex> l(m_PeersMutex);
m_Peers.erase (it);
}
// delete buffer of just disconnected router
auto r = i2p::data::netdb.FindRouter (ident);
if (r && !r->IsUpdated ()) r->ScheduleBufferToDelete ();
std::lock_guard<std::mutex> l(m_PeersMutex);
m_Peers.erase (it);
}
}
}
@@ -1028,7 +1006,7 @@ namespace transport
if (session)
session->SendLocalRouterInfo (true);
it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
m_Rng() % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
}
++it;
}
@@ -1052,7 +1030,7 @@ namespace transport
if (ecode != boost::asio::error::operation_aborted)
{
PeerTest ();
m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
}
}
@@ -1199,7 +1177,7 @@ namespace transport
}
/** XXX: if routes are not restricted this dies */
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer()
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer() const
{
{
std::lock_guard<std::mutex> l(m_FamilyMutex);
@@ -1208,7 +1186,7 @@ namespace transport
if(sz > 1)
{
auto it = m_TrustedFamilies.begin ();
std::advance(it, m_Rng() % sz);
std::advance(it, rand() % sz);
fam = *it;
}
else if (sz == 1)
@@ -1226,7 +1204,7 @@ namespace transport
if(sz == 1)
return i2p::data::netdb.FindRouter(m_TrustedRouters[0]);
auto it = m_TrustedRouters.begin();
std::advance(it, m_Rng() % sz);
std::advance(it, rand() % sz);
return i2p::data::netdb.FindRouter(*it);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -20,7 +20,6 @@
#include <string>
#include <memory>
#include <atomic>
#include <random>
#include <boost/asio.hpp>
#include "TransportSession.h"
#include "SSU2.h"
@@ -107,8 +106,7 @@ namespace transport
};
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
const int PEER_TEST_INTERVAL = 68*60; // in seconds
const int PEER_TEST_INTERVAL_VARIANCE = 3*60; // in seconds
const int PEER_TEST_INTERVAL = 71; // in minutes
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
const int MAX_NUM_DELAYED_MESSAGES = 150;
@@ -170,7 +168,7 @@ namespace transport
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
/** get a trusted first hop for restricted routes */
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer();
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
/** do we want to use restricted routes? */
bool RoutesRestricted() const;
/** restrict routes to use only these router families for first hops */
@@ -193,7 +191,7 @@ namespace transport
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
std::shared_ptr<TransportSession> PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
void SetPriority (std::shared_ptr<Peer> peer);
void SetPriority (std::shared_ptr<Peer> peer) const;
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
void HandlePeerTestTimer (const boost::system::error_code& ecode);
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
@@ -241,7 +239,6 @@ namespace transport
mutable std::mutex m_TrustedRoutersMutex;
i2p::I2NPMessagesHandler m_LoopbackHandler;
std::mt19937 m_Rng;
public:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -179,12 +179,9 @@ namespace tunnel
{
uint8_t ret = hop->GetRetCode (msg + 1);
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
if (hop->ident)
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
[ret](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->TunnelBuildResponse (ret);
});
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
if (profile)
profile->TunnelBuildResponse (ret);
if (ret)
// if any of participants declined the tunnel is not established
established = false;
@@ -746,11 +743,11 @@ namespace tunnel
while (hop)
{
if (hop->ident)
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->TunnelNonReplied ();
});
{
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
if (profile)
profile->TunnelNonReplied ();
}
hop = hop->next;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -560,7 +560,7 @@ namespace tunnel
i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false);
if (hop)
{
if (!hop->HasProfile () || !hop->GetProfile ()->IsBad ())
if (!hop->GetProfile ()->IsBad ())
break;
}
else if (tryClient)
@@ -588,7 +588,7 @@ namespace tunnel
(inbound && i2p::transport::transports.GetNumPeers () > 25))
{
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ());
if (r && r->IsECIES () && (!r->HasProfile () || !r->GetProfile ()->IsBad ()) &&
if (r && r->IsECIES () && !r->GetProfile ()->IsBad () &&
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
{
prevHop = r;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -1350,14 +1350,12 @@ namespace client
LogPrint (eLogError, "SAM: Runtime exception: ", ex.what ());
}
decltype(m_Sessions) sessions;
{
std::unique_lock<std::mutex> l(m_SessionsMutex);
m_Sessions.swap (sessions);
}
for (auto& it: sessions)
it.second->Close ();
for (auto& it: m_Sessions)
it.second->Close ();
m_Sessions.clear ();
}
StopIOService ();
}