David Liu

PeerConnectionTransport

  1 +package io.livekit.android.room
  2 +
  3 +import dagger.assisted.Assisted
  4 +import dagger.assisted.AssistedInject
  5 +import org.webrtc.*
  6 +
  7 +class PeerConnectionTransport
  8 +@AssistedInject
  9 +constructor(
  10 + config: PeerConnection.RTCConfiguration,
  11 + listener: PeerConnection.Observer,
  12 + @Assisted connectionFactory: PeerConnectionFactory
  13 +) {
  14 + val peerConnection: PeerConnection = connectionFactory.createPeerConnection(
  15 + config,
  16 + listener
  17 + ) ?: throw IllegalStateException("peer connection creation failed?")
  18 + val pendingCandidates = mutableListOf<IceCandidate>()
  19 +
  20 + fun addIceCandidate(candidate: IceCandidate) {
  21 + if (peerConnection.remoteDescription != null) {
  22 + peerConnection.addIceCandidate(candidate)
  23 + } else {
  24 + pendingCandidates.add(candidate)
  25 + }
  26 + }
  27 +
  28 + fun setRemoteDescription(sd: SessionDescription) {
  29 + peerConnection.setRemoteDescription(object : SdpObserver {
  30 + override fun onCreateSuccess(p0: SessionDescription?) {
  31 + }
  32 +
  33 + override fun onSetSuccess() {
  34 + pendingCandidates.forEach { pending ->
  35 + peerConnection.addIceCandidate(pending)
  36 + }
  37 + pendingCandidates.clear()
  38 + }
  39 +
  40 + override fun onCreateFailure(p0: String?) {
  41 + }
  42 +
  43 + override fun onSetFailure(p0: String?) {
  44 + }
  45 +
  46 + }, sd)
  47 + }
  48 +
  49 + fun close() {
  50 + peerConnection.close()
  51 + }
  52 +}
@@ -13,10 +13,11 @@ import okhttp3.WebSocket @@ -13,10 +13,11 @@ import okhttp3.WebSocket
13 import okhttp3.WebSocketListener 13 import okhttp3.WebSocketListener
14 import okio.ByteString 14 import okio.ByteString
15 import org.webrtc.IceCandidate 15 import org.webrtc.IceCandidate
  16 +import org.webrtc.PeerConnection
16 import org.webrtc.SessionDescription 17 import org.webrtc.SessionDescription
17 import javax.inject.Inject 18 import javax.inject.Inject
18 19
19 -internal class RTCClient 20 +class RTCClient
20 @Inject 21 @Inject
21 constructor( 22 constructor(
22 private val websocketFactory: WebSocket.Factory, 23 private val websocketFactory: WebSocket.Factory,
@@ -28,7 +29,7 @@ constructor( @@ -28,7 +29,7 @@ constructor(
28 private var currentWs: WebSocket? = null 29 private var currentWs: WebSocket? = null
29 var listener: Listener? = null 30 var listener: Listener? = null
30 31
31 - fun connect( 32 + fun join(
32 host: String, 33 host: String,
33 token: String, 34 token: String,
34 isSecure: Boolean, 35 isSecure: Boolean,
@@ -240,5 +241,16 @@ constructor( @@ -240,5 +241,16 @@ constructor(
240 const val SD_TYPE_ANSWER = "answer" 241 const val SD_TYPE_ANSWER = "answer"
241 const val SD_TYPE_OFFER = "offer" 242 const val SD_TYPE_OFFER = "offer"
242 const val SD_TYPE_PRANSWER = "pranswer" 243 const val SD_TYPE_PRANSWER = "pranswer"
  244 +
  245 + private fun iceServer(url: String) =
  246 + PeerConnection.IceServer.builder(url).createIceServer()
  247 +
  248 + val DEFAULT_ICE_SERVERS = listOf(
  249 + iceServer("stun:stun.l.google.com:19302"),
  250 + iceServer("stun:stun1.l.google.com:19302"),
  251 + iceServer("stun:stun2.l.google.com:19302"),
  252 + iceServer("stun:stun3.l.google.com:19302"),
  253 + iceServer("stun:stun4.l.google.com:19302"),
  254 + )
243 } 255 }
244 } 256 }
1 package io.livekit.android.room 1 package io.livekit.android.room
2 2
3 -internal class RTCEngine { 3 +import org.webrtc.PeerConnection
  4 +import javax.inject.Inject
4 5
  6 +class RTCEngine
  7 +@Inject
  8 +constructor(
  9 + private val client: RTCClient
  10 +) {
  11 +
  12 + init {
  13 + val rtcConfig = PeerConnection.RTCConfiguration(RTCClient.DEFAULT_ICE_SERVERS).apply {
  14 + sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN
  15 + continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY
  16 + }
  17 +
  18 + }
  19 +
  20 + suspend fun join(url: String, token: String, isSecure: Boolean) {
  21 + client.join(url, token, isSecure)
  22 + }
5 } 23 }
1 package io.livekit.android.room 1 package io.livekit.android.room
2 2
3 -class Room( 3 +import dagger.assisted.Assisted
  4 +import dagger.assisted.AssistedInject
  5 +import io.livekit.android.ConnectOptions
4 6
  7 +class Room
  8 +@AssistedInject
  9 +constructor(
  10 + private val connectOptions: ConnectOptions,
  11 + @Assisted private val engine: RTCEngine,
5 ) { 12 ) {
6 13
  14 + suspend fun connect() {
  15 + engine.join(connectOptions)
  16 + }
7 } 17 }