From e74f47b64c4467b9af16b25b09428e44e782662a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 31 Jul 2015 18:13:11 -0700 Subject: [PATCH] use a list of pairs of pairs for ACK2 --- libraries/networking/src/udt/Connection.cpp | 48 +++++++++++++-------- libraries/networking/src/udt/Connection.h | 6 ++- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 56fc1292b6..62336a31ae 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -161,8 +161,11 @@ void Connection::sendACK(bool wasCausedBySyncTimeout) { // have the socket send off our packet _parentSocket->writeBasePacket(*ackPacket, _destination); + Q_ASSERT_X(_sentACKs.empty() || _sentACKs.back().first + 1 == _currentACKSubSequenceNumber, + "Connection::sendACK", "Adding an invalid ACK to _sentACKs"); + // write this ACK to the map of sent ACKs - _sentACKs[_currentACKSubSequenceNumber] = { nextACKNumber, high_resolution_clock::now() }; + _sentACKs.push_back({ _currentACKSubSequenceNumber, { nextACKNumber, high_resolution_clock::now() }}); // reset the number of data packets received since last ACK _packetsSinceACK = 0; @@ -372,7 +375,7 @@ void Connection::processACK(std::unique_ptr controlPacket) { // read the ACKed sequence number SequenceNumber ack; controlPacket->readPrimitive(&ack); - + // validate that this isn't a BS ACK if (ack > getSendQueue().getCurrentSequenceNumber()) { // in UDT they specifically break the connection here - do we want to do anything? @@ -463,23 +466,32 @@ void Connection::processACK2(std::unique_ptr controlPacket) { controlPacket->readPrimitive(&subSequenceNumber); // check if we had that subsequence number in our map - auto it = _sentACKs.find(subSequenceNumber); + auto it = std::find_if_not(_sentACKs.begin(), _sentACKs.end(), [subSequenceNumber](const ACKListPair& pair){ + return subSequenceNumber < pair.first; + }); + if (it != _sentACKs.end()) { - // update the RTT using the ACK window - SequenceNumberTimePair& pair = it->second; - - // calculate the RTT (time now - time ACK sent) - auto now = high_resolution_clock::now(); - int rtt = duration_cast(now - pair.second).count(); - - updateRTT(rtt); - - // set the RTT for congestion control - _congestionControl->setRTT(_rtt); - - // update the last ACKed ACK - if (pair.first > _lastReceivedAcknowledgedACK) { - _lastReceivedAcknowledgedACK = pair.first; + if (it->first == subSequenceNumber){ + // update the RTT using the ACK window + + // calculate the RTT (time now - time ACK sent) + auto now = high_resolution_clock::now(); + int rtt = duration_cast(now - it->second.second).count(); + + updateRTT(rtt); + + // set the RTT for congestion control + _congestionControl->setRTT(_rtt); + + // update the last ACKed ACK + if (it->second.first > _lastReceivedAcknowledgedACK) { + _lastReceivedAcknowledgedACK = it->second.first; + } + + // erase this sub-sequence number and anything below it now that we've gotten our timing information + _sentACKs.erase(_sentACKs.begin(), it); + } else { + Q_UNREACHABLE(); } } diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index 23a77bf4db..dd86f9bc5b 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -13,6 +13,7 @@ #define hifi_Connection_h #include +#include #include #include @@ -35,7 +36,8 @@ class Connection : public QObject { Q_OBJECT public: using SequenceNumberTimePair = std::pair; - using SentACKMap = std::unordered_map; + using ACKListPair = std::pair; + using SentACKList = std::list; Connection(Socket* parentSocket, HifiSockAddr destination, std::unique_ptr congestionControl); ~Connection(); @@ -100,7 +102,7 @@ private: int _bandwidth { 1 }; // Exponential moving average for estimated bandwidth, in packets per second int _deliveryRate { 16 }; // Exponential moving average for receiver's receive rate, in packets per second - SentACKMap _sentACKs; // Map of ACK sub-sequence numbers to ACKed sequence number and sent time + SentACKList _sentACKs; // Map of ACK sub-sequence numbers to ACKed sequence number and sent time Socket* _parentSocket { nullptr }; HifiSockAddr _destination;