Skip to content

feat(moq-transport): add draft-19 stream core#41

Merged
kkroo merged 2 commits into
mainfrom
multicastengineer/blo-16780-draft19-core
Jul 19, 2026
Merged

feat(moq-transport): add draft-19 stream core#41
kkroo merged 2 commits into
mainfrom
multicastengineer/blo-16780-draft19-core

Conversation

@allyblockcast

@allyblockcast allyblockcast Bot commented Jul 18, 2026

Copy link
Copy Markdown

Summary

  • add an explicit, non-advertised WireProfile::Draft19 transport core
  • implement draft-19 vi64, unified SETUP (0x2f00), length-bounded setup options, and generic vi64 message framing
  • establish paired unidirectional control streams and dedicated bidirectional request streams over WebTransport
  • enforce first-request/first-response, FIN, RESET_STREAM, and STOP_SENDING lifecycle rules with draft-19 codes
  • keep the draft-16 codec untouched and pin the moqt-16-v1 fixture digest

Verification

  • CARGO_HOME=/runtime-cache/tmp/opencode/moq-rs-cargo-home cargo test -p moq-transport
    • 236 unit tests passed
    • 12 draft-19 wire/lifecycle tests passed
    • moqt_16_wire_vectors_are_byte_exact_and_round_trip passed
  • CARGO_HOME=/runtime-cache/tmp/opencode/moq-rs-cargo-home cargo clippy -p moq-transport --all-targets -- -D warnings
  • cargo fmt --all -- --check

Scope

This intentionally does not add moqt-19 to native QUIC ALPN or WebTransport protocol advertisement. Exact negotiation is tracked separately after this framing and stream foundation lands.

Paperclip: https://paperclip.blockcast.net/BLO/issues/BLO-16780

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@allyblockcast

allyblockcast Bot commented Jul 18, 2026

Copy link
Copy Markdown
Author

🔗 Paperclip issue: BLO-16780

1 similar comment
@allyblockcast

allyblockcast Bot commented Jul 18, 2026

Copy link
Copy Markdown
Author

🔗 Paperclip issue: BLO-16780

@allyblockcast

allyblockcast Bot commented Jul 18, 2026

Copy link
Copy Markdown
Author

@ally Please review the draft-19 wire and state-machine boundaries, especially non-minimal vi64 decoding, SETUP option delta/parity handling, paired unidirectional control-stream closure, and SUBSCRIBE/PUBLISH FIN + RESET_STREAM/STOP_SENDING transitions. Confirm that the explicit profile cannot alter the pinned moqt-16-v1 path.

@allyblockcast allyblockcast Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ally — Consolidated PR Review

Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex (Codex/OpenCode nested CLI unavailable in this k8s Job pod; adversarial pass applied directly against /tmp/pr.diff).

reviewed head: 688f731

This is a self-review (PR author resolves to my own App identity, app/allyblockcast); running the full pipeline per policy and posting via my distinct reviewer identity.

Important Issues (1)

  • [native-codex] moq-transport/src/session/draft19.rs:187-191Draft19RequestStream::receive_first_response panics instead of erroring on a reachable state:
    if self.receiver.done().await? {
        self.lifecycle.receive_fin()?;
        unreachable!("premature FIN must fail")
    }
    receive_fin() only errors while receive_required_before_fin is still true, which holds on the first call. After a successful first response for a non-Subscribe kind (Fetch/TrackStatus/PublishNamespace/SubscribeNamespace/SubscribeTracks), that flag is cleared to false. A second call to this method after the stream is done then makes receive_fin() succeed, and execution falls through to unreachable!(), which panics. The sibling receive_message() (lines ~226-236) handles the identical scenario correctly by returning Ok(None) via ?/early-return instead of assuming an invariant — this method should follow the same pattern (propagate StreamProtocolError::PrematureFin explicitly rather than relying on unreachable!()). No test covers this async wrapper's edge case (only the underlying RequestStream state machine is tested directly in draft19_wire.rs), so the gap wasn't caught by CI.

Suggestions (2)

  • [pr-review-toolkit] moq-transport/src/profile/draft19.rs:366-372RequestKind::success_response maps Publish, TrackStatus, PublishNamespace, SubscribeNamespace, and SubscribeTracks all to the same response code 0x07, while only Subscribe (0x04) and Fetch (0x18) get distinct codes. Worth double-checking this against the draft-19 message-type registry — if these five request kinds actually have distinct "Ok" response types, first-response validation would silently accept the wrong response for four of them.
  • [gstack/review] moq-transport/src/session/draft19.rsprotocol_error is duplicated verbatim on both Draft19Session (lines ~55-60) and Draft19RequestStream (lines ~168-173). Could be a shared free function taking &web_transport::Session to avoid the copy.

Strengths

  • Vi64 encode/decode is correct and thoroughly verified against literal test vectors, including boundary lengths (1, 2, 3, 8, 9-byte forms) and non-minimal encodings.
  • Legacy moqt-16-v1 fixture isolation is well done: pinned FNV-1a digest guards against silent fixture drift, and the profile-crossed negative test confirms rejection without consuming bytes.
  • RequestStream's state machine (FIN/reset/STOP_SENDING transitions) has solid direct unit coverage across Subscribe/Publish/Fetch/TrackStatus request families.

Recommended Action

  1. Fix the unreachable!() panic path in receive_first_response before this API is wired into higher-level session code.
  2. Verify the success_response code assignments against the draft-19 message-type registry.
  3. Suggestion on protocol_error duplication is opportunistic — take or leave.

@kkroo
kkroo merged commit 039b389 into main Jul 19, 2026
2 checks passed
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