diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 16912daf..4b6e8bc8 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -715,8 +715,8 @@ namespace client } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): - LeaseSetDestination (isPublic, params), - m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0), + LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), + m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { if (isPublic) @@ -727,6 +727,14 @@ namespace client m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); + + // extract streaming params + if (params) + { + auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY); + if (it != params->end ()) + m_StreamingAckDelay = std::stoi(it->second); + } } ClientDestination::~ClientDestination () diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 3b87d1d0..d11b10dd 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -58,6 +58,10 @@ namespace client const char I2CP_PARAM_MAX_TUNNEL_LATENCY[] = "latency.max"; const int DEFAULT_MAX_TUNNEL_LATENCY = 0; + // streaming + const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay"; + const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds + typedef std::function stream)> StreamRequestComplete; class LeaseSetDestination: public i2p::garlic::GarlicDestination, @@ -199,6 +203,7 @@ namespace client void StopAcceptingStreams (); bool IsAcceptingStreams () const; void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor); + int GetStreamingAckDelay () const { return m_StreamingAckDelay; } // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; @@ -230,6 +235,7 @@ namespace client uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; std::shared_ptr m_Decryptor; + int m_StreamingAckDelay; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; i2p::datagram::DatagramDestination * m_DatagramDestination; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 2bf267fa..ef655776 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -62,6 +62,7 @@ namespace stream m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), + m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); @@ -73,7 +74,8 @@ namespace stream m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE), - m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0) + m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), + m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); } @@ -161,7 +163,7 @@ namespace stream { m_IsAckSendScheduled = true; auto ackTimeout = m_RTT/10; - if (ackTimeout > ACK_SEND_TIMEOUT) ackTimeout = ACK_SEND_TIMEOUT; + if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout)); m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, shared_from_this (), std::placeholders::_1)); @@ -199,7 +201,7 @@ namespace stream { // wait for SYN m_IsAckSendScheduled = true; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ACK_SEND_TIMEOUT)); + m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(SYN_TIMEOUT)); m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, shared_from_this (), std::placeholders::_1)); } @@ -805,7 +807,7 @@ namespace stream { if (m_LastReceivedSequenceNumber < 0) { - LogPrint (eLogWarning, "Streaming: SYN has not been received after ", ACK_SEND_TIMEOUT, " milliseconds after follow on, terminate rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID); + LogPrint (eLogWarning, "Streaming: SYN has not been received after ", SYN_TIMEOUT, " milliseconds after follow on, terminate rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID); m_Status = eStreamStatusReset; Close (); return; diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 94b356e8..025ceb63 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -42,13 +42,13 @@ namespace stream const size_t STREAMING_MTU = 1730; const size_t MAX_PACKET_SIZE = 4096; const size_t COMPRESSION_THRESHOLD_SIZE = 66; - const int ACK_SEND_TIMEOUT = 200; // in milliseconds const int MAX_NUM_RESEND_ATTEMPTS = 6; const int WINDOW_SIZE = 6; // in messages const int MIN_WINDOW_SIZE = 1; const int MAX_WINDOW_SIZE = 128; const int INITIAL_RTT = 8000; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds + const int SYN_TIMEOUT = 200; // how long we wait for SYN after follow-on, in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds const int MAX_RECEIVE_TIMEOUT = 30; // in seconds @@ -242,7 +242,7 @@ namespace stream std::mutex m_SendBufferMutex; SendBufferQueue m_SendBuffer; - int m_WindowSize, m_RTT, m_RTO; + int m_WindowSize, m_RTT, m_RTO, m_AckDelay; uint64_t m_LastWindowSizeIncreaseTime; int m_NumResendAttempts; }; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index e340c3f1..f823a92b 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -431,6 +431,7 @@ namespace client options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND); options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY); options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY); + options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const @@ -447,7 +448,7 @@ namespace client if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value)) options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value)) - options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; + options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; } void ClientContext::ReadTunnels () diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 4b5d0dce..9b65ef32 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -90,8 +90,8 @@ namespace client template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const; template - void ReadI2CPOptions (const Section& section, std::map& options) const; - void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; + void ReadI2CPOptions (const Section& section, std::map& options) const; // for tunnels + void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; // for HTTP and SOCKS proxy void CleanupUDP(const boost::system::error_code & ecode); void ScheduleCleanupUDP();