From b0343ee1d1c7fa3a74bd9c9241884ec0bb371ffb Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 10 Nov 2016 09:59:07 -0500 Subject: [PATCH] Only fetch PreKey once. Previously we were retrying as if it might succeed, and running into rate-limit errors. Also, added a specific rate limit error message. // FREEBIE --- SignalServiceKit.podspec | 2 +- .../TSInvalidIdentityKeySendingErrorMessage.h | 3 +- .../TSInvalidIdentityKeySendingErrorMessage.m | 7 ++- src/Messages/OWSMessageSender.m | 49 +++++++++++-------- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/SignalServiceKit.podspec b/SignalServiceKit.podspec index 7c40071e2..9bb34d4d8 100644 --- a/SignalServiceKit.podspec +++ b/SignalServiceKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = "SignalServiceKit" - s.version = "0.5.1" + s.version = "0.5.2" s.summary = "An Objective-C library for communicating with the Signal messaging service." s.description = <<-DESC diff --git a/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h b/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h index 76fed64d0..d22a9c017 100644 --- a/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h +++ b/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h @@ -22,8 +22,7 @@ extern NSString *TSInvalidRecipientKey; + (instancetype)untrustedKeyWithOutgoingMessage:(TSOutgoingMessage *)outgoingMessage inThread:(TSThread *)thread forRecipient:(NSString *)recipientId - preKeyBundle:(PreKeyBundle *)preKeyBundle - withTransaction:(YapDatabaseReadWriteTransaction *)transaction; + preKeyBundle:(PreKeyBundle *)preKeyBundle; @property (nonatomic, readonly) NSString *recipientId; @property (nonatomic, readonly) NSString *messageId; diff --git a/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m b/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m index c896626b2..26629baba 100644 --- a/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m +++ b/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m @@ -28,7 +28,7 @@ NSString *TSInvalidRecipientKey = @"TSInvalidRecipientKey"; inThread:(TSThread *)thread forRecipient:(NSString *)recipientId preKeyBundle:(PreKeyBundle *)preKeyBundle - transaction:(YapDatabaseReadWriteTransaction *)transaction { +{ self = [super initWithTimestamp:message.timestamp inThread:thread failedMessageType:TSErrorMessageWrongTrustedIdentityKey]; @@ -46,12 +46,11 @@ NSString *TSInvalidRecipientKey = @"TSInvalidRecipientKey"; inThread:(TSThread *)thread forRecipient:(NSString *)recipientId preKeyBundle:(PreKeyBundle *)preKeyBundle - withTransaction:(YapDatabaseReadWriteTransaction *)transaction { +{ TSInvalidIdentityKeySendingErrorMessage *message = [[self alloc] initWithOutgoingMessage:outgoingMessage inThread:thread forRecipient:recipientId - preKeyBundle:preKeyBundle - transaction:transaction]; + preKeyBundle:preKeyBundle]; return message; } diff --git a/src/Messages/OWSMessageSender.m b/src/Messages/OWSMessageSender.m index 4d1af25b4..ac1f25f3d 100644 --- a/src/Messages/OWSMessageSender.m +++ b/src/Messages/OWSMessageSender.m @@ -41,6 +41,7 @@ NS_ASSUME_NONNULL_BEGIN int const OWSMessageSenderRetryAttempts = 3; NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceException"; +NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; @interface OWSMessageSender () @@ -420,12 +421,31 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio deviceMessages = [self deviceMessages:message forRecipient:recipient inThread:thread]; } @catch (NSException *exception) { deviceMessages = @[]; + if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { + [[TSInvalidIdentityKeySendingErrorMessage + untrustedKeyWithOutgoingMessage:message + inThread:thread + forRecipient:exception.userInfo[TSInvalidRecipientKey] + preKeyBundle:exception.userInfo[TSInvalidPreKeyBundleKey]] save]; + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeUntrustedIdentityKey, + NSLocalizedString(@"FAILED_SENDING_BECAUSE_UNTRUSTED_IDENTITY_KEY", + @"action sheet header when re-sending message which failed because of untrusted identity keys")); + return failureHandler(error); + } + + if ([exception.name isEqualToString:OWSMessageSenderRateLimitedException]) { + NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeUntrustedIdentityKey, + NSLocalizedString(@"FAILED_SENDING_BECAUSE_RATE_LIMIT", + @"action sheet header when re-sending message which failed because of too many attempts")); + return failureHandler(error); + } + 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]; NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError(); - failureHandler(error); + return failureHandler(error); } } @@ -449,15 +469,7 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio void (^retrySend)() = ^void() { if (remainingAttempts <= 0) { - NSError *presentedError = error; - if (statuscode == 409) { - presentedError = OWSErrorWithCodeDescription(OWSErrorCodeUntrustedIdentityKey, - NSLocalizedString(@"FAILED_SENDING_BECAUSE_UNTRUSTED_IDENTITY_KEY", - @"action sheet header when re-sending message which failed because of untrusted " - @"identity keys")); - } - - return failureHandler(presentedError); + return failureHandler(error); } dispatch_async([OWSDispatch sendingQueue], ^{ @@ -659,6 +671,11 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio exception = [NSException exceptionWithName:OWSMessageSenderInvalidDeviceException reason:@"Device not registered" userInfo:nil]; + } else if (response.statusCode == 413) { + // Can't throw exception from within callback as it's probabably a different thread. + exception = [NSException exceptionWithName:OWSMessageSenderRateLimitedException + reason:@"Too many prekey requests" + userInfo:nil]; } dispatch_semaphore_signal(sema); }]; @@ -803,17 +820,7 @@ NSString *const OWSMessageSenderInvalidDeviceException = @"InvalidDeviceExceptio [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) { + 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