diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index 7fc8dc1e7..2fcebc234 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -935,7 +935,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; if (isGroupMessage || isDeviceLinkMessage) { [self sendMessage:messageSend]; } else { - BOOL isSilentMessage = message.isSilent; + BOOL isSilentMessage = message.isSilent || [message isKindOfClass:LKEphemeralMessage.class]; BOOL isFriendRequestMessage = [message isKindOfClass:LKFriendRequestMessage.class]; [[LKAPI getDestinationsFor:contactID] .thenOn(OWSDispatch.sendingQueue, ^(NSArray *destinations) { @@ -1160,9 +1160,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; // so that we can learn from the service whether or not there are // linked devices that we don't know about. OWSLogWarn(@"Sending a message with no device messages."); - - // Loki: We don't handle linked devices yet so it's better to just exit early - // This would only occur if we're sending a message to ourself + NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError(); [error setIsRetryable:NO]; return messageSend.failure(error); @@ -1631,20 +1629,21 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; messageSend.isLocalNumber, messageSend.isUDSend); - // Loki: Since we don't support multi-device sending yet, just send it to the primary device - NSMutableArray *deviceIds = [NSMutableArray arrayWithObject:@(OWSDevicePrimaryDeviceId)]; - - /* Loki: Original code - NSMutableArray *deviceIds = [recipient.devices mutableCopy]; - */ - - OWSAssertDebug(deviceIds); + NSString *userHexEncodedPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey; + __block NSMutableSet *recipientIDs = [NSSet setWithObject:recipient.uniqueId]; + if ([messageSend.message isKindOfClass:OWSOutgoingSyncMessage.class]) { + [OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:userHexEncodedPublicKey in:transaction] ?: userHexEncodedPublicKey; + NSSet *linkedDeviceHexEncodedPublicKeys = [LKDatabaseUtilities getLinkedDeviceHexEncodedPublicKeysFor:userHexEncodedPublicKey in:transaction]; + recipientIDs = [recipientIDs setByAddingObjectsFromSet:linkedDeviceHexEncodedPublicKeys].mutableCopy; + }]; + } if (messageSend.isLocalNumber) { - [deviceIds removeObject:@(OWSDevicePrimaryDeviceId)]; + [recipientIDs removeObject:userHexEncodedPublicKey]; } - for (NSNumber *deviceId in deviceIds) { + for (NSString *recipientID in recipientIDs) { @try { // This may involve blocking network requests, so we do it _before_ // we open a transaction. @@ -1653,7 +1652,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; BOOL isFriendRequest = [messageSend.message isKindOfClass:LKFriendRequestMessage.class]; BOOL isDeviceLinkMessage = [messageSend.message isKindOfClass:LKDeviceLinkMessage.class]; if (!isFriendRequest && !isDeviceLinkMessage) { - [self throws_ensureRecipientHasSessionForMessageSend:messageSend deviceId:deviceId]; + [self throws_ensureRecipientHasSessionForMessageSend:messageSend deviceId:@(OWSDevicePrimaryDeviceId)]; } __block NSDictionary *_Nullable messageDict; @@ -1662,7 +1661,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { @try { messageDict = [self throws_encryptedMessageForMessageSend:messageSend - deviceId:deviceId + recipientID:recipientID plainText:plainText transaction:transaction]; } @catch (NSException *exception) { @@ -1684,7 +1683,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; if ([exception.name isEqualToString:OWSMessageSenderInvalidDeviceException]) { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [recipient updateRegisteredRecipientWithDevicesToAdd:nil - devicesToRemove:@[ deviceId ] + devicesToRemove:@[ @(OWSDevicePrimaryDeviceId) ] transaction:transaction]; }]; } else { @@ -1883,43 +1882,40 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } - (nullable NSDictionary *)throws_encryptedMessageForMessageSend:(OWSMessageSend *)messageSend - deviceId:(NSNumber *)deviceId + recipientID:(NSString *)recipientID plainText:(NSData *)plainText transaction:(YapDatabaseReadWriteTransaction *)transaction { OWSAssertDebug(messageSend); - OWSAssertDebug(deviceId); + OWSAssertDebug(recipientID); OWSAssertDebug(plainText); OWSAssertDebug(transaction); OWSPrimaryStorage *storage = self.primaryStorage; TSOutgoingMessage *message = messageSend.message; - SignalRecipient *recipient = messageSend.recipient; - NSString *recipientId = recipient.recipientId; - OWSAssertDebug(recipientId.length > 0); // Loki: Both for friend request messages and device link messages we use fallback encryption as we don't necessarily have a session yet BOOL isFriendRequest = [messageSend.message isKindOfClass:LKFriendRequestMessage.class]; BOOL isDeviceLinkMessage = [messageSend.message isKindOfClass:LKDeviceLinkMessage.class]; if (isFriendRequest || isDeviceLinkMessage) { - return [self throws_encryptedFriendRequestOrDeviceLinkMessageForMessageSend:messageSend deviceId:deviceId plainText:plainText]; + return [self throws_encryptedFriendRequestOrDeviceLinkMessageForMessageSend:messageSend deviceId:@(OWSDevicePrimaryDeviceId) plainText:plainText]; } // This may throw an exception. - if (![storage containsSession:recipientId deviceId:[deviceId intValue] protocolContext:transaction]) { + if (![storage containsSession:recipientID deviceId:@(OWSDevicePrimaryDeviceId).intValue protocolContext:transaction]) { NSString *missingSessionException = @"missingSessionException"; OWSRaiseException(missingSessionException, @"Unexpectedly missing session for recipient: %@, device: %@", - recipientId, - deviceId); + recipientID, + @(OWSDevicePrimaryDeviceId)); } SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storage preKeyStore:storage signedPreKeyStore:storage identityKeyStore:self.identityManager - recipientId:recipientId - deviceId:[deviceId intValue]]; + recipientId:recipientID + deviceId:@(OWSDevicePrimaryDeviceId).intValue]; NSData *_Nullable serializedMessage; TSWhisperMessageType messageType; @@ -1935,8 +1931,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; OWSRaiseException(@"SecretSessionCipherFailure", @"Can't create secret session cipher."); } - serializedMessage = [secretCipher throwswrapped_encryptMessageWithRecipientId:recipientId - deviceId:deviceId.intValue + serializedMessage = [secretCipher throwswrapped_encryptMessageWithRecipientId:recipientID + deviceId:@(OWSDevicePrimaryDeviceId).intValue paddedPlaintext:[plainText paddedMessageBody] senderCertificate:messageSend.senderCertificate protocolContext:transaction @@ -1962,8 +1958,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; BOOL isPing = addressMessage != nil && addressMessage.isPing; OWSMessageServiceParams *messageParams = [[OWSMessageServiceParams alloc] initWithType:messageType - recipientId:recipientId - device:[deviceId intValue] + recipientId:recipientID + device:@(OWSDevicePrimaryDeviceId).intValue content:serializedMessage isSilent:isSilent isOnline:isOnline