Update for desktop protocol changes

This commit is contained in:
nielsandriesse 2020-07-09 12:10:24 +10:00
parent 2b41a5b84e
commit 1f4d991036
4 changed files with 76 additions and 42 deletions

View File

@ -94,12 +94,12 @@ public final class SessionManagementProtocol : NSObject {
// Check that we don't already have a session
let hasSession = storage.containsSession(publicKey, deviceId: Int32(OWSDevicePrimaryDeviceId), protocolContext: transaction)
guard !hasSession else { return }
// Check that we didn't already send a session request
var hasSentSessionRequest = false
// Check that we didn't already send or process a session request
var hasSentOrProcessedSessionRequest = false
storage.dbReadConnection.read { transaction in
hasSentSessionRequest = storage.getSessionRequestTimestamp(for: publicKey, in: transaction) != nil
hasSentOrProcessedSessionRequest = storage.getSessionRequestTimestamp(for: publicKey, in: transaction) != nil
}
guard !hasSentSessionRequest else { return }
guard !hasSentOrProcessedSessionRequest else { return }
// Create the thread if needed
let thread = TSContactThread.getOrCreateThread(withContactId: publicKey, transaction: transaction)
thread.save(with: transaction)
@ -184,9 +184,9 @@ public final class SessionManagementProtocol : NSObject {
return print("[Loki] Couldn't parse pre key bundle received from: \(publicKey).")
}
if isSessionRequestMessage(protoContent.dataMessage),
let sentSessionRequestTimestamp = storage.getSessionRequestTimestamp(for: publicKey, in: transaction),
envelope.timestamp < NSDate.ows_millisecondsSince1970(for: sentSessionRequestTimestamp) {
// We sent a session request after this one was sent
let sessionRequestTimestamp = storage.getSessionRequestTimestamp(for: publicKey, in: transaction),
envelope.timestamp < NSDate.ows_millisecondsSince1970(for: sessionRequestTimestamp) {
// We sent or processed a session request after this one was sent
return print("[Loki] Ignoring session request from: \(publicKey).")
}
storage.setPreKeyBundle(preKeyBundle, forContact: publicKey, transaction: transaction)
@ -199,10 +199,11 @@ public final class SessionManagementProtocol : NSObject {
let publicKey = envelope.source! // Set during UD decryption
if let sentSessionRequestTimestamp = storage.getSessionRequestTimestamp(for: publicKey, in: transaction),
envelope.timestamp < NSDate.ows_millisecondsSince1970(for: sentSessionRequestTimestamp) {
// We sent a session request after this one was sent
// We sent or processed a session request after this one was sent
print("[Loki] Ignoring session request from: \(publicKey).")
return false
}
storage.setSessionRequestTimestamp(for: publicKey, to: Date(), in: transaction)
sendSessionEstablishedMessage(to: publicKey, in: transaction)
return true
}

View File

@ -25,6 +25,7 @@
#import "OWSIncomingSentMessageTranscript.h"
#import "OWSMessageSender.h"
#import "OWSMessageUtils.h"
#import "OWSOutgoingNullMessage.h"
#import "OWSOutgoingReceiptManager.h"
#import "OWSPrimaryStorage+SessionStore.h"
#import "OWSPrimaryStorage+Loki.h"
@ -482,7 +483,53 @@ NS_ASSUME_NONNULL_BEGIN
} else if (contentProto.typingMessage) {
[self handleIncomingEnvelope:envelope withTypingMessage:contentProto.typingMessage transaction:transaction];
} else if (contentProto.nullMessage) {
OWSLogInfo(@"Received null message.");
// Loki: This is needed for compatibility with refactored desktop clients
// ========
NSString *publicKey = envelope.source;
if (envelope.type == SSKProtoEnvelopeTypeFriendRequest) {
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:publicKey transaction:transaction];
[thread saveWithTransaction:transaction];
OWSOutgoingNullMessage *sessionEstablishedMessage = [[OWSOutgoingNullMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMetaMessageUnspecified
quotedMessage:nil
contactShare:nil
linkPreview:nil];
SSKMessageSenderJobQueue *messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue;
[messageSenderJobQueue addMessage:sessionEstablishedMessage transaction:transaction];
} else {
OWSLogWarn(@"Ignoring null message from: %@.", publicKey);
}
LKFriendRequestStatus friendRequestStatus = [self.primaryStorage getFriendRequestStatusForContact:publicKey transaction:transaction];
if (friendRequestStatus == LKFriendRequestStatusNone || friendRequestStatus == LKFriendRequestStatusRequestExpired) {
[self.primaryStorage setFriendRequestStatus:LKFriendRequestStatusRequestReceived forContact:publicKey transaction:transaction];
} else if (friendRequestStatus == LKFriendRequestStatusRequestSent) {
// Loki: Update device links in a blocking way
// FIXME: This is horrible for performance
// FIXME: ========
// The envelope source is set during UD decryption
if ([ECKeyPair isValidHexEncodedPublicKeyWithCandidate:publicKey]) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[[LKMultiDeviceProtocol updateDeviceLinksIfNeededForPublicKey:envelope.source transaction:transaction].ensureOn(queue, ^() {
dispatch_semaphore_signal(semaphore);
}).catchOn(queue, ^(NSError *error) {
dispatch_semaphore_signal(semaphore);
}) retainUntilComplete];
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC));
}
// FIXME: ========
[self.primaryStorage setFriendRequestStatus:LKFriendRequestStatusFriends forContact:publicKey transaction:transaction];
[LKFriendRequestProtocol sendFriendRequestAcceptedMessageToPublicKey:publicKey using:transaction];
NSString *masterPublicKey = ([LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:publicKey in:transaction] ?: publicKey);
[LKSyncMessagesProtocol syncContactWithPublicKey:masterPublicKey];
}
// ========
} else if (contentProto.receiptMessage) {
[self handleIncomingEnvelope:envelope
withReceiptMessage:contentProto.receiptMessage
@ -1551,26 +1598,6 @@ NS_ASSUME_NONNULL_BEGIN
// Loki: Handle friend request if needed
[LKFriendRequestProtocol handleFriendRequestMessageIfNeededFromEnvelope:envelope using:transaction];
if (body.length == 0 && attachmentPointers.count < 1 && !contact) {
if (envelope.type == SSKProtoEnvelopeTypeFriendRequest) {
// Loki: This is needed for compatibility with refactored desktop clients
[LKSessionManagementProtocol sendSessionEstablishedMessageToPublicKey:publicKey transaction:transaction];
} else {
OWSLogWarn(@"Ignoring empty incoming message from: %@ with timestamp: %lu.", publicKey, (unsigned long)timestamp);
}
return nil;
}
// Loki: This is needed for compatibility with refactored desktop clients
LKFriendRequestStatus friendRequestStatus = [self.primaryStorage getFriendRequestStatusForContact:publicKey transaction:transaction];
if (friendRequestStatus == LKFriendRequestStatusNone || friendRequestStatus == LKFriendRequestStatusRequestExpired) {
[self.primaryStorage setFriendRequestStatus:LKFriendRequestStatusRequestReceived forContact:publicKey transaction:transaction];
} else if (friendRequestStatus == LKFriendRequestStatusRequestSent) {
[self.primaryStorage setFriendRequestStatus:LKFriendRequestStatusFriends forContact:publicKey transaction:transaction];
[LKFriendRequestProtocol sendFriendRequestAcceptedMessageToPublicKey:publicKey using:transaction];
[LKSyncMessagesProtocol syncContactWithPublicKey:masterPublicKey];
}
[self finalizeIncomingMessage:incomingMessage
thread:thread

View File

@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
contactShare:(nullable OWSContact *)contactShare
linkPreview:(nullable OWSLinkPreview *)linkPreview NS_UNAVAILABLE;
linkPreview:(nullable OWSLinkPreview *)linkPreview;
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage;

View File

@ -51,16 +51,21 @@ NS_ASSUME_NONNULL_BEGIN
{
SSKProtoNullMessageBuilder *nullMessageBuilder = [SSKProtoNullMessage builder];
NSUInteger contentLength = self.verificationStateSyncMessage.unpaddedVerifiedLength;
NSUInteger contentLength;
if (self.verificationStateSyncMessage != nil) {
contentLength = self.verificationStateSyncMessage.unpaddedVerifiedLength;
OWSAssertDebug(self.verificationStateSyncMessage.paddingBytesLength > 0);
OWSAssertDebug(self.verificationStateSyncMessage.paddingBytesLength > 0);
// We add the same amount of padding in the VerificationStateSync message and it's coresponding NullMessage so that
// the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage. We pad
// the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be *additionally*
// padded by the superclass while being sent. The end result is we send a NullMessage of a non-distinct size, and a
// verification sync which is ~1-512 bytes larger then that.
contentLength += self.verificationStateSyncMessage.paddingBytesLength;
// We add the same amount of padding in the VerificationStateSync message and it's coresponding NullMessage so that
// the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage. We pad
// the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be *additionally*
// padded by the superclass while being sent. The end result is we send a NullMessage of a non-distinct size, and a
// verification sync which is ~1-512 bytes larger then that.
contentLength += self.verificationStateSyncMessage.paddingBytesLength;
} else {
contentLength = arc4random_uniform(512);
}
OWSAssertDebug(contentLength > 0);
@ -68,8 +73,8 @@ NS_ASSUME_NONNULL_BEGIN
NSError *error;
SSKProtoNullMessage *_Nullable nullMessage = [nullMessageBuilder buildAndReturnError:&error];
if (error || !nullMessage) {
OWSFailDebug(@"could not build protobuf: %@", error);
if (error != nil || nullMessage == nil) {
OWSFailDebug(@"Couldn't build protobuf due to error: %@.", error);
return nil;
}
@ -77,10 +82,11 @@ NS_ASSUME_NONNULL_BEGIN
contentBuilder.nullMessage = nullMessage;
NSData *_Nullable contentData = [contentBuilder buildSerializedDataAndReturnError:&error];
if (error || !contentData) {
OWSFailDebug(@"could not serialize protobuf: %@", error);
if (error != nil || contentData == nil) {
OWSFailDebug(@"Couldn't serialize protobuf due to error: %@.", error);
return nil;
}
return contentData;
}