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 {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation deps.coroutines.lib
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0'
api 'io.github.webrtc-sdk:android:114.5735.03'
api 'io.github.webrtc-sdk:android:114.5735.04'
api "com.squareup.okhttp3:okhttp:4.10.0"
api 'com.github.davidliu:audioswitch:d18e3e31d427c27f1593030e024b370bf24480fd'
implementation "androidx.annotation:annotation:1.4.0"
... ...
... ... @@ -37,7 +37,7 @@ data class RoomOptions(
/**
* Options for end-to-end encryption.
*/
var e2eeOptions: E2EEOptions? = null,
val e2eeOptions: E2EEOptions? = null,
val audioTrackCaptureDefaults: LocalAudioTrackOptions? = null,
val videoTrackCaptureDefaults: LocalVideoTrackOptions? = null,
... ...
... ... @@ -16,9 +16,13 @@
package io.livekit.android.e2ee
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.livekit.android.events.RoomEvent
import io.livekit.android.room.Room
import io.livekit.android.room.participant.*
import io.livekit.android.room.participant.LocalParticipant
import io.livekit.android.room.participant.RemoteParticipant
import io.livekit.android.room.track.LocalAudioTrack
import io.livekit.android.room.track.LocalVideoTrack
import io.livekit.android.room.track.RemoteAudioTrack
... ... @@ -30,19 +34,27 @@ import org.webrtc.FrameCryptor
import org.webrtc.FrameCryptor.FrameCryptionState
import org.webrtc.FrameCryptorAlgorithm
import org.webrtc.FrameCryptorFactory
import org.webrtc.PeerConnectionFactory
import org.webrtc.RtpReceiver
import org.webrtc.RtpSender
class E2EEManager
constructor(keyProvider: KeyProvider) {
@AssistedInject
constructor(
@Assisted keyProvider: KeyProvider,
peerConnectionFactory: PeerConnectionFactory,
) {
private var room: Room? = null
private var keyProvider: KeyProvider
private var peerConnectionFactory: PeerConnectionFactory
private var frameCryptors = mutableMapOf<Pair<String, String>, FrameCryptor>()
private var algorithm: FrameCryptorAlgorithm = FrameCryptorAlgorithm.AES_GCM
private lateinit var emitEvent: (roomEvent: RoomEvent) -> Unit?
var enabled: Boolean = false
init {
this.keyProvider = keyProvider
this.peerConnectionFactory = peerConnectionFactory
}
public fun keyProvider(): KeyProvider {
... ... @@ -153,12 +165,13 @@ constructor(keyProvider: KeyProvider) {
FrameCryptionState.ENCRYPTIONFAILED -> E2EEState.ENCRYPTION_FAILED
FrameCryptionState.DECRYPTIONFAILED -> E2EEState.DECRYPTION_FAILED
FrameCryptionState.INTERNALERROR -> E2EEState.INTERNAL_ERROR
else -> { E2EEState.INTERNAL_ERROR }
else -> E2EEState.INTERNAL_ERROR
}
}
private fun addRtpSender(sender: RtpSender, participantId: String, trackId: String, kind: String): FrameCryptor {
var frameCryptor = FrameCryptorFactory.createFrameCryptorForRtpSender(
peerConnectionFactory,
sender,
participantId,
algorithm,
... ... @@ -172,6 +185,7 @@ constructor(keyProvider: KeyProvider) {
private fun addRtpReceiver(receiver: RtpReceiver, participantId: String, trackId: String, kind: String): FrameCryptor {
var frameCryptor = FrameCryptorFactory.createFrameCryptorForRtpReceiver(
peerConnectionFactory,
receiver,
participantId,
algorithm,
... ... @@ -209,4 +223,11 @@ constructor(keyProvider: KeyProvider) {
}
frameCryptors.clear()
}
@AssistedFactory
interface Factory {
fun create(
@Assisted keyProvider: KeyProvider,
): E2EEManager
}
}
... ...
... ... @@ -20,7 +20,7 @@ import livekit.LivekitModels.Encryption
var defaultRatchetSalt = "LKFrameEncryptionKey"
var defaultMagicBytes = "LK-ROCKS"
var defaultRatchetWindowSize = 16
var defaultRatchetWindowSize = 0
var defaultFaultTolerance = -1
class E2EEOptions
... ...
... ... @@ -66,6 +66,7 @@ constructor(
val audioHandler: AudioHandler,
@Singleton
private val closeableManager: CloseableManager,
private val e2EEManagerFactory: E2EEManager.Factory,
) : RTCEngine.Listener, ParticipantListener {
private lateinit var coroutineScope: CoroutineScope
... ... @@ -268,12 +269,13 @@ constructor(
connectOptions = options
if (roomOptions.e2eeOptions != null) {
e2eeManager = E2EEManager(roomOptions!!.e2eeOptions!!.keyProvider)
e2eeManager!!.setup(this, { event ->
coroutineScope.launch {
emitWhenConnected(event)
e2eeManager = e2EEManagerFactory.create(roomOptions.e2eeOptions.keyProvider).apply {
setup(this@Room) { event ->
coroutineScope.launch {
emitWhenConnected(event)
}
}
})
}
}
engine.join(url, token, options, roomOptions)
... ... @@ -531,6 +533,7 @@ constructor(
*/
private fun cleanupRoom() {
e2eeManager?.cleanUp()
e2eeManager = null
localParticipant.cleanup()
remoteParticipants.keys.toMutableSet() // copy keys to avoid concurrent modifications.
.forEach { sid -> handleParticipantDisconnect(sid) }
... ...
... ... @@ -24,6 +24,7 @@ import androidx.test.platform.app.InstrumentationRegistry
import io.livekit.android.assert.assertIsClassList
import io.livekit.android.audio.NoAudioHandler
import io.livekit.android.coroutines.TestCoroutineRule
import io.livekit.android.e2ee.E2EEManager
import io.livekit.android.events.*
import io.livekit.android.memory.CloseableManager
import io.livekit.android.mock.*
... ... @@ -61,6 +62,9 @@ class RoomTest {
@Mock
lateinit var rtcEngine: RTCEngine
@Mock
lateinit var e2EEManagerFactory: E2EEManager.Factory
var eglBase: EglBase = MockEglBase()
val localParticipantFactory = object : LocalParticipant.Factory {
... ... @@ -89,6 +93,7 @@ class RoomTest {
ioDispatcher = coroutineRule.dispatcher,
audioHandler = NoAudioHandler(),
closeableManager = CloseableManager(),
e2EEManagerFactory = e2EEManagerFactory,
)
}
... ...