b25644bf8b
Verified and applied 12 focused fixes from a four-agent review of the quic module. Each fix verified against the actual code; agent findings that traced to false positives (pendingPing clear-without-emit, sentPackets on encrypt failure) are documented in the review thread but not changed. Concurrency / flakiness: - PTO consecutive count: double-increment removed; now incremented exactly once per PTO event in handlePtoFired before requeue, so the threshold check inside requeueInflightForProbe sees the post- increment value AND the between-probe re-requeue doesn't bump again. - Wallclock → monotonic: QuicConnection.nowMillis defaults to TimeSource.Monotonic anchored at construction, so NTP step / suspend-resume can't poison RTT samples. Driver uses connection.nowMillis instead of carrying its own clock. - Close-state race: atomic CAS via closeStateMonitor in close() and markClosedExternally so concurrent teardown paths can't both fire qlog "connection closed" and stomp on closeReason. - streamsList CME: converted to @Volatile var List<QuicStream> with immutable-snapshot publishing under streamsLock. closeAllSignals' iteration is now CME-free without holding the (suspending) lock. - JcaAesGcmAead: synchronized seal/open; multi-entry recent-nonce history (was single most-recent — could mask a duplicate against the second-most-recent under intermediate seals); on seal failure evict the cached nonce so a retry with the same nonce takes the safe fresh-Cipher path. Wire correctness / spec: - Connection-level send credit no longer debited on retransmits (added Chunk.isRetransmit; writer skips sendConnectionFlowConsumed += data.size when set). Pre-fix a few PTO rounds on a long stream exhausted credit and stalled the connection. - ACK-delay shl overflow: clamp ackDelayExponent to 0..20 and clamp the peer's varint to (Long.MAX_VALUE >>> exponent) before shift; clamp negative now-vs-recv-time before shift on outbound AckTracker. - Key-update commit only when new-phase packet PN exceeds largestReceived (RFC 9001 §6.1). - RESET_STREAM final-size validation: enforce equality with prior FIN size and ≥ highestObservedOffset; close FINAL_SIZE_ERROR otherwise. - STOP_SENDING handling: respond with RESET_STREAM on the local send side (was silently dropped, peer's flow-credit wasted). - ReceiveBuffer.insert: typed InsertResult; second FIN with conflicting size and offset-past-FIN data both surface FINAL_SIZE_ERROR via the parser instead of being silently dropped. - Retry SCID==DCID self-loop: reject Retry where the peer's SCID equals our original DCID (RFC 9000 §17.2.5.2). DoS hardening: - ACK PN walk: drainAckedSentPackets rewritten to scan in-flight keys against parsed ranges instead of walking every PN. A peer with firstAckRange = 2^62-1 used to pin a core forever; now bounded by the sent-packets map size. - UDP socket: channel.connect(remote) after bind so the kernel filters off-path datagrams. Stops trivial source spoofing from burning AEAD attempts. https://claude.ai/code/session_01AhGvbMV8uPRse3TmAGaddM