David Zhao

Improved reconnection when network changes.

1 <component name="ProjectCodeStyleConfiguration"> 1 <component name="ProjectCodeStyleConfiguration">
2 <code_scheme name="Project" version="173"> 2 <code_scheme name="Project" version="173">
3 <JetCodeStyleSettings> 3 <JetCodeStyleSettings>
4 - <option name="PACKAGES_TO_USE_STAR_IMPORTS">  
5 - <value>  
6 - <package name="java.util" alias="false" withSubpackages="false" />  
7 - <package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />  
8 - <package name="io.ktor" alias="false" withSubpackages="true" />  
9 - </value>  
10 - </option>  
11 - <option name="PACKAGES_IMPORT_LAYOUT">  
12 - <value>  
13 - <package name="" alias="false" withSubpackages="true" />  
14 - <package name="java" alias="false" withSubpackages="true" />  
15 - <package name="javax" alias="false" withSubpackages="true" />  
16 - <package name="kotlin" alias="false" withSubpackages="true" />  
17 - <package name="" alias="true" withSubpackages="true" />  
18 - </value>  
19 - </option>  
20 <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> 4 <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
21 </JetCodeStyleSettings> 5 </JetCodeStyleSettings>
22 <codeStyleSettings language="XML"> 6 <codeStyleSettings language="XML">
@@ -11,7 +11,7 @@ buildscript { @@ -11,7 +11,7 @@ buildscript {
11 11
12 } 12 }
13 dependencies { 13 dependencies {
14 - classpath 'com.android.tools.build:gradle:7.0.0-beta03' 14 + classpath 'com.android.tools.build:gradle:7.0.0-beta04'
15 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 15 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
16 classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" 16 classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
17 classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version" 17 classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
1 #Thu Apr 29 14:50:17 JST 2021 1 #Thu Apr 29 14:50:17 JST 2021
2 distributionBase=GRADLE_USER_HOME 2 distributionBase=GRADLE_USER_HOME
3 -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip 3 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 distributionPath=wrapper/dists 4 distributionPath=wrapper/dists
5 zipStorePath=wrapper/dists 5 zipStorePath=wrapper/dists
6 zipStoreBase=GRADLE_USER_HOME 6 zipStoreBase=GRADLE_USER_HOME
@@ -25,9 +25,10 @@ constructor( @@ -25,9 +25,10 @@ constructor(
25 listener 25 listener
26 ) ?: throw IllegalStateException("peer connection creation failed?") 26 ) ?: throw IllegalStateException("peer connection creation failed?")
27 val pendingCandidates = mutableListOf<IceCandidate>() 27 val pendingCandidates = mutableListOf<IceCandidate>()
  28 + var iceRestart: Boolean = false
28 29
29 fun addIceCandidate(candidate: IceCandidate) { 30 fun addIceCandidate(candidate: IceCandidate) {
30 - if (peerConnection.remoteDescription != null) { 31 + if (peerConnection.remoteDescription != null && !iceRestart) {
31 peerConnection.addIceCandidate(candidate) 32 peerConnection.addIceCandidate(candidate)
32 } else { 33 } else {
33 pendingCandidates.add(candidate) 34 pendingCandidates.add(candidate)
@@ -42,6 +43,7 @@ constructor( @@ -42,6 +43,7 @@ constructor(
42 peerConnection.addIceCandidate(pending) 43 peerConnection.addIceCandidate(pending)
43 } 44 }
44 pendingCandidates.clear() 45 pendingCandidates.clear()
  46 + iceRestart = false
45 super.onSetSuccess() 47 super.onSetSuccess()
46 } 48 }
47 } 49 }
@@ -50,6 +52,10 @@ constructor( @@ -50,6 +52,10 @@ constructor(
50 return observer.awaitSet() 52 return observer.awaitSet()
51 } 53 }
52 54
  55 + fun prepareForIceRestart() {
  56 + iceRestart = true
  57 + }
  58 +
53 fun close() { 59 fun close() {
54 peerConnection.close() 60 peerConnection.close()
55 } 61 }
@@ -276,6 +276,8 @@ constructor( @@ -276,6 +276,8 @@ constructor(
276 276
277 // trigger ICE restart 277 // trigger ICE restart
278 iceState = IceState.RECONNECTING 278 iceState = IceState.RECONNECTING
  279 + publisher.prepareForIceRestart()
  280 + subscriber.prepareForIceRestart()
279 negotiate() 281 negotiate()
280 } 282 }
281 283
@@ -114,14 +114,14 @@ constructor( @@ -114,14 +114,14 @@ constructor(
114 } 114 }
115 115
116 override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { 116 override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
117 - Timber.v(t) { "websocket failure: ${response}" } 117 + Timber.v(t) { "websocket failure: $response" }
118 118
119 super.onFailure(webSocket, t, response) 119 super.onFailure(webSocket, t, response)
120 } 120 }
121 121
122 //------------------------------- End WebSocket Listener ------------------------------------// 122 //------------------------------- End WebSocket Listener ------------------------------------//
123 123
124 - fun fromProtoSessionDescription(sd: LivekitRtc.SessionDescription): SessionDescription { 124 + private fun fromProtoSessionDescription(sd: LivekitRtc.SessionDescription): SessionDescription {
125 val rtcSdpType = when (sd.type) { 125 val rtcSdpType = when (sd.type) {
126 SD_TYPE_ANSWER -> SessionDescription.Type.ANSWER 126 SD_TYPE_ANSWER -> SessionDescription.Type.ANSWER
127 SD_TYPE_OFFER -> SessionDescription.Type.OFFER 127 SD_TYPE_OFFER -> SessionDescription.Type.OFFER
@@ -131,7 +131,7 @@ constructor( @@ -131,7 +131,7 @@ constructor(
131 return SessionDescription(rtcSdpType, sd.sdp) 131 return SessionDescription(rtcSdpType, sd.sdp)
132 } 132 }
133 133
134 - fun toProtoSessionDescription(sdp: SessionDescription): LivekitRtc.SessionDescription { 134 + private fun toProtoSessionDescription(sdp: SessionDescription): LivekitRtc.SessionDescription {
135 val sdBuilder = LivekitRtc.SessionDescription.newBuilder() 135 val sdBuilder = LivekitRtc.SessionDescription.newBuilder()
136 sdBuilder.sdp = sdp.description 136 sdBuilder.sdp = sdp.description
137 sdBuilder.type = when (sdp.type) { 137 sdBuilder.type = when (sdp.type) {
@@ -224,11 +224,10 @@ constructor( @@ -224,11 +224,10 @@ constructor(
224 sendRequest(request) 224 sendRequest(request)
225 } 225 }
226 226
227 - fun sendUpdateSubscription(sid: String, subscribe: Boolean, videoQuality: LivekitRtc.VideoQuality) { 227 + fun sendUpdateSubscription(sid: String, subscribe: Boolean) {
228 val subscription = LivekitRtc.UpdateSubscription.newBuilder() 228 val subscription = LivekitRtc.UpdateSubscription.newBuilder()
229 .addTrackSids(sid) 229 .addTrackSids(sid)
230 .setSubscribe(subscribe) 230 .setSubscribe(subscribe)
231 - .setQuality(videoQuality)  
232 231
233 val request = LivekitRtc.SignalRequest.newBuilder() 232 val request = LivekitRtc.SignalRequest.newBuilder()
234 .setSubscription(subscription) 233 .setSubscription(subscription)
@@ -247,7 +246,8 @@ constructor( @@ -247,7 +246,8 @@ constructor(
247 private fun sendRequest(request: LivekitRtc.SignalRequest) { 246 private fun sendRequest(request: LivekitRtc.SignalRequest) {
248 Timber.v { "sending request: $request" } 247 Timber.v { "sending request: $request" }
249 if (!isConnected || currentWs == null) { 248 if (!isConnected || currentWs == null) {
250 - throw IllegalStateException("not connected!") 249 + Timber.w { "not connected, could not send request $request" }
  250 + return
251 } 251 }
252 val sent: Boolean 252 val sent: Boolean
253 if (useJson) { 253 if (useJson) {
@@ -340,7 +340,7 @@ constructor( @@ -340,7 +340,7 @@ constructor(
340 const val SD_TYPE_ANSWER = "answer" 340 const val SD_TYPE_ANSWER = "answer"
341 const val SD_TYPE_OFFER = "offer" 341 const val SD_TYPE_OFFER = "offer"
342 const val SD_TYPE_PRANSWER = "pranswer" 342 const val SD_TYPE_PRANSWER = "pranswer"
343 - const val PROTOCOL_VERSION = 2; 343 + const val PROTOCOL_VERSION = 2
344 344
345 private fun iceServer(url: String) = 345 private fun iceServer(url: String) =
346 PeerConnection.IceServer.builder(url).createIceServer() 346 PeerConnection.IceServer.builder(url).createIceServer()
@@ -44,7 +44,7 @@ class RemoteTrackPublication( @@ -44,7 +44,7 @@ class RemoteTrackPublication(
44 unsubscribed = !subscribed 44 unsubscribed = !subscribed
45 val participant = this.participant.get() as? RemoteParticipant ?: return 45 val participant = this.participant.get() as? RemoteParticipant ?: return
46 46
47 - participant.signalClient.sendUpdateSubscription(sid, !unsubscribed, videoQuality) 47 + participant.signalClient.sendUpdateSubscription(sid, !unsubscribed)
48 } 48 }
49 49
50 /** 50 /**