continue reworking StackNode implementations

This commit is contained in:
soypat
2025-06-07 11:59:56 -03:00
parent c76fde4677
commit 6cf5896543
12 changed files with 289 additions and 538 deletions
+25 -11
View File
@@ -9,6 +9,7 @@ import (
)
type Handler struct {
connID uint64
ourHWAddr []byte
ourProtoAddr []byte
htype uint16
@@ -26,22 +27,31 @@ type HandlerConfig struct {
ProtocolType ethernet.Type
}
func NewHandler(cfg HandlerConfig) (*Handler, error) {
func (c *Handler) Reset(cfg HandlerConfig) error {
if len(cfg.HardwareAddr) == 0 || len(cfg.HardwareAddr) > 255 ||
len(cfg.ProtocolAddr) == 0 || len(cfg.ProtocolAddr) > 255 {
return nil, errors.New("invalid Handler address config")
return errors.New("invalid Handler address config")
} else if cfg.MaxQueries <= 0 || cfg.MaxPending <= 0 {
return nil, errors.New("invalid Handler query or pending config")
return errors.New("invalid Handler query or pending config")
}
h := &Handler{
pending: make([][sizeHeaderv6]byte, 0, cfg.MaxPending),
*c = Handler{
connID: c.connID + 1,
ourHWAddr: c.ourHWAddr[:0],
ourProtoAddr: c.ourProtoAddr[:0],
htype: cfg.HardwareType,
protoType: cfg.ProtocolType,
ourHWAddr: cfg.HardwareAddr,
ourProtoAddr: cfg.ProtocolAddr,
queries: make([]queryResult, 0, cfg.MaxQueries),
pending: c.pending[:0],
queries: c.queries[:0],
}
return h, nil
c.ourHWAddr = append(c.ourHWAddr, cfg.HardwareAddr...)
c.ourProtoAddr = append(c.ourProtoAddr, cfg.ProtocolAddr...)
if cap(c.pending) < cfg.MaxPending {
c.pending = make([][52]byte, cfg.MaxPending)[:0]
}
if cap(c.queries) < cfg.MaxQueries {
c.queries = make([]queryResult, cfg.MaxQueries)[:0]
}
return nil
}
type queryResult struct {
@@ -50,8 +60,8 @@ type queryResult struct {
querysent bool
}
// ResetState drops pending queries and incoming requests.
func (c *Handler) ResetState() {
// AbortPending drops pending queries and incoming requests.
func (c *Handler) AbortPending() {
c.pending = c.pending[:0]
c.queries = c.queries[:0]
}
@@ -60,6 +70,10 @@ func (c *Handler) expectSize() int {
return sizeHeader + 2*len(c.ourHWAddr) + 2*len(c.ourProtoAddr)
}
func (c *Handler) ConnectionID() *uint64 {
return &c.connID
}
func (c *Handler) QueryResult(protoAddr []byte) (hwAddr []byte, err error) {
for i := range c.queries {
if bytes.Equal(protoAddr, c.queries[i].protoaddr) {
+22 -2
View File
@@ -5,11 +5,13 @@ import (
"log"
"testing"
"github.com/soypat/lneto"
"github.com/soypat/lneto/ethernet"
)
func TestHandler(t *testing.T) {
c1, err := NewHandler(HandlerConfig{
var c1, c2 Handler
err := c1.Reset(HandlerConfig{
HardwareAddr: []byte{0xde, 0xad, 0xbe, 0xef, 0x00, 0x00},
ProtocolAddr: []byte{192, 168, 1, 1},
MaxQueries: 1,
@@ -20,7 +22,7 @@ func TestHandler(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c2, err := NewHandler(HandlerConfig{
err = c2.Reset(HandlerConfig{
HardwareAddr: []byte{0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee},
ProtocolAddr: []byte{192, 168, 1, 2},
MaxQueries: 1,
@@ -58,6 +60,7 @@ func TestHandler(t *testing.T) {
} else if n == 0 {
t.Fatal("expected send of data after first query")
}
validateARP(t, buf[:])
err = c2.Recv(buf[:n]) // Receive request.
if err != nil {
t.Fatal(err)
@@ -69,6 +72,7 @@ func TestHandler(t *testing.T) {
} else if n == 0 {
t.Fatal("got no response to request")
}
validateARP(t, buf[:])
n, err = c2.Send(discard[:]) // Double tap check, should send nothing.
if err != nil {
t.Fatal("double tap send error:", err)
@@ -99,3 +103,19 @@ func TestHandler(t *testing.T) {
t.Fatal("expected no data")
}
}
func validateARP(t *testing.T, buf []byte) {
t.Helper()
afrm, err := NewFrame(buf)
if err != nil {
t.Error(err)
return
}
var vld lneto.Validator
afrm.ValidateSize(&vld)
if vld.HasError() {
t.Errorf("invalid arp: %s", vld.Err())
} else if err := vld.Err(); err != nil {
panic("unreachable: " + err.Error())
}
}