d03e179816
The Retry parser + integrity-tag verifier already existed in RetryPacket.kt, but feedDatagram dropped Retry packets on the floor. Hook them up: - QuicConnectionParser.feedLongHeaderPacket detects RETRY type before the standard parse-and-decrypt path, parses via RetryPacket, and dispatches to QuicConnection.applyRetry. - QuicConnection.start() now caches the ClientHello bytes (TLS only emits ClientHello once; we need to re-queue the same bytes on the fresh Initial keys after Retry). New applyRetry method: verifies the integrity tag, swaps DCID to Retry's SCID, re-derives Initial keys, resets the Initial PN space + sentPackets + cryptoSend, re-enqueues the cached ClientHello, stores the Retry token, and latches retryConsumed so a second Retry is dropped. - LevelState.restoreFromRetry / PacketNumberSpaceState.resetForRetry give applyRetry an in-place reset (the level reference is a `val`, so we mirror discardKeys' field-reset pattern). - QuicConnectionWriter.buildLongHeaderFromFrames threads conn.retryToken through the Initial header's Token field on every Initial we emit after Retry. Per RFC 9001 §5.8, a Retry with a bad integrity tag is silently dropped; per RFC 9000 §17.2.5.2, only one Retry is honored per connection. Both invariants are tested. New test: RetryHandlingTest covers the happy path (DCID swap, PN reset, token threading, ClientHello replay, ≥1200-byte padding), the bad-tag path, and the second-retry path.