Repository navigation
feat(moq-webrtc)!: remove peer-to-peer and the relay's STUN responder - #8771
Conversation
moq-dev/moq keeps what a large live-media platform uses. Peer-to-peer routing, with browsers and native nodes forwarding for each other, moves to a downstream product that re-plans it there (maintainer decision 2026-11-14). Git history keeps the code for a later port. Removed: - moq-webrtc's `p2p` module and feature (MoQ over a data channel, host candidates per interface, mDNS `.local` resolution) and the ICE agent's STUN Binding client and trickle events, which only it used. - The vendored sctp-proto and str0m's data channels (about 25k lines), which only the data-channel transport used. WHIP/WHEP keep str0m, dimpl, and the `is` ICE agent. - The private `@moq/p2p` package, `test/p2p`, its interop CI step, and its nightly bench. - moq-relay's public STUN responder: the `stun` feature, the `[stun]` config, `--stun-bind` / `MOQ_STUN_BIND`, the `moq_relay::stun` module, and its `moq_relay_stun_*` metrics. - The stun-types dependency, and if-addrs from the workspace. mdns-sd stays for LAN cluster discovery. - The P2P, browser mesh, and WHIP-without-SCTP quests. Public API: moq-webrtc loses the `p2p` feature and module; moq-relay loses the `stun` feature, its config section, flag, env var, module, and metrics. None of it was ever released: `origin/release` ships moq-rtc with no data-channel transport and moq-relay 0.17.16 with no STUN responder, so no MIGRATE.md entries are needed. Migration: a relay config with `[stun]`, `--stun-bind`, or `MOQ_STUN_BIND` must drop it, and an application that listed the relay as a STUN server points ICE at a dedicated STUN server instead. Users of `moq_webrtc::p2p` or `@moq/p2p` stay on an earlier commit or port the code from history. Wire: a WHIP or WHEP offer's `m=application` (data channel) section is now answered rejected (port 0, left out of BUNDLE) instead of accepted with an SCTP association nobody read. Audio and video negotiate as before. moq-lite and moq-transport are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Important
Rejecting m=application moves the WHIP/WHEP answer's ICE candidates onto a rejected line whenever the offer lists its data channel first. Details inline.
Reviewed changes
I read every non-vendored change line by line and skimmed the deleted vendored and test code for anything that crossed into the kept paths.
- moq-webrtc
p2pand SCTP removed. Thep2pmodule and feature, vendoredsctp_proto, and str0m'schannel/sctpmodules are gone. str0m'sSdpApilosesadd_channel*and SNAP, andpoll_outputstops looping for SCTP. - The ICE agent drops its STUN client.
Agent::nextnow returnsstr0m::Eventdirectly.Phase::Heldand the gathering hold are gone, so the deadline starts atstarted. - Offered data channels are answered rejected. The app m-line is emitted as
disabled: true(port 0) and left out of BUNDLE. A new test covers an offer whose data channel comes after its audio. - moq-relay's STUN responder removed. The
stunfeature,[stun],--stun-bind, andmoq_relay_stun_*metrics are gone.MOQ_STUN_BINDnow falls under the existing rule that refuses unknownMOQ_*variables at startup. - JS, CI, and docs cleanup.
@moq/p2p,test/p2p, the interop step, the nightly benches, theselect.shfeature, the OSS-scanner build, and the threat model are updated. A grep outsidequest/finds no stale references.origin/releaseships no moq-tokio or moq-cliwebrtcfeature, so dropping thatupgrade.mdnote is safe.
claude-opus-5-5 | 𝕏
An offer that puts its data channel first had every candidate on the rejected line, which is out of the BUNDLE group. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # rs/moq-relay/src/settings.rs
There was a problem hiding this comment.
✅ No new issues found. The fix for the earlier candidate-placement finding is correct.
Reviewed changes
This pass covers the two commits pushed since the last Pullfrog review at c947a7d.
- Moved answer candidates to the first accepted m-line.
as_sdpnow builds every line withmedia_attributes(false). Afterpending.apply_to(which can flipdisabled), it splices theCandidateattributes onto the first non-disabled line, at the same position in the attribute list as before, and falls back to index 0 when no line is accepted. This also covers a rejected audio or video line at index 0. - Added
candidates_skip_a_rejected_first_line. The test sends an offer whosem=applicationcomes first. It checks that the rejected line carries no candidate and the accepted audio line does. - Applied rustfmt. Whitespace changes only.
claude-opus-5-5 | 𝕏
There was a problem hiding this comment.
✅ No new issues found. The only change since the last review is a merge of
main, and it resolves cleanly.
Reviewed changes
This pass covers the merge pushed since the last Pullfrog review at cb327ea.
- Merged
maininto the branch. Onmain, #8747 deletedrs/moq-relay/src/settings.rs, and the settings registry now comes fromConfigthroughconfig::registry(). The PR's deletion of theStunsettings struct therefore drops out of the diff. RemovingConfig::stunalone is enough to remove[stun],--stun-bind, andMOQ_STUN_BIND. A grep outsidequest/finds no remainingfeature = "stun",MOQ_STUN,stun-bind, or p2p references.Discard::Stunininternal.rsis the uring demux drop counter. It is unrelated to this PR and stays.
claude-opus-5-5 | 𝕏
|
quest land watch: the merge queue removed this pull request at e9f4ca1 because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
codex, gpt-6.1-sol, medium effort land fixer note:
(written by codex, gpt-6.1-sol, medium effort) |
|
codex, gpt-6.1-sol, medium effort land fixer: CONFLICT (content): Merge conflict in bun.lock Auto-merging nix/Cargo.nix Auto-merging package.json Auto-merging quest/m3/mesh/README.md Automatic merge failed; fix conflicts and then commit the result. (written by codex, gpt-6.1-sol, medium effort) |
# Conflicts: # bun.lock
There was a problem hiding this comment.
✅ No new issues found. The only change since the last review is another merge of
main, and it resolves cleanly.
Reviewed changes
This pass covers the merge pushed since the last Pullfrog review at e9f4ca1.
- Merged
maininto the branch. The range-diff shows only shifted context inbun.lock, wheremainadded the@moq/obsworkspace andtypescript7.0.2, and inquest/m3/mesh/README.md, wheremainedited the Related list this PR also touches. None of the PR's own edits changed, and the earlier candidate-placement fix invendor/str0m/change/sdp.rsis unchanged.
claude-opus-5-5 | 𝕏
Conflicts: main removed the relay's STUN responder (#8771), so the handoff no longer carries a STUN socket (Role::Stun and Sockets::udp go too). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main dropped TCP sockets (#8772) and peer-to-peer (#8771). The track socket's messages, main's new tests, and the interop socket clients now key each message's group, since a socket track is scale-less. A lite-07 test helper stamps its frame with its group's key, as the first frame's absolute delta must. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…om the media and gateway crates moq-audio's aac, bus, and aec, moq-ffi's audio and video, moq-rtmp's tls, and moq-quic's mux always compile, and moq-video's dmabuf compiles on Linux. v4l2 joins the defaults of moq-video, moq-transcode, and moq-cli beside vaapi and nvidia. moq-webrtc's p2p already went with #8771. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Summary
moq-dev/moq keeps what a large live-media platform uses. Peer-to-peer
routing, with browsers and native nodes forwarding for each other, moves
to a downstream product that re-plans it there (maintainer decision
2026-11-14). Git history keeps the code for a later port.
Removed:
p2pmodule and feature (MoQ over a data channel, hostcandidates per interface, mDNS
.localresolution) and the ICE agent'sSTUN Binding client and trickle events, which only it used.
which only the data-channel transport used. WHIP/WHEP keep str0m, dimpl,
and the
isICE agent.@moq/p2ppackage,test/p2p, its interop CI step, andits nightly bench.
stunfeature, the[stun]config,
--stun-bind/MOQ_STUN_BIND, themoq_relay::stunmodule,and its
moq_relay_stun_*metrics.stays for LAN cluster discovery.
Impact
Public API: moq-webrtc loses the
p2pfeature and module; moq-relayloses the
stunfeature, its config section, flag, env var, module, andmetrics. None of it was ever released:
origin/releaseships moq-rtcwith no data-channel transport and moq-relay 0.17.16 with no STUN
responder, so no MIGRATE.md entries are needed.
Migration: a relay config with
[stun],--stun-bind, orMOQ_STUN_BINDmust drop it, and an application that listed the relayas a STUN server points ICE at a dedicated STUN server instead. Users of
moq_webrtc::p2por@moq/p2pstay on an earlier commit or port thecode from history.
Wire: a WHIP or WHEP offer's
m=application(data channel) section isnow answered rejected (port 0, left out of BUNDLE) instead of accepted
with an SCTP association nobody read. Audio and video negotiate as
before. moq-lite and moq-transport are unchanged.
Decisions
Taken while the maintainer was away, for review:
Client::connect_with,Listener::accept_with, and theqmuxestablished-elsewhere path, built for P2P, stay: they are the hook Kixel's port would use, and removing them breaks moq-tokio (rejected: deleting them now).webrtc-sctp-featurequest).Validation
just checkin the dev shell passes after mergingmain(Rust lint and tests, JS, gh, quest, nix).candidates_skip_a_rejected_first_linecovers it (it fails without the fix).moq-relaybinary refuses--stun-bindwith a usage error and a[stun]config with "unknown fieldstun".quest check: 484 documents ok.Follow-ups
None. The P2P quests now live in kixel.ai's
quest/m3/p2p/(kixel-ai/kixel.ai#98). Expect a small conflict with moq-dev/moq#8756, which deletesquest/m3/mesh/andquest/m5/mesh-ice.mdthat this edits.Models
Size: L
Implementer: Claude Code, claude-opus-5-5, unknown effort
🤖 Generated with Claude Code
(Written by Opus 5.5)
Review
Rewritten by
quest reviewafter each round.Head: a2b9216
Base: origin/main at 2f328ef
Risk: high,
it changes .github/workflows/interop.yml, which is always high, as are 1 more of its paths: workflows run with the repository's secrets and decide what merges and shipsClassified: high by the always-high paths
Reviewer: Codex, gpt-6.1-sol, xhigh effort
Session:
01a1dbcf-f22d-7393-9760-0d1d2cc98f16, round 4Score: 10/10,
The update only merges main, and the merge resolutions preserve the reviewed removals while retaining upstream additions without new issues found by code inspection.Rounds: 4; first round 1 (medium 1); findings 1 (medium 1): fixed 1, refuted 0, open 0
Findings: none