d4ffe0474f
Peer's CONNECTION_CLOSE now transitions the connection through DRAINING
for 3 * PTO before flipping to CLOSED, instead of going straight to
CLOSED. While DRAINING:
- the writer emits no packets (drainOutbound returns null);
- the parser drops late inbound silently at the top of feedDatagramInner;
- close()-awaiters unblock immediately via closingDrainSignal so the
transition isn't gated on the 3*PTO grace.
After 3 * PTO the driver's send-loop timer fires
markClosedExternally("draining period elapsed") which transitions to
CLOSED. The §10.2.2 grace period gives the peer's last retransmits a
chance to converge before we discard state.
Implementation:
* `Status.DRAINING` enum value with kdoc tying it to §10.2.2.
* `QuicConnection.drainingDeadlineMs` + `enterDraining(reason, nowMs)`
(sets status, computes `now + max(3*pto, MIN_DRAINING_PERIOD_MS)`,
completes closingDrainSignal, fires qlog) + `isDrainingExpired`.
* Parser's CONNECTION_CLOSE handler routes through `enterDraining`
instead of `markClosedExternally`.
* Driver folds `drainingDeadlineMs` into its send-loop sleep
`withTimeoutOrNull` and transitions to CLOSED on expiry.
* Writer short-circuits drainOutbound for DRAINING (returns null —
spec MUST NOT send).
* Parser drops late inbound at the top of feedDatagramInner.
Updated `FrameRoutingTest.connection_close_from_peer_short_circuits_remaining_frames`
to expect DRAINING (was CLOSED). Other status=CLOSED assertions in the
test suite cover OUR-side closes (markClosedExternally on protocol
violations / TRANSPORT_PARAMETER_ERROR / FLOW_CONTROL_ERROR) which
still go directly to CLOSED.
Test: `DrainingStateTest` (7 cases) covers the peer-close → DRAINING
transition, late-inbound drop, deadline math, the
MIN_DRAINING_PERIOD_MS floor, retransmit no-op semantics, and the
fresh-connection invariant.
Plan updated to mark all 🟡 Medium items resolved. The 2026-05-09
audit's complete spec-compliance close-out: 2 of 2 High + 6 of 6
Medium fixed in seven commits.
https://claude.ai/code/session_01XGmmaVuy2wsSZQx2AqN2ik