Streamline SignalRecipient.

pull/1/head
Matthew Chen 7 years ago
parent ef3933bfaa
commit 05a4222b2d

@ -38,31 +38,27 @@ NS_ASSUME_NONNULL_BEGIN
return self; return self;
} }
- (SignalRecipient *)signalRecipientForRegisteredRecipientId:(NSString *)recipientId - (void)lookupIdentifier:(NSString *)recipientId
{
__block SignalRecipient *recipient;
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
recipient =
[SignalRecipient ensureRecipientExistsWithRegisteredRecipientId:recipientId transaction:transaction];
}];
return recipient;
}
- (void)lookupIdentifier:(NSString *)identifier
success:(void (^)(SignalRecipient *recipient))success success:(void (^)(SignalRecipient *recipient))success
failure:(void (^)(NSError *error))failure failure:(void (^)(NSError *error))failure
{ {
OWSAssert(recipientId.length > 0);
// This should never happen according to nullability annotations... but IIRC it does. =/ // This should never happen according to nullability annotations... but IIRC it does. =/
if (!identifier) { if (!recipientId) {
OWSFail(@"%@ Cannot lookup nil identifier", self.logTag); OWSFail(@"%@ Cannot lookup nil identifier", self.logTag);
failure(OWSErrorWithCodeDescription(OWSErrorCodeInvalidMethodParameters, @"Cannot lookup nil identifier")); failure(OWSErrorWithCodeDescription(OWSErrorCodeInvalidMethodParameters, @"Cannot lookup nil identifier"));
return; return;
} }
[self contactIntersectionWithSet:[NSSet setWithObject:identifier] NSSet *recipiendIds = [NSSet setWithObject:recipientId];
success:^(NSSet<NSString *> *_Nonnull matchedIds) { [self contactIntersectionWithSet:recipiendIds
if (matchedIds.count == 1) { success:^(NSSet<SignalRecipient *> *recipients) {
success([self signalRecipientForRegisteredRecipientId:identifier]); if (recipients.count > 0) {
OWSAssert(recipients.count == 1);
SignalRecipient *recipient = recipients.allObjects.firstObject;
success(recipient);
} else { } else {
failure(OWSErrorMakeNoSuchSignalRecipientError()); failure(OWSErrorMakeNoSuchSignalRecipientError());
} }
@ -81,13 +77,8 @@ NS_ASSUME_NONNULL_BEGIN
} }
[self contactIntersectionWithSet:[NSSet setWithArray:identifiers] [self contactIntersectionWithSet:[NSSet setWithArray:identifiers]
success:^(NSSet<NSString *> *_Nonnull matchedIds) { success:^(NSSet<SignalRecipient *> *recipients) {
if (matchedIds.count > 0) { if (recipients.count > 0) {
NSMutableArray<SignalRecipient *> *recipients = [NSMutableArray new];
for (NSString *identifier in matchedIds) {
[recipients
addObject:[self signalRecipientForRegisteredRecipientId:identifier]];
}
success([recipients copy]); success([recipients copy]);
} else { } else {
failure(OWSErrorMakeNoSuchSignalRecipientError()); failure(OWSErrorMakeNoSuchSignalRecipientError());
@ -96,6 +87,7 @@ NS_ASSUME_NONNULL_BEGIN
failure:failure]; failure:failure];
} }
// TODO: Modify this to support delta lookups.
- (void)updateSignalContactIntersectionWithABContacts:(NSArray<Contact *> *)abContacts - (void)updateSignalContactIntersectionWithABContacts:(NSArray<Contact *> *)abContacts
success:(void (^)(void))success success:(void (^)(void))success
failure:(void (^)(NSError *error))failure failure:(void (^)(NSError *error))failure
@ -109,7 +101,8 @@ NS_ASSUME_NONNULL_BEGIN
} }
NSMutableSet *recipientIds = [NSMutableSet set]; 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]]; NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]];
[recipientIds addObjectsFromArray:allRecipientKeys]; [recipientIds addObjectsFromArray:allRecipientKeys];
}]; }];
@ -117,62 +110,70 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableSet<NSString *> *allContacts = [[abPhoneNumbers setByAddingObjectsFromSet:recipientIds] mutableCopy]; NSMutableSet<NSString *> *allContacts = [[abPhoneNumbers setByAddingObjectsFromSet:recipientIds] mutableCopy];
[self contactIntersectionWithSet:allContacts [self contactIntersectionWithSet:allContacts
success:^(NSSet<NSString *> *matchedIds) { success:^(NSSet<SignalRecipient *> *recipients) {
[recipientIds minusSet:matchedIds];
// TODO:
//
// Update cache of registered identifiers.
DDLogInfo(@"%@ successfully intersected contacts.", self.logTag); DDLogInfo(@"%@ successfully intersected contacts.", self.logTag);
success(); success();
} }
failure:failure]; failure:failure];
} }
- (void)contactIntersectionWithSet:(NSSet<NSString *> *)idSet - (void)contactIntersectionWithSet:(NSSet<NSString *> *)recipientIdsToLookup
success:(void (^)(NSSet<NSString *> *matchedIds))success success:(void (^)(NSSet<SignalRecipient *> *recipients))success
failure:(void (^)(NSError *error))failure { failure:(void (^)(NSError *error))failure {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableDictionary *phoneNumbersByHashes = [NSMutableDictionary dictionary]; NSMutableDictionary<NSString *, NSString *> *phoneNumbersByHashes = [NSMutableDictionary new];
for (NSString *identifier in idSet) { for (NSString *recipientId in recipientIdsToLookup) {
[phoneNumbersByHashes setObject:identifier NSString *hash = [Cryptography truncatedSHA1Base64EncodedWithoutPadding:recipientId];
forKey:[Cryptography truncatedSHA1Base64EncodedWithoutPadding:identifier]]; phoneNumbersByHashes[hash] = recipientId;
} }
NSArray *hashes = [phoneNumbersByHashes allKeys]; NSArray<NSString *> *hashes = [phoneNumbersByHashes allKeys];
TSRequest *request = [OWSRequestFactory contactsIntersectionRequestWithHashesArray:hashes]; TSRequest *request = [OWSRequestFactory contactsIntersectionRequestWithHashesArray:hashes];
[[TSNetworkManager sharedManager] makeRequest:request [[TSNetworkManager sharedManager] makeRequest:request
success:^(NSURLSessionDataTask *tsTask, id responseDict) { success:^(NSURLSessionDataTask *task, id responseDict) {
NSMutableSet *identifiers = [NSMutableSet new]; NSMutableSet<NSString *> *registeredRecipientIds = [NSMutableSet new];
NSArray *contactsArray = [(NSDictionary *)responseDict objectForKey:@"contacts"];
if ([responseDict isKindOfClass:[NSDictionary class]]) {
// Map attributes to phone numbers NSArray<NSDictionary *> *_Nullable contactsArray = responseDict[@"contacts"];
if (contactsArray) { if ([contactsArray isKindOfClass:[NSArray class]]) {
for (NSDictionary *dict in contactsArray) { for (NSDictionary *contactDict in contactsArray) {
NSString *hash = [dict objectForKey:@"token"]; if (![contactDict isKindOfClass:[NSDictionary class]]) {
NSString *identifier = [phoneNumbersByHashes objectForKey:hash]; OWSProdLogAndFail(@"%@ invalid contact dictionary.", self.logTag);
continue;
if (identifier.length < 1) { }
DDLogWarn(@"%@ An interesecting hash wasn't found in the mapping.", self.logTag); NSString *_Nullable hash = contactDict[@"token"];
continue; 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];
} }
[identifiers addObject:identifier];
} }
} }
// Insert or update contact attributes NSMutableSet<SignalRecipient *> *recipients = [NSMutableSet new];
// [OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// TODO: Do we need to _eagerly_ ensure a SignalRecipient instance exists? for (NSString *recipientId in recipientIdsToLookup) {
[OWSPrimaryStorage.dbReadWriteConnection if ([registeredRecipientIds containsObject:recipientId]) {
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { SignalRecipient *recipient =
for (NSString *identifier in identifiers) { [SignalRecipient markAccountAsRegistered:recipientId transaction:transaction];
[SignalRecipient ensureRecipientExistsWithRegisteredRecipientId:identifier [recipients addObject:recipient];
transaction:transaction]; } else {
[SignalRecipient markAccountAsNotRegistered:recipientId transaction:transaction];
} }
}]; }
}];
success([identifiers copy]); success([recipients copy]);
} }
failure:^(NSURLSessionDataTask *task, NSError *error) { failure:^(NSURLSessionDataTask *task, NSError *error) {
if (!IsNSErrorNetworkFailure(error)) { if (!IsNSErrorNetworkFailure(error)) {

@ -21,12 +21,6 @@ NS_ASSUME_NONNULL_BEGIN
+ (SignalRecipient *)ensureRecipientExistsWithRecipientId:(NSString *)recipientId + (SignalRecipient *)ensureRecipientExistsWithRecipientId:(NSString *)recipientId
transaction:(YapDatabaseReadWriteTransaction *)transaction; transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (void)ensureRecipientExistsWithRecipientId:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction;
// TODO: Replace with cache of known signal account ids.
// TODO: Remove?
+ (nullable instancetype)registeredRecipientForRecipientId:(NSString *)recipientId + (nullable instancetype)registeredRecipientForRecipientId:(NSString *)recipientId
transaction:(YapDatabaseReadTransaction *)transaction; transaction:(YapDatabaseReadTransaction *)transaction;
@ -40,11 +34,12 @@ NS_ASSUME_NONNULL_BEGIN
// TODO: Replace with cache of known signal account ids. // TODO: Replace with cache of known signal account ids.
+ (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction; + (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction;
+ (void)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)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; + (void)markAccountAsNotRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction;
- (void)markAccountAsNotRegisteredWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -57,36 +57,6 @@ NS_ASSUME_NONNULL_BEGIN
return recipient; return recipient;
} }
+ (void)ensureRecipientExistsWithRecipientId:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
SignalRecipient *_Nullable existingRecipient = [self recipientForRecipientId:recipientId transaction:transaction];
if (!existingRecipient) {
DDLogDebug(@"%@ in %s creating recipient: %@, with deviceId: %u",
self.logTag,
__PRETTY_FUNCTION__,
recipientId,
(unsigned int)deviceId);
SignalRecipient *newRecipient = [[self alloc] initWithTextSecureIdentifier:recipientId];
[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];
}
}
- (instancetype)initWithTextSecureIdentifier:(NSString *)textSecureIdentifier - (instancetype)initWithTextSecureIdentifier:(NSString *)textSecureIdentifier
{ {
self = [super initWithUniqueId:textSecureIdentifier]; self = [super initWithUniqueId:textSecureIdentifier];
@ -184,17 +154,19 @@ NS_ASSUME_NONNULL_BEGIN
return; return;
} }
NSMutableOrderedSet *updatedDevices = [self.devices mutableCopy]; NSMutableOrderedSet *updatedDevices = (self.devices
? [self.devices mutableCopy]
: [NSMutableOrderedSet new]);
[updatedDevices unionSet:set]; [updatedDevices unionSet:set];
self.devices = [updatedDevices copy]; self.devices = [updatedDevices copy];
} }
- (void)removeDevices:(NSSet *)set - (void)removeDevices:(NSSet *)set
{ {
NSMutableOrderedSet *updatedDevices = [self.devices mutableCopy]; NSMutableOrderedSet *updatedDevices = (self.devices
? [self.devices mutableCopy]
: [NSMutableOrderedSet new]);
[updatedDevices minusSet:set]; [updatedDevices minusSet:set];
self.devices = [updatedDevices copy]; self.devices = [updatedDevices copy];
} }
@ -230,7 +202,7 @@ NS_ASSUME_NONNULL_BEGIN
return (instance && !instance.mayBeUnregistered); return (instance && !instance.mayBeUnregistered);
} }
+ (void)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction + (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
OWSAssert(transaction); OWSAssert(transaction);
OWSAssert(recipientId.length > 0); OWSAssert(recipientId.length > 0);
@ -242,13 +214,30 @@ NS_ASSUME_NONNULL_BEGIN
instance = [[self alloc] initWithTextSecureIdentifier:recipientId]; instance = [[self alloc] initWithTextSecureIdentifier:recipientId];
[instance saveWithTransaction:transaction]; [instance saveWithTransaction:transaction];
return; } else if (instance.mayBeUnregistered) {
instance.mayBeUnregistered = NO;
[instance saveWithTransaction:transaction];
} }
if (!instance.mayBeUnregistered) { return instance;
return; }
+ (void)markAccountAsRegistered:(NSString *)recipientId
deviceId:(UInt32)deviceId
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
OWSAssert(recipientId.length > 0);
SignalRecipient *recipient = [self markAccountAsRegistered: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:transaction];
} }
instance.mayBeUnregistered = NO;
[instance saveWithTransaction:transaction];
} }
+ (void)markAccountAsNotRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction + (void)markAccountAsNotRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction
@ -267,15 +256,6 @@ NS_ASSUME_NONNULL_BEGIN
[instance saveWithTransaction:transaction]; [instance saveWithTransaction:transaction];
} }
- (void)markAccountAsNotRegisteredWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
self.mayBeUnregistered = YES;
[SignalRecipient markAccountAsNotRegistered:self.recipientId transaction:transaction];
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

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

@ -716,7 +716,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return; return;
} }
[recipient markAccountAsNotRegisteredWithTransaction:transaction]; [SignalRecipient markAccountAsNotRegistered:recipient.recipientId
transaction:transaction];
[[TSInfoMessage userNotRegisteredMessageInThread:thread recipientId:recipient.recipientId] [[TSInfoMessage userNotRegisteredMessageInThread:thread recipientId:recipient.recipientId]
saveWithTransaction:transaction]; saveWithTransaction:transaction];

Loading…
Cancel
Save