Add protocol context to protocol kit.

pull/1/head
Matthew Chen 7 years ago
parent 39e353503f
commit 218bb15ea7

@ -27,7 +27,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString *)threadIdFromGroupId:(NSData *)groupId; + (NSString *)threadIdFromGroupId:(NSData *)groupId;
// all group threads containing recipient as a member // all group threads containing recipient as a member
+ (NSArray<TSGroupThread *> *)groupThreadsWithRecipientId:(NSString *)recipientId; + (NSArray<TSGroupThread *> *)groupThreadsWithRecipientId:(NSString *)recipientId
transaction:(YapDatabaseReadWriteTransaction *)transaction;
- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream; - (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream;
- (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream - (void)updateAvatarWithAttachmentStream:(TSAttachmentStream *)attachmentStream

@ -144,27 +144,21 @@ NS_ASSUME_NONNULL_BEGIN
return [groupMemberIds copy]; return [groupMemberIds copy];
} }
// Group and Contact threads share a collection, this is a convenient way to enumerate *just* the group threads
+ (void)enumerateGroupThreadsUsingBlock:(void (^)(TSGroupThread *groupThread, BOOL *stop))block
{
[self enumerateCollectionObjectsUsingBlock:^(id obj, BOOL *stop) {
if ([obj isKindOfClass:[TSGroupThread class]]) {
block((TSGroupThread *)obj, stop);
}
}];
}
// @returns all threads to which the recipient is a member. // @returns all threads to which the recipient is a member.
// //
// @note If this becomes a hotspot we can extract into a YapDB View. // @note If this becomes a hotspot we can extract into a YapDB View.
// As is, the number of groups should be small (dozens, *maybe* hundreds), and we only enumerate them upon SN changes. // As is, the number of groups should be small (dozens, *maybe* hundreds), and we only enumerate them upon SN changes.
+ (NSArray<TSGroupThread *> *)groupThreadsWithRecipientId:(NSString *)recipientId + (NSArray<TSGroupThread *> *)groupThreadsWithRecipientId:(NSString *)recipientId
{ transaction:(YapDatabaseReadWriteTransaction *)transaction {
NSMutableArray<TSGroupThread *> *groupThreads = [NSMutableArray new]; NSMutableArray<TSGroupThread *> *groupThreads = [NSMutableArray new];
[self enumerateGroupThreadsUsingBlock:^(TSGroupThread *_Nonnull groupThread, BOOL *_Nonnull stop) { [self enumerateCollectionObjectsWithTransaction:transaction usingBlock:^(id obj, BOOL *stop) {
if ([groupThread.groupModel.groupMemberIds containsObject:recipientId]) { if ([obj isKindOfClass:[TSGroupThread class]]) {
[groupThreads addObject:groupThread]; TSGroupThread *groupThread = (TSGroupThread *)obj;
if ([groupThread.groupModel.groupMemberIds containsObject:recipientId]) {
[groupThreads addObject:groupThread];
}
} }
}]; }];

@ -471,7 +471,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
[TSErrorMessage nonblockingIdentityChangeInThread:contactThread recipientId:recipientId]; [TSErrorMessage nonblockingIdentityChangeInThread:contactThread recipientId:recipientId];
[messages addObject:errorMessage]; [messages addObject:errorMessage];
for (TSGroupThread *groupThread in [TSGroupThread groupThreadsWithRecipientId:recipientId]) { for (TSGroupThread *groupThread in [TSGroupThread groupThreadsWithRecipientId:recipientId transaction:transaction]) {
[messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]]; [messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]];
} }
@ -564,7 +564,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
}); });
} }
// TODO: Keep converting.
- (void)sendSyncVerificationStateMessage:(OWSVerificationStateSyncMessage *)message - (void)sendSyncVerificationStateMessage:(OWSVerificationStateSyncMessage *)message
{ {
OWSAssert(message); OWSAssert(message);
@ -585,7 +584,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
DDLogInfo(@"%@ Successfully sent verification state sync message", self.logTag); DDLogInfo(@"%@ Successfully sent verification state sync message", self.logTag);
// Record that this verification state was successfully synced. // Record that this verification state was successfully synced.
[self clearSyncMessageForRecipientId:message.verificationForRecipientId]; [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) {
[self clearSyncMessageForRecipientId:message.verificationForRecipientId transaction:transaction];
}];
} }
failure:^(NSError *error) { failure:^(NSError *error) {
DDLogError(@"%@ Failed to send verification state sync message with error: %@", self.logTag, error); DDLogError(@"%@ Failed to send verification state sync message with error: %@", self.logTag, error);
@ -598,12 +599,13 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
self.logTag, self.logTag,
message.verificationForRecipientId); message.verificationForRecipientId);
// Otherwise this will fail forever. // Otherwise this will fail forever.
[self clearSyncMessageForRecipientId:message.verificationForRecipientId]; [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) {
[self clearSyncMessageForRecipientId:message.verificationForRecipientId transaction:transaction];
}];
} }
}]; }];
} }
// TODO: Change signature of this method.
- (void)clearSyncMessageForRecipientId:(NSString *)recipientId - (void)clearSyncMessageForRecipientId:(NSString *)recipientId
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
@ -630,25 +632,29 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
NSData *identityKey = [rawIdentityKey removeKeyType]; NSData *identityKey = [rawIdentityKey removeKeyType];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
switch (verified.state) { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * transaction) {
case OWSSignalServiceProtosVerifiedStateDefault: switch (verified.state) {
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault case OWSSignalServiceProtosVerifiedStateDefault:
recipientId:recipientId [self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
identityKey:identityKey recipientId:recipientId
overwriteOnConflict:NO]; identityKey:identityKey
break; overwriteOnConflict:NO
case OWSSignalServiceProtosVerifiedStateVerified: transaction:transaction];
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified break;
recipientId:recipientId case OWSSignalServiceProtosVerifiedStateVerified:
identityKey:identityKey [self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
overwriteOnConflict:YES]; recipientId:recipientId
break; identityKey:identityKey
case OWSSignalServiceProtosVerifiedStateUnverified: overwriteOnConflict:YES
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.", transaction:transaction];
recipientId, break;
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified)); case OWSSignalServiceProtosVerifiedStateUnverified:
return; OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
} recipientId,
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
return;
}
}];
[self fireIdentityStateChangeNotification]; [self fireIdentityStateChangeNotification];
}); });
} }
@ -657,7 +663,11 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
recipientId:(NSString *)recipientId recipientId:(NSString *)recipientId
identityKey:(NSData *)identityKey identityKey:(NSData *)identityKey
overwriteOnConflict:(BOOL)overwriteOnConflict overwriteOnConflict:(BOOL)overwriteOnConflict
transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
OWSAssert(recipientId.length > 0);
OWSAssert(transaction);
if (recipientId.length < 1) { if (recipientId.length < 1) {
OWSFail(@"Verification state sync message missing recipientId."); OWSFail(@"Verification state sync message missing recipientId.");
return; return;
@ -668,103 +678,105 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
return; return;
} }
@synchronized(self) OWSRecipientIdentity *_Nullable recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId
{ transaction:transaction];
OWSRecipientIdentity *_Nullable recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId]; if (!recipientIdentity) {
if (!recipientIdentity) { // There's no existing recipient identity for this recipient.
// There's no existing recipient identity for this recipient. // We should probably create one.
// We should probably create one.
if (verificationState == OWSVerificationStateDefault) {
if (verificationState == OWSVerificationStateDefault) { // There's no point in creating a new recipient identity just to
// There's no point in creating a new recipient identity just to // set its verification state to default.
// set its verification state to default. return;
}
// Ensure a remote identity exists for this key. We may be learning about
// it for the first time.
[self saveRemoteIdentity:identityKey recipientId:recipientId protocolContext:transaction];
recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId
transaction:transaction];
if (recipientIdentity == nil) {
OWSFail(@"Missing expected identity: %@", recipientId);
return;
}
if (![recipientIdentity.recipientId isEqualToString:recipientId]) {
OWSFail(@"recipientIdentity has unexpected recipientId: %@", recipientId);
return;
}
if (![recipientIdentity.identityKey isEqualToData:identityKey]) {
OWSFail(@"recipientIdentity has unexpected identityKey: %@", recipientId);
return;
}
if (recipientIdentity.verificationState == verificationState) {
return;
}
DDLogInfo(@"%@ setVerificationState: %@ (%@ -> %@)",
self.logTag,
recipientId,
OWSVerificationStateToString(recipientIdentity.verificationState),
OWSVerificationStateToString(verificationState));
[recipientIdentity updateWithVerificationState:verificationState
transaction:transaction];
// No need to call [saveChangeMessagesForRecipientId:..] since this is
// a new recipient.
} else {
// There's an existing recipient identity for this recipient.
// We should update it.
if (![recipientIdentity.recipientId isEqualToString:recipientId]) {
OWSFail(@"recipientIdentity has unexpected recipientId: %@", recipientId);
return;
}
if (![recipientIdentity.identityKey isEqualToData:identityKey]) {
// The conflict case where we receive a verification sync message
// whose identity key disagrees with the local identity key for
// this recipient.
if (!overwriteOnConflict) {
DDLogWarn(@"recipientIdentity has non-matching identityKey: %@", recipientId);
return; return;
} }
// Ensure a remote identity exists for this key. We may be learning about DDLogWarn(@"recipientIdentity has non-matching identityKey; overwriting: %@", recipientId);
// it for the first time. [self saveRemoteIdentity:identityKey recipientId:recipientId protocolContext:transaction];
[self saveRemoteIdentity:identityKey recipientId:recipientId protocolContext:protocolContext];
recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId
recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId]; transaction:transaction];
if (recipientIdentity == nil) { if (recipientIdentity == nil) {
OWSFail(@"Missing expected identity: %@", recipientId); OWSFail(@"Missing expected identity: %@", recipientId);
return; return;
} }
if (![recipientIdentity.recipientId isEqualToString:recipientId]) { if (![recipientIdentity.recipientId isEqualToString:recipientId]) {
OWSFail(@"recipientIdentity has unexpected recipientId: %@", recipientId); OWSFail(@"recipientIdentity has unexpected recipientId: %@", recipientId);
return; return;
} }
if (![recipientIdentity.identityKey isEqualToData:identityKey]) { if (![recipientIdentity.identityKey isEqualToData:identityKey]) {
OWSFail(@"recipientIdentity has unexpected identityKey: %@", recipientId); OWSFail(@"recipientIdentity has unexpected identityKey: %@", recipientId);
return; return;
} }
if (recipientIdentity.verificationState == verificationState) {
return;
}
DDLogInfo(@"%@ setVerificationState: %@ (%@ -> %@)",
self.logTag,
recipientId,
OWSVerificationStateToString(recipientIdentity.verificationState),
OWSVerificationStateToString(verificationState));
[recipientIdentity updateWithVerificationState:verificationState];
// No need to call [saveChangeMessagesForRecipientId:..] since this is
// a new recipient.
} else {
// There's an existing recipient identity for this recipient.
// We should update it.
if (![recipientIdentity.recipientId isEqualToString:recipientId]) {
OWSFail(@"recipientIdentity has unexpected recipientId: %@", recipientId);
return;
}
if (![recipientIdentity.identityKey isEqualToData:identityKey]) {
// The conflict case where we receive a verification sync message
// whose identity key disagrees with the local identity key for
// this recipient.
if (!overwriteOnConflict) {
DDLogWarn(@"recipientIdentity has non-matching identityKey: %@", recipientId);
return;
}
DDLogWarn(@"recipientIdentity has non-matching identityKey; overwriting: %@", recipientId);
[self saveRemoteIdentity:identityKey recipientId:recipientId protocolContext:protocolContext];
recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId];
if (recipientIdentity == nil) {
OWSFail(@"Missing expected identity: %@", recipientId);
return;
}
if (![recipientIdentity.recipientId isEqualToString:recipientId]) {
OWSFail(@"recipientIdentity has unexpected recipientId: %@", recipientId);
return;
}
if (![recipientIdentity.identityKey isEqualToData:identityKey]) {
OWSFail(@"recipientIdentity has unexpected identityKey: %@", recipientId);
return;
}
}
if (recipientIdentity.verificationState == verificationState) {
return;
}
[recipientIdentity updateWithVerificationState:verificationState];
[self saveChangeMessagesForRecipientId:recipientId
verificationState:verificationState
isLocalChange:NO
transaction:transaction];
} }
if (recipientIdentity.verificationState == verificationState) {
return;
}
[recipientIdentity updateWithVerificationState:verificationState
transaction:transaction];
[self saveChangeMessagesForRecipientId:recipientId
verificationState:verificationState
isLocalChange:NO
transaction:transaction];
} }
} }

Loading…
Cancel
Save