Streamline SignalRecipient.

pull/1/head
Matthew Chen 7 years ago
parent b6489c6948
commit 77884913d8

@ -6,7 +6,14 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
// We hang the "known device list" for signal accounts on this entity. // 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 @interface SignalRecipient : TSYapDatabaseObject
@property (nonatomic, readonly) NSOrderedSet *devices; @property (nonatomic, readonly) NSOrderedSet *devices;
@ -20,14 +27,15 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)getOrCreatedUnsavedRecipientForRecipientId:(NSString *)recipientId + (instancetype)getOrCreatedUnsavedRecipientForRecipientId:(NSString *)recipientId
transaction:(YapDatabaseReadTransaction *)transaction; transaction:(YapDatabaseReadTransaction *)transaction;
- (void)addDevices:(NSSet *)set; - (void)addDevicesToRegisteredRecipient:(NSSet *)devices
- (void)removeDevices:(NSSet *)set; transaction:(YapDatabaseReadWriteTransaction *)transaction;
- (void)removeDevicesFromRegisteredRecipient:(NSSet *)devices
transaction:(YapDatabaseReadWriteTransaction *)transaction;
- (NSString *)recipientId; - (NSString *)recipientId;
- (NSComparisonResult)compare:(SignalRecipient *)other; - (NSComparisonResult)compare:(SignalRecipient *)other;
// TODO: Replace with cache of known signal account ids.
+ (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction; + (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction;
+ (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction; + (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction;

@ -10,8 +10,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface SignalRecipient () @interface SignalRecipient ()
@property (nonatomic) BOOL mayBeUnregistered;
@property (nonatomic) NSOrderedSet *devices; @property (nonatomic) NSOrderedSet *devices;
@end @end
@ -96,12 +94,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(transaction); OWSAssert(transaction);
OWSAssert(recipientId.length > 0); OWSAssert(recipientId.length > 0);
SignalRecipient *_Nullable instance = [self recipientForRecipientId:recipientId transaction:transaction]; return [self recipientForRecipientId:recipientId transaction:transaction];
if (instance && !instance.mayBeUnregistered) {
return instance;
} else {
return nil;
}
} }
+ (nullable instancetype)recipientForRecipientId:(NSString *)recipientId + (nullable instancetype)recipientForRecipientId:(NSString *)recipientId
@ -134,9 +127,11 @@ NS_ASSUME_NONNULL_BEGIN
return myself; 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__); OWSFail(@"%@ in %s adding self as recipient device", self.logTag, __PRETTY_FUNCTION__);
return; return;
} }
@ -144,19 +139,45 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableOrderedSet *updatedDevices = (self.devices NSMutableOrderedSet *updatedDevices = (self.devices
? [self.devices mutableCopy] ? [self.devices mutableCopy]
: [NSMutableOrderedSet new]); : [NSMutableOrderedSet new]);
[updatedDevices unionSet:set]; [updatedDevices unionSet:devices];
self.devices = [updatedDevices copy]; self.devices = [updatedDevices copy];
} }
- (void)removeDevices:(NSSet *)set - (void)removeDevices:(NSSet *)devices
{ {
OWSAssert(devices.count > 0);
NSMutableOrderedSet *updatedDevices = (self.devices NSMutableOrderedSet *updatedDevices = (self.devices
? [self.devices mutableCopy] ? [self.devices mutableCopy]
: [NSMutableOrderedSet new]); : [NSMutableOrderedSet new]);
[updatedDevices minusSet:set]; [updatedDevices minusSet:devices];
self.devices = [updatedDevices copy]; self.devices = [updatedDevices copy];
} }
- (void)addDevicesToRegisteredRecipient:(NSSet *)devices transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
OWSAssert(devices.count > 0);
[self addDevices:devices];
SignalRecipient *latest = [SignalRecipient markAccountAsRegistered:self.recipientId transaction:transaction];
[latest addDevices:devices];
[latest saveWithTransaction:transaction];
}
- (void)removeDevicesFromRegisteredRecipient:(NSSet *)devices transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(transaction);
OWSAssert(devices.count > 0);
[self removeDevices:devices];
SignalRecipient *latest = [SignalRecipient markAccountAsRegistered:self.recipientId transaction:transaction];
[latest removeDevices:devices];
[latest saveWithTransaction:transaction];
}
- (NSString *)recipientId - (NSString *)recipientId
{ {
return self.uniqueId; return self.uniqueId;
@ -174,19 +195,10 @@ NS_ASSUME_NONNULL_BEGIN
DDLogVerbose(@"%@ saved signal recipient: %@", self.logTag, self.recipientId); DDLogVerbose(@"%@ saved signal recipient: %@", self.logTag, self.recipientId);
} }
+ (BOOL)isRegisteredSignalAccount:(NSString *)recipientId
{
__block BOOL result;
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
result = [self isRegisteredSignalAccount:recipientId transaction:transaction];
}];
return result;
}
+ (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction + (BOOL)isRegisteredSignalAccount:(NSString *)recipientId transaction:(YapDatabaseReadTransaction *)transaction
{ {
SignalRecipient *_Nullable instance = [self recipientForRecipientId:recipientId transaction:transaction]; SignalRecipient *_Nullable instance = [self recipientForRecipientId:recipientId transaction:transaction];
return (instance && !instance.mayBeUnregistered); return instance != nil;
} }
+ (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction + (SignalRecipient *)markAccountAsRegistered:(NSString *)recipientId transaction:(YapDatabaseReadWriteTransaction *)transaction
@ -201,9 +213,6 @@ NS_ASSUME_NONNULL_BEGIN
instance = [[self alloc] initWithTextSecureIdentifier:recipientId]; instance = [[self alloc] initWithTextSecureIdentifier:recipientId];
[instance saveWithTransaction:transaction]; [instance saveWithTransaction:transaction];
} else if (instance.mayBeUnregistered) {
instance.mayBeUnregistered = NO;
[instance saveWithTransaction:transaction];
} }
return instance; return instance;
} }
@ -236,11 +245,7 @@ NS_ASSUME_NONNULL_BEGIN
if (!instance) { if (!instance) {
return; return;
} }
if (instance.mayBeUnregistered) { [instance removeWithTransaction:transaction];
return;
}
instance.mayBeUnregistered = YES;
[instance saveWithTransaction:transaction];
} }
@end @end

@ -77,7 +77,7 @@ void AssertIsOnSendingQueue()
messageSender:(OWSMessageSender *)messageSender messageSender:(OWSMessageSender *)messageSender
dbConnection:(YapDatabaseConnection *)dbConnection dbConnection:(YapDatabaseConnection *)dbConnection
success:(void (^)(void))aSuccessHandler success:(void (^)(void))aSuccessHandler
failure:(void (^)(NSError *_Nonnull error))aFailureHandler NS_DESIGNATED_INITIALIZER; failure:(void (^)(NSError * error))aFailureHandler NS_DESIGNATED_INITIALIZER;
@end @end
@ -99,7 +99,7 @@ void AssertIsOnSendingQueue()
@property (nonatomic, readonly) OWSMessageSender *messageSender; @property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; @property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@property (nonatomic, readonly) void (^successHandler)(void); @property (nonatomic, readonly) void (^successHandler)(void);
@property (nonatomic, readonly) void (^failureHandler)(NSError *_Nonnull error); @property (nonatomic, readonly) void (^failureHandler)(NSError * error);
@end @end
@ -111,7 +111,7 @@ void AssertIsOnSendingQueue()
messageSender:(OWSMessageSender *)messageSender messageSender:(OWSMessageSender *)messageSender
dbConnection:(YapDatabaseConnection *)dbConnection dbConnection:(YapDatabaseConnection *)dbConnection
success:(void (^)(void))successHandler success:(void (^)(void))successHandler
failure:(void (^)(NSError *_Nonnull error))failureHandler failure:(void (^)(NSError * error))failureHandler
{ {
self = [super init]; self = [super init];
if (!self) { if (!self) {
@ -151,7 +151,7 @@ void AssertIsOnSendingQueue()
// Sanity check preconditions // Sanity check preconditions
if (self.message.hasAttachments) { if (self.message.hasAttachments) {
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * transaction) {
TSAttachmentStream *attachmentStream TSAttachmentStream *attachmentStream
= (TSAttachmentStream *)[self.message attachmentWithTransaction:transaction]; = (TSAttachmentStream *)[self.message attachmentWithTransaction:transaction];
OWSAssert(attachmentStream); OWSAssert(attachmentStream);
@ -1157,7 +1157,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} }
[self.dbConnection [self.dbConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) {
if (extraDevices.count < 1 && missingDevices.count < 1) { if (extraDevices.count < 1 && missingDevices.count < 1) {
OWSProdFail([OWSAnalyticsEvents messageSenderErrorNoMissingOrExtraDevices]); OWSProdFail([OWSAnalyticsEvents messageSenderErrorNoMissingOrExtraDevices]);
} }
@ -1170,16 +1170,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
protocolContext:transaction]; protocolContext:transaction];
} }
[recipient removeDevices:[NSSet setWithArray:extraDevices]]; [recipient removeDevicesFromRegisteredRecipient:[NSSet setWithArray:extraDevices]
transaction:transaction];
} }
if (missingDevices && missingDevices.count > 0) { if (missingDevices && missingDevices.count > 0) {
DDLogInfo(@"%@ Adding missing devices: %@", self.logTag, missingDevices); 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), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
completionHandler(); completionHandler();
}); });
@ -1271,7 +1271,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
} }
} @catch (NSException *exception) { } @catch (NSException *exception) {
if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) { if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) {
[recipient removeDevices:[NSSet setWithObject:deviceNumber]]; [self.dbConnection
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) {
[recipient removeDevicesFromRegisteredRecipient:[NSSet setWithObject:deviceNumber]
transaction:transaction];
}];
} else { } else {
@throw exception; @throw exception;
} }

Loading…
Cancel
Save