⛏️ index : haiku.git

author Jérôme Duval <jerome.duval@gmail.com> 2025-12-04 13:28:37.0 +01:00:00
committer Adrien Destugues <pulkomandy@pulkomandy.tk> 2025-12-09 10:14:36.0 +00:00:00
commit
9d587f4f3fb2573dc24f36a21398544161d535a7 [patch]
tree
e5ca99f5b39e4d0711bec8bcbcd7261116683fa4
parent
5860e2c161f4a3ba48943cde1dcb4c02fa8820e8
download
9d587f4f3fb2573dc24f36a21398544161d535a7.tar.gz

tcp: send RST instead of FIN, when user closed and received data get lost

this is the abort way of closing a connection.
tested with golang's http test TestTransportGzip. All TestTransport* pass.

Change-Id: Ib79516eb8a16480d7a4425675748ff76554e9c6c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10054
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>

Diff

 src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
index 20436e4..974c168 100644
--- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
+++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp
@@ -323,7 +323,8 @@
	FLAG_RECOVERY				= 0x40,
	FLAG_OPTION_SACK_PERMITTED	= 0x80,
	FLAG_AUTO_RECEIVE_BUFFER_SIZE = 0x100,
	FLAG_CAN_NOTIFY 			= 0x200
	FLAG_CAN_NOTIFY 			= 0x200,
	FLAG_USER_CLOSED			= 0x400
};


@@ -821,7 +822,7 @@

	TRACE("SendData(buffer %p, size %" B_PRIu32 ", flags %#" B_PRIx32
		") [total %" B_PRIuSIZE " bytes, has %" B_PRIuSIZE "]", buffer,
		buffer->size, buffer->flags, fSendQueue.Size(), fSendQueue.Free());
		buffer->size, buffer->msg_flags, fSendQueue.Size(), fSendQueue.Free());
	T(APICall(this, "senddata"));

	const uint32 flags = buffer->msg_flags;
@@ -1222,9 +1223,14 @@
{
	tcp_state previousState = fState;

	if (fState == SYNCHRONIZE_RECEIVED || fState == ESTABLISHED)
	if (fState == SYNCHRONIZE_RECEIVED || fState == ESTABLISHED) {
		// We "should send a RST if there is any unread received data,
		// or if any new data is received" (RFC 2525 § 2.16). This
		// isn't a TCP state, so use a flag.
		if (closing && fReceiveQueue.Available() > 0)
			fFlags |= FLAG_USER_CLOSED;
		fState = FINISH_SENT;
	else if (fState == FINISH_RECEIVED)
	} else if (fState == FINISH_RECEIVED)
		fState = WAIT_FOR_FINISH_ACKNOWLEDGE;
	else
		return B_OK;
@@ -1238,6 +1244,9 @@
		return status;
	}

	if ((fFlags & FLAG_USER_CLOSED) != 0)
		fState = CLOSED;

	return B_OK;
}

@@ -2344,7 +2353,7 @@

		if ((fSendNext + segmentLength) == fSendQueue.LastSequence() && !force) {
			if (state_needs_finish(fState))
				segment.flags |= TCP_FLAG_FINISH;
				segment.flags |= (fFlags & FLAG_USER_CLOSED) != 0 ? TCP_FLAG_RESET : TCP_FLAG_FINISH;
			if (length > 0)
				segment.flags |= TCP_FLAG_PUSH;
		}