This document turns the current transport work into an implementation checklist for moqxr.
Add transport modes that let the existing publisher pipeline send MOQT control and media objects over either:
- direct QUIC with raw MOQT ALPN
- WebTransport over HTTP/3, with MOQT draft negotiation happening inside the WebTransport session
The current repository already handles:
- MP4 parsing
- fragmented MP4 fast-path packaging
- progressive MP4 remux into synthetic fragments
- draft-aware publish planning
The transport work should add:
- QUIC connection management
- HTTP/3 and WebTransport session establishment
- MOQT session setup and control streams
- media object publication over QUIC streams
- transport-level backpressure and error handling
The transport work should not initially add:
- broad muxing or repackaging logic
- advanced QUIC features such as migration or multipath
The intended layering is:
- Packaging layer
Uses
ParsedMp4,SegmentedMp4, andPublishPlan. - Session layer
Converts a
PublishPlaninto MOQT control and object publication actions. - Transport layer Provides connection, stream, and write primitives.
- Transport adapters
Implement the transport layer on top of:
- picoquic raw QUIC callbacks and sockets
- picoquic
h3zero+ WebTransport helpers
This separation is important because MOQT draft churn should stay isolated to the session layer, while raw QUIC and WebTransport remain byte-stream transports.
- Add a transport interface for connect, open stream, write, close
- Add a session façade that consumes
PublishPlan - Add a picoquic client stub that implements the transport interface
- Keep current CLI and packaging flow unchanged
- Add explicit transport selection in CLI/config
- Add a WebTransport client scaffold behind
PublisherTransport
- Add endpoint configuration: host, port, ALPN
- Add TLS configuration hooks: cert, key, CA, insecure-dev toggle
- Establish a client QUIC connection with picoquic
- Report handshake success and failures cleanly
- Require explicit transport path for WebTransport endpoints
- Establish client HTTP/3 connection with ALPN
h3by default - Bring up a WebTransport CONNECT session using picoquic
h3zerohelpers - Map WebTransport stream open/read/write operations onto
PublisherTransport - Report WebTransport session establishment failures cleanly
- Open a control stream after handshake
- Implement setup and session negotiation scaffolding
- Implement namespace or publish announcement flow
- Represent draft-14 and draft-16 control-plane differences behind one abstraction
- Confirm the same
MoqtSessionflow works unchanged on top of WebTransport streams
- Publish initialization object first
- Publish media objects according to
PublishPlan - Decide and document one stream mapping policy
- Use picoquic's callback-driven write path for WebTransport application streams
- Handle transport write backpressure beyond the current callback-driven queue
- Add detailed trace logs for handshake, stream lifecycle, and object publication
- Add unit tests for session-to-transport mapping
- Add loopback integration tests for transport
- Add interoperability tests against a raw OpenMOQ endpoint
- Add manual interoperability coverage against WebTransport-capable endpoints
Current policy:
- one bidirectional control stream per session
- one unidirectional stream per published object
This remains intentionally conservative. It keeps object boundaries explicit and makes current draft-specific control and subscriber-serving logic easier to validate. Stream reuse is still a possible future optimization once backpressure handling is in place.
Owns:
- connection establishment
- stream creation
- byte writes
- close
- connection state
Does not own:
- MOQT message structure
- media packaging
- object scheduling policy
Owns:
- setup and control-plane sequencing
- draft-specific control behavior
- translation from
PublishPlanto transport actions
Does not own:
- raw QUIC callbacks
- MP4 parsing
- object bytes
Owns:
- picoquic configuration and lifecycle
- callback bridging
- stream IDs and write execution
- error translation into transport-level status objects
Owns:
- HTTP/3 session establishment over picoquic
- WebTransport CONNECT setup using
h3zeroand picoquic WebTransport helpers - mapping WebTransport streams to transport stream operations
- error translation into transport-level status objects
Does not own:
- MOQT draft semantics
- MOQT control messages
- media packaging
- Land transport selection and factory scaffolding
- Keep raw QUIC defaults stable while separating transport-specific ALPN behavior
- Implement a connect-only WebTransport client using picoquic
h3zero - Add WebTransport stream mapping
- Reuse
MoqtSessionon top of the new transport - Add interoperability coverage before optimizing backpressure or stream reuse
- The transport seam and session façade are implemented.
- CLI flags for endpoint, transport, ALPN, and TLS-related parameters are present.
- The build integrates local picoquic, picohttp, and picotls source checkouts directly.
- Raw QUIC and WebTransport publisher transports both build and pass local transport tests.
- The session layer uses a dedicated control-message encoder that keeps draft-14 and draft-16 naming differences out of the transport adapter.
- Subscriber-driven serving is implemented for
--forward 0, including multitrack publication in publish-plan/media-time order rather than draining one subscribed track completely before the next. - Incremental downstream
SUBSCRIBEhandling lets later-arriving tracks join future object servicing without restarting the session or losing interleaving for remaining media objects. - WebTransport mode is implemented on picoquic
h3zerohelpers and uses callback-driven WT app-stream writes instead of direct stream pushes. - Current live interoperability results:
<moqx-la-relay-host>:4433/moq-relayand<moqx-ord-relay-host>:4433/moq-relaycomplete verified-TLS draft-16 WebTransport setup and reachPUBLISH_NAMESPACE_OKmoq-relay.red5.net:4433/moqcompletes verified-TLS draft-16 WebTransport setup, reachesPUBLISH_NAMESPACE_OK, accepts a downstreamSUBSCRIBEforcatalog, and serves the catalog objectmoq-relay.red5.net:4433/moq-relayrejects WebTransport CONNECT with HTTP404; use/moqfor that relay- historical endpoints such as
draft-14.cloudflare.mediaoverquic.comandfb.mvfst.net:9448are retained as reference points, but are not the primary draft-16 validation targets
- After
PUBLISH_NAMESPACE_OK, an idle--forward 0publisher now exits cleanly after the subscriber timeout, emitsPUBLISH_NAMESPACE_DONE, and does not treat the absence of downstreamSUBSCRIBEas a publish failure.
- draft-14 vs draft-16 control differences leaking into transport code
- draft-16 message parameter rules drifting from the spec;
SUBSCRIBE_NAMESPACEandPUBLISH_OKhave dedicated regression coverage now - coupling raw QUIC or WebTransport callback state too tightly to publish scheduling
- incomplete backpressure behavior once object volume or pacing pressure increases
- treating H3 ALPN and MOQT draft signaling as the same layer in WebTransport mode
- keep draft-specific message encoding in session code
- keep transport status and callbacks generic
- keep the current one-object-per-stream policy until backpressure and reuse semantics are explicit
- add integration tests before optimizing stream reuse or pacing
- keep WebTransport session establishment concerns inside
WebTransportClient, notMoqtSession