add endpoint to recently connected list after successive peer test

This commit is contained in:
orignal
2026-01-21 14:45:29 -05:00
parent 45b6a2319b
commit 08aa515228
+58 -56
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024-2025, The PurpleI2P Project
* Copyright (c) 2024-2026, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -14,18 +14,18 @@ namespace i2p
{
namespace transport
{
SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID):
SSU2Session (server, nullptr, nullptr, false),
SSU2PeerTestSession::SSU2PeerTestSession (SSU2Server& server, uint64_t sourceConnID, uint64_t destConnID):
SSU2Session (server, nullptr, nullptr, false),
m_MsgNumReceived (0), m_NumResends (0),m_IsConnectedRecently (false), m_IsStatusChanged (false),
m_PeerTestResendTimer (server.GetService ())
{
if (!sourceConnID) sourceConnID = ~destConnID;
if (!destConnID) destConnID = ~sourceConnID;
SetSourceConnID (sourceConnID);
SetDestConnID (destConnID);
SetState (eSSU2SessionStatePeerTest);
SetDestConnID (destConnID);
SetState (eSSU2SessionStatePeerTest);
SetTerminationTimeout (SSU2_PEER_TEST_EXPIRATION_TIMEOUT);
}
}
bool SSU2PeerTestSession::ProcessPeerTest (uint8_t * buf, size_t len)
{
@@ -63,14 +63,14 @@ namespace transport
HandlePayload (payload, len - 48);
SetIsDataReceived (false);
return true;
}
}
void SSU2PeerTestSession::HandleAddress (const uint8_t * buf, size_t len)
{
if (!ExtractEndpoint (buf, len, m_OurEndpoint))
LogPrint (eLogWarning, "SSU2: Can't handle address block from peer test message");
}
}
void SSU2PeerTestSession::HandlePeerTest (const uint8_t * buf, size_t len)
{
// msgs 5-7
@@ -80,19 +80,19 @@ namespace transport
{
LogPrint (eLogDebug, "SSU2: PeerTest msg num ", msg, " received after ", m_MsgNumReceived, ". Ignored");
return;
}
}
size_t offset = 3; // points to signed data after msg + code + flag
uint32_t nonce = bufbe32toh (buf + offset + 1); // 1 - ver
switch (msg) // msg
{
case 5: // Alice from Charlie 1
{
{
if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ())
{
m_PeerTestResendTimer.cancel (); // cancel delayed msg 6 if any
if (GetServer ().IsForcedFirewalled (GetRemoteEndpoint ().address().is_v4()))
if (GetServer ().IsForcedFirewalled (GetRemoteEndpoint ().address().is_v4()))
// we assume that msg 5 was not received if forced firewalled
return;
return;
m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ());
if (GetAddress ())
{
@@ -108,49 +108,51 @@ namespace transport
break;
}
case 6: // Charlie from Alice
{
{
m_PeerTestResendTimer.cancel (); // no more msg 5 resends
if (GetAddress ())
SendPeerTest (7, buf + offset, len - offset);
else
LogPrint (eLogWarning, "SSU2: Unknown address for peer test 6");
GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ());
GetServer ().RequestRemoveSession (GetConnID ());
break;
}
}
case 7: // Alice from Charlie 2
{
{
m_PeerTestResendTimer.cancel (); // no more msg 6 resends
if (m_MsgNumReceived < 5 && m_OurEndpoint.port ()) // msg 5 was not received
{
if (m_OurEndpoint.address ().is_v4 ()) // ipv4
{
if (i2p::context.GetStatus () == eRouterStatusFirewalled)
{
{
if (m_OurEndpoint.port () != GetServer ().GetPort (true))
i2p::context.SetError (eRouterErrorSymmetricNAT);
else if (i2p::context.GetError () == eRouterErrorSymmetricNAT)
i2p::context.SetError (eRouterErrorNone);
}
}
}
else
{
if (i2p::context.GetStatusV6 () == eRouterStatusFirewalled)
{
{
if (m_OurEndpoint.port () != GetServer ().GetPort (false))
i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT);
else if (i2p::context.GetErrorV6 () == eRouterErrorSymmetricNAT)
i2p::context.SetErrorV6 (eRouterErrorNone);
}
}
}
GetServer ().RequestRemoveSession (GetConnID ());
}
}
GetServer ().AddConnectedRecently (GetRemoteEndpoint (), i2p::util::GetSecondsSinceEpoch ());
GetServer ().RequestRemoveSession (GetConnID ());
break;
}
default:
}
default:
LogPrint (eLogWarning, "SSU2: PeerTest unexpected msg num ", msg);
return;
}
m_MsgNumReceived = msg;
}
m_MsgNumReceived = msg;
}
void SSU2PeerTestSession::SendPeerTest (uint8_t msg)
@@ -190,7 +192,7 @@ namespace transport
// send
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ());
UpdateNumSentBytes (payloadSize + 32);
}
}
void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, bool delayed)
{
@@ -200,26 +202,26 @@ namespace transport
// schedule resend for msgs 5 or 6
if (msg == 5 || msg == 6)
ScheduleResend (msg);
}
void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen,
}
void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr, bool delayed)
{
if (!addr) return;
SetAddress (addr);
SendPeerTest (msg, signedData, signedDataLen, delayed);
}
SendPeerTest (msg, signedData, signedDataLen, delayed);
}
void SSU2PeerTestSession::Connect ()
{
LogPrint (eLogError, "SSU2: Can't connect peer test session");
}
}
bool SSU2PeerTestSession::ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len)
{
LogPrint (eLogError, "SSU2: Can't handle incoming message in peer test session");
return false;
}
}
void SSU2PeerTestSession::ScheduleResend (uint8_t msg)
{
@@ -233,19 +235,19 @@ namespace transport
if (ecode != boost::asio::error::operation_aborted)
{
auto s1 = s.lock ();
if (s1)
if (s1)
{
if (msg > s1->m_MsgNumReceived)
{
if (msg > s1->m_MsgNumReceived)
{
s1->SendPeerTest (msg);
s1->m_NumResends++;
s1->ScheduleResend (msg);
}
}
}
}
}
}
});
}
}
}
}
SSU2HolePunchSession::SSU2HolePunchSession (SSU2Server& server, uint32_t nonce,
const boost::asio::ip::udp::endpoint& remoteEndpoint,
@@ -257,12 +259,12 @@ namespace transport
uint64_t destConnID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id
uint64_t sourceConnID = ~destConnID;
SetSourceConnID (sourceConnID);
SetDestConnID (destConnID);
SetDestConnID (destConnID);
SetState (eSSU2SessionStateHolePunch);
SetRemoteEndpoint (remoteEndpoint);
SetAddress (addr);
SetTerminationTimeout (SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT);
}
SetTerminationTimeout (SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT);
}
void SSU2HolePunchSession::SendHolePunch ()
{
@@ -288,12 +290,12 @@ namespace transport
htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000);
size_t payloadSize = 7;
payloadSize += CreateAddressBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize, ep);
// relay response block
// relay response block
if (payloadSize + m_RelayResponseBlock.size () < GetMaxPayloadSize ())
{
{
memcpy (payload + payloadSize, m_RelayResponseBlock.data (), m_RelayResponseBlock.size ());
payloadSize += m_RelayResponseBlock.size ();
}
}
payloadSize += CreatePaddingBlock (payload + payloadSize, GetMaxPayloadSize () - payloadSize);
// encrypt
uint8_t n[12];
@@ -307,14 +309,14 @@ namespace transport
// send
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep);
UpdateNumSentBytes (payloadSize + 32);
}
}
void SSU2HolePunchSession::SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen)
{
m_RelayResponseBlock.assign (relayResponseBlock, relayResponseBlock + relayResponseBlockLen);
SendHolePunch ();
ScheduleResend ();
}
}
void SSU2HolePunchSession::ScheduleResend ()
{
@@ -328,21 +330,21 @@ namespace transport
if (ecode != boost::asio::error::operation_aborted)
{
auto s1 = s.lock ();
if (s1 && s1->GetState () == eSSU2SessionStateHolePunch)
if (s1 && s1->GetState () == eSSU2SessionStateHolePunch)
{
s1->SendHolePunch ();
s1->m_NumResends++;
s1->ScheduleResend ();
}
}
s1->ScheduleResend ();
}
}
});
}
}
}
bool SSU2HolePunchSession::ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len)
{
m_HolePunchResendTimer.cancel ();
return SSU2Session::ProcessFirstIncomingMessage (connID, buf, len);
}
}
}
}