From 817859ce7658b30f8a4f76b6e260b4ed7ab147a4 Mon Sep 17 00:00:00 2001 From: michau-krakow <> Date: Mon, 27 Feb 2023 13:39:28 +0100 Subject: [PATCH] Delay socket close so to re-send final ACK if needed. Socket will be closed on the next retransmission timer expiry --- lib/protocol/reader.js | 16 ++++++++++++---- lib/streams/server/get-stream.js | 3 +++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/protocol/reader.js b/lib/protocol/reader.js index a4c3a95..78d18aa 100644 --- a/lib/protocol/reader.js +++ b/lib/protocol/reader.js @@ -33,6 +33,10 @@ var Reader = module.exports = function (Super, args){ return a.block - b.block; }; this._restransmitterStartFn = function (){ + if (me._noMoreData) { + return me._close(); + } + var block = me._blockToRetransmit (); if (block > 0){ //Update the window and emit back to the client the data @@ -157,7 +161,9 @@ Reader.prototype._notifyWindow = function (block){ if (this._lastReceived){ this._noMoreData = true; - return this._close (); + // RFC 1350 section 6: On the other hand, delaying is encouraged. This means that the host sending the final + // ACK will wait for a while before terminating in order to retransmit the final ACK if it has been lost + return this.onFinished(); } this._pending = this._windowSize; @@ -168,9 +174,11 @@ Reader.prototype._notifyWindow = function (block){ }; Reader.prototype._onData = function (message){ - //DATA packet received after sending the last packet, the socket will be - //closed in the next tick - if (this._noMoreData) return; + //DATA packet received after sending the last packet, the socket is delay-closed so just ACK the client + if (this._noMoreData) { + this._sendAck(message.block); + return; + } if (message.block === 0 && this._rolloverFix === 0){ //The server has rollovered to 0 diff --git a/lib/streams/server/get-stream.js b/lib/streams/server/get-stream.js index e695742..a2e5693 100644 --- a/lib/streams/server/get-stream.js +++ b/lib/streams/server/get-stream.js @@ -91,6 +91,9 @@ GetStream.prototype._createReader = function (helper, message, globalOptions){ me.emit ("close"); me.emit ("abort"); }; + this._reader.onFinished = function () { + me.push (null); // Closes the stream, but not the Reader + }; this._reader.onClose = function (){ delete me._currFiles.put[me.file]; me.emit ("close");