diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index d1a225d2e..55213ef3f 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -37,7 +37,7 @@ static PushManager *sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedManager = [self new]; + sharedManager = [self new]; }); return sharedManager; } @@ -48,11 +48,11 @@ if (self) { self.notificationTracker = [NotificationTracker notificationTracker]; self.missingPermissionsAlertView = - [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") - message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") - delegate:nil - cancelButtonTitle:NSLocalizedString(@"OK", @"") - otherButtonTitles:nil, nil]; + [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") + message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil, nil]; } return self; } @@ -60,7 +60,7 @@ #pragma mark Manage Incoming Push -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { - + if ([self isRedPhonePush:userInfo]) { ResponderSessionDescriptor* call; if (![self.notificationTracker shouldProcessNotification:userInfo]){ @@ -150,7 +150,6 @@ } else{ NSString *threadId = [notification.userInfo objectForKey:Signal_Thread_UserInfo_Key]; [Environment messageThreadId:threadId]; - completionHandler(); } } @@ -174,7 +173,7 @@ } -(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type -{ +{ [self application:[UIApplication sharedApplication] didReceiveRemoteNotification:payload.dictionaryPayload]; } @@ -207,7 +206,7 @@ { self.pushNotificationFutureSource = [TOCFutureSource new]; [UIApplication.sharedApplication registerForRemoteNotifications]; - + return self.pushNotificationFutureSource.future; } @@ -217,10 +216,10 @@ [requestPushTokenFuture catchDo:^(id failureObj) { [self.missingPermissionsAlertView show]; - failure(failureObj); - DDLogError(@"This should not happen on iOS8. No push token was provided"); + failure(failureObj); + DDLogError(@"This should not happen on iOS8. No push token was provided"); }]; - + [requestPushTokenFuture thenDo:^(NSData *pushToken) { TOCFuture *voipPushTokenFuture = [self registerPushKitNotificationFuture]; @@ -253,15 +252,15 @@ voipToken:fakeToken withSuccess:success failure:failure]; - + return; } - + [self requestPushTokenWithSuccess:^(NSData *pushToken, NSData *voipToken) { [self registerTokenWithRedPhoneServer:pushToken voipToken:voipToken withSuccess:success failure:failure]; } failure:^(NSError *error) { - [self.missingPermissionsAlertView show]; - failure([NSError errorWithDomain:pushManagerDomain code:400 userInfo:@{}]); + [self.missingPermissionsAlertView show]; + failure([NSError errorWithDomain:pushManagerDomain code:400 userInfo:@{}]); }]; } @@ -271,22 +270,22 @@ failure:(failedPushRegistrationBlock)failure { [RPServerRequestsManager.sharedInstance performRequest:[RPAPICall requestTextSecureVerificationCode] - success:^(NSURLSessionDataTask *task, id responseObject) { - NSError *error; - - NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error]; - NSString *tsToken = [dictionary objectForKey:@"token"]; - - if (!tsToken || !pushToken || error) { - failure(error); - return; - } - - success(pushToken, voipToken, tsToken); - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - failure(error); - }]; + success:^(NSURLSessionDataTask *task, id responseObject) { + NSError *error; + + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error]; + NSString *tsToken = [dictionary objectForKey:@"token"]; + + if (!tsToken || !pushToken || error) { + failure(error); + return; + } + + success(pushToken, voipToken, tsToken); + } + failure:^(NSURLSessionDataTask *task, NSError *error) { + failure(error); + }]; } - (TOCFuture *)registerForUserNotificationsFuture @@ -294,8 +293,8 @@ self.userNotificationFutureSource = [TOCFutureSource new]; UIUserNotificationSettings *settings = - [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] - categories:[NSSet setWithObjects:[self userNotificationsCallCategory], [self userNotificationsMessageCategory], nil]]; + [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] + categories:[NSSet setWithObjects:[self userNotificationsCallCategory], [self userNotificationsMessageCategory], nil]]; [UIApplication.sharedApplication registerUserNotificationSettings:settings]; return self.userNotificationFutureSource.future; @@ -348,12 +347,12 @@ - (BOOL)wantRemoteNotifications { BOOL isSimulator = [UIDevice.currentDevice.model.lowercaseString rangeOfString:@"simulator"].location != NSNotFound; - + if (isSimulator) { // Simulator is used for debugging but can't receive push notifications, so don't bother trying to get them return NO; } - + return YES; } @@ -376,25 +375,25 @@ self.registerWithServerFutureSource = [TOCFutureSource new]; [RPServerRequestsManager.sharedInstance performRequest:[RPAPICall registerPushNotificationWithPushToken:pushToken voipToken:voipToken] - success:^(NSURLSessionDataTask *task, id responseObject) { - if ([task.response isKindOfClass:NSHTTPURLResponse.class]) { - NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode]; - if (statusCode == 200) { - [self.registerWithServerFutureSource trySetResult:@YES]; - } else { - DDLogError(@"The server returned %@ instead of a 200 status code", task.response); - [self.registerWithServerFutureSource - trySetFailure:[NSError errorWithDomain:pushManagerDomain code:500 userInfo:nil]]; - } - } else { - [self.registerWithServerFutureSource trySetFailure:task.response]; - } - - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - [self.registerWithServerFutureSource trySetFailure:error]; - }]; - + success:^(NSURLSessionDataTask *task, id responseObject) { + if ([task.response isKindOfClass:NSHTTPURLResponse.class]) { + NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode]; + if (statusCode == 200) { + [self.registerWithServerFutureSource trySetResult:@YES]; + } else { + DDLogError(@"The server returned %@ instead of a 200 status code", task.response); + [self.registerWithServerFutureSource + trySetFailure:[NSError errorWithDomain:pushManagerDomain code:500 userInfo:nil]]; + } + } else { + [self.registerWithServerFutureSource trySetFailure:task.response]; + } + + } + failure:^(NSURLSessionDataTask *task, NSError *error) { + [self.registerWithServerFutureSource trySetFailure:error]; + }]; + return self.registerWithServerFutureSource.future; } diff --git a/Signal/src/textsecure/Messages/TSMessagesManager.m b/Signal/src/textsecure/Messages/TSMessagesManager.m index c8b707738..ae1e72473 100644 --- a/Signal/src/textsecure/Messages/TSMessagesManager.m +++ b/Signal/src/textsecure/Messages/TSMessagesManager.m @@ -45,8 +45,6 @@ #import #import -#define ddLogLevel LOG_LEVEL_VERBOSE - @interface TSMessagesManager () @property SystemSoundID newMessageSound; diff --git a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m b/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m index ad77cebd9..309d2717e 100644 --- a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m +++ b/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m @@ -21,8 +21,8 @@ #define kWebSocketHeartBeat 30 #define kWebSocketReconnectTry 5 -#define kBackgroundConnectTimer 120 -#define kBackgroundConnectKeepAlive 20 +#define kBackgroundConnectTimer 10 +#define kBackgroundConnectKeepAlive 15 NSString * const SocketOpenedNotification = @"SocketOpenedNotification"; NSString * const SocketClosedNotification = @"SocketClosedNotification"; @@ -31,7 +31,7 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; @interface TSSocketManager () @property (nonatomic, retain) NSTimer *pingTimer; @property (nonatomic, retain) NSTimer *reconnectTimer; -@property (nonatomic, retain) NSTimer *backgroundKeepAliveTimer; + @property (nonatomic, retain) SRWebSocket *websocket; @property (nonatomic) SocketStatus status; @@ -39,6 +39,8 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; @property (nonatomic) UIBackgroundTaskIdentifier fetchingTaskIdentifier; @property BOOL didFetchInBackground; +@property (nonatomic, retain) NSTimer *backgroundKeepAliveTimer; +@property (nonatomic, retain) NSTimer *backgroundConnectTimer; @end @@ -61,7 +63,7 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; dispatch_once(&onceToken, ^{ sharedMyManager = [[self alloc] init]; sharedMyManager.fetchingTaskIdentifier = UIBackgroundTaskInvalid; - sharedMyManager.didFetchInBackground = FALSE; + sharedMyManager.didFetchInBackground = NO; }); return sharedMyManager; } @@ -104,8 +106,8 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; socket = [[SRWebSocket alloc] initWithURLRequest:request]; socket.delegate = [self sharedManager]; - [socket open]; [[self sharedManager] setWebsocket:socket]; + [socket open]; } + (void)resignActivity{ @@ -126,14 +128,14 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; [[NSRunLoop mainRunLoop] addTimer:self.pingTimer forMode:NSDefaultRunLoopMode]; - self.status = kSocketStatusOpen; - + self.status = kSocketStatusOpen; [self.reconnectTimer invalidate]; self.reconnectTimer = nil; } - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { DDLogError(@"Error connecting to socket %@", error); + [self.pingTimer invalidate]; self.status = kSocketStatusClosed; [self scheduleRetry]; @@ -177,6 +179,8 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; } - (void)keepAliveBackground { + [self.backgroundConnectTimer invalidate]; + if (self.fetchingTaskIdentifier) { [self.backgroundKeepAliveTimer invalidate]; @@ -188,7 +192,7 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; // Additionally, we want the reconnect timer to work in the background too. [[NSRunLoop mainRunLoop] addTimer:self.backgroundKeepAliveTimer forMode:NSDefaultRunLoopMode]; - + } } @@ -215,10 +219,12 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; } - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { - DDLogVerbose(@"WebSocket did close"); [self.pingTimer invalidate]; self.status = kSocketStatusClosed; - [self scheduleRetry]; + + if (!wasClean && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) { + [self scheduleRetry]; + } } - (void)webSocketHeartBeat { @@ -231,7 +237,9 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; } - (NSString*)webSocketAuthenticationString { - return [NSString stringWithFormat:@"?login=%@&password=%@", [[TSAccountManager registeredNumber] stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"],[TSStorageManager serverAuthToken]]; + return [NSString stringWithFormat:@"?login=%@&password=%@", + [[TSAccountManager registeredNumber] stringByReplacingOccurrencesOfString:@"+" + withString:@"%2B"],[TSStorageManager serverAuthToken]]; } - (void)scheduleRetry { @@ -265,11 +273,24 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; TSSocketManager *sharedInstance = [TSSocketManager sharedManager]; if (sharedInstance.fetchingTaskIdentifier == UIBackgroundTaskInvalid) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + sharedInstance.backgroundConnectTimer = [NSTimer scheduledTimerWithTimeInterval:kBackgroundConnectTimer + target:sharedInstance + selector:@selector(backgroundConnectTimerExpired) + userInfo:nil + repeats:NO]; + + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + [loop addTimer:[TSSocketManager sharedManager].backgroundConnectTimer + forMode:NSDefaultRunLoopMode]; + [loop run]; + }); + [sharedInstance.backgroundKeepAliveTimer invalidate]; - sharedInstance.didFetchInBackground = NO; + sharedInstance.didFetchInBackground = NO; sharedInstance.fetchingTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [TSSocketManager resignActivity]; - [sharedInstance closeBackgroundTask]; + [[TSSocketManager sharedManager] closeBackgroundTask]; }]; [self becomeActive]; @@ -278,21 +299,25 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; } } +- (void)backgroundConnectTimerExpired { + [self backgroundTimeExpired]; +} + - (void)backgroundTimeExpired { [[self class] resignActivity]; [self closeBackgroundTask]; } - (void)closeBackgroundTask { - UIBackgroundTaskIdentifier identifier = self.fetchingTaskIdentifier; - self.fetchingTaskIdentifier = UIBackgroundTaskInvalid; [self.backgroundKeepAliveTimer invalidate]; + [self.backgroundConnectTimer invalidate]; if (!self.didFetchInBackground) { [self backgroundConnectTimedOut]; } - [[UIApplication sharedApplication] endBackgroundTask:identifier]; + [[UIApplication sharedApplication] endBackgroundTask:self.fetchingTaskIdentifier]; + self.fetchingTaskIdentifier = UIBackgroundTaskInvalid; } - (void)backgroundConnectTimedOut {