Skip to content

Register the SDK's own transport with livekit-net - #1106

Merged
pblazej merged 8 commits into
mainfrom
blaze/rust-net-adapter
Oct 23, 2026
Merged

pblazej merged 8 commits into
mainfrom
blaze/rust-net-adapter

Conversation

@pblazej

@pblazej pblazej commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

livekit-net does not include its own WebSocket and HTTP clients. The host app must supply them. This PR gives livekit-net the existing WebSocket and HTTP stack of the SDK, through an adapter of about 180 lines. The SDK does not get a second URLSession implementation.

The Rust side uses the same session as the Swift side, so it gets the same behavior. That includes the .callSignaling QoS, multipath handover, and the TLS workaround for the iOS 26 simulator.

Changes:

  • Add Sources/LiveKit/Support/Network/RustTransport.swift. It calls setWsClient(c:) and setHttpClient(c:) from LiveKitFFI one time, on first access. ConnectionDependencies.init triggers it, before any signaling starts.
  • Send every header that livekit-net gives for a WebSocket upgrade. If a header name repeats, the request keeps all of its values.
  • Keep the HTTP status when the server rejects a WebSocket upgrade. livekit-net returns this status as TransportError::Http, and livekit-signaling maps it to SignalError::Handshake. A 404 status starts the fallback from the v1 path to the v0 path.
  • Reject an HttpMethod case that this SDK does not know with TransportError.Other. Before this change, the adapter sent such a request as GET.

The RustTransportTests suite goes from Rust back through the FFI. It uses the self_test_* exports of livekit-net against a live livekit-server. No test uses a mock.

Local results on macOS, with livekit-server 1.13.7 started as livekit-server --dev and enable_participant_data_blob: true:

  • swift test --no-parallel --filter RustTransportTests: all 14 tests (24 test cases) passed.
  • swift test --no-parallel --filter LiveKitCoreTests: 580 of 588 tests passed, 0 failed, and 8 skipped. The skipped tests are in CooperativePoolBlockingTests, which skips them by design.
  • swiftlint and swiftformat --lint found no issues in the changed files.

This PR uses the LiveKitFFI 0.13.1 pin from main and does not change a package file. LiveKitFFI 0.13.1 contains the livekit-net bindings in livekit_net.swift. The earlier blocker, livekit/rust-sdks#1362, merged on 2026-09-08.

@pblazej
pblazej force-pushed the blaze/rust-net-adapter branch 4 times, most recently from 22d5249 to cf00102 Compare September 2, 2026 14:46
@pblazej

pblazej commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Blocked by UniFFI release (soon) 🚫 works locally tho

@pblazej
pblazej marked this pull request as ready for review September 2, 2026 14:50
@pblazej
pblazej requested review from 1egoman and ladvoc September 2, 2026 14:53

@devin-ai-integration devin-ai-integration 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.

Note

Newer findings are available below. Devin Review posted a newer report on this PR, in addition to the findings presented here.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@1egoman 1egoman 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.

Generally makes sense to me from a 10k foot view level, but I'm unable to effectively review the lower level swift idiosyncrasies

@pblazej

pblazej commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

@1egoman are you going to change the rust side? It's not a high-priority to me (no consumers atm)

@1egoman

1egoman commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

are you going to change the rust side?

No rust changes are planned to this interface AFAIK at the moment, unless you are planning some 😄

@xianshijing-lk xianshijing-lk 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.

one question

Comment thread Sources/LiveKit/Support/Network/RustTransport.swift
pblazej and others added 2 commits September 22, 2026 15:51
livekit-net leaves the WebSocket and HTTP clients to the host. Rather than
add a second, parallel URLSession stack for the Rust side, adapt the one
already here, so Rust-side signalling inherits the tuning the Swift path
gets: .callSignaling QoS, multipath handover, extended background idle,
the iOS 26 simulator TLS workaround, and the delegate's error logging.

Registration is a lazy global, forced from ConnectionDependencies.init:
process-wide rather than connection-scoped, since livekit-net keeps the
first registration, but that is the earliest construction on the connect
path, so no signalling can outrun it and a Room that never connects pays
nothing.

WebSocket gains a headers/timeout init (SignalClient supplies its own
Authorization header) and keeps the HTTP status off a rejected upgrade,
which is what livekit-net's TransportError::Http carries: livekit-signaling
maps it to SignalError::Handshake, where a 404 gates the v1 -> v0
signalling path fallback and other statuses fail fast rather than driving
a reconnect loop.

HTTP.request now owns the cache policy and timeout as parameters, so the
shared session's URLCache can't serve a stale validate or region response
to either caller.

The tests drive the seam from Rust through the FFI using livekit-net's own
self_test_* exports, so nothing is asserted against a mock.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The released bindings name the setter argument `c`, not `client`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pblazej
pblazej force-pushed the blaze/rust-net-adapter branch from 1ab7cd0 to 7e7b64f Compare September 22, 2026 13:53
The UniFFI enum is non-frozen, so a switch over it needs `@unknown
default` once the module is built with library evolution enabled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

pblazej and others added 5 commits September 22, 2026 16:28
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: omnigent <noreply@omnigent.ai>
HttpMethod is non-frozen, so a newer LiveKitFFI binary can add a case,
for example PUT. The adapter sent such a request as GET, which is a
valid request with different semantics. makeRequest now throws
TransportError.Other for an unknown case, and request(method:url:...)
returns that error to livekit-net.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: omnigent <noreply@omnigent.ai>
WsClientAdapter.connect turned livekit-net's header list into a
dictionary, so entries with the same name collapsed to the last value,
for example two Sec-WebSocket-Protocol entries. WebSocket now takes an
ordered list of name/value pairs and adds each one with addValue, so
every entry reaches the request. SignalClient passes its single
Authorization header in the same form.

The request is built in WebSocket.makeRequest, which a unit test drives
with repeated names that also differ only in case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: omnigent <noreply@omnigent.ai>
RustTransportTests contacted the server without the shared readiness
gate that withRooms and the Objective-C helper use, so a slow simulator
start could fail them. The suite init now calls
TestEnvironment.waitForServer, which is public for this. The init
comment now names ConnectionDependencies.init, which is where the SDK
forces the transport registration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: omnigent <noreply@omnigent.ai>
@pblazej
pblazej merged commit e4ec2e9 into main Oct 23, 2026
56 of 57 checks passed
@pblazej
pblazej deleted the blaze/rust-net-adapter branch October 23, 2026 11:45
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.

3 participants