Compare commits

...

6 Commits

Author SHA1 Message Date
orignal
d610e6c4c1 Merge pull request #2132 from PurpleI2P/openssl
recent changes
2024-12-06 20:14:40 -05:00
orignal
13604ccbb6 Changing the window calculation algorithm, increasing the minimum window size 2024-12-05 22:15:11 -05:00
orignal
e996db03c0 process SessionConfirmed in establisher's thread 2024-12-05 20:57:40 -05:00
orignal
35352f1497 Merge pull request #2125 from PurpleI2P/openssl
Recent changes
2024-11-19 18:27:05 -05:00
orignal
e695f1e060 Merge pull request #2118 from PurpleI2P/openssl
recent changes
2024-10-28 20:33:07 -04:00
orignal
ecc635e9bc Merge pull request #2105 from PurpleI2P/openssl
2.54.0
2024-10-08 10:01:35 -04:00
4 changed files with 161 additions and 123 deletions

View File

@@ -344,6 +344,7 @@ namespace transport
m_Server (server), m_Socket (m_Server.GetService ()), m_Server (server), m_Socket (m_Server.GetService ()),
m_IsEstablished (false), m_IsTerminated (false), m_IsEstablished (false), m_IsTerminated (false),
m_Establisher (new NTCP2Establisher), m_Establisher (new NTCP2Establisher),
m_SendKey (nullptr), m_ReceiveKey (nullptr),
#if OPENSSL_SIPHASH #if OPENSSL_SIPHASH
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr), m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
#else #else
@@ -721,6 +722,7 @@ namespace transport
void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{ {
(void) bytes_transferred;
if (ecode) if (ecode)
{ {
LogPrint (eLogWarning, "NTCP2: SessionConfirmed read error: ", ecode.message ()); LogPrint (eLogWarning, "NTCP2: SessionConfirmed read error: ", ecode.message ());
@@ -729,6 +731,17 @@ namespace transport
else else
{ {
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval;
boost::asio::post (m_Server.GetEstablisherService (),
[s = shared_from_this ()] ()
{
s->ProcessSessionConfirmed ();;
});
}
}
void NTCP2Session::ProcessSessionConfirmed ()
{
// run on establisher thread
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received"); LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
// part 1 // part 1
uint8_t nonce[12]; uint8_t nonce[12];
@@ -736,27 +749,51 @@ namespace transport
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce)) if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
{ {
// part 2 // part 2
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC auto buf = std::make_shared<std::vector<uint8_t> > (m_Establisher->m3p2Len - 16); // -MAC
memset (nonce, 0, 12); // set nonce to 0 again memset (nonce, 0, 12); // set nonce to 0 again
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf.data ())) // TODO:handle in establisher thread if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf->data ())) // TODO:handle in establisher thread
{ {
// payload // payload
// RI block must be first // RI block must be first
if (buf[0] != eNTCP2BlkRouterInfo) if ((*buf)[0] != eNTCP2BlkRouterInfo)
{ {
LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)buf[0], " in SessionConfirmed"); LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)(*buf)[0], " in SessionConfirmed");
Terminate (); boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
return; return;
} }
auto size = bufbe16toh (buf.data () + 1); auto size = bufbe16toh (buf->data () + 1);
if (size > buf.size () - 3 || size > i2p::data::MAX_RI_BUFFER_SIZE + 1) if (size > buf->size () - 3 || size > i2p::data::MAX_RI_BUFFER_SIZE + 1)
{ {
LogPrint (eLogError, "NTCP2: Unexpected RouterInfo size ", size, " in SessionConfirmed"); LogPrint (eLogError, "NTCP2: Unexpected RouterInfo size ", size, " in SessionConfirmed");
Terminate (); boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
return; return;
} }
boost::asio::post (m_Server.GetService (),
[s = shared_from_this (), buf, size] ()
{
s->EstablishSessionAfterSessionConfirmed (buf, size);
});
}
else
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
}
else
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
}
void NTCP2Session::EstablishSessionAfterSessionConfirmed (std::shared_ptr<std::vector<uint8_t> > buf, size_t size)
{
// run on main NTCP2 thread
KeyDerivationFunctionDataPhase ();
// Bob data phase keys
m_SendKey = m_Kba;
m_ReceiveKey = m_Kab;
SetSipKeys (m_Sipkeysba, m_Sipkeysab);
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
// we need to set keys for SendTerminationAndTerminate
// TODO: check flag // TODO: check flag
i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag i2p::data::RouterInfo ri (buf->data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag
if (ri.IsUnreachable ()) if (ri.IsUnreachable ())
{ {
LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ()); LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ());
@@ -824,27 +861,12 @@ namespace transport
SetRemoteIdentity (ri1->GetRouterIdentity ()); SetRemoteIdentity (ri1->GetRouterIdentity ());
if (m_Server.AddNTCP2Session (shared_from_this (), true)) if (m_Server.AddNTCP2Session (shared_from_this (), true))
{ {
KeyDerivationFunctionDataPhase ();
// Bob data phase keys
m_SendKey = m_Kba;
m_ReceiveKey = m_Kab;
SetSipKeys (m_Sipkeysba, m_Sipkeysab);
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
Established (); Established ();
ReceiveLength (); ReceiveLength ();
} }
else else
Terminate (); Terminate ();
} }
else
Terminate ();
}
else
Terminate ();
}
}
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey) void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
{ {

View File

@@ -180,6 +180,8 @@ namespace transport
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void ProcessSessionConfirmed ();
void EstablishSessionAfterSessionConfirmed (std::shared_ptr<std::vector<uint8_t> > buf, size_t size);
// data // data
void ReceiveLength (); void ReceiveLength ();

View File

@@ -73,7 +73,7 @@ namespace stream
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_LocalDestination (local), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_DoubleWinIncCounter (false), m_LocalDestination (local),
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service),
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0),
@@ -101,7 +101,7 @@ namespace stream
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_LocalDestination (local), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_DoubleWinIncCounter (false), m_LocalDestination (local),
m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT),
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0),
@@ -495,6 +495,7 @@ namespace stream
return; return;
} }
int rttSample = INT_MAX; int rttSample = INT_MAX;
int incCounter = 0;
m_IsNAcked = false; m_IsNAcked = false;
m_IsResendNeeded = false; m_IsResendNeeded = false;
int nackCount = packet->GetNACKCount (); int nackCount = packet->GetNACKCount ();
@@ -537,8 +538,7 @@ namespace stream
m_LocalDestination.DeletePacket (sentPacket); m_LocalDestination.DeletePacket (sentPacket);
acknowledged = true; acknowledged = true;
if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK) if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK)
if (m_RTT < m_LocalDestination.GetRandom () % INITIAL_RTO) // dirty incCounter++;
m_WindowIncCounter++;
} }
else else
break; break;
@@ -552,7 +552,7 @@ namespace stream
m_SlowRTT2 = rttSample; m_SlowRTT2 = rttSample;
m_PrevRTTSample = rttSample; m_PrevRTTSample = rttSample;
m_Jitter = rttSample / 10; // 10% m_Jitter = rttSample / 10; // 10%
m_Jitter += 5; // for low-latency connections m_Jitter += 15; // for low-latency connections
m_IsFirstRttSample = false; m_IsFirstRttSample = false;
} }
else else
@@ -569,9 +569,23 @@ namespace stream
jitter = m_PrevRTTSample - rttSample; jitter = m_PrevRTTSample - rttSample;
else else
jitter = rttSample / 10; // 10% jitter = rttSample / 10; // 10%
jitter += 5; // for low-latency connections jitter += 15; // for low-latency connections
m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter; m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter;
} }
if (rttSample > m_SlowRTT)
{
incCounter = 0;
m_DoubleWinIncCounter = 1;
}
else if (rttSample < m_SlowRTT)
{
if (m_DoubleWinIncCounter)
{
incCounter = incCounter * 2;
m_DoubleWinIncCounter = 0;
}
}
m_WindowIncCounter = m_WindowIncCounter + incCounter;
// //
// delay-based CC // delay-based CC
if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection
@@ -1297,8 +1311,6 @@ namespace stream
else if (m_IsResendNeeded) // resend packets else if (m_IsResendNeeded) // resend packets
ResendPacket (); ResendPacket ();
// delay-based CC // delay-based CC
else if (!m_IsWinDropped && int(m_SentPackets.size ()) == m_WindowSize) // we sending packets too fast, early detection
ProcessWindowDrop ();
else if (m_WindowSize > int(m_SentPackets.size ())) // send packets else if (m_WindowSize > int(m_SentPackets.size ())) // send packets
SendBuffer (); SendBuffer ();
} }

View File

@@ -19,6 +19,7 @@
#include <mutex> #include <mutex>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Base.h" #include "Base.h"
#include "Gzip.h"
#include "I2PEndian.h" #include "I2PEndian.h"
#include "Identity.h" #include "Identity.h"
#include "LeaseSet.h" #include "LeaseSet.h"
@@ -54,7 +55,7 @@ namespace stream
const size_t COMPRESSION_THRESHOLD_SIZE = 66; const size_t COMPRESSION_THRESHOLD_SIZE = 66;
const int MAX_NUM_RESEND_ATTEMPTS = 10; const int MAX_NUM_RESEND_ATTEMPTS = 10;
const int INITIAL_WINDOW_SIZE = 10; const int INITIAL_WINDOW_SIZE = 10;
const int MIN_WINDOW_SIZE = 2; const int MIN_WINDOW_SIZE = 3;
const int MAX_WINDOW_SIZE = 512; const int MAX_WINDOW_SIZE = 512;
const double RTT_EWMA_ALPHA = 0.25; const double RTT_EWMA_ALPHA = 0.25;
const double SLOWRTT_EWMA_ALPHA = 0.05; const double SLOWRTT_EWMA_ALPHA = 0.05;
@@ -274,6 +275,7 @@ namespace stream
bool m_IsTimeOutResend; bool m_IsTimeOutResend;
bool m_IsImmediateAckRequested; bool m_IsImmediateAckRequested;
bool m_IsRemoteLeaseChangeInProgress; bool m_IsRemoteLeaseChangeInProgress;
bool m_DoubleWinIncCounter;
StreamingDestination& m_LocalDestination; StreamingDestination& m_LocalDestination;
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity; std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
std::shared_ptr<const i2p::crypto::Verifier> m_TransientVerifier; // in case of offline key std::shared_ptr<const i2p::crypto::Verifier> m_TransientVerifier; // in case of offline key