mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 13:27:17 +01:00
cleanup unclaimed out-of-sequence fragments
This commit is contained in:
parent
b83e7e6c5c
commit
46f927fc1b
|
@ -714,6 +714,8 @@ namespace tunnel
|
||||||
|
|
||||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||||
tunnel->SetState (eTunnelStateExpiring);
|
tunnel->SetState (eTunnelStateExpiring);
|
||||||
|
else // we don't need to cleanup expiring tunnels
|
||||||
|
tunnel->Cleanup ();
|
||||||
}
|
}
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
@ -763,7 +765,10 @@ namespace tunnel
|
||||||
it = m_TransitTunnels.erase (it);
|
it = m_TransitTunnels.erase (it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
tunnel->Cleanup ();
|
||||||
it++;
|
it++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
Tunnel.h
4
Tunnel.h
|
@ -165,6 +165,10 @@ namespace tunnel
|
||||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||||
void Print (std::stringstream& s) const;
|
void Print (std::stringstream& s) const;
|
||||||
bool IsInbound() const { return true; }
|
bool IsInbound() const { return true; }
|
||||||
|
|
||||||
|
// override TunnelBase
|
||||||
|
void Cleanup () { m_Endpoint.Cleanup (); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
TunnelEndpoint m_Endpoint;
|
TunnelEndpoint m_Endpoint;
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace tunnel
|
||||||
m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent),
|
m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent),
|
||||||
m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {};
|
m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {};
|
||||||
virtual ~TunnelBase () {};
|
virtual ~TunnelBase () {};
|
||||||
|
virtual void Cleanup () {};
|
||||||
|
|
||||||
virtual void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg) = 0;
|
virtual void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg) = 0;
|
||||||
virtual void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg) = 0;
|
virtual void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg) = 0;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
#include "TunnelEndpoint.h"
|
#include "TunnelEndpoint.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -192,7 +193,7 @@ namespace tunnel
|
||||||
|
|
||||||
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data)
|
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data)
|
||||||
{
|
{
|
||||||
if (!m_OutOfSequenceFragments.insert ({{msgID, fragmentNum}, {fragmentNum, isLastFragment, data}}).second)
|
if (!m_OutOfSequenceFragments.insert ({{msgID, fragmentNum}, {isLastFragment, data, i2p::util::GetMillisecondsSinceEpoch () }}).second)
|
||||||
LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID);
|
LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,30 +214,25 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
auto it = m_OutOfSequenceFragments.find ({msgID, msg.nextFragmentNum});
|
auto it = m_OutOfSequenceFragments.find ({msgID, msg.nextFragmentNum});
|
||||||
if (it != m_OutOfSequenceFragments.end ())
|
if (it != m_OutOfSequenceFragments.end ())
|
||||||
{
|
{
|
||||||
if (it->second.fragmentNum == msg.nextFragmentNum)
|
LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found");
|
||||||
|
size_t size = it->second.data->GetLength ();
|
||||||
|
if (msg.data->len + size > msg.data->maxLen)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)it->second.fragmentNum, " of message ", msgID, " found");
|
LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough");
|
||||||
size_t size = it->second.data->GetLength ();
|
auto newMsg = NewI2NPMessage ();
|
||||||
if (msg.data->len + size > msg.data->maxLen)
|
*newMsg = *(msg.data);
|
||||||
{
|
msg.data = newMsg;
|
||||||
LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough");
|
|
||||||
auto newMsg = NewI2NPMessage ();
|
|
||||||
*newMsg = *(msg.data);
|
|
||||||
msg.data = newMsg;
|
|
||||||
}
|
|
||||||
if (msg.data->Concat (it->second.data->GetBuffer (), size) < size) // concatenate out-of-sync fragment
|
|
||||||
LogPrint (eLogError, "TunnelMessage: Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen);
|
|
||||||
if (it->second.isLastFragment)
|
|
||||||
// message complete
|
|
||||||
msg.nextFragmentNum = 0;
|
|
||||||
else
|
|
||||||
msg.nextFragmentNum++;
|
|
||||||
m_OutOfSequenceFragments.erase (it);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (msg.data->Concat (it->second.data->GetBuffer (), size) < size) // concatenate out-of-sync fragment
|
||||||
|
LogPrint (eLogError, "TunnelMessage: Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen);
|
||||||
|
if (it->second.isLastFragment)
|
||||||
|
// message complete
|
||||||
|
msg.nextFragmentNum = 0;
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Tunnel message: next fragment ", (int)it->second.fragmentNum, " of message ", msgID, " mismatch. ", (int)msg.nextFragmentNum, " expected");
|
msg.nextFragmentNum++;
|
||||||
|
m_OutOfSequenceFragments.erase (it);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -275,6 +271,19 @@ namespace tunnel
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "TunnelMessage: Unknown delivery type ", (int)msg.deliveryType);
|
LogPrint (eLogError, "TunnelMessage: Unknown delivery type ", (int)msg.deliveryType);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TunnelEndpoint::Cleanup ()
|
||||||
|
{
|
||||||
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
// out-of-sequence fragments
|
||||||
|
for (auto it = m_OutOfSequenceFragments.begin (); it != m_OutOfSequenceFragments.end ();)
|
||||||
|
{
|
||||||
|
if (ts > it->second.receiveTime + i2p::I2NP_MESSAGE_EXPIRATION_TIMEOUT)
|
||||||
|
it = m_OutOfSequenceFragments.erase (it);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ namespace tunnel
|
||||||
|
|
||||||
struct Fragment
|
struct Fragment
|
||||||
{
|
{
|
||||||
uint8_t fragmentNum;
|
|
||||||
bool isLastFragment;
|
bool isLastFragment;
|
||||||
std::shared_ptr<I2NPMessage> data;
|
std::shared_ptr<I2NPMessage> data;
|
||||||
|
uint64_t receiveTime; // milliseconds since epoch
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -30,7 +30,8 @@ namespace tunnel
|
||||||
TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0) {};
|
TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0) {};
|
||||||
~TunnelEndpoint ();
|
~TunnelEndpoint ();
|
||||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||||
|
void Cleanup ();
|
||||||
|
|
||||||
void HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg);
|
void HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue