changes to TCP stack to enable xnet functionality

This commit is contained in:
soypat
2025-08-16 15:17:46 -03:00
parent c2995383da
commit 9cf4e35d2e
10 changed files with 124 additions and 19 deletions
+34 -1
View File
@@ -2,6 +2,7 @@ package xnet
import (
"errors"
"io"
"net/netip"
"sync"
"time"
@@ -16,6 +17,10 @@ import (
"github.com/soypat/lneto/tcp"
)
const (
minTCPBuffer = 256
)
type StackAsync struct {
mu sync.Mutex
hostname string
@@ -52,6 +57,8 @@ type StackConfig struct {
NTPServer netip.Addr
Hostname string
MaxTCPConns int
TCPBufferSizeTx int // Size of transmit buffer for TCP connections.
TCPBufferSizeRx int // Size of receive buffer for TCP connections.
RandSeed int64
HardwareAddress [6]byte
MTU uint16
@@ -112,9 +119,35 @@ func (s *StackAsync) Reset(cfg StackConfig) error {
// Enable TCP if connections present.
if cfg.MaxTCPConns > 0 {
if cfg.TCPBufferSizeRx < minTCPBuffer || cfg.TCPBufferSizeTx < minTCPBuffer {
return io.ErrShortBuffer
}
if cap(s.tcpconns) < cfg.MaxTCPConns {
s.tcpconns = make([]tcp.Conn, cfg.MaxTCPConns)
}
s.tcpconns = s.tcpconns[:cfg.MaxTCPConns]
for i := range s.tcpconns {
c := &s.tcpconns[i]
c.Abort() // Abort forcibly closes connection to allow buffer setting and reduce risk of race conditions.
h := c.InternalHandler()
sizetx := h.FreeTx()
sizerx := h.SizeRx()
// If size is sufficient then buffers will remain nil and memory will be reused.
var rxbuf, txbuf []byte
if sizetx < cfg.TCPBufferSizeTx || sizerx < cfg.TCPBufferSizeRx {
buf := make([]byte, cfg.TCPBufferSizeTx+cfg.TCPBufferSizeRx)
rxbuf = buf[:cfg.TCPBufferSizeRx]
txbuf = buf[cfg.TCPBufferSizeRx : cfg.TCPBufferSizeRx+cfg.TCPBufferSizeTx]
}
err = c.Configure(tcp.ConnConfig{
RxBuf: rxbuf,
TxBuf: txbuf,
TxPacketQueueSize: 4,
})
if err != nil {
return err
}
}
err = s.tcps.ResetTCP(cfg.MaxTCPConns)
if err != nil {
return err
@@ -213,7 +246,7 @@ func (s *StackAsync) DialTCP(localPort uint16, addrp netip.AddrPort) (conn *tcp.
}
for i := range s.tcpconns {
maybeFreeConn := &s.tcpconns[i]
state := conn.State()
state := maybeFreeConn.State()
if state.IsClosed() {
conn = maybeFreeConn
break // Can be used!
+5 -6
View File
@@ -122,21 +122,20 @@ func (s StackBlocking) DoDialTCP(localPort uint16, addrp netip.AddrPort, timeout
deadline := time.Now().Add(timeout)
for i := 0; i < maxIter; i++ {
state := conn.State()
switch state {
case tcp.StateEstablished:
break
case tcp.StateSynSent, tcp.StateSynRcvd:
if state == tcp.StateEstablished {
return conn, nil
} else if state == tcp.StateSynSent || state == tcp.StateSynRcvd || conn.InternalHandler().AwaitingSynSend() {
if err = s.checkDeadline(deadline); err != nil {
return nil, err
}
time.Sleep(sleep)
default:
} else {
// Unexpected state, abort and terminate connection.
conn.Abort()
return nil, errTCPFailedToConnect
}
}
return conn, nil
return conn, errDeadlineExceed
}
func (s StackBlocking) checkDeadline(deadline time.Time) error {