Skip to content

Draft 16 migration#131

Open
itzmanish wants to merge 39 commits intocloudflare:mainfrom
itzmanish:draft-16
Open

Draft 16 migration#131
itzmanish wants to merge 39 commits intocloudflare:mainfrom
itzmanish:draft-16

Conversation

@itzmanish
Copy link
Copy Markdown
Contributor

No description provided.

@itzmanish itzmanish marked this pull request as draft January 14, 2026 10:10
@itzmanish itzmanish marked this pull request as ready for review January 21, 2026 15:19
itzmanish and others added 17 commits January 23, 2026 17:01
* handles publish_namespace correctly and register to the coordinator
* adds subscribe_namespace request handling
* updates moq-pub which correct publish_namespace and handles incoming
subscribe request at application level
When a TrackReader in the cache has been closed (due to publisher
disconnect, error, etc.), new subscribers would receive the stale
cached reader instead of triggering a fresh upstream subscription.

This change:
- Adds TrackReader::is_closed() to detect closed/dropped tracks
- Updates TracksReader::subscribe() to check liveness before returning
  cached tracks, evicting stale entries when found

Includes unit tests for both the bug scenario and normal deduplication.
Replace is_some() + unwrap() patterns with if-let to satisfy
clippy::unnecessary_unwrap lint in Rust 1.93+.

Affected files:
- moq-pub/src/media.rs
- moq-relay-ietf/src/relay.rs
A standardized test client for MoQT interoperability testing. Implements
test scenarios based on the moq-interop-runner framework.

Test cases:
- setup-only: Connect, complete SETUP exchange, close gracefully
- announce-only: Announce namespace, receive OK
- subscribe-error: Subscribe to non-existent track, expect error
- announce-subscribe: Publisher announces, subscriber subscribes
- subscribe-before-announce: Out-of-order setup handling
- publish-namespace-done: Announce then send PUBLISH_NAMESPACE_DONE

Also enables TLS_DISABLE_VERIFY environment variable support in
moq-native-ietf for containerized testing workflows.

Usage:
  moq-test-client --relay https://localhost:4443
  moq-test-client --relay https://localhost:4443 --test setup-only
  moq-test-client --list
fix: clippy warnings

fix: clippy warning

fix: cargo fmt
* track is_closed was checking for state as dropped, but we consume
track writer when creating stream/subgroup/datagram which drops the
track writer and thus mark the state dropped, because of that
tracks.subscribe() was not returning the reader even though reader was
active. Fixed by checking is_closed on the reader_mode.
itzmanish and others added 6 commits February 12, 2026 17:43
…rrors

Bug: When multiple tracks (audio + video) are played concurrently in
moq-sub, each track's recv_group() writes objects individually to a
shared stdout via Arc<Mutex<O>>. Since fMP4 objects alternate between
moof (metadata) and mdat (media data) boxes, a concurrent task can
acquire the lock between a moof and its corresponding mdat, causing
interleaving:

  [video moof] → [audio moof] → [audio mdat] → [video mdat]

ffmpeg then reads video moof + audio mdat as a single segment, parsing
MP4 traf box bytes (0x74726166) as H.264 NAL unit sizes, producing:

  Invalid NAL unit size (1953653094 > 413)
  Error splitting the input into NAL units

This was not observed on the main branch because the relay's announce-
based subscribe path (TracksReader::subscribe) creates per-subscriber
Track pairs forwarded through the consumer.rs event loop, delivering
objects at the natural publish rate with low interleave probability.

On feat/publish, the relay's TrackInfo/subscribe_upstream architecture
uses shared tracks (OnceLock) with inline forward_upstream(), creating
a tighter setup window that increases concurrent delivery probability
between audio and video tracks.

Fix: Buffer moof objects in recv_group() and write moof+mdat as a
single atomic operation under one lock acquisition, preventing any
interleaving regardless of relay delivery timing.
Upgrade from web-transport v0.3 / web-transport-quinn v0.3 to
web-transport v0.10.4 / web-transport-quinn v0.11.8 (crates.io).

The v0.11.x quinn backend has proper support for:
- H3 SETTINGS: ENABLE_DATAGRAM, WEBTRANSPORT_MAX_SESSIONS,
  ENABLE_CONNECT_PROTOCOL, and Chrome-compat deprecated settings
- Capsule protocol for graceful session close
- Sub-protocol negotiation via wt-available-protocols headers
- GREASE filtering in H3 settings
- Session::raw() for clean raw-QUIC (moqt:// scheme) fallback

API changes adapted:
- ALPN constant changed from &[u8] to &str (.as_bytes() added)
- accept(conn) -> Request::accept(conn) then .ok().await
- connect_with(conn, url) -> Session::connect(conn, request) with
  ConnectRequest carrying the MoQT version as subprotocol
- conn.into() -> Session::raw(conn, url, ConnectResponse::default())
- Three error variants collapsed into one web_transport::Error
- Session methods now take &self instead of &mut self
- read_buf() returns Option<usize> instead of bool
- read_chunk() renamed to read()

The subprotocol negotiation is critical for cross-implementation
WebTransport interop: per draft-15+, version negotiation uses ALPN
for raw QUIC and wt-available-protocols for WebTransport. Without
offering the version as a subprotocol, servers like quiche-moq and
moxygen that enforce WT-Available-Protocols reject the session.
…riber

RequestOk and RequestError are bidirectional messages used as responses
to requests from either side: PUBLISH_NAMESPACE (publisher-originated)
and SUBSCRIBE_NAMESPACE (subscriber-originated) both receive RequestOk
as their acknowledgment.

The run_recv dispatch tried Publisher first, so RequestOk always matched
the Publisher enum and was routed exclusively to the subscriber handler.
When a client sent PUBLISH_NAMESPACE and the relay responded with
RequestOk, the client's subscriber handler couldn't find the request ID
(it belongs to the publisher) and silently dropped the message. This
caused the announce-only and publish-namespace-done interop tests to
time out waiting for a response that was received but never delivered.

Fix: handle RequestOk and RequestError as a special case before the
normal dispatch, trying both subscriber and publisher handlers so the
response reaches whichever side owns that request ID.
…aft-16

Upgrade web-transport crates to v0.10 and add WT subprotocol negotiation
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.

2 participants