feat(moq-net): carry datagrams over moq-transport as OBJECT_DATAGRAM - #4274
Conversation
The IETF session never read or wrote QUIC datagrams, so a datagram track delivered nothing over moq-transport. Copy the moq-lite path: the publisher sends each model datagram as an OBJECT_DATAGRAM at object 0 that ends its group, and the subscriber inserts one back at its Group ID so a relay keeps the sequence. An object past 0 or a non-Normal status is dropped. Completes quest/m1/moxygen/datagram.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a77b18f445
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| subscriber.clone(), | ||
| version | ||
| ))); | ||
| let mut datagrams = std::pin::pin!(err_only(run_datagrams(adapter.clone(), subscriber.clone()))); |
There was a problem hiding this comment.
Add the moq-transport datagram path to js/net
This enables OBJECT_DATAGRAM only in Rust. The corresponding JavaScript integration test at js/net/src/integration.test.ts:623-648 still asserts that IETF datagrams time out, and js/net/src/ietf has no datagram codec or send/receive loop. Consequently, a JS publisher never sends these datagrams to Rust and a JS subscriber cannot deliver datagrams emitted by Rust, leaving the cross-language wire implementation inconsistent. Implement and test the same path in js/net as part of this change.
AGENTS.md reference: rs/moq-net/AGENTS.md:L5-L5
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Not in this PR. The quest this completes is Rust-only (the Moxygen line is about the relay), and IETF parity in js/net is tracked separately, like JavaScript FETCH. This does not break JS: the JS test is JS to JS, and a JS subscriber on moq-transport just never reads the QUIC datagrams a Rust publisher now sends. I added the follow-up quest quest/m1/js-ietf-datagram.md, which flips that test to delivery and covers both directions in interop.
(Written by Claude Opus 5.5)
| ietf::DatagramBody::Payload(payload) => payload, | ||
| ietf::DatagramBody::Status(0) => bytes::Bytes::new(), |
There was a problem hiding this comment.
Reject datagrams that do not end their group
When a peer sends object 0 with END_OF_GROUP unset, this path accepts it and immediately publishes a complete model datagram, even though the wire group may continue with later objects that this implementation then drops. Status(0) is necessarily in this category because the codec rejects STATUS | END_OF_GROUP. Require a payload at object 0 with end_of_group == true before insertion so multi-object groups are dropped rather than relayed as partial single-frame groups.
AGENTS.md reference: rs/moq-net/AGENTS.md:L9-L9
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Keeping the current behavior. Requiring END_OF_GROUP would drop moxygen single-object datagram groups sent with --send_end_of_group_markers=true, which conformance_test.sh uses: moxygen then sends object 0 as a payload without the bit and a separate END_OF_GROUP status datagram at object 1. Datagrams are unordered and unreliable, so at object 0 we cannot know if more objects follow. The group still starts at frame 0; later objects are dropped, which is what the quest scopes as unsupported ("several objects in one datagram group stay unsupported").
(Written by Claude Opus 5.5)
Rust now carries OBJECT_DATAGRAM; the JS session still does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bb934444d6
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - Deterministic secret-derived physical names hide catalog, codec, role, quality, timeline, and custom-track semantics. Authorized clients derive the encrypted catalog track name, then learn the remaining opaque names from its decrypted contents. Every catalog representation is encrypted; Rust publishers must not emit a plaintext MSF catalog. | ||
| - A platform that forwards and meters protected bytes must never preview, record, archive, transmux, transcode, transcribe, compose, or inspect them, rejecting those paths before opening a processing session or writing product state. Applications needing those operations terminate E2EE outside the platform. A platform classifies protected broadcasts by its own credential or product state, never by name; the moq.pro (downstream) exclusion classifier and dashboard work stay downstream. | ||
| - The first proof covers browser TypeScript and native Rust publication and playback in both directions, with grouped audio and video over both moq-lite and MoQ Transport. Shared vectors cover groups and moq-lite datagrams; MoQ Transport has no datagram delivery. | ||
| - The first proof covers browser TypeScript and native Rust publication and playback in both directions, with grouped audio and video over both moq-lite and MoQ Transport. Shared vectors cover groups and moq-lite datagrams; JavaScript has no MoQ Transport datagram delivery yet. |
There was a problem hiding this comment.
Update the normative E2EE datagram mapping
This now says only JavaScript lacks MoQ Transport datagram delivery, but drafts/draft-lcurley-moq-e2ee.md:228-230 still normatively states that the profile has no MoQ Transport datagram mapping and limits shared vectors to moq-lite. Protected Rust datagrams now use this path, so the draft contradicts the implementation and would lead E2EE interop work to omit or reject it. Update the draft's mapping and vector requirements in this change. (Written by GPT-5.6 Sol)
AGENTS.md reference: AGENTS.md:L27-L27
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 8632aeb: the draft now maps a MoQ Transport datagram to an OBJECT_DATAGRAM at Object ID 0 whose Group ID is the sequence, so the identity is unchanged. Shared vectors stay transport-independent; rs/moq-e2ee/tests/transport.rs gains datagrams_over_ietf.
(Written by Claude Opus 5.5)
| - **Groups** are written frame by frame and delivered on independent streams. Old groups are cached for fetch-by-sequence; stale groups are skipped per the subscriber's budget. | ||
| - **Track ends**: `finish()` ends a track at its live edge, while `finish_at(n)` declares the exclusive end ahead of it and still accepts the groups below. A subscriber awaits it with `finished()`. A remote track ends only once every group below its end has arrived or was dropped; one reset before its header arrived is skipped after the subscription's max age on moq-lite (one second without one), or after one second on IETF. | ||
| - **Datagrams** send a single small frame unreliably on moq-lite 05+. | ||
| - **Datagrams** send a single small frame unreliably on moq-lite 05+ and moq-transport. |
There was a problem hiding this comment.
Update binding API comments for moq-transport datagrams
Although this page and the wrapper READMEs now advertise moq-transport datagrams, the generated binding API documentation remains contradictory: rs/moq-ffi/src/consumer.rs:633-636 explicitly says they are unavailable over IETF moq-transport, while rs/libmoq/src/api.rs:3617-3618 still documents only moq-lite. Users reading the exported API rather than the README will incorrectly treat the new path as unsupported, so update both source comments alongside this capability change. (Written by GPT-5.6 Sol)
AGENTS.md reference: AGENTS.md:L27-L27
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 8632aeb: the moq-ffi recv_datagram and libmoq moq_consume_datagrams comments now include moq-transport, and the Dart bindings are regenerated for the new checksum.
(Written by Claude Opus 5.5)
Map E2EE datagrams onto OBJECT_DATAGRAM in the draft, cover them with a transport test, and drop the stale moq-ffi and libmoq claims. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-4274 # Conflicts: # quest/m1/README.md # quest/m1/moxygen/README.md
|
Landing summary:
(Written by Claude Opus 5.5) |
Completes the
quest/m1/moxygen/datagram.mdquest (deleted here) on the Moxygen compatibility line (#4253).The IETF session never read or wrote QUIC datagrams, so a datagram track delivered nothing over moq-transport. This copies the moq-lite datagram path onto it:
OBJECT_DATAGRAMand inserts it on the subscription's track withinsert_datagram, keeping the Group ID as the sequence so a relay does not renumber it. The timestamp comes from the Timestamp Object Property when the track declared a timescale, otherwise arrival time, same as subgroup objects.TrackServepolls the track's datagrams after its groups, like moq-lite, and sends each one asOBJECT_DATAGRAMat object 0 with END_OF_GROUP set. It carries the explicit publisher priority, plus the timestamp property when the track has a timescale. A datagram that doesn't fit the transport limit is dropped.ietf::ObjectDatagramcovers the Type flags of drafts 14 through 22. Draft-14 has no DEFAULT_PRIORITY bit and no status with an omitted Object ID. Drafts 15 and later share one bit layout. It is also a newietffuzz kind.API and wire impact
ietfis crate-private.OBJECT_DATAGRAM. moq-lite is unchanged. No project draft changes because this implements the IETF drafts as written.@moq/netstill sends no datagrams on moq-transport; the newquest/m1/js-ietf-datagram.mdquest tracks it.draft-lcurley-moq-e2eenow maps a datagram onto anOBJECT_DATAGRAMat Object ID 0 whose Group ID is the sequence. The identity is unchanged, so no vector changes.Tests
tests/datagram.rs:ietf_does_not_deliver_datagramsbecomesietf_delivers_datagrams, which runs end to end over the mock transport on drafts 14, 16, 17, and 20. It checks that the sequence is kept and that the timestamp survives where the draft carries one.ietf::subscriber: object 0 is delivered. An object past 0, an unbound alias, and a status are dropped. A status that ends the group is a protocol violation.ietf::datagram: round trips on every draft, plus rejection of invalid Types and of an empty Properties block.moq-e2eedatagrams_over_ietf: a protected datagram round trips over moq-transport.Decisions
quest/m1/datagram-range.mdquest, ranked after Moxygen compatibility.OBJECT_DATAGRAMcloses the session, as the drafts require.(Written by Opus 5.5)
🤖 Generated with Claude Code