Files
lneto/internet/stack-port.go
T
2025-06-07 09:36:10 -03:00

82 lines
1.7 KiB
Go

package internet
import (
"encoding/binary"
"io"
)
type StackPort struct {
connID uint64
protocol uint64
handlers []node
dstPortOff int
}
func (ps *StackPort) Reset(protocol uint64, dstPortOffset int) {
*ps = StackPort{
connID: ps.connID + 1,
handlers: ps.handlers[:0],
dstPortOff: dstPortOffset,
protocol: protocol,
}
}
func (ps *StackPort) LocalPort() uint16 { return 0 }
func (ps *StackPort) Protocol() uint64 { return ps.protocol }
func (ps *StackPort) ConnectionID() *uint64 { return &ps.connID }
func (ps *StackPort) Encapsulate(b []byte, offset int) (n int, err error) {
if ps.dstPortOff+offset+2 > len(b) {
return 0, io.ErrShortBuffer
}
var i int
for i = 0; i < len(ps.handlers); i++ {
n, err = ps.handlers[i].encapsulate(b, offset)
if err != nil || n > 0 {
break
}
}
ps.handleResult(i, n, err)
return n, err
}
func (ps *StackPort) Demux(b []byte, offset int) (err error) {
if ps.dstPortOff+offset+2 > len(b) {
return io.ErrShortBuffer
}
port := binary.BigEndian.Uint16(b[ps.dstPortOff+offset:])
var i int
for i = 0; i < len(ps.handlers); i++ {
if port != ps.handlers[i].port {
continue
}
err = ps.handlers[i].demux(b, offset)
if err != nil {
break
}
}
ps.handleResult(i, 0, err)
return err
}
func (ps *StackPort) Register(h StackNode) error {
port := h.LocalPort()
proto := h.Protocol()
if port <= 0 {
return errZeroPort
} else if proto != ps.protocol {
return errInvalidProto
}
ps.handlers = append(ps.handlers, node{
demux: h.Demux,
encapsulate: h.Encapsulate,
port: uint16(port),
})
return nil
}
func (ps *StackPort) handleResult(handlerIdx, n int, err error) {
handleNodeError(&ps.handlers, handlerIdx, err)
}