cap RX buffers in UDP rather than callers

This commit is contained in:
JackDoan
2026-07-31 13:58:52 -05:00
parent d7bcfb5d6b
commit bc70bf47f8
7 changed files with 15 additions and 8 deletions
+1 -1
View File
@@ -195,7 +195,7 @@ func (u *StdConn) ListenOut(r EncReader, flush func()) error {
continue
}
r(netip.AddrPortFrom(rua.Addr().Unmap(), rua.Port()), buffer[:n])
r(netip.AddrPortFrom(rua.Addr().Unmap(), rua.Port()), buffer[:n:n])
flush()
}
}
+1 -1
View File
@@ -106,7 +106,7 @@ func (u *GenericConn) ListenOut(r EncReader, flush func()) error {
continue
}
r(netip.AddrPortFrom(rua.Addr().Unmap(), rua.Port()), buffer[:n])
r(netip.AddrPortFrom(rua.Addr().Unmap(), rua.Port()), buffer[:n:n])
flush()
}
}
+2 -2
View File
@@ -305,7 +305,7 @@ func (u *StdConn) ListenOut(r EncReader, flush func()) error {
// deliverSegments hands a received superdatagram to r, splitting it back into pre-coalesce packets
func deliverSegments(r EncReader, from netip.AddrPort, payload []byte, segSize int) {
if segSize <= 0 || segSize >= len(payload) { //avoid bogus values
r(from, payload)
r(from, payload[:len(payload):len(payload)])
return
}
for off := 0; off < len(payload); off += segSize {
@@ -313,7 +313,7 @@ func deliverSegments(r EncReader, from netip.AddrPort, payload []byte, segSize i
if end > len(payload) {
end = len(payload)
}
r(from, payload[off:end])
r(from, payload[off:end:end])
}
}
+8 -1
View File
@@ -210,8 +210,10 @@ func TestParseRecvCmsgCorruptLenNoPanic(t *testing.T) {
// error here shreds encrypted packets and every decrypt downstream fails.
func TestDeliverSegments(t *testing.T) {
from := netip.MustParseAddrPort("192.0.2.1:4242")
// Spare backing capacity mimics the recvmmsg row a real payload sits in;
// the cap checks below prove none of it leaks to a delivered segment.
pay := func(n int) []byte {
b := make([]byte, n)
b := make([]byte, n, n+512)
for i := range b {
b[i] = byte(i)
}
@@ -262,6 +264,11 @@ func TestDeliverSegments(t *testing.T) {
if len(seg) != wantLens[i] {
t.Fatalf("segment %d len=%d want %d", i, len(seg), wantLens[i])
}
if cap(seg) != len(seg) {
// EncReader contract: an append into spare capacity would
// scribble into the next segment of the shared row.
t.Errorf("segment %d cap=%d, want %d (capacity must not reach into the row)", i, cap(seg), len(seg))
}
if len(seg) > 0 && &seg[0] != &c.payload[off] {
t.Errorf("segment %d does not alias payload at offset %d", i, off)
}
+1 -1
View File
@@ -161,7 +161,7 @@ func (u *RIOConn) ListenOut(r EncReader, flush func()) error {
continue
}
r(netip.AddrPortFrom(netip.AddrFrom16(rua.Addr).Unmap(), (rua.Port>>8)|((rua.Port&0xff)<<8)), buffer[:n])
r(netip.AddrPortFrom(netip.AddrFrom16(rua.Addr).Unmap(), (rua.Port>>8)|((rua.Port&0xff)<<8)), buffer[:n:n])
flush()
}
}
+1 -1
View File
@@ -189,7 +189,7 @@ func (u *TesterConn) ListenOut(r EncReader, flush func()) error {
case <-u.done:
return os.ErrClosed
case p := <-u.RxPackets:
r(p.From, p.Data)
r(p.From, p.Data[:len(p.Data):len(p.Data)])
// The batcher borrows plaintext decrypted in place inside p.Data
// until Flush, so the packet must stay alive across flush()
flush()