diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index b53cce0a..14fc6407 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -916,20 +916,32 @@ namespace stream UpdateCurrentRemoteLease (true); if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD) { + bool freshTunnel = false; if (!m_CurrentOutboundTunnel) { auto leaseRouter = i2p::data::netdb.FindRouter (m_CurrentRemoteLease->tunnelGateway); m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (nullptr, leaseRouter ? leaseRouter->GetCompatibleTransports (false) : (i2p::data::RouterInfo::CompatibleTransports)i2p::data::RouterInfo::eAllTransports); + freshTunnel = true; } else if (!m_CurrentOutboundTunnel->IsEstablished ()) + { + auto oldOutboundTunnel = m_CurrentOutboundTunnel; m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel); + if (m_CurrentOutboundTunnel && oldOutboundTunnel->GetEndpointIdentHash() != m_CurrentOutboundTunnel->GetEndpointIdentHash()) + freshTunnel = true; + } if (!m_CurrentOutboundTunnel) { LogPrint (eLogError, "Streaming: No outbound tunnels in the pool, sSID=", m_SendStreamID); m_CurrentRemoteLease = nullptr; return; } + if (freshTunnel) + { + m_RTO = INITIAL_RTO; + m_TunnelsChangeSequenceNumber = m_SequenceNumber; // should be determined more precisely + } std::vector msgs; for (const auto& it: packets) @@ -1024,34 +1036,31 @@ namespace stream if (packets.size () > 0) { m_NumResendAttempts++; - if (m_RTO != INITIAL_RTO) + if (m_NumResendAttempts == 1 && m_RTO != INITIAL_RTO) + { + // congestion avoidance m_RTO *= 2; - switch (m_NumResendAttempts) + m_WindowSize -= (m_WindowSize + WINDOW_SIZE_DROP_FRACTION) / WINDOW_SIZE_DROP_FRACTION; // adjustment >= 1 + if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; + } + else { - case 1: // congestion avoidance - m_WindowSize -= (m_WindowSize + WINDOW_SIZE_DROP_FRACTION) / WINDOW_SIZE_DROP_FRACTION; // adjustment >= 1 - if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE; - break; - case 2: - m_TunnelsChangeSequenceNumber = m_SequenceNumber; - m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time -#if (__cplusplus >= 201703L) // C++ 17 or higher - [[fallthrough]]; -#endif - // no break here - case 4: - if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); - UpdateCurrentRemoteLease (); // pick another lease - LogPrint (eLogWarning, "Streaming: Another remote lease has been selected for stream with rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID); - break; - case 3: + m_TunnelsChangeSequenceNumber = m_SequenceNumber; + m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change + if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); + if (m_NumResendAttempts & 1) + { // pick another outbound tunnel - m_TunnelsChangeSequenceNumber = m_SequenceNumber; - if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (m_CurrentOutboundTunnel); - LogPrint (eLogWarning, "Streaming: Another outbound tunnel has been selected for stream with sSID=", m_SendStreamID); - break; - default: ; + LogPrint (eLogWarning, "Streaming: Resend #", m_NumResendAttempts, + ", another outbound tunnel has been selected for stream with sSID=", m_SendStreamID); + } + else + { + UpdateCurrentRemoteLease (); // pick another lease + LogPrint (eLogWarning, "Streaming: Resend #", m_NumResendAttempts, + ", another remote lease has been selected for stream with rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID); + } } SendPackets (packets); } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 7a521002..e27deb9c 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -52,7 +52,7 @@ namespace stream const size_t STREAMING_MTU_RATCHETS = 1812; const size_t MAX_PACKET_SIZE = 4096; const size_t COMPRESSION_THRESHOLD_SIZE = 66; - const int MAX_NUM_RESEND_ATTEMPTS = 6; + const int MAX_NUM_RESEND_ATTEMPTS = 9; const int WINDOW_SIZE = 6; // in messages const int MIN_WINDOW_SIZE = 1; const int MAX_WINDOW_SIZE = 128;