Files
lneto/internet/stack-ports.go
T
2025-12-18 18:44:50 -03:00

83 lines
1.9 KiB
Go

package internet
import (
"encoding/binary"
"io"
"math"
"github.com/soypat/lneto"
)
type StackPorts struct {
connID uint64
handlers handlers
dstPortOff uint16
protocol uint16
}
func (ps *StackPorts) ResetUDP(maxNodes int) error {
return ps.Reset(uint64(lneto.IPProtoUDP), 2, maxNodes)
}
func (ps *StackPorts) ResetTCP(maxNodes int) error {
return ps.Reset(uint64(lneto.IPProtoTCP), 2, maxNodes)
}
func (ps *StackPorts) Reset(protocol uint64, dstPortOffset uint16, maxNodes int) error {
if protocol > math.MaxUint16 {
return errInvalidProto
} else if maxNodes <= 0 {
return errZeroMaxNodesArg
}
ps.handlers.reset(maxNodes)
*ps = StackPorts{
connID: ps.connID + 1,
handlers: ps.handlers,
dstPortOff: dstPortOffset,
protocol: uint16(protocol),
}
return nil
}
func (ps *StackPorts) LocalPort() uint16 { return 0 }
func (ps *StackPorts) Protocol() uint64 { return uint64(ps.protocol) }
func (ps *StackPorts) ConnectionID() *uint64 { return &ps.connID }
func (ps *StackPorts) Encapsulate(b []byte, offset int) (n int, err error) {
if int(ps.dstPortOff)+offset+2 > len(b) {
return 0, io.ErrShortBuffer
}
_, n, err = ps.handlers.encapsulateAny(b, offset)
return n, err
}
func (ps *StackPorts) Demux(b []byte, offset int) (err error) {
if int(ps.dstPortOff)+offset+2 > len(b) {
return io.ErrShortBuffer
}
port := binary.BigEndian.Uint16(b[int(ps.dstPortOff)+offset:])
node := ps.handlers.nodeByPort(port)
if node == nil {
return nil
}
err = node.demux(b, offset)
if ps.handlers.tryHandleError(node, err) {
// discarded handler gracefully.
err = nil
}
return err
}
func (ps *StackPorts) Register(h StackNode) error {
port := h.LocalPort()
proto := h.Protocol()
if port <= 0 {
return errZeroPort
} else if proto != uint64(ps.protocol) {
return errInvalidProto
}
return ps.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, nil))
}