From 66c9a7d763f219591430182b6ff307a3fa70728d Mon Sep 17 00:00:00 2001 From: Patricio Whittingslow Date: Thu, 27 Jun 2024 21:09:30 -0300 Subject: [PATCH] start adding debug logic, slightly better Listener recv --- stacks/portstack.go | 16 ++++++++++------ stacks/tcpconn.go | 5 ++--- stacks/tcplistener.go | 38 ++++++++++++++++++++++---------------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/stacks/portstack.go b/stacks/portstack.go index c5533f4..89d959e 100644 --- a/stacks/portstack.go +++ b/stacks/portstack.go @@ -315,12 +315,6 @@ func (ps *PortStack) RecvEth(ethernetFrame []byte) (err error) { } pkt := &ps.auxTCP - if pkt == nil { - ps.error("TCP packet dropped") - ps.droppedPackets++ - err = ErrDroppedPacket // Our socket needs handling before admitting more packets. - break - } if isDebug { ps.debug("TCP:recv", slog.Int("opt", len(tcpOptions)), @@ -347,6 +341,16 @@ func (ps *PortStack) RecvEth(ethernetFrame []byte) (err error) { } else if err == ErrFlagPending { err = nil // TODO(soypat). } + if err != nil && isDebug && ps.logger.Enabled(context.Background(), internal.LevelTrace) { + seg := pkt.TCP.Segment(len(payload)) + ps.trace("stack:error", + slog.Uint64("seg.seq", uint64(seg.SEQ)), + slog.Uint64("seg.ack", uint64(seg.ACK)), + slog.Uint64("seg.wnd", uint64(seg.WND)), + slog.String("seg.flags", seg.Flags.String()), + slog.Uint64("seg.data", uint64(seg.DATALEN)), + ) + } } if err != nil { ps.error("Stack.RecvEth", slog.String("err", err.Error())) diff --git a/stacks/tcpconn.go b/stacks/tcpconn.go index 544e885..9e5a02e 100644 --- a/stacks/tcpconn.go +++ b/stacks/tcpconn.go @@ -332,13 +332,12 @@ func (sock *TCPConn) checkPipeOpen() error { } func (sock *TCPConn) recv(pkt *TCPPacket) (err error) { - sock.trace("TCPConn.recv:start") + remotePort := sock.remote.Port() + sock.trace("TCPConn.recv:start", slog.Uint64("lport", uint64(sock.localPort)), slog.Uint64("rport", uint64(remotePort))) prevState := sock.scb.State() if prevState.IsClosed() { return io.EOF } - - remotePort := sock.remote.Port() if remotePort != 0 && pkt.TCP.SourcePort != remotePort { return nil // This packet came from a different client to the one we are interacting with. } diff --git a/stacks/tcplistener.go b/stacks/tcplistener.go index a9bea17..5a33926 100644 --- a/stacks/tcplistener.go +++ b/stacks/tcplistener.go @@ -129,26 +129,32 @@ func (l *TCPListener) recv(pkt *TCPPacket) error { if !l.isOpen() { return io.EOF } + l.stack.trace("lst:recv", slog.Uint64("lport", uint64(l.port)), slog.Uint64("rport", uint64(pkt.TCP.SourcePort))) var freeconn *TCPConn - isSYN := pkt.TCP.Flags() == seqs.FlagSYN + isSYN := pkt.TCP.Ack == 0 && pkt.TCP.Flags() == seqs.FlagSYN var connidx int - for connidx = range l.conns { - conn := &l.conns[connidx] - if pkt.TCP.Ack == 0 && isSYN && !l.used[connidx] && conn.State() == seqs.StateListen { - // Get first available connection in list for first SYN packet, initiating connection. - freeconn = conn - break - } - if pkt.TCP.SourcePort != conn.remote.Port() || - pkt.IP.Source != conn.remote.Addr().As4() { - continue // Not for this connection. + if isSYN { + for connidx = range l.conns { + conn := &l.conns[connidx] + if conn.scb.State() == seqs.StateListen && !conn.scb.HasPending() { + // Get first available connection in list for first SYN packet, initiating connection. + if l.used[connidx] { + // See https://github.com/soypat/seqs/issues/25. + l.stack.trace("lst:reuse-conn", slog.Uint64("rport", uint64(pkt.TCP.SourcePort)), slog.Uint64("rport-old", uint64(conn.remote.Port()))) + } + freeconn = conn + break + } } - err := conn.recv(pkt) - if err == io.EOF { - l.freeConnForReuse(connidx) - err = nil + } else { + for connidx = range l.conns { + conn := &l.conns[connidx] + isMatch := pkt.TCP.SourcePort == conn.remote.Port() && pkt.IP.Source == conn.remote.Addr().As4() + if isMatch { + freeconn = conn + break + } } - return err } if freeconn == nil { l.trace("lst:noconn2recv")