diff --git a/SignalServiceKit/src/Account/TSAccountManager.h b/SignalServiceKit/src/Account/TSAccountManager.h index 50e0d75cf..18e1446a2 100644 --- a/SignalServiceKit/src/Account/TSAccountManager.h +++ b/SignalServiceKit/src/Account/TSAccountManager.h @@ -9,6 +9,7 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const TSRegistrationErrorDomain; extern NSString *const TSRegistrationErrorUserInfoHTTPStatus; extern NSString *const RegistrationStateDidChangeNotification; +extern NSString *const DeregistrationStateDidChangeNotification; extern NSString *const kNSNotificationName_LocalNumberDidChange; @class OWSPrimaryStorage; @@ -116,6 +117,12 @@ extern NSString *const kNSNotificationName_LocalNumberDidChange; + (void)unregisterTextSecureWithSuccess:(void (^)(void))success failure:(void (^)(NSError *error))failureBlock; +#pragma mark - Deregistration + +// De-registration reflects whether or not the service has received a 403 +- (BOOL)isDeregistered; +- (void)setIsDeregistered:(BOOL)isDeregistered; + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Account/TSAccountManager.m b/SignalServiceKit/src/Account/TSAccountManager.m index 1972c4b74..049459c69 100644 --- a/SignalServiceKit/src/Account/TSAccountManager.m +++ b/SignalServiceKit/src/Account/TSAccountManager.m @@ -23,9 +23,11 @@ NS_ASSUME_NONNULL_BEGIN NSString *const TSRegistrationErrorDomain = @"TSRegistrationErrorDomain"; NSString *const TSRegistrationErrorUserInfoHTTPStatus = @"TSHTTPStatus"; NSString *const RegistrationStateDidChangeNotification = @"RegistrationStateDidChangeNotification"; +NSString *const DeregistrationStateDidChangeNotification = @"DeregistrationStateDidChangeNotification"; NSString *const kNSNotificationName_LocalNumberDidChange = @"kNSNotificationName_LocalNumberDidChange"; NSString *const TSAccountManager_RegisteredNumberKey = @"TSStorageRegisteredNumberKey"; +NSString *const TSAccountManager_IsDeregisteredKey = @"TSAccountManager_IsDeregisteredKey"; NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegistrationId"; NSString *const TSAccountManager_UserAccountCollection = @"TSStorageUserAccountCollection"; @@ -44,6 +46,8 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling @property (nonatomic, nullable) NSString *cachedLocalNumber; @property (nonatomic, readonly) YapDatabaseConnection *dbConnection; +@property (nonatomic, nullable) NSNumber *cachedIsDeregistered; + @end #pragma mark - @@ -108,6 +112,7 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling _isRegistered = NO; _cachedLocalNumber = nil; _phoneNumberAwaitingVerification = nil; + _cachedIsDeregistered = nil; [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { [transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection]; @@ -152,6 +157,7 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling // Warm these cached values. [self isRegistered]; [self localNumber]; + [self isDeregistered]; } + (nullable NSString *)localNumber @@ -524,6 +530,47 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling } } +#pragma mark - Deregistration + +- (BOOL)isDeregistered +{ + // Cache this since we access this a lot, and once set it will not change. + @synchronized(self) { + if (self.cachedIsDeregistered == nil) { + self.cachedIsDeregistered = @([self.dbConnection boolForKey:TSAccountManager_IsDeregisteredKey + inCollection:TSAccountManager_UserAccountCollection + defaultValue:NO]); + } + } + + OWSAssert(self.cachedIsDeregistered); + return self.cachedIsDeregistered.boolValue; +} + +- (void)setIsDeregistered:(BOOL)isDeregistered +{ + @synchronized(self) { + if (self.cachedIsDeregistered && self.cachedIsDeregistered.boolValue == isDeregistered)) + { + return; + } + + DDLogWarn(@"%@ isDeregistered: %d", self.logTag, isDeregistered); + + self.cachedIsDeregistered == @(isDeregistered); + } + + [self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [transaction setValue:@(isDeregistered) + forKey:TSAccountManager_IsDeregisteredKey + inCollection:TSAccountManager_UserAccountCollection]; + }]; + + [[NSNotificationCenter defaultCenter] postNotificationNameAsync:DeregistrationStateDidChangeNotification + object:nil + userInfo:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Network/API/TSNetworkManager.m b/SignalServiceKit/src/Network/API/TSNetworkManager.m index 4d0d5adba..6e00e038f 100644 --- a/SignalServiceKit/src/Network/API/TSNetworkManager.m +++ b/SignalServiceKit/src/Network/API/TSNetworkManager.m @@ -87,6 +87,9 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); // TODO: Remove this logging when the call connection issues have been resolved. TSNetworkManagerSuccess success = ^(NSURLSessionDataTask *task, _Nullable id responseObject) { DDLogInfo(@"%@ request succeeded : %@", self.logTag, request); + + [TSAccountManager.sharedInstance setIsDeregistered:NO]; + successBlock(task, responseObject); }; TSNetworkManagerFailure failure = [TSNetworkManager errorPrettifyingForFailureBlock:failureBlock request:request]; @@ -166,6 +169,9 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); } case 400: { DDLogError(@"The request contains an invalid parameter : %@, %@", networkError.debugDescription, request); + + [TSAccountManager.sharedInstance setIsDeregistered:YES]; + failureBlock(task, error); break; } diff --git a/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m b/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m index de4c6c0ba..064bbdae4 100644 --- a/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m +++ b/SignalServiceKit/src/Network/WebSockets/TSSocketManager.m @@ -612,8 +612,14 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_ BOOL hasSuccessStatus = 200 <= responseStatus && responseStatus <= 299; BOOL didSucceed = hasSuccessStatus && hasValidResponse; if (didSucceed) { + [TSAccountManager.sharedInstance setIsDeregistered:NO]; + [socketMessage didSucceedWithResponseObject:responseObject]; } else { + if (responseStatus == 403) { + [TSAccountManager.sharedInstance setIsDeregistered:YES]; + } + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageResponseFailed, NSLocalizedString( @"ERROR_DESCRIPTION_RESPONSE_FAILED", @"Error indicating that a socket response failed."));