diff --git a/Signal/src/Jobs/MessageFetcherJob.swift b/Signal/src/Jobs/MessageFetcherJob.swift index 52ae389d3..37c68eba0 100644 --- a/Signal/src/Jobs/MessageFetcherJob.swift +++ b/Signal/src/Jobs/MessageFetcherJob.swift @@ -127,10 +127,6 @@ public class MessageFetcherJob: NSObject { } builder.setType(type) - if let relay = messageDict["relay"] as? String { - builder.setRelay(relay) - } - guard let timestamp = messageDict["timestamp"] as? UInt64 else { Logger.error("\(self.logTag) message body didn't have timestamp") return nil diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 8a1f71ab0..c3e8f4eda 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -74,7 +74,6 @@ #import #import #import -#import #import #import #import diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m b/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m index a77549a58..21344687a 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIContacts.m @@ -5,6 +5,7 @@ #import "DebugUIContacts.h" #import "OWSTableViewController.h" #import "Signal-Swift.h" +#import "SignalApp.h" #import NS_ASSUME_NONNULL_BEGIN @@ -50,6 +51,18 @@ NS_ASSUME_NONNULL_BEGIN actionBlock:^{ [DebugUIContacts clearSignalAccountCache]; }], + [OWSTableItem itemWithTitle:@"Clear SignalRecipient Cache" + actionBlock:^{ + [DebugUIContacts clearSignalRecipientCache]; + }], + [OWSTableItem itemWithTitle:@"New Unregistered Contact Thread" + actionBlock:^{ + [DebugUIContacts createUnregisteredContactThread]; + }], + [OWSTableItem itemWithTitle:@"New Unregistered Group Thread" + actionBlock:^{ + [DebugUIContacts createUnregisteredGroupThread]; + }], ]]; } @@ -1290,6 +1303,12 @@ NS_ASSUME_NONNULL_BEGIN [SignalAccount removeAllObjectsInCollection]; } ++ (void)clearSignalRecipientCache +{ + DDLogWarn(@"%@ Deleting all signal recipients.", self.logTag); + [SignalRecipient removeAllObjectsInCollection]; +} + + (void)deleteAllContacts { [self deleteContactsWithFilter:^(CNContact *contact) { @@ -1304,6 +1323,41 @@ NS_ASSUME_NONNULL_BEGIN }]; } ++ (NSString *)unregisteredRecipientId +{ + // We ensure that the phone number is invalid by appending too many digits. + NSMutableString *recipientId = [@"+1" mutableCopy]; + for (int i = 0; i < 11; i++) { + [recipientId appendFormat:@"%d", (int)(arc4random() % 10)]; + } + return [recipientId copy]; +} + ++ (void)createUnregisteredContactThread +{ + NSString *recipientId = [self unregisteredRecipientId]; + TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId]; + [SignalApp.sharedApp presentConversationForThread:thread]; +} + ++ (void)createUnregisteredGroupThread +{ + NSString *unregisteredRecipientId = [self unregisteredRecipientId]; + NSString *validRecipientId = @"+19174054216"; + + NSString *groupName = @"Partially invalid group"; + NSMutableArray *recipientIds = [@[ + unregisteredRecipientId, + validRecipientId, + [TSAccountManager localNumber], + ] mutableCopy]; + NSData *groupId = [SecurityUtils generateRandomBytes:16]; + TSGroupModel *model = + [[TSGroupModel alloc] initWithTitle:groupName memberIds:recipientIds image:nil groupId:groupId]; + TSGroupThread *thread = [TSGroupThread getOrCreateThreadWithGroupModel:model]; + [SignalApp.sharedApp presentConversationForThread:thread]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m index 9a1ded442..2241d9d2d 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m @@ -3729,7 +3729,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac digest:nil byteCount:filesize contentType:@"audio/mp3" - relay:@"" sourceFilename:@"test.mp3" attachmentType:TSAttachmentTypeDefault]; pointer.state = TSAttachmentPointerStateFailed; @@ -4596,7 +4595,6 @@ typedef OWSContact * (^OWSContactBlock)(YapDatabaseReadWriteTransaction *transac digest:nil byteCount:filesize contentType:fakeAssetLoader.mimeType - relay:@"" sourceFilename:fakeAssetLoader.filename attachmentType:TSAttachmentTypeDefault]; attachmentPointer.state = TSAttachmentPointerStateFailed; diff --git a/SignalMessaging/environment/Release.m b/SignalMessaging/environment/Release.m index 210408b6b..0824d0428 100644 --- a/SignalMessaging/environment/Release.m +++ b/SignalMessaging/environment/Release.m @@ -24,8 +24,7 @@ ContactsUpdater *contactsUpdater = [ContactsUpdater sharedUpdater]; OWSMessageSender *messageSender = [[OWSMessageSender alloc] initWithNetworkManager:networkManager primaryStorage:primaryStorage - contactsManager:contactsManager - contactsUpdater:contactsUpdater]; + contactsManager:contactsManager]; instance = [[Environment alloc] initWithContactsManager:contactsManager contactsUpdater:contactsUpdater diff --git a/SignalServiceKit/src/Contacts/Contact.m b/SignalServiceKit/src/Contacts/Contact.m index c088eda73..8bc4004bf 100644 --- a/SignalServiceKit/src/Contacts/Contact.m +++ b/SignalServiceKit/src/Contacts/Contact.m @@ -208,8 +208,8 @@ NS_ASSUME_NONNULL_BEGIN __block NSMutableArray *result = [NSMutableArray array]; for (PhoneNumber *number in [self.parsedPhoneNumbers sortedArrayUsingSelector:@selector(compare:)]) { - SignalRecipient *signalRecipient = - [SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]; + SignalRecipient *_Nullable signalRecipient = + [SignalRecipient registeredRecipientForRecipientId:number.toE164 transaction:transaction]; if (signalRecipient) { [result addObject:signalRecipient]; } @@ -223,7 +223,7 @@ NS_ASSUME_NONNULL_BEGIN [OWSPrimaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { for (PhoneNumber *number in self.parsedPhoneNumbers) { - if ([SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]) { + if ([SignalRecipient isRegisteredRecipient:number.toE164 transaction:transaction]) { [identifiers addObject:number.toE164]; } } diff --git a/SignalServiceKit/src/Contacts/ContactsUpdater.h b/SignalServiceKit/src/Contacts/ContactsUpdater.h index 8ede7a494..a686db178 100644 --- a/SignalServiceKit/src/Contacts/ContactsUpdater.h +++ b/SignalServiceKit/src/Contacts/ContactsUpdater.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "SignalRecipient.h" @@ -12,8 +12,6 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedUpdater; -- (nullable SignalRecipient *)synchronousLookup:(NSString *)identifier error:(NSError **)error; - // This asynchronously tries to verify whether or not a contact id // corresponds to a service account. // diff --git a/SignalServiceKit/src/Contacts/ContactsUpdater.m b/SignalServiceKit/src/Contacts/ContactsUpdater.m index 8d972f7c0..cdd883651 100644 --- a/SignalServiceKit/src/Contacts/ContactsUpdater.m +++ b/SignalServiceKit/src/Contacts/ContactsUpdater.m @@ -38,53 +38,27 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (nullable SignalRecipient *)synchronousLookup:(NSString *)identifier error:(NSError **)error -{ - OWSAssert(error); - - DDLogInfo(@"%@ %s %@", self.logTag, __PRETTY_FUNCTION__, identifier); - - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - __block SignalRecipient *recipient; - - // Assigning to a pointer parameter within the block is not preventing the referenced error from being dealloc - // Instead, we avoid ambiguity in ownership by assigning to a local __block variable ensuring the error will be - // retained until our error parameter can take ownership. - __block NSError *retainedError; - [self lookupIdentifier:identifier - success:^(SignalRecipient *fetchedRecipient) { - recipient = fetchedRecipient; - dispatch_semaphore_signal(sema); - } - failure:^(NSError *lookupError) { - DDLogError( - @"%@ Could not find recipient for recipientId: %@, error: %@.", self.logTag, identifier, lookupError); - - retainedError = lookupError; - dispatch_semaphore_signal(sema); - }]; - - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - *error = retainedError; - return recipient; -} - -- (void)lookupIdentifier:(NSString *)identifier +- (void)lookupIdentifier:(NSString *)recipientId success:(void (^)(SignalRecipient *recipient))success failure:(void (^)(NSError *error))failure { + OWSAssert(recipientId.length > 0); + // This should never happen according to nullability annotations... but IIRC it does. =/ - if (!identifier) { + if (!recipientId) { OWSFail(@"%@ Cannot lookup nil identifier", self.logTag); failure(OWSErrorWithCodeDescription(OWSErrorCodeInvalidMethodParameters, @"Cannot lookup nil identifier")); return; } - [self contactIntersectionWithSet:[NSSet setWithObject:identifier] - success:^(NSSet *_Nonnull matchedIds) { - if (matchedIds.count == 1) { - success([SignalRecipient recipientWithTextSecureIdentifier:identifier]); + NSSet *recipiendIds = [NSSet setWithObject:recipientId]; + [self contactIntersectionWithSet:recipiendIds + success:^(NSSet *recipients) { + if (recipients.count > 0) { + OWSAssert(recipients.count == 1); + + SignalRecipient *recipient = recipients.allObjects.firstObject; + success(recipient); } else { failure(OWSErrorMakeNoSuchSignalRecipientError()); } @@ -103,12 +77,8 @@ NS_ASSUME_NONNULL_BEGIN } [self contactIntersectionWithSet:[NSSet setWithArray:identifiers] - success:^(NSSet *_Nonnull matchedIds) { - if (matchedIds.count > 0) { - NSMutableArray *recipients = [NSMutableArray new]; - for (NSString *identifier in matchedIds) { - [recipients addObject:[SignalRecipient recipientWithTextSecureIdentifier:identifier]]; - } + success:^(NSSet *recipients) { + if (recipients.count > 0) { success([recipients copy]); } else { failure(OWSErrorMakeNoSuchSignalRecipientError()); @@ -117,6 +87,7 @@ NS_ASSUME_NONNULL_BEGIN failure:failure]; } +// TODO: Modify this to support delta lookups. - (void)updateSignalContactIntersectionWithABContacts:(NSArray *)abContacts success:(void (^)(void))success failure:(void (^)(NSError *error))failure @@ -130,7 +101,8 @@ NS_ASSUME_NONNULL_BEGIN } NSMutableSet *recipientIds = [NSMutableSet set]; - [OWSPrimaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { + [OWSPrimaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction * transaction) { + // TODO: Don't do this. NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]]; [recipientIds addObjectsFromArray:allRecipientKeys]; }]; @@ -138,78 +110,70 @@ NS_ASSUME_NONNULL_BEGIN NSMutableSet *allContacts = [[abPhoneNumbers setByAddingObjectsFromSet:recipientIds] mutableCopy]; [self contactIntersectionWithSet:allContacts - success:^(NSSet *matchedIds) { - [recipientIds minusSet:matchedIds]; - - // Cleaning up unregistered identifiers - [OWSPrimaryStorage.dbReadWriteConnection - readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (NSString *identifier in recipientIds) { - SignalRecipient *recipient = - [SignalRecipient fetchObjectWithUniqueID:identifier - transaction:transaction]; - - [recipient removeWithTransaction:transaction]; - } - }]; - + success:^(NSSet *recipients) { DDLogInfo(@"%@ successfully intersected contacts.", self.logTag); success(); } failure:failure]; } -- (void)contactIntersectionWithSet:(NSSet *)idSet - success:(void (^)(NSSet *matchedIds))success +- (void)contactIntersectionWithSet:(NSSet *)recipientIdsToLookup + success:(void (^)(NSSet *recipients))success failure:(void (^)(NSError *error))failure { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSMutableDictionary *phoneNumbersByHashes = [NSMutableDictionary dictionary]; - for (NSString *identifier in idSet) { - [phoneNumbersByHashes setObject:identifier - forKey:[Cryptography truncatedSHA1Base64EncodedWithoutPadding:identifier]]; + NSMutableDictionary *phoneNumbersByHashes = [NSMutableDictionary new]; + for (NSString *recipientId in recipientIdsToLookup) { + NSString *hash = [Cryptography truncatedSHA1Base64EncodedWithoutPadding:recipientId]; + phoneNumbersByHashes[hash] = recipientId; } - NSArray *hashes = [phoneNumbersByHashes allKeys]; - + NSArray *hashes = [phoneNumbersByHashes allKeys]; + TSRequest *request = [OWSRequestFactory contactsIntersectionRequestWithHashesArray:hashes]; [[TSNetworkManager sharedManager] makeRequest:request - success:^(NSURLSessionDataTask *tsTask, id responseDict) { - NSMutableDictionary *attributesForIdentifier = [NSMutableDictionary dictionary]; - NSArray *contactsArray = [(NSDictionary *)responseDict objectForKey:@"contacts"]; - - // Map attributes to phone numbers - if (contactsArray) { - for (NSDictionary *dict in contactsArray) { - NSString *hash = [dict objectForKey:@"token"]; - NSString *identifier = [phoneNumbersByHashes objectForKey:hash]; - - if (!identifier) { - DDLogWarn(@"%@ An interesecting hash wasn't found in the mapping.", self.logTag); - break; + success:^(NSURLSessionDataTask *task, id responseDict) { + NSMutableSet *registeredRecipientIds = [NSMutableSet new]; + + if ([responseDict isKindOfClass:[NSDictionary class]]) { + NSArray *_Nullable contactsArray = responseDict[@"contacts"]; + if ([contactsArray isKindOfClass:[NSArray class]]) { + for (NSDictionary *contactDict in contactsArray) { + if (![contactDict isKindOfClass:[NSDictionary class]]) { + OWSProdLogAndFail(@"%@ invalid contact dictionary.", self.logTag); + continue; + } + NSString *_Nullable hash = contactDict[@"token"]; + if (hash.length < 1) { + OWSProdLogAndFail(@"%@ contact missing hash.", self.logTag); + continue; + } + NSString *_Nullable recipientId = phoneNumbersByHashes[hash]; + if (recipientId.length < 1) { + OWSProdLogAndFail(@"%@ An intersecting hash wasn't found in the mapping.", self.logTag); + continue; + } + if (![recipientIdsToLookup containsObject:recipientId]) { + OWSProdLogAndFail(@"%@ Intersection response included unexpected recipient.", self.logTag); + continue; + } + [registeredRecipientIds addObject:recipientId]; } - - [attributesForIdentifier setObject:dict forKey:identifier]; } } - - // Insert or update contact attributes - [OWSPrimaryStorage.dbReadWriteConnection - readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (NSString *identifier in attributesForIdentifier) { - SignalRecipient *recipient = [SignalRecipient recipientWithTextSecureIdentifier:identifier - withTransaction:transaction]; - if (!recipient) { - recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:identifier relay:nil]; - } - - NSDictionary *attributes = [attributesForIdentifier objectForKey:identifier]; - - recipient.relay = attributes[@"relay"]; - - [recipient saveWithTransaction:transaction]; + + NSMutableSet *recipients = [NSMutableSet new]; + [OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + for (NSString *recipientId in recipientIdsToLookup) { + if ([registeredRecipientIds containsObject:recipientId]) { + SignalRecipient *recipient = + [SignalRecipient markRecipientAsRegisteredAndGet:recipientId transaction:transaction]; + [recipients addObject:recipient]; + } else { + [SignalRecipient removeUnregisteredRecipient:recipientId transaction:transaction]; } - }]; + } + }]; - success([NSSet setWithArray:attributesForIdentifier.allKeys]); + success([recipients copy]); } failure:^(NSURLSessionDataTask *task, NSError *error) { if (!IsNSErrorNetworkFailure(error)) { diff --git a/SignalServiceKit/src/Contacts/SignalAccount.h b/SignalServiceKit/src/Contacts/SignalAccount.h index 7f61c7b30..5b416f9a4 100644 --- a/SignalServiceKit/src/Contacts/SignalAccount.h +++ b/SignalServiceKit/src/Contacts/SignalAccount.h @@ -15,7 +15,6 @@ NS_ASSUME_NONNULL_BEGIN // * Contacts with multiple signal accounts will correspond to // multiple instances of SignalAccount. // * For non-contacts, the contact property will be nil. -// @interface SignalAccount : TSYapDatabaseObject // An E164 value identifying the signal account. @@ -42,11 +41,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRecipientId:(NSString *)recipientId; -// In most cases this should be non-null. This should only -// be null in the case where the SignalRecipient was -// deleted before this property was accessed. -- (nullable SignalRecipient *)signalRecipientWithTransaction:(YapDatabaseReadTransaction *)transaction; - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/SignalAccount.m b/SignalServiceKit/src/Contacts/SignalAccount.m index 158992de1..523947479 100644 --- a/SignalServiceKit/src/Contacts/SignalAccount.m +++ b/SignalServiceKit/src/Contacts/SignalAccount.m @@ -36,15 +36,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (nullable SignalRecipient *)signalRecipientWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - OWSAssertIsOnMainThread(); - OWSAssert(transaction); - - OWSAssert(self.recipientId.length > 0); - return [SignalRecipient recipientWithTextSecureIdentifier:self.recipientId withTransaction:transaction]; -} - - (nullable NSString *)uniqueId { return _recipientId; diff --git a/SignalServiceKit/src/Contacts/SignalRecipient.h b/SignalServiceKit/src/Contacts/SignalRecipient.h index d9e6aa9a2..e1ef16f7b 100644 --- a/SignalServiceKit/src/Contacts/SignalRecipient.h +++ b/SignalServiceKit/src/Contacts/SignalRecipient.h @@ -6,36 +6,45 @@ NS_ASSUME_NONNULL_BEGIN +// SignalRecipient serves two purposes: +// +// a) It serves as a cache of "known" Signal accounts. When the service indicates +// that an account exists, we make sure that an instance of SignalRecipient exists +// for that recipient id (using mark as registered). +// When the service indicates that an account does not exist, we remove any +// SignalRecipient. +// b) We hang the "known device list" for known signal accounts on this entity. @interface SignalRecipient : TSYapDatabaseObject -- (instancetype)initWithTextSecureIdentifier:(NSString *)textSecureIdentifier - relay:(nullable NSString *)relay; - -+ (instancetype)selfRecipient; - -+ (void)ensureRecipientExistsWithRecipientId:(NSString *)recipientId - deviceId:(UInt32)deviceId - relay:(NSString *)relay - transaction:(YapDatabaseReadWriteTransaction *)transaction; +@property (nonatomic, readonly) NSOrderedSet *devices; -+ (nullable instancetype)recipientWithTextSecureIdentifier:(NSString *)textSecureIdentifier; -+ (nullable instancetype)recipientWithTextSecureIdentifier:(NSString *)textSecureIdentifier - withTransaction:(YapDatabaseReadTransaction *)transaction; +- (instancetype)init NS_UNAVAILABLE; -@property (readonly) NSOrderedSet *devices; -- (void)addDevices:(NSSet *)set; -- (void)removeDevices:(NSSet *)set; ++ (instancetype)selfRecipient; -@property (nonatomic, nullable) NSString *relay; ++ (nullable instancetype)registeredRecipientForRecipientId:(NSString *)recipientId + transaction:(YapDatabaseReadTransaction *)transaction; ++ (instancetype)getOrBuildUnsavedRecipientForRecipientId:(NSString *)recipientId + transaction:(YapDatabaseReadTransaction *)transaction; -- (BOOL)supportsVoice; -// This property indicates support for both WebRTC audio and video calls. -- (BOOL)supportsWebRTC; +- (void)addDevicesToRegisteredRecipient:(NSSet *)devices + transaction:(YapDatabaseReadWriteTransaction *)transaction; +- (void)removeDevicesFromRegisteredRecipient:(NSSet *)devices + transaction:(YapDatabaseReadWriteTransaction *)transaction; - (NSString *)recipientId; - (NSComparisonResult)compare:(SignalRecipient *)other; ++ (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 NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/SignalRecipient.m b/SignalServiceKit/src/Contacts/SignalRecipient.m index 55d8003f2..2790e59ab 100644 --- a/SignalServiceKit/src/Contacts/SignalRecipient.m +++ b/SignalServiceKit/src/Contacts/SignalRecipient.m @@ -3,7 +3,6 @@ // #import "SignalRecipient.h" -#import "OWSIdentityManager.h" #import "TSAccountManager.h" #import @@ -11,47 +10,28 @@ NS_ASSUME_NONNULL_BEGIN @interface SignalRecipient () -@property NSOrderedSet *devices; +@property (nonatomic) NSOrderedSet *devices; @end -@implementation SignalRecipient +#pragma mark - -+ (NSString *)collection { - return @"SignalRecipient"; -} +@implementation SignalRecipient -+ (void)ensureRecipientExistsWithRecipientId:(NSString *)recipientId - deviceId:(UInt32)deviceId - relay:(NSString *)relay - transaction:(YapDatabaseReadWriteTransaction *)transaction ++ (instancetype)getOrBuildUnsavedRecipientForRecipientId:(NSString *)recipientId + transaction:(YapDatabaseReadTransaction *)transaction { - SignalRecipient *_Nullable existingRecipient = - [self recipientWithTextSecureIdentifier:recipientId withTransaction:transaction]; - if (!existingRecipient) { - DDLogDebug( - @"%@ in %s creating recipient with deviceId: %u", self.logTag, __PRETTY_FUNCTION__, (unsigned int)deviceId); - - SignalRecipient *newRecipient = [[self alloc] initWithTextSecureIdentifier:recipientId relay:relay]; - [newRecipient addDevices:[NSSet setWithObject:@(deviceId)]]; - [newRecipient saveWithTransaction:transaction]; - - return; - } - - if (![existingRecipient.devices containsObject:@(deviceId)]) { - DDLogDebug(@"%@ in %s adding device %u to existing recipient.", - self.logTag, - __PRETTY_FUNCTION__, - (unsigned int)deviceId); - - [existingRecipient addDevices:[NSSet setWithObject:@(deviceId)]]; - [existingRecipient saveWithTransaction:transaction]; + OWSAssert(transaction); + OWSAssert(recipientId.length > 0); + + SignalRecipient *_Nullable recipient = [self registeredRecipientForRecipientId:recipientId transaction:transaction]; + if (!recipient) { + recipient = [[self alloc] initWithTextSecureIdentifier:recipientId]; } + return recipient; } - (instancetype)initWithTextSecureIdentifier:(NSString *)textSecureIdentifier - relay:(nullable NSString *)relay { self = [super initWithUniqueId:textSecureIdentifier]; if (!self) { @@ -75,8 +55,6 @@ NS_ASSUME_NONNULL_BEGIN _devices = [NSOrderedSet orderedSetWithObject:@(1)]; } - _relay = [relay isEqualToString:@""] ? nil : relay; - return self; } @@ -98,17 +76,23 @@ NS_ASSUME_NONNULL_BEGIN return self; } -+ (nullable instancetype)recipientWithTextSecureIdentifier:(NSString *)textSecureIdentifier - withTransaction:(YapDatabaseReadTransaction *)transaction + ++ (nullable instancetype)registeredRecipientForRecipientId:(NSString *)recipientId + transaction:(YapDatabaseReadTransaction *)transaction { - return [self fetchObjectWithUniqueID:textSecureIdentifier transaction:transaction]; + OWSAssert(transaction); + OWSAssert(recipientId.length > 0); + + return [self fetchObjectWithUniqueID:recipientId transaction:transaction]; } -+ (nullable instancetype)recipientWithTextSecureIdentifier:(NSString *)textSecureIdentifier ++ (nullable instancetype)recipientForRecipientId:(NSString *)recipientId { + OWSAssert(recipientId.length > 0); + __block SignalRecipient *recipient; - [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { - recipient = [self recipientWithTextSecureIdentifier:textSecureIdentifier withTransaction:transaction]; + [self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + recipient = [self registeredRecipientForRecipientId:recipientId transaction:transaction]; }]; return recipient; } @@ -116,42 +100,72 @@ NS_ASSUME_NONNULL_BEGIN // TODO This method should probably live on the TSAccountManager rather than grabbing a global singleton. + (instancetype)selfRecipient { - SignalRecipient *myself = [self recipientWithTextSecureIdentifier:[TSAccountManager localNumber]]; + SignalRecipient *myself = [self recipientForRecipientId:[TSAccountManager localNumber]]; if (!myself) { - myself = [[self alloc] initWithTextSecureIdentifier:[TSAccountManager localNumber] relay:nil]; + myself = [[self alloc] initWithTextSecureIdentifier:[TSAccountManager localNumber]]; } return myself; } -- (void)addDevices:(NSSet *)set +- (void)addDevices:(NSSet *)devices { - if ([self.uniqueId isEqual:[TSAccountManager localNumber]] && [set containsObject:@(1)]) { + OWSAssert(devices.count > 0); + + if ([self.uniqueId isEqual:[TSAccountManager localNumber]] && [devices containsObject:@(1)]) { OWSFail(@"%@ in %s adding self as recipient device", self.logTag, __PRETTY_FUNCTION__); return; } NSMutableOrderedSet *updatedDevices = [self.devices mutableCopy]; - [updatedDevices unionSet:set]; - + [updatedDevices unionSet:devices]; self.devices = [updatedDevices copy]; } -- (void)removeDevices:(NSSet *)set +- (void)removeDevices:(NSSet *)devices { - NSMutableOrderedSet *updatedDevices = [self.devices mutableCopy]; - [updatedDevices minusSet:set]; + OWSAssert(devices.count > 0); + NSMutableOrderedSet *updatedDevices = [self.devices mutableCopy]; + [updatedDevices minusSet:devices]; self.devices = [updatedDevices copy]; } -- (BOOL)supportsVoice +- (void)addDevicesToRegisteredRecipient:(NSSet *)devices transaction:(YapDatabaseReadWriteTransaction *)transaction { - return YES; + OWSAssert(transaction); + OWSAssert(devices.count > 0); + + [self addDevices:devices]; + + 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]; } -- (BOOL)supportsWebRTC +- (void)removeDevicesFromRegisteredRecipient:(NSSet *)devices transaction:(YapDatabaseReadWriteTransaction *)transaction { - return YES; + OWSAssert(transaction); + OWSAssert(devices.count > 0); + + [self removeDevices:devices]; + + 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]; } - (NSString *)recipientId @@ -165,12 +179,80 @@ NS_ASSUME_NONNULL_BEGIN } - (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction +{ + // We only want to mutate the persisted SignalRecipients in the database + // using other methods of this class, e.g. markRecipientAsRegistered... + // to create, addDevices and removeDevices to mutate. We're trying to + // be strict about using persisted SignalRecipients as a cache to + // reflect "last known registration status". Forcing our codebase to + // use those methods helps ensure that we update the cache deliberately. + OWSProdLogAndFail(@"%@ Don't call saveWithTransaction from outside this class.", self.logTag); + + [self saveWithTransaction_internal:transaction]; +} + +- (void)saveWithTransaction_internal:(YapDatabaseReadWriteTransaction *)transaction { [super saveWithTransaction:transaction]; DDLogVerbose(@"%@ saved signal recipient: %@", self.logTag, self.recipientId); } ++ (BOOL)isRegisteredRecipient:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction +{ + SignalRecipient *_Nullable instance = [self registeredRecipientForRecipientId:recipientId transaction:transaction]; + return instance != nil; +} + ++ (SignalRecipient *)markRecipientAsRegisteredAndGet:(NSString *)recipientId + transaction:(YapDatabaseReadWriteTransaction *)transaction +{ + OWSAssert(transaction); + OWSAssert(recipientId.length > 0); + + SignalRecipient *_Nullable instance = [self registeredRecipientForRecipientId:recipientId transaction:transaction]; + + if (!instance) { + DDLogDebug(@"%@ creating recipient: %@", self.logTag, recipientId); + + instance = [[self alloc] initWithTextSecureIdentifier:recipientId]; + [instance saveWithTransaction_internal:transaction]; + } + return instance; +} + ++ (void)markRecipientAsRegistered:(NSString *)recipientId + deviceId:(UInt32)deviceId + transaction:(YapDatabaseReadWriteTransaction *)transaction +{ + OWSAssert(transaction); + OWSAssert(recipientId.length > 0); + + SignalRecipient *recipient = [self markRecipientAsRegisteredAndGet:recipientId transaction:transaction]; + if (![recipient.devices containsObject:@(deviceId)]) { + DDLogDebug(@"%@ in %s adding device %u to existing recipient.", + self.logTag, + __PRETTY_FUNCTION__, + (unsigned int)deviceId); + + [recipient addDevices:[NSSet setWithObject:@(deviceId)]]; + [recipient saveWithTransaction_internal:transaction]; + } +} + ++ (void)removeUnregisteredRecipient:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction +{ + OWSAssert(transaction); + OWSAssert(recipientId.length > 0); + + SignalRecipient *_Nullable instance = [self registeredRecipientForRecipientId:recipientId transaction:transaction]; + if (!instance) { + return; + } + DDLogDebug(@"%@ removing recipient: %@", self.logTag, recipientId); + [instance removeWithTransaction:transaction]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread.h b/SignalServiceKit/src/Contacts/Threads/TSContactThread.h index 0c28b19b2..c0ac5c256 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSContactThread.h +++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread.h @@ -15,10 +15,6 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId transaction:(YapDatabaseReadWriteTransaction *)transaction; -+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId - transaction:(YapDatabaseReadWriteTransaction *)transaction - relay:(nullable NSString *)relay; - // Unlike getOrCreateThreadWithContactId, this will _NOT_ create a thread if one does not already exist. + (nullable instancetype)getThreadWithContactId:(NSString *)contactId transaction:(YapDatabaseReadTransaction *)transaction; diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread.m b/SignalServiceKit/src/Contacts/Threads/TSContactThread.m index 1fbf3dc36..53464dee5 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSContactThread.m +++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread.m @@ -27,35 +27,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } -+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId - transaction:(YapDatabaseReadWriteTransaction *)transaction - relay:(nullable NSString *)relay -{ - OWSAssert(contactId.length > 0); - - SignalRecipient *recipient = - [SignalRecipient recipientWithTextSecureIdentifier:contactId withTransaction:transaction]; - - if (!recipient) { - // If no recipient record exists for that contactId, create an empty record - // for immediate use, then ask ContactsUpdater to try to update it async. - recipient = - [[SignalRecipient alloc] initWithTextSecureIdentifier:contactId - relay:relay]; - [recipient saveWithTransaction:transaction]; - - // Update recipient with Server record async. - [[ContactsUpdater sharedUpdater] lookupIdentifier:contactId - success:^(SignalRecipient *recipient) { - } - failure:^(NSError *error) { - DDLogWarn(@"Failed to lookup contact with error:%@", error); - }]; - } - - return [self getOrCreateThreadWithContactId:contactId transaction:transaction]; -} - + (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId transaction:(YapDatabaseReadWriteTransaction *)transaction { OWSAssert(contactId.length > 0); diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m index be7f09200..13341b9cd 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m @@ -4,7 +4,6 @@ #import "TSGroupThread.h" #import "NSData+Base64.h" -#import "SignalRecipient.h" #import "TSAttachmentStream.h" #import #import diff --git a/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m b/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m index 64f20b1b4..4dc206bac 100644 --- a/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m +++ b/SignalServiceKit/src/Devices/OWSRecordTranscriptJob.m @@ -80,7 +80,6 @@ NS_ASSUME_NONNULL_BEGIN OWSAttachmentsProcessor *attachmentsProcessor = [[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:transcript.attachmentPointerProtos - relay:transcript.relay networkManager:self.networkManager transaction:transaction]; diff --git a/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.h b/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.h index b1a8b19c5..361aa9676 100644 --- a/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.h +++ b/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.h @@ -30,7 +30,6 @@ extern NSString *const kAttachmentDownloadAttachmentIDKey; - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithAttachmentProtos:(NSArray *)attachmentProtos - relay:(nullable NSString *)relay networkManager:(TSNetworkManager *)networkManager transaction:(YapDatabaseReadWriteTransaction *)transaction NS_DESIGNATED_INITIALIZER; diff --git a/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.m b/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.m index 0e1132786..980fc5635 100644 --- a/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.m +++ b/SignalServiceKit/src/Messages/Attachments/OWSAttachmentsProcessor.m @@ -57,7 +57,6 @@ static const CGFloat kAttachmentDownloadProgressTheta = 0.001f; } - (instancetype)initWithAttachmentProtos:(NSArray *)attachmentProtos - relay:(nullable NSString *)relay networkManager:(TSNetworkManager *)networkManager transaction:(YapDatabaseReadWriteTransaction *)transaction { @@ -72,7 +71,7 @@ static const CGFloat kAttachmentDownloadProgressTheta = 0.001f; NSMutableArray *attachmentPointers = [NSMutableArray new]; for (OWSSignalServiceProtosAttachmentPointer *attachmentProto in attachmentProtos) { - TSAttachmentPointer *pointer = [TSAttachmentPointer attachmentPointerFromProto:attachmentProto relay:relay]; + TSAttachmentPointer *pointer = [TSAttachmentPointer attachmentPointerFromProto:attachmentProto]; [attachmentIds addObject:pointer.uniqueId]; [pointer saveWithTransaction:transaction]; @@ -152,8 +151,7 @@ static const CGFloat kAttachmentDownloadProgressTheta = 0.001f; if (attachment.serverId < 100) { DDLogError(@"%@ Suspicious attachment id: %llu", self.logTag, (unsigned long long)attachment.serverId); } - TSRequest *request = - [OWSRequestFactory attachmentRequestWithAttachmentId:attachment.serverId relay:attachment.relay]; + TSRequest *request = [OWSRequestFactory attachmentRequestWithAttachmentId:attachment.serverId]; [self.networkManager makeRequest:request success:^(NSURLSessionDataTask *task, id responseObject) { diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h index ddd96cad7..9920d6813 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h @@ -25,14 +25,11 @@ typedef NS_ENUM(NSUInteger, TSAttachmentPointerState) { digest:(nullable NSData *)digest byteCount:(UInt32)byteCount contentType:(NSString *)contentType - relay:(NSString *)relay sourceFilename:(nullable NSString *)sourceFilename attachmentType:(TSAttachmentType)attachmentType NS_DESIGNATED_INITIALIZER; -+ (TSAttachmentPointer *)attachmentPointerFromProto:(OWSSignalServiceProtosAttachmentPointer *)attachmentProto - relay:(NSString *_Nullable)relay; ++ (TSAttachmentPointer *)attachmentPointerFromProto:(OWSSignalServiceProtosAttachmentPointer *)attachmentProto; -@property (nonatomic, readonly) NSString *relay; @property (atomic) TSAttachmentPointerState state; @property (nullable, atomic) NSString *mostRecentFailureLocalizedText; diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m index b1fbcead2..00a61c68d 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m @@ -30,7 +30,6 @@ NS_ASSUME_NONNULL_BEGIN digest:(nullable NSData *)digest byteCount:(UInt32)byteCount contentType:(NSString *)contentType - relay:(NSString *)relay sourceFilename:(nullable NSString *)sourceFilename attachmentType:(TSAttachmentType)attachmentType { @@ -45,7 +44,6 @@ NS_ASSUME_NONNULL_BEGIN _digest = digest; _state = TSAttachmentPointerStateEnqueued; - _relay = relay; self.attachmentType = attachmentType; return self; @@ -53,7 +51,6 @@ NS_ASSUME_NONNULL_BEGIN + (TSAttachmentPointer *)attachmentPointerFromProto:(OWSSignalServiceProtosAttachmentPointer *)attachmentProto - relay:(NSString *_Nullable)relay { OWSAssert(attachmentProto.id != 0); OWSAssert(attachmentProto.key != nil); @@ -75,7 +72,6 @@ NS_ASSUME_NONNULL_BEGIN digest:digest byteCount:attachmentProto.size contentType:attachmentProto.contentType - relay:relay sourceFilename:attachmentProto.fileName attachmentType:attachmentType]; return pointer; diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h index 93e3b4317..a6b9d3737 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.h @@ -19,10 +19,8 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSIncomingSentMessageTranscript : NSObject - (instancetype)initWithProto:(OWSSignalServiceProtosSyncMessageSent *)sentProto - relay:(nullable NSString *)relay transaction:(YapDatabaseReadWriteTransaction *)transaction; -@property (nonatomic, readonly) NSString *relay; @property (nonatomic, readonly) OWSSignalServiceProtosDataMessage *dataMessage; @property (nonatomic, readonly) NSString *recipientId; @property (nonatomic, readonly) uint64_t timestamp; diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m index 01490fc49..333fd0dad 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSIncomingSentMessageTranscript.m @@ -19,7 +19,6 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWSIncomingSentMessageTranscript - (instancetype)initWithProto:(OWSSignalServiceProtosSyncMessageSent *)sentProto - relay:(nullable NSString *)relay transaction:(YapDatabaseReadWriteTransaction *)transaction { self = [super init]; @@ -27,7 +26,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } - _relay = relay; _dataMessage = sentProto.message; _recipientId = sentProto.destination; _timestamp = sentProto.timestamp; @@ -45,9 +43,8 @@ NS_ASSUME_NONNULL_BEGIN _thread = [TSContactThread getOrCreateThreadWithContactId:_recipientId transaction:transaction]; } - _quotedMessage = - [TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread relay:relay transaction:transaction]; - _contact = [OWSContacts contactForDataMessage:_dataMessage relay:relay transaction:transaction]; + _quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread transaction:transaction]; + _contact = [OWSContacts contactForDataMessage:_dataMessage transaction:transaction]; return self; } diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContact.h b/SignalServiceKit/src/Messages/Interactions/OWSContact.h index 7dfc2ed86..254436f39 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSContact.h +++ b/SignalServiceKit/src/Messages/Interactions/OWSContact.h @@ -10,7 +10,6 @@ NS_ASSUME_NONNULL_BEGIN @class CNContact; @class OWSAttachmentInfo; @class OWSSignalServiceProtosDataMessage; -@class OWSSignalServiceProtosDataMessage; @class OWSSignalServiceProtosDataMessageContact; @class TSAttachment; @class TSAttachmentStream; @@ -177,7 +176,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value); + (nullable OWSSignalServiceProtosDataMessageContact *)protoForContact:(OWSContact *)contact; + (nullable OWSContact *)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage - relay:(nullable NSString *)relay transaction:(YapDatabaseReadWriteTransaction *)transaction; @end diff --git a/SignalServiceKit/src/Messages/Interactions/OWSContact.m b/SignalServiceKit/src/Messages/Interactions/OWSContact.m index a05c514b8..b105602f1 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSContact.m +++ b/SignalServiceKit/src/Messages/Interactions/OWSContact.m @@ -893,7 +893,6 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value) } + (nullable OWSContact *)contactForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage - relay:(nullable NSString *)relay transaction:(YapDatabaseReadWriteTransaction *)transaction { OWSAssert(dataMessage); @@ -968,8 +967,7 @@ NSString *NSStringForContactAddressType(OWSContactAddressType value) if (avatarInfo.hasAvatar) { OWSSignalServiceProtosAttachmentPointer *avatarAttachment = avatarInfo.avatar; - TSAttachmentPointer *attachmentPointer = - [TSAttachmentPointer attachmentPointerFromProto:avatarAttachment relay:relay]; + TSAttachmentPointer *attachmentPointer = [TSAttachmentPointer attachmentPointerFromProto:avatarAttachment]; [attachmentPointer saveWithTransaction:transaction]; contact.avatarAttachmentId = attachmentPointer.uniqueId; diff --git a/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.h b/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.h index 202f8f1ec..49d973fec 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.h +++ b/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.h @@ -92,7 +92,6 @@ NS_ASSUME_NONNULL_BEGIN + (nullable instancetype)quotedMessageForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage thread:(TSThread *)thread - relay:(nullable NSString *)relay transaction:(YapDatabaseReadWriteTransaction *)transaction; @end diff --git a/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.m b/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.m index a846b5e6a..4dc7881e0 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSQuotedMessage.m @@ -105,7 +105,6 @@ NS_ASSUME_NONNULL_BEGIN + (TSQuotedMessage *_Nullable)quotedMessageForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage thread:(TSThread *)thread - relay:(nullable NSString *)relay transaction:(YapDatabaseReadWriteTransaction *)transaction { OWSAssert(dataMessage); @@ -169,7 +168,7 @@ NS_ASSUME_NONNULL_BEGIN OWSSignalServiceProtosAttachmentPointer *thumbnailAttachmentProto = quotedAttachment.thumbnail; TSAttachmentPointer *thumbnailPointer = - [TSAttachmentPointer attachmentPointerFromProto:thumbnailAttachmentProto relay:relay]; + [TSAttachmentPointer attachmentPointerFromProto:thumbnailAttachmentProto]; [thumbnailPointer saveWithTransaction:transaction]; attachmentInfo.thumbnailAttachmentPointerId = thumbnailPointer.uniqueId; diff --git a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m index c1cdd2983..4dd0a1764 100644 --- a/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m +++ b/SignalServiceKit/src/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m @@ -8,7 +8,6 @@ #import "OWSPrimaryStorage+SessionStore.h" #import "OWSPrimaryStorage.h" #import "PreKeyBundle+jsonDict.h" -#import "SignalRecipient.h" #import "TSContactThread.h" #import "TSErrorMessage_privateConstructor.h" #import "TSOutgoingMessage.h" diff --git a/SignalServiceKit/src/Messages/OWSMessageDecrypter.m b/SignalServiceKit/src/Messages/OWSMessageDecrypter.m index 001b3aa4c..78698d056 100644 --- a/SignalServiceKit/src/Messages/OWSMessageDecrypter.m +++ b/SignalServiceKit/src/Messages/OWSMessageDecrypter.m @@ -110,10 +110,9 @@ NS_ASSUME_NONNULL_BEGIN DecryptSuccessBlock successBlock = ^(NSData *_Nullable plaintextData, YapDatabaseReadWriteTransaction *transaction) { - [SignalRecipient ensureRecipientExistsWithRecipientId:envelope.source - deviceId:envelope.sourceDevice - relay:envelope.relay - transaction:transaction]; + [SignalRecipient markRecipientAsRegistered:envelope.source + deviceId:envelope.sourceDevice + transaction:transaction]; successBlockParameter(plaintextData, transaction); }; diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 74f49f420..47989a9cd 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -516,7 +516,6 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(groupThread); OWSAttachmentsProcessor *attachmentsProcessor = [[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:@[ dataMessage.group.avatar ] - relay:envelope.relay networkManager:self.networkManager transaction:transaction]; @@ -553,7 +552,6 @@ NS_ASSUME_NONNULL_BEGIN OWSAttachmentsProcessor *attachmentsProcessor = [[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:dataMessage.attachments - relay:envelope.relay networkManager:self.networkManager transaction:transaction]; if (!attachmentsProcessor.hasSupportedAttachments) { @@ -605,7 +603,6 @@ NS_ASSUME_NONNULL_BEGIN if (syncMessage.hasSent) { OWSIncomingSentMessageTranscript *transcript = [[OWSIncomingSentMessageTranscript alloc] initWithProto:syncMessage.sent - relay:envelope.relay transaction:transaction]; OWSRecordTranscriptJob *recordJob = @@ -916,8 +913,7 @@ NS_ASSUME_NONNULL_BEGIN uint64_t timestamp = envelope.timestamp; NSString *body = dataMessage.body; NSData *groupId = dataMessage.hasGroup ? dataMessage.group.id : nil; - OWSContact *_Nullable contact = - [OWSContacts contactForDataMessage:dataMessage relay:envelope.relay transaction:transaction]; + OWSContact *_Nullable contact = [OWSContacts contactForDataMessage:dataMessage transaction:transaction]; if (dataMessage.group.type == OWSSignalServiceProtosGroupContextTypeRequestInfo) { [self handleGroupInfoRequest:envelope dataMessage:dataMessage transaction:transaction]; @@ -1016,7 +1012,6 @@ NS_ASSUME_NONNULL_BEGIN TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage thread:oldGroupThread - relay:envelope.relay transaction:transaction]; DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu", @@ -1060,13 +1055,11 @@ NS_ASSUME_NONNULL_BEGIN self.logTag, envelopeAddress(envelope), (unsigned long)timestamp); - TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:envelope.source - transaction:transaction - relay:envelope.relay]; + TSContactThread *thread = + [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction]; TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage thread:thread - relay:envelope.relay transaction:transaction]; TSIncomingMessage *incomingMessage = diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.h b/SignalServiceKit/src/Messages/OWSMessageSender.h index 6b65f8f9b..95c488969 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.h +++ b/SignalServiceKit/src/Messages/OWSMessageSender.h @@ -8,11 +8,9 @@ NS_ASSUME_NONNULL_BEGIN extern const NSUInteger kOversizeTextMessageSizeThreshold; -@class ContactsUpdater; @class OWSBlockingManager; @class OWSPrimaryStorage; @class OWSUploadingService; -@class SignalRecipient; @class TSInvalidIdentityKeySendingErrorMessage; @class TSNetworkManager; @class TSOutgoingMessage; @@ -42,15 +40,13 @@ NS_SWIFT_NAME(MessageSender) // For subclassing in tests OWSUploadingService *_uploadingService; - ContactsUpdater *_contactsUpdater; } - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager primaryStorage:(OWSPrimaryStorage *)primaryStorage - contactsManager:(id)contactsManager - contactsUpdater:(ContactsUpdater *)contactsUpdater; + contactsManager:(id)contactsManager; - (void)setBlockingManager:(OWSBlockingManager *)blockingManager; diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index 4b8c46580..018977468 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -4,7 +4,6 @@ #import "OWSMessageSender.h" #import "AppContext.h" -#import "ContactsUpdater.h" #import "NSData+keyVersionByte.h" #import "NSData+messagePadding.h" #import "NSDate+OWS.h" @@ -78,7 +77,7 @@ void AssertIsOnSendingQueue() messageSender:(OWSMessageSender *)messageSender dbConnection:(YapDatabaseConnection *)dbConnection success:(void (^)(void))aSuccessHandler - failure:(void (^)(NSError *_Nonnull error))aFailureHandler NS_DESIGNATED_INITIALIZER; + failure:(void (^)(NSError * error))aFailureHandler NS_DESIGNATED_INITIALIZER; @end @@ -100,7 +99,7 @@ void AssertIsOnSendingQueue() @property (nonatomic, readonly) OWSMessageSender *messageSender; @property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (nonatomic, readonly) void (^successHandler)(void); -@property (nonatomic, readonly) void (^failureHandler)(NSError *_Nonnull error); +@property (nonatomic, readonly) void (^failureHandler)(NSError * error); @end @@ -112,7 +111,7 @@ void AssertIsOnSendingQueue() messageSender:(OWSMessageSender *)messageSender dbConnection:(YapDatabaseConnection *)dbConnection success:(void (^)(void))successHandler - failure:(void (^)(NSError *_Nonnull error))failureHandler + failure:(void (^)(NSError * error))failureHandler { self = [super init]; if (!self) { @@ -152,7 +151,7 @@ void AssertIsOnSendingQueue() // Sanity check preconditions if (self.message.hasAttachments) { - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { + [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * transaction) { TSAttachmentStream *attachmentStream = (TSAttachmentStream *)[self.message attachmentWithTransaction:transaction]; OWSAssert(attachmentStream); @@ -216,7 +215,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; @property (nonatomic, readonly) OWSBlockingManager *blockingManager; @property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (nonatomic, readonly) id contactsManager; -@property (nonatomic, readonly) ContactsUpdater *contactsUpdater; @property (atomic, readonly) NSMutableDictionary *sendingQueueMap; @end @@ -226,7 +224,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; - (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager primaryStorage:(OWSPrimaryStorage *)primaryStorage contactsManager:(id)contactsManager - contactsUpdater:(ContactsUpdater *)contactsUpdater { self = [super init]; if (!self) { @@ -236,7 +233,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; _networkManager = networkManager; _primaryStorage = primaryStorage; _contactsManager = contactsManager; - _contactsUpdater = contactsUpdater; _sendingQueueMap = [NSMutableDictionary new]; _dbConnection = primaryStorage.newDatabaseConnection; @@ -451,42 +447,19 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; - (NSArray *)signalRecipientsForRecipientIds:(NSArray *)recipientIds message:(TSOutgoingMessage *)message - error:(NSError **)error { OWSAssert(recipientIds); OWSAssert(message); - OWSAssert(error); - - *error = nil; NSMutableArray *recipients = [NSMutableArray new]; - - for (NSString *recipientId in recipientIds) { - SignalRecipient *existingRecipient = [SignalRecipient recipientWithTextSecureIdentifier:recipientId]; - - if (existingRecipient) { - [recipients addObject:existingRecipient]; - } else { - SignalRecipient *newRecipient = [self.contactsUpdater synchronousLookup:recipientId error:error]; - if (newRecipient) { - [recipients addObject:newRecipient]; - } else { - DDLogWarn(@"%@ No SignalRecipient for recipientId: %@", self.logTag, recipientId); - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - // Mark this recipient as "skipped". - [message updateWithSkippedRecipient:recipientId transaction:transaction]; - }]; - } + [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + for (NSString *recipientId in recipientIds) { + SignalRecipient *recipient = + [SignalRecipient getOrBuildUnsavedRecipientForRecipientId:recipientId transaction:transaction]; + [recipients addObject:recipient]; } - } - - if (recipients.count == 0 && !*error) { - // error should be set in contactsUpater, but just in case. - OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotFindContacts1]); - *error = OWSErrorMakeFailedToSendOutgoingMessageError(); - } - - return [recipients copy]; + }]; + return recipients; } - (void)sendMessageToService:(TSOutgoingMessage *)message @@ -553,20 +526,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; return; } - NSError *error; NSArray *recipients = - [self signalRecipientsForRecipientIds:sendingRecipientIds.allObjects message:message error:&error]; - - if (recipients.count == 0) { - if (!error) { - OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotFindContacts2]); - error = OWSErrorMakeFailedToSendOutgoingMessageError(); - } - // If no recipients were found, there's no reason to retry. It will just fail again. - [error setIsRetryable:NO]; - failureHandler(error); - return; - } + [self signalRecipientsForRecipientIds:sendingRecipientIds.allObjects message:message]; + OWSAssert(recipients.count == sendingRecipientIds.count); [self groupSend:recipients message:message thread:gThread success:successHandler failure:failureHandler]; @@ -593,26 +555,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; return; } - SignalRecipient *recipient = [SignalRecipient recipientWithTextSecureIdentifier:recipientContactId]; - if (!recipient) { - NSError *error; - // possibly returns nil. - recipient = [self.contactsUpdater synchronousLookup:recipientContactId error:&error]; - - if (error) { - if (error.code == OWSErrorCodeNoSuchSignalRecipient) { - DDLogWarn(@"%@ recipient contact not found", self.logTag); - [self unregisteredRecipient:recipient message:message thread:thread]; - } - - OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotFindContacts3]); - // No need to repeat trying to find a failure. Apart from repeatedly failing, it would also cause us - // to print redundant error messages. - [error setIsRetryable:NO]; - failureHandler(error); - return; - } - } + NSArray *recipients = + [self signalRecipientsForRecipientIds:@[recipientContactId] message:message]; + OWSAssert(recipients.count == 1); + SignalRecipient *recipient = recipients.firstObject; if (!recipient) { NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError(); @@ -759,15 +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]; } - [recipient removeWithTransaction:transaction]; + if (![SignalRecipient isRegisteredRecipient:recipient.recipientId transaction:transaction]) { + return; + } + + [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. }]; } @@ -779,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: %@", @@ -821,7 +778,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; NSArray *deviceMessages; @try { - deviceMessages = [self deviceMessages:message forRecipient:recipient]; + deviceMessages = [self deviceMessages:message recipient:recipient]; } @catch (NSException *exception) { deviceMessages = @[]; if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { @@ -943,7 +900,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; // This emulates the completion logic of an actual successful save (see below). [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [message updateWithSkippedRecipient:localNumber transaction:transaction]; - [recipient saveWithTransaction:transaction]; }]; successHandler(); }); @@ -967,6 +923,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; // * The first (after upgrading?) time we send a sync message to our linked devices. // * After unlinking all linked devices. // * After trying and failing to link a device. + // * The first time we send a message to a user, if they don't have their + // default device. For example, if they have unregistered + // their primary but still have a linked device. Or later, when they re-register. // // When we're not sure if we have linked devices, we need to try // to send self-sync messages even if they have no device messages @@ -977,7 +936,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; TSRequest *request = [OWSRequestFactory submitMessageRequestWithRecipient:recipient.uniqueId messages:deviceMessages - relay:recipient.relay timeStamp:message.timestamp]; if (useWebsocketIfAvailable && TSSocketManager.canMakeRequests) { [TSSocketManager.sharedManager makeRequest:request @@ -1061,8 +1019,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; dispatch_async([OWSDispatch sendingQueue], ^{ [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [recipient saveWithTransaction:transaction]; [message updateWithSentRecipient:recipient.uniqueId transaction:transaction]; + + // If we've just delivered a message to a user, we know they + // have a valid Signal account. + [SignalRecipient markRecipientAsRegisteredAndGet:recipient.recipientId transaction:transaction]; }]; [self handleMessageSentLocally:message]; @@ -1112,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 " @@ -1125,22 +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; @@ -1153,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; } @@ -1200,7 +1180,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } [self.dbConnection - asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) { if (extraDevices.count < 1 && missingDevices.count < 1) { OWSProdFail([OWSAnalyticsEvents messageSenderErrorNoMissingOrExtraDevices]); } @@ -1213,16 +1193,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; protocolContext:transaction]; } - [recipient removeDevices:[NSSet setWithArray:extraDevices]]; + [recipient removeDevicesFromRegisteredRecipient:[NSSet setWithArray:extraDevices] + transaction:transaction]; } if (missingDevices && missingDevices.count > 0) { DDLogInfo(@"%@ Adding missing devices: %@", self.logTag, missingDevices); - [recipient addDevices:[NSSet setWithArray:missingDevices]]; + [recipient addDevicesToRegisteredRecipient:[NSSet setWithArray:missingDevices] + transaction:transaction]; } - [recipient saveWithTransaction:transaction]; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ completionHandler(); }); @@ -1270,8 +1250,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; }]; } -- (NSArray *)deviceMessages:(TSOutgoingMessage *)message - forRecipient:(SignalRecipient *)recipient +- (NSArray *)deviceMessages:(TSOutgoingMessage *)message recipient:(SignalRecipient *)recipient { OWSAssert(message); OWSAssert(recipient); @@ -1292,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 @@ -1314,7 +1293,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } } @catch (NSException *exception) { if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) { - [recipient removeDevices:[NSSet setWithObject:deviceNumber]]; + [self.dbConnection + asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) { + [recipient removeDevicesFromRegisteredRecipient:[NSSet setWithObject:deviceNumber] + transaction:transaction]; + }]; } else { @throw exception; } @@ -1325,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; @@ -1360,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" diff --git a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h index d73be79c1..9ea9864c1 100644 --- a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h +++ b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.h @@ -37,7 +37,7 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo + (TSRequest *)allocAttachmentRequest; -+ (TSRequest *)attachmentRequestWithAttachmentId:(UInt64)attachmentId relay:(nullable NSString *)relay; ++ (TSRequest *)attachmentRequestWithAttachmentId:(UInt64)attachmentId; + (TSRequest *)availablePreKeysCountRequest; @@ -60,7 +60,6 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo + (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId messages:(NSArray *)messages - relay:(nullable NSString *)relay timeStamp:(uint64_t)timeStamp; + (TSRequest *)registerSignedPrekeyRequestWithSignedPreKeyRecord:(SignedPreKeyRecord *)signedPreKey; diff --git a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m index 1b38b7ea5..334252fc0 100644 --- a/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m +++ b/SignalServiceKit/src/Network/API/Requests/OWSRequestFactory.m @@ -101,17 +101,12 @@ NS_ASSUME_NONNULL_BEGIN return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}]; } -+ (TSRequest *)attachmentRequestWithAttachmentId:(UInt64)attachmentId relay:(nullable NSString *)relay ++ (TSRequest *)attachmentRequestWithAttachmentId:(UInt64)attachmentId { OWSAssert(attachmentId > 0); NSString *path = [NSString stringWithFormat:@"%@/%llu", textSecureAttachmentsAPI, attachmentId]; - // TODO: Should this be in the parameters? - if (relay.length > 0) { - path = [path stringByAppendingFormat:@"?relay=%@", relay]; - } - return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}]; } @@ -211,7 +206,6 @@ NS_ASSUME_NONNULL_BEGIN + (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId messages:(NSArray *)messages - relay:(nullable NSString *)relay timeStamp:(uint64_t)timeStamp { // NOTE: messages may be empty; See comments in OWSDeviceManager. @@ -219,14 +213,11 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(timeStamp > 0); NSString *path = [textSecureMessagesAPI stringByAppendingString:recipientId]; - NSMutableDictionary *parameters = [@{ + NSDictionary *parameters = @{ @"messages" : messages, @"timestamp" : @(timeStamp), - } mutableCopy]; + }; - if (relay) { - parameters[@"relay"] = relay; - } return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters]; } diff --git a/SignalServiceKit/src/Network/API/TSNetworkManager.m b/SignalServiceKit/src/Network/API/TSNetworkManager.m index d0414d70f..9ac53d739 100644 --- a/SignalServiceKit/src/Network/API/TSNetworkManager.m +++ b/SignalServiceKit/src/Network/API/TSNetworkManager.m @@ -222,6 +222,7 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); break; } case 417: { + // TODO: Is this response code obsolete? DDLogWarn(@"The number is already registered on a relay. Please unregister there first: %@", request); failureBlock(task, [self errorWithHTTPCode:statusCode diff --git a/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m b/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m index 00e207d9c..ae6c0bdb8 100644 --- a/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m +++ b/SignalServiceKit/src/Protocols/ProtoBuf+OWS.m @@ -1,13 +1,12 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // +#import "Cryptography.h" #import "ProfileManagerProtocol.h" #import "ProtoBuf+OWS.h" -#import "SignalRecipient.h" #import "TSThread.h" #import "TextSecureKitEnv.h" -#import "Cryptography.h" NS_ASSUME_NONNULL_BEGIN