Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8fc8204
feat: add new DataStreams ffi encapsulation class
1egoman Jul 30, 2026
de50f91
feat: cut over from swift data streams v1 implementation to rust base…
1egoman Jul 30, 2026
b1082b2
feat: add in tests ported to use livekit-uniffi provided data tracks …
1egoman Jul 30, 2026
25c717d
fix: advertise client protocol of v2 by default
1egoman Aug 4, 2026
0ad61e1
fix: wire up Registry.remoteClientProtocol
1egoman Aug 4, 2026
07939e9
feat: add new ClientCapability struct and add list under Participant.…
1egoman Aug 4, 2026
1931c8f
feat: consume capabilities field in data streams remote registry
1egoman Aug 4, 2026
0928935
Update Sources/LiveKit/DataStream/DataStreams.swift
1egoman Aug 5, 2026
730e8bc
fix(data-stream): create the subsystem eagerly to avoid a first-acces…
1egoman Aug 5, 2026
4f2b1c6
fix(data-stream): report writer open state from the FFI
1egoman Aug 5, 2026
a71b3b1
feat(data-stream): configurable max payload size; per-sender ordered …
1egoman Aug 5, 2026
74cc7ad
fix(data-stream): advertise client capabilities on both connection paths
1egoman Aug 5, 2026
c2666be
feat: add object c compatibility for DataStreamOptions
1egoman Aug 5, 2026
5fce9c5
fix(data-streams): honor connect-time maxPayloadSize
1egoman Aug 5, 2026
c8df3cb
test(data-stream): port ported suites to the nanopb builder API
pblazej Aug 17, 2026
1c75e58
fix(data-stream): order the outgoing pump; re-read maxPayloadSize per…
pblazej Aug 17, 2026
f2b4e54
test(data-stream): restore ordered-topic specs; cover the FFI info/er…
pblazej Aug 17, 2026
4a39c69
refactor(data-stream): tighten Sendable and known-issue signal after …
pblazej Aug 17, 2026
49ba7b2
docs(data-stream): correct where the missing stream-closed signal lives
pblazej Aug 17, 2026
039ed3f
feat(data-stream): adopt the revised data-stream FFI
pblazej Aug 18, 2026
e7947c4
feat(data-stream): await the outgoing delegate, propagating send fail…
pblazej Aug 18, 2026
0d1391a
test(data-stream): wait on open-stream count instead of handler entry
pblazej Aug 18, 2026
7f82f82
test(data-stream): restore the encryption-type mismatch coverage
pblazej Aug 19, 2026
51bcce3
docs(data-stream): document the new options; reject a non-positive pa…
pblazej Aug 19, 2026
0d5dd1f
fix: rename maxPayloadSize to maxPayloadByteLength to match other sdks
1egoman Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changes/data-streams-v2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
minor type="changed" "Data streams: reimplemented on the Rust livekit-data-stream core over UniFFI, adding DEFLATE compression and single-packet inlining for one-shot sends when every recipient supports them, a configurable incoming payload cap via RoomOptions.dataStreamOptions, and Participant.capabilities"
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ let package = Package(
dependencies: [
"LiveKit",
"LiveKitTestSupport",
.product(name: "LiveKitUniFFI", package: "livekit-uniffi-xcframework"),
],
),
.testTarget(
Expand Down
1 change: 1 addition & 0 deletions Package@swift-6.2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ let package = Package(
dependencies: [
"LiveKit",
"LiveKitTestSupport",
.product(name: "LiveKitUniFFI", package: "livekit-uniffi-xcframework"),
],
),
.testTarget(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ actor TranscriptionStreamReceiver: MessageReceiver, Loggable {

let topic = topic

// SDK-internal receiver — register via `incomingStreamManager` directly
// so the receiver works even if the `Room.reservedTopicPrefix` guard is
// later widened to cover non-RPC `lk.*` topics like this one.
try await room.incomingStreamManager.registerTextStreamHandler(for: topic, ordered: true) { [weak self] reader, participantIdentity in
// SDK-internal receiver — register via `dataStreams` directly so the
// receiver works even if the `Room.reservedTopicPrefix` guard is later
// widened to cover non-RPC `lk.*` topics like this one.
try room.dataStreams.registerTextStreamHandler(for: topic, ordered: true) { [weak self] reader, participantIdentity in
var lastMessage: ReceivedMessage?
for try await message in reader where !message.isEmpty {
guard let self else { return }
Expand All @@ -114,9 +114,7 @@ actor TranscriptionStreamReceiver: MessageReceiver, Loggable {
}

continuation.onTermination = { [weak self] _ in
Task { [weak self] in
await self?.room.incomingStreamManager.unregisterTextStreamHandler(for: topic)
}
self?.room.dataStreams.unregisterTextStreamHandler(for: topic)
}

return stream
Expand Down
10 changes: 7 additions & 3 deletions Sources/LiveKit/Core/DataChannelPair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ internal import LiveKitWebRTC
// MARK: - Internal delegate

protocol DataChannelDelegate: AnyObject, Sendable {
func dataChannel(_ dataChannelPair: DataChannelPair, didReceiveDataPacket dataPacket: Livekit_DataPacket)
/// - Parameter encryptionType: the type declared on the packet *as received*, captured before
/// decryption. `EncryptedPacket` shares a protobuf `oneof` with the stream payload, so
/// decrypting overwrites it — the value is unrecoverable from `dataPacket` afterwards.
func dataChannel(_ dataChannelPair: DataChannelPair, didReceiveDataPacket dataPacket: Livekit_DataPacket, encryptionType: EncryptionType)
func dataChannel(_ dataChannelPair: DataChannelPair, didFailToDecryptDataPacket dataPacket: Livekit_DataPacket, error: LiveKitError)
}

Expand Down Expand Up @@ -675,14 +678,15 @@ extension DataChannelPair: LKRTCDataChannelDelegate {
if let encryptedPacket = dataPacket.encryptedPacketOrNil,
let e2eeManager = _state.e2eeManager
{
let encryptionType = encryptedPacket.encryptionType.toLKType()
do {
let decryptedData = try e2eeManager.handle(encryptedData: encryptedPacket.toRTCEncryptedPacket(), participantIdentity: dataPacket.participantIdentity)
let decryptedPayload = try Livekit_EncryptedPacketPayload(serializedBytes: decryptedData)

let dataPacket = dataPacket.modifying { decryptedPayload.applyTo(&$0) }

delegates.notify { [dataPacket] in
$0.dataChannel(self, didReceiveDataPacket: dataPacket)
$0.dataChannel(self, didReceiveDataPacket: dataPacket, encryptionType: encryptionType)
}
} catch {
log("Failed to decrypt data packet: \(error)", .error)
Expand All @@ -692,7 +696,7 @@ extension DataChannelPair: LKRTCDataChannelDelegate {
}
} else {
delegates.notify {
$0.dataChannel(self, didReceiveDataPacket: dataPacket)
$0.dataChannel(self, didReceiveDataPacket: dataPacket, encryptionType: .none)
}
}
}
Expand Down
16 changes: 12 additions & 4 deletions Sources/LiveKit/Core/Room+DataStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public extension Room {
throw LiveKitError(.invalidParameter,
message: "Stream topic prefix '\(Room.reservedTopicPrefix)' is reserved for internal SDK use")
}
try await incomingStreamManager.registerByteStreamHandler(for: topic, onNewStream)
try dataStreams.registerByteStreamHandler(for: topic, onNewStream)
}

/// Registers a handler for incoming text streams matching the given topic.
Expand All @@ -50,7 +50,7 @@ public extension Room {
throw LiveKitError(.invalidParameter,
message: "Stream topic prefix '\(Room.reservedTopicPrefix)' is reserved for internal SDK use")
}
try await incomingStreamManager.registerTextStreamHandler(for: topic, onNewStream)
try dataStreams.registerTextStreamHandler(for: topic, onNewStream)
}

/// Unregisters a byte stream handler that was previously registered for the given topic.
Expand All @@ -60,7 +60,7 @@ public extension Room {
@objc
func unregisterByteStreamHandler(for topic: String) async {
guard !topic.hasPrefix(Room.reservedTopicPrefix) else { return }
await incomingStreamManager.unregisterByteStreamHandler(for: topic)
dataStreams.unregisterByteStreamHandler(for: topic)
}

/// Unregisters a text stream handler that was previously registered for the given topic.
Expand All @@ -70,10 +70,18 @@ public extension Room {
@objc
func unregisterTextStreamHandler(for topic: String) async {
guard !topic.hasPrefix(Room.reservedTopicPrefix) else { return }
await incomingStreamManager.unregisterTextStreamHandler(for: topic)
dataStreams.unregisterTextStreamHandler(for: topic)
}
}

// MARK: - Handler type aliases

/// Handler for incoming byte data streams.
public typealias ByteStreamHandler = @Sendable (ByteStreamReader, Participant.Identity) async throws -> Void

/// Handler for incoming text data streams.
public typealias TextStreamHandler = @Sendable (TextStreamReader, Participant.Identity) async throws -> Void

extension Room {
/// Reserved data-stream topic prefix for RPC v2 (`lk.rpc_request` / `lk.rpc_response`,
/// and any future `lk.rpc_*` topics). The broader `lk.*` namespace is convention-only
Expand Down
34 changes: 17 additions & 17 deletions Sources/LiveKit/Core/Room.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,10 @@ public class Room: NSObject, @unchecked Sendable, ObservableObject, Loggable {
lazy var subscriberDataChannel = DataChannelPair(delegate: self)
lazy var publisherDataChannel = DataChannelPair(delegate: self)

let incomingStreamManager = IncomingStreamManager()
lazy var outgoingStreamManager = OutgoingStreamManager { [weak self] packet in
try await self?.send(dataPacket: packet)
} encryptionProvider: { [weak self] in
self?.e2eeManager?.dataChannelEncryptionType ?? .none
}
// The data stream subsystem (incoming/outgoing UniFFI managers, the topic→handler registry, and
// packet routing) behind one reference. Kept for the Room's lifetime — not session-scoped like
// ``DataTracks`` — so stream handlers survive reconnects and can be registered before connect.
private(set) var dataStreams: DataStreams!

// MARK: - Data Tracks

Expand Down Expand Up @@ -282,6 +280,9 @@ public class Room: NSObject, @unchecked Sendable, ObservableObject, Loggable {
roomOptions: roomOptions ?? RoomOptions()))

super.init()

dataStreams = DataStreams(room: self)

// log sdk & os versions
log("sdk: \(LiveKitSDK.version), ffi: \(LiveKitSDK.ffiVersion), os: \(String(describing: Utils.os()))(\(Utils.osVersionString())), modelId: \(String(describing: Utils.modelIdentifier() ?? "unknown"))")

Expand Down Expand Up @@ -610,7 +611,7 @@ extension Room {
await activeParticipantCompleters.reset(throwing: disconnectError)
// Fail open data streams so their handlers return; a handler blocked on a
// reader that will never finish would stall its topic's ordered queue.
await incomingStreamManager.reset()
dataStreams.reset()

await signalClient.cleanUp(withError: disconnectError)
// Cancel all track stats timers before closing transports to prevent
Expand Down Expand Up @@ -659,10 +660,10 @@ extension Room {
private func setupRpc() async {
await rpcClient.attach(to: self)
await rpcServer.attach(to: self)
await incomingStreamManager.registerTextStreamHandlerIfNeeded(for: RpcStreamTopic.request) { [weak rpcServer] reader, identity in
dataStreams.registerTextStreamHandlerIfNeeded(for: RpcStreamTopic.request) { [weak rpcServer] reader, identity in
await rpcServer?.handleIncomingRequestStream(reader: reader, callerIdentity: identity)
}
await incomingStreamManager.registerTextStreamHandlerIfNeeded(for: RpcStreamTopic.response) { [weak rpcClient] reader, identity in
dataStreams.registerTextStreamHandlerIfNeeded(for: RpcStreamTopic.response) { [weak rpcClient] reader, identity in
await rpcClient?.handleIncomingResponseStream(reader: reader, senderIdentity: identity)
}
}
Expand Down Expand Up @@ -701,7 +702,7 @@ extension Room {
// so the caller sees `recipientDisconnected` (1503) immediately instead of
// hanging until the user-supplied `responseTimeout`.
await rpcClient.handleParticipantDisconnected(identity)
await incomingStreamManager.closeStreams(from: identity)
dataStreams.closeStreams(from: identity)

guard let participant = _state.mutate({ $0.remoteParticipants.removeValue(forKey: identity) }) else {
throw LiveKitError(.invalidState, message: "Participant not found for \(identity)")
Expand Down Expand Up @@ -798,20 +799,19 @@ public extension Room {
// MARK: - DataChannelDelegate

extension Room: DataChannelDelegate {
func dataChannel(_: DataChannelPair, didReceiveDataPacket dataPacket: Livekit_DataPacket) {
func dataChannel(_: DataChannelPair, didReceiveDataPacket dataPacket: Livekit_DataPacket, encryptionType: EncryptionType) {

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.

🟡 Encrypted data messages are reported to apps as unencrypted

The encryption kind handed to the data-message callback is read from the packet after it has already been unscrambled (dataPacket.encryptedPacket.encryptionType at Sources/LiveKit/Core/Room.swift:805), so apps are always told an encrypted message arrived in the clear even though the correct value is now available as a parameter.
Impact: Applications that inspect whether received data was end-to-end encrypted always see "none", so they cannot distinguish encrypted from plaintext senders.

Mechanism: the oneof field carrying the encryption type is overwritten by decryption

The new delegate signature (Sources/LiveKit/Core/DataChannelPair.swift:26-29) exists precisely because EncryptedPacket shares a protobuf oneof with the decrypted payload: decryptedPayload.applyTo(&$0) sets e.g. builder.user, clearing encryptedPacket (Sources/LiveKit/E2EE/Protos+E2EE.swift:68-88). The stream cases were migrated to the new encryptionType parameter, but the .user case still reads the now-cleared field, so engine(_:didReceiveUserPacket:encryptionType:) — and ultimately room(_:participant:didReceiveData:forTopic:encryptionType:) — always receives .none for decrypted packets.

Prompt for agents
In Sources/LiveKit/Core/Room.swift the DataChannelDelegate implementation now receives the as-received `encryptionType` as a parameter (because decryption clears `dataPacket.encryptedPacket`). The `.user` case still derives the value from `dataPacket.encryptedPacket.encryptionType.toLKType()`, which is always `.none` for a packet that went through decryption. Pass the new `encryptionType` parameter through to `engine(_:didReceiveUserPacket:encryptionType:)` instead.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

🟨 Encryption status of received data messages is misreported as unencrypted

After a packet is decrypted, the encryption kind is read from the protobuf field that decryption overwrites (dataPacket.encryptedPacket.encryptionType at Sources/LiveKit/Core/Room.swift:805), so room(_:participant:didReceiveData:forTopic:encryptionType:) always reports .none. Applications that gate trust on whether inbound data was end-to-end encrypted cannot distinguish an encrypted sender from a plaintext one, which can lead to accepting unauthenticated/plaintext payloads as if they were E2EE-protected. The PR adds the correct as-received value as a parameter and uses it for the data-stream paths, but not for the user-packet path.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

switch dataPacket.value {
case let .speaker(update): engine(self, didUpdateSpeakers: update.speakers)
case let .user(userPacket): engine(self, didReceiveUserPacket: userPacket, encryptionType: dataPacket.encryptedPacket.encryptionType.toLKType())
case let .transcription(packet): room(didReceiveTranscriptionPacket: packet)
case let .rpcResponse(response): room(didReceiveRpcResponse: response)
case let .rpcAck(ack): room(didReceiveRpcAck: ack)
case let .rpcRequest(request): room(didReceiveRpcRequest: request, from: dataPacket.participantIdentity)
case let .streamHeader(header):
incomingStreamManager.handle(.header(header, dataPacket.participantIdentity, dataPacket.encryptedPacket.encryptionType.toLKType()))
case let .streamChunk(chunk):
incomingStreamManager.handle(.chunk(chunk, dataPacket.encryptedPacket.encryptionType.toLKType()))
case let .streamTrailer(trailer):
incomingStreamManager.handle(.trailer(trailer, dataPacket.encryptedPacket.encryptionType.toLKType()))
case .streamHeader, .streamChunk, .streamTrailer:
// Forward the whole (already-decrypted, deduped) packet; the UniFFI incoming manager
// decodes the stream header/chunk/trailer itself. The encryption type travels beside it
// because decryption consumed the packet field that carried it.
dataStreams.handleIncoming(dataPacket, encryptionType: encryptionType)
default: return
}
}
Expand Down
132 changes: 132 additions & 0 deletions Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright 2026 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import Foundation

internal import LiveKitUniFFI

// The objects the Rust core calls into. Split from `DataStreams` itself so the coordinator file
// stays about coordination; each type here is a thin adapter that forwards across the boundary.
extension DataStreams {
// MARK: - Incoming delegate

/// Receives the incoming manager's stream-open callbacks and forwards them to the coordinator.
/// A separate object because the FFI manager retains its delegate strongly; holding the
/// coordinator weakly keeps this the weak link so teardown doesn't leak.
final class IncomingDelegate: LiveKitUniFFI.IncomingDataStreamManagerDelegate, @unchecked Sendable {

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 29 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'IncomingDataStreamManagerDelegate' in module 'LiveKitUniFFI'
weak var coordinator: DataStreams?

func onByteStreamOpened(reader: LiveKitUniFFI.ByteStreamReader, identity: String) {

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'

Check failure on line 32 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'ByteStreamReader' in module 'LiveKitUniFFI'
coordinator?.handleByteStreamOpened(reader, identity: identity)
}

func onTextStreamOpened(reader: LiveKitUniFFI.TextStreamReader, identity: String) {

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'

Check failure on line 36 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'TextStreamReader' in module 'LiveKitUniFFI'
coordinator?.handleTextStreamOpened(reader, identity: identity)
}

func onStreamClosed(streamId: String, identity: String) {
coordinator?.handleStreamClosed(streamID: streamId, identity: identity)
}
}

// MARK: - Outgoing delegate

/// Receives the outgoing manager's encoded `DataPacket`s and sends them over the reliable data
/// channel via `Room.send(dataPacket:)` — preserving E2EE, reliable sequencing, and identity
/// stamping. The room is held weakly to avoid retaining it through the FFI manager.
///
/// The callback is `async`, which is what lets this honor the FFI's contract: it returns only
/// once the packets have actually reached the transport. Three properties follow, none of which
/// needs machinery on this side.
///
/// - **Order.** The core awaits this call before pumping the next packet, so calls arrive — and
/// complete — strictly in emission order. That matters: the receiver drops a chunk that
/// arrives before its header and fails the stream on a non-consecutive chunk index.
/// - **Back-pressure.** The originating `write`/`send_*` stays pending until this returns, so a
/// producer can't outrun the transport and queue unboundedly.
/// - **Failures.** Throwing `PacketDeliveryError` fails that originating call with
/// `.sendFailed` and closes the stream, so `isOpen` reflects reality.
///
/// `@unchecked Sendable` for the weak back-reference alone: it is assigned in `init` and never
/// mutated afterwards.
final class OutgoingDelegate: LiveKitUniFFI.OutgoingDataStreamManagerDelegate, @unchecked Sendable {

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'

Check failure on line 65 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'OutgoingDataStreamManagerDelegate' in module 'LiveKitUniFFI'
private weak var room: Room?

init(room: Room) {
self.room = room
}

func onPacketsAvailable(packets: [Data]) async throws {
// The room is gone, so there is no transport left to fail against; the manager is being
// torn down with it.
guard let room else { return }

for data in packets {
guard let packet = try? Livekit_DataPacket(serializedBytes: data) else {
room.log("Failed to decode outgoing data stream packet", .warning)
continue
}
do {
try await room.send(dataPacket: packet)
} catch {
throw LiveKitUniFFI.PacketDeliveryError.Failed(reason: String(describing: error))
}
}
}
}

// MARK: - Remote participant registry

/// Read access to the room's remote participants, used by the outgoing manager to resolve
/// broadcast recipients and decide compression eligibility. Client protocol/capabilities aren't
/// currently exposed on `RemoteParticipant`, so they default to none — compression stays off
/// until they're wired, which is a safe default (a non-compressed send always works).
final class Registry: LiveKitUniFFI.RemoteParticipantRegistryDelegate, @unchecked Sendable {

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'

Check failure on line 97 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'RemoteParticipantRegistryDelegate' in module 'LiveKitUniFFI'
private weak var room: Room?

init(room: Room) {
self.room = room
}

private func participant(for identity: String) -> RemoteParticipant? {
room?.remoteParticipants.first { $0.key.stringValue == identity }?.value
}

func remoteClientProtocol(identity: String) -> Int32 {
Int32(participant(for: identity)?.clientProtocol.rawValue ?? 0)
}

func remoteCapabilities(identity: String) -> [LiveKitUniFFI.ClientCapability] {

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 112 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'ClientCapability' in module 'LiveKitUniFFI'
participant(for: identity)?.capabilities.map(\.ffiValue) ?? []
}

func remoteIdentities() -> [String] {
guard let room else { return [] }
return room.remoteParticipants.keys.map(\.stringValue)
}
}
}

private extension ClientCapability {
/// Bridges to the FFI enum. Kept here so `ClientCapability` itself stays free of any
/// `LiveKitUniFFI` import, matching how the rest of the public API is layered.
var ffiValue: LiveKitUniFFI.ClientCapability {

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, iOS Simulator,name=iPhone 17 Pro,OS=27.0)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, tvOS Simulator,name=Apple TV 4K (3rd generation),OS=27.0)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, visionOS Simulator,name=Apple Vision Pro,OS=27.0)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS,variant=Mac Catalyst)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, iOS Simulator,name=iPhone 17 Pro,OS=26.5, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, iOS Simulator,name=iPhone 16 Pro,OS=18.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, visionOS Simulator,name=Apple Vision Pro,OS=26.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, tvOS Simulator,name=Apple TV,OS=26.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS,variant=Mac Catalyst)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, tvOS Simulator,name=Apple TV,OS=18.5)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS,variant=Mac Catalyst)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-26, 26.6, macOS, true)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.4, macOS)

no type named 'ClientCapability' in module 'LiveKitUniFFI'

Check failure on line 126 in Sources/LiveKit/DataStream/DataStreams+FFIDelegates.swift

View workflow job for this annotation

GitHub Actions / Build & Test (xcode-27, latest, macOS)

no type named 'ClientCapability' in module 'LiveKitUniFFI'
switch self {
case .packetTrailer: .packetTrailer
case .compressionDeflateRaw: .compressionDeflateRaw
}
}
}
Loading
Loading