From 46bd22decc4a510e8b4013f50a5ee5b90e252ff3 Mon Sep 17 00:00:00 2001 From: Jens Alfke Date: Mon, 1 Feb 2016 18:24:52 -0800 Subject: [PATCH] CBLWebSocketChangeTracker: Handle remote disconnect If the server closes the WebSocket connection, even cleanly with no error status, the change tracker should treat it as a recoverable error and retry. Fixes #1083 --- .../ChangeTracker/CBLWebSocketChangeTracker.m | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/Source/ChangeTracker/CBLWebSocketChangeTracker.m b/Source/ChangeTracker/CBLWebSocketChangeTracker.m index 4dbc22357..2d83195f5 100644 --- a/Source/ChangeTracker/CBLWebSocketChangeTracker.m +++ b/Source/ChangeTracker/CBLWebSocketChangeTracker.m @@ -232,17 +232,34 @@ - (void)webSocket:(PSWebSocket *)ws if (ws != _ws) return; _ws = nil; + NSInteger effectiveCode = code; + NSString* effectiveReason = reason; if (wasClean && (code == PSWebSocketStatusCodeNormal || code == 0)) { - LogTo(ChangeTracker, @"%@: closed", self); - [self stop]; - } else { - NSDictionary* userInfo = $dict({NSLocalizedFailureReasonErrorKey, reason}, - {NSURLErrorFailingURLStringErrorKey, - self.changesFeedURL.absoluteString}); - NSError* error = [NSError errorWithDomain: PSWebSocketErrorDomain code: code - userInfo: userInfo]; - [self failedWithError: error]; + // Clean shutdown with no error/status: + if (!_running) { + // I closed the connection, so this is expected. + LogTo(ChangeTracker, @"%@: closed", self); + [self stop]; + return; // without reporting error + + } else { + // Server closed the connection. It shouldn't do this unless it's going offline + // or something; treat this as an (non-fatal) error. + LogTo(ChangeTracker, @"%@: closed unexpectedly", self); + effectiveCode = 503; // Service Unavailable + if (!effectiveReason) + effectiveReason = @"Server closed connection"; + } } + + // Report error: + LogTo(ChangeTracker, @"%@: closed with code %ld, reason '%@'", self, effectiveCode, reason); + NSDictionary* userInfo = $dict({NSLocalizedFailureReasonErrorKey, reason}, + {NSURLErrorFailingURLStringErrorKey, + self.changesFeedURL.absoluteString}); + NSError* error = [NSError errorWithDomain: PSWebSocketErrorDomain code: effectiveCode + userInfo: userInfo]; + [self failedWithError: error]; }); }