Respond to CR.

pull/1/head
Matthew Chen 7 years ago
parent ace07ac62a
commit cc91cb3dbf

@ -223,7 +223,7 @@ NS_ASSUME_NONNULL_BEGIN
[OWSPrimaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
for (PhoneNumber *number in self.parsedPhoneNumbers) {
if ([SignalRecipient isRegisteredSignalAccount:number.toE164 transaction:transaction]) {
if ([SignalRecipient isRegisteredRecipient:number.toE164 transaction:transaction]) {
[identifiers addObject:number.toE164];
}
}

@ -165,10 +165,10 @@ NS_ASSUME_NONNULL_BEGIN
for (NSString *recipientId in recipientIdsToLookup) {
if ([registeredRecipientIds containsObject:recipientId]) {
SignalRecipient *recipient =
[SignalRecipient markAccountAsRegistered:recipientId transaction:transaction];
[SignalRecipient markRecipientAsRegisteredAndGet:recipientId transaction:transaction];
[recipients addObject:recipient];
} else {
[SignalRecipient markAccountAsNotRegistered:recipientId transaction:transaction];
[SignalRecipient removeUnregisteredRecipient:recipientId transaction:transaction];
}
}
}];

@ -36,13 +36,14 @@ NS_ASSUME_NONNULL_BEGIN
- (NSComparisonResult)compare:(SignalRecipient *)other;
+ (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction;
+ (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (void)markAccountAsRegistered:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (void)markAccountAsNotRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (BOOL)isRegisteredRecipient:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction;
+ (SignalRecipient *)markRecipientAsRegisteredAndGet:(NSString *)recipientId
transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (void)markRecipientAsRegistered:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (void)removeUnregisteredRecipient:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction;
@end

@ -146,7 +146,14 @@ NS_ASSUME_NONNULL_BEGIN
[self addDevices:devices];
SignalRecipient *latest = [SignalRecipient markAccountAsRegistered:self.recipientId transaction:transaction];
SignalRecipient *latest =
[SignalRecipient markRecipientAsRegisteredAndGet:self.recipientId transaction:transaction];
if ([devices isSubsetOfSet:latest.devices.set]) {
return;
}
DDLogDebug(@"%@ adding devices: %@, to recipient: %@", self.logTag, devices, latest.recipientId);
[latest addDevices:devices];
[latest saveWithTransaction_internal:transaction];
}
@ -158,7 +165,14 @@ NS_ASSUME_NONNULL_BEGIN
[self removeDevices:devices];
SignalRecipient *latest = [SignalRecipient markAccountAsRegistered:self.recipientId transaction:transaction];
SignalRecipient *latest =
[SignalRecipient markRecipientAsRegisteredAndGet:self.recipientId transaction:transaction];
if (![devices isSubsetOfSet:latest.devices.set]) {
return;
}
DDLogDebug(@"%@ removing devices: %@, from recipient: %@", self.logTag, devices, latest.recipientId);
[latest removeDevices:devices];
[latest saveWithTransaction_internal:transaction];
}
@ -187,13 +201,14 @@ NS_ASSUME_NONNULL_BEGIN
DDLogVerbose(@"%@ saved signal recipient: %@", self.logTag, self.recipientId);
}
+ (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction
+ (BOOL)isRegisteredRecipient:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction
{
SignalRecipient *_Nullable instance = [self recipientForRecipientId:recipientId transaction:transaction];
return instance != nil;
}
+ (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction
+ (SignalRecipient *)markRecipientAsRegisteredAndGet:(NSString *)recipientId
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
OWSAssert(recipientId.length > 0);
@ -209,14 +224,14 @@ NS_ASSUME_NONNULL_BEGIN
return instance;
}
+ (void)markAccountAsRegistered:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction
+ (void)markRecipientAsRegistered:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
OWSAssert(recipientId.length > 0);
SignalRecipient *recipient = [self markAccountAsRegistered:recipientId transaction:transaction];
SignalRecipient *recipient = [self markRecipientAsRegisteredAndGet:recipientId transaction:transaction];
if (![recipient.devices containsObject:@(deviceId)]) {
DDLogDebug(@"%@ in %s adding device %u to existing recipient.",
self.logTag,
@ -228,7 +243,7 @@ NS_ASSUME_NONNULL_BEGIN
}
}
+ (void)markAccountAsNotRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction
+ (void)removeUnregisteredRecipient:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
OWSAssert(recipientId.length > 0);
@ -237,6 +252,7 @@ NS_ASSUME_NONNULL_BEGIN
if (!instance) {
return;
}
DDLogDebug(@"%@ removing recipient: %@", self.logTag, recipientId);
[instance removeWithTransaction:transaction];
}

@ -110,9 +110,9 @@ NS_ASSUME_NONNULL_BEGIN
DecryptSuccessBlock successBlock
= ^(NSData *_Nullable plaintextData, YapDatabaseReadWriteTransaction *transaction) {
[SignalRecipient markAccountAsRegistered:envelope.source
deviceId:envelope.sourceDevice
transaction:transaction];
[SignalRecipient markRecipientAsRegistered:envelope.source
deviceId:envelope.sourceDevice
transaction:transaction];
successBlockParameter(plaintextData, transaction);
};

@ -452,7 +452,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSAssert(message);
NSMutableArray<SignalRecipient *> *recipients = [NSMutableArray new];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
for (NSString *recipientId in recipientIds) {
SignalRecipient *recipient =
[SignalRecipient getOrBuildUnsavedRecipientForRecipientId:recipientId transaction:transaction];
@ -705,21 +705,24 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
message:(TSOutgoingMessage *)message
thread:(TSThread *)thread
{
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (thread.isGroupThread) {
// Mark as "skipped" group members who no longer have signal accounts.
[message updateWithSkippedRecipient:recipient.recipientId transaction:transaction];
}
if (![SignalRecipient isRegisteredSignalAccount:recipient.recipientId transaction:transaction]) {
if (![SignalRecipient isRegisteredRecipient:recipient.recipientId transaction:transaction]) {
return;
}
[SignalRecipient markAccountAsNotRegistered:recipient.recipientId
transaction:transaction];
[SignalRecipient removeUnregisteredRecipient:recipient.recipientId transaction:transaction];
[[TSInfoMessage userNotRegisteredMessageInThread:thread recipientId:recipient.recipientId]
saveWithTransaction:transaction];
// TODO: Should we deleteAllSessionsForContact here?
// If so, we'll need to avoid doing a prekey fetch every
// time we try to send a message to an unregistered user.
}];
}
@ -731,6 +734,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
success:(void (^)(void))successHandler
failure:(RetryableFailureHandler)failureHandler
{
OWSAssert(message);
OWSAssert(recipient);
OWSAssert(thread || [message isKindOfClass:[OWSOutgoingSyncMessage class]]);
DDLogInfo(@"%@ attempting to send message: %@, timestamp: %llu, recipient: %@",
@ -773,7 +778,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
NSArray<NSDictionary *> *deviceMessages;
@try {
deviceMessages = [self deviceMessages:message forRecipient:recipient];
deviceMessages = [self deviceMessages:message recipient:recipient];
} @catch (NSException *exception) {
deviceMessages = @[];
if ([exception.name isEqualToString:UntrustedIdentityKeyException]) {
@ -908,6 +913,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} else if (!mayHaveLinkedDevices && hasDeviceMessages) {
OWSFail(@"%@ sync message has device messages for unknown secondary devices.", self.logTag);
}
} else {
OWSAssert(deviceMessages.count > 0);
}
if (deviceMessages.count == 0) {
@ -1016,7 +1023,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// If we've just delivered a message to a user, we know they
// have a valid Signal account.
[SignalRecipient markAccountAsRegistered:recipient.recipientId transaction:transaction];
[SignalRecipient markRecipientAsRegisteredAndGet:recipient.recipientId transaction:transaction];
}];
[self handleMessageSentLocally:message];
@ -1066,6 +1073,25 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
});
};
void (^handle404)(void) = ^{
DDLogWarn(@"%@ Unregistered recipient: %@", self.logTag, recipient.uniqueId);
OWSAssert(thread);
dispatch_async([OWSDispatch sendingQueue], ^{
[self unregisteredRecipient:recipient message:message thread:thread];
NSError *error = OWSErrorMakeNoSuchSignalRecipientError();
// No need to retry if the recipient is not registered.
[error setIsRetryable:NO];
// If one member of a group deletes their account,
// the group should ignore errors when trying to send
// messages to this ex-member.
[error setShouldBeIgnoredForGroups:YES];
failureHandler(error);
});
};
switch (statusCode) {
case 401: {
DDLogWarn(@"%@ Unable to send due to invalid credentials. Did the user's client get de-authed by "
@ -1079,23 +1105,15 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return failureHandler(error);
}
case 404: {
DDLogWarn(@"%@ Unregistered recipient: %@", self.logTag, recipient.uniqueId);
OWSAssert(thread);
[self unregisteredRecipient:recipient message:message thread:thread];
NSError *error = OWSErrorMakeNoSuchSignalRecipientError();
// No need to retry if the recipient is not registered.
[error setIsRetryable:NO];
// If one member of a group deletes their account,
// the group should ignore errors when trying to send
// messages to this ex-member.
[error setShouldBeIgnoredForGroups:YES];
return failureHandler(error);
handle404();
return;
}
case 409: {
// Mismatched devices
DDLogWarn(@"%@ Mismatched devices for recipient: %@", self.logTag, recipient.uniqueId);
DDLogWarn(@"%@ Mismatched devices for recipient: %@ (%zd)",
self.logTag,
recipient.uniqueId,
deviceMessages.count);
NSError *_Nullable error = nil;
NSDictionary *_Nullable responseJson = nil;
@ -1108,6 +1126,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return failureHandler(error);
}
NSNumber *_Nullable errorCode = responseJson[@"code"];
if ([@(404) isEqual:errorCode]) {
// Some 404s are returned as 409.
handle404();
return;
}
[self handleMismatchedDevicesWithResponseJson:responseJson recipient:recipient completion:retrySend];
break;
}
@ -1225,8 +1250,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}];
}
- (NSArray<NSDictionary *> *)deviceMessages:(TSOutgoingMessage *)message
forRecipient:(SignalRecipient *)recipient
- (NSArray<NSDictionary *> *)deviceMessages:(TSOutgoingMessage *)message recipient:(SignalRecipient *)recipient
{
OWSAssert(message);
OWSAssert(recipient);
@ -1247,7 +1271,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@try {
messageDict = [self encryptedMessageWithPlaintext:plainText
toRecipient:recipient.uniqueId
recipient:recipient
deviceId:deviceNumber
keyingStorage:self.primaryStorage
isSilent:message.isSilent
@ -1284,18 +1308,21 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
}
- (NSDictionary *)encryptedMessageWithPlaintext:(NSData *)plainText
toRecipient:(NSString *)identifier
recipient:(SignalRecipient *)recipient
deviceId:(NSNumber *)deviceNumber
keyingStorage:(OWSPrimaryStorage *)storage
isSilent:(BOOL)isSilent
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(plainText);
OWSAssert(identifier.length > 0);
OWSAssert(recipient);
OWSAssert(deviceNumber);
OWSAssert(storage);
OWSAssert(transaction);
NSString *identifier = recipient.recipientId;
OWSAssert(identifier.length > 0);
if (![storage containsSession:identifier deviceId:[deviceNumber intValue] protocolContext:transaction]) {
__block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block PreKeyBundle *_Nullable bundle;
@ -1319,6 +1346,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
DDLogError(@"Server replied to PreKeyBundle request with error: %@", error);
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
if (response.statusCode == 404) {
[recipient removeDevicesFromRegisteredRecipient:[NSSet setWithObject:deviceNumber]
transaction:transaction];
// Can't throw exception from within callback as it's probabably a different thread.
exception = [NSException exceptionWithName:OWSMessageSenderInvalidDeviceException
reason:@"Device not registered"

Loading…
Cancel
Save