tcpHandler looks rounded off, add to example

This commit is contained in:
soypat
2025-02-10 20:26:02 -03:00
parent 64a7102064
commit 0cb43c47a4
10 changed files with 184 additions and 137 deletions
+80 -16
View File
@@ -33,14 +33,43 @@ type Handler struct {
logger
}
func (h *Handler) Reset() error {
*h = Handler{
connid: h.connid + 1,
bufTx: h.bufTx,
bufRx: h.bufRx,
func (h *Handler) SetBuffers(txbuf, rxbuf []byte, packets int) error {
if !h.scb.State().IsClosed() {
return errors.New("tcp.Handler must be closed before setting buffers")
}
if rxbuf != nil {
h.bufRx.Buf = rxbuf
}
if len(h.bufRx.Buf) < 1 {
return errors.New("short rx buffer")
}
h.bufRx.Reset()
h.bufTx.ResetOrReuse(nil, 0, 0)
return h.bufTx.ResetOrReuse(txbuf, packets, 0)
}
func (h *Handler) LocalPort() uint16 {
return h.localPort
}
func (h *Handler) Open(state State, localPort, remotePort uint16, iss Value) error {
// Open will fail unless SCB in closed state.
err := h.scb.Open(iss, Size(h.bufRx.Size()), state)
if err != nil {
return err
}
*h = Handler{
scb: h.scb,
bufTx: h.bufTx,
bufRx: h.bufRx,
connid: h.connid + 1,
localPort: localPort,
remotePort: remotePort,
validator: h.validator,
logger: h.logger,
closing: false,
}
h.bufTx.ResetOrReuse(nil, 0, iss)
h.bufRx.Reset()
return nil
}
@@ -100,26 +129,54 @@ func (h *Handler) Recv(b []byte) error {
return nil
}
func (h *Handler) Handle(b []byte) (int, error) {
func (h *Handler) Send(b []byte) (int, error) {
h.trace("tcp.Handler:start", slog.Uint64("port", uint64(h.localPort)))
if h.isClosed() {
return 0, net.ErrClosed
} else if h.AwaitingSyn() {
return h.sendInitSyn(b)
}
tfrm, err := NewFrame(b)
if err != nil {
return 0, err
}
var segment Segment
if h.AwaitingSyn() {
// Handling init syn segment.
segment = Segment{
SEQ: h.scb.ISS(),
ACK: 0,
Flags: FlagSYN,
WND: h.scb.RecvWindow(),
DATALEN: 0,
}
} else {
var ok bool
available := min(h.bufTx.Buffered(), len(b)-sizeHeaderTCP)
segment, ok = h.scb.PendingSegment(available)
if !ok {
// No pending control segment or data to send. Yield.
return 0, nil
}
n, seq, err := h.bufTx.MakePacket(b[sizeHeaderTCP : sizeHeaderTCP+segment.DATALEN])
if err != nil {
return 0, err
} else if seq != segment.SEQ {
panic("mismatching sequence numbers")
} else if n != int(segment.DATALEN) {
panic("expected n == available")
}
}
prevState := h.scb.State()
err = h.scb.Send(segment)
if err != nil {
return 0, err
} else if prevState != h.scb.State() && h.logenabled(slog.LevelInfo) {
h.info("tcp.Handler:tx-statechange", slog.Uint64("port", uint64(h.localPort)), slog.String("oldState", prevState.String()), slog.String("newState", h.scb.State().String()), slog.String("txflags", segment.Flags.String()))
}
tfrm.SetSourcePort(h.localPort)
tfrm.SetDestinationPort(h.remotePort)
return 0, nil
}
func (h *Handler) sendInitSyn(b []byte) (int, error) {
return 0, nil
tfrm.SetSegment(segment, 5) // No TCP options.
tfrm.SetUrgentPtr(0)
return sizeHeaderTCP + int(segment.DATALEN), nil
}
// AwaitingSyn checks if the Handler is waiting for a Syn to arrive.
@@ -130,3 +187,10 @@ func (h *Handler) AwaitingSyn() bool {
func (h *Handler) isClosed() bool {
return h.closing || h.scb.State().IsClosed()
}
func min(a, b int) int {
if a < b {
return a
}
return b
}