From 42e9a4ebf04d3a21051ea9d76378b0dc13fad5c3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 4 Feb 2016 13:43:50 -0800 Subject: [PATCH] fix ATP SendQueue failure to receive after re-activity --- libraries/networking/src/udt/Connection.cpp | 10 +++++++++- libraries/networking/src/udt/Connection.h | 2 ++ libraries/networking/src/udt/SendQueue.cpp | 13 ++++++++----- libraries/networking/src/udt/SendQueue.h | 7 ++++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index e63d44e72f..3b5b26d05d 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -82,8 +82,12 @@ void Connection::resetRTT() { SendQueue& Connection::getSendQueue() { if (!_sendQueue) { + + // we may have a sequence number from the previous inactive queue - re-use that so that the + // receiver is getting the sequence numbers it expects (given that the connection must still be active) + // Lasily create send queue - _sendQueue = SendQueue::create(_parentSocket, _destination); + _sendQueue = SendQueue::create(_parentSocket, _destination, _inactiveSendQueueSequenceNumber); #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Created SendQueue for connection to" << _destination; @@ -105,6 +109,10 @@ SendQueue& Connection::getSendQueue() { } void Connection::queueInactive() { + // get the current sequence number from the send queue, this is to be re-used if the send + // queue is re-activated for this connection + _inactiveSendQueueSequenceNumber = _sendQueue->getCurrentSequenceNumber(); + // tell our current send queue to go down and reset our ptr to it to null stopSendQueue(); diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index f8c4acd7d9..b58b7ec570 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -139,6 +139,8 @@ private: SequenceNumber _lastSentACK; // The last sent ACK SequenceNumber _lastSentACK2; // The last sent ACK sub-sequence number in an ACK2 + + SequenceNumber _inactiveSendQueueSequenceNumber { 0 }; int _acksDuringSYN { 1 }; // The number of non-SYN ACKs sent during SYN int _lightACKsDuringSYN { 1 }; // The number of lite ACKs sent during SYN interval diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index ba99efdcea..4d6e431b45 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -52,11 +52,11 @@ private: Mutex2& _mutex2; }; -std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination) { +std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber) { Q_ASSERT_X(socket, "SendQueue::create", "Must be called with a valid Socket*"); - auto queue = std::unique_ptr(new SendQueue(socket, destination)); - + auto queue = std::unique_ptr(new SendQueue(socket, destination, currentSequenceNumber)); + // Setup queue private thread QThread* thread = new QThread; thread->setObjectName("Networking: SendQueue " + destination.objectName()); // Name thread for easier debug @@ -74,10 +74,12 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin return queue; } -SendQueue::SendQueue(Socket* socket, HifiSockAddr dest) : +SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber) : _socket(socket), - _destination(dest) + _destination(dest), + _currentSequenceNumber(currentSequenceNumber) { + } void SendQueue::queuePacket(std::unique_ptr packet) { @@ -389,6 +391,7 @@ bool SendQueue::isInactive(bool sentAPacket) { static const int NUM_TIMEOUTS_BEFORE_INACTIVE = 16; static const int MIN_SECONDS_BEFORE_INACTIVE_MS = 5 * 1000; if (_timeoutExpiryCount >= NUM_TIMEOUTS_BEFORE_INACTIVE && + _lastReceiverResponse > 0 && (QDateTime::currentMSecsSinceEpoch() - _lastReceiverResponse) > MIN_SECONDS_BEFORE_INACTIVE_MS) { // If the flow window has been full for over CONSIDER_INACTIVE_AFTER, // then signal the queue is inactive and return so it can be cleaned up diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 3fe4006139..5428e7a26d 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -50,7 +50,8 @@ public: Stopped }; - static std::unique_ptr create(Socket* socket, HifiSockAddr destination); + static std::unique_ptr create(Socket* socket, HifiSockAddr destination, + SequenceNumber currentSequenceNumber = SequenceNumber()); void queuePacket(std::unique_ptr packet); void queuePacketList(std::unique_ptr packetList); @@ -83,7 +84,7 @@ private slots: void run(); private: - SendQueue(Socket* socket, HifiSockAddr dest); + SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber); SendQueue(SendQueue& other) = delete; SendQueue(SendQueue&& other) = delete; @@ -108,7 +109,7 @@ private: std::atomic _lastACKSequenceNumber { 0 }; // Last ACKed sequence number - SequenceNumber _currentSequenceNumber; // Last sequence number sent out + SequenceNumber _currentSequenceNumber { 0 }; // Last sequence number sent out std::atomic _atomicCurrentSequenceNumber { 0 }; // Atomic for last sequence number sent out std::atomic _packetSendPeriod { 0 }; // Interval between two packet send event in microseconds, set from CC