ControlBlock.Send refused any outgoing segment carrying data in
FIN-WAIT-1, citing RFC 9293's "no further SENDs from the user will be
accepted by the TCP implementation". That rule bounds what the
application may queue, which Handler.Write already enforces, and not the
retransmission of data the connection has already accepted from it.
The consequence is that write-then-close, which is what nearly every
server does with a response, cannot recover from losing its last data
segment. The FIN occupies a sequence number above that data, so the peer
cannot cross the gap to process the close: it waits for bytes that are
never resent while the sender waits for an ACK that cannot arrive.
Neither side times out at the TCP layer.
FIN-WAIT-2 keeps the restriction and gains the reasoning: it is reached
by our FIN being acknowledged, which acknowledges everything below it, so
no unacknowledged data can remain there.
PendingSegment needs the same distinction, since it decides whether to
offer send-buffer data at all; it gets an unexported State predicate
rather than a new exported one.
Two tests, the second red before the change:
- retransmission after RTO expiry, covering the Handler/LossRecovery
seam that the RTO unit tests do not reach (they exercise the state
machine in isolation, where it behaves correctly).
- retransmission after a close with unacknowledged data.
Co-authored-by: Derek den Haas <i.pestano@easyflor.nl>
* tcp: remove retransmit logic entirely; add duplicate ack counting to ControlBlock
* retransmit implemented in nice simple straightforward way
* narrow down retransmission cases
* remove old timing tests
* add ControlBlock retransmit test
* add failing handler test
* reworking payload length semantic meaning in code
* fix establish conn logic
* clean up tests and add TCB dupack generation and test it
* catch pending retransmit satisfy in test
* add fuzz test for control block
* bugfix: be more strict in what is considered dupack
* add IncomingIsDupACK docs
* limit queue of retransmits
* protect retransmit overflow from incorrectly updating nxt
* pcap: reuse Frame memory
* slog: reduce heap allocations of addresses; also prevent heap alloc of dhcp options in pcap
* dns: heapless improvement; add StackAsync buffer for more heapless operation; start thinking of errors
* errors: begin standardise errors in lneto
* errors: finish standardization of errors
* fix merge issues
* add more lneto errors to rest of package
* format errors.go
* reduce heap allocations in tcp logging; omit use of AppendFloat which allocates a metric sh*tton
* debugheaplog: better heap statistic logging
* heap: use string for pcap.Frame.Protocol
* add potential to eliminate Flags.String heap alloc, remove incorrect HEAP comments
* add StackAsync.DebugErr and httpraw.SetBytes
* many heap alloc reductions and replacement of bytes.Equal with internal.BytesEqual
* tcp: mss honoring; accept syn with ECE/CWR flags; add RSTQueue type
* tcp: move option logic to own file
* remove prints in pcap
* add MSS send threshold inspired by linux/freebsd/lwip thresh