apply some of @ddirect suggestions

This commit is contained in:
Patricio Whittingslow
2025-12-22 18:41:14 -03:00
parent 5e631a1b3d
commit f6bc73ee6c
7 changed files with 104 additions and 41 deletions
+4 -11
View File
@@ -165,6 +165,7 @@ func (h *handlers) demuxByPort(buf []byte, offset int, port uint16) (*node, erro
err := node.demux(buf, offset)
if h.tryHandleError(node, err) {
err = nil
node = nil // Node is destroyed in tryHandleError and invalidated.
}
return node, err
}
@@ -174,12 +175,13 @@ func (h *handlers) demuxByPort(buf []byte, offset int, port uint16) (*node, erro
func (h *handlers) encapsulateAny(buf []byte, offsetIP, offsetThisFrame int) (_ *node, n int, err error) {
for i := range h.nodes {
node := &h.nodes[i]
if node.IsInvalid() || (len(node.remoteAddr) > 0 && isAllZeros(node.remoteAddr)) {
if node.IsInvalid() {
continue
}
n, err = node.encapsulate(buf, offsetIP, offsetThisFrame)
if h.tryHandleError(node, err) {
err = nil // CLOSE error handled gracefully by deleting node.
err = nil // CLOSE error handled gracefully by deleting node.
node = nil // Node is destroyed in tryHandleError and invalidated.
}
if n > 0 {
return node, n, err
@@ -191,15 +193,6 @@ func (h *handlers) encapsulateAny(buf []byte, offsetIP, offsetThisFrame int) (_
return nil, 0, err // Return last written error.
}
func isAllZeros(b []byte) bool {
for i := range b {
if b[i] != 0 {
return false
}
}
return true
}
var (
errZeroMaxNodesArg = errors.New("zero max nodes arg")
errZeroPort = errors.New("port must be greater than zero")
+76 -9
View File
@@ -4,11 +4,13 @@ import (
"encoding/binary"
"errors"
"io"
"log/slog"
"math"
"strconv"
"github.com/soypat/lneto"
"github.com/soypat/lneto/ethernet"
"github.com/soypat/lneto/internal"
)
type StackPorts struct {
@@ -16,6 +18,7 @@ type StackPorts struct {
handlers handlers
dstPortOff uint16
protocol uint16
// stores last node to demux/encapsulate.
}
func (ps *StackPorts) ResetUDP(maxNodes int) error {
@@ -52,12 +55,7 @@ func (ps *StackPorts) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame
if int(ps.dstPortOff)+offsetToFrame+2 > len(carrierData) {
return 0, io.ErrShortBuffer
}
var node *node
node, n, err = ps.handlers.encapsulateAny(carrierData, offsetToIP, offsetToFrame)
if n > 0 && len(node.remoteAddr) == 6 && offsetToIP >= 14 {
efrm, _ := ethernet.NewFrame(carrierData[offsetToIP-14:])
*efrm.DestinationHardwareAddr() = [6]byte(node.remoteAddr)
}
_, n, err = ps.handlers.encapsulateAny(carrierData, offsetToIP, offsetToFrame)
return n, err
}
@@ -72,15 +70,84 @@ func (ps *StackPorts) Demux(b []byte, offset int) (err error) {
// Register registers a port StackNode on StackPorts.
// If dstMAC is set to non-nil, length six buffer then
func (ps *StackPorts) Register(h StackNode, dstMAC []byte) error {
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
} else if dstMAC != nil && len(dstMAC) != 6 {
}
return ps.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, nil))
}
// StackPortsMACFiltered is a StackPorts implementation but that avoids calling encapsulate on nodes
// with a non-nil MAC address registered via Register method that is set to all zero values.
// If the address is set to nil no filtering occurs. MAC Address is set automatically on the ethernet frame by StackPortsMACFiltered when non-nil.
type StackPortsMACFiltered struct {
sp StackPorts
}
func (mfsp *StackPortsMACFiltered) Register(h StackNode, addr []byte) error {
port := h.LocalPort()
proto := h.Protocol()
if port <= 0 {
return errZeroPort
} else if proto != uint64(mfsp.sp.protocol) {
return errInvalidProto
} else if addr != nil && len(addr) != 6 {
return errors.New("invalid MAC")
}
return ps.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, dstMAC))
return mfsp.sp.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, addr))
}
func (ps *StackPortsMACFiltered) ResetUDP(maxNodes int) error {
return ps.sp.ResetUDP(maxNodes)
}
func (ps *StackPortsMACFiltered) ResetTCP(maxNodes int) error {
return ps.sp.ResetTCP(maxNodes)
}
func (ps *StackPortsMACFiltered) Reset(protocol uint64, dstPortOffset uint16, maxNodes int) error {
return ps.sp.Reset(protocol, dstPortOffset, maxNodes)
}
func (ps *StackPortsMACFiltered) LocalPort() uint16 { return 0 }
func (ps *StackPortsMACFiltered) Protocol() uint64 { return uint64(ps.sp.protocol) }
func (ps *StackPortsMACFiltered) ConnectionID() *uint64 { return &ps.sp.connID }
func (ps *StackPortsMACFiltered) Demux(b []byte, offset int) (err error) {
// No MAC Filtering on ingress. TODO?
return ps.sp.Demux(b, offset)
}
func (ps *StackPortsMACFiltered) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) {
if int(ps.sp.dstPortOff)+offsetToFrame+2 > len(carrierData) {
return 0, io.ErrShortBuffer
}
h := &ps.sp.handlers
for i := range h.nodes {
node := &h.nodes[i]
if node.IsInvalid() || (len(node.remoteAddr) > 0 && internal.IsZeroed(node.remoteAddr...)) {
continue
}
n, err = node.encapsulate(carrierData, offsetToIP, offsetToFrame)
if h.tryHandleError(node, err) {
err = nil // CLOSE error handled gracefully by deleting node.
}
if n > 0 {
if len(node.remoteAddr) == 6 && offsetToIP >= 14 {
efrm, _ := ethernet.NewFrame(carrierData[offsetToIP-14:])
*efrm.DestinationHardwareAddr() = [6]byte(node.remoteAddr)
}
return n, err
} else if err != nil {
// Make sure not to hang on one handler that keeps returning an error.
h.error("handlers:encapsulate", slog.String("func", "encapsulateAny"), slog.String("ctx", h.context), slog.String("err", err.Error()))
}
}
return 0, err // Return last written error.
}