Skip to content

.forceWebsockets(true) has issues with reconnect #1500

Open
@Rostyk

Description

@Rostyk

I'm using the socket in a swift iOS app like this:

private var manager: SocketManager!
private var socketIO: SocketIOClient!
.....

 manager = SocketManager(socketURL: URL(string: url)!,
                                config: [
                                    .log(true),
                                    .reconnects(true),
                                    .forceWebsockets(true)
                                    .connectParams(["roomId": nameSpace])])
        
socketIO.on(clientEvent: .reconnect, callback: { [weak self] data, ack in
            NSLog("Socket is in reconnect state")
            self?.state = .reconnecting
})
socketIO = manager.defaultSocket
socketIO.connect()

After the internet connection is lost, no .reconnect event is sent for 25 seconds and there's no way to change that behavior. I see in SocketEngine.swift this piece of code:

public func didReceive(event: Starscream.WebSocketEvent, client: Starscream.WebSocketClient) {
        switch event {
        case let .connected(headers):
            wsConnected = true
            self.client?.engineDidWebsocketUpgrade(headers: headers)
            websocketDidConnect()
        case .cancelled:
            wsConnected = false
            websocketDidDisconnect(error: EngineError.canceled)
        case .disconnected(_, _):
            wsConnected = false
            websocketDidDisconnect(error: nil)
        case let .text(msg):
            parseEngineMessage(msg)
        case let .binary(data):
            parseEngineData(data)
        case _:
            break
        }
 }

So the viabilityChanged(Bool) state is not handled in the didReceive

public enum WebSocketEvent {
    case connected([String: String])
    case disconnected(String, UInt16)
    case text(String)
    case binary(Data)
    case pong(Data?)
    case ping(Data?)
    case error(Error?)
    case viabilityChanged(Bool) // falls into default case and there's no way to subscribe for this event
    case reconnectSuggested(Bool)
    case cancelled
    case peerClosed
}

The viabilityChanged(false) is sent by StarScream in .forceWebsocket(true) mode which indicates that the socket has no physical connection. Instead I don't get the clientEvent: .reconnect until the ping times out, which is 25 seconds usually. The pingTimeout is taken from here:

if let pingInterval = json["pingInterval"] as? Int, let pingTimeout = json["pingTimeout"] as? Int {
       self.pingInterval = pingInterval
       self.pingTimeout = pingTimeout
}

Is there something I'm missing here or it's designed this way and it's okay.
I'm happy to submit pull-request with few tweaks to improve it

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions