Skip to content

fix(quic): announce stream limits that arrive after a refused open - #5774

Merged
kixelated merged 5 commits into
mainfrom
quest/m0/ci/platform-macos-zero-rtt
Oct 16, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest/m0/ci/platform-macos-zero-rtt

Conversation

@kixelated

@kixelated kixelated commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

moq-tokio quic::driver::tests::zero_rtt has failed on every macOS Platform run since #5664 moved moq-tokio onto moq-quic (first failure in run 38924430657). It times out in the initial full handshake: the server's 0.5-RTT open_uni and the client's first accept_uni both end in TimedOut after the 30s idle timeout. Linux passes.

The default aws-lc-rs provider sends a post-quantum key share, so the ClientHello (about 1.5 KB) spans two Initial packets. On Linux both have arrived by the time the server calls accept, and finish_accept replays the second one, so the client's transport parameters are known before the test calls into_0rtt().open_uni(). When the second Initial shows up after accept instead, which macOS loopback allows, the server has a stream limit of 0. open_uni is refused and parks on StreamEvent::Available. The second Initial then sets the limit through StreamsState::set_params, which emits no event. Nothing wakes the opener, and the connection idles out. Upstream quinn has the same set_params (checked against main), and noq does too. This test was first added to the repo in #5664, so it never ran on the noq stack.

Approach

  • StreamsState::set_params emits StreamEvent::Available when it raises a stream limit after an open was refused, the same event MAX_STREAMS raises. A new open_refused flag gates it so ordinary handshakes emit no extra event. A plain "limit rose" check fired on every connection and broke 29 proto tests that assert exact event sequences.
  • Regression test moq-quic tests::late_peer_params_make_streams_available: long ALPN names split the ClientHello under either crypto provider, the server accepts after the first Initial, open is refused, and once the pair is driven the server must report Available and open the stream. Without the fix it fails on Linux at the Available assertion.
  • Listed as a carried change in rs/moq-quic/README.md.
  • The quest is deleted, along with its references.

Impact

  • No public API change. StreamEvent::Available already exists and now also fires in this case.
  • No wire change.

Alternatives

  • Wake stream_budget_available in the moq-tokio driver on HandshakeDataReady. That would only work around a missing proto event, and moq-uring and other drivers would still be broken.
  • Emit Available on every limit increase from transport parameters. Correct, but it adds an event to every handshake and churns 29 tests.

Verification

  • just check passes locally.
  • Platform dispatch 38975613806 at b1b08b0: macOS passed (895/895 Rust tests, zero_rtt in 0.18s instead of a 30s timeout). Windows failed only on the known moq-relay::drills relay_killed_mid_group_aborts_then_resumes (quest/m0/ci/platform-windows-drill.md).

Follow-ups

  • Offer the fix upstream to quinn-rs/quinn. That needs maintainer approval, since it is outside our orgs.
  • moq-gst source::imp::session_tests::a_refused_redial_posts_a_bus_error_after_playback failed once locally with AddrInUse on a loaded host. It is unrelated to this change, and the rerun passed.

🤖 Generated with Claude Code

(Written by Opus 5.5)

kixelated and others added 5 commits October 16, 2026 15:10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A server accepted before the rest of a multi-packet ClientHello learns the
client's stream limits only when the next Initial arrives. A 0.5-RTT open_uni
refused in between never woke, so the connection sat until the idle timeout.
That is what fails moq-tokio's zero_rtt test on macOS, where loopback can
deliver the second Initial after accept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review October 16, 2026 23:05
@coderabbitai

coderabbitai Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You'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 16 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 501fd77b-7574-4308-96ef-fc4dd979ea40
📥 Commits

Reviewing files that changed from the base of the PR and between a185a1f and b1b08b0.

📒 Files selected for processing: 7
  • quest/m0/ci/README.md
  • quest/m0/ci/platform-macos-zero-rtt.md
  • quest/m0/ci/platform-queue.md
  • rs/moq-quic/README.md
  • rs/moq-quic/src/connection/streams/mod.rs
  • rs/moq-quic/src/connection/streams/state.rs
  • rs/moq-quic/src/tests/mod.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T23:08:21.805498Z b1b08b0 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary:

  • Root cause, not a timeout bump: a server accepted before the second Initial of a split ClientHello refuses a 0.5-RTT open_uni (stream limit 0), and StreamsState::set_params raised the limit later without emitting StreamEvent::Available, so the opener never woke. The fix emits Available in that case, gated on a refused open.
  • Verified locally: late_peer_params_make_streams_available fails without the fix (at the Available assertion) and passes with it; moq-quic and moq-tokio pass (1058 tests).
  • Platform dispatch on this head: macOS passed. Windows failed only on moq-relay::drills relay_killed_mid_group_aborts_then_resumes, the known pre-existing failure tracked by quest/m0/ci/platform-windows-drill.md.
  • Codex reviewed this head with no findings.
  • No public API change, no wire change.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit 6f95a54 Oct 16, 2026
10 of 11 checks passed
@kixelated
kixelated deleted the quest/m0/ci/platform-macos-zero-rtt branch October 16, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant