diff --git a/Source/ARTRealtime.m b/Source/ARTRealtime.m index c3312dcb1..4260f077d 100644 --- a/Source/ARTRealtime.m +++ b/Source/ARTRealtime.m @@ -1238,8 +1238,13 @@ - (void)realtimeTransportClosed:(id)transport { return; } - // Close succeeded. Nothing more to do. - [self transition:ARTRealtimeClosed]; + if (self.connection.state_nosync == ARTRealtimeClosing) { + // Close succeeded. Nothing more to do. + [self transition:ARTRealtimeClosed]; + } else if (self.connection.state_nosync != ARTRealtimeClosed && self.connection.state_nosync != ARTRealtimeFailed) { + // Unexpected closure; recover. + [self transition:ARTRealtimeDisconnected]; + } } ART_TRY_OR_MOVE_TO_FAILED_END } diff --git a/Source/ARTWebSocketTransport.m b/Source/ARTWebSocketTransport.m index 5a908098a..6cb605c82 100644 --- a/Source/ARTWebSocketTransport.m +++ b/Source/ARTWebSocketTransport.m @@ -257,10 +257,7 @@ - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reas switch (code) { case ARTWsCloseNormal: - if (_state == ARTRealtimeTransportStateClosing) { - // OK - [_delegate realtimeTransportClosed:self]; - } + [_delegate realtimeTransportClosed:self]; break; case ARTWsNeverConnected: [_delegate realtimeTransportNeverConnected:self]; diff --git a/Spec/RealtimeClient.swift b/Spec/RealtimeClient.swift index 50e742bfe..7e8ee048b 100644 --- a/Spec/RealtimeClient.swift +++ b/Spec/RealtimeClient.swift @@ -1404,6 +1404,30 @@ class RealtimeClient: QuickSpec { client.connect() } } + + fit("moves to DISCONNECTED on an unexpected normal WebSocket close") { + let options = AblyTests.commonAppSetup() + options.disconnectedRetryTimeout = 0.3 + let client = ARTRealtime(options: options) + defer { client.dispose(); client.close() } + + var received = false + client.channels.get("test").subscribe() { msg in + received = true + } + + expect(client.connection.state).toEventually(equal(ARTRealtimeConnectionState.connected), timeout: testTimeout) + + let ws = (client.transport! as! ARTWebSocketTransport).websocket! + ws.close(withCode: 1000, reason: "test") + + expect(client.connection.state).toEventually(equal(ARTRealtimeConnectionState.disconnected), timeout: testTimeout) + expect(client.connection.state).toEventually(equal(ARTRealtimeConnectionState.connected), timeout: testTimeout) + + client.channels.get("test").publish(nil, data: "test") + + expect(received).toEventually(beTrue(), timeout: testTimeout) + } } } }