check for idle time. don't create and test tunnel if idling

This commit is contained in:
orignal committed 2026-04-02 13:37:35 -04:00
1 parent 7f4bfccdbb
commit a683b98e73
5 files changed
+60 -13

No files matched your search

+10 -10
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
*
@@ -105,8 +105,8 @@ namespace garlic
for (auto& msg: msgs)
ret.push_back (WrapSingleMessage(msg));
return ret;
}
}
ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
GarlicRoutingSession (owner, attachLeaseSet),
@@ -435,8 +435,8 @@ namespace garlic
GarlicDestination::GarlicDestination ():
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL),
m_NumTags (32), // 32 tags by default
m_PayloadBuffer (nullptr), m_LastIncomingSessionTimestamp (0),
m_IsIdling (false), m_NumTags (32), // 32 tags by default
m_PayloadBuffer (nullptr), m_LastIncomingSessionTimestamp (0),
m_NumRatchetInboundTags (0) // 0 means standard
{
}
@@ -550,8 +550,8 @@ namespace garlic
{
// otherwise ECIESx25519
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
if (ts > m_LastIncomingSessionTimestamp + INCOMING_SESSIONS_MINIMAL_INTERVAL)
{
if (ts > m_LastIncomingSessionTimestamp + INCOMING_SESSIONS_MINIMAL_INTERVAL)
{
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
if (session->HandleNextMessage (buf, length, nullptr, 0))
m_LastIncomingSessionTimestamp = ts;
@@ -761,7 +761,7 @@ namespace garlic
if (destination->GetEncryptionType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{
if (SupportsEncryptionType (destination->GetEncryptionType ()))
{
{
ECIESX25519AEADRatchetSessionPtr session;
uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey); // we are supposed to get static key
@@ -1125,11 +1125,11 @@ namespace garlic
{
return m_Encryptor.Encrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
}
bool GarlicDestination::AEADChaCha20Poly1305Decrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen,
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len)
{
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
}
}
}
}
+3
View File
@@ -245,6 +245,8 @@ namespace garlic
void CleanUp ();
std::mt19937& GetRng () { return m_Rng; };
bool IsIdling () const { return m_IsIdling; };
void SetIsIdling (bool isIdling) { m_IsIdling = isIdling; };
void SetNumTags (int numTags) { m_NumTags = numTags; };
int GetNumTags () const { return m_NumTags; };
void SetNumRatchetInboundTags (int numTags) { m_NumRatchetInboundTags = numTags; };
@@ -308,6 +310,7 @@ namespace garlic
private:
std::mt19937 m_Rng;
bool m_IsIdling;
// outgoing sessions
int m_NumTags;
std::mutex m_SessionsMutex;
+5 -2
View File
@@ -480,8 +480,11 @@ namespace tunnel
{
if (ts > m_NextManageTime || ts + 2*TUNNEL_POOL_MANAGE_INTERVAL < m_NextManageTime) // in case if clock was adjusted
{
CreateTunnels (ts);
TestTunnels (ts);
if (!m_LocalDestination || !m_LocalDestination->IsIdling ())
{
CreateTunnels (ts);
TestTunnels (ts);
}
m_NextManageTime = ts + TUNNEL_POOL_MANAGE_INTERVAL + (tunnels.GetRng ()() % TUNNEL_POOL_MANAGE_INTERVAL)/2;
}
}
+37
View File
@@ -54,10 +54,28 @@ namespace client
m_ConnectTimeout = timeout;
}
void I2PService::SetCloseIdleTime (uint64_t idleTime)
{
if (idleTime > 0 && idleTime < I2P_SERVICE_MIN_CLOSE_IDLE_TIME) idleTime = I2P_SERVICE_MIN_CLOSE_IDLE_TIME;
m_CloseIdleTime = idleTime;
if (m_CloseIdleTime)
{
if (!m_IdleCheckTimer) m_IdleCheckTimer.reset (new boost::asio::steady_timer(m_LocalDestination->GetService ()));
ScheduleIdleCheckTimer ();
}
}
void I2PService::UpdateLastActivityTime ()
{
if (m_CloseIdleTime)
{
m_LastActivityTime = i2p::util::GetMonotonicMilliseconds ();
if (m_LocalDestination->IsIdling ())
{
m_LocalDestination->SetIsIdling (false);
ScheduleIdleCheckTimer ();
}
}
}
void I2PService::AddReadyCallback(ReadyCallback cb)
@@ -108,6 +126,25 @@ namespace client
m_ReadyTimerTriggered = false;
}
void I2PService::ScheduleIdleCheckTimer ()
{
if (!m_IdleCheckTimer || !m_CloseIdleTime) return;
m_IdleCheckTimer->expires_after(std::chrono::milliseconds (m_CloseIdleTime/2));
m_IdleCheckTimer->async_wait(std::bind(&I2PService::HandleIdleCheckTimer, shared_from_this (), std::placeholders::_1));
}
void I2PService::HandleIdleCheckTimer(const boost::system::error_code & ec)
{
if (ec != boost::asio::error::operation_aborted)
{
auto ts = i2p::util::GetMonotonicMilliseconds ();
if (ts > m_LastActivityTime + m_CloseIdleTime)
m_LocalDestination->SetIsIdling (true);
else
ScheduleIdleCheckTimer ();
}
}
void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, std::string_view dest, uint16_t port) {
assert(streamRequestComplete);
auto address = i2p::client::context.GetAddressBook ().GetAddress (dest);
+5 -1
View File
@@ -23,6 +23,7 @@ namespace i2p
namespace client
{
constexpr int I2P_SERVICE_READINESS_CHECK_INTERVAL = 1; // in seconds
constexpr uint64_t I2P_SERVICE_MIN_CLOSE_IDLE_TIME = 30000; // in milliseconds
class I2PServiceHandler;
class I2PService : public std::enable_shared_from_this<I2PService>
@@ -50,7 +51,7 @@ namespace client
void ClearHandlers ();
void SetConnectTimeout(uint64_t timeout);
void SetCloseIdleTime (uint64_t idleTime) { m_CloseIdleTime = idleTime; };
void SetCloseIdleTime (uint64_t idleTime);
void UpdateLastActivityTime ();
void AddReadyCallback(ReadyCallback cb);
@@ -76,6 +77,8 @@ namespace client
void TriggerReadyCheckTimer();
void HandleReadyCheckTimer(const boost::system::error_code & ec);
void ScheduleIdleCheckTimer ();
void HandleIdleCheckTimer(const boost::system::error_code & ec);
private:
@@ -88,6 +91,7 @@ namespace client
uint64_t m_ConnectTimeout; // in seconds
uint64_t m_CloseIdleTime; // in milliseconds
uint64_t m_LastActivityTime; // monotonic milliseconds
std::unique_ptr<boost::asio::steady_timer> m_IdleCheckTimer;
static constexpr size_t NEVER_TIMES_OUT = 0;