livekit / client-sdk-swift

LiveKit Swift Client SDK. Easily build live audio or video experiences into your mobile app, game or website.
https://livekit.io
Apache License 2.0
176 stars 85 forks source link

occasionally unable to connect to the room #304

Closed wzJun1 closed 6 months ago

wzJun1 commented 6 months ago

Describe the bug

when someone has created a room and there is someone in the room, and the iOS client using the iOS SDK is used to enter, occasionally the room cannot be connected and the following log appears.

Additional explanation: This may appear when the App is run for the first time (when there is no process of the App), but it does not appear the second, third and subsequent times.

SDK Version client sdk:latest version livekit server:1.5.2

Expected behavior normal connection, because everything works fine on Android (v1.6.0)

Logs xcode debug output:

2024-01-14T15:12:06+0800 warning LiveKitSDK : [KTCallKit] VideoView.performLayout() track is nil, cannot layout without track
2024-01-14T15:12:06+0800 warning LiveKitSDK : [KTCallKit] VideoView.performLayout() track is nil, cannot layout without track
2024-01-14T15:12:06+0800 info LiveKitSDK : [KTCallKit] Room.connect(url:token:connectOptions:roomOptions:) connecting to room...
2024-01-14T15:12:06+0800 error LiveKitSDK : [KTCallKit] Engine.signalClient(_:didReceiveOffer:) failed to send answer, subscriber is nil
2024-01-14T15:12:06+0800 info LiveKitSDK : [KTCallKit] Room.signalClient(_:didReceiveConnectResponse:) ServerInfo(edition: standard, version: 1.5.2, protocol: 11, region: , nodeID: ND_AyE5ctYueGJn, debugInfo: )
2024-01-14T15:12:06+0800 error LiveKitSDK : [KTCallKit] Engine.signalClient(_:didReceiveIceCandidate:target:) Failed to add ice candidate, transport is nil for target: subscriber
2024-01-14T15:12:06+0800 error LiveKitSDK : [KTCallKit] Engine.signalClient(_:didReceiveIceCandidate:target:) Failed to add ice candidate, transport is nil for target: subscriber

iOS Room Options

room = Room(
            delegate: self,
            connectOptions: ConnectOptions(
                autoSubscribe: false,
                reconnectAttempts: 1000,
                reconnectAttemptDelay: 3
            ),
            roomOptions: RoomOptions(
                defaultCameraCaptureOptions: CameraCaptureOptions(
                    position: "front",
                    dimensions: .h540_169,
                    fps: 15
                ),
                defaultScreenShareCaptureOptions: ScreenShareCaptureOptions(
                    useBroadcastExtension: false
                ),
                defaultAudioCaptureOptions: AudioCaptureOptions(
                    echoCancellation: true,
                    noiseSuppression: true,
                    autoGainControl: true,
                    typingNoiseDetection: true,
                    highpassFilter: true
                ),
                defaultVideoPublishOptions: VideoPublishOptions(
                    encoding: VideoEncoding(
                        maxBitrate: 9_500_000,
                        maxFps: 60
                    ),
                    simulcast: false,
                    simulcastLayers: []
                ),
                defaultAudioPublishOptions: AudioPublishOptions(
                    encoding: AudioEncoding(maxBitrate: 96_000),
                    dtx: true
                ),
                adaptiveStream: false,
                dynacast: false,
                suspendLocalVideoTracksInBackground: false
            )
        )

LiveKitServer Config

port: 7880
log_level: info
redis:
  address: 172.10.15.5:6379
  db: 8  
rtc:
  tcp_port: 7881
  port_range_start: 50000
  port_range_end: 60000
  use_external_ip: true
keys:
  xxx: 26148d621ef74844918af182d63976b6
turn:
  enabled: true
  domain: xxx.xxx.com
  tls_port: 443
  cert_file: /www/server/panel/vhost/cert/xxx.xxx.com/fullchain.pem
  key_file: /www/server/panel/vhost/cert/xxx.xxx.com/privkey.pem
webhook: 
  api_key: 'xxx'
  urls: 
    - 'http://xxx.xxx.com/api/webhook'
    - 'http://xxx.xxx.com/api/webhook'

TestConnection test.png

wzJun1 commented 6 months ago

The same problem occurs when using livekit cloud

wzJun1 commented 6 months ago

Version: 1.0.13 no such problem

wzJun1 commented 6 months ago

urgent! urgent!

I printed the websocket message and found that the join message was delayed.

hiroshihorie commented 6 months ago

Hello, can I have the exact SDK version ?

wzJun1 commented 6 months ago

Hello, can I have the exact SDK version ?

Latest, direct git clone

git clone https://github.com/livekit/client-sdk-swift.git

wzJun1 commented 6 months ago

I don't understand what caused it, but when printing the websocket message, I found that when the connection is success, I will receive the join first. Once there are problems or abnormal connection, you will receive an offer or refreshToken first. I'm not sure if it will be helpful for your verification.

It can be confirmed that the old version does not have this issue

hiroshihorie commented 6 months ago

Ok you are on the latest main, that sounds like something wrong with the response queue. I will investigate.

wzJun1 commented 6 months ago

Ok you are on the latest main, that sounds like something wrong with the response queue. I will investigate.

Thank you for your reply! Hope you can check!

hiroshihorie commented 6 months ago

I think this will fix it: https://github.com/livekit/client-sdk-swift/pull/306

wzJun1 commented 6 months ago

Okay, I will try it.

wzJun1 commented 6 months ago

thx! The connection is normal!

But my IDE doesn’t seem to support the following writing method, so I modified it.

     func _onWebSocketMessage(message: URLSessionWebSocketTask.Message) {

          // var response: Livekit_SignalResponse? = if case let .data(data) = message {
          // try? Livekit_SignalResponse(contiguousBytes: data)
          // } else if case let .string(string) = message {
          // try? Livekit_SignalResponse(jsonString: string)
          // } else {
          // nil
          // }

         var response: Livekit_SignalResponse? = nil

         if case let .data(data) = message {
             response = try? Livekit_SignalResponse(contiguousBytes: data)
         } else if case let .string(string) = message {
             response = try? Livekit_SignalResponse(jsonString: string)
         } else {
             response = nil
         }

         guard let response else {
             log("Failed to decode SignalResponse", .warning)
             return
         }

         Task {
             var isJoinOrReconnect = false
             switch response.message {
             case .join, .reconnect: isJoinOrReconnect = true
             default: false
             }
             // Always process join or reconnect messages even if suspended...
             await _responseQueue.processIfResumed(response, or: isJoinOrReconnect)
         }
     }
hiroshihorie commented 6 months ago

Xcode 14.2 compiling has been fixed, and now it's merged in main branch. Thanks for the detailed report !