mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 01:59:59 +02:00
use microseconds for intervals, setup timeout NAKs
This commit is contained in:
parent
09a497a59b
commit
74b0fa7e87
3 changed files with 60 additions and 11 deletions
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "Connection.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#include "../HifiSockAddr.h"
|
||||
#include "ControlPacket.h"
|
||||
#include "Packet.h"
|
||||
|
@ -37,6 +39,28 @@ void Connection::sendReliablePacket(unique_ptr<Packet> packet) {
|
|||
_sendQueue->queuePacket(move(packet));
|
||||
}
|
||||
|
||||
void Connection::sync() {
|
||||
// we send out a periodic ACK every rate control interval
|
||||
sendACK();
|
||||
|
||||
// check if we need to re-transmit a loss list
|
||||
// we do this if it has been longer than the current nakInterval since we last sent
|
||||
auto now = high_resolution_clock::now();
|
||||
|
||||
if (duration_cast<milliseconds>(now - _lastNAKTime).count() >= _nakInterval) {
|
||||
// construct a NAK packet that will hold all of the lost sequence numbers
|
||||
auto lossListPacket = ControlPacket::create(ControlPacket::NAK, _lossList.getLength() * sizeof(SequenceNumber));
|
||||
|
||||
|
||||
|
||||
// have our SendQueue send off this control packet
|
||||
_sendQueue->sendPacket(*lossListPacket);
|
||||
|
||||
_lastNAKTime = high_resolution_clock::now();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Connection::sendACK(bool wasCausedBySyncTimeout) {
|
||||
static const int ACK_PACKET_PAYLOAD_BYTES = sizeof(_lastSentACK) + sizeof(_currentACKSubSequenceNumber)
|
||||
+ sizeof(_rtt) + sizeof(int32_t) + sizeof(int32_t);
|
||||
|
@ -65,10 +89,10 @@ void Connection::sendACK(bool wasCausedBySyncTimeout) {
|
|||
|
||||
} else if (nextACKNumber == _lastSentACK) {
|
||||
// We already sent this ACK, but check if we should re-send it.
|
||||
// We will re-send if it has been more than RTT + (4 * RTT variance) since the last ACK
|
||||
milliseconds sinceLastACK = duration_cast<milliseconds>(currentTime - lastACKSendTime);
|
||||
// We will re-send if it has been more than the estimated timeout since the last ACK
|
||||
microseconds sinceLastACK = duration_cast<microseconds>(currentTime - lastACKSendTime);
|
||||
|
||||
if (sinceLastACK.count() < (_rtt + (4 * _rttVariance))) {
|
||||
if (sinceLastACK.count() < estimatedTimeout()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -162,6 +186,23 @@ void Connection::processReceivedSequenceNumber(SequenceNumber seq) {
|
|||
|
||||
// have the send queue send off our packet immediately
|
||||
_sendQueue->sendPacket(*lossReport);
|
||||
|
||||
// record our last NAK time
|
||||
_lastNAKTime = high_resolution_clock::now();
|
||||
|
||||
// figure out when we should send the next loss report, if we haven't heard anything back
|
||||
_nakInterval = (_rtt + 4 * _rttVariance);
|
||||
|
||||
int receivedPacketsPerSecond = _receiveWindow.getPacketReceiveSpeed();
|
||||
if (receivedPacketsPerSecond > 0) {
|
||||
// the NAK interval is at least the _minNAKInterval
|
||||
// but might be the time required for all lost packets to be retransmitted
|
||||
_nakInterval = std::max((int) (_lossList.getLength() * (USECS_PER_SECOND / receivedPacketsPerSecond)),
|
||||
_minNAKInterval);
|
||||
} else {
|
||||
// the NAK interval is at least the _minNAKInterval but might be the estimated timeout
|
||||
_nakInterval = std::max(estimatedTimeout(), _minNAKInterval);
|
||||
}
|
||||
}
|
||||
|
||||
if (seq > _lastReceivedSequenceNumber) {
|
||||
|
@ -202,7 +243,7 @@ void Connection::processACK(std::unique_ptr<ControlPacket> controlPacket) {
|
|||
auto currentTime = high_resolution_clock::now();
|
||||
static high_resolution_clock::time_point lastACK2SendTime;
|
||||
|
||||
milliseconds sinceLastACK2 = duration_cast<milliseconds>(currentTime - lastACK2SendTime);
|
||||
microseconds sinceLastACK2 = duration_cast<microseconds>(currentTime - lastACK2SendTime);
|
||||
|
||||
if (sinceLastACK2.count() > _synInterval || currentACKSubSequenceNumber == _lastSentACK2) {
|
||||
// setup a static ACK2 packet we will re-use
|
||||
|
@ -304,7 +345,7 @@ void Connection::processACK2(std::unique_ptr<ControlPacket> controlPacket) {
|
|||
|
||||
// calculate the RTT (time now - time ACK sent)
|
||||
auto now = high_resolution_clock::now();
|
||||
int rtt = duration_cast<milliseconds>(now - pair.second).count();
|
||||
int rtt = duration_cast<microseconds>(now - pair.second).count();
|
||||
|
||||
updateRTT(rtt);
|
||||
|
||||
|
|
|
@ -35,9 +35,8 @@ public:
|
|||
Connection(Socket* parentSocket, HifiSockAddr destination);
|
||||
|
||||
void sendReliablePacket(std::unique_ptr<Packet> packet);
|
||||
|
||||
void sendACK(bool wasCausedBySyncTimeout = true);
|
||||
void sendLightACK() const;
|
||||
|
||||
void sync(); // rate control method, fired by Socket for all connections on SYN interval
|
||||
|
||||
SequenceNumber nextACK() const;
|
||||
|
||||
|
@ -47,6 +46,9 @@ public:
|
|||
void processControl(std::unique_ptr<ControlPacket> controlPacket);
|
||||
|
||||
private:
|
||||
void sendACK(bool wasCausedBySyncTimeout = true);
|
||||
void sendLightACK() const;
|
||||
|
||||
void processACK(std::unique_ptr<ControlPacket> controlPacket);
|
||||
void processLightACK(std::unique_ptr<ControlPacket> controlPacket);
|
||||
void processACK2(std::unique_ptr<ControlPacket> controlPacket);
|
||||
|
@ -54,7 +56,13 @@ private:
|
|||
|
||||
void updateRTT(int rtt);
|
||||
|
||||
int _synInterval; // Periodical Rate Control Interval, defaults to 10ms
|
||||
int estimatedTimeout() const { return _rtt + _rttVariance * 4; }
|
||||
|
||||
int _synInterval; // Periodical Rate Control Interval, in microseconds, defaults to 10ms
|
||||
|
||||
int _nakInterval; // NAK timeout interval, in microseconds
|
||||
int _minNAKInterval { 100000 }; // NAK timeout interval lower bound, default of 100ms
|
||||
std::chrono::high_resolution_clock::time_point _lastNAKTime;
|
||||
|
||||
LossList _lossList; // List of all missing packets
|
||||
SequenceNumber _lastReceivedSequenceNumber { SequenceNumber::MAX }; // The largest sequence number received from the peer
|
||||
|
@ -68,7 +76,7 @@ private:
|
|||
|
||||
int _totalReceivedACKs { 0 };
|
||||
|
||||
int32_t _rtt; // RTT, in milliseconds
|
||||
int32_t _rtt; // RTT, in microseconds
|
||||
int32_t _rttVariance; // RTT variance
|
||||
int _flowWindowSize; // Flow control window size
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ void Socket::rateControlSync() {
|
|||
|
||||
// enumerate our list of connections and ask each of them to send off periodic ACK packet for rate control
|
||||
for (auto& connection : _connectionsHash) {
|
||||
connection.second->sendACK();
|
||||
connection.second->sync();
|
||||
}
|
||||
|
||||
if (_synTimer.interval() != _synInterval) {
|
||||
|
|
Loading…
Reference in a new issue