diff --git a/tcp/conn.go b/tcp/conn.go index d703b7c..8027046 100644 --- a/tcp/conn.go +++ b/tcp/conn.go @@ -366,11 +366,11 @@ func (conn *Conn) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) } else if len(raddr) != len(conn.remoteAddr) { return 0, errMismatchedIPVersion } - conn.trace("TCPConn.encaps", slog.Uint64("lport", uint64(conn.h.LocalPort())), slog.Uint64("rport", uint64(conn.h.remotePort))) n, err = conn.h.Send(carrierData[offsetToFrame:]) - if err != nil { + if err != nil || n == 0 { return 0, err } + conn.trace("TCPConn.encaps", slog.Uint64("lport", uint64(conn.h.LocalPort())), slog.Uint64("rport", uint64(conn.h.remotePort))) err = internal.SetIPAddrs(ipFrame, conn.ipID, nil, conn.remoteAddr) if err != nil { return 0, err diff --git a/tcp/handler.go b/tcp/handler.go index 30299e9..7f9dcc8 100644 --- a/tcp/handler.go +++ b/tcp/handler.go @@ -236,15 +236,19 @@ func (h *Handler) Close() error { // It does no IP interfacing or CRC calculation of packet, which is left to the caller to perform. // The returned integer is the length written to the argument buffer. func (h *Handler) Send(b []byte) (int, error) { - h.trace("tcp.Handler:start", slog.Uint64("port", uint64(h.localPort))) if h.IsTxOver() { return 0, net.ErrClosed } + awaitingSyn := h.AwaitingSynSend() + buffered := h.bufTx.BufferedUnsent() + if !awaitingSyn && buffered == 0 && !h.closing && !h.scb.HasPending() { + // Early nop short circuit. + return 0, nil + } tfrm, err := NewFrame(b) if err != nil { return 0, err } - buffered := h.bufTx.BufferedUnsent() if buffered == 0 && h.closing { // If Close called and no more data to be sent, terminate connection! h.closing = false @@ -258,7 +262,7 @@ func (h *Handler) Send(b []byte) (int, error) { offset := uint8(5) mss := uint16(len(b) - sizeHeaderTCP) var segment Segment - if h.AwaitingSynSend() { + if awaitingSyn { // Handling init syn segment. segment = ClientSynSegment(h.bufTx.iss, Size(h.bufRx.Size())) h.optcodec.PutOption16(b[sizeHeaderTCP:], OptMaxSegmentSize, mss)