mirror of
https://github.com/soypat/lneto.git
synced 2026-08-24 16:39:07 +00:00
tcpHandler looks rounded off, add to example
This commit is contained in:
+80
-16
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user