From 676d2702b748471856cc36cae2d3c1ee4be27dc7 Mon Sep 17 00:00:00 2001
From: Cory McWilliams <cory@unprompted.com>
Date: Fri, 11 Apr 2025 19:29:10 -0400
Subject: [PATCH] ssb: Read back-pressure on a tunnel connection affects the
 parent connection.  This was causing spurrious disconnects.

---
 src/ssb.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/src/ssb.c b/src/ssb.c
index 5830ee77c..c1dbd1dbf 100644
--- a/src/ssb.c
+++ b/src/ssb.c
@@ -37,6 +37,8 @@
 #define PRE_CALLBACK(ssb, cb) uint64_t pre_callback_hrtime_ns = _tf_ssb_callback_pre(ssb)
 #define POST_CALLBACK(ssb, cb) _tf_ssb_callback_post(ssb, cb, pre_callback_hrtime_ns)
 
+const int k_read_back_pressure_threshold = 256;
+
 static_assert(k_id_base64_len == sodium_base64_ENCODED_LEN(9 + crypto_box_PUBLICKEYBYTES, sodium_base64_VARIANT_ORIGINAL), "k_id_base64_len");
 static_assert(k_id_bin_len == crypto_box_PUBLICKEYBYTES, "k_id_bin_len");
 static_assert(k_blob_id_len == (sodium_base64_ENCODED_LEN(crypto_hash_sha256_BYTES, sodium_base64_VARIANT_ORIGINAL) + 8), "k_blob_id_len");
@@ -2080,6 +2082,11 @@ static void _tf_ssb_connection_destroy(tf_ssb_connection_t* connection, const ch
 		JS_SetOpaque(object, NULL);
 		JS_FreeValue(ssb->context, object);
 	}
+	if (connection->read_back_pressure >= k_read_back_pressure_threshold && connection->tunnel_connection)
+	{
+		tf_ssb_connection_adjust_read_backpressure(connection->tunnel_connection, -1);
+		connection->read_back_pressure = 0;
+	}
 	if (connection->async.data && !uv_is_closing((uv_handle_t*)&connection->async))
 	{
 		uv_close((uv_handle_t*)&connection->async, _tf_ssb_connection_on_close);
@@ -4555,19 +4562,32 @@ JSValue tf_ssb_connection_requests_to_object(tf_ssb_connection_t* connection)
 
 void tf_ssb_connection_adjust_read_backpressure(tf_ssb_connection_t* connection, int delta)
 {
-	const int k_threshold = 256;
 	int old_pressure = connection->read_back_pressure;
 	connection->read_back_pressure += delta;
 	if (!connection->is_closing)
 	{
 		uv_async_send(&connection->scheduled_async);
-		if (old_pressure < k_threshold && connection->read_back_pressure >= k_threshold)
+		if (old_pressure < k_read_back_pressure_threshold && connection->read_back_pressure >= k_read_back_pressure_threshold)
 		{
-			_tf_ssb_connection_read_stop(connection);
+			if (connection->tunnel_connection)
+			{
+				tf_ssb_connection_adjust_read_backpressure(connection->tunnel_connection, 1);
+			}
+			else
+			{
+				_tf_ssb_connection_read_stop(connection);
+			}
 		}
-		else if (old_pressure >= k_threshold && connection->read_back_pressure < k_threshold)
+		else if (old_pressure >= k_read_back_pressure_threshold && connection->read_back_pressure < k_read_back_pressure_threshold)
 		{
-			_tf_ssb_connection_read_start(connection);
+			if (connection->tunnel_connection)
+			{
+				tf_ssb_connection_adjust_read_backpressure(connection->tunnel_connection, -1);
+			}
+			else
+			{
+				_tf_ssb_connection_read_start(connection);
+			}
 		}
 	}
 	connection->ref_count += delta;