CloudWebRTC
Committed by GitHub

upgrade libwebrtc to 114.5735.04. (#277)

* Setup E2EEManager for dependency injection

* upgrade libwebrtc to 114.5735.04.

* fix test build

* spotless

* Update e2ee option defaults to prevent deadlocks

* more defaults update

---------

Co-authored-by: davidliu <davidliu@deviange.net>
@@ -139,7 +139,7 @@ dependencies { @@ -139,7 +139,7 @@ dependencies {
139 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 139 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
140 implementation deps.coroutines.lib 140 implementation deps.coroutines.lib
141 implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0' 141 implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0'
142 - api 'io.github.webrtc-sdk:android:114.5735.03' 142 + api 'io.github.webrtc-sdk:android:114.5735.04'
143 api "com.squareup.okhttp3:okhttp:4.10.0" 143 api "com.squareup.okhttp3:okhttp:4.10.0"
144 api 'com.github.davidliu:audioswitch:d18e3e31d427c27f1593030e024b370bf24480fd' 144 api 'com.github.davidliu:audioswitch:d18e3e31d427c27f1593030e024b370bf24480fd'
145 implementation "androidx.annotation:annotation:1.4.0" 145 implementation "androidx.annotation:annotation:1.4.0"
@@ -37,7 +37,7 @@ data class RoomOptions( @@ -37,7 +37,7 @@ data class RoomOptions(
37 /** 37 /**
38 * Options for end-to-end encryption. 38 * Options for end-to-end encryption.
39 */ 39 */
40 - var e2eeOptions: E2EEOptions? = null, 40 + val e2eeOptions: E2EEOptions? = null,
41 41
42 val audioTrackCaptureDefaults: LocalAudioTrackOptions? = null, 42 val audioTrackCaptureDefaults: LocalAudioTrackOptions? = null,
43 val videoTrackCaptureDefaults: LocalVideoTrackOptions? = null, 43 val videoTrackCaptureDefaults: LocalVideoTrackOptions? = null,
@@ -16,9 +16,13 @@ @@ -16,9 +16,13 @@
16 16
17 package io.livekit.android.e2ee 17 package io.livekit.android.e2ee
18 18
  19 +import dagger.assisted.Assisted
  20 +import dagger.assisted.AssistedFactory
  21 +import dagger.assisted.AssistedInject
19 import io.livekit.android.events.RoomEvent 22 import io.livekit.android.events.RoomEvent
20 import io.livekit.android.room.Room 23 import io.livekit.android.room.Room
21 -import io.livekit.android.room.participant.* 24 +import io.livekit.android.room.participant.LocalParticipant
  25 +import io.livekit.android.room.participant.RemoteParticipant
22 import io.livekit.android.room.track.LocalAudioTrack 26 import io.livekit.android.room.track.LocalAudioTrack
23 import io.livekit.android.room.track.LocalVideoTrack 27 import io.livekit.android.room.track.LocalVideoTrack
24 import io.livekit.android.room.track.RemoteAudioTrack 28 import io.livekit.android.room.track.RemoteAudioTrack
@@ -30,19 +34,27 @@ import org.webrtc.FrameCryptor @@ -30,19 +34,27 @@ import org.webrtc.FrameCryptor
30 import org.webrtc.FrameCryptor.FrameCryptionState 34 import org.webrtc.FrameCryptor.FrameCryptionState
31 import org.webrtc.FrameCryptorAlgorithm 35 import org.webrtc.FrameCryptorAlgorithm
32 import org.webrtc.FrameCryptorFactory 36 import org.webrtc.FrameCryptorFactory
  37 +import org.webrtc.PeerConnectionFactory
33 import org.webrtc.RtpReceiver 38 import org.webrtc.RtpReceiver
34 import org.webrtc.RtpSender 39 import org.webrtc.RtpSender
35 40
36 class E2EEManager 41 class E2EEManager
37 -constructor(keyProvider: KeyProvider) { 42 +@AssistedInject
  43 +constructor(
  44 + @Assisted keyProvider: KeyProvider,
  45 + peerConnectionFactory: PeerConnectionFactory,
  46 +) {
38 private var room: Room? = null 47 private var room: Room? = null
39 private var keyProvider: KeyProvider 48 private var keyProvider: KeyProvider
  49 + private var peerConnectionFactory: PeerConnectionFactory
40 private var frameCryptors = mutableMapOf<Pair<String, String>, FrameCryptor>() 50 private var frameCryptors = mutableMapOf<Pair<String, String>, FrameCryptor>()
41 private var algorithm: FrameCryptorAlgorithm = FrameCryptorAlgorithm.AES_GCM 51 private var algorithm: FrameCryptorAlgorithm = FrameCryptorAlgorithm.AES_GCM
42 private lateinit var emitEvent: (roomEvent: RoomEvent) -> Unit? 52 private lateinit var emitEvent: (roomEvent: RoomEvent) -> Unit?
43 var enabled: Boolean = false 53 var enabled: Boolean = false
  54 +
44 init { 55 init {
45 this.keyProvider = keyProvider 56 this.keyProvider = keyProvider
  57 + this.peerConnectionFactory = peerConnectionFactory
46 } 58 }
47 59
48 public fun keyProvider(): KeyProvider { 60 public fun keyProvider(): KeyProvider {
@@ -153,12 +165,13 @@ constructor(keyProvider: KeyProvider) { @@ -153,12 +165,13 @@ constructor(keyProvider: KeyProvider) {
153 FrameCryptionState.ENCRYPTIONFAILED -> E2EEState.ENCRYPTION_FAILED 165 FrameCryptionState.ENCRYPTIONFAILED -> E2EEState.ENCRYPTION_FAILED
154 FrameCryptionState.DECRYPTIONFAILED -> E2EEState.DECRYPTION_FAILED 166 FrameCryptionState.DECRYPTIONFAILED -> E2EEState.DECRYPTION_FAILED
155 FrameCryptionState.INTERNALERROR -> E2EEState.INTERNAL_ERROR 167 FrameCryptionState.INTERNALERROR -> E2EEState.INTERNAL_ERROR
156 - else -> { E2EEState.INTERNAL_ERROR } 168 + else -> E2EEState.INTERNAL_ERROR
157 } 169 }
158 } 170 }
159 171
160 private fun addRtpSender(sender: RtpSender, participantId: String, trackId: String, kind: String): FrameCryptor { 172 private fun addRtpSender(sender: RtpSender, participantId: String, trackId: String, kind: String): FrameCryptor {
161 var frameCryptor = FrameCryptorFactory.createFrameCryptorForRtpSender( 173 var frameCryptor = FrameCryptorFactory.createFrameCryptorForRtpSender(
  174 + peerConnectionFactory,
162 sender, 175 sender,
163 participantId, 176 participantId,
164 algorithm, 177 algorithm,
@@ -172,6 +185,7 @@ constructor(keyProvider: KeyProvider) { @@ -172,6 +185,7 @@ constructor(keyProvider: KeyProvider) {
172 185
173 private fun addRtpReceiver(receiver: RtpReceiver, participantId: String, trackId: String, kind: String): FrameCryptor { 186 private fun addRtpReceiver(receiver: RtpReceiver, participantId: String, trackId: String, kind: String): FrameCryptor {
174 var frameCryptor = FrameCryptorFactory.createFrameCryptorForRtpReceiver( 187 var frameCryptor = FrameCryptorFactory.createFrameCryptorForRtpReceiver(
  188 + peerConnectionFactory,
175 receiver, 189 receiver,
176 participantId, 190 participantId,
177 algorithm, 191 algorithm,
@@ -209,4 +223,11 @@ constructor(keyProvider: KeyProvider) { @@ -209,4 +223,11 @@ constructor(keyProvider: KeyProvider) {
209 } 223 }
210 frameCryptors.clear() 224 frameCryptors.clear()
211 } 225 }
  226 +
  227 + @AssistedFactory
  228 + interface Factory {
  229 + fun create(
  230 + @Assisted keyProvider: KeyProvider,
  231 + ): E2EEManager
  232 + }
212 } 233 }
@@ -20,7 +20,7 @@ import livekit.LivekitModels.Encryption @@ -20,7 +20,7 @@ import livekit.LivekitModels.Encryption
20 20
21 var defaultRatchetSalt = "LKFrameEncryptionKey" 21 var defaultRatchetSalt = "LKFrameEncryptionKey"
22 var defaultMagicBytes = "LK-ROCKS" 22 var defaultMagicBytes = "LK-ROCKS"
23 -var defaultRatchetWindowSize = 16 23 +var defaultRatchetWindowSize = 0
24 var defaultFaultTolerance = -1 24 var defaultFaultTolerance = -1
25 25
26 class E2EEOptions 26 class E2EEOptions
@@ -66,6 +66,7 @@ constructor( @@ -66,6 +66,7 @@ constructor(
66 val audioHandler: AudioHandler, 66 val audioHandler: AudioHandler,
67 @Singleton 67 @Singleton
68 private val closeableManager: CloseableManager, 68 private val closeableManager: CloseableManager,
  69 + private val e2EEManagerFactory: E2EEManager.Factory,
69 ) : RTCEngine.Listener, ParticipantListener { 70 ) : RTCEngine.Listener, ParticipantListener {
70 71
71 private lateinit var coroutineScope: CoroutineScope 72 private lateinit var coroutineScope: CoroutineScope
@@ -268,12 +269,13 @@ constructor( @@ -268,12 +269,13 @@ constructor(
268 connectOptions = options 269 connectOptions = options
269 270
270 if (roomOptions.e2eeOptions != null) { 271 if (roomOptions.e2eeOptions != null) {
271 - e2eeManager = E2EEManager(roomOptions!!.e2eeOptions!!.keyProvider)  
272 - e2eeManager!!.setup(this, { event ->  
273 - coroutineScope.launch {  
274 - emitWhenConnected(event) 272 + e2eeManager = e2EEManagerFactory.create(roomOptions.e2eeOptions.keyProvider).apply {
  273 + setup(this@Room) { event ->
  274 + coroutineScope.launch {
  275 + emitWhenConnected(event)
  276 + }
275 } 277 }
276 - }) 278 + }
277 } 279 }
278 280
279 engine.join(url, token, options, roomOptions) 281 engine.join(url, token, options, roomOptions)
@@ -531,6 +533,7 @@ constructor( @@ -531,6 +533,7 @@ constructor(
531 */ 533 */
532 private fun cleanupRoom() { 534 private fun cleanupRoom() {
533 e2eeManager?.cleanUp() 535 e2eeManager?.cleanUp()
  536 + e2eeManager = null
534 localParticipant.cleanup() 537 localParticipant.cleanup()
535 remoteParticipants.keys.toMutableSet() // copy keys to avoid concurrent modifications. 538 remoteParticipants.keys.toMutableSet() // copy keys to avoid concurrent modifications.
536 .forEach { sid -> handleParticipantDisconnect(sid) } 539 .forEach { sid -> handleParticipantDisconnect(sid) }
@@ -24,6 +24,7 @@ import androidx.test.platform.app.InstrumentationRegistry @@ -24,6 +24,7 @@ import androidx.test.platform.app.InstrumentationRegistry
24 import io.livekit.android.assert.assertIsClassList 24 import io.livekit.android.assert.assertIsClassList
25 import io.livekit.android.audio.NoAudioHandler 25 import io.livekit.android.audio.NoAudioHandler
26 import io.livekit.android.coroutines.TestCoroutineRule 26 import io.livekit.android.coroutines.TestCoroutineRule
  27 +import io.livekit.android.e2ee.E2EEManager
27 import io.livekit.android.events.* 28 import io.livekit.android.events.*
28 import io.livekit.android.memory.CloseableManager 29 import io.livekit.android.memory.CloseableManager
29 import io.livekit.android.mock.* 30 import io.livekit.android.mock.*
@@ -61,6 +62,9 @@ class RoomTest { @@ -61,6 +62,9 @@ class RoomTest {
61 @Mock 62 @Mock
62 lateinit var rtcEngine: RTCEngine 63 lateinit var rtcEngine: RTCEngine
63 64
  65 + @Mock
  66 + lateinit var e2EEManagerFactory: E2EEManager.Factory
  67 +
64 var eglBase: EglBase = MockEglBase() 68 var eglBase: EglBase = MockEglBase()
65 69
66 val localParticipantFactory = object : LocalParticipant.Factory { 70 val localParticipantFactory = object : LocalParticipant.Factory {
@@ -89,6 +93,7 @@ class RoomTest { @@ -89,6 +93,7 @@ class RoomTest {
89 ioDispatcher = coroutineRule.dispatcher, 93 ioDispatcher = coroutineRule.dispatcher,
90 audioHandler = NoAudioHandler(), 94 audioHandler = NoAudioHandler(),
91 closeableManager = CloseableManager(), 95 closeableManager = CloseableManager(),
  96 + e2EEManagerFactory = e2EEManagerFactory,
92 ) 97 )
93 } 98 }
94 99