emqx / CocoaMQTT

MQTT 5.0 client library for iOS and macOS written in Swift
https://www.emqx.com/en
Other
1.6k stars 419 forks source link

Reconnection quits after failure #533

Open skidnight opened 1 year ago

skidnight commented 1 year ago

I am having issues with keeping connection alive, in my case it seems to be manifesting due to a DNS failure (that I know my network is causing), but I think this may be a broader issue with reconnection. For reference I was able to keep the connection alive for over 4 hours in the background until this issue arose, but I've experienced the same failure in the foreground.

This is how I am setting up the client

        self.mWebSocket = CocoaMQTTWebSocket(uri: "/ws");
        self.mClient = CocoaMQTT(clientID: String(ProcessInfo().processIdentifier), host: host, port: UInt16(port), socket: self.mWebSocket)
        self.mClient?.keepAlive = 60
        self.mClient?.delegate = self
        self.mClient?.enableSSL = true
        self.mClient?.autoReconnect = true
        self.mClient?.autoReconnectTimeInterval = 1
        self.mClient?.cleanSession = false

        self.mClient?.logLevel = .debug
        self.mClient?.username = username
        self.mClient?.password = password

        // Connect to MQTT Broker
        _ = self.mClient!.connect(timeout: 60)

These are the debug logs from the connection. Notice it attempts to connect, fails, says it is going to retry in 1s, receives a ConnAck and then disconnects. I would expect the connection to be retried in 2s after the failure. At this point the connection is never re-attempted by the library.

CocoaMQTT(debug): SEND: CONNECT(id: 1114, username: XXXX, password: XXXX, keepAlive : 60, cleansess: false)
CocoaMQTT(debug): =========================MQTT 3.1.1=========================
CocoaMQTT(debug): packetFixedHeaderType 16
CocoaMQTT(debug): remainingLen(len: len) [82]
CocoaMQTT(debug): variableHeader [0, 4, 77, 81, 84, 84, 4, 192, 0, 60]
CocoaMQTT(debug): payload [payload bytes]
CocoaMQTT(debug): =============================================================

2023-06-22 08:58:53.360598-0400 [1114:295196] [connection] nw_flow_add_write_request [C1 10.40.0.10:443 failed parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns)] cannot accept write requests
2023-06-22 08:58:53.360780-0400 [1114:295196] [connection] nw_write_request_report [C1] Send failed with error "Socket is not connected"

2023-06-22T08:58:53-0400 debug DEBUG : "Disconnect err: Optional(Error Domain=NSPOSIXErrorDomain Code=57 \"Socket is not connected\" UserInfo={NSErrorFailingURLStringKey=https:\/\/brokerurl\/ws, NSErrorFailingURLKey=https:\/\/brokerurl:443\/ws})"

CocoaMQTT(info): Try reconnect to server after 1s
2023-06-22 08:58:53.403984-0400[1114:295196] [tcp] tcp_input [C1.1.1:3] flags=[R] seq=471036559, ack=0, win=0 state=LAST_ACK rcv_nxt=471036559, snd_una=2406599669
2023-06-22 08:58:53.648604-0400 [1114:295191] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C4] Client called nw_connection_copy_connected_local_endpoint on unconnected nw_connection
2023-06-22 08:58:53.648677-0400 [1114:295191] [connection] nw_connection_copy_connected_remote_endpoint_block_invoke [C4] Client called nw_connection_copy_connected_remote_endpoint on unconnected nw_connection
2023-06-22 08:58:53.648757-0400 [1114:295191] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C4] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
CocoaMQTT(debug): SEND: CONNECT(id: 1114, username: XXXX, password: XXXX, keepAlive : 60, cleansess: false)
CocoaMQTT(debug): =========================MQTT 3.1.1=========================
CocoaMQTT(debug): packetFixedHeaderType 16
CocoaMQTT(debug): remainingLen(len: len) [82]
CocoaMQTT(debug): variableHeader [0, 4, 77, 81, 84, 84, 4, 192, 0, 60]
CocoaMQTT(debug): payload [payload]
CocoaMQTT(debug): =============================================================
CocoaMQTT(debug): RECV: CONNACK(code: nil, sp: false)
2023-06-22 08:58:54.614220-0400 [1114:295191] Connection 5: received failure notification
2023-06-22 08:58:54.614386-0400 [1114:295191] [connection] nw_read_request_report [C5] Receive failed with error "Socket is not connected"
CocoaMQTT(debug): SEND: DISCONNECT
CocoaMQTT(debug): =========================MQTT 3.1.1=========================
CocoaMQTT(debug): packetFixedHeaderType 224
CocoaMQTT(debug): remainingLen(len: len) [0]
CocoaMQTT(debug): variableHeader []
CocoaMQTT(debug): payload []
CocoaMQTT(debug): =============================================================

2023-06-22 08:58:54.616147-0400[1114:295191] [connection] nw_flow_service_reads [C5 10.40.0.10:443 failed parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns)] No output handler
2023-06-22 08:58:54.617988-0400 Centurion Anywhere[1114:295191] [connection] nw_write_request_report [C5] Send failed with error "Socket is not connected"
2023-06-22 08:58:54.621400-0400 [1114:295192] [connection] nw_flow_add_write_request [C5 10.40.0.10:443 failed parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns)] cannot accept write requests
2023-06-22 08:58:54.621456-0400 [1114:295192] [connection] nw_write_request_report [C5] Send failed with error "Socket is not connected"
2023-06-22 08:58:54.622137-0400 [1114:295192] [connection] nw_flow_add_write_request [C5 10.40.0.10:443 failed parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns)] cannot accept write requests
2023-06-22 08:58:54.622199-0400 [1114:295192] [connection] nw_write_request_report [C5] Send failed with error "Socket is not connected"
...
2023-06-22T08:58:54-0400 debug "Disconnect err: nil""}

Eventually this state will end up with the library filling up its message buffers but the connection is never resumed. Should I be manually re-attempting the connection when I get a disconnect but with no error? Does attempting to publish when the connection is not established cause a disconnect?

Any help would be much appreciated. Thanks!

leeway1208 commented 1 year ago

Maybe you can set your own variables in the callback below. func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) Then when ack != .accept does not have 5 times or something else, you can set self.mClient?.autoReconnect = false.