Repository navigation
fix(moq-quic): delete the remaining 0-RTT code - #7492
Conversation
Quest-Claim: 803cbd8ffc8a701b
Drop the 0-RTT to Data-space mappings, the no-op 0-RTT arm, and the rustls early-data guards, which rustls's defaults make redundant. The characterize test now proves a 0-RTT packet carrying an ACK is dropped unprocessed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t-leftovers # Conflicts: # rs/moq-quic/README.md
PartialDecode::new now skips 0-RTT packets itself and decodes the packet coalesced after them, and ZeroRtt moves out of LongType into LongHeaderType, so no decoded header can hold one. That deletes is_0rtt(), the endpoint's leading-packet loop, the unprotect_header check, and the connection arm. A datagram holding only 0-RTT packets is PacketDecodeError::ZeroRtt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 5 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. CodeRabbit Verify
|
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: c26bbaabf19469fa2c3c22603f59ee565d470a1b.
No actionable bugs found. Moving 0-RTT rejection into decoding is a sound simplification: decoded headers can no longer carry unsupported early data, while the skip loop preserves subsequent coalesced packets and checks payload bounds before advancing. The endpoint and connection paths consistently use that decoder. The rustls default-policy reliance is documented; caller-supplied configs must leave early data disabled.
Verification: static inspection of the decoder, routing/decryption paths, rustls adapters and upstream 0.23.46 defaults, plus the changed regression/fuzz coverage. I did not run tests, fuzzing, or builds.
(Written by gpt-6.1-sol)
There was a problem hiding this comment.
Important
Removing the early-data normalization in QuicServerConfig::with_initial/try_from exposes a panic. rustls 0.23.46 only accepts max_early_data_size of 0 or 0xffff_ffff (rustls-0.23.46/src/quic.rs:283), and start_session unwraps that result at rs/moq-quic/src/crypto/rustls.rs:469. A caller-supplied rustls::ServerConfig with a normal early-data size (any other value) now panics on the first accepted connection; the deleted guard coerced it to 0, so this is a regression.
Reviewed changes
- 0-RTT dropped inside the decoder:
PartialDecode::newskips leading 0-RTT packets and decodes the packet coalesced after them; a datagram of only 0-RTT returns the newPacketDecodeError::ZeroRtt;ProtectedHeader::decodereturnsOptionand advances the cursor past a 0-RTT payload. ZeroRttleaves the decoded types: moved fromLongTypeintoLongHeaderType, deletingPartialDecode::is_0rtt, the endpoint's leading-packet loop, theunprotect_headercheck, theprocess_decrypted_packetarm, and the 0-RTT-to-Data mapping in bothspace()s.- rustls early-data guards removed:
Quic{Client,Server}Config::{with_initial, try_from}no longer force early data off; the crate README, bothMIGRATE.mds, and the rustls doc comments now tell callers to leave it off. - Tests: new
zero_rtt_alone_is_dropped/zero_rtt_coalesced_is_skipped, the characterize test rewritten to prove a 0-RTT ACK is dropped while a coalesced Initial/1-RTT is read, the fuzzpacketinvariant updated, and a moq-uring comment fixed. - Quest deleted:
quest/m1/quic-zero-rtt-leftovers.mdand itsREADME.mdlink.
The parser change itself holds: the skip advances exactly the 0-RTT packet's declared length, cannot loop or panic, and keeps data()/remainder partitioned with the input; the documented Version-Negotiation behavior change for a coalesced unsupported version is sound. The finding below is only in the rustls config path.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
rustls's QUIC ServerConnection::new rejects any max_early_data_size other than 0 or 0xffff_ffff, and start_session unwraps it, so a caller-supplied server config with a normal early-data size panicked on the first accepted connection once the guard was gone. 0xffff_ffff would also let TLS accept early data the transport discards, breaking the crypto::ServerConfig contract. The guards are not dead code, so the Plan's "otherwise keep the guard and its test" applies: restore them, their test, and the docs that describe them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: cfb28a66511dfda6180edb8a3bad39bd3999b96c.
The independent caller-supplied rustls config finding is fixed. Restoring all four normalization guards prevents unsupported early-data sizes from reaching the unwrapped QUIC constructor and preserves the transport's early-data rejection contract. The adapter and its resumption test now match the base branch. My previous review missed that non-default-config panic; relying on defaults alone was insufficient.
No new actionable bugs found. Keeping the decoder simplification while retaining the existing TLS guards is the smaller, sound scope. The other update changes came from the base merge.
Verification: static comparison against the previous reviewed head and current base, including rustls 0.23.46 constructor validation. Tests and builds were not run.
(Written by gpt-6.1-sol)
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Since pullfrog's prior review at c26bbaabf, the only change is that this PR reverted its rustls over-deletion and restored main exactly, leaving the decoder change as the sole behavioral delta.
- rustls early-data guards restored:
Quic{Client,Server}Config::{with_initial, try_from}coerceenable_early_data/max_early_data_sizeoff again, withsupplied_configs_reject_early_data_and_keep_resumptionand main's wording in the crate README and bothMIGRATE.mdfiles. This closes the accept-path panic the prior review flagged, and also stops the one rustls-accepted0xffff_ffffvalue from leaving the TLS layer accepting early data the transport discards. - Decoder change unchanged: the
PartialDecode::new0-RTT skip, the move ofZeroRttintoLongHeaderType, and the removed endpoint/connection/unprotect_headercode are byte-identical to the version the prior review verified.
rs/moq-quic/src/crypto/rustls.rs, the crate README, and both MIGRATE.md files now diff empty against origin/main; the remaining 10 files are the reviewed decoder change plus the quest deletion.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
#7539 landed, so quic-lb-forward-extras drops its Required on the deleted relay-quic-lb-forward quest. Follow-ups that extend still-open quest PRs now require them: ts-small-step-back (#7221), quic-long-type (#7492), and ts-idle-jitter (#7504). release-fanout-bench notes #7493 landed. Apply the pending edits whose PRs have landed: lite-07 ranges drops its fetch-range Required (#7545 landed the miss judging and cached backfill) and records #7207's range-identity question; quic-lock-contention records #7531's recommendation to keep the Mutex and RefCell. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Finishes quest/m1/quic-zero-rtt-leftovers.md: moq-quic keeps only the code that recognizes and drops a 0-RTT packet, and that code now lives in the packet decoder.
Changes
PartialDecode::newskips 0-RTT packets and decodes the packet coalesced after them, so a coalesced datagram's later packets still decode. A datagram holding only 0-RTT packets returns the newPacketDecodeError::ZeroRtt.ProtectedHeader::decodereturnsOk(None)for a 0-RTT packet, after moving the cursor past its payload. A 0-RTT packet longer than the datagram is stillInvalidHeader.ZeroRttmoved out ofLongTypeintoLongHeaderType, so no decoded header can hold one. That deletesPartialDecode::is_0rtt(), the endpoint's leading-packet loop, the check inpacket_crypto::unprotect_header, and the 0-RTT arm inConnection::process_decrypted_packet.PartialDecode::space()andHeader::space()no longer map 0-RTT to the Data space.QuicClientConfig::{with_initial, try_from}andQuicServerConfig::{with_initial, try_from}, and their test. rustls 0.23.46 leaves early data off by default, but the guards also normalize caller-supplied configs: rustls's QUICServerConnection::newrejects anymax_early_data_sizeother than0or0xffff_ffff(rustls-0.23.46/src/quic.rs:283), andstart_sessionunwraps that result, so without the guard such a config panics on the first accepted connection. The Plan said to keep the guard and its test in that case. This PR first removed them, and Pullfrog's review thread found the panic, so cfb28a6 restored them.rs/moq-quic/src/crypto/rustls.rs, the README, and bothMIGRATE.mdfiles now match main.packet::tests::zero_rtt_alone_is_droppedcovers a datagram of one or two 0-RTT packets, plus a truncated one.packet::tests::zero_rtt_coalesced_is_skippedcovers 0-RTT before, between, and after Handshake and short packets.zero_rtt_packets_are_dropped(end to end) sends a 0-RTT packet carrying an ACK for packet 1000, which the server never sent, so processing it would be a PROTOCOL_VIOLATION. The packet goes before and after a coalesced Initial, alone on the established connection, and before a 1-RTT packet. No case processes the ACK, and the 1-RTT STREAM frame is read. WithLongType::ZeroRttgone, the test builds a Handshake header and rewrites its type bits, which header protection doesn't cover.packetfuzz target's invariant now matches the skip. The decoded packet must be the bytes just before the remainder, and any skipped prefix must start with a 0-RTT long header.quest/m1/README.md.Metricsrename in the BBR3 line.rs/moq-quic/src/crypto/rustls.rs.Requiredfrom quest/m2/quic-long-type.md, plus its "until fix(moq-quic): delete the remaining 0-RTT code #7492 lands" line. Main planned that follow-up with this quest as its blocker, so deleting this quest left a dangling link thatquest checkflagged.Public API: none.
packetis a private module, soPacketDecodeError,ProtectedHeader, andLongTypearen't exported. Wire: none.Decisions
Keep
is_0rtt(), or drop 0-RTT another way?is_0rtt()as the only recognizer, and make the connection armunreachable!(what this PR first did).PartialDecode::newskips 0-RTT packets itself, andZeroRttmoves out ofLongTypeintoLongHeaderType, so no decoded header can hold one. That deletesis_0rtt(), the endpoint's leading-packet loop, theunprotect_headercheck, and the connection arm. Later packets in a coalesced datagram must still decode after a skipped 0-RTT packet, and tests must show a 0-RTT packet dropped both alone and coalesced.matches!at both drop sites. That needs a new accessor, which isis_0rtt()under another name.The quest file is deleted in this PR, so this answer is recorded only here.
Notes for review
crypto::ServerConfigcontract ("Sessions must reject early data",rs/moq-quic/src/crypto.rs:121) holds.malformed header: {e}lines in the endpoint and inhandle_coalesced. Before, the endpoint dropped it silently.PartialDecode::new. If that packet has an unsupported version and the datagram is at least 1200 bytes, the server sends Version Negotiation. That is also what happens when such a packet arrives first, so a peer can't get anything it couldn't already get. Real peers don't mix versions in one datagram.LongTypenow has a single variant,Handshake. Collapsing it is listed as a follow-up and was left out of this PR to keep the shape the decision asked for.Checks
At 82fcbcf (main merged at e25f626):
just rs check-test-changedover this PR's changed files (moq-quic, moq-uring, and their dependents): clippy, tests, fmt, doc, shear, sort, and hakari all passed. 6152 + 556 + 277 tests passed, includingzero_rtt_alone_is_dropped,zero_rtt_coalesced_is_skipped, andzero_rtt_packets_are_dropped.quest check --base origin/main: 549 documents ok.Review
Round 1 (new session after the merge):
quest review --base origin/main, Codexgpt-6.1-solat medium effort, head 82fcbcf. No findings.Online: Pullfrog's only finding, on c26bbaa, was fixed in cfb28a6 (thread resolved). Pullfrog and the OpenAI review both reported no new issues at cfb28a6.
Follow-ups
LongTypeis planned as quest/m2/quic-long-type.md, which this PR unblocks.rs/moq-quic/src/tests/token.rs:84-85(poll_transmit→transmitnext toProtectedHeader::Initial→Some(ProtectedHeader::Initial)). Whichever lands second keeps both changes. Nothing this PR adds calls an API that moq-quic owns its waits #7490 renames.🤖 Generated with Claude Code
(Written by Claude Opus 5.5)