mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 00:00:29 +03:00
limit stream's inbound speed
This commit is contained in:
parent
41dd8b527d
commit
fb8e0e1b5b
@ -980,6 +980,7 @@ namespace client
|
|||||||
LeaseSetDestination (service, isPublic, params),
|
LeaseSetDestination (service, isPublic, params),
|
||||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||||
m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED),
|
m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED),
|
||||||
|
m_StreamingInboundSpeed (DEFAULT_MAX_INBOUND_SPEED),
|
||||||
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0),
|
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0),
|
||||||
m_DatagramDestination (nullptr), m_RefCounter (0), m_LastPublishedTimestamp (0),
|
m_DatagramDestination (nullptr), m_RefCounter (0), m_LastPublishedTimestamp (0),
|
||||||
m_ReadyChecker(service)
|
m_ReadyChecker(service)
|
||||||
@ -1051,6 +1052,9 @@ namespace client
|
|||||||
it = params->find (I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED);
|
it = params->find (I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
m_StreamingOutboundSpeed = std::stoi(it->second);
|
m_StreamingOutboundSpeed = std::stoi(it->second);
|
||||||
|
it = params->find (I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED);
|
||||||
|
if (it != params->end ())
|
||||||
|
m_StreamingInboundSpeed = std::stoi(it->second);
|
||||||
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true
|
m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true
|
||||||
|
@ -86,6 +86,8 @@ namespace client
|
|||||||
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
|
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
|
||||||
const char I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED[] = "i2p.streaming.maxOutboundSpeed"; // bytes/sec
|
const char I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED[] = "i2p.streaming.maxOutboundSpeed"; // bytes/sec
|
||||||
const int DEFAULT_MAX_OUTBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s
|
const int DEFAULT_MAX_OUTBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s
|
||||||
|
const char I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED[] = "i2p.streaming.maxInboundSpeed"; // bytes/sec
|
||||||
|
const int DEFAULT_MAX_INBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s
|
||||||
const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
|
const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
|
||||||
const int DEFAULT_ANSWER_PINGS = true;
|
const int DEFAULT_ANSWER_PINGS = true;
|
||||||
|
|
||||||
@ -262,6 +264,7 @@ namespace client
|
|||||||
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
||||||
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
||||||
int GetStreamingOutboundSpeed () const { return m_StreamingOutboundSpeed; }
|
int GetStreamingOutboundSpeed () const { return m_StreamingOutboundSpeed; }
|
||||||
|
int GetStreamingInboundSpeed () const { return m_StreamingInboundSpeed; }
|
||||||
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
|
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
|
||||||
|
|
||||||
// datagram
|
// datagram
|
||||||
@ -300,6 +303,7 @@ namespace client
|
|||||||
|
|
||||||
int m_StreamingAckDelay;
|
int m_StreamingAckDelay;
|
||||||
int m_StreamingOutboundSpeed;
|
int m_StreamingOutboundSpeed;
|
||||||
|
int m_StreamingInboundSpeed;
|
||||||
bool m_IsStreamingAnswerPings;
|
bool m_IsStreamingAnswerPings;
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
||||||
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
||||||
|
@ -70,6 +70,7 @@ namespace stream
|
|||||||
std::shared_ptr<const i2p::data::LeaseSet> remote, int port): m_Service (service),
|
std::shared_ptr<const i2p::data::LeaseSet> remote, int port): m_Service (service),
|
||||||
m_SendStreamID (0), m_SequenceNumber (0),
|
m_SendStreamID (0), m_SequenceNumber (0),
|
||||||
m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1),
|
m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1),
|
||||||
|
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
|
||||||
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
||||||
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true),
|
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true),
|
||||||
m_IsTimeOutResend (false), m_LocalDestination (local),
|
m_IsTimeOutResend (false), m_LocalDestination (local),
|
||||||
@ -78,18 +79,25 @@ namespace stream
|
|||||||
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO),
|
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO),
|
||||||
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT),
|
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT),
|
||||||
m_PrevRTT (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
|
m_PrevRTT (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
|
||||||
m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_DropWindowDelayTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_DropWindowDelayTime (0),
|
||||||
|
m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed
|
||||||
|
m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
||||||
{
|
{
|
||||||
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
|
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
|
||||||
m_RemoteIdentity = remote->GetIdentity ();
|
m_RemoteIdentity = remote->GetIdentity ();
|
||||||
auto outboundSpeed = local.GetOwner ()->GetStreamingOutboundSpeed ();
|
auto outboundSpeed = local.GetOwner ()->GetStreamingOutboundSpeed ();
|
||||||
if (outboundSpeed)
|
if (outboundSpeed)
|
||||||
m_MinPacingTime = (1000000LL*STREAMING_MTU)/outboundSpeed;
|
m_MinPacingTime = (1000000LL*STREAMING_MTU)/outboundSpeed;
|
||||||
|
|
||||||
|
auto inboundSpeed = local.GetOwner ()->GetStreamingInboundSpeed (); // for limit inbound speed
|
||||||
|
if (inboundSpeed)
|
||||||
|
m_PacketACKInterval = (1000000LL*STREAMING_MTU)/inboundSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local):
|
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local):
|
||||||
m_Service (service), m_SendStreamID (0), m_SequenceNumber (0),
|
m_Service (service), m_SendStreamID (0), m_SequenceNumber (0),
|
||||||
m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1),
|
m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1),
|
||||||
|
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
|
||||||
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
||||||
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true),
|
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true),
|
||||||
m_IsTimeOutResend (false), m_LocalDestination (local),
|
m_IsTimeOutResend (false), m_LocalDestination (local),
|
||||||
@ -98,12 +106,18 @@ namespace stream
|
|||||||
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowIncCounter (0),
|
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowIncCounter (0),
|
||||||
m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
||||||
m_PrevRTTSample (INITIAL_RTT), m_PrevRTT (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
|
m_PrevRTTSample (INITIAL_RTT), m_PrevRTT (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
|
||||||
m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_DropWindowDelayTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_DropWindowDelayTime (0),
|
||||||
|
m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed
|
||||||
|
m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
||||||
{
|
{
|
||||||
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
|
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
|
||||||
auto outboundSpeed = local.GetOwner ()->GetStreamingOutboundSpeed ();
|
auto outboundSpeed = local.GetOwner ()->GetStreamingOutboundSpeed ();
|
||||||
if (outboundSpeed)
|
if (outboundSpeed)
|
||||||
m_MinPacingTime = (1000000LL*STREAMING_MTU)/outboundSpeed;
|
m_MinPacingTime = (1000000LL*STREAMING_MTU)/outboundSpeed;
|
||||||
|
|
||||||
|
auto inboundSpeed = local.GetOwner ()->GetStreamingInboundSpeed (); // for limit inbound speed
|
||||||
|
if (inboundSpeed)
|
||||||
|
m_PacketACKInterval = (1000000LL*STREAMING_MTU)/inboundSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream::~Stream ()
|
Stream::~Stream ()
|
||||||
@ -754,10 +768,26 @@ namespace stream
|
|||||||
void Stream::SendQuickAck ()
|
void Stream::SendQuickAck ()
|
||||||
{
|
{
|
||||||
int32_t lastReceivedSeqn = m_LastReceivedSequenceNumber;
|
int32_t lastReceivedSeqn = m_LastReceivedSequenceNumber;
|
||||||
|
// for limit inbound speed
|
||||||
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
int numPackets = 0;
|
||||||
|
int64_t passedTime = m_PacketACKInterval * INITIAL_WINDOW_SIZE; // in microseconds // while m_LastACKSendTime == 0
|
||||||
|
if (m_LastACKSendTime)
|
||||||
|
passedTime = (ts - m_LastACKSendTime)*1000; // in microseconds
|
||||||
|
numPackets = (passedTime + m_PacketACKIntervalRem) / m_PacketACKInterval;
|
||||||
|
m_PacketACKIntervalRem = (passedTime + m_PacketACKIntervalRem) - (numPackets * m_PacketACKInterval);
|
||||||
|
if (m_LastConfirmedReceivedSequenceNumber + numPackets < m_LastReceivedSequenceNumber)
|
||||||
|
lastReceivedSeqn = m_LastConfirmedReceivedSequenceNumber + numPackets;
|
||||||
|
if (numPackets == 0) return;
|
||||||
|
// for limit inbound speed
|
||||||
if (!m_SavedPackets.empty ())
|
if (!m_SavedPackets.empty ())
|
||||||
{
|
{
|
||||||
int32_t seqn = (*m_SavedPackets.rbegin ())->GetSeqn ();
|
for (auto it: m_SavedPackets)
|
||||||
if (seqn > lastReceivedSeqn) lastReceivedSeqn = seqn;
|
{
|
||||||
|
auto seqn = it->GetSeqn ();
|
||||||
|
if (m_LastConfirmedReceivedSequenceNumber + numPackets < int(seqn)) break; // for limit inbound speed
|
||||||
|
if (seqn > lastReceivedSeqn) lastReceivedSeqn = seqn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (lastReceivedSeqn < 0)
|
if (lastReceivedSeqn < 0)
|
||||||
{
|
{
|
||||||
@ -786,6 +816,11 @@ namespace stream
|
|||||||
for (auto it: m_SavedPackets)
|
for (auto it: m_SavedPackets)
|
||||||
{
|
{
|
||||||
auto seqn = it->GetSeqn ();
|
auto seqn = it->GetSeqn ();
|
||||||
|
if (m_LastConfirmedReceivedSequenceNumber + numPackets < int(seqn)) // for limit inbound speed
|
||||||
|
{
|
||||||
|
htobe32buf (packet + 12, nextSeqn - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (numNacks + (seqn - nextSeqn) >= 256)
|
if (numNacks + (seqn - nextSeqn) >= 256)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Streaming: Number of NACKs exceeds 256. seqn=", seqn, " nextSeqn=", nextSeqn);
|
LogPrint (eLogError, "Streaming: Number of NACKs exceeds 256. seqn=", seqn, " nextSeqn=", nextSeqn);
|
||||||
@ -827,6 +862,8 @@ namespace stream
|
|||||||
p.len = size;
|
p.len = size;
|
||||||
|
|
||||||
SendPackets (std::vector<Packet *> { &p });
|
SendPackets (std::vector<Packet *> { &p });
|
||||||
|
m_LastACKSendTime = ts; // for limit inbound speed
|
||||||
|
m_LastConfirmedReceivedSequenceNumber = lastReceivedSeqn; // for limit inbound speed
|
||||||
LogPrint (eLogDebug, "Streaming: Quick Ack sent. ", (int)numNacks, " NACKs");
|
LogPrint (eLogDebug, "Streaming: Quick Ack sent. ", (int)numNacks, " NACKs");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +249,7 @@ namespace stream
|
|||||||
uint32_t m_TunnelsChangeSequenceNumber;
|
uint32_t m_TunnelsChangeSequenceNumber;
|
||||||
int32_t m_LastReceivedSequenceNumber;
|
int32_t m_LastReceivedSequenceNumber;
|
||||||
int32_t m_PreviousReceivedSequenceNumber;
|
int32_t m_PreviousReceivedSequenceNumber;
|
||||||
|
int32_t m_LastConfirmedReceivedSequenceNumber; // for limit inbound speed
|
||||||
StreamStatus m_Status;
|
StreamStatus m_Status;
|
||||||
bool m_IsAckSendScheduled;
|
bool m_IsAckSendScheduled;
|
||||||
bool m_IsNAcked;
|
bool m_IsNAcked;
|
||||||
@ -277,6 +278,7 @@ namespace stream
|
|||||||
float m_WindowSize, m_LastWindowDropSize;
|
float m_WindowSize, m_LastWindowDropSize;
|
||||||
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample, m_PrevRTT, m_Jitter;
|
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample, m_PrevRTT, m_Jitter;
|
||||||
uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, m_DropWindowDelayTime, m_LastSendTime; // microseconds
|
uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, m_DropWindowDelayTime, m_LastSendTime; // microseconds
|
||||||
|
uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed
|
||||||
int m_NumResendAttempts, m_NumPacketsToSend;
|
int m_NumResendAttempts, m_NumPacketsToSend;
|
||||||
size_t m_MTU;
|
size_t m_MTU;
|
||||||
};
|
};
|
||||||
|
@ -472,6 +472,7 @@ namespace client
|
|||||||
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_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);
|
options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY);
|
||||||
options[I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, DEFAULT_MAX_OUTBOUND_SPEED);
|
options[I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED, DEFAULT_MAX_OUTBOUND_SPEED);
|
||||||
|
options[I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED);
|
||||||
options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false);
|
options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false);
|
||||||
options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE);
|
options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE);
|
||||||
std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "0,4");
|
std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "0,4");
|
||||||
|
Loading…
Reference in New Issue
Block a user