This commit is contained in:
nielsandriesse 2020-05-08 16:03:00 +10:00
parent 1e300e3d47
commit 238972e695
5 changed files with 18 additions and 52 deletions

View File

@ -34,32 +34,16 @@ public final class ClosedGroupsProtocol : NSObject {
@objc(establishSessionsIfNeededWithClosedGroupMembers:in:)
public static func establishSessionsIfNeeded(with closedGroupMembers: [String], in thread: TSGroupThread) {
func establishSessionsIfNeeded(with hexEncodedPublicKeys: Set<String>) {
storage.dbReadWriteConnection.readWrite { transaction in
hexEncodedPublicKeys.forEach { hexEncodedPublicKey in
guard hexEncodedPublicKey != getUserHexEncodedPublicKey() else { return }
let hasSession = storage.containsSession(hexEncodedPublicKey, deviceId: Int32(OWSDevicePrimaryDeviceId), protocolContext: transaction)
guard !hasSession else { return }
let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction)
let sessionRequestMessage = SessionRequestMessage(thread: thread)
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: sessionRequestMessage, transaction: transaction)
}
}
}
// We could just let the multi device message sending logic take care of slave devices, but that'd mean
// making a request to the file server for each member involved. With the line below we (hopefully) reduce
// that to one request.
LokiFileServerAPI.getDeviceLinks(associatedWith: Set(closedGroupMembers)).map {
Set($0.flatMap { [ $0.master.hexEncodedPublicKey, $0.slave.hexEncodedPublicKey ] }).union(closedGroupMembers)
}.done { hexEncodedPublicKeys in
DispatchQueue.main.async {
establishSessionsIfNeeded(with: hexEncodedPublicKeys)
}
}.catch { _ in
// Try the inefficient way if the file server failed
DispatchQueue.main.async {
establishSessionsIfNeeded(with: Set(closedGroupMembers))
storage.dbReadWriteConnection.readWrite { transaction in
closedGroupMembers.forEach { hexEncodedPublicKey in
guard hexEncodedPublicKey != getUserHexEncodedPublicKey() else { return }
let hasSession = storage.containsSession(hexEncodedPublicKey, deviceId: Int32(OWSDevicePrimaryDeviceId), protocolContext: transaction)
guard !hasSession else { return }
let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction)
thread.save(with: transaction)
let sessionRequestMessage = SessionRequestMessage(thread: thread)
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: sessionRequestMessage, transaction: transaction)
}
}
}

View File

@ -264,8 +264,6 @@ public final class FriendRequestProtocol : NSObject {
}
// The envelope source is set during UD decryption
let hexEncodedPublicKey = envelope.source!
// Don't handle a friend request if we're already handling a session request from someone
guard !SessionManagementProtocol.inFlightSessionRequests.contains(hexEncodedPublicKey) else { return }
// The envelope type is set during UD decryption.
guard envelope.type == .friendRequest else {
print("[Loki] Ignoring friend request logic for non friend request type envelope.")

View File

@ -56,8 +56,10 @@ public final class MultiDeviceProtocol : NSObject {
}
private static func sendMessage(_ messageSend: OWSMessageSend, to destination: MultiDeviceDestination, in transaction: YapDatabaseReadTransaction) -> Promise<Void> {
let (threadPromise, threadPromiseSeal) = Promise<TSContactThread>.pending()
if let thread = TSContactThread.getWithContactId(destination.hexEncodedPublicKey, transaction: transaction) {
let (threadPromise, threadPromiseSeal) = Promise<TSThread>.pending()
if messageSend.message.thread.isGroupThread() {
threadPromiseSeal.fulfill(messageSend.message.thread)
} else if let thread = TSContactThread.getWithContactId(destination.hexEncodedPublicKey, transaction: transaction) {
threadPromiseSeal.fulfill(thread)
} else {
// Dispatch async on the main queue to avoid nested write transactions
@ -73,7 +75,8 @@ public final class MultiDeviceProtocol : NSObject {
let messageSender = SSKEnvironment.shared.messageSender
let (promise, seal) = Promise<Void>.pending()
let shouldSendAutoGeneratedFR = !thread.isContactFriend && !(message is FriendRequestMessage)
&& !SessionMetaProtocol.isThreadNoteToSelf(thread) && message.shouldBeSaved() // shouldBeSaved indicates it isn't a transient message
&& !SessionMetaProtocol.isThreadNoteToSelf(thread) && !thread.isGroupThread() // Group threads work through session requests
&& message.shouldBeSaved() // shouldBeSaved indicates it isn't a transient message
if !shouldSendAutoGeneratedFR {
let messageSendCopy = copy(messageSend, for: destination, with: seal)
messageSender.sendMessage(messageSendCopy)

View File

@ -14,9 +14,6 @@ public final class SessionManagementProtocol : NSObject {
internal static var storage: OWSPrimaryStorage { OWSPrimaryStorage.shared() }
/// The session requests that are currently being handled.
public static var inFlightSessionRequests: Set<String> = []
// MARK: - General
// BEHAVIOR NOTE: OWSMessageSender.throws_encryptedMessageForMessageSend:recipientId:plaintext:transaction: sets
// isFriendRequest to true if the message in question is a friend request or a device linking request, but NOT if
@ -195,7 +192,6 @@ public final class SessionManagementProtocol : NSObject {
public static func handleSessionRequestMessage(_ dataMessage: SSKProtoDataMessage, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadWriteTransaction) {
// The envelope source is set during UD decryption
let hexEncodedPublicKey = envelope.source!
inFlightSessionRequests.insert(hexEncodedPublicKey)
var closedGroupMembers: Set<String> = []
TSGroupThread.enumerateCollectionObjects(with: transaction) { object, _ in
guard let group = object as? TSGroupThread, group.groupModel.groupType == .closedGroup,
@ -203,7 +199,6 @@ public final class SessionManagementProtocol : NSObject {
closedGroupMembers.formUnion(group.groupModel.groupMemberIds)
}
LokiFileServerAPI.getDeviceLinks(associatedWith: closedGroupMembers).ensure {
defer { inFlightSessionRequests.remove(hexEncodedPublicKey) }
storage.dbReadWriteConnection.readWrite { transaction in
let validHEPKs = closedGroupMembers.flatMap {
LokiDatabaseUtilities.getLinkedDeviceHexEncodedPublicKeys(for: $0, in: transaction)

View File

@ -173,23 +173,11 @@ public final class SyncMessagesProtocol : NSObject {
let friendRequestStatus = storage.getFriendRequestStatus(for: hexEncodedPublicKey, transaction: transaction)
switch friendRequestStatus {
case .none, .requestExpired:
let messageSender = SSKEnvironment.shared.messageSender
// We need to send the FR message to all of the user's devices as the contact sync message excludes slave devices
let autoGeneratedFRMessage = MultiDeviceProtocol.getAutoGeneratedMultiDeviceFRMessage(for: hexEncodedPublicKey, in: transaction)
// This takes into account multi device
messageSender.send(autoGeneratedFRMessage, success: {
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
autoGeneratedFRMessage.remove(with: transaction)
}
}
}, failure: { error in
DispatchQueue.main.async {
storage.dbReadWriteConnection.readWrite { transaction in
autoGeneratedFRMessage.remove(with: transaction)
}
}
})
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: autoGeneratedFRMessage, transaction: transaction)
case .requestReceived:
// Not sendFriendRequestAcceptanceMessage(to:using:) to take into account multi device
FriendRequestProtocol.acceptFriendRequest(from: hexEncodedPublicKey, using: transaction)
@ -217,8 +205,6 @@ public final class SyncMessagesProtocol : NSObject {
thread.save(with: transaction)
}
ClosedGroupsProtocol.establishSessionsIfNeeded(with: groupModel.groupMemberIds, in: thread)
let infoMessage = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: thread, messageType: .typeGroupUpdate, customMessage: "You have joined the group.")
infoMessage.save(with: transaction)
}
}