WIP: adapt to verification proto changes

// FREEBIE
This commit is contained in:
Michael Kirk 2017-06-21 20:19:23 -04:00
parent f526a372c9
commit 48b3f498a9
5 changed files with 172 additions and 139 deletions

View file

@ -9,12 +9,15 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSVerificationStateSyncMessage : OWSOutgoingSyncMessage
- (void)addVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId;
- (instancetype)initWithVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
verificationForRecipientId:(NSString *)recipientId;
// Returns the list of recipient ids referenced in this message.
- (NSArray<NSString *> *)recipientIds;
//// Returns the list of recipient ids referenced in this message.
//- (NSArray<NSString *> *)recipientIds;
// This is a clunky name, but we want to differentiate it from `recipientIdentifier` inherited from `TSOutgoingMessage`
@property (nonatomic, readonly) NSString *verificationForRecipientId;
@end

View file

@ -9,99 +9,125 @@
NS_ASSUME_NONNULL_BEGIN
@interface OWSVerificationStateTuple : NSObject
@property (nonatomic) OWSVerificationState verificationState;
@property (nonatomic) NSData *identityKey;
@property (nonatomic) NSString *recipientId;
@end
#pragma mark -
@implementation OWSVerificationStateTuple
@end
//@interface OWSVerificationStateTuple : NSObject
//
//@property (nonatomic) OWSVerificationState verificationState;
//@property (nonatomic) NSData *identityKey;
//@property (nonatomic) NSString *recipientId;
//
//@end
//
//#pragma mark -
//
//@implementation OWSVerificationStateTuple
//
//@end
#pragma mark -
@interface OWSVerificationStateSyncMessage ()
@property (nonatomic, readonly) NSMutableArray<OWSVerificationStateTuple *> *tuples;
//@property (nonatomic, readonly) NSMutableArray<OWSVerificationStateTuple *> *tuples;
@property (nonatomic, readonly) OWSVerificationState verificationState;
@property (nonatomic, readonly) NSData *identityKey;
@end
#pragma mark -
@implementation OWSVerificationStateSyncMessage
//
//- (instancetype)init
//{
// self = [super init];
// if (!self) {
// return self;
// }
//
// _tuples = [NSMutableArray new];
//
// return self;
//}
- (instancetype)init
- (instancetype)initWithVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
verificationForRecipientId:(NSString *)verificationForRecipientId
{
OWSAssert(identityKey.length == kIdentityKeyLength);
OWSAssert(verificationForRecipientId.length > 0);
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
// will figure that out on it's own.
OWSAssert(verificationState != OWSVerificationStateNoLongerVerified);
self = [super init];
if (!self) {
return self;
}
_tuples = [NSMutableArray new];
_verificationState = verificationState;
_identityKey = identityKey;
_verificationForRecipientId = verificationForRecipientId;
return self;
}
- (void)addVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId
{
OWSAssert(identityKey.length == kIdentityKeyLength);
OWSAssert(recipientId.length > 0);
OWSAssert(self.tuples);
OWSVerificationStateTuple *tuple = [OWSVerificationStateTuple new];
tuple.verificationState = verificationState;
tuple.identityKey = identityKey;
tuple.recipientId = recipientId;
[self.tuples addObject:tuple];
}
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
OWSAssert(self.tuples.count > 0);
// OWSAssert(self.tuples.count > 0);
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
for (OWSVerificationStateTuple *tuple in self.tuples) {
OWSSignalServiceProtosSyncMessageVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosSyncMessageVerifiedBuilder new];
verifiedBuilder.destination = tuple.recipientId;
verifiedBuilder.identityKey = tuple.identityKey;
switch (tuple.verificationState) {
// for (OWSVerificationStateTuple *tuple in self.tuples) {
// OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
// verifiedBuilder.destination = tuple.recipientId;
// verifiedBuilder.identityKey = tuple.identityKey;
// switch (tuple.verificationState) {
// case OWSVerificationStateDefault:
// verifiedBuilder.state = OWSSignalServiceProtosVerifiedStateDefault;
// break;
// case OWSVerificationStateVerified:
// verifiedBuilder.state = OWSSignalServiceProtosVerifiedStateVerified;
// break;
// case OWSVerificationStateNoLongerVerified:
// verifiedBuilder.state = OWSSignalServiceProtosVerifiedStateUnverified;
// break;
// }
// [syncMessageBuilder addVerified:[verifiedBuilder build]];
// }
//
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
verifiedBuilder.destination = self.verificationForRecipientId;
verifiedBuilder.identityKey = self.identityKey;
verifiedBuilder.state = ^{
switch (self.verificationState) {
case OWSVerificationStateDefault:
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateDefault;
break;
return OWSSignalServiceProtosVerifiedStateDefault;
case OWSVerificationStateVerified:
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateVerified;
break;
return OWSSignalServiceProtosVerifiedStateVerified;
case OWSVerificationStateNoLongerVerified:
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateUnverified;
break;
return OWSSignalServiceProtosVerifiedStateUnverified;
}
[syncMessageBuilder addVerified:[verifiedBuilder build]];
}
}();
// Add 1-512 bytes of random padding bytes.
size_t paddingLengthBytes = arc4random_uniform(512) + 1;
[syncMessageBuilder setPadding:[Cryptography generateRandomBytes:paddingLengthBytes]];
syncMessageBuilder.padding = [Cryptography generateRandomBytes:paddingLengthBytes];
return [syncMessageBuilder build];
}
- (NSArray<NSString *> *)recipientIds
{
NSMutableArray<NSString *> *result = [NSMutableArray new];
for (OWSVerificationStateTuple *tuple in self.tuples) {
OWSAssert(tuple.recipientId.length > 0);
[result addObject:tuple.recipientId];
}
return [result copy];
}
//- (NSArray<NSString *> *)recipientIds
//{
// NSMutableArray<NSString *> *result = [NSMutableArray new];
// for (OWSVerificationStateTuple *tuple in self.tuples) {
// OWSAssert(tuple.recipientId.length > 0);
// [result addObject:tuple.recipientId];
// }
//
// return [result copy];
//}
@end

View file

@ -17,7 +17,7 @@ extern NSString *const kNSNotificationName_IdentityStateDidChange;
extern const NSUInteger kIdentityKeyLength;
@class OWSRecipientIdentity;
@class OWSSignalServiceProtosSyncMessageVerified;
@class OWSSignalServiceProtosVerified;
// This class can be safely accessed and used from any thread.
@interface OWSIdentityManager : NSObject <IdentityKeyStore>
@ -49,7 +49,7 @@ extern const NSUInteger kIdentityKeyLength;
// Will try to send a sync message with all verification states.
- (void)syncAllVerificationStates;
- (void)processIncomingSyncMessage:(NSArray<OWSSignalServiceProtosSyncMessageVerified *> *)verifieds;
- (void)processIncomingSyncMessage:(OWSSignalServiceProtosVerified *)verified;
@end

View file

@ -455,7 +455,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
}];
}];
OWSVerificationStateSyncMessage *message = [OWSVerificationStateSyncMessage new];
NSMutableArray<OWSVerificationStateSyncMessage *> *messages = [NSMutableArray new];
for (NSString *recipientId in recipientIds) {
OWSRecipientIdentity *recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId];
if (!recipientIdentity) {
@ -483,13 +483,17 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
recipientId);
continue;
}
[message addVerificationState:recipientIdentity.verificationState
identityKey:identityKey
recipientId:recipientId];
OWSVerificationStateSyncMessage *message = [[OWSVerificationStateSyncMessage alloc]
initWithVerificationState:recipientIdentity.verificationState
identityKey:identityKey
verificationForRecipientId:recipientIdentity.recipientId];
[messages addObject:message];
}
if (message.recipientIds.count > 0) {
if (messages.count > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
[self sendSyncVerificationStateMessage:message];
for (OWSVerificationStateSyncMessage *message in messages) {
[self sendSyncVerificationStateMessage:message];
}
});
}
}
@ -501,8 +505,8 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
OWSVerificationStateSyncMessage *message =
[OWSVerificationStateSyncMessage new];
NSMutableArray<OWSVerificationStateSyncMessage *> *messages = [NSMutableArray new];
[OWSRecipientIdentity enumerateCollectionObjectsUsingBlock:^(OWSRecipientIdentity *recipientIdentity, BOOL *stop) {
OWSAssert(recipientIdentity);
OWSAssert(recipientIdentity.recipientId.length > 0);
@ -523,13 +527,17 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
return;
}
[message addVerificationState:recipientIdentity.verificationState
identityKey:identityKey
recipientId:recipientIdentity.recipientId];
OWSVerificationStateSyncMessage *message = [[OWSVerificationStateSyncMessage alloc]
initWithVerificationState:recipientIdentity.verificationState
identityKey:identityKey
verificationForRecipientId:recipientIdentity.recipientId];
[messages addObject:message];
}];
if (message.recipientIds.count > 0) {
if (messages.count > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
[self sendSyncVerificationStateMessage:message];
for (OWSVerificationStateSyncMessage *message in messages) {
[self sendSyncVerificationStateMessage:message];
}
});
}
}
@ -539,7 +547,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
- (void)sendSyncVerificationStateMessage:(OWSVerificationStateSyncMessage *)message
{
OWSAssert(message);
OWSAssert(message.recipientIds.count > 0);
OWSAssert(message.verificationForRecipientId.length > 0);
OWSAssert([NSThread isMainThread]);
[self.messageSender sendMessage:message
@ -547,7 +555,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
// Record that this verification state was successfully synced.
[self clearSyncMessageForRecipientIds:message.recipientIds];
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
@ -557,66 +565,62 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
- (void)clearSyncMessageForRecipientId:(NSString *)recipientId
{
OWSAssert(recipientId.length > 0);
[self clearSyncMessageForRecipientIds:@[recipientId]];
//
// [self clearSyncMessageForRecipientIds:@[recipientId]];
//}
//
//- (void)clearSyncMessageForRecipientIds:(NSArray<NSString *> *)recipientIds
//{
// OWSAssert(recipientIds.count > 0);
//
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// @synchronized(self)
// {
// for (NSString *recipientId in recipientIds) {
[self.storageManager removeObjectForKey:recipientId
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
// }
// }
// });
}
- (void)clearSyncMessageForRecipientIds:(NSArray<NSString *> *)recipientIds
- (void)processIncomingSyncMessage:(OWSSignalServiceProtosVerified *)verified
{
OWSAssert(recipientIds.count > 0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
for (NSString *recipientId in recipientIds) {
[self.storageManager removeObjectForKey:recipientId
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
}
}
});
}
NSString *recipientId = verified.destination;
if (recipientId.length < 1) {
OWSFail(@"Verification state sync message missing recipientId.");
return;
}
NSData *rawIdentityKey = verified.identityKey;
if (rawIdentityKey.length != kIdentityKeyLength) {
OWSFail(@"Verification state sync message for recipient: %@ with malformed identityKey: %@",
recipientId,
rawIdentityKey);
return;
}
NSData *identityKey = [rawIdentityKey removeKeyType];
- (void)processIncomingSyncMessage:(NSArray<OWSSignalServiceProtosSyncMessageVerified *> *)verifieds
{
for (OWSSignalServiceProtosSyncMessageVerified *verified in verifieds) {
NSString *recipientId = verified.destination;
if (recipientId.length < 1) {
OWSFail(@"Verification state sync message missing recipientId.");
continue;
}
NSData *rawIdentityKey = verified.identityKey;
if (rawIdentityKey.length != kIdentityKeyLength) {
OWSFail(@"Verification state sync message for recipient: %@ with malformed identityKey: %@",
switch (verified.state) {
case OWSSignalServiceProtosVerifiedStateDefault:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:NO];
break;
case OWSSignalServiceProtosVerifiedStateVerified:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:YES];
break;
case OWSSignalServiceProtosVerifiedStateUnverified:
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
recipientId,
rawIdentityKey);
continue;
}
NSData *identityKey = [rawIdentityKey removeKeyType];
switch (verified.state) {
case OWSSignalServiceProtosSyncMessageVerifiedStateDefault:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:NO];
break;
case OWSSignalServiceProtosSyncMessageVerifiedStateVerified:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:YES];
break;
case OWSSignalServiceProtosSyncMessageVerifiedStateUnverified:
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
recipientId,
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
continue;
}
}
if (verifieds.count > 0) {
[self fireIdentityStateChangeNotification];
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
return;
}
[self fireIdentityStateChangeNotification];
}
- (void)tryToApplyVerificationStateFromSyncMessage:(OWSVerificationState)verificationState

View file

@ -219,8 +219,9 @@ NS_ASSUME_NONNULL_BEGIN
[description appendString:@"Blocked"];
} else if (syncMessage.read.count > 0) {
[description appendString:@"ReadReceipt"];
} else if (syncMessage.verified.count > 0){
NSString *verifiedString = [NSString stringWithFormat:@"Verifications: (%lu)", (unsigned long)syncMessage.verified.count];
} else if (syncMessage.hasVerified) {
NSString *verifiedString =
[NSString stringWithFormat:@"Verification for: %@", syncMessage.verified.destination];
[description appendString:verifiedString];
} else {
// Shouldn't happen
@ -687,9 +688,8 @@ NS_ASSUME_NONNULL_BEGIN
[[OWSReadReceiptsProcessor alloc] initWithReadReceiptProtos:syncMessage.read
storageManager:self.storageManager];
[readReceiptsProcessor process];
} else if (syncMessage.verified.count > 0) {
DDLogInfo(@"%@ Received %ld verification state(s)", self.tag, (u_long)syncMessage.verified.count);
} else if (syncMessage.hasVerified) {
DDLogInfo(@"%@ Received verification state for %@", self.tag, syncMessage.verified.destination);
[[OWSIdentityManager sharedManager] processIncomingSyncMessage:syncMessage.verified];
} else {
DDLogWarn(@"%@ Ignoring unsupported sync message.", self.tag);