Skip to content

feat(moq-net)!: sockets drop the tcp protocol - #8772

Merged
kixelated merged 3 commits into
mainfrom
remove-socket-tcp
Nov 15, 2026
Merged

kixelated merged 3 commits into
mainfrom
remove-socket-tcp

Conversation

@kixelated

@kixelated kixelated commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

moq-dev/moq keeps what a large live-media platform would use. A reliable
byte pipe over MoQ is not that, so it moves downstream, where it can be
built on moq-net's public API. Sockets keep the track protocol, which
MoQ Boy's crowd input and the CARLA demo use.

Removed, per language:

  • Rust (moq-net): socket::TcpStream, Endpoint::dial_tcp,
    Endpoint::poll_accept_tcp / accept_tcp, and the per-session pump on the
    origin's driver. With one stream type left, Incoming, Dialing and
    Accepting are no longer generic and the Stream trait is gone:
    Incoming<TrackStream> is now Incoming.
  • JS (@moq/net): socket.TcpStream, Endpoint.dialTcp, Endpoint.acceptTcp.
    Incoming is no longer generic; accept(info?, options?) returns a
    TrackStream.
  • moq-ffi: MoqSocketEndpoint::dial_tcp / accept_tcp,
    MoqSocketIncomingTcp, MoqSocketTcpStream.
  • C (moq-c): moq_socket_dial_tcp, moq_socket_accept_tcp; a stream's
    writer is always a raw track handle.
  • Swift, Kotlin, Go, Python, Dart wrappers: their dialTcp/DialTCP/
    dial_tcp, acceptTcp/AcceptTCP/accept_tcp, IncomingTcp/
    IncomingTCP, and TcpStream/TCPStream. Dart's generated bindings are
    regenerated.

dial_track, accept_track, TrackStream and the endpoint itself are
unchanged in every language.

Also removed, from #8741, which
merged while this was in review: moq-tokio's socket::TcpStream, the moq
CLI's tcp dial / tcp accept forwarding and its doc section,
dial_tcp's priority argument in Rust and JS (Socket.TcpOptions), and
the new quest/m1/stream/relay-eviction.md, which moves to Kixel with the
other byte-stream quests (kixel-ai/kixel.ai#105). #8741's kio clock test fix
and the public group::Consumer::poll_next_frame stay.

Impact

Sockets are not on release, so no published user is affected, and no
MIGRATE.md entry is added. A main user of a tcp session moves to a track
session, writing each message as a group, or builds a byte stream on
moq-net's track and group API.

The cut must drop or rewrite these Unreleased MIGRATE.md notes, which
predate this PR, so that none ships in a version section:

  • The socket notes that describe TCP halves: swift, dart/moq, go/wrapper,
    cpp/moq, c/moq, py/moq-rs, kt/moq, rs/moq-ffi, js/net (the TcpStream,
    dialTcp/acceptTcp, and TCP-reader lines), and rs/moq-net (the tcp
    sessions clause).
  • The GroupProducer.ready notes in swift, dart/moq, go/wrapper, cpp/moq,
    py/moq-rs, kt/moq, and rs/moq-ffi: drop their closing clause that ties
    ready to TCP socket streams, and keep the rest.

Wire: no message or encoding changes. Session track names keep their
leading track protocol segment. A tcp/... dial now reaches an endpoint
as an unknown protocol and is reset as unsupported, as any other unknown
protocol already was. doc/concept/socket.md drops the tcp section.

Quests: the byte-stream quests (m1/stream, m4/stream-js, m5/ffi-stream,
m9/stream-bench) are removed, with the prose that linked them.

Decisions

Taken while the maintainer was away, for review:

Validation

  • just check in the dev shell passes after merging main with feat(net)!: Rust byte streams over a socket session, with TCP forwarding in moq #8741 (ce7829d); quest check 490 documents ok.
  • just test interop --sockets and just test interop --all pass.
  • Socket tests: moq-net, moq-ffi, moq-c, and moq-relay (socket_auth), 30 JS, 8 Python; just go check, just dart check, and just kt check pass. Swift was not compiled here (no toolchain); CI covers it.
  • Breaking the abandoned-dial pruning on purpose fails the rewritten queue test.

Follow-ups

None. Byte streams are planned in kixel.ai (quest/m0/mesh/streams.md, kixel-ai/kixel.ai#98). Expect a small conflict with moq-dev/moq#8756, which deletes quest/m3/mesh/ that 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 review after each round.

  • Head: ce7829d

  • Base: origin/main at 2f328ef

  • Risk: high, Removing TCP socket APIs and CLI forwarding can break downstream applications and scripts, requiring a revert or downstream migration.

  • Classified: medium by default

  • Reviewer: Codex, gpt-6.1-sol, xhigh effort

  • Session: 01a1dc04-13f7-7182-8bab-d507eecc0215, round 2

  • Score: 9/10, No actionable defects were found in the merge changes, but builds and tests were not run as instructed, leaving runtime validation unverified.

  • Raised the risk to high: Removing TCP socket APIs and CLI forwarding can break downstream applications and scripts, requiring a revert or downstream migration.

  • Rounds: 2; first round 0; findings 0: fixed 0, refuted 0, open 0

  • Findings: none

kixelated and others added 2 commits November 14, 2026 13:30
moq-dev/moq keeps what a large live-media platform would use. A reliable
byte pipe over MoQ is not that, so it moves downstream, where it can be
built on moq-net's public API. Sockets keep the `track` protocol, which
MoQ Boy's crowd input and the CARLA demo use.

Removed, per language:
- Rust (moq-net): `socket::TcpStream`, `Endpoint::dial_tcp`,
  `Endpoint::poll_accept_tcp` / `accept_tcp`, and the per-session pump on the
  origin's driver. With one stream type left, `Incoming`, `Dialing` and
  `Accepting` are no longer generic and the `Stream` trait is gone:
  `Incoming<TrackStream>` is now `Incoming`.
- JS (@moq/net): `socket.TcpStream`, `Endpoint.dialTcp`, `Endpoint.acceptTcp`.
  `Incoming` is no longer generic; `accept(info?, options?)` returns a
  `TrackStream`.
- moq-ffi: `MoqSocketEndpoint::dial_tcp` / `accept_tcp`,
  `MoqSocketIncomingTcp`, `MoqSocketTcpStream`.
- C (moq-c): `moq_socket_dial_tcp`, `moq_socket_accept_tcp`; a stream's
  writer is always a raw track handle.
- Swift, Kotlin, Go, Python, Dart wrappers: their `dialTcp`/`DialTCP`/
  `dial_tcp`, `acceptTcp`/`AcceptTCP`/`accept_tcp`, `IncomingTcp`/
  `IncomingTCP`, and `TcpStream`/`TCPStream`. Dart's generated bindings are
  regenerated.

`dial_track`, `accept_track`, `TrackStream` and the endpoint itself are
unchanged in every language.

Migration: sockets are not on `release`, so no published user needs one,
and no MIGRATE.md entry is added. The Unreleased MIGRATE.md notes that
describe TCP halves (moq-ffi, Python, Go, Kotlin, Swift, Dart, C, C++,
@moq/net, moq-net) predate this and should be dropped at the cut rather
than carried into a version section. A `main` user of a tcp session moves
to a track session, writing each message as a group, or builds a byte
stream on moq-net's track and group API.

Wire: no message or encoding changes. Session track names keep their
leading `track` protocol segment. A `tcp/...` dial now reaches an endpoint
as an unknown protocol and is reset as unsupported, as any other unknown
protocol already was. doc/concept/socket.md drops the `tcp` section.

Quests: the byte-stream quests (m1/stream, m4/stream-js, m5/ffi-stream,
m9/stream-bench) are removed, with the prose that linked them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Socket sessions now use track streams only across the core implementation, language bindings, and CLI. The changes remove TCP-specific APIs, stream adapters, forwarding commands, and protocol branches. Tests, benchmarks, and interop harnesses now exercise track sessions, including ordering, cancellation, resets, endpoint closure, and routing. Documentation and project notes also remove or revise descriptions of TCP socket sessions and proposed byte-stream support.

Merge Risk: Minimal · up to ce782

This change removes the TCP socket sessions and leaves track sessions as the only socket API, which breaks callers of the removed TCP APIs by design. The remaining track paths keep their reliable ordering and unsupported-hop behavior. No concrete merge-blocking risk was found.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title "feat(moq-net)!: sockets drop the tcp protocol" matches the main change. The changeset removes the TCP socket protocol across Rust, JavaScript, FFI, C, Swift, Kotlin, Go, Python, and Dart, w…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description is specific and related to the changeset. It states that the PR removes TCP socket support across Rust, JS, FFI, C, Swift, Kotlin, Go, Python and Dart, and that the track APIs remain. …
Full details: Title check

Explanation

The title "feat(moq-net)!: sockets drop the tcp protocol" matches the main change. The changeset removes the TCP socket protocol across Rust, JavaScript, FFI, C, Swift, Kotlin, Go, Python, and Dart, while the track protocol remains. The title is specific, concise, and follows a conventional-commit style with the breaking-change marker.

Full details: Description check

Explanation

The description is specific and related to the changeset. It states that the PR removes TCP socket support across Rust, JS, FFI, C, Swift, Kotlin, Go, Python and Dart, and that the track APIs remain. It also lists the removed APIs per language, the byte-stream quest removals, the wire impact, and the validation performed. This matches the changeset summaries, so the description check passes.

Finishing Touches

Simplify code

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

Clippy (1.99.1)

Clippy execution timed out

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3a7aed58-6b69-40c6-bc5f-2b4ae231756f
Commits

Reviewing files that changed from the base of the PR and between 3a48cbf and ce7829d.

Files ignored due to path filters: 1

  • Cargo.lock is excluded by !**/*.lock
Files selected for processing: 59

  • dart/moq/lib/socket.dart
  • dart/moq_ffi/lib/src/moq.dart
  • doc/bin/cli.md
  • doc/concept/index.md
  • doc/concept/socket.md
  • doc/lib/js/net.md
  • doc/lib/py/index.md
  • doc/lib/rs/moq-net.md
  • go/wrapper/bridge.go
  • go/wrapper/internal/bridge/handles.go
  • go/wrapper/socket/socket.go
  • js/net/api/index.api.md
  • js/net/bench/socket.ts
  • js/net/src/index.ts
  • js/net/src/socket.test.ts
  • js/net/src/socket.ts
  • kt/moq/src/jvmAndAndroidMain/kotlin/dev/moq/socket/Socket.kt
  • nix/Cargo.nix
  • py/moq-rs/README.md
  • py/moq-rs/benches/ffi.py
  • py/moq-rs/docs/index.md
  • py/moq-rs/moq/socket.py
  • py/moq-rs/tests/test_socket.py
  • quest/m0/test-flakes-2/README.md
  • quest/m1/README.md
  • quest/m1/stream/README.md
  • quest/m1/stream/relay-eviction.md
  • quest/m3/README.md
  • quest/m3/mesh/README.md
  • quest/m3/mesh/endpoint.md
  • quest/m4/stream-js.md
  • quest/m5/ffi-stream.md
  • quest/m9/stream-bench.md
  • rs/moq-boy/src/input.rs
  • rs/moq-c/README.md
  • rs/moq-c/src/consume.rs
  • rs/moq-c/src/publish.rs
  • rs/moq-c/src/socket.rs
  • rs/moq-c/src/test/parity.rs
  • rs/moq-cli/Cargo.toml
  • rs/moq-cli/src/args.rs
  • rs/moq-cli/src/main.rs
  • rs/moq-cli/src/tcp.rs
  • rs/moq-ffi/src/producer.rs
  • rs/moq-ffi/src/socket.rs
  • rs/moq-net/CHANGELOG.md
  • rs/moq-net/src/model/origin.rs
  • rs/moq-net/src/model/socket.rs
  • rs/moq-net/tests/integration/socket.rs
  • rs/moq-relay/tests/integration/socket_auth.rs
  • rs/moq-tokio/src/lib.rs
  • rs/moq-tokio/src/socket.rs
  • swift/Sources/Moq/Socket.swift
  • test/interop/clients/js-native/socket.ts
  • test/interop/clients/python/sockets.py
  • test/interop/clients/rust/socket-js.rs
  • test/interop/clients/rust/socket.rs
  • test/interop/interop.sh
  • test/interop/socket.sh
Files with no reviewable changes: 18

  • dart/moq/lib/socket.dart
  • doc/bin/cli.md
  • go/wrapper/bridge.go
  • go/wrapper/internal/bridge/handles.go
  • kt/moq/src/jvmAndAndroidMain/kotlin/dev/moq/socket/Socket.kt
  • nix/Cargo.nix
  • py/moq-rs/docs/index.md
  • quest/m1/stream/README.md
  • quest/m1/stream/relay-eviction.md
  • quest/m4/stream-js.md
  • quest/m5/ffi-stream.md
  • quest/m9/stream-bench.md
  • rs/moq-c/src/publish.rs
  • rs/moq-cli/Cargo.toml
  • rs/moq-cli/src/tcp.rs
  • rs/moq-net/src/model/origin.rs
  • rs/moq-tokio/src/lib.rs
  • rs/moq-tokio/src/socket.rs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No code issues. One release-process gap in the PR description, below.

Reviewed changes

This review covers removing the socket tcp protocol across moq-net, @moq/net, moq-ffi, moq-c, and every wrapper, plus the docs, tests, interop, and quests that change with it.

  • moq-net socket model: removes TcpStream, the Pump task on the origin's driver, the Stream trait and per-protocol queues. Incoming, Dialing, and Accepting are no longer generic. Before the first accept there is still no server broadcast, so dropping the listening flag keeps the old behavior.
  • @moq/net socket: removes dialTcp, acceptTcp, TcpStream, and the TCP copy and second-group watchers. Incoming.accept(info?, options?) now always returns a TrackStream.
  • FFI and C ABI: removes dial_tcp, accept_tcp, MoqSocketIncomingTcp, and MoqSocketTcpStream, plus moq_socket_dial_tcp and moq_socket_accept_tcp. A stream's writer is always a raw track handle, and RawControl::Group is gone.
  • Wrappers: Go, Swift, Kotlin, Python, and Dart drop their TCP types and methods. Dart's bindings are regenerated.
  • Wire and docs: no message changes. A tcp/... dial is reset as unsupported like any unknown protocol, and an_unknown_protocol_is_reset tests this. doc/concept/socket.md and the per-language docs now describe track sessions only.
  • Tests and interop: the relay's socket_auth tests now run track sessions in both directions. The interop lanes drop the protocol argument. The case label becomes socket, and no recorded baseline referenced the old labels.

ℹ️ The migration audit may miss the stale-note cleanup, and the list of notes is incomplete

RELEASE.md says the breaking cut reads each ! PR's Impact section. This PR has no ## Impact heading: the cleanup instruction is in a "Migration:" paragraph under Summary. That paragraph lists the Unreleased MIGRATE.md notes that describe TCP halves. It does not mention the GroupProducer.ready notes, which also say "a TCP socket stream's producer needs it to behave like TCP". Unless both are fixed, the next cut could ship notes for an API that never shipped.

Technical details
# Move the migration note into an Impact section and list every stale TCP-socket note

## Affected sites
- PR #8772 description — no `## Impact` section; the cut's migration audit (RELEASE.md:14, sh/migrate.sh:4) reads Impact sections.
- swift/MIGRATE.md:15, dart/moq/MIGRATE.md:15, go/wrapper/MIGRATE.md:15, cpp/moq/MIGRATE.md:9, py/moq-rs/MIGRATE.md:15, kt/moq/MIGRATE.md:15, rs/moq-ffi/MIGRATE.md:16 — the `GroupProducer.ready` notes end with a clause tying `ready` to TCP socket streams ("a TCP socket stream's producer needs it to behave like TCP" / "a `TcpStream` producer needs it" / "a TCP socket session needs it"), which the PR's list doesn't name.
- The socket notes the PR already names (swift:13, dart:13, go:13, cpp:7, c/moq:14, py:13, kt:13, rs/moq-ffi:14, js/net:20-24, rs/moq-net:28).

## Required outcome
- The PR description has an `## Impact` section with the migration guidance: tcp is removed, `main` users move to a track session, and no published user is affected.
- That section tells the cut to drop or rewrite every Unreleased note above, including the TCP clause in each `ready` note, so none ships in a version section.

## Suggested approach
- Edit only the PR description. The MIGRATE guard rejects direct `MIGRATE.md` edits outside a cut, as the PR already notes.

Pullfrog  | Fix it ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

@kixelated
kixelated enabled auto-merge November 14, 2026 21:47
@kixelated

Copy link
Copy Markdown
Collaborator Author

Fixed in the description: the migration guidance now sits under ## Impact, which lists every stale Unreleased note for the cut, including the TCP clause in each GroupProducer.ready note (swift, dart/moq, go/wrapper, cpp/moq, py/moq-rs, kt/moq, rs/moq-ffi). MIGRATE.md itself stays untouched, since the guard refuses edits outside a cut.

(Written by Claude Opus 5.5)

Takes this branch's side of every socket conflict with #8741, and drops what
#8741 added for the tcp protocol: moq-tokio's socket::TcpStream, the moq CLI's
tcp forwarding, dial_tcp's priority, and the byte-stream quests, including the
new relay-eviction quest, which moves to Kixel with the rest. #8741's kio test
fix and the public group::Consumer::poll_next_frame stay.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found. The new Impact section in the PR description resolves the earlier concern.

Reviewed changes

Since the last review, main was merged in. That merge brought in #8741's tcp additions, and this PR now removes them along with the rest of tcp.

  • moq-tokio and moq CLI: removed moq_tokio::socket (TcpStream, MAX_FRAME), rs/moq-cli/src/tcp.rs, Command::Tcp, the tcp dial-only branch in main.rs, and the rand dependency that only tcp dial used.
  • moq-net socket: removed #8741's priority argument on dial_tcp/accept and the chunk-by-chunk Local pump. These went with the rest of the tcp code. subscription() stays at its default priority, and group::Consumer::poll_next_frame stays public.
  • @moq/net: removed Socket.TcpOptions and the priority test that went with it. The regenerated api/index.api.md matches.
  • Docs and quests: removed the doc/bin/cli.md TCP section and quest/m1/stream/relay-eviction.md. The quest/m3/mesh references now describe byte streams without links. A tree-wide grep finds no dial_tcp, acceptTcp, TcpOptions, moq_tokio::socket, or moq tcp references, and no links to the deleted quests. The only remaining mentions are the Unreleased MIGRATE.md notes, which the Impact section covers.
  • PR description: added an ## Impact section. It lists every stale Unreleased socket note and the GroupProducer.ready TCP clauses for the release cut to drop.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@kixelated
kixelated added this pull request to the merge queue Nov 14, 2026
Merged via the queue into main with commit a5d9fe8 Nov 15, 2026
9 checks passed
@kixelated
kixelated deleted the remove-socket-tcp branch November 15, 2026 00:56
kixelated added a commit that referenced this pull request Nov 15, 2026
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>
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