Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/warp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
minor type="added" "Enable WARP (SPED: DTLS handshake carried in the ICE exchange, SNAP: SCTP association parameters in SDP), shortening connection and data channel setup. Always on and negotiated with the server: a server without WARP support gets a standard handshake"
4 changes: 4 additions & 0 deletions Sources/LiveKit/Core/RTC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ extension RTC {

LKRTCInitializeSSL()

// WARP SPED (DTLS in STUN); SNAP is on `LKRTCConfiguration.liveKitDefault()`.
// Both engage only when the server negotiates them.
LKRTCPeerConnectionFactory.configureFieldTrials("\(kLKRTCFieldTrialIceHandshakeDtlsKey)/\(kLKRTCFieldTrialEnabledValue)/")
Comment thread
pblazej marked this conversation as resolved.

Room.log("Initializing PeerConnectionFactory...")

return LKRTCPeerConnectionFactory(audioDeviceModuleType: admType.toRTCType(),
Expand Down
3 changes: 3 additions & 0 deletions Sources/LiveKit/Extensions/RTCConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ extension LKRTCConfiguration {
result.continualGatheringPolicy = .gatherContinually
result.candidateNetworkPolicy = .all
result.tcpCandidatePolicy = .enabled
// WARP SNAP (SCTP INIT in SDP). Immutable per peer connection, so it must never vary
// between creation and `setConfiguration`.
result.enableSctpSnap = true

return result
}
Expand Down
46 changes: 46 additions & 0 deletions Tests/LiveKitCoreTests/WARPTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.
*/

@testable import LiveKit
import LiveKitWebRTC
import Testing

/// WARP is offered unconditionally; the server decides whether it engages.
@Suite(.tags(.networking)) struct WARPTests {
private final class StubDelegate: TransportDelegate {
func transport(_: Transport, didUpdateState _: LKRTCPeerConnectionState) {}
func transport(_: Transport, didGenerateIceCandidate _: IceCandidate) {}
func transport(_: Transport, didOpenDataChannel _: LKRTCDataChannel) {}
func transport(_: Transport, didAddTrack _: RTCMediaTrack, rtpReceiver _: RTCReceiver, streamIds _: [String]) {}
func transport(_: Transport, didRemoveTrackWithId _: String) {}
func transportShouldNegotiate(_: Transport) {}
}

@Test func offerAdvertisesSPEDAndSNAP() async throws {
let transport = try await Transport(config: .liveKitDefault(),
target: .publisher,
primary: true,
delegate: StubDelegate())
defer { Task { await transport.close() } }

_ = await transport.dataChannel(for: LKRTCDataChannel.Labels.reliable,
configuration: RTC.createDataChannelConfiguration())
let sdp = try await transport.createOffer().sdp

#expect(sdp.contains("goog-sped-v1"), "SPED: the WebRTC-IceHandshakeDtls field trial")
#expect(sdp.contains("a=sctp-init:"), "SNAP: enableSctpSnap")
}
}
Loading