From 6b3a2c429cdd31aa3e5100acb9bfaf65a96162ee Mon Sep 17 00:00:00 2001 From: Patricio Whittingslow Date: Mon, 27 Oct 2025 00:23:57 -0300 Subject: [PATCH] found failing case for multipacket --- tcp/conn.go | 2 ++ tcp/handler.go | 5 +++++ x/xnet/xnet_test.go | 21 ++++++++++++++------- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/tcp/conn.go b/tcp/conn.go index 3aa2b41..4c6d8d4 100644 --- a/tcp/conn.go +++ b/tcp/conn.go @@ -69,6 +69,8 @@ func (conn *Conn) State() State { return conn.h.State() } // and available to read via a [Conn.Read] call. func (conn *Conn) BufferedInput() int { return conn.h.BufferedInput() } +func (conn *Conn) AvailableInput() int { return conn.h.FreeRx() } + // AvailableOutput returns amount of bytes available to write to output // before [Conn.Write] returns an error due to insufficient space to store outgoing data. func (conn *Conn) AvailableOutput() int { return conn.h.AvailableOutput() } diff --git a/tcp/handler.go b/tcp/handler.go index a43e63e..af9eb9e 100644 --- a/tcp/handler.go +++ b/tcp/handler.go @@ -290,6 +290,11 @@ func (h *Handler) FreeTx() int { return h.bufTx.Free() } +// FreeRx returns the amount of space free in the receive buffer. +func (h *Handler) FreeRx() int { + return h.bufRx.Free() +} + // SizeRx returns the size of the TCP receive ring buffer. func (h *Handler) SizeRx() int { return h.bufRx.Size() diff --git a/x/xnet/xnet_test.go b/x/xnet/xnet_test.go index 6c3930a..95449b7 100644 --- a/x/xnet/xnet_test.go +++ b/x/xnet/xnet_test.go @@ -22,7 +22,8 @@ func TestStackAsyncTCP_multipacket(t *testing.T) { const seed = 1234 const MTU = 1500 const svPort = 8080 - const maxPkt = 30 + const maxPktLen = 30 + const maxNPkt = 32 client, sv, clconn, svconn := newTCPStacks(t, seed, MTU) tst := tester{ t: t, buf: make([]byte, MTU), @@ -34,10 +35,13 @@ func TestStackAsyncTCP_multipacket(t *testing.T) { tst.TestTCPClose(client, sv, clconn, svconn) var buf [MTU]byte for i := 0; i < 30; i++ { - payloadSize := rng.Intn(maxPkt) + 1 + payloadSize := rng.Intn(maxPktLen) + 1 tst.TestTCPSetupAndEstablish(sv, client, svconn, clconn, svPort, 1337) - a, _ := rng.Read(buf[:payloadSize]) - tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a]) + npkt := rng.Intn(maxNPkt-1) + 2 + for ipkt := 0; ipkt < npkt; ipkt++ { + a, _ := rng.Read(buf[:payloadSize]) + tst.TestTCPEstablishedSingleData(sv, client, svconn, clconn, buf[:a]) + } tst.TestTCPClose(client, sv, clconn, svconn) if t.Failed() { t.FailNow() @@ -180,11 +184,14 @@ func (tst *tester) TestTCPHandshake(stack1, stack2 *StackAsync) { func (tst *tester) TestTCPEstablishedSingleData(srcStack, dstStack *StackAsync, srcConn, dstConn *tcp.Conn, sendData []byte) { t := tst.t t.Helper() - avail := srcConn.AvailableOutput() - if avail < len(sendData) { - t.Fatal("insufficient space for write call", avail, len(sendData)) + availTx := srcConn.AvailableOutput() + availRx := dstConn.AvailableInput() + if availTx < len(sendData) { + t.Fatal("insufficient space for write call", availTx, len(sendData)) } else if len(sendData) <= 0 { panic("empty data!") + } else if availRx < len(sendData) { + t.Fatal("insufficient space for dst read call", availRx, len(sendData)) } _, err := srcConn.Write(sendData) if err != nil {