From 70a3bbbe2fd09f5b9e0c2b7f17fa2f8b43c6ffda Mon Sep 17 00:00:00 2001 From: soypat Date: Sat, 5 Apr 2025 17:17:32 -0300 Subject: [PATCH] add stackbasic test --- internal/ltesto/httptap.go | 31 ---------------- internet/basicstack.go | 3 +- internet/stackbasic_test.go | 71 +++++++++++++++++++++++++++++++++++++ internet/tcpconn.go | 30 +++++++++++++++- 4 files changed, 102 insertions(+), 33 deletions(-) create mode 100644 internet/stackbasic_test.go diff --git a/internal/ltesto/httptap.go b/internal/ltesto/httptap.go index cbcfcee..4a56f03 100644 --- a/internal/ltesto/httptap.go +++ b/internal/ltesto/httptap.go @@ -5,12 +5,10 @@ import ( "encoding/json" "errors" "fmt" - "log" "log/slog" "net/http" "net/netip" "net/url" - "time" "github.com/soypat/lneto/internal" ) @@ -73,35 +71,6 @@ func (h *HTTPTapClient) Write(b []byte) (int, error) { func (h *HTTPTapClient) Close() error { return nil } -func (h *HTTPTapClient) HandleTap(buf []byte) (HandleTapResult, error) { - nread, err := tap.Read(buf[:]) - if err != nil { - slogger.error("tap-err", slog.String("err", err.Error())) - log.Fatal(err) - } else if nread > 0 { - err = lStack.RecvEth(buf[:nread]) - if err != nil { - slogger.error("recv", slog.String("err", err.Error()), slog.Int("plen", nread)) - } else { - slogger.info("recv", slog.Int("plen", nread)) - } - } - nw, err := lStack.HandleEth(buf[:]) - if err != nil { - slogger.error("handle", slog.String("err", err.Error())) - } else if nw > 0 { - _, err = tap.Write(buf[:nw]) - if err != nil { - log.Fatal(err) - } else { - slogger.info("write", slog.Int("plen", nw)) - } - } - if nread == 0 && nw == 0 { - time.Sleep(5 * time.Millisecond) - } -} - type HTTPTapServer struct { router *http.ServeMux stack stack diff --git a/internet/basicstack.go b/internet/basicstack.go index 25d3eb3..a83b7ac 100644 --- a/internet/basicstack.go +++ b/internet/basicstack.go @@ -38,7 +38,8 @@ func (sb *StackBasic) Recv(frame []byte) error { if err != nil { return err } - if *ifrm.DestinationAddr() != sb.ip { + dst := ifrm.DestinationAddr() + if *dst != sb.ip { return errors.New("packet not for us") } sb.validator.ResetErr() diff --git a/internet/stackbasic_test.go b/internet/stackbasic_test.go new file mode 100644 index 0000000..e640289 --- /dev/null +++ b/internet/stackbasic_test.go @@ -0,0 +1,71 @@ +package internet + +import ( + "math/rand" + "net/netip" + "testing" +) + +func TestBasicStack(t *testing.T) { + rng := rand.New(rand.NewSource(1)) + var sbCl, sbSv StackBasic + var connCl, connSv TCPConn + setupClientServer(t, rng, &sbCl, &sbSv, &connCl, &connSv) + var buf [2048]byte + n, err := sbCl.Handle(buf[:]) + if err != nil { + t.Fatal(err) + } else if n == 0 { + t.Fatal("expected data exchange") + } + err = sbSv.Recv(buf[:n]) + if err != nil { + t.Fatal(err) + } +} + +func setupClientServer(t *testing.T, rng *rand.Rand, client, server *StackBasic, connClient, connServer *TCPConn) { + bufsize := 2048 + // Ensure buffer sizes are OK with reused buffers. + svip := netip.AddrPortFrom(netip.AddrFrom4([4]byte{192, 168, 1, 0}), 80) + clip := netip.AddrPortFrom(netip.AddrFrom4([4]byte{192, 168, 1, 1}), 1337) + server.SetAddr(svip.Addr()) + client.SetAddr(clip.Addr()) + + err := connServer.Configure(&TCPConnConfig{ + RxBuf: make([]byte, bufsize), + TxBuf: make([]byte, bufsize), + TxPacketQueueSize: 3, + Logger: nil, + }) + if err != nil { + t.Fatal(err) + } + err = connClient.Configure(&TCPConnConfig{ + RxBuf: make([]byte, bufsize), + TxBuf: make([]byte, bufsize), + TxPacketQueueSize: 3, + Logger: nil, + }) + if err != nil { + t.Fatal(err) + } + + err = connServer.OpenListen(svip.Port(), 200) + if err != nil { + t.Fatal(err) + } + err = connClient.OpenActive(svip, clip.Port(), 100) + if err != nil { + t.Fatal(err) + } + + err = server.RegisterTCPConn(connServer) + if err != nil { + t.Fatal(err) + } + err = client.RegisterTCPConn(connClient) + if err != nil { + t.Fatal(err) + } +} diff --git a/internet/tcpconn.go b/internet/tcpconn.go index 4344098..fe7456a 100644 --- a/internet/tcpconn.go +++ b/internet/tcpconn.go @@ -116,7 +116,10 @@ func (conn *TCPConn) HandleIP(buf []byte, off int) (n int, err error) { if err != nil { return 0, err } - copy(raddr, conn.remoteAddr) + err = setDstAddr(buf[:off], conn.remoteAddr) + if err != nil { + return 0, err + } return n, nil } @@ -145,6 +148,31 @@ func getIPAddr(buf []byte) (addr []byte, err error) { return addr, err } +func setDstAddr(buf []byte, addr []byte) (err error) { + var dstaddr []byte + switch buf[0] >> 4 { + case 4: + ifrm4, err := ipv4.NewFrame(buf) + if err != nil { + return err + } + dstaddr = ifrm4.DestinationAddr()[:] + case 6: + ifrm6, err := ipv6.NewFrame(buf) + if err != nil { + return err + } + dstaddr = ifrm6.DestinationAddr()[:] + default: + err = errors.New("unsupported IP version") + } + if err == nil && len(dstaddr) != len(addr) { + return errors.New("invalid ip version to setDstAddr") + } + copy(dstaddr, addr) + return nil +} + func (conn *TCPConn) isRaddrSet() bool { return len(conn.remoteAddr) != 0 }