2017-01-24 21:47:41 +01:00
|
|
|
//
|
2018-01-11 15:56:38 +01:00
|
|
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
2017-01-24 21:47:41 +01:00
|
|
|
//
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2017-09-14 17:00:30 +02:00
|
|
|
#import "OWSMessageManager.h"
|
2017-11-29 21:27:19 +01:00
|
|
|
#import "AppContext.h"
|
2018-01-26 22:11:05 +01:00
|
|
|
#import "AppReadiness.h"
|
2016-08-26 01:01:35 +02:00
|
|
|
#import "ContactsManagerProtocol.h"
|
2017-08-28 18:03:59 +02:00
|
|
|
#import "Cryptography.h"
|
2016-08-26 01:01:35 +02:00
|
|
|
#import "MimeTypeUtil.h"
|
2017-09-22 16:30:35 +02:00
|
|
|
#import "NSDate+OWS.h"
|
2018-02-16 02:45:28 +01:00
|
|
|
#import "NSString+SSK.h"
|
2016-12-18 22:08:26 +01:00
|
|
|
#import "NotificationsProtocol.h"
|
2016-10-14 23:00:29 +02:00
|
|
|
#import "OWSAttachmentsProcessor.h"
|
2017-04-03 20:42:04 +02:00
|
|
|
#import "OWSBlockingManager.h"
|
2016-12-18 22:08:26 +01:00
|
|
|
#import "OWSCallMessageHandler.h"
|
2018-05-01 14:52:59 +02:00
|
|
|
#import "OWSContact.h"
|
2017-11-16 15:54:55 +01:00
|
|
|
#import "OWSDevice.h"
|
2016-10-05 17:42:44 +02:00
|
|
|
#import "OWSDisappearingConfigurationUpdateInfoMessage.h"
|
|
|
|
#import "OWSDisappearingMessagesConfiguration.h"
|
|
|
|
#import "OWSDisappearingMessagesJob.h"
|
2017-09-14 17:00:30 +02:00
|
|
|
#import "OWSIdentityManager.h"
|
2017-02-16 00:32:27 +01:00
|
|
|
#import "OWSIncomingMessageFinder.h"
|
2016-08-23 22:38:05 +02:00
|
|
|
#import "OWSIncomingSentMessageTranscript.h"
|
2016-10-14 23:00:29 +02:00
|
|
|
#import "OWSMessageSender.h"
|
2018-01-30 21:05:04 +01:00
|
|
|
#import "OWSMessageUtils.h"
|
2018-03-05 15:30:58 +01:00
|
|
|
#import "OWSPrimaryStorage+SessionStore.h"
|
|
|
|
#import "OWSPrimaryStorage.h"
|
2017-09-15 21:28:44 +02:00
|
|
|
#import "OWSReadReceiptManager.h"
|
2016-10-05 17:42:44 +02:00
|
|
|
#import "OWSRecordTranscriptJob.h"
|
2017-10-02 22:35:24 +02:00
|
|
|
#import "OWSSyncConfigurationMessage.h"
|
2016-08-26 01:01:35 +02:00
|
|
|
#import "OWSSyncContactsMessage.h"
|
2016-08-27 00:07:54 +02:00
|
|
|
#import "OWSSyncGroupsMessage.h"
|
2017-05-05 23:22:56 +02:00
|
|
|
#import "OWSSyncGroupsRequestMessage.h"
|
2017-08-02 19:12:26 +02:00
|
|
|
#import "ProfileManagerProtocol.h"
|
2016-04-08 09:38:34 +02:00
|
|
|
#import "TSAccountManager.h"
|
2018-04-05 18:01:53 +02:00
|
|
|
#import "TSAttachment.h"
|
|
|
|
#import "TSAttachmentPointer.h"
|
2018-04-07 02:08:17 +02:00
|
|
|
#import "TSAttachmentStream.h"
|
2016-07-28 01:58:49 +02:00
|
|
|
#import "TSContactThread.h"
|
2015-12-07 03:31:43 +01:00
|
|
|
#import "TSDatabaseView.h"
|
2016-07-28 01:58:49 +02:00
|
|
|
#import "TSGroupModel.h"
|
|
|
|
#import "TSGroupThread.h"
|
2017-09-14 17:00:30 +02:00
|
|
|
#import "TSIncomingMessage.h"
|
2015-12-07 03:31:43 +01:00
|
|
|
#import "TSInfoMessage.h"
|
2016-09-23 22:55:56 +02:00
|
|
|
#import "TSNetworkManager.h"
|
2017-09-14 17:00:30 +02:00
|
|
|
#import "TSOutgoingMessage.h"
|
2018-02-07 18:44:09 +01:00
|
|
|
#import "TSQuotedMessage.h"
|
2015-12-07 03:31:43 +01:00
|
|
|
#import "TextSecureKitEnv.h"
|
2018-06-07 07:57:59 +02:00
|
|
|
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
2017-12-19 03:42:50 +01:00
|
|
|
#import <YapDatabase/YapDatabase.h>
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2016-10-05 17:42:44 +02:00
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
2017-09-14 17:00:30 +02:00
|
|
|
@interface OWSMessageManager ()
|
2016-10-01 20:42:39 +02:00
|
|
|
|
2016-12-18 22:08:26 +01:00
|
|
|
@property (nonatomic, readonly) id<OWSCallMessageHandler> callMessageHandler;
|
2016-10-01 20:42:39 +02:00
|
|
|
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
|
2018-03-05 15:30:58 +01:00
|
|
|
@property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage;
|
2016-10-14 23:00:29 +02:00
|
|
|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
2017-02-16 00:32:27 +01:00
|
|
|
@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
|
2017-04-03 20:42:04 +02:00
|
|
|
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
2017-06-22 03:04:16 +02:00
|
|
|
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
|
2017-09-14 17:00:30 +02:00
|
|
|
@property (nonatomic, readonly) TSNetworkManager *networkManager;
|
|
|
|
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
2016-10-01 20:42:39 +02:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
2017-05-09 20:38:49 +02:00
|
|
|
#pragma mark -
|
|
|
|
|
2017-09-14 17:00:30 +02:00
|
|
|
@implementation OWSMessageManager
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2017-09-14 17:00:30 +02:00
|
|
|
+ (instancetype)sharedManager
|
|
|
|
{
|
|
|
|
static OWSMessageManager *sharedMyManager = nil;
|
2015-12-07 03:31:43 +01:00
|
|
|
static dispatch_once_t onceToken;
|
|
|
|
dispatch_once(&onceToken, ^{
|
2016-10-14 23:00:29 +02:00
|
|
|
sharedMyManager = [[self alloc] initDefault];
|
2015-12-07 03:31:43 +01:00
|
|
|
});
|
|
|
|
return sharedMyManager;
|
|
|
|
}
|
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
- (instancetype)initDefault
|
2016-09-23 22:55:56 +02:00
|
|
|
{
|
2016-10-14 23:00:29 +02:00
|
|
|
TSNetworkManager *networkManager = [TSNetworkManager sharedManager];
|
2018-03-05 15:30:58 +01:00
|
|
|
OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager];
|
2016-10-14 23:00:29 +02:00
|
|
|
id<ContactsManagerProtocol> contactsManager = [TextSecureKitEnv sharedEnv].contactsManager;
|
2016-12-18 22:08:26 +01:00
|
|
|
id<OWSCallMessageHandler> callMessageHandler = [TextSecureKitEnv sharedEnv].callMessageHandler;
|
2017-06-22 03:04:16 +02:00
|
|
|
OWSIdentityManager *identityManager = [OWSIdentityManager sharedManager];
|
2017-03-30 18:37:22 +02:00
|
|
|
OWSMessageSender *messageSender = [TextSecureKitEnv sharedEnv].messageSender;
|
2017-09-14 17:00:30 +02:00
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
|
|
|
|
return [self initWithNetworkManager:networkManager
|
2018-03-05 15:30:58 +01:00
|
|
|
primaryStorage:primaryStorage
|
2016-12-18 22:08:26 +01:00
|
|
|
callMessageHandler:callMessageHandler
|
2016-10-14 23:00:29 +02:00
|
|
|
contactsManager:contactsManager
|
2017-06-22 03:04:16 +02:00
|
|
|
identityManager:identityManager
|
2016-10-14 23:00:29 +02:00
|
|
|
messageSender:messageSender];
|
2016-09-23 22:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
|
2018-03-05 15:30:58 +01:00
|
|
|
primaryStorage:(OWSPrimaryStorage *)primaryStorage
|
2016-12-18 22:08:26 +01:00
|
|
|
callMessageHandler:(id<OWSCallMessageHandler>)callMessageHandler
|
2016-10-01 20:42:39 +02:00
|
|
|
contactsManager:(id<ContactsManagerProtocol>)contactsManager
|
2017-06-22 03:04:16 +02:00
|
|
|
identityManager:(OWSIdentityManager *)identityManager
|
2016-10-14 23:00:29 +02:00
|
|
|
messageSender:(OWSMessageSender *)messageSender
|
2016-09-23 22:55:56 +02:00
|
|
|
{
|
2015-12-07 03:31:43 +01:00
|
|
|
self = [super init];
|
|
|
|
|
2016-09-23 22:55:56 +02:00
|
|
|
if (!self) {
|
|
|
|
return self;
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-03-05 15:30:58 +01:00
|
|
|
_primaryStorage = primaryStorage;
|
2016-09-23 22:55:56 +02:00
|
|
|
_networkManager = networkManager;
|
2016-12-18 22:08:26 +01:00
|
|
|
_callMessageHandler = callMessageHandler;
|
2016-10-01 20:42:39 +02:00
|
|
|
_contactsManager = contactsManager;
|
2017-06-22 03:04:16 +02:00
|
|
|
_identityManager = identityManager;
|
2016-10-14 23:00:29 +02:00
|
|
|
_messageSender = messageSender;
|
2016-09-23 22:55:56 +02:00
|
|
|
|
2018-03-05 15:30:58 +01:00
|
|
|
_dbConnection = primaryStorage.newDatabaseConnection;
|
|
|
|
_incomingMessageFinder = [[OWSIncomingMessageFinder alloc] initWithPrimaryStorage:primaryStorage];
|
2017-04-03 20:42:04 +02:00
|
|
|
_blockingManager = [OWSBlockingManager sharedManager];
|
2017-04-01 00:36:08 +02:00
|
|
|
|
|
|
|
OWSSingletonAssert();
|
2017-12-04 18:38:44 +01:00
|
|
|
OWSAssert(CurrentAppContext().isMainApp);
|
2017-04-01 00:36:08 +02:00
|
|
|
|
2017-06-30 18:12:37 +02:00
|
|
|
[self startObserving];
|
|
|
|
|
2015-12-07 03:31:43 +01:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2017-06-30 18:12:37 +02:00
|
|
|
- (void)startObserving
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(yapDatabaseModified:)
|
|
|
|
name:YapDatabaseModifiedNotification
|
2018-03-05 15:30:58 +01:00
|
|
|
object:OWSPrimaryStorage.sharedManager.dbNotificationObject];
|
2017-11-29 17:37:49 +01:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(yapDatabaseModified:)
|
|
|
|
name:YapDatabaseModifiedExternallyNotification
|
2018-01-11 16:04:03 +01:00
|
|
|
object:nil];
|
2017-06-30 18:12:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)yapDatabaseModified:(NSNotification *)notification
|
|
|
|
{
|
2018-02-14 20:09:27 +01:00
|
|
|
if (AppReadiness.isAppReady) {
|
|
|
|
[OWSMessageUtils.sharedManager updateApplicationBadgeCount];
|
|
|
|
} else {
|
|
|
|
static dispatch_once_t onceToken;
|
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
|
[AppReadiness runNowOrWhenAppIsReady:^{
|
|
|
|
[OWSMessageUtils.sharedManager updateApplicationBadgeCount];
|
|
|
|
}];
|
|
|
|
});
|
|
|
|
}
|
2017-06-30 18:12:37 +02:00
|
|
|
}
|
|
|
|
|
2017-09-13 18:14:22 +02:00
|
|
|
#pragma mark - Blocking
|
2017-04-25 21:42:49 +02:00
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (BOOL)isEnvelopeBlocked:(SSKProtoEnvelope *)envelope
|
2016-08-22 22:09:58 +02:00
|
|
|
{
|
2017-09-13 18:14:22 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
|
2017-09-20 17:48:37 +02:00
|
|
|
return [_blockingManager isRecipientIdBlocked:envelope.source];
|
2017-09-13 18:14:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - message handling
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)processEnvelope:(SSKProtoEnvelope *)envelope
|
2017-09-13 21:35:33 +02:00
|
|
|
plaintextData:(NSData *_Nullable)plaintextData
|
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-08-22 22:09:58 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(transaction);
|
2017-09-13 18:14:22 +02:00
|
|
|
OWSAssert([TSAccountManager isRegistered]);
|
2017-11-29 21:27:19 +01:00
|
|
|
OWSAssert(CurrentAppContext().isMainApp);
|
2017-02-10 01:35:10 +01:00
|
|
|
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ handling decrypted envelope: %@", self.logTag, [self descriptionForEnvelope:envelope]);
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-02-16 02:45:28 +01:00
|
|
|
if (!envelope.source.isValidE164) {
|
|
|
|
DDLogVerbose(
|
|
|
|
@"%@ incoming envelope has invalid source: %@", self.logTag, [self descriptionForEnvelope:envelope]);
|
|
|
|
OWSFail(@"%@ incoming envelope has invalid source", self.logTag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-13 18:14:22 +02:00
|
|
|
OWSAssert(envelope.source.length > 0);
|
|
|
|
OWSAssert(![self isEnvelopeBlocked:envelope]);
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2017-09-13 18:14:22 +02:00
|
|
|
switch (envelope.type) {
|
2018-08-01 16:45:21 +02:00
|
|
|
case SSKProtoEnvelopeTypeCiphertext:
|
|
|
|
case SSKProtoEnvelopeTypePrekeyBundle:
|
2017-09-13 18:14:22 +02:00
|
|
|
if (plaintextData) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleEnvelope:envelope plaintextData:plaintextData transaction:transaction];
|
2017-09-13 18:14:22 +02:00
|
|
|
} else {
|
|
|
|
OWSFail(
|
2017-11-08 20:04:51 +01:00
|
|
|
@"%@ missing decrypted data for envelope: %@", self.logTag, [self descriptionForEnvelope:envelope]);
|
2017-01-24 21:47:41 +01:00
|
|
|
}
|
2017-09-13 18:14:22 +02:00
|
|
|
break;
|
2018-08-01 16:45:21 +02:00
|
|
|
case SSKProtoEnvelopeTypeReceipt:
|
2017-09-13 18:14:22 +02:00
|
|
|
OWSAssert(!plaintextData);
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleDeliveryReceipt:envelope transaction:transaction];
|
2017-09-13 18:14:22 +02:00
|
|
|
break;
|
2018-04-16 20:48:29 +02:00
|
|
|
// Other messages are just dismissed for now.
|
2018-08-01 16:45:21 +02:00
|
|
|
case SSKProtoEnvelopeTypeKeyExchange:
|
2017-09-13 18:14:22 +02:00
|
|
|
DDLogWarn(@"Received Key Exchange Message, not supported");
|
|
|
|
break;
|
2018-08-01 16:45:21 +02:00
|
|
|
case SSKProtoEnvelopeTypeUnknown:
|
2017-09-13 18:14:22 +02:00
|
|
|
DDLogWarn(@"Received an unknown message type");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DDLogWarn(@"Received unhandled envelope type: %d", (int)envelope.type);
|
|
|
|
break;
|
2016-12-06 03:32:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleDeliveryReceipt:(SSKProtoEnvelope *)envelope transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2017-09-13 18:14:22 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2017-09-22 23:23:09 +02:00
|
|
|
// Old-style delivery notices don't include a "delivery timestamp".
|
2017-09-27 20:19:26 +02:00
|
|
|
[self processDeliveryReceiptsFromRecipientId:envelope.source
|
|
|
|
sentTimestamps:@[
|
|
|
|
@(envelope.timestamp),
|
|
|
|
]
|
|
|
|
deliveryTimestamp:nil
|
|
|
|
transaction:transaction];
|
2017-09-22 22:40:44 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 20:19:26 +02:00
|
|
|
// deliveryTimestamp is an optional parameter, since legacy
|
|
|
|
// delivery receipts don't have a "delivery timestamp". Those
|
|
|
|
// messages repurpose the "timestamp" field to indicate when the
|
|
|
|
// corresponding message was originally sent.
|
|
|
|
- (void)processDeliveryReceiptsFromRecipientId:(NSString *)recipientId
|
|
|
|
sentTimestamps:(NSArray<NSNumber *> *)sentTimestamps
|
|
|
|
deliveryTimestamp:(NSNumber *_Nullable)deliveryTimestamp
|
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2017-09-22 22:40:44 +02:00
|
|
|
{
|
|
|
|
OWSAssert(recipientId);
|
|
|
|
OWSAssert(sentTimestamps);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
|
|
|
for (NSNumber *nsTimestamp in sentTimestamps) {
|
|
|
|
uint64_t timestamp = [nsTimestamp unsignedLongLongValue];
|
|
|
|
|
|
|
|
NSArray<TSOutgoingMessage *> *messages
|
|
|
|
= (NSArray<TSOutgoingMessage *> *)[TSInteraction interactionsWithTimestamp:timestamp
|
|
|
|
ofClass:[TSOutgoingMessage class]
|
|
|
|
withTransaction:transaction];
|
|
|
|
if (messages.count < 1) {
|
2017-09-27 20:19:26 +02:00
|
|
|
// The service sends delivery receipts for "unpersisted" messages
|
2017-09-22 22:40:44 +02:00
|
|
|
// like group updates, so these errors are expected to a certain extent.
|
2017-09-27 20:19:26 +02:00
|
|
|
//
|
|
|
|
// TODO: persist "early" delivery receipts.
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Missing message for delivery receipt: %llu", self.logTag, timestamp);
|
2017-09-22 22:40:44 +02:00
|
|
|
} else {
|
|
|
|
if (messages.count > 1) {
|
2018-07-18 03:08:53 +02:00
|
|
|
DDLogInfo(@"%@ More than one message (%lu) for delivery receipt: %llu",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2018-07-18 03:08:53 +02:00
|
|
|
(unsigned long)messages.count,
|
2017-11-08 20:04:51 +01:00
|
|
|
timestamp);
|
2017-09-22 22:40:44 +02:00
|
|
|
}
|
|
|
|
for (TSOutgoingMessage *outgoingMessage in messages) {
|
2018-04-23 16:30:51 +02:00
|
|
|
[outgoingMessage updateWithDeliveredRecipient:recipientId
|
|
|
|
deliveryTimestamp:deliveryTimestamp
|
|
|
|
transaction:transaction];
|
2017-09-22 22:40:44 +02:00
|
|
|
}
|
2017-09-22 21:15:04 +02:00
|
|
|
}
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2017-09-13 18:14:22 +02:00
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleEnvelope:(SSKProtoEnvelope *)envelope
|
2017-09-13 21:35:33 +02:00
|
|
|
plaintextData:(NSData *)plaintextData
|
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-12-06 03:32:11 +01:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(plaintextData);
|
|
|
|
OWSAssert(transaction);
|
2018-06-07 07:57:59 +02:00
|
|
|
OWSAssert(envelope.timestamp > 0);
|
|
|
|
OWSAssert(envelope.source.length > 0);
|
|
|
|
OWSAssert(envelope.sourceDevice > 0);
|
2017-02-16 00:32:27 +01:00
|
|
|
|
|
|
|
BOOL duplicateEnvelope = [self.incomingMessageFinder existsMessageWithTimestamp:envelope.timestamp
|
|
|
|
sourceId:envelope.source
|
2017-09-13 21:35:33 +02:00
|
|
|
sourceDeviceId:envelope.sourceDevice
|
|
|
|
transaction:transaction];
|
2017-02-16 00:32:27 +01:00
|
|
|
if (duplicateEnvelope) {
|
2017-08-28 23:29:25 +02:00
|
|
|
DDLogInfo(@"%@ Ignoring previously received envelope from %@ with timestamp: %llu",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-08-28 23:29:25 +02:00
|
|
|
envelopeAddress(envelope),
|
|
|
|
envelope.timestamp);
|
2017-02-16 00:32:27 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-03 21:50:27 +02:00
|
|
|
if (envelope.content != nil) {
|
2018-08-02 15:34:50 +02:00
|
|
|
NSError *error;
|
|
|
|
SSKProtoContent *_Nullable contentProto = [SSKProtoContent parseData:plaintextData error:&error];
|
|
|
|
if (error || !contentProto) {
|
|
|
|
OWSFail(@"%@ could not parse proto: %@", self.logTag, error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DDLogInfo(@"%@ handling content: <Content: %@>", self.logTag, [self descriptionForContent:contentProto]);
|
2017-08-01 19:53:51 +02:00
|
|
|
|
2018-08-02 15:34:50 +02:00
|
|
|
if (contentProto.hasSyncMessage) {
|
|
|
|
[self handleIncomingEnvelope:envelope withSyncMessage:contentProto.syncMessage transaction:transaction];
|
2017-11-16 15:54:55 +01:00
|
|
|
|
|
|
|
[[OWSDeviceManager sharedManager] setHasReceivedSyncMessage];
|
2018-08-02 15:34:50 +02:00
|
|
|
} else if (contentProto.hasDataMessage) {
|
|
|
|
[self handleIncomingEnvelope:envelope withDataMessage:contentProto.dataMessage transaction:transaction];
|
|
|
|
} else if (contentProto.hasCallMessage) {
|
|
|
|
[self handleIncomingEnvelope:envelope withCallMessage:contentProto.callMessage];
|
|
|
|
} else if (contentProto.hasNullMessage) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Received null message.", self.logTag);
|
2018-08-02 15:34:50 +02:00
|
|
|
} else if (contentProto.hasReceiptMessage) {
|
|
|
|
[self handleIncomingEnvelope:envelope
|
|
|
|
withReceiptMessage:contentProto.receiptMessage
|
|
|
|
transaction:transaction];
|
2016-08-23 22:38:05 +02:00
|
|
|
} else {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ Ignoring envelope. Content with no known payload", self.logTag);
|
2016-08-22 22:09:58 +02:00
|
|
|
}
|
2018-08-03 21:50:27 +02:00
|
|
|
} else if (envelope.legacyMessage != nil) { // DEPRECATED - Remove after all clients have been upgraded.
|
2018-08-02 15:34:50 +02:00
|
|
|
NSError *error;
|
|
|
|
SSKProtoDataMessage *_Nullable dataMessageProto = [SSKProtoDataMessage parseData:plaintextData error:&error];
|
|
|
|
if (error || !dataMessageProto) {
|
|
|
|
OWSFail(@"%@ could not parse proto: %@", self.logTag, error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DDLogInfo(@"%@ handling message: <DataMessage: %@ />",
|
|
|
|
self.logTag,
|
|
|
|
[self descriptionForDataMessage:dataMessageProto]);
|
2017-08-04 15:33:56 +02:00
|
|
|
|
2018-08-02 15:34:50 +02:00
|
|
|
[self handleIncomingEnvelope:envelope withDataMessage:dataMessageProto transaction:transaction];
|
2016-12-06 03:32:11 +01:00
|
|
|
} else {
|
2018-07-25 22:00:25 +02:00
|
|
|
OWSProdInfoWEnvelope([OWSAnalyticsEvents messageManagerErrorEnvelopeNoActionablePayload], envelope);
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleIncomingEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
withDataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-07-31 02:40:14 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
2017-05-05 23:22:56 +02:00
|
|
|
|
2018-02-02 16:56:16 +01:00
|
|
|
if (dataMessage.hasTimestamp) {
|
|
|
|
if (dataMessage.timestamp <= 0) {
|
|
|
|
DDLogError(@"%@ Ignoring message with invalid data message timestamp: %@", self.logTag, envelope.source);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// This prevents replay attacks by the service.
|
|
|
|
if (dataMessage.timestamp != envelope.timestamp) {
|
|
|
|
DDLogError(
|
|
|
|
@"%@ Ignoring message with non-matching data message timestamp: %@", self.logTag, envelope.source);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-04 15:33:56 +02:00
|
|
|
if ([dataMessage hasProfileKey]) {
|
|
|
|
NSData *profileKey = [dataMessage profileKey];
|
2017-09-13 21:35:33 +02:00
|
|
|
NSString *recipientId = envelope.source;
|
2017-08-28 18:03:59 +02:00
|
|
|
if (profileKey.length == kAES256_KeyByteLength) {
|
|
|
|
[self.profileManager setProfileKeyData:profileKey forRecipientId:recipientId];
|
|
|
|
} else {
|
|
|
|
OWSFail(
|
|
|
|
@"Unexpected profile key length:%lu on message from:%@", (unsigned long)profileKey.length, recipientId);
|
|
|
|
}
|
2017-08-04 15:33:56 +02:00
|
|
|
}
|
|
|
|
|
2016-08-22 22:09:58 +02:00
|
|
|
if (dataMessage.hasGroup) {
|
2017-10-04 16:06:38 +02:00
|
|
|
TSGroupThread *_Nullable groupThread =
|
2017-10-03 19:41:48 +02:00
|
|
|
[TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
|
2017-10-04 16:06:38 +02:00
|
|
|
|
|
|
|
if (!groupThread) {
|
|
|
|
// Unknown group.
|
2018-08-01 23:13:01 +02:00
|
|
|
if (dataMessage.group.type == SSKProtoGroupContextTypeUpdate) {
|
2017-10-04 16:06:38 +02:00
|
|
|
// Accept group updates for unknown groups.
|
2018-08-01 23:13:01 +02:00
|
|
|
} else if (dataMessage.group.type == SSKProtoGroupContextTypeDeliver) {
|
2017-10-04 16:06:38 +02:00
|
|
|
[self sendGroupInfoRequest:dataMessage.group.id envelope:envelope transaction:transaction];
|
2017-10-03 19:41:48 +02:00
|
|
|
return;
|
2017-10-04 16:06:38 +02:00
|
|
|
} else {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Ignoring group message for unknown group from: %@", self.logTag, envelope.source);
|
2017-08-08 18:16:17 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
}
|
2017-09-21 20:03:24 +02:00
|
|
|
|
2018-08-01 23:13:01 +02:00
|
|
|
if ((dataMessage.flags & SSKProtoDataMessageFlagsEndSession) != 0) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleEndSessionMessageWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
2018-08-01 23:13:01 +02:00
|
|
|
} else if ((dataMessage.flags & SSKProtoDataMessageFlagsExpirationTimerUpdate) != 0) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleExpirationTimerUpdateMessageWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
2018-08-01 23:13:01 +02:00
|
|
|
} else if ((dataMessage.flags & SSKProtoDataMessageFlagsProfileKeyUpdate) != 0) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleProfileKeyMessageWithEnvelope:envelope dataMessage:dataMessage];
|
2016-10-14 23:00:29 +02:00
|
|
|
} else if (dataMessage.attachments.count > 0) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleReceivedMediaWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
} else {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleReceivedTextMessageWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
2017-10-03 19:41:48 +02:00
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
if ([self isDataMessageGroupAvatarUpdate:dataMessage]) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogVerbose(@"%@ Data message had group avatar attachment", self.logTag);
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleReceivedGroupAvatarUpdateWithEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
2016-10-14 23:00:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
- (void)sendGroupInfoRequest:(NSData *)groupId
|
2018-08-01 16:45:21 +02:00
|
|
|
envelope:(SSKProtoEnvelope *)envelope
|
2017-10-03 19:41:48 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
|
|
|
{
|
|
|
|
OWSAssert(groupId.length > 0);
|
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
|
|
|
if (groupId.length < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-07 23:00:45 +01:00
|
|
|
// FIXME: https://github.com/signalapp/Signal-iOS/issues/1340
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Sending group info request: %@", self.logTag, envelopeAddress(envelope));
|
2017-10-03 19:41:48 +02:00
|
|
|
|
|
|
|
NSString *recipientId = envelope.source;
|
|
|
|
|
|
|
|
TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
|
|
|
|
|
|
|
|
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
|
|
|
|
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread groupId:groupId];
|
2017-11-15 19:21:31 +01:00
|
|
|
[self.messageSender enqueueMessage:syncGroupsRequestMessage
|
2017-10-03 19:41:48 +02:00
|
|
|
success:^{
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ Successfully sent Request Group Info message.", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogError(@"%@ Failed to send Request Group Info message with error: %@", self.logTag, error);
|
2017-10-03 19:41:48 +02:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2017-08-25 23:16:49 +02:00
|
|
|
- (id<ProfileManagerProtocol>)profileManager
|
|
|
|
{
|
|
|
|
return [TextSecureKitEnv sharedEnv].profileManager;
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleIncomingEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
withReceiptMessage:(SSKProtoReceiptMessage *)receiptMessage
|
2017-09-22 22:40:44 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2017-09-15 21:28:44 +02:00
|
|
|
{
|
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(receiptMessage);
|
2017-09-22 22:40:44 +02:00
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2018-08-02 15:34:50 +02:00
|
|
|
NSArray<NSNumber *> *sentTimestamps = receiptMessage.timestamp;
|
2017-09-15 21:28:44 +02:00
|
|
|
|
|
|
|
switch (receiptMessage.type) {
|
2018-08-01 23:13:01 +02:00
|
|
|
case SSKProtoReceiptMessageTypeDelivery:
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogVerbose(@"%@ Processing receipt message with delivery receipts.", self.logTag);
|
2017-09-27 20:19:26 +02:00
|
|
|
[self processDeliveryReceiptsFromRecipientId:envelope.source
|
|
|
|
sentTimestamps:sentTimestamps
|
|
|
|
deliveryTimestamp:@(envelope.timestamp)
|
|
|
|
transaction:transaction];
|
2017-09-15 21:28:44 +02:00
|
|
|
return;
|
2018-08-01 23:13:01 +02:00
|
|
|
case SSKProtoReceiptMessageTypeRead:
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogVerbose(@"%@ Processing receipt message with read receipts.", self.logTag);
|
2017-09-22 22:40:44 +02:00
|
|
|
[OWSReadReceiptManager.sharedManager processReadReceiptsFromRecipientId:envelope.source
|
|
|
|
sentTimestamps:sentTimestamps
|
|
|
|
readTimestamp:envelope.timestamp];
|
2017-09-15 21:28:44 +02:00
|
|
|
break;
|
|
|
|
default:
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Ignoring receipt message of unknown type: %d.", self.logTag, (int)receiptMessage.type);
|
2017-09-15 21:28:44 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleIncomingEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
withCallMessage:(SSKProtoCallMessage *)callMessage
|
2016-12-18 22:08:26 +01:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
2017-08-04 15:33:56 +02:00
|
|
|
OWSAssert(callMessage);
|
|
|
|
|
|
|
|
if ([callMessage hasProfileKey]) {
|
|
|
|
NSData *profileKey = [callMessage profileKey];
|
2017-09-13 21:35:33 +02:00
|
|
|
NSString *recipientId = envelope.source;
|
2017-08-25 23:16:49 +02:00
|
|
|
[self.profileManager setProfileKeyData:profileKey forRecipientId:recipientId];
|
2017-08-04 15:33:56 +02:00
|
|
|
}
|
|
|
|
|
2017-09-20 17:48:37 +02:00
|
|
|
// 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.
|
2017-09-13 21:35:33 +02:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
if (callMessage.hasOffer) {
|
|
|
|
[self.callMessageHandler receivedOffer:callMessage.offer fromCallerId:envelope.source];
|
|
|
|
} else if (callMessage.hasAnswer) {
|
|
|
|
[self.callMessageHandler receivedAnswer:callMessage.answer fromCallerId:envelope.source];
|
|
|
|
} else if (callMessage.iceUpdate.count > 0) {
|
2018-08-01 23:13:01 +02:00
|
|
|
for (SSKProtoCallMessageIceUpdate *iceUpdate in callMessage.iceUpdate) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self.callMessageHandler receivedIceUpdate:iceUpdate fromCallerId:envelope.source];
|
|
|
|
}
|
|
|
|
} else if (callMessage.hasHangup) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogVerbose(@"%@ Received CallMessage with Hangup.", self.logTag);
|
2017-09-13 21:35:33 +02:00
|
|
|
[self.callMessageHandler receivedHangup:callMessage.hangup fromCallerId:envelope.source];
|
|
|
|
} else if (callMessage.hasBusy) {
|
|
|
|
[self.callMessageHandler receivedBusy:callMessage.busy fromCallerId:envelope.source];
|
|
|
|
} else {
|
|
|
|
OWSProdInfoWEnvelope([OWSAnalyticsEvents messageManagerErrorCallMessageNoActionablePayload], envelope);
|
2016-12-18 22:08:26 +01:00
|
|
|
}
|
2017-09-13 21:35:33 +02:00
|
|
|
});
|
2016-12-18 22:08:26 +01:00
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleReceivedGroupAvatarUpdateWithEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-10-14 23:00:29 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
TSGroupThread *_Nullable groupThread =
|
|
|
|
[TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
|
|
|
|
if (!groupThread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ Missing group for group avatar update", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-04 18:01:45 +02:00
|
|
|
OWSAssert(groupThread);
|
2016-10-14 23:00:29 +02:00
|
|
|
OWSAttachmentsProcessor *attachmentsProcessor =
|
|
|
|
[[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:@[ dataMessage.group.avatar ]
|
2017-09-13 21:35:33 +02:00
|
|
|
networkManager:self.networkManager
|
|
|
|
transaction:transaction];
|
2016-10-14 23:00:29 +02:00
|
|
|
|
|
|
|
if (!attachmentsProcessor.hasSupportedAttachments) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ received unsupported group avatar envelope", self.logTag);
|
2016-10-14 23:00:29 +02:00
|
|
|
return;
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
2016-10-14 23:00:29 +02:00
|
|
|
[attachmentsProcessor fetchAttachmentsForMessage:nil
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:transaction
|
2017-05-10 16:05:01 +02:00
|
|
|
success:^(TSAttachmentStream *attachmentStream) {
|
2016-10-14 23:00:29 +02:00
|
|
|
[groupThread updateAvatarWithAttachmentStream:attachmentStream];
|
|
|
|
}
|
2017-05-10 16:05:01 +02:00
|
|
|
failure:^(NSError *error) {
|
2016-10-14 23:00:29 +02:00
|
|
|
DDLogError(@"%@ failed to fetch attachments for group avatar sent at: %llu. with error: %@",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2016-10-14 23:00:29 +02:00
|
|
|
envelope.timestamp,
|
|
|
|
error);
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleReceivedMediaWithEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-10-14 23:00:29 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
TSThread *_Nullable thread = [self threadForEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
|
|
|
if (!thread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ ignoring media message for unknown group.", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
OWSAttachmentsProcessor *attachmentsProcessor =
|
|
|
|
[[OWSAttachmentsProcessor alloc] initWithAttachmentProtos:dataMessage.attachments
|
2017-09-13 21:35:33 +02:00
|
|
|
networkManager:self.networkManager
|
|
|
|
transaction:transaction];
|
2016-10-14 23:00:29 +02:00
|
|
|
if (!attachmentsProcessor.hasSupportedAttachments) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ received unsupported media envelope", self.logTag);
|
2016-10-14 23:00:29 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-06 23:59:42 +02:00
|
|
|
TSIncomingMessage *_Nullable createdMessage = [self handleReceivedEnvelope:envelope
|
|
|
|
withDataMessage:dataMessage
|
|
|
|
attachmentIds:attachmentsProcessor.attachmentIds
|
|
|
|
transaction:transaction];
|
2017-05-10 16:05:01 +02:00
|
|
|
|
|
|
|
if (!createdMessage) {
|
|
|
|
return;
|
|
|
|
}
|
2016-10-14 23:00:29 +02:00
|
|
|
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogDebug(@"%@ incoming attachment message: %@", self.logTag, createdMessage.debugDescription);
|
2017-06-13 16:50:42 +02:00
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
[attachmentsProcessor fetchAttachmentsForMessage:createdMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:transaction
|
2017-05-10 16:05:01 +02:00
|
|
|
success:^(TSAttachmentStream *attachmentStream) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogDebug(@"%@ successfully fetched attachment: %@ for message: %@",
|
|
|
|
self.logTag,
|
|
|
|
attachmentStream,
|
|
|
|
createdMessage);
|
2016-10-14 23:00:29 +02:00
|
|
|
}
|
2017-05-10 16:05:01 +02:00
|
|
|
failure:^(NSError *error) {
|
2016-10-14 23:00:29 +02:00
|
|
|
DDLogError(
|
2017-11-08 20:04:51 +01:00
|
|
|
@"%@ failed to fetch attachments for message: %@ with error: %@", self.logTag, createdMessage, error);
|
2016-10-14 23:00:29 +02:00
|
|
|
}];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleIncomingEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
withSyncMessage:(SSKProtoSyncMessage *)syncMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-08-23 22:38:05 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(syncMessage);
|
|
|
|
OWSAssert(transaction);
|
2017-08-04 18:01:45 +02:00
|
|
|
OWSAssert([TSAccountManager isRegistered]);
|
2017-09-13 21:35:33 +02:00
|
|
|
|
2017-08-04 18:01:45 +02:00
|
|
|
NSString *localNumber = [TSAccountManager localNumber];
|
2017-09-13 21:35:33 +02:00
|
|
|
if (![localNumber isEqualToString:envelope.source]) {
|
2017-08-04 18:01:45 +02:00
|
|
|
// Sync messages should only come from linked devices.
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorSyncMessageFromUnknownSource], envelope);
|
2017-08-04 18:01:45 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-23 22:38:05 +02:00
|
|
|
if (syncMessage.hasSent) {
|
|
|
|
OWSIncomingSentMessageTranscript *transcript =
|
2018-04-07 21:26:22 +02:00
|
|
|
[[OWSIncomingSentMessageTranscript alloc] initWithProto:syncMessage.sent
|
|
|
|
transaction:transaction];
|
2016-10-14 23:00:29 +02:00
|
|
|
|
|
|
|
OWSRecordTranscriptJob *recordJob =
|
2017-09-15 21:28:44 +02:00
|
|
|
[[OWSRecordTranscriptJob alloc] initWithIncomingSentMessageTranscript:transcript];
|
2016-10-14 23:00:29 +02:00
|
|
|
|
2018-08-01 23:13:01 +02:00
|
|
|
SSKProtoDataMessage *dataMessage = syncMessage.sent.message;
|
2017-08-04 15:33:56 +02:00
|
|
|
OWSAssert(dataMessage);
|
|
|
|
NSString *destination = syncMessage.sent.destination;
|
2017-08-29 15:31:02 +02:00
|
|
|
if (dataMessage && destination.length > 0 && dataMessage.hasProfileKey) {
|
2017-08-04 15:33:56 +02:00
|
|
|
// If we observe a linked device sending our profile key to another
|
|
|
|
// user, we can infer that that user belongs in our profile whitelist.
|
2017-08-29 15:31:02 +02:00
|
|
|
if (dataMessage.hasGroup) {
|
|
|
|
[self.profileManager addGroupIdToProfileWhitelist:dataMessage.group.id];
|
|
|
|
} else {
|
|
|
|
[self.profileManager addUserToProfileWhitelist:destination];
|
|
|
|
}
|
2017-08-04 15:33:56 +02:00
|
|
|
}
|
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
if ([self isDataMessageGroupAvatarUpdate:syncMessage.sent.message]) {
|
2017-05-10 16:05:01 +02:00
|
|
|
[recordJob runWithAttachmentHandler:^(TSAttachmentStream *attachmentStream) {
|
2017-10-03 19:41:48 +02:00
|
|
|
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
TSGroupThread *_Nullable groupThread =
|
|
|
|
[TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
|
|
|
|
if (!groupThread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ ignoring sync group avatar update for unknown group.", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
[groupThread updateAvatarWithAttachmentStream:attachmentStream transaction:transaction];
|
|
|
|
}];
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
|
|
|
transaction:transaction];
|
2016-10-14 23:00:29 +02:00
|
|
|
} else {
|
2017-05-10 16:05:01 +02:00
|
|
|
[recordJob runWithAttachmentHandler:^(TSAttachmentStream *attachmentStream) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogDebug(@"%@ successfully fetched transcript attachment: %@", self.logTag, attachmentStream);
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
|
|
|
transaction:transaction];
|
2016-10-14 23:00:29 +02:00
|
|
|
}
|
2016-09-01 16:28:35 +02:00
|
|
|
} else if (syncMessage.hasRequest) {
|
2018-08-01 23:13:01 +02:00
|
|
|
if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeContacts) {
|
2017-11-21 16:01:55 +01:00
|
|
|
// We respond asynchronously because populating the sync message will
|
|
|
|
// create transactions and it's not practical (due to locking in the OWSIdentityManager)
|
|
|
|
// to plumb our transaction through.
|
|
|
|
//
|
|
|
|
// In rare cases this means we won't respond to the sync request, but that's
|
|
|
|
// acceptable.
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
|
OWSSyncContactsMessage *syncContactsMessage =
|
|
|
|
[[OWSSyncContactsMessage alloc] initWithSignalAccounts:self.contactsManager.signalAccounts
|
|
|
|
identityManager:self.identityManager
|
|
|
|
profileManager:self.profileManager];
|
2018-08-07 18:57:48 +02:00
|
|
|
__block NSData *_Nullable syncData;
|
|
|
|
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
syncData = [syncContactsMessage buildPlainTextAttachmentDataWithTransaction:transaction];
|
|
|
|
}];
|
|
|
|
if (!syncData) {
|
|
|
|
OWSFail(@"%@ Failed to serialize contacts sync message.", self.logTag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DataSource *dataSource = [DataSourceValue dataSourceWithSyncMessageData:syncData];
|
2017-11-21 16:01:55 +01:00
|
|
|
[self.messageSender enqueueTemporaryAttachment:dataSource
|
|
|
|
contentType:OWSMimeTypeApplicationOctetStream
|
|
|
|
inMessage:syncContactsMessage
|
|
|
|
success:^{
|
|
|
|
DDLogInfo(@"%@ Successfully sent Contacts response syncMessage.", self.logTag);
|
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
DDLogError(
|
|
|
|
@"%@ Failed to send Contacts response syncMessage with error: %@", self.logTag, error);
|
|
|
|
}];
|
|
|
|
});
|
2018-08-01 23:13:01 +02:00
|
|
|
} else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeGroups) {
|
2018-08-07 19:03:33 +02:00
|
|
|
OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
|
|
|
|
NSData *_Nullable syncData = [syncGroupsMessage buildPlainTextAttachmentDataWithTransaction:transaction];
|
|
|
|
if (!syncData) {
|
|
|
|
OWSFail(@"%@ Failed to serialize groups sync message.", self.logTag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DataSource *dataSource = [DataSourceValue dataSourceWithSyncMessageData:syncData];
|
|
|
|
[self.messageSender enqueueTemporaryAttachment:dataSource
|
|
|
|
contentType:OWSMimeTypeApplicationOctetStream
|
|
|
|
inMessage:syncGroupsMessage
|
|
|
|
success:^{
|
|
|
|
DDLogInfo(@"%@ Successfully sent Groups response syncMessage.", self.logTag);
|
2018-08-07 18:57:48 +02:00
|
|
|
}
|
2018-08-07 19:03:33 +02:00
|
|
|
failure:^(NSError *error) {
|
|
|
|
DDLogError(@"%@ Failed to send Groups response syncMessage with error: %@", self.logTag, error);
|
|
|
|
}];
|
2018-08-01 23:13:01 +02:00
|
|
|
} else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeBlocked) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Received request for block list", self.logTag);
|
2017-10-03 21:53:39 +02:00
|
|
|
[_blockingManager syncBlockedPhoneNumbers];
|
2018-08-01 23:13:01 +02:00
|
|
|
} else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeConfiguration) {
|
2017-10-03 17:11:15 +02:00
|
|
|
BOOL areReadReceiptsEnabled =
|
|
|
|
[[OWSReadReceiptManager sharedManager] areReadReceiptsEnabledWithTransaction:transaction];
|
2017-10-02 22:35:24 +02:00
|
|
|
OWSSyncConfigurationMessage *syncConfigurationMessage =
|
|
|
|
[[OWSSyncConfigurationMessage alloc] initWithReadReceiptsEnabled:areReadReceiptsEnabled];
|
2017-11-15 19:21:31 +01:00
|
|
|
[self.messageSender enqueueMessage:syncConfigurationMessage
|
2017-10-02 22:35:24 +02:00
|
|
|
success:^{
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Successfully sent Configuration response syncMessage.", self.logTag);
|
2017-10-02 22:35:24 +02:00
|
|
|
}
|
|
|
|
failure:^(NSError *error) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogError(
|
|
|
|
@"%@ Failed to send Configuration response syncMessage with error: %@", self.logTag, error);
|
2017-10-02 22:35:24 +02:00
|
|
|
}];
|
2016-11-22 18:14:39 +01:00
|
|
|
} else {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ ignoring unsupported sync request message", self.logTag);
|
2016-08-26 01:01:35 +02:00
|
|
|
}
|
2017-03-31 02:04:19 +02:00
|
|
|
} else if (syncMessage.hasBlocked) {
|
2017-09-28 16:01:17 +02:00
|
|
|
NSArray<NSString *> *blockedPhoneNumbers = [syncMessage.blocked.numbers copy];
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
2018-05-11 16:36:40 +02:00
|
|
|
[self.blockingManager setBlockedPhoneNumbers:blockedPhoneNumbers sendSyncMessage:NO];
|
2017-09-13 21:35:33 +02:00
|
|
|
});
|
2016-09-01 16:28:35 +02:00
|
|
|
} else if (syncMessage.read.count > 0) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Received %ld read receipt(s)", self.logTag, (u_long)syncMessage.read.count);
|
2017-09-26 17:45:22 +02:00
|
|
|
[OWSReadReceiptManager.sharedManager processReadReceiptsFromLinkedDevice:syncMessage.read
|
2018-04-18 02:53:27 +02:00
|
|
|
readTimestamp:envelope.timestamp
|
2017-09-26 17:45:22 +02:00
|
|
|
transaction:transaction];
|
2017-06-22 02:19:23 +02:00
|
|
|
} else if (syncMessage.hasVerified) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Received verification state for %@", self.logTag, syncMessage.verified.destination);
|
2018-02-02 20:52:45 +01:00
|
|
|
[self.identityManager processIncomingSyncMessage:syncMessage.verified transaction:transaction];
|
2016-08-23 22:38:05 +02:00
|
|
|
} else {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ Ignoring unsupported sync message.", self.logTag);
|
2016-08-23 22:38:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleEndSessionMessageWithEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-08-22 22:09:58 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
|
|
|
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
|
|
|
|
|
2018-05-03 18:39:10 +02:00
|
|
|
[[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
2017-09-20 17:48:37 +02:00
|
|
|
inThread:thread
|
|
|
|
messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-03-05 15:30:58 +01:00
|
|
|
[self.primaryStorage deleteAllSessionsForContact:envelope.source protocolContext:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleExpirationTimerUpdateMessageWithEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-07-29 21:33:25 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
TSThread *_Nullable thread = [self threadForEnvelope:envelope dataMessage:dataMessage transaction:transaction];
|
|
|
|
if (!thread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ ignoring expiring messages update for unknown group.", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-10-05 17:42:44 +02:00
|
|
|
|
|
|
|
OWSDisappearingMessagesConfiguration *disappearingMessagesConfiguration;
|
|
|
|
if (dataMessage.hasExpireTimer && dataMessage.expireTimer > 0) {
|
|
|
|
DDLogInfo(@"%@ Expiring messages duration turned to %u for thread %@",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2016-10-05 17:42:44 +02:00
|
|
|
(unsigned int)dataMessage.expireTimer,
|
|
|
|
thread);
|
|
|
|
disappearingMessagesConfiguration =
|
|
|
|
[[OWSDisappearingMessagesConfiguration alloc] initWithThreadId:thread.uniqueId
|
|
|
|
enabled:YES
|
|
|
|
durationSeconds:dataMessage.expireTimer];
|
|
|
|
} else {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ Expiring messages have been turned off for thread %@", self.logTag, thread);
|
2016-10-05 17:42:44 +02:00
|
|
|
disappearingMessagesConfiguration = [[OWSDisappearingMessagesConfiguration alloc]
|
|
|
|
initWithThreadId:thread.uniqueId
|
|
|
|
enabled:NO
|
|
|
|
durationSeconds:OWSDisappearingMessagesConfigurationDefaultExpirationDuration];
|
|
|
|
}
|
2017-08-04 18:01:45 +02:00
|
|
|
OWSAssert(disappearingMessagesConfiguration);
|
2017-09-13 21:35:33 +02:00
|
|
|
[disappearingMessagesConfiguration saveWithTransaction:transaction];
|
2016-12-02 03:10:15 +01:00
|
|
|
NSString *name = [self.contactsManager displayNameForPhoneIdentifier:envelope.source];
|
2016-10-05 17:42:44 +02:00
|
|
|
OWSDisappearingConfigurationUpdateInfoMessage *message =
|
2018-05-03 18:39:10 +02:00
|
|
|
[[OWSDisappearingConfigurationUpdateInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
2016-10-05 17:42:44 +02:00
|
|
|
thread:thread
|
|
|
|
configuration:disappearingMessagesConfiguration
|
2018-06-14 16:08:38 +02:00
|
|
|
createdByRemoteName:name
|
2018-06-14 16:35:47 +02:00
|
|
|
createdInExistingGroup:NO];
|
2017-09-13 21:35:33 +02:00
|
|
|
[message saveWithTransaction:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleProfileKeyMessageWithEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-08-28 23:00:55 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
|
|
|
|
NSString *recipientId = envelope.source;
|
2017-08-28 23:00:55 +02:00
|
|
|
if (!dataMessage.hasProfileKey) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(
|
|
|
|
@"%@ received profile key message without profile key from: %@", self.logTag, envelopeAddress(envelope));
|
2017-08-28 23:00:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
NSData *profileKey = dataMessage.profileKey;
|
|
|
|
if (profileKey.length != kAES256_KeyByteLength) {
|
2017-08-29 00:03:14 +02:00
|
|
|
OWSFail(@"%@ received profile key of unexpected length:%lu from:%@",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-08-28 23:00:55 +02:00
|
|
|
(unsigned long)profileKey.length,
|
2017-09-13 21:35:33 +02:00
|
|
|
envelopeAddress(envelope));
|
2017-08-28 23:00:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
id<ProfileManagerProtocol> profileManager = [TextSecureKitEnv sharedEnv].profileManager;
|
|
|
|
[profileManager setProfileKeyData:profileKey forRecipientId:recipientId];
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleReceivedTextMessageWithEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-07-29 21:33:25 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
|
|
|
[self handleReceivedEnvelope:envelope withDataMessage:dataMessage attachmentIds:@[] transaction:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2017-05-05 23:22:56 +02:00
|
|
|
- (void)sendGroupUpdateForThread:(TSGroupThread *)gThread message:(TSOutgoingMessage *)message
|
|
|
|
{
|
|
|
|
OWSAssert(gThread);
|
2017-08-04 18:01:45 +02:00
|
|
|
OWSAssert(gThread.groupModel);
|
2017-05-05 23:22:56 +02:00
|
|
|
OWSAssert(message);
|
|
|
|
|
|
|
|
if (gThread.groupModel.groupImage) {
|
2017-09-08 18:51:25 +02:00
|
|
|
NSData *data = UIImagePNGRepresentation(gThread.groupModel.groupImage);
|
2018-07-30 17:00:56 +02:00
|
|
|
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"];
|
2018-07-30 16:22:45 +02:00
|
|
|
[self.messageSender enqueueTemporaryAttachment:dataSource
|
2017-05-05 23:22:56 +02:00
|
|
|
contentType:OWSMimeTypeImagePng
|
|
|
|
inMessage:message
|
|
|
|
success:^{
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogDebug(@"%@ Successfully sent group update with avatar", self.logTag);
|
2017-05-05 23:22:56 +02:00
|
|
|
}
|
2017-05-10 16:05:01 +02:00
|
|
|
failure:^(NSError *error) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogError(@"%@ Failed to send group avatar update with error: %@", self.logTag, error);
|
2017-05-05 23:22:56 +02:00
|
|
|
}];
|
|
|
|
} else {
|
2017-11-15 19:21:31 +01:00
|
|
|
[self.messageSender enqueueMessage:message
|
2017-05-05 23:22:56 +02:00
|
|
|
success:^{
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogDebug(@"%@ Successfully sent group update", self.logTag);
|
2017-05-05 23:22:56 +02:00
|
|
|
}
|
2017-05-10 16:05:01 +02:00
|
|
|
failure:^(NSError *error) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogError(@"%@ Failed to send group update with error: %@", self.logTag, error);
|
2017-05-05 23:22:56 +02:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (void)handleGroupInfoRequest:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2017-05-10 16:05:01 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
2018-08-01 23:13:01 +02:00
|
|
|
OWSAssert(dataMessage.group.type == SSKProtoGroupContextTypeRequestInfo);
|
2017-05-10 16:05:01 +02:00
|
|
|
|
|
|
|
NSData *groupId = dataMessage.hasGroup ? dataMessage.group.id : nil;
|
|
|
|
if (!groupId) {
|
2017-07-21 21:38:44 +02:00
|
|
|
OWSFail(@"Group info request is missing group id.");
|
2017-05-10 16:05:01 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(
|
|
|
|
@"%@ Received 'Request Group Info' message for group: %@ from: %@", self.logTag, groupId, envelope.source);
|
2017-05-10 16:05:01 +02:00
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
TSGroupThread *_Nullable gThread = [TSGroupThread threadWithGroupId:dataMessage.group.id transaction:transaction];
|
2017-09-13 21:35:33 +02:00
|
|
|
if (!gThread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ Unknown group: %@", self.logTag, groupId);
|
2017-09-13 21:35:33 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-05-12 18:39:36 +02:00
|
|
|
|
2017-10-04 16:19:19 +02:00
|
|
|
// Ensure sender is in the group.
|
2017-09-13 21:35:33 +02:00
|
|
|
if (![gThread.groupModel.groupMemberIds containsObject:envelope.source]) {
|
|
|
|
DDLogWarn(@"%@ Ignoring 'Request Group Info' message for non-member of group. %@ not in %@",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-09-13 21:35:33 +02:00
|
|
|
envelope.source,
|
|
|
|
gThread.groupModel.groupMemberIds);
|
2017-10-04 16:19:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure we are in the group.
|
|
|
|
OWSAssert([TSAccountManager isRegistered]);
|
|
|
|
NSString *localNumber = [TSAccountManager localNumber];
|
|
|
|
if (![gThread.groupModel.groupMemberIds containsObject:localNumber]) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ Ignoring 'Request Group Info' message for group we no longer belong to.", self.logTag);
|
2017-10-04 16:19:19 +02:00
|
|
|
return;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2017-05-10 16:05:01 +02:00
|
|
|
|
2017-09-13 21:35:33 +02:00
|
|
|
NSString *updateGroupInfo =
|
|
|
|
[gThread.groupModel getInfoStringAboutUpdateTo:gThread.groupModel contactsManager:self.contactsManager];
|
2018-06-13 22:44:22 +02:00
|
|
|
|
|
|
|
uint32_t expiresInSeconds = [gThread disappearingMessagesDurationWithTransaction:transaction];
|
|
|
|
TSOutgoingMessage *message = [TSOutgoingMessage outgoingMessageInThread:gThread
|
|
|
|
groupMetaMessage:TSGroupMessageUpdate
|
|
|
|
expiresInSeconds:expiresInSeconds];
|
|
|
|
|
2017-09-13 21:35:33 +02:00
|
|
|
[message updateWithCustomMessage:updateGroupInfo transaction:transaction];
|
|
|
|
// Only send this group update to the requester.
|
2018-04-24 22:38:35 +02:00
|
|
|
[message updateWithSendingToSingleGroupRecipient:envelope.source transaction:transaction];
|
2017-09-13 21:35:33 +02:00
|
|
|
|
2017-09-21 17:55:25 +02:00
|
|
|
[self sendGroupUpdateForThread:gThread message:message];
|
2017-05-10 16:05:01 +02:00
|
|
|
}
|
|
|
|
|
2018-08-01 16:45:21 +02:00
|
|
|
- (TSIncomingMessage *_Nullable)handleReceivedEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
withDataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-05-10 16:05:01 +02:00
|
|
|
attachmentIds:(NSArray<NSString *> *)attachmentIds
|
2017-09-13 21:35:33 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-07-29 21:33:25 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2016-10-05 17:42:44 +02:00
|
|
|
uint64_t timestamp = envelope.timestamp;
|
2016-08-22 22:09:58 +02:00
|
|
|
NSString *body = dataMessage.body;
|
|
|
|
NSData *groupId = dataMessage.hasGroup ? dataMessage.group.id : nil;
|
2018-07-13 20:03:28 +02:00
|
|
|
OWSContact *_Nullable contact = [OWSContacts contactForDataMessage:dataMessage transaction:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-08-01 23:13:01 +02:00
|
|
|
if (dataMessage.group.type == SSKProtoGroupContextTypeRequestInfo) {
|
2017-09-13 21:35:33 +02:00
|
|
|
[self handleGroupInfoRequest:envelope dataMessage:dataMessage transaction:transaction];
|
2017-05-10 16:05:01 +02:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
if (groupId.length > 0) {
|
|
|
|
NSMutableSet *newMemberIds = [NSMutableSet setWithArray:dataMessage.group.members];
|
2018-02-16 02:45:28 +01:00
|
|
|
for (NSString *recipientId in newMemberIds) {
|
|
|
|
if (!recipientId.isValidE164) {
|
|
|
|
DDLogVerbose(@"%@ incoming group update has invalid group member: %@",
|
|
|
|
self.logTag,
|
|
|
|
[self descriptionForEnvelope:envelope]);
|
|
|
|
OWSFail(@"%@ incoming group update has invalid group member", self.logTag);
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
2017-10-03 19:41:48 +02:00
|
|
|
|
|
|
|
// Group messages create the group if it doesn't already exist.
|
|
|
|
//
|
|
|
|
// We distinguish between the old group state (if any) and the new group state.
|
|
|
|
TSGroupThread *_Nullable oldGroupThread = [TSGroupThread threadWithGroupId:groupId transaction:transaction];
|
|
|
|
if (oldGroupThread) {
|
2017-10-04 16:06:38 +02:00
|
|
|
// Don't trust other clients; ensure all known group members remain in the
|
|
|
|
// group unless it is a "quit" message in which case we should only remove
|
|
|
|
// the quiting member below.
|
2017-10-03 19:41:48 +02:00
|
|
|
[newMemberIds addObjectsFromArray:oldGroupThread.groupModel.groupMemberIds];
|
|
|
|
}
|
2017-09-13 21:35:33 +02:00
|
|
|
|
|
|
|
switch (dataMessage.group.type) {
|
2018-08-01 23:13:01 +02:00
|
|
|
case SSKProtoGroupContextTypeUpdate: {
|
2017-10-03 19:41:48 +02:00
|
|
|
// Ensures that the thread exists but doesn't update it.
|
|
|
|
TSGroupThread *newGroupThread =
|
|
|
|
[TSGroupThread getOrCreateThreadWithGroupId:groupId transaction:transaction];
|
|
|
|
|
2018-06-14 16:08:38 +02:00
|
|
|
|
|
|
|
uint64_t now = [NSDate ows_millisecondTimeStamp];
|
2017-10-03 19:41:48 +02:00
|
|
|
TSGroupModel *newGroupModel = [[TSGroupModel alloc] initWithTitle:dataMessage.group.name
|
2018-02-13 07:10:29 +01:00
|
|
|
memberIds:newMemberIds.allObjects
|
2017-10-04 16:06:38 +02:00
|
|
|
image:oldGroupThread.groupModel.groupImage
|
2017-10-03 19:41:48 +02:00
|
|
|
groupId:dataMessage.group.id];
|
|
|
|
NSString *updateGroupInfo = [newGroupThread.groupModel getInfoStringAboutUpdateTo:newGroupModel
|
|
|
|
contactsManager:self.contactsManager];
|
|
|
|
newGroupThread.groupModel = newGroupModel;
|
|
|
|
[newGroupThread saveWithTransaction:transaction];
|
|
|
|
|
2018-06-14 16:08:38 +02:00
|
|
|
[[[TSInfoMessage alloc] initWithTimestamp:now
|
2017-10-03 19:41:48 +02:00
|
|
|
inThread:newGroupThread
|
2017-09-13 21:35:33 +02:00
|
|
|
messageType:TSInfoMessageTypeGroupUpdate
|
|
|
|
customMessage:updateGroupInfo] saveWithTransaction:transaction];
|
2018-06-14 16:08:38 +02:00
|
|
|
|
|
|
|
if (dataMessage.hasExpireTimer && dataMessage.expireTimer > 0) {
|
|
|
|
[[OWSDisappearingMessagesJob sharedJob]
|
|
|
|
becomeConsistentWithDisappearingDuration:dataMessage.expireTimer
|
|
|
|
thread:newGroupThread
|
|
|
|
appearBeforeTimestamp:now
|
|
|
|
createdByRemoteContactName:nil
|
2018-06-14 16:35:47 +02:00
|
|
|
createdInExistingGroup:YES
|
2018-06-14 16:08:38 +02:00
|
|
|
transaction:transaction];
|
|
|
|
}
|
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
return nil;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2018-08-01 23:13:01 +02:00
|
|
|
case SSKProtoGroupContextTypeQuit: {
|
2017-10-03 19:41:48 +02:00
|
|
|
if (!oldGroupThread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogInfo(@"%@ ignoring quit group message from unknown group.", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
[newMemberIds removeObject:envelope.source];
|
|
|
|
oldGroupThread.groupModel.groupMemberIds = [newMemberIds.allObjects mutableCopy];
|
|
|
|
[oldGroupThread saveWithTransaction:transaction];
|
2017-09-13 21:35:33 +02:00
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
NSString *nameString = [self.contactsManager displayNameForPhoneIdentifier:envelope.source];
|
2017-09-13 21:35:33 +02:00
|
|
|
NSString *updateGroupInfo =
|
|
|
|
[NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""), nameString];
|
2018-05-03 18:39:10 +02:00
|
|
|
[[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
2017-10-03 19:41:48 +02:00
|
|
|
inThread:oldGroupThread
|
2017-09-13 21:35:33 +02:00
|
|
|
messageType:TSInfoMessageTypeGroupUpdate
|
|
|
|
customMessage:updateGroupInfo] saveWithTransaction:transaction];
|
2017-10-04 16:06:38 +02:00
|
|
|
return nil;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2018-08-01 23:13:01 +02:00
|
|
|
case SSKProtoGroupContextTypeDeliver: {
|
2017-10-03 19:41:48 +02:00
|
|
|
if (!oldGroupThread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ ignoring deliver group message from unknown group.", self.logTag);
|
2017-10-03 19:41:48 +02:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2018-05-02 18:43:23 +02:00
|
|
|
if (body.length == 0 && attachmentIds.count < 1 && !contact) {
|
2017-09-14 16:00:34 +02:00
|
|
|
DDLogWarn(@"%@ ignoring empty incoming message from: %@ for group: %@ with timestamp: %lu",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-09-13 21:35:33 +02:00
|
|
|
envelopeAddress(envelope),
|
|
|
|
groupId,
|
|
|
|
(unsigned long)timestamp);
|
2017-10-03 19:41:48 +02:00
|
|
|
return nil;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2017-10-03 19:41:48 +02:00
|
|
|
|
2018-04-07 21:26:22 +02:00
|
|
|
TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage
|
|
|
|
thread:oldGroupThread
|
|
|
|
transaction:transaction];
|
2018-02-07 18:44:09 +01:00
|
|
|
|
2017-10-03 19:41:48 +02:00
|
|
|
DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-10-03 19:41:48 +02:00
|
|
|
envelopeAddress(envelope),
|
|
|
|
groupId,
|
|
|
|
(unsigned long)timestamp);
|
2018-02-07 18:44:09 +01:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
TSIncomingMessage *incomingMessage =
|
2018-02-07 18:44:09 +01:00
|
|
|
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
|
|
|
|
inThread:oldGroupThread
|
|
|
|
authorId:envelope.source
|
|
|
|
sourceDeviceId:envelope.sourceDevice
|
|
|
|
messageBody:body
|
|
|
|
attachmentIds:attachmentIds
|
|
|
|
expiresInSeconds:dataMessage.expireTimer
|
2018-04-27 21:29:19 +02:00
|
|
|
quotedMessage:quotedMessage
|
2018-05-01 17:26:01 +02:00
|
|
|
contactShare:contact];
|
2018-02-07 18:44:09 +01:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
[self finalizeIncomingMessage:incomingMessage
|
|
|
|
thread:oldGroupThread
|
|
|
|
envelope:envelope
|
|
|
|
transaction:transaction];
|
|
|
|
return incomingMessage;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
|
|
|
default: {
|
2017-11-08 20:04:51 +01:00
|
|
|
DDLogWarn(@"%@ Ignoring unknown group message type: %d", self.logTag, (int)dataMessage.group.type);
|
2017-10-03 19:41:48 +02:00
|
|
|
return nil;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2018-05-02 18:43:23 +02:00
|
|
|
if (body.length == 0 && attachmentIds.count < 1 && !contact) {
|
2017-09-14 16:00:34 +02:00
|
|
|
DDLogWarn(@"%@ ignoring empty incoming message from: %@ with timestamp: %lu",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-09-13 21:35:33 +02:00
|
|
|
envelopeAddress(envelope),
|
|
|
|
(unsigned long)timestamp);
|
2017-10-03 19:41:48 +02:00
|
|
|
return nil;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2017-10-03 19:41:48 +02:00
|
|
|
|
|
|
|
DDLogDebug(@"%@ incoming message from: %@ with timestamp: %lu",
|
2017-11-08 20:04:51 +01:00
|
|
|
self.logTag,
|
2017-10-03 19:41:48 +02:00
|
|
|
envelopeAddress(envelope),
|
|
|
|
(unsigned long)timestamp);
|
2018-07-13 20:03:28 +02:00
|
|
|
TSContactThread *thread =
|
|
|
|
[TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
|
2017-10-04 16:06:38 +02:00
|
|
|
|
2018-04-07 21:26:22 +02:00
|
|
|
TSQuotedMessage *_Nullable quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:dataMessage
|
|
|
|
thread:thread
|
|
|
|
transaction:transaction];
|
2018-02-07 18:44:09 +01:00
|
|
|
|
|
|
|
TSIncomingMessage *incomingMessage =
|
|
|
|
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
|
|
|
|
inThread:thread
|
|
|
|
authorId:[thread contactIdentifier]
|
|
|
|
sourceDeviceId:envelope.sourceDevice
|
|
|
|
messageBody:body
|
|
|
|
attachmentIds:attachmentIds
|
|
|
|
expiresInSeconds:dataMessage.expireTimer
|
2018-04-27 21:29:19 +02:00
|
|
|
quotedMessage:quotedMessage
|
2018-05-01 17:26:01 +02:00
|
|
|
contactShare:contact];
|
2018-04-07 19:59:49 +02:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
[self finalizeIncomingMessage:incomingMessage
|
|
|
|
thread:thread
|
|
|
|
envelope:envelope
|
|
|
|
transaction:transaction];
|
|
|
|
return incomingMessage;
|
2017-09-13 21:35:33 +02:00
|
|
|
}
|
2017-10-04 16:06:38 +02:00
|
|
|
}
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
- (void)finalizeIncomingMessage:(TSIncomingMessage *)incomingMessage
|
|
|
|
thread:(TSThread *)thread
|
2018-08-01 16:45:21 +02:00
|
|
|
envelope:(SSKProtoEnvelope *)envelope
|
2017-10-04 16:06:38 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
|
|
|
{
|
2017-10-03 19:41:48 +02:00
|
|
|
OWSAssert(thread);
|
|
|
|
OWSAssert(incomingMessage);
|
2017-10-04 16:06:38 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(transaction);
|
2017-10-03 19:41:48 +02:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
OWSAssert([TSAccountManager isRegistered]);
|
|
|
|
|
|
|
|
if (!thread) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ Can't finalize without thread", self.logTag);
|
2017-10-04 16:06:38 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!incomingMessage) {
|
2017-11-08 20:04:51 +01:00
|
|
|
OWSFail(@"%@ Can't finalize missing message", self.logTag);
|
2017-10-04 16:06:38 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-09-13 21:35:33 +02:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
[incomingMessage saveWithTransaction:transaction];
|
2017-09-13 21:35:33 +02:00
|
|
|
|
2018-04-18 02:53:27 +02:00
|
|
|
// Any messages sent from the current user - from this device or another - should be automatically marked as read.
|
|
|
|
if ([envelope.source isEqualToString:TSAccountManager.localNumber]) {
|
2017-10-04 16:06:38 +02:00
|
|
|
// Don't send a read receipt for messages sent by ourselves.
|
2018-04-18 02:53:27 +02:00
|
|
|
[incomingMessage markAsReadAtTimestamp:envelope.timestamp sendReadReceipt:NO transaction:transaction];
|
2017-10-04 16:06:38 +02:00
|
|
|
}
|
2016-09-08 20:21:10 +02:00
|
|
|
|
2018-04-07 19:59:49 +02:00
|
|
|
TSQuotedMessage *_Nullable quotedMessage = incomingMessage.quotedMessage;
|
|
|
|
if (quotedMessage && quotedMessage.thumbnailAttachmentPointerId) {
|
|
|
|
// We weren't able to derive a local thumbnail, so we'll fetch the referenced attachment.
|
|
|
|
TSAttachmentPointer *attachmentPointer =
|
|
|
|
[TSAttachmentPointer fetchObjectWithUniqueID:quotedMessage.thumbnailAttachmentPointerId
|
|
|
|
transaction:transaction];
|
|
|
|
|
|
|
|
if ([attachmentPointer isKindOfClass:[TSAttachmentPointer class]]) {
|
|
|
|
OWSAttachmentsProcessor *attachmentProcessor =
|
|
|
|
[[OWSAttachmentsProcessor alloc] initWithAttachmentPointer:attachmentPointer
|
|
|
|
networkManager:self.networkManager];
|
|
|
|
|
2018-05-07 18:32:31 +02:00
|
|
|
DDLogDebug(
|
|
|
|
@"%@ downloading thumbnail for message: %lu", self.logTag, (unsigned long)incomingMessage.timestamp);
|
2018-04-07 19:59:49 +02:00
|
|
|
[attachmentProcessor fetchAttachmentsForMessage:incomingMessage
|
|
|
|
transaction:transaction
|
|
|
|
success:^(TSAttachmentStream *_Nonnull attachmentStream) {
|
|
|
|
[self.dbConnection
|
|
|
|
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
|
|
|
[incomingMessage setQuotedMessageThumbnailAttachmentStream:attachmentStream];
|
|
|
|
[incomingMessage saveWithTransaction:transaction];
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
failure:^(NSError *_Nonnull error) {
|
2018-05-07 18:32:31 +02:00
|
|
|
DDLogWarn(@"%@ failed to fetch thumbnail for message: %lu with error: %@",
|
2018-04-07 19:59:49 +02:00
|
|
|
self.logTag,
|
2018-05-07 18:32:31 +02:00
|
|
|
(unsigned long)incomingMessage.timestamp,
|
2018-04-07 19:59:49 +02:00
|
|
|
error);
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 16:06:38 +02:00
|
|
|
|
2018-05-03 17:31:06 +02:00
|
|
|
OWSContact *_Nullable contact = incomingMessage.contactShare;
|
|
|
|
if (contact && contact.avatarAttachmentId) {
|
|
|
|
TSAttachmentPointer *attachmentPointer =
|
|
|
|
[TSAttachmentPointer fetchObjectWithUniqueID:contact.avatarAttachmentId transaction:transaction];
|
|
|
|
|
|
|
|
if (![attachmentPointer isKindOfClass:[TSAttachmentPointer class]]) {
|
|
|
|
OWSFail(@"%@ in %s avatar attachmentPointer was unexpectedly nil", self.logTag, __PRETTY_FUNCTION__);
|
|
|
|
} else {
|
|
|
|
OWSAttachmentsProcessor *attachmentProcessor =
|
|
|
|
[[OWSAttachmentsProcessor alloc] initWithAttachmentPointer:attachmentPointer
|
|
|
|
networkManager:self.networkManager];
|
|
|
|
|
2018-05-07 18:32:31 +02:00
|
|
|
DDLogDebug(@"%@ downloading contact avatar for message: %lu",
|
|
|
|
self.logTag,
|
|
|
|
(unsigned long)incomingMessage.timestamp);
|
2018-05-03 17:31:06 +02:00
|
|
|
[attachmentProcessor fetchAttachmentsForMessage:incomingMessage
|
|
|
|
transaction:transaction
|
|
|
|
success:^(TSAttachmentStream *_Nonnull attachmentStream) {
|
|
|
|
[self.dbConnection
|
|
|
|
asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
|
|
|
[incomingMessage touchWithTransaction:transaction];
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
failure:^(NSError *_Nonnull error) {
|
2018-05-07 18:32:31 +02:00
|
|
|
DDLogWarn(@"%@ failed to fetch contact avatar for message: %lu with error: %@",
|
2018-05-03 17:31:06 +02:00
|
|
|
self.logTag,
|
2018-05-07 18:32:31 +02:00
|
|
|
(unsigned long)incomingMessage.timestamp,
|
2018-05-03 17:31:06 +02:00
|
|
|
error);
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 16:06:38 +02:00
|
|
|
// In case we already have a read receipt for this new message (this happens sometimes).
|
|
|
|
[OWSReadReceiptManager.sharedManager applyEarlyReadReceiptsForIncomingMessage:incomingMessage
|
|
|
|
transaction:transaction];
|
2016-10-05 17:42:44 +02:00
|
|
|
|
2018-04-17 00:38:29 +02:00
|
|
|
[[OWSDisappearingMessagesJob sharedJob] becomeConsistentWithConfigurationForMessage:incomingMessage
|
|
|
|
contactsManager:self.contactsManager
|
|
|
|
transaction:transaction];
|
2017-09-13 21:35:33 +02:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
// Update thread preview in inbox
|
|
|
|
[thread touchWithTransaction:transaction];
|
2016-08-23 22:38:05 +02:00
|
|
|
|
2017-10-04 16:06:38 +02:00
|
|
|
[[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForIncomingMessage:incomingMessage
|
|
|
|
inThread:thread
|
|
|
|
contactsManager:self.contactsManager
|
|
|
|
transaction:transaction];
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2016-10-14 23:00:29 +02:00
|
|
|
#pragma mark - helpers
|
2015-12-07 03:31:43 +01:00
|
|
|
|
2018-08-01 23:13:01 +02:00
|
|
|
- (BOOL)isDataMessageGroupAvatarUpdate:(SSKProtoDataMessage *)dataMessage
|
2016-10-14 23:00:29 +02:00
|
|
|
{
|
2018-08-01 23:13:01 +02:00
|
|
|
return dataMessage.hasGroup && dataMessage.group.type == SSKProtoGroupContextTypeUpdate
|
2016-10-14 23:00:29 +02:00
|
|
|
&& dataMessage.group.hasAvatar;
|
2015-12-07 03:31:43 +01:00
|
|
|
}
|
|
|
|
|
2017-07-25 00:05:26 +02:00
|
|
|
/**
|
|
|
|
* @returns
|
2017-10-03 19:41:48 +02:00
|
|
|
* Group or Contact thread for message, creating a new contact thread if necessary,
|
|
|
|
* but never creating a new group thread.
|
2017-07-25 00:05:26 +02:00
|
|
|
*/
|
2018-08-01 16:45:21 +02:00
|
|
|
- (nullable TSThread *)threadForEnvelope:(SSKProtoEnvelope *)envelope
|
2018-08-01 23:13:01 +02:00
|
|
|
dataMessage:(SSKProtoDataMessage *)dataMessage
|
2017-10-03 19:41:48 +02:00
|
|
|
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
2016-10-05 17:42:44 +02:00
|
|
|
{
|
2017-09-13 21:35:33 +02:00
|
|
|
OWSAssert(envelope);
|
|
|
|
OWSAssert(dataMessage);
|
|
|
|
OWSAssert(transaction);
|
|
|
|
|
2016-10-05 17:42:44 +02:00
|
|
|
if (dataMessage.hasGroup) {
|
2017-10-03 19:41:48 +02:00
|
|
|
NSData *groupId = dataMessage.group.id;
|
|
|
|
OWSAssert(groupId.length > 0);
|
|
|
|
TSGroupThread *_Nullable groupThread = [TSGroupThread threadWithGroupId:groupId transaction:transaction];
|
|
|
|
// This method should only be called from a code path that has already verified
|
|
|
|
// that this is a "known" group.
|
|
|
|
OWSAssert(groupThread);
|
|
|
|
return groupThread;
|
2016-10-05 17:42:44 +02:00
|
|
|
} else {
|
2017-09-13 21:35:33 +02:00
|
|
|
return [TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction];
|
2016-10-05 17:42:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-07 03:31:43 +01:00
|
|
|
@end
|
2016-10-05 17:42:44 +02:00
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|