From a0df56a68e5db7729a209b069bcdfd56e6d7e92a Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 19 Sep 2016 21:57:20 -0400 Subject: [PATCH] Fix multiple keychange errors (#29) * Don't attempt to send a message unless we've successfully built a deveice-messages * Only process message exception when we're done with retries. // FREEBIE --- src/Contacts/TSThread.m | 13 ++++++ src/Messages/Interactions/TSMessage.m | 2 +- src/Messages/TSMessagesManager+sendMessages.m | 46 +++++++++++++++++-- src/Messages/TSMessagesManager.m | 38 +++++++-------- 4 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/Contacts/TSThread.m b/src/Contacts/TSThread.m index 573ada0bd..80f90a37a 100644 --- a/src/Contacts/TSThread.m +++ b/src/Contacts/TSThread.m @@ -131,6 +131,19 @@ NS_ASSUME_NONNULL_BEGIN }]; } +/** + * Useful for tests and debugging. In production use an enumeration method. + */ +- (NSArray *)allInteractions +{ + NSMutableArray *interactions = [NSMutableArray new]; + [self enumerateInteractionsUsingBlock:^(TSInteraction *_Nonnull interaction) { + [interactions addObject:interaction]; + }]; + + return [interactions copy]; +} + - (NSArray *)receivedMessagesForInvalidKey:(NSData *)key { NSMutableArray *errorMessages = [NSMutableArray new]; diff --git a/src/Messages/Interactions/TSMessage.m b/src/Messages/Interactions/TSMessage.m index ee3c7098b..7e9fa3990 100644 --- a/src/Messages/Interactions/TSMessage.m +++ b/src/Messages/Interactions/TSMessage.m @@ -103,7 +103,7 @@ static const NSUInteger OWSMessageSchemaVersion = 2; NSString *attachmentId = self.attachmentIds[0]; return [NSString stringWithFormat:@"Media Message with attachmentId:%@", attachmentId]; } else { - return [NSString stringWithFormat:@"Message with body:%@", self.body]; + return [NSString stringWithFormat:@"%@ with body:%@", [self class], self.body]; } } diff --git a/src/Messages/TSMessagesManager+sendMessages.m b/src/Messages/TSMessagesManager+sendMessages.m index 2a6691f08..467fe8ce0 100644 --- a/src/Messages/TSMessagesManager+sendMessages.m +++ b/src/Messages/TSMessagesManager+sendMessages.m @@ -247,7 +247,33 @@ dispatch_queue_t sendingQueue() { if (remainingAttempts > 0) { remainingAttempts -= 1; - NSArray *deviceMessages = [self deviceMessages:message forRecipient:recipient inThread:thread]; + NSArray *deviceMessages; + @try { + deviceMessages = [self deviceMessages:message forRecipient:recipient inThread:thread]; + } @catch (NSException *exception) { + deviceMessages = @[]; + if (remainingAttempts == 0) { + DDLogWarn(@"%@ Terminal failure to build any device messages. Giving up with exception:%@", + self.tag, + exception); + [self processException:exception outgoingMessage:message inThread:thread]; + return; + } + } + + if (deviceMessages.count == 0) { + DDLogWarn(@"%@ Failed to build any device messages. Not sending.", self.tag); + // Retrying incase we fixed our stale devices last time 'round. + dispatch_async(sendingQueue(), ^{ + [self sendMessage:message + toRecipient:recipient + inThread:thread + withAttemps:remainingAttempts + success:successBlock + failure:failureBlock]; + }); + return; + } TSSubmitMessageRequest *request = [[TSSubmitMessageRequest alloc] initWithRecipient:recipient.uniqueId messages:deviceMessages @@ -275,14 +301,14 @@ dispatch_queue_t sendingQueue() { } case 409: { // Mismatched devices - DDLogWarn(@"Mismatch Devices."); + DDLogWarn(@"%@ Mismatch Devices.", self.tag); NSError *e; NSDictionary *serializedResponse = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&e]; if (e) { - DDLogError(@"Failed to serialize response of mismatched devices: %@", e.description); + DDLogError(@"%@ Failed to serialize response of mismatched devices: %@", self.tag, e); } else { [self handleMismatchedDevices:serializedResponse recipient:recipient]; } @@ -412,8 +438,7 @@ dispatch_queue_t sendingQueue() { if ([exception.name isEqualToString:InvalidDeviceException]) { [recipient removeDevices:[NSSet setWithObject:deviceNumber]]; } else { - DDLogWarn(@"Failed building message for device: %@ withe error %@", deviceNumber, exception); - [self processException:exception outgoingMessage:message inThread:thread]; + @throw exception; } } } @@ -566,4 +591,15 @@ dispatch_queue_t sendingQueue() { } }); } + ++ (NSString *)tag +{ + return [NSString stringWithFormat:@"[%@]", self.class]; +} + +- (NSString *)tag +{ + return self.class.tag; +} + @end diff --git a/src/Messages/TSMessagesManager.m b/src/Messages/TSMessagesManager.m index 6d5e86510..161be85b4 100644 --- a/src/Messages/TSMessagesManager.m +++ b/src/Messages/TSMessagesManager.m @@ -478,26 +478,26 @@ DDLogWarn(@"Got exception: %@", exception.description); [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSErrorMessage *errorMessage; - - if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { - errorMessage = [TSInvalidIdentityKeySendingErrorMessage - untrustedKeyWithOutgoingMessage:message - inThread:thread - forRecipient:exception.userInfo[TSInvalidRecipientKey] - preKeyBundle:exception.userInfo[TSInvalidPreKeyBundleKey] - withTransaction:transaction]; - message.messageState = TSOutgoingMessageStateUnsent; - [message saveWithTransaction:transaction]; - } else if (message.groupMetaMessage == TSGroupMessageNone) { - // Only update this with exception if it is not a group message as group - // messages may except for one group - // send but not another and the UI doesn't know how to handle that - [message setMessageState:TSOutgoingMessageStateUnsent]; - [message saveWithTransaction:transaction]; - } + TSErrorMessage *errorMessage; + + if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { + errorMessage = [TSInvalidIdentityKeySendingErrorMessage + untrustedKeyWithOutgoingMessage:message + inThread:thread + forRecipient:exception.userInfo[TSInvalidRecipientKey] + preKeyBundle:exception.userInfo[TSInvalidPreKeyBundleKey] + withTransaction:transaction]; + message.messageState = TSOutgoingMessageStateUnsent; + [message saveWithTransaction:transaction]; + } else if (message.groupMetaMessage == TSGroupMessageNone) { + // Only update this with exception if it is not a group message as group + // messages may except for one group + // send but not another and the UI doesn't know how to handle that + [message setMessageState:TSOutgoingMessageStateUnsent]; + [message saveWithTransaction:transaction]; + } - [errorMessage saveWithTransaction:transaction]; + [errorMessage saveWithTransaction:transaction]; }]; }