Repository navigation
fix: send raw QUIC stream codes as is in iroh and quinn - #408
Conversation
A raw QUIC session mapped RESET_STREAM and STOP_SENDING codes through the HTTP/3 WebTransport code space, so a plain QUIC peer saw CANCELLED (1) as 0x52e4a40fa8dc and its own codes read back as invalid. Raw sessions in web-transport-iroh and web-transport-quinn now send the code as is and read a plain code as is. A code in the HTTP/3 range still decodes, since older raw peers send that form and no u32 reaches it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The maintainer accepted the raw QUIC wire change for moq's (Written by Claude Opus 5.5) |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed 59fc7d7 after ready-for-review. No actionable defects found in the introduced changes.
Direction: keeping the code-space choice on each stream is a small, appropriate fix. Raw and HTTP/3 open/accept paths propagate it consistently, including Quinn's poll API; the wrapped read/write errors and reset/stop operations use it without changing the public conversion impls. Accepting legacy mapped codes is unambiguous because that range is above every u32. No additional abstraction appears necessary.
The older-peer receive incompatibility is explicitly accepted in the linked release decision. The other backends and raw connection-close decoding remain documented follow-ups, not fixes supplied by this PR.
Verification: inspected all ten changed files and surrounding stream/session/error paths; checked mapping boundaries at 0, 29/30/31 and u32::MAX. GitHub CI for this exact SHA passed both just check and just test. I did not rerun Rust tests locally because this review environment has no Rust/Nix toolchain, and did not independently run cross-version interop.
(Written by review (OpenAI))
kixelated
left a comment
There was a problem hiding this comment.
No findings.
What I checked:
- Send paths:
reset(iroh/quinnsend.rs) andstop(recv.rs) both go throughencode_stream_code. Raw sendscode.into()(u32 to VarInt is infallible); HTTP/3 keeps theerror_to_http3+unwrapit had before. - Receive paths: all
Reset/Stoppeddecoding goes throughdecode_stream_code:read,read_exact,read_chunk(s),read_to_end,received_reset,write*,stopped, quinnpoll_read, quinnpoll_write, and quinnpoll_closed, which capturesrawbefore the retained future. The onlyerror_from_http3calls left are the publicFromimpls (no longer used by the streams), close-code paths (out of scope, as the PR says), and ffi's connection-close decode. TheAsyncRead/AsyncWriteimpls pass quinn'sio::Errorthrough unmapped, the same as before. - Raw flag at every constructor: iroh uses
h3.is_none()on open andtruein the raw accept branches. quinn usessession_id.is_none()(onlySession::rawsetsNone), including the poll-traitopen_*_ownedandpoll_accept_*paths. Both crates' H3 accept loops passfalse. HTTP/3 behaviour is unchanged. - Overflow/ambiguity:
ERROR_FIRST(0x52e4a40fa8db) is aboveu32::MAX, so a raw u32 code never decodes as a legacy mapped code. A raw peer code above u32 still becomesInvalidReset/InvalidStopped, which is the right use of those variants. In quinn, a known session error still replaces them, as before. - iroh/quinn parity: the two diffs mirror each other. iroh has no poll-trait stream impls, so it has nothing to add there.
- Tests: both new tests pass at 59fc7d7. With
src/reverted to the parent and the tests kept,raw_session_stream_codes_are_not_mappedfails attests/raw.rs:259andtests::raw_stream_codesfails attests.rs:468. Both tests cover only the uni path. Bi and the poll-trait open/accept paths are fine by inspection but not exercised.
Impact: there is no public API change; only pub(crate) helpers and constructor arguments were added. The wire change is raw QUIC only and is one-way compatible, as described: an unfixed raw peer (for example an older moq relay on quinn) reads a fixed peer's resets and stops as InvalidReset/InvalidStopped. The decision to make is whether a release note should call that out for mixed-version moq deployments.
(Written by Claude Opus 5.5)
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (10)
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review. WalkthroughThe Iroh and Quinn transports now track whether each stream belongs to a raw QUIC or HTTP/3 session. Stream reset and stop codes use the corresponding encoding. Receive and write errors decode codes according to the stream mode, while raw-mode decoding also recognizes legacy HTTP/3-mapped codes. Tests cover unchanged raw codes and legacy mapped codes. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to The change consistently separates raw QUIC stream codes from HTTP/3 mapping while retaining legacy decoding compatibility. No actionable merge-blocking risk is established; merge after normal checks pass. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change is limited to stream error-code handling on existing QUIC sessions. No new privilege or trust-boundary bypass was identified. Mixed-version peers can interpret the newly emitted codes differently, so compatibility remains the principal design risk. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches✨ Simplify code
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. Comment |
A raw QUIC session (
Session::raw) inweb-transport-irohandweb-transport-quinnmapped RESET_STREAM and STOP_SENDING codes through the HTTP/3 WebTransport code space. A plain QUIC peer saw CANCELLED (1) as0x52e4a40fa8dc, and its own small codes read back asInvalidReset/InvalidStopped. moq hit this against moxygen over raw QUIC (moq-dev/moq#4602). The same fix forweb-transport-moqis moq-dev/noq#27.resetandstopcodes as is, and read a peer's code as is when it fits in au32.u32reaches that range, so it cannot be mistaken for a raw code.Impact
From<ReadError>/From<WriteError>impls keep their HTTP/3 decoding; the streams decode through the session instead.InvalidReset/InvalidStopped.Tests
web-transport-irohtests::raw_stream_codesandweb-transport-quinntests/raw.rs::raw_session_stream_codes_are_not_mappeddrive a raw session against a plain connection: reset and stop in each direction arrive verbatim, and a legacy HTTP/3-mapped code from the plain peer still decodes. Both fail without the fix.Not changed here
web-transport-noqandweb-transport-quichehave raw sessions with the same mapping. moq does not use them; left for a follow-up.web-transport-irohandweb-transport-quinnstill decode a raw peer'sApplicationClosedcode only through the HTTP/3 space, so a raw close code is not reported bysession_error(). fix(web-transport-moq): report a raw QUIC peer's close code noq#11 fixed that forweb-transport-moq.🤖 Generated with Claude Code
(Written by Claude Opus 5.5)