Respond to CR.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 46f17a02cb
commit 993df25f3f

@ -59,8 +59,8 @@ NSString *const OWSReadReceiptsProcessorMarkedMessageAsReadNotification =
- (instancetype)initWithIncomingMessage:(TSIncomingMessage *)message storageManager:(TSStorageManager *)storageManager
{
// Only groupthread sets authorId, thus this crappy code.
// TODO ALL incoming messages should have an authorId.
// authorId isn't set on all legacy messages, so we take
// extra measures to ensure we obtain a valid value.
NSString *messageAuthorId;
if (message.authorId) { // Group Thread
messageAuthorId = message.authorId;

@ -1,5 +1,6 @@
// Created by Michael Kirk on 9/24/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSSendReadReceiptsJob.h"
#import "OWSMessageSender.h"
@ -41,8 +42,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)runWith:(TSIncomingMessage *)message
{
// Only groupthread sets authorId, thus this crappy code.
// TODO Refactor so that ALL incoming messages have an authorId.
// authorId isn't set on all legacy messages, so we take
// extra measures to ensure we obtain a valid value.
NSString *messageAuthorId;
if (message.authorId) { // Group Thread
messageAuthorId = message.authorId;

@ -92,8 +92,8 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
if ([interaction isKindOfClass:[TSIncomingMessage class]]) {
TSIncomingMessage *message = (TSIncomingMessage *)interaction;
// Only groupthread sets authorId, thus this crappy code.
// TODO ALL incoming messages should have an authorId.
// authorId isn't set on all legacy messages, so we take
// extra measures to ensure we obtain a valid value.
NSString *messageAuthorId;
if (message.authorId) { // Group Thread
messageAuthorId = message.authorId;

@ -3,6 +3,7 @@
//
#import "OWSBatchMessageProcessor.h"
#import "NSArray+OWS.h"
#import "OWSSignalServiceProtos.pb.h"
#import "TSDatabaseView.h"
#import "TSMessagesManager.h"
@ -19,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
@class OWSSignalServiceProtosEnvelope;
@interface OWSBatchMessageProcessingJob : TSYapDatabaseObject
@interface OWSMessageContentJob : TSYapDatabaseObject
@property (nonatomic, readonly) NSDate *createdAt;
@ -32,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
@interface OWSBatchMessageProcessingJob ()
@interface OWSMessageContentJob ()
@property (nonatomic, readonly) NSData *envelopeData;
@property (nonatomic, readonly, nullable) NSData *plaintextData;
@ -41,7 +42,12 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
@implementation OWSBatchMessageProcessingJob
@implementation OWSMessageContentJob
+ (NSString *)collection
{
return @"OWSBatchMessageProcessingJob";
}
- (instancetype)initWithEnvelopeData:(NSData *)envelopeData plaintextData:(NSData *_Nullable)plaintextData
{
@ -68,20 +74,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Finder
NSString *const OWSBatchMessageProcessingJobFinderExtensionName = @"OWSBatchMessageProcessingJobFinderExtensionName";
NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMessageProcessingJobFinderExtensionGroup";
@interface OWSBatchMessageProcessingJobFinder : NSObject
NSString *const OWSMessageContentJobFinderExtensionName = @"OWSBatchMessageProcessingFinderExtensionName";
NSString *const OWSMessageContentJobFinderExtensionGroup = @"OWSBatchMessageProcessingFinderExtensionGroup";
- (NSArray<OWSBatchMessageProcessingJob *> *)nextJobsForBatchSize:(NSUInteger)maxBatchSize;
- (void)addJobWithEnvelopeData:(NSData *)envelopeData plaintextData:(NSData *_Nullable)plaintextData;
- (void)removeJobWithId:(NSString *)uniqueId;
@interface OWSMessageContentJobFinder : NSObject
@end
#pragma mark -
@interface OWSBatchMessageProcessingJobFinder ()
@interface OWSMessageContentJobFinder ()
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@ -89,7 +91,7 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
#pragma mark -
@implementation OWSBatchMessageProcessingJobFinder
@implementation OWSMessageContentJobFinder
- (instancetype)initWithDBConnection:(YapDatabaseConnection *)dbConnection
{
@ -105,50 +107,41 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
return self;
}
- (NSArray<OWSBatchMessageProcessingJob *> *)nextJobsForBatchSize:(NSUInteger)maxBatchSize
- (NSArray<OWSMessageContentJob *> *)nextJobsForBatchSize:(NSUInteger)maxBatchSize
{
NSMutableArray<OWSBatchMessageProcessingJob *> *jobs = [NSMutableArray new];
NSMutableArray<OWSMessageContentJob *> *jobs = [NSMutableArray new];
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
YapDatabaseViewTransaction *viewTransaction = [transaction ext:OWSBatchMessageProcessingJobFinderExtensionName];
YapDatabaseViewTransaction *viewTransaction = [transaction ext:OWSMessageContentJobFinderExtensionName];
OWSAssert(viewTransaction != nil);
NSMutableArray<NSString *> *jobIds = [NSMutableArray new];
[viewTransaction enumerateKeysInGroup:OWSBatchMessageProcessingJobFinderExtensionGroup
usingBlock:^(NSString *_Nonnull collection,
NSString *_Nonnull key,
NSUInteger index,
BOOL *_Nonnull stop) {
[jobIds addObject:key];
if (jobIds.count >= maxBatchSize) {
*stop = YES;
}
}];
for (NSString *jobId in jobIds) {
OWSBatchMessageProcessingJob *_Nullable job =
[OWSBatchMessageProcessingJob fetchObjectWithUniqueID:jobId transaction:transaction];
if (job) {
[jobs addObject:job];
} else {
OWSFail(@"Could not load job: %@", jobId);
}
}
[viewTransaction enumerateKeysAndObjectsInGroup:OWSMessageContentJobFinderExtensionGroup
usingBlock:^(NSString *_Nonnull collection,
NSString *_Nonnull key,
id _Nonnull object,
NSUInteger index,
BOOL *_Nonnull stop) {
OWSMessageContentJob *job = object;
[jobs addObject:job];
if (jobs.count >= maxBatchSize) {
*stop = YES;
}
}];
}];
return jobs;
return [jobs copy];
}
- (void)addJobWithEnvelopeData:(NSData *)envelopeData plaintextData:(NSData *_Nullable)plaintextData
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[[[OWSBatchMessageProcessingJob alloc] initWithEnvelopeData:envelopeData plaintextData:plaintextData]
[[[OWSMessageContentJob alloc] initWithEnvelopeData:envelopeData plaintextData:plaintextData]
saveWithTransaction:transaction];
}];
}
- (void)removeJobWithId:(NSString *)uniqueId
- (void)removeJobsWithIds:(NSArray<NSString *> *)uniqueIds
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeObjectForKey:uniqueId inCollection:[OWSBatchMessageProcessingJob collection]];
[transaction removeObjectsForKeys:uniqueIds inCollection:[OWSMessageContentJob collection]];
}];
}
@ -164,17 +157,17 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
NSString *key2,
id object2) {
if (![object1 isKindOfClass:[OWSBatchMessageProcessingJob class]]) {
if (![object1 isKindOfClass:[OWSMessageContentJob class]]) {
OWSFail(@"Unexpected object: %@ in collection: %@", [object1 class], collection1);
return NSOrderedSame;
}
OWSBatchMessageProcessingJob *job1 = (OWSBatchMessageProcessingJob *)object1;
OWSMessageContentJob *job1 = (OWSMessageContentJob *)object1;
if (![object2 isKindOfClass:[OWSBatchMessageProcessingJob class]]) {
if (![object2 isKindOfClass:[OWSMessageContentJob class]]) {
OWSFail(@"Unexpected object: %@ in collection: %@", [object2 class], collection2);
return NSOrderedSame;
}
OWSBatchMessageProcessingJob *job2 = (OWSBatchMessageProcessingJob *)object2;
OWSMessageContentJob *job2 = (OWSMessageContentJob *)object2;
return [job1.createdAt compare:job2.createdAt];
}];
@ -184,18 +177,18 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
NSString *_Nonnull collection,
NSString *_Nonnull key,
id _Nonnull object) {
if (![object isKindOfClass:[OWSBatchMessageProcessingJob class]]) {
if (![object isKindOfClass:[OWSMessageContentJob class]]) {
OWSFail(@"Unexpected object: %@ in collection: %@", object, collection);
return nil;
}
// Arbitrary string - all in the same group. We're only using the view for sorting.
return OWSBatchMessageProcessingJobFinderExtensionGroup;
return OWSMessageContentJobFinderExtensionGroup;
}];
YapDatabaseViewOptions *options = [YapDatabaseViewOptions new];
options.allowedCollections = [[YapWhitelistBlacklist alloc]
initWithWhitelist:[NSSet setWithObject:[OWSBatchMessageProcessingJob collection]]];
options.allowedCollections =
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[OWSMessageContentJob collection]]];
return [[YapDatabaseView alloc] initWithGrouping:grouping sorting:sorting versionTag:@"1" options:options];
}
@ -203,40 +196,40 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
+ (void)syncRegisterDatabaseExtension:(YapDatabase *)database
{
YapDatabaseView *existingView = [database registeredExtension:OWSBatchMessageProcessingJobFinderExtensionName];
YapDatabaseView *existingView = [database registeredExtension:OWSMessageContentJobFinderExtensionName];
if (existingView) {
OWSFail(@"%@ was already initialized.", OWSBatchMessageProcessingJobFinderExtensionName);
OWSFail(@"%@ was already initialized.", OWSMessageContentJobFinderExtensionName);
// already initialized
return;
}
[database registerExtension:[self databaseExtension] withName:OWSBatchMessageProcessingJobFinderExtensionName];
[database registerExtension:[self databaseExtension] withName:OWSMessageContentJobFinderExtensionName];
}
@end
#pragma mark - Queue Processing
@interface OWSBatchMessageProcessingQueue : NSObject
@interface OWSMessageContentQueue : NSObject
@property (nonatomic, readonly) TSMessagesManager *messagesManager;
@property (nonatomic, readonly) YapDatabaseConnection *dbReadWriteConnection;
@property (nonatomic, readonly) OWSBatchMessageProcessingJobFinder *finder;
@property (nonatomic, readonly) OWSMessageContentJobFinder *finder;
@property (nonatomic) BOOL isDrainingQueue;
- (instancetype)initWithMessagesManager:(TSMessagesManager *)messagesManager
storageManager:(TSStorageManager *)storageManager
finder:(OWSBatchMessageProcessingJobFinder *)finder NS_DESIGNATED_INITIALIZER;
finder:(OWSMessageContentJobFinder *)finder NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
#pragma mark -
@implementation OWSBatchMessageProcessingQueue
@implementation OWSMessageContentQueue
- (instancetype)initWithMessagesManager:(TSMessagesManager *)messagesManager
storageManager:(TSStorageManager *)storageManager
finder:(OWSBatchMessageProcessingJobFinder *)finder
finder:(OWSMessageContentJobFinder *)finder
{
OWSSingletonAssert();
@ -299,7 +292,7 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
{
AssertIsOnMainThread();
NSArray<OWSBatchMessageProcessingJob *> *jobs = [self.finder nextJobsForBatchSize:kIncomingMessageBatchSize];
NSArray<OWSMessageContentJob *> *jobs = [self.finder nextJobsForBatchSize:kIncomingMessageBatchSize];
OWSAssert(jobs);
if (jobs.count < 1) {
self.isDrainingQueue = NO;
@ -310,23 +303,22 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
[self processJobs:jobs
completion:^{
dispatch_async(dispatch_get_main_queue(), ^{
for (OWSBatchMessageProcessingJob *job in jobs) {
[self.finder removeJobWithId:job.uniqueId];
}
[self.finder removeJobsWithIds:jobs.uniqueIds];
DDLogVerbose(@"%@ completed %zd jobs. %zd jobs left.",
self.tag,
jobs.count,
[OWSBatchMessageProcessingJob numberOfKeysInCollection]);
[OWSMessageContentJob numberOfKeysInCollection]);
[self drainQueueWorkStep];
});
}];
}
- (void)processJobs:(NSArray<OWSBatchMessageProcessingJob *> *)jobs completion:(void (^)())completion
- (void)processJobs:(NSArray<OWSMessageContentJob *> *)jobs completion:(void (^)())completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (OWSBatchMessageProcessingJob *job in jobs) {
for (OWSMessageContentJob *job in jobs) {
[self.messagesManager processEnvelope:job.envelopeProto
plaintextData:job.plaintextData
transaction:transaction];
@ -354,7 +346,7 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
@interface OWSBatchMessageProcessor ()
@property (nonatomic, readonly) OWSBatchMessageProcessingQueue *processingQueue;
@property (nonatomic, readonly) OWSMessageContentQueue *processingQueue;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@end
@ -374,12 +366,10 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
return self;
}
OWSBatchMessageProcessingJobFinder *finder =
[[OWSBatchMessageProcessingJobFinder alloc] initWithDBConnection:dbConnection];
OWSBatchMessageProcessingQueue *processingQueue =
[[OWSBatchMessageProcessingQueue alloc] initWithMessagesManager:messagesManager
storageManager:storageManager
finder:finder];
OWSMessageContentJobFinder *finder = [[OWSMessageContentJobFinder alloc] initWithDBConnection:dbConnection];
OWSMessageContentQueue *processingQueue = [[OWSMessageContentQueue alloc] initWithMessagesManager:messagesManager
storageManager:storageManager
finder:finder];
_processingQueue = processingQueue;
@ -412,7 +402,7 @@ NSString *const OWSBatchMessageProcessingJobFinderExtensionGroup = @"OWSBatchMes
+ (void)syncRegisterDatabaseExtension:(YapDatabase *)database
{
[OWSBatchMessageProcessingJobFinder syncRegisterDatabaseExtension:database];
[OWSMessageContentJobFinder syncRegisterDatabaseExtension:database];
}
#pragma mark - instance methods

@ -23,6 +23,8 @@ extern NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange;
- (NSArray<NSString *> *)blockedPhoneNumbers;
- (BOOL)isRecipientIdBlocked:(NSString *)recipientId;
@end
NS_ASSUME_NONNULL_END

@ -161,6 +161,11 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
}
}
- (BOOL)isRecipientIdBlocked:(NSString *)recipientId
{
return [self.blockedPhoneNumbers containsObject:recipientId];
}
// This should be called every time the block list changes.
- (void)handleUpdate

@ -3,6 +3,7 @@
//
#import "OWSMessageReceiver.h"
#import "NSArray+OWS.h"
#import "OWSBatchMessageProcessor.h"
#import "OWSSignalServiceProtos.pb.h"
#import "TSDatabaseView.h"
@ -20,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
@class OWSSignalServiceProtosEnvelope;
@interface OWSMessageProcessingJob : TSYapDatabaseObject
@interface OWSMessageDecryptJob : TSYapDatabaseObject
@property (nonatomic, readonly) NSDate *createdAt;
@ -32,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
@interface OWSMessageProcessingJob ()
@interface OWSMessageDecryptJob ()
@property (nonatomic, readonly) NSData *envelopeData;
@ -40,7 +41,12 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
@implementation OWSMessageProcessingJob
@implementation OWSMessageDecryptJob
+ (NSString *)collection
{
return @"OWSMessageProcessingJob";
}
- (instancetype)initWithEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
{
@ -66,20 +72,16 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Finder
NSString *const OWSMessageProcessingJobFinderExtensionName = @"OWSMessageProcessingJobFinderExtensionName";
NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProcessingJobFinderExtensionGroup";
NSString *const OWSMessageDecryptJobFinderExtensionName = @"OWSMessageProcessingJobFinderExtensionName";
NSString *const OWSMessageDecryptJobFinderExtensionGroup = @"OWSMessageProcessingJobFinderExtensionGroup";
@interface OWSMessageProcessingJobFinder : NSObject
- (NSArray<OWSMessageProcessingJob *> *)nextJobsForBatchSize:(NSUInteger)maxBatchSize;
- (void)addJobForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope;
- (void)removeJobWithId:(NSString *)uniqueId;
@interface OWSMessageDecryptJobFinder : NSObject
@end
#pragma mark -
@interface OWSMessageProcessingJobFinder ()
@interface OWSMessageDecryptJobFinder ()
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@ -87,7 +89,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
#pragma mark -
@implementation OWSMessageProcessingJobFinder
@implementation OWSMessageDecryptJobFinder
- (instancetype)initWithDBConnection:(YapDatabaseConnection *)dbConnection
{
@ -103,49 +105,40 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
return self;
}
- (NSArray<OWSMessageProcessingJob *> *)nextJobsForBatchSize:(NSUInteger)maxBatchSize
- (NSArray<OWSMessageDecryptJob *> *)nextJobsForBatchSize:(NSUInteger)maxBatchSize
{
NSMutableArray<OWSMessageProcessingJob *> *jobs = [NSMutableArray new];
NSMutableArray<OWSMessageDecryptJob *> *jobs = [NSMutableArray new];
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
YapDatabaseViewTransaction *viewTransaction = [transaction ext:OWSMessageProcessingJobFinderExtensionName];
YapDatabaseViewTransaction *viewTransaction = [transaction ext:OWSMessageDecryptJobFinderExtensionName];
OWSAssert(viewTransaction != nil);
NSMutableArray<NSString *> *jobIds = [NSMutableArray new];
[viewTransaction enumerateKeysInGroup:OWSMessageProcessingJobFinderExtensionGroup
usingBlock:^(NSString *_Nonnull collection,
NSString *_Nonnull key,
NSUInteger index,
BOOL *_Nonnull stop) {
[jobIds addObject:key];
if (jobIds.count >= maxBatchSize) {
*stop = YES;
}
}];
for (NSString *jobId in jobIds) {
OWSMessageProcessingJob *_Nullable job =
[OWSMessageProcessingJob fetchObjectWithUniqueID:jobId transaction:transaction];
if (job) {
[jobs addObject:job];
} else {
OWSFail(@"Could not load job: %@", jobId);
}
}
[viewTransaction enumerateKeysAndObjectsInGroup:OWSMessageDecryptJobFinderExtensionGroup
usingBlock:^(NSString *_Nonnull collection,
NSString *_Nonnull key,
id _Nonnull object,
NSUInteger index,
BOOL *_Nonnull stop) {
OWSMessageDecryptJob *job = object;
[jobs addObject:job];
if (jobs.count >= maxBatchSize) {
*stop = YES;
}
}];
}];
return jobs;
return [jobs copy];
}
- (void)addJobForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[[[OWSMessageProcessingJob alloc] initWithEnvelope:envelope] saveWithTransaction:transaction];
[[[OWSMessageDecryptJob alloc] initWithEnvelope:envelope] saveWithTransaction:transaction];
}];
}
- (void)removeJobWithId:(NSString *)uniqueId
- (void)removeJobsWithIds:(NSArray<NSString *> *)uniqueIds
{
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeObjectForKey:uniqueId inCollection:[OWSMessageProcessingJob collection]];
[transaction removeObjectsForKeys:uniqueIds inCollection:[OWSMessageDecryptJob collection]];
}];
}
@ -161,17 +154,17 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
NSString *key2,
id object2) {
if (![object1 isKindOfClass:[OWSMessageProcessingJob class]]) {
if (![object1 isKindOfClass:[OWSMessageDecryptJob class]]) {
OWSFail(@"Unexpected object: %@ in collection: %@", [object1 class], collection1);
return NSOrderedSame;
}
OWSMessageProcessingJob *job1 = (OWSMessageProcessingJob *)object1;
OWSMessageDecryptJob *job1 = (OWSMessageDecryptJob *)object1;
if (![object2 isKindOfClass:[OWSMessageProcessingJob class]]) {
if (![object2 isKindOfClass:[OWSMessageDecryptJob class]]) {
OWSFail(@"Unexpected object: %@ in collection: %@", [object2 class], collection2);
return NSOrderedSame;
}
OWSMessageProcessingJob *job2 = (OWSMessageProcessingJob *)object2;
OWSMessageDecryptJob *job2 = (OWSMessageDecryptJob *)object2;
return [job1.createdAt compare:job2.createdAt];
}];
@ -181,18 +174,18 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
NSString *_Nonnull collection,
NSString *_Nonnull key,
id _Nonnull object) {
if (![object isKindOfClass:[OWSMessageProcessingJob class]]) {
if (![object isKindOfClass:[OWSMessageDecryptJob class]]) {
OWSFail(@"Unexpected object: %@ in collection: %@", object, collection);
return nil;
}
// Arbitrary string - all in the same group. We're only using the view for sorting.
return OWSMessageProcessingJobFinderExtensionGroup;
return OWSMessageDecryptJobFinderExtensionGroup;
}];
YapDatabaseViewOptions *options = [YapDatabaseViewOptions new];
options.allowedCollections =
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[OWSMessageProcessingJob collection]]];
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[OWSMessageDecryptJob collection]]];
return [[YapDatabaseView alloc] initWithGrouping:grouping sorting:sorting versionTag:@"1" options:options];
}
@ -200,40 +193,40 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
+ (void)syncRegisterDatabaseExtension:(YapDatabase *)database
{
YapDatabaseView *existingView = [database registeredExtension:OWSMessageProcessingJobFinderExtensionName];
YapDatabaseView *existingView = [database registeredExtension:OWSMessageDecryptJobFinderExtensionName];
if (existingView) {
OWSFail(@"%@ was already initialized.", OWSMessageProcessingJobFinderExtensionName);
OWSFail(@"%@ was already initialized.", OWSMessageDecryptJobFinderExtensionName);
// already initialized
return;
}
[database registerExtension:[self databaseExtension] withName:OWSMessageProcessingJobFinderExtensionName];
[database registerExtension:[self databaseExtension] withName:OWSMessageDecryptJobFinderExtensionName];
}
@end
#pragma mark - Queue Processing
@interface OWSMessageProcessingQueue : NSObject
@interface OWSMessageDecryptQueue : NSObject
@property (nonatomic, readonly) TSMessagesManager *messagesManager;
@property (nonatomic, readonly) OWSBatchMessageProcessor *batchMessageProcessor;
@property (nonatomic, readonly) OWSMessageProcessingJobFinder *finder;
@property (nonatomic, readonly) OWSMessageDecryptJobFinder *finder;
@property (nonatomic) BOOL isDrainingQueue;
- (instancetype)initWithMessagesManager:(TSMessagesManager *)messagesManager
batchMessageProcessor:(OWSBatchMessageProcessor *)batchMessageProcessor
finder:(OWSMessageProcessingJobFinder *)finder NS_DESIGNATED_INITIALIZER;
finder:(OWSMessageDecryptJobFinder *)finder NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
#pragma mark -
@implementation OWSMessageProcessingQueue
@implementation OWSMessageDecryptQueue
- (instancetype)initWithMessagesManager:(TSMessagesManager *)messagesManager
batchMessageProcessor:(OWSBatchMessageProcessor *)batchMessageProcessor
finder:(OWSMessageProcessingJobFinder *)finder
finder:(OWSMessageDecryptJobFinder *)finder
{
OWSSingletonAssert();
@ -294,7 +287,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
{
AssertIsOnMainThread();
NSArray<OWSMessageProcessingJob *> *jobs = [self.finder nextJobsForBatchSize:kIncomingMessageBatchSize];
NSArray<OWSMessageDecryptJob *> *jobs = [self.finder nextJobsForBatchSize:kIncomingMessageBatchSize];
OWSAssert(jobs);
if (jobs.count < 1) {
self.isDrainingQueue = NO;
@ -305,19 +298,17 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
[self processJobs:jobs
completion:^{
dispatch_async(dispatch_get_main_queue(), ^{
for (OWSMessageProcessingJob *job in jobs) {
[self.finder removeJobWithId:job.uniqueId];
}
[self.finder removeJobsWithIds:jobs.uniqueIds];
DDLogVerbose(@"%@ completed %zd jobs. %zd jobs left.",
self.tag,
jobs.count,
[OWSMessageProcessingJob numberOfKeysInCollection]);
[OWSMessageDecryptJob numberOfKeysInCollection]);
[self drainQueueWorkStep];
});
}];
}
- (void)processJobs:(NSArray<OWSMessageProcessingJob *> *)jobs completion:(void (^)())completion
- (void)processJobs:(NSArray<OWSMessageDecryptJob *> *)jobs completion:(void (^)())completion
{
[self processJobs:jobs
unprocessedJobs:[jobs mutableCopy]
@ -325,8 +316,8 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
completion:completion];
}
- (void)processJobs:(NSArray<OWSMessageProcessingJob *> *)jobs
unprocessedJobs:(NSMutableArray<OWSMessageProcessingJob *> *)unprocessedJobs
- (void)processJobs:(NSArray<OWSMessageDecryptJob *> *)jobs
unprocessedJobs:(NSMutableArray<OWSMessageDecryptJob *> *)unprocessedJobs
plaintextDataMap:(NSMutableDictionary<NSString *, NSData *> *)plaintextDataMap
completion:(void (^)())completion
{
@ -334,7 +325,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
OWSAssert(unprocessedJobs.count <= jobs.count);
if (unprocessedJobs.count < 1) {
for (OWSMessageProcessingJob *job in jobs) {
for (OWSMessageDecryptJob *job in jobs) {
NSData *_Nullable plaintextData = plaintextDataMap[job.uniqueId];
[self.batchMessageProcessor enqueueEnvelopeData:job.envelopeData plaintextData:plaintextData];
}
@ -344,7 +335,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OWSAssert(unprocessedJobs.count > 0);
OWSMessageProcessingJob *job = unprocessedJobs.firstObject;
OWSMessageDecryptJob *job = unprocessedJobs.firstObject;
[unprocessedJobs removeObjectAtIndex:0];
[self.messagesManager decryptEnvelope:job.envelopeProto
successBlock:^(NSData *_Nullable plaintextData) {
@ -383,7 +374,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
@interface OWSMessageReceiver ()
@property (nonatomic, readonly) OWSMessageProcessingQueue *processingQueue;
@property (nonatomic, readonly) OWSMessageDecryptQueue *processingQueue;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@end
@ -403,11 +394,11 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
return self;
}
OWSMessageProcessingJobFinder *finder = [[OWSMessageProcessingJobFinder alloc] initWithDBConnection:dbConnection];
OWSMessageProcessingQueue *processingQueue =
[[OWSMessageProcessingQueue alloc] initWithMessagesManager:messagesManager
batchMessageProcessor:batchMessageProcessor
finder:finder];
OWSMessageDecryptJobFinder *finder = [[OWSMessageDecryptJobFinder alloc] initWithDBConnection:dbConnection];
OWSMessageDecryptQueue *processingQueue =
[[OWSMessageDecryptQueue alloc] initWithMessagesManager:messagesManager
batchMessageProcessor:batchMessageProcessor
finder:finder];
_processingQueue = processingQueue;
@ -442,7 +433,7 @@ NSString *const OWSMessageProcessingJobFinderExtensionGroup = @"OWSMessageProces
+ (void)syncRegisterDatabaseExtension:(YapDatabase *)database
{
[OWSMessageProcessingJobFinder syncRegisterDatabaseExtension:database];
[OWSMessageDecryptJobFinder syncRegisterDatabaseExtension:database];
}
#pragma mark - instance methods

@ -65,6 +65,7 @@ NS_SWIFT_NAME(MessageSender)
* Send and resend text messages or resend messages with existing attachments.
* If you haven't yet created the attachment, see the `sendAttachmentData:` variants.
*/
// TODO: make transaction nonnull and remove `sendMessage:success:failure`
- (void)sendMessage:(TSOutgoingMessage *)message
success:(void (^)())successHandler
failure:(void (^)(NSError *error))failureHandler;

@ -636,8 +636,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// you might, for example, have a pending outgoing message when
// you block them.
OWSAssert(recipientContactId.length > 0);
NSArray<NSString *> *blockedPhoneNumbers = _blockingManager.blockedPhoneNumbers;
if ([blockedPhoneNumbers containsObject:recipientContactId]) {
if ([_blockingManager isRecipientIdBlocked:recipientContactId]) {
DDLogInfo(@"%@ skipping 1:1 send to blocked contact: %@", self.tag, recipientContactId);
NSError *error = OWSErrorMakeMessageSendFailedToBlockListError();
// No need to retry - the user will continue to be blocked.

@ -275,7 +275,7 @@ const NSUInteger kIncomingMessageBatchSize = 10;
{
OWSAssert(envelope);
return [_blockingManager.blockedPhoneNumbers containsObject:envelope.source];
return [_blockingManager isRecipientIdBlocked:envelope.source];
}
#pragma mark - Decryption
@ -375,9 +375,6 @@ const NSUInteger kIncomingMessageBatchSize = 10;
[self decryptEnvelope:envelope
messageTypeName:@"Secure Message"
missingPayloadBlock:^{
OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]);
}
cipherMessageBlock:^(NSData *encryptedData) {
return [[WhisperMessage alloc] initWithData:encryptedData];
}
@ -398,9 +395,6 @@ const NSUInteger kIncomingMessageBatchSize = 10;
[self decryptEnvelope:envelope
messageTypeName:@"PreKey Bundle"
missingPayloadBlock:^{
OWSProdFail([OWSAnalyticsEvents messageManagerErrorPrekeyBundleEnvelopeHasNoContent]);
}
cipherMessageBlock:^(NSData *encryptedData) {
return [[PreKeyWhisperMessage alloc] initWithData:encryptedData];
}
@ -410,26 +404,24 @@ const NSUInteger kIncomingMessageBatchSize = 10;
- (void)decryptEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
messageTypeName:(NSString *)messageTypeName
missingPayloadBlock:(void (^_Nonnull)())missingPayloadBlock
cipherMessageBlock:(id<CipherMessage> (^_Nonnull)(NSData *))cipherMessageBlock
successBlock:(DecryptSuccessBlock)successBlock
failureBlock:(void (^)(NSError *_Nullable error))failureBlock
{
OWSAssert(envelope);
OWSAssert(messageTypeName.length > 0);
OWSAssert(missingPayloadBlock);
OWSAssert(cipherMessageBlock);
OWSAssert(successBlock);
OWSAssert(failureBlock);
TSStorageManager *storageManager = [TSStorageManager sharedManager];
TSStorageManager *storageManager = self.storageManager;
NSString *recipientId = envelope.source;
int deviceId = envelope.sourceDevice;
// DEPRECATED - Remove after all clients have been upgraded.
NSData *encryptedData = envelope.hasContent ? envelope.content : envelope.legacyMessage;
if (!encryptedData) {
missingPayloadBlock();
OWSProdFail([OWSAnalyticsEvents messageManagerErrorMessageEnvelopeHasNoContent]);
failureBlock(nil);
return;
}
@ -468,7 +460,7 @@ const NSUInteger kIncomingMessageBatchSize = 10;
OWSAssert(transaction);
OWSAssert([TSAccountManager isRegistered]);
DDLogInfo(@"%@ received envelope: %@", self.tag, [self descriptionForEnvelope:envelope]);
DDLogInfo(@"%@ handling decrypted envelope: %@", self.tag, [self descriptionForEnvelope:envelope]);
OWSAssert(envelope.source.length > 0);
OWSAssert(![self isEnvelopeBlocked:envelope]);
@ -510,6 +502,8 @@ const NSUInteger kIncomingMessageBatchSize = 10;
if ([interaction isKindOfClass:[TSOutgoingMessage class]]) {
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)interaction;
[outgoingMessage updateWithWasDeliveredWithTransaction:transaction];
} else {
OWSFail(@"%@ Unexpected message with timestamp: %llu", self.tag, envelope.timestamp);
}
}
@ -653,7 +647,9 @@ const NSUInteger kIncomingMessageBatchSize = 10;
[self.profileManager setProfileKeyData:profileKey forRecipientId:recipientId];
}
// TODO: Should we do this synchronously?
// By dispatching async, we introduce the possibility that these messages might be lost
// if the app exits before this block is executed. This is fine, since the call by
// definition will end if the app exits.
dispatch_async(dispatch_get_main_queue(), ^{
if (callMessage.hasOffer) {
[self.callMessageHandler receivedOffer:callMessage.offer fromCallerId:envelope.source];
@ -801,7 +797,7 @@ const NSUInteger kIncomingMessageBatchSize = 10;
TSGroupThread *groupThread =
[TSGroupThread getOrCreateThreadWithGroupIdData:syncMessage.sent.message.group.id
transaction:transaction];
[groupThread updateAvatarWithAttachmentStream:attachmentStream transaction:transaction];
[groupThread updateAvatarWithAttachmentStream:attachmentStream];
}
transaction:transaction];
} else {
@ -844,6 +840,7 @@ const NSUInteger kIncomingMessageBatchSize = 10;
DDLogWarn(@"%@ ignoring unsupported sync request message", self.tag);
}
} else if (syncMessage.hasBlocked) {
// TODO: Do this synchronously.
dispatch_async(dispatch_get_main_queue(), ^{
NSArray<NSString *> *blockedPhoneNumbers = [syncMessage.blocked.numbers copy];
[_blockingManager setBlockedPhoneNumbers:blockedPhoneNumbers sendSyncMessage:NO];
@ -857,6 +854,7 @@ const NSUInteger kIncomingMessageBatchSize = 10;
[readReceiptsProcessor processWithTransaction:transaction];
} else if (syncMessage.hasVerified) {
DDLogInfo(@"%@ Received verification state for %@", self.tag, syncMessage.verified.destination);
// TODO: Do this synchronously.
dispatch_async(dispatch_get_main_queue(), ^{
[self.identityManager processIncomingSyncMessage:syncMessage.verified];
});
@ -875,14 +873,12 @@ const NSUInteger kIncomingMessageBatchSize = 10;
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
if (thread) { // TODO thread should always be nonnull.
[[[TSInfoMessage alloc] initWithTimestamp:envelope.timestamp
inThread:thread
messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction];
}
[[[TSInfoMessage alloc] initWithTimestamp:envelope.timestamp
inThread:thread
messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction];
dispatch_async([OWSDispatch sessionStoreQueue], ^{
[[TSStorageManager sharedManager] deleteAllSessionsForContact:envelope.source];
[self.storageManager deleteAllSessionsForContact:envelope.source];
});
}
@ -1186,6 +1182,7 @@ const NSUInteger kIncomingMessageBatchSize = 10;
}
if (thread && incomingMessage) {
// TODO: Do this synchronously.
dispatch_async(dispatch_get_main_queue(), ^{
// In case we already have a read receipt for this new message (happens sometimes).
OWSReadReceiptsProcessor *readReceiptsProcessor =

@ -0,0 +1,13 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@interface NSArray (OWS)
- (NSArray<NSString *> *)uniqueIds;
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,25 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "NSArray+OWS.h"
#import "TSYapDatabaseObject.h"
NS_ASSUME_NONNULL_BEGIN
@implementation NSArray (OWS)
- (NSArray<NSString *> *)uniqueIds
{
NSMutableArray<NSString *> *result = [NSMutableArray new];
for (id object in self) {
OWSAssert([object isKindOfClass:[TSYapDatabaseObject class]]);
TSYapDatabaseObject *dbObject = object;
[result addObject:dbObject.uniqueId];
}
return result;
}
@end
NS_ASSUME_NONNULL_END

@ -126,8 +126,6 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString *)messageManagerErrorOversizeMessage;
+ (NSString *)messageManagerErrorPrekeyBundleEnvelopeHasNoContent;
+ (NSString *)messageManagerErrorSyncMessageFromUnknownSource;
+ (NSString *)messageManagerErrorUntrustedIdentityKeyException;

@ -297,11 +297,6 @@ NS_ASSUME_NONNULL_BEGIN
return @"message_manager_error_oversize_message";
}
+ (NSString *)messageManagerErrorPrekeyBundleEnvelopeHasNoContent
{
return @"message_manager_error_prekey_bundle_envelope_has_no_content";
}
+ (NSString *)messageManagerErrorSyncMessageFromUnknownSource
{
return @"message_manager_error_sync_message_from_unknown_source";

Loading…
Cancel
Save