From bc59445542e91ea3461a8f7671883a877ab71dba Mon Sep 17 00:00:00 2001
From: Deuce <shurd@sasktel.net>
Date: Wed, 2 Dec 2020 15:44:16 -0500
Subject: [PATCH] Perform super-graceful shutdown of the socket on success.

This should guard against a RST being sent on success.  It's possible
that the remote has sent data (ie: M_EOB) we would recv() after we
commit to ending the session.  If the script terminates while there
is data to be read, this would result in sending a RST.

To prevent this, we call shutdown(sock, SHUT_WR) via setting is_writeable
to false (because that's how we roll), then recv() all data until the
remote closes the session, or the timeout passes.
---
 exec/load/binkp.js | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/exec/load/binkp.js b/exec/load/binkp.js
index 1087e277c6..3cf4df88ce 100644
--- a/exec/load/binkp.js
+++ b/exec/load/binkp.js
@@ -1,4 +1,4 @@
-const binkp_revision = 2;
+const binkp_revision = 3;
 
 require('sockdefs.js', 'SOCK_STREAM');
 require('fido.js', 'FIDO');
@@ -916,6 +916,8 @@ BinkP.prototype.session = function()
 BinkP.prototype.close = function()
 {
 	var i;
+	var end;
+	var remain;
 
 	// Send an ERR and close.
 	this.ack_file();
@@ -937,6 +939,16 @@ BinkP.prototype.close = function()
 			if (this.senteob < 1)
 				this.sendCmd(this.command.M_EOB);
 		}
+		// Attempt a super-duper graceful shutdown to prevent RST...
+		this.sock.is_writeable = false;
+		remain = this.timeout;
+		end = time() + remain;
+		do {
+			if (this.sock.recv(2048, remain) == 0)
+				break;
+			remain = end - time();
+		} while (remain > 0);
+		this.sock.close();
 	}
 	this.tx_queue.forEach(function(file) {
 		file.file.close();
-- 
GitLab