Browse Source

WIP

pull/313/head
nielsandriesse 2 years ago
parent
commit
15c6784f0f
  1. 2
      SessionMessagingKit/Jobs/MessageReceiveJob.swift
  2. 2
      SessionMessagingKit/Jobs/MessageSendJob.swift
  3. 2
      SessionMessagingKit/Messages/Control Message/ClosedGroupUpdate.swift
  4. 39
      SessionMessagingKit/Messages/Control Message/NullMessage.swift
  5. 4
      SessionMessagingKit/Messages/Control Message/SessionRequest.swift
  6. 2
      SessionMessagingKit/Messages/Control Message/TypingIndicator.swift
  7. 8
      SessionMessagingKit/Sending & Receiving/MessageSender.swift
  8. 76
      Signal.xcodeproj/project.pbxproj
  9. 7
      SignalUtilitiesKit/ClosedGroupPoller.swift
  10. 92
      SignalUtilitiesKit/ClosedGroupsProtocol.swift
  11. 25
      SignalUtilitiesKit/MessageSender+Promise.swift
  12. 256
      SignalUtilitiesKit/MessageSenderJobQueue.swift
  13. 4
      SignalUtilitiesKit/Meta/SignalUtilitiesKit.h
  14. 274
      SignalUtilitiesKit/MultiDeviceProtocol.swift
  15. 47
      SignalUtilitiesKit/OWSMessageDecrypter.h
  16. 686
      SignalUtilitiesKit/OWSMessageDecrypter.m
  17. 24
      SignalUtilitiesKit/OWSMessageHandler.h
  18. 183
      SignalUtilitiesKit/OWSMessageHandler.m
  19. 33
      SignalUtilitiesKit/OWSMessageManager.h
  20. 1735
      SignalUtilitiesKit/OWSMessageManager.m
  21. 28
      SignalUtilitiesKit/OWSMessageReceiver.h
  22. 513
      SignalUtilitiesKit/OWSMessageReceiver.m
  23. 96
      SignalUtilitiesKit/OWSMessageSend.swift
  24. 121
      SignalUtilitiesKit/OWSMessageSender.h
  25. 1744
      SignalUtilitiesKit/OWSMessageSender.m
  26. 7
      SignalUtilitiesKit/Poller.swift
  27. 15
      SignalUtilitiesKit/SessionManagementProtocol.swift
  28. 13
      SignalUtilitiesKit/SessionMetaProtocol.swift
  29. 14
      SignalUtilitiesKit/SyncMessagesProtocol.swift
  30. 2
      SignalUtilitiesKit/TSConstants.h
  31. 2
      SignalUtilitiesKit/TSConstants.m
  32. 21
      SignalUtilitiesKit/TypingIndicators.swift
  33. 21
      SignalUtilitiesKit/Utilities/Destination+Conversion.swift
  34. 17
      SignalUtilitiesKit/Utilities/MessageSender+Utilities.swift

2
SessionMessagingKit/Jobs/MessageReceiveJob.swift

@ -9,7 +9,7 @@ public final class MessageReceiveJob : NSObject, Job, NSCoding { // NSObject/NS
public static let maxFailureCount: UInt = 10
// MARK: Initialization
init(data: Data) {
public init(data: Data) {
self.data = data
}

2
SessionMessagingKit/Jobs/MessageSendJob.swift

@ -14,7 +14,7 @@ public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCodi
@objc public convenience init(message: Message, publicKey: String) { self.init(message: message, destination: .contact(publicKey: publicKey)) }
@objc public convenience init(message: Message, groupPublicKey: String) { self.init(message: message, destination: .closedGroup(groupPublicKey: groupPublicKey)) }
init(message: Message, destination: Message.Destination) {
public init(message: Message, destination: Message.Destination) {
self.message = message
self.destination = destination
}

2
SessionMessagingKit/Messages/Control Message/ClosedGroupUpdate.swift

@ -14,6 +14,8 @@ public final class ClosedGroupUpdate : ControlMessage {
}
// MARK: Initialization
public override init() { super.init() }
internal init(kind: Kind) {
super.init()
self.kind = kind

39
SessionMessagingKit/Messages/Control Message/NullMessage.swift

@ -0,0 +1,39 @@
import SessionProtocolKit
import SessionUtilitiesKit
@objc(SNNullMessage)
public final class NullMessage : ControlMessage {
// MARK: Initialization
public override init() { super.init() }
// MARK: Coding
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
public override func encode(with coder: NSCoder) {
super.encode(with: coder)
}
// MARK: Proto Conversion
public override class func fromProto(_ proto: SNProtoContent) -> NullMessage? {
guard proto.nullMessage != nil else { return nil }
return NullMessage()
}
public override func toProto() -> SNProtoContent? {
let nullMessageProto = SNProtoNullMessage.builder()
let paddingSize = UInt.random(in: 0..<512) // random(in:) uses the system's default random generator, which is cryptographically secure
let padding = Data.getSecureRandomData(ofSize: paddingSize)!
nullMessageProto.setPadding(padding)
let contentProto = SNProtoContent.builder()
do {
contentProto.setNullMessage(try nullMessageProto.build())
return try contentProto.build()
} catch {
SNLog("Couldn't construct null message proto from: \(self).")
return nil
}
}
}

4
SessionMessagingKit/Messages/Control Message/SessionRequest.swift

@ -3,9 +3,11 @@ import SessionUtilitiesKit
@objc(SNSessionRequest)
public final class SessionRequest : ControlMessage {
private var preKeyBundle: PreKeyBundle?
public var preKeyBundle: PreKeyBundle?
// MARK: Initialization
public override init() { super.init() }
internal init(preKeyBundle: PreKeyBundle) {
super.init()
self.preKeyBundle = preKeyBundle

2
SessionMessagingKit/Messages/Control Message/TypingIndicator.swift

@ -29,6 +29,8 @@ public final class TypingIndicator : ControlMessage {
public override var isValid: Bool { kind != nil }
// MARK: Initialization
public override init() { super.init() }
internal init(kind: Kind) {
super.init()
self.kind = kind

8
SessionMessagingKit/Sending & Receiving/MessageSender.swift

@ -20,7 +20,7 @@ public enum MessageSender {
}
}
internal static func send(_ message: Message, to destination: Message.Destination, using transaction: Any) -> Promise<Void> {
public static func send(_ message: Message, to destination: Message.Destination, using transaction: Any) -> Promise<Void> {
switch destination {
case .contact(_), .closedGroup(_): return sendToSnodeDestination(destination, message: message, using: transaction)
case .openGroup(_, _): return sendToOpenGroupDestination(destination, message: message, using: transaction)
@ -141,6 +141,12 @@ public enum MessageSender {
}
internal static func sendToOpenGroupDestination(_ destination: Message.Destination, message: Message, using transaction: Any) -> Promise<Void> {
message.sentTimestamp = NSDate.millisecondTimestamp()
switch destination {
case .contact(_): preconditionFailure()
case .closedGroup(_): preconditionFailure()
case .openGroup(let channel, let server): message.recipient = "\(server).\(channel)"
}
guard message.isValid else { return Promise(error: Error.invalidMessage) }
let (channel, server) = { () -> (UInt64, String) in
switch destination {

76
Signal.xcodeproj/project.pbxproj

@ -362,7 +362,6 @@
C33FDC21255A581F00E217F9 /* OWSPrimaryStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA67255A57F900E217F9 /* OWSPrimaryStorage.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC22255A581F00E217F9 /* OWSBlockingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA68255A57F900E217F9 /* OWSBlockingManager.m */; };
C33FDC23255A581F00E217F9 /* SSKPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA69255A57F900E217F9 /* SSKPreferences.swift */; };
C33FDC24255A581F00E217F9 /* OWSMessageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA6A255A57F900E217F9 /* OWSMessageManager.m */; };
C33FDC25255A581F00E217F9 /* OWSDisappearingConfigurationUpdateInfoMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA6B255A57FA00E217F9 /* OWSDisappearingConfigurationUpdateInfoMessage.m */; };
C33FDC26255A581F00E217F9 /* ProtoUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA6C255A57FA00E217F9 /* ProtoUtils.m */; };
C33FDC27255A581F00E217F9 /* YapDatabase+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA6D255A57FA00E217F9 /* YapDatabase+Promise.swift */; };
@ -401,7 +400,6 @@
C33FDC49255A581F00E217F9 /* NSTimer+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA8F255A57FD00E217F9 /* NSTimer+OWS.m */; };
C33FDC4A255A582000E217F9 /* TSYapDatabaseObject.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA90255A57FD00E217F9 /* TSYapDatabaseObject.m */; };
C33FDC4B255A582000E217F9 /* LKSyncOpenGroupsMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA91255A57FD00E217F9 /* LKSyncOpenGroupsMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC4C255A582000E217F9 /* OWSMessageSender.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA92255A57FE00E217F9 /* OWSMessageSender.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC4E255A582000E217F9 /* Data+Streaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA94255A57FE00E217F9 /* Data+Streaming.swift */; };
C33FDC4F255A582000E217F9 /* OWSChunkedOutputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA95255A57FE00E217F9 /* OWSChunkedOutputStream.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC50255A582000E217F9 /* OWSDispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDA96255A57FE00E217F9 /* OWSDispatch.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -426,7 +424,6 @@
C33FDC63255A582000E217F9 /* Mnemonic.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAA9255A580000E217F9 /* Mnemonic.swift */; };
C33FDC64255A582000E217F9 /* NSObject+Casting.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAAA255A580000E217F9 /* NSObject+Casting.m */; };
C33FDC65255A582000E217F9 /* OWSWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAAB255A580000E217F9 /* OWSWebSocket.m */; };
C33FDC66255A582000E217F9 /* OWSMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAAC255A580000E217F9 /* OWSMessageHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC67255A582000E217F9 /* OWSDeviceProvisioner.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAAD255A580000E217F9 /* OWSDeviceProvisioner.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC68255A582000E217F9 /* OWSReceiptsForSenderMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAAE255A580000E217F9 /* OWSReceiptsForSenderMessage.m */; };
C33FDC69255A582000E217F9 /* String+Trimming.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAAF255A580000E217F9 /* String+Trimming.swift */; };
@ -434,7 +431,6 @@
C33FDC6B255A582000E217F9 /* OWSStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAB1255A580000E217F9 /* OWSStorage.m */; };
C33FDC6C255A582000E217F9 /* TSNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAB2255A580000E217F9 /* TSNetworkManager.m */; };
C33FDC6D255A582000E217F9 /* TSContactThread.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAB3255A580000E217F9 /* TSContactThread.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC6E255A582000E217F9 /* OWSMessageReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAB4255A580000E217F9 /* OWSMessageReceiver.m */; };
C33FDC6F255A582000E217F9 /* TSNetworkManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAB5255A580000E217F9 /* TSNetworkManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC70255A582000E217F9 /* SyncMessagesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAB6255A580100E217F9 /* SyncMessagesProtocol.swift */; };
C33FDC71255A582000E217F9 /* OWSFailedMessagesJob.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDAB7255A580100E217F9 /* OWSFailedMessagesJob.m */; };
@ -456,7 +452,6 @@
C33FDC83255A582000E217F9 /* OWSContact.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAC9255A580200E217F9 /* OWSContact.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDC84255A582000E217F9 /* LokiMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDACA255A580200E217F9 /* LokiMessage.swift */; };
C33FDC85255A582000E217F9 /* CDSSigningCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDACB255A580200E217F9 /* CDSSigningCertificate.m */; };
C33FDC86255A582000E217F9 /* OWSMessageSend.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDACC255A580200E217F9 /* OWSMessageSend.swift */; };
C33FDC87255A582000E217F9 /* SSKJobRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDACD255A580200E217F9 /* SSKJobRecord.m */; };
C33FDC88255A582000E217F9 /* OWSVerificationStateSyncMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDACE255A580300E217F9 /* OWSVerificationStateSyncMessage.m */; };
C33FDC89255A582000E217F9 /* OWSAttachmentDownloads.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDACF255A580300E217F9 /* OWSAttachmentDownloads.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -563,7 +558,6 @@
C33FDCF4255A582000E217F9 /* Poller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB3A255A580B00E217F9 /* Poller.swift */; };
C33FDCF5255A582000E217F9 /* NSNotificationCenter+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB3B255A580B00E217F9 /* NSNotificationCenter+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDCF7255A582000E217F9 /* OWSProfileKeyMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB3D255A580B00E217F9 /* OWSProfileKeyMessage.m */; };
C33FDCF8255A582000E217F9 /* OWSMessageSender.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB3E255A580B00E217F9 /* OWSMessageSender.m */; };
C33FDCF9255A582000E217F9 /* String+SSK.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB3F255A580C00E217F9 /* String+SSK.swift */; };
C33FDCFA255A582000E217F9 /* SignalIOSProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB40255A580C00E217F9 /* SignalIOSProto.swift */; };
C33FDCFB255A582000E217F9 /* MIMETypeUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB41255A580C00E217F9 /* MIMETypeUtil.m */; };
@ -623,7 +617,6 @@
C33FDD33255A582000E217F9 /* PhoneNumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB79255A581000E217F9 /* PhoneNumberUtil.m */; };
C33FDD34255A582000E217F9 /* NotificationsProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB7A255A581000E217F9 /* NotificationsProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD36255A582000E217F9 /* OWSVerificationStateChangeMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB7C255A581000E217F9 /* OWSVerificationStateChangeMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD37255A582000E217F9 /* OWSMessageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB7D255A581100E217F9 /* OWSMessageManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD38255A582000E217F9 /* TSPreKeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB7E255A581100E217F9 /* TSPreKeyManager.m */; };
C33FDD39255A582000E217F9 /* FullTextSearchFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB7F255A581100E217F9 /* FullTextSearchFinder.swift */; };
C33FDD3A255A582000E217F9 /* Notification+Loki.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB80255A581100E217F9 /* Notification+Loki.swift */; };
@ -642,7 +635,6 @@
C33FDD47255A582000E217F9 /* DeviceLinkingSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB8D255A581200E217F9 /* DeviceLinkingSessionDelegate.swift */; };
C33FDD48255A582000E217F9 /* OWSContact+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB8E255A581200E217F9 /* OWSContact+Private.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD49255A582000E217F9 /* ParamParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB8F255A581200E217F9 /* ParamParser.swift */; };
C33FDD4A255A582000E217F9 /* OWSMessageDecrypter.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB90255A581200E217F9 /* OWSMessageDecrypter.m */; };
C33FDD4B255A582000E217F9 /* ProtoUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB91255A581200E217F9 /* ProtoUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD4C255A582000E217F9 /* OWSDeviceProvisioningService.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB92255A581200E217F9 /* OWSDeviceProvisioningService.m */; };
C33FDD4D255A582000E217F9 /* PreKeyBundle+jsonDict.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB93255A581200E217F9 /* PreKeyBundle+jsonDict.m */; };
@ -653,7 +645,6 @@
C33FDD52255A582000E217F9 /* DeviceNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB98255A581300E217F9 /* DeviceNames.swift */; };
C33FDD53255A582000E217F9 /* OWSPrimaryStorage+keyFromIntLong.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB99255A581300E217F9 /* OWSPrimaryStorage+keyFromIntLong.m */; };
C33FDD54255A582000E217F9 /* OWS2FAManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB9A255A581300E217F9 /* OWS2FAManager.m */; };
C33FDD55255A582000E217F9 /* MessageSenderJobQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB9B255A581300E217F9 /* MessageSenderJobQueue.swift */; };
C33FDD56255A582000E217F9 /* TSIncomingMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB9C255A581300E217F9 /* TSIncomingMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD57255A582000E217F9 /* OWSCallMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDB9D255A581300E217F9 /* OWSCallMessageHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD58255A582000E217F9 /* TSAttachmentPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB9E255A581400E217F9 /* TSAttachmentPointer.m */; };
@ -691,12 +682,10 @@
C33FDD7C255A582000E217F9 /* SSKAsserts.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBC2255A581700E217F9 /* SSKAsserts.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD7D255A582000E217F9 /* AnyPromise+Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBC3255A581700E217F9 /* AnyPromise+Conversion.swift */; };
C33FDD7E255A582000E217F9 /* TypingIndicatorMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBC4255A581700E217F9 /* TypingIndicatorMessage.swift */; };
C33FDD80255A582000E217F9 /* OWSMessageReceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBC6255A581700E217F9 /* OWSMessageReceiver.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD82255A582000E217F9 /* OWSFingerprint.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBC8255A581700E217F9 /* OWSFingerprint.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD83255A582000E217F9 /* CreatePreKeysOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBC9255A581700E217F9 /* CreatePreKeysOperation.swift */; };
C33FDD84255A582000E217F9 /* LKGroupUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBCA255A581700E217F9 /* LKGroupUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD85255A582000E217F9 /* TSInvalidIdentityKeyReceivingErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBCB255A581800E217F9 /* TSInvalidIdentityKeyReceivingErrorMessage.m */; };
C33FDD86255A582000E217F9 /* MultiDeviceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBCC255A581800E217F9 /* MultiDeviceProtocol.swift */; };
C33FDD88255A582000E217F9 /* OWSMessageServiceParams.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBCE255A581800E217F9 /* OWSMessageServiceParams.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD89255A582000E217F9 /* OWSFingerprintBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBCF255A581800E217F9 /* OWSFingerprintBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD8A255A582000E217F9 /* OnionRequestAPI+Encryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBD0255A581800E217F9 /* OnionRequestAPI+Encryption.swift */; };
@ -733,7 +722,6 @@
C33FDDA9255A582000E217F9 /* TSStorageKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBEF255A581B00E217F9 /* TSStorageKeys.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDAA255A582000E217F9 /* LokiDatabaseUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBF0255A581B00E217F9 /* LokiDatabaseUtilities.swift */; };
C33FDDAB255A582000E217F9 /* OWSIdentityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBF1255A581B00E217F9 /* OWSIdentityManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDAC255A582000E217F9 /* MessageSender+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBF2255A581B00E217F9 /* MessageSender+Promise.swift */; };
C33FDDAD255A582000E217F9 /* OWSBlockedPhoneNumbersMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBF3255A581B00E217F9 /* OWSBlockedPhoneNumbersMessage.h */; };
C33FDDAE255A582000E217F9 /* DisplayNameUtilities2.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBF4255A581B00E217F9 /* DisplayNameUtilities2.swift */; };
C33FDDAF255A582000E217F9 /* OWSDeviceProvisioningService.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBF5255A581B00E217F9 /* OWSDeviceProvisioningService.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -743,7 +731,6 @@
C33FDDB3255A582000E217F9 /* OWSError.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBF9255A581C00E217F9 /* OWSError.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDB4255A582000E217F9 /* PhoneNumberUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBFA255A581C00E217F9 /* PhoneNumberUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDB5255A582000E217F9 /* Storage+PublicChats.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBFB255A581C00E217F9 /* Storage+PublicChats.swift */; };
C33FDDB6255A582000E217F9 /* OWSMessageHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBFC255A581C00E217F9 /* OWSMessageHandler.m */; };
C33FDDB7255A582000E217F9 /* OWSPrimaryStorage+Calling.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBFD255A581C00E217F9 /* OWSPrimaryStorage+Calling.m */; };
C33FDDB8255A582000E217F9 /* NSSet+Functional.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBFE255A581C00E217F9 /* NSSet+Functional.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDB9255A582000E217F9 /* OWSOutgoingSyncMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBFF255A581C00E217F9 /* OWSOutgoingSyncMessage.m */; };
@ -761,7 +748,6 @@
C33FDDC5255A582000E217F9 /* OWSError.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDC0B255A581D00E217F9 /* OWSError.m */; };
C33FDDC6255A582000E217F9 /* TSInfoMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDC0C255A581E00E217F9 /* TSInfoMessage.m */; };
C33FDDC7255A582000E217F9 /* OWSProvisioningMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDC0D255A581E00E217F9 /* OWSProvisioningMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDC8255A582000E217F9 /* OWSMessageDecrypter.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDC0E255A581E00E217F9 /* OWSMessageDecrypter.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDC9255A582000E217F9 /* LKDeviceLinkMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDC0F255A581E00E217F9 /* LKDeviceLinkMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDDCA255A582000E217F9 /* ProofOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDC10255A581E00E217F9 /* ProofOfWork.swift */; };
C33FDDCB255A582000E217F9 /* TSSocketManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDC11255A581E00E217F9 /* TSSocketManager.m */; };
@ -1156,6 +1142,9 @@
C3CA3AB4255CDAE600F4C6D4 /* japanese.txt in Resources */ = {isa = PBXBuildFile; fileRef = C3CA3AB3255CDAE600F4C6D4 /* japanese.txt */; };
C3CA3ABE255CDB0D00F4C6D4 /* portuguese.txt in Resources */ = {isa = PBXBuildFile; fileRef = C3CA3ABD255CDB0D00F4C6D4 /* portuguese.txt */; };
C3CA3AC8255CDB2900F4C6D4 /* spanish.txt in Resources */ = {isa = PBXBuildFile; fileRef = C3CA3AC7255CDB2900F4C6D4 /* spanish.txt */; };
C3CA3B13255CF18200F4C6D4 /* Destination+Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CA3B12255CF18200F4C6D4 /* Destination+Conversion.swift */; };
C3CA3B1D255CF3C800F4C6D4 /* MessageSender+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CA3B1C255CF3C800F4C6D4 /* MessageSender+Utilities.swift */; };
C3CA3B2F255CF84E00F4C6D4 /* NullMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CA3B2E255CF84E00F4C6D4 /* NullMessage.swift */; };
C3D0972B2510499C00F6E3E4 /* BackgroundPoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */; };
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */; };
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */; };
@ -1728,7 +1717,6 @@
C33FDA67255A57F900E217F9 /* OWSPrimaryStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSPrimaryStorage.h; sourceTree = "<group>"; };
C33FDA68255A57F900E217F9 /* OWSBlockingManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSBlockingManager.m; sourceTree = "<group>"; };
C33FDA69255A57F900E217F9 /* SSKPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSKPreferences.swift; sourceTree = "<group>"; };
C33FDA6A255A57F900E217F9 /* OWSMessageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageManager.m; sourceTree = "<group>"; };
C33FDA6B255A57FA00E217F9 /* OWSDisappearingConfigurationUpdateInfoMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDisappearingConfigurationUpdateInfoMessage.m; sourceTree = "<group>"; };
C33FDA6C255A57FA00E217F9 /* ProtoUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProtoUtils.m; sourceTree = "<group>"; };
C33FDA6D255A57FA00E217F9 /* YapDatabase+Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "YapDatabase+Promise.swift"; sourceTree = "<group>"; };
@ -1767,7 +1755,6 @@
C33FDA8F255A57FD00E217F9 /* NSTimer+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+OWS.m"; sourceTree = "<group>"; };
C33FDA90255A57FD00E217F9 /* TSYapDatabaseObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSYapDatabaseObject.m; sourceTree = "<group>"; };
C33FDA91255A57FD00E217F9 /* LKSyncOpenGroupsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LKSyncOpenGroupsMessage.h; sourceTree = "<group>"; };
C33FDA92255A57FE00E217F9 /* OWSMessageSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageSender.h; sourceTree = "<group>"; };
C33FDA94255A57FE00E217F9 /* Data+Streaming.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+Streaming.swift"; sourceTree = "<group>"; };
C33FDA95255A57FE00E217F9 /* OWSChunkedOutputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSChunkedOutputStream.h; sourceTree = "<group>"; };
C33FDA96255A57FE00E217F9 /* OWSDispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDispatch.h; sourceTree = "<group>"; };
@ -1792,7 +1779,6 @@
C33FDAA9255A580000E217F9 /* Mnemonic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mnemonic.swift; sourceTree = "<group>"; };
C33FDAAA255A580000E217F9 /* NSObject+Casting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Casting.m"; sourceTree = "<group>"; };
C33FDAAB255A580000E217F9 /* OWSWebSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSWebSocket.m; sourceTree = "<group>"; };
C33FDAAC255A580000E217F9 /* OWSMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageHandler.h; sourceTree = "<group>"; };
C33FDAAD255A580000E217F9 /* OWSDeviceProvisioner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDeviceProvisioner.h; sourceTree = "<group>"; };
C33FDAAE255A580000E217F9 /* OWSReceiptsForSenderMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSReceiptsForSenderMessage.m; sourceTree = "<group>"; };
C33FDAAF255A580000E217F9 /* String+Trimming.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Trimming.swift"; sourceTree = "<group>"; };
@ -1800,7 +1786,6 @@
C33FDAB1255A580000E217F9 /* OWSStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSStorage.m; sourceTree = "<group>"; };
C33FDAB2255A580000E217F9 /* TSNetworkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSNetworkManager.m; sourceTree = "<group>"; };
C33FDAB3255A580000E217F9 /* TSContactThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContactThread.h; sourceTree = "<group>"; };
C33FDAB4255A580000E217F9 /* OWSMessageReceiver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageReceiver.m; sourceTree = "<group>"; };
C33FDAB5255A580000E217F9 /* TSNetworkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSNetworkManager.h; sourceTree = "<group>"; };
C33FDAB6255A580100E217F9 /* SyncMessagesProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncMessagesProtocol.swift; sourceTree = "<group>"; };
C33FDAB7255A580100E217F9 /* OWSFailedMessagesJob.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSFailedMessagesJob.m; sourceTree = "<group>"; };
@ -1822,7 +1807,6 @@
C33FDAC9255A580200E217F9 /* OWSContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContact.h; sourceTree = "<group>"; };
C33FDACA255A580200E217F9 /* LokiMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LokiMessage.swift; sourceTree = "<group>"; };
C33FDACB255A580200E217F9 /* CDSSigningCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDSSigningCertificate.m; sourceTree = "<group>"; };
C33FDACC255A580200E217F9 /* OWSMessageSend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSMessageSend.swift; sourceTree = "<group>"; };
C33FDACD255A580200E217F9 /* SSKJobRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKJobRecord.m; sourceTree = "<group>"; };
C33FDACE255A580300E217F9 /* OWSVerificationStateSyncMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSVerificationStateSyncMessage.m; sourceTree = "<group>"; };
C33FDACF255A580300E217F9 /* OWSAttachmentDownloads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAttachmentDownloads.h; sourceTree = "<group>"; };
@ -1929,7 +1913,6 @@
C33FDB3A255A580B00E217F9 /* Poller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poller.swift; sourceTree = "<group>"; };
C33FDB3B255A580B00E217F9 /* NSNotificationCenter+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+OWS.h"; sourceTree = "<group>"; };
C33FDB3D255A580B00E217F9 /* OWSProfileKeyMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSProfileKeyMessage.m; sourceTree = "<group>"; };
C33FDB3E255A580B00E217F9 /* OWSMessageSender.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageSender.m; sourceTree = "<group>"; };
C33FDB3F255A580C00E217F9 /* String+SSK.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+SSK.swift"; sourceTree = "<group>"; };
C33FDB40255A580C00E217F9 /* SignalIOSProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalIOSProto.swift; sourceTree = "<group>"; };
C33FDB41255A580C00E217F9 /* MIMETypeUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MIMETypeUtil.m; sourceTree = "<group>"; };
@ -1989,7 +1972,6 @@
C33FDB79255A581000E217F9 /* PhoneNumberUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneNumberUtil.m; sourceTree = "<group>"; };
C33FDB7A255A581000E217F9 /* NotificationsProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationsProtocol.h; sourceTree = "<group>"; };
C33FDB7C255A581000E217F9 /* OWSVerificationStateChangeMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSVerificationStateChangeMessage.h; sourceTree = "<group>"; };
C33FDB7D255A581100E217F9 /* OWSMessageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageManager.h; sourceTree = "<group>"; };
C33FDB7E255A581100E217F9 /* TSPreKeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSPreKeyManager.m; sourceTree = "<group>"; };
C33FDB7F255A581100E217F9 /* FullTextSearchFinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullTextSearchFinder.swift; sourceTree = "<group>"; };
C33FDB80255A581100E217F9 /* Notification+Loki.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Notification+Loki.swift"; sourceTree = "<group>"; };
@ -2008,7 +1990,6 @@
C33FDB8D255A581200E217F9 /* DeviceLinkingSessionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceLinkingSessionDelegate.swift; sourceTree = "<group>"; };
C33FDB8E255A581200E217F9 /* OWSContact+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OWSContact+Private.h"; sourceTree = "<group>"; };
C33FDB8F255A581200E217F9 /* ParamParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParamParser.swift; sourceTree = "<group>"; };
C33FDB90255A581200E217F9 /* OWSMessageDecrypter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageDecrypter.m; sourceTree = "<group>"; };
C33FDB91255A581200E217F9 /* ProtoUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProtoUtils.h; sourceTree = "<group>"; };
C33FDB92255A581200E217F9 /* OWSDeviceProvisioningService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDeviceProvisioningService.m; sourceTree = "<group>"; };
C33FDB93255A581200E217F9 /* PreKeyBundle+jsonDict.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PreKeyBundle+jsonDict.m"; sourceTree = "<group>"; };
@ -2019,7 +2000,6 @@
C33FDB98255A581300E217F9 /* DeviceNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceNames.swift; sourceTree = "<group>"; };
C33FDB99255A581300E217F9 /* OWSPrimaryStorage+keyFromIntLong.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "OWSPrimaryStorage+keyFromIntLong.m"; sourceTree = "<group>"; };
C33FDB9A255A581300E217F9 /* OWS2FAManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS2FAManager.m; sourceTree = "<group>"; };
C33FDB9B255A581300E217F9 /* MessageSenderJobQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageSenderJobQueue.swift; sourceTree = "<group>"; };
C33FDB9C255A581300E217F9 /* TSIncomingMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSIncomingMessage.h; sourceTree = "<group>"; };
C33FDB9D255A581300E217F9 /* OWSCallMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCallMessageHandler.h; sourceTree = "<group>"; };
C33FDB9E255A581400E217F9 /* TSAttachmentPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentPointer.m; sourceTree = "<group>"; };
@ -2057,12 +2037,10 @@
C33FDBC2255A581700E217F9 /* SSKAsserts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKAsserts.h; sourceTree = "<group>"; };
C33FDBC3255A581700E217F9 /* AnyPromise+Conversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AnyPromise+Conversion.swift"; sourceTree = "<group>"; };
C33FDBC4255A581700E217F9 /* TypingIndicatorMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypingIndicatorMessage.swift; sourceTree = "<group>"; };
C33FDBC6255A581700E217F9 /* OWSMessageReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageReceiver.h; sourceTree = "<group>"; };
C33FDBC8255A581700E217F9 /* OWSFingerprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSFingerprint.h; sourceTree = "<group>"; };
C33FDBC9255A581700E217F9 /* CreatePreKeysOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreatePreKeysOperation.swift; sourceTree = "<group>"; };
C33FDBCA255A581700E217F9 /* LKGroupUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LKGroupUtilities.h; sourceTree = "<group>"; };
C33FDBCB255A581800E217F9 /* TSInvalidIdentityKeyReceivingErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInvalidIdentityKeyReceivingErrorMessage.m; sourceTree = "<group>"; };
C33FDBCC255A581800E217F9 /* MultiDeviceProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiDeviceProtocol.swift; sourceTree = "<group>"; };
C33FDBCE255A581800E217F9 /* OWSMessageServiceParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageServiceParams.h; sourceTree = "<group>"; };
C33FDBCF255A581800E217F9 /* OWSFingerprintBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSFingerprintBuilder.h; sourceTree = "<group>"; };
C33FDBD0255A581800E217F9 /* OnionRequestAPI+Encryption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OnionRequestAPI+Encryption.swift"; sourceTree = "<group>"; };
@ -2099,7 +2077,6 @@
C33FDBEF255A581B00E217F9 /* TSStorageKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSStorageKeys.h; sourceTree = "<group>"; };
C33FDBF0255A581B00E217F9 /* LokiDatabaseUtilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LokiDatabaseUtilities.swift; sourceTree = "<group>"; };
C33FDBF1255A581B00E217F9 /* OWSIdentityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSIdentityManager.h; sourceTree = "<group>"; };
C33FDBF2255A581B00E217F9 /* MessageSender+Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MessageSender+Promise.swift"; sourceTree = "<group>"; };
C33FDBF3255A581B00E217F9 /* OWSBlockedPhoneNumbersMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBlockedPhoneNumbersMessage.h; sourceTree = "<group>"; };
C33FDBF4255A581B00E217F9 /* DisplayNameUtilities2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayNameUtilities2.swift; sourceTree = "<group>"; };
C33FDBF5255A581B00E217F9 /* OWSDeviceProvisioningService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDeviceProvisioningService.h; sourceTree = "<group>"; };
@ -2109,7 +2086,6 @@
C33FDBF9255A581C00E217F9 /* OWSError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSError.h; sourceTree = "<group>"; };
C33FDBFA255A581C00E217F9 /* PhoneNumberUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhoneNumberUtil.h; sourceTree = "<group>"; };
C33FDBFB255A581C00E217F9 /* Storage+PublicChats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Storage+PublicChats.swift"; sourceTree = "<group>"; };
C33FDBFC255A581C00E217F9 /* OWSMessageHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageHandler.m; sourceTree = "<group>"; };
C33FDBFD255A581C00E217F9 /* OWSPrimaryStorage+Calling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "OWSPrimaryStorage+Calling.m"; sourceTree = "<group>"; };
C33FDBFE255A581C00E217F9 /* NSSet+Functional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSSet+Functional.h"; sourceTree = "<group>"; };
C33FDBFF255A581C00E217F9 /* OWSOutgoingSyncMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOutgoingSyncMessage.m; sourceTree = "<group>"; };
@ -2127,7 +2103,6 @@
C33FDC0B255A581D00E217F9 /* OWSError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSError.m; sourceTree = "<group>"; };
C33FDC0C255A581E00E217F9 /* TSInfoMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInfoMessage.m; sourceTree = "<group>"; };
C33FDC0D255A581E00E217F9 /* OWSProvisioningMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSProvisioningMessage.h; sourceTree = "<group>"; };
C33FDC0E255A581E00E217F9 /* OWSMessageDecrypter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageDecrypter.h; sourceTree = "<group>"; };
C33FDC0F255A581E00E217F9 /* LKDeviceLinkMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LKDeviceLinkMessage.h; sourceTree = "<group>"; };
C33FDC10255A581E00E217F9 /* ProofOfWork.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProofOfWork.swift; sourceTree = "<group>"; };
C33FDC11255A581E00E217F9 /* TSSocketManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSocketManager.m; sourceTree = "<group>"; };
@ -2525,6 +2500,9 @@
C3CA3AB3255CDAE600F4C6D4 /* japanese.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = japanese.txt; sourceTree = "<group>"; };
C3CA3ABD255CDB0D00F4C6D4 /* portuguese.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = portuguese.txt; sourceTree = "<group>"; };
C3CA3AC7255CDB2900F4C6D4 /* spanish.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = spanish.txt; sourceTree = "<group>"; };
C3CA3B12255CF18200F4C6D4 /* Destination+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Destination+Conversion.swift"; sourceTree = "<group>"; };
C3CA3B1C255CF3C800F4C6D4 /* MessageSender+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageSender+Utilities.swift"; sourceTree = "<group>"; };
C3CA3B2E255CF84E00F4C6D4 /* NullMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NullMessage.swift; sourceTree = "<group>"; };
C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundPoller.swift; sourceTree = "<group>"; };
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sheet.swift; sourceTree = "<group>"; };
@ -3230,6 +3208,7 @@
C3C2A7702553A41E00C340D1 /* ControlMessage.swift */,
C300A5BC2554B00D00555489 /* ReadReceipt.swift */,
C300A5C82554B04E00555489 /* SessionRequest.swift */,
C3CA3B2E255CF84E00F4C6D4 /* NullMessage.swift */,
C300A5D22554B05A00555489 /* TypingIndicator.swift */,
C300A5DC2554B06600555489 /* ClosedGroupUpdate.swift */,
C300A5E62554B07300555489 /* ExpirationTimerUpdate.swift */,
@ -3350,6 +3329,7 @@
C33FD9AC255A548A00E217F9 /* SignalUtilitiesKit */ = {
isa = PBXGroup;
children = (
C3CA3B11255CF17200F4C6D4 /* Utilities */,
C33FDC09255A581D00E217F9 /* AccountServiceClient.swift */,
C33FDBC3255A581700E217F9 /* AnyPromise+Conversion.swift */,
C33FDB8A255A581200E217F9 /* AppContext.h */,
@ -3609,13 +3589,10 @@
C33FDAFD255A580600E217F9 /* LRUCache.swift */,
C33FDA7E255A57FB00E217F9 /* Mention.swift */,
C33FDA81255A57FC00E217F9 /* MentionsManager.swift */,
C33FDBF2255A581B00E217F9 /* MessageSender+Promise.swift */,
C33FDB9B255A581300E217F9 /* MessageSenderJobQueue.swift */,
C33FDB82255A581100E217F9 /* MessageWrapper.swift */,
C33FDAFC255A580600E217F9 /* MIMETypeUtil.h */,
C33FDB41255A580C00E217F9 /* MIMETypeUtil.m */,
C33FDAA9255A580000E217F9 /* Mnemonic.swift */,
C33FDBCC255A581800E217F9 /* MultiDeviceProtocol.swift */,
C33FDA9F255A57FF00E217F9 /* NetworkManager.swift */,
C33FDB80255A581100E217F9 /* Notification+Loki.swift */,
C33FDB7A255A581000E217F9 /* NotificationsProtocol.h */,
@ -3736,17 +3713,6 @@
C33FDB67255A580F00E217F9 /* OWSMediaGalleryFinder.h */,
C33FDB71255A581000E217F9 /* OWSMediaGalleryFinder.m */,
C33FDB22255A580900E217F9 /* OWSMediaUtils.swift */,
C33FDC0E255A581E00E217F9 /* OWSMessageDecrypter.h */,
C33FDB90255A581200E217F9 /* OWSMessageDecrypter.m */,
C33FDAAC255A580000E217F9 /* OWSMessageHandler.h */,
C33FDBFC255A581C00E217F9 /* OWSMessageHandler.m */,
C33FDB7D255A581100E217F9 /* OWSMessageManager.h */,
C33FDA6A255A57F900E217F9 /* OWSMessageManager.m */,
C33FDBC6255A581700E217F9 /* OWSMessageReceiver.h */,
C33FDAB4255A580000E217F9 /* OWSMessageReceiver.m */,
C33FDACC255A580200E217F9 /* OWSMessageSend.swift */,
C33FDA92255A57FE00E217F9 /* OWSMessageSender.h */,
C33FDB3E255A580B00E217F9 /* OWSMessageSender.m */,
C33FDBCE255A581800E217F9 /* OWSMessageServiceParams.h */,
C33FDB70255A580F00E217F9 /* OWSMessageServiceParams.m */,
C33FDAE8255A580500E217F9 /* OWSMessageUtils.h */,
@ -4364,6 +4330,15 @@
path = Mnemonic;
sourceTree = "<group>";
};
C3CA3B11255CF17200F4C6D4 /* Utilities */ = {
isa = PBXGroup;
children = (
C3CA3B12255CF18200F4C6D4 /* Destination+Conversion.swift */,
C3CA3B1C255CF3C800F4C6D4 /* MessageSender+Utilities.swift */,
);
path = Utilities;
sourceTree = "<group>";
};
C3F0A58F255C8E3D007BE2A3 /* Meta */ = {
isa = PBXGroup;
children = (
@ -4542,7 +4517,6 @@
C33FDD65255A582000E217F9 /* OWSFileSystem.h in Headers */,
C33FDCD6255A582000E217F9 /* UIImage+OWS.h in Headers */,
C38EF219255B6D3B007E1867 /* OWSConversationColor.h in Headers */,
C33FDD80255A582000E217F9 /* OWSMessageReceiver.h in Headers */,
C38EF369255B6DCC007E1867 /* ViewControllerUtils.h in Headers */,
C33FDC6D255A582000E217F9 /* TSContactThread.h in Headers */,
C33FDD7A255A582000E217F9 /* OWSRequestFactory.h in Headers */,
@ -4572,7 +4546,6 @@
C33FDCDF255A582000E217F9 /* TSDatabaseSecondaryIndexes.h in Headers */,
C33FDDBD255A582000E217F9 /* ByteParser.h in Headers */,
C33FDCBC255A582000E217F9 /* TSCall.h in Headers */,
C33FDD37255A582000E217F9 /* OWSMessageManager.h in Headers */,
C38EF2C3255B6DA6007E1867 /* OWSContactOffersInteraction.h in Headers */,
C33FDD95255A582000E217F9 /* OWSDevicesService.h in Headers */,
C38EF243255B6D67007E1867 /* UIViewController+OWS.h in Headers */,
@ -4616,7 +4589,6 @@
C33FDC42255A581F00E217F9 /* YapDatabaseTransaction+OWS.h in Headers */,
C33FDD48255A582000E217F9 /* OWSContact+Private.h in Headers */,
C33FDCA6255A582000E217F9 /* SignalRecipient.h in Headers */,
C33FDC66255A582000E217F9 /* OWSMessageHandler.h in Headers */,
C33FDDA1255A582000E217F9 /* NSTimer+OWS.h in Headers */,
C38EF277255B6D7A007E1867 /* OWSDatabaseMigration.h in Headers */,
C38EF294255B6D86007E1867 /* OWSSounds.h in Headers */,
@ -4629,7 +4601,6 @@
C33FDC83255A582000E217F9 /* OWSContact.h in Headers */,
C33FDCB2255A582000E217F9 /* OWSSyncGroupsRequestMessage.h in Headers */,
C33FDCA7255A582000E217F9 /* SSKMessageSenderJobRecord.h in Headers */,
C33FDDC8255A582000E217F9 /* OWSMessageDecrypter.h in Headers */,
C38EF262255B6D6F007E1867 /* OWSContactsManager.h in Headers */,
C33FDCC2255A582000E217F9 /* OWSProfileKeyMessage.h in Headers */,
C33FDCDE255A582000E217F9 /* OWSOutgoingSentMessageTranscript.h in Headers */,
@ -4653,7 +4624,6 @@
C33FDDB3255A582000E217F9 /* OWSError.h in Headers */,
C33FDD57255A582000E217F9 /* OWSCallMessageHandler.h in Headers */,
C33FDCC8255A582000E217F9 /* NSError+MessageSending.h in Headers */,
C33FDC4C255A582000E217F9 /* OWSMessageSender.h in Headers */,
C38EF403255B6DF7007E1867 /* ContactCellView.h in Headers */,
C33FDD6D255A582000E217F9 /* OWSOutgoingNullMessage.h in Headers */,
C33FDCA0255A582000E217F9 /* TSInteraction.h in Headers */,
@ -5649,7 +5619,6 @@
C33FDDA8255A582000E217F9 /* ClosedGroupUpdateMessage.swift in Sources */,
C33FDCF9255A582000E217F9 /* String+SSK.swift in Sources */,
C38EF389255B6DD2007E1867 /* AttachmentTextView.swift in Sources */,
C33FDDAC255A582000E217F9 /* MessageSender+Promise.swift in Sources */,
C38EF36A255B6DCC007E1867 /* NewNonContactConversationViewController.m in Sources */,
C38EF321255B6DBF007E1867 /* OWSAudioPlayer.m in Sources */,
C33FDD0A255A582000E217F9 /* OWSPrimaryStorage+PreKeyStore.m in Sources */,
@ -5664,7 +5633,6 @@
C38EF3C2255B6DE7007E1867 /* ImageEditorPaletteView.swift in Sources */,
C38EF245255B6D67007E1867 /* UIFont+OWS.m in Sources */,
C33FDD26255A582000E217F9 /* NSNotificationCenter+OWS.m in Sources */,
C33FDDB6255A582000E217F9 /* OWSMessageHandler.m in Sources */,
C38EF36F255B6DCC007E1867 /* OWSViewController.m in Sources */,
C33FDC80255A582000E217F9 /* Fingerprint.pb.swift in Sources */,
C33FDD42255A582000E217F9 /* TSAccountManager.m in Sources */,
@ -5678,7 +5646,6 @@
C33FDD5F255A582000E217F9 /* SignalServiceProfile.swift in Sources */,
C33FDD83255A582000E217F9 /* CreatePreKeysOperation.swift in Sources */,
C33FDDD5255A582000E217F9 /* OWSBackgroundTask.m in Sources */,
C33FDC6E255A582000E217F9 /* OWSMessageReceiver.m in Sources */,
C33FDC7E255A582000E217F9 /* TSAttachmentStream.m in Sources */,
C33FDC62255A582000E217F9 /* BuildConfiguration.swift in Sources */,
C38EF40A255B6DF7007E1867 /* OWSFlatButton.swift in Sources */,
@ -5753,7 +5720,6 @@
C33FDC7C255A582000E217F9 /* TSAttachment.m in Sources */,
C38EF3C7255B6DE7007E1867 /* ImageEditorCanvasView.swift in Sources */,
C38EF3F3255B6DF7007E1867 /* ContactsViewHelper.m in Sources */,
C33FDC24255A581F00E217F9 /* OWSMessageManager.m in Sources */,
C33FDC46255A581F00E217F9 /* PublicChatPoller.swift in Sources */,
C38EF400255B6DF7007E1867 /* GalleryRailView.swift in Sources */,
C38EF32E255B6DBF007E1867 /* ImageCache.swift in Sources */,
@ -5796,6 +5762,7 @@
C38EF3FC255B6DF7007E1867 /* AvatarImageView.swift in Sources */,
C33FDD13255A582000E217F9 /* OWSFailedAttachmentDownloadsJob.m in Sources */,
C38EF24D255B6D67007E1867 /* UIView+OWS.swift in Sources */,
C3CA3B13255CF18200F4C6D4 /* Destination+Conversion.swift in Sources */,
C33FDCB5255A582000E217F9 /* SessionMetaProtocol.swift in Sources */,
C33FDC91255A582000E217F9 /* OWSDeviceProvisioner.m in Sources */,
C33FDC6A255A582000E217F9 /* ProvisioningProto.swift in Sources */,
@ -5811,7 +5778,6 @@
C38EF310255B6DBF007E1867 /* DebugLogger.m in Sources */,
C38EF38B255B6DD2007E1867 /* AttachmentPrepViewController.swift in Sources */,
C33FDD98255A582000E217F9 /* LokiPushNotificationManager.swift in Sources */,
C33FDCF8255A582000E217F9 /* OWSMessageSender.m in Sources */,
C33FDD70255A582000E217F9 /* DataSource.m in Sources */,
C33FDD2F255A582000E217F9 /* AppReadiness.m in Sources */,
C33FDCEC255A582000E217F9 /* SSKIncrementingIdFinder.swift in Sources */,
@ -5824,7 +5790,6 @@
C33FDC3B255A581F00E217F9 /* MentionsManager.swift in Sources */,
C33FDC49255A581F00E217F9 /* NSTimer+OWS.m in Sources */,
C38EF260255B6D6F007E1867 /* OWSContactsManager.m in Sources */,
C33FDD55255A582000E217F9 /* MessageSenderJobQueue.swift in Sources */,
C33FDCFD255A582000E217F9 /* YapDatabaseConnection+OWS.m in Sources */,
C38EF3BC255B6DE7007E1867 /* ImageEditorPanGestureRecognizer.swift in Sources */,
C33FDC23255A581F00E217F9 /* SSKPreferences.swift in Sources */,
@ -5867,7 +5832,6 @@
C33FDD85255A582000E217F9 /* TSInvalidIdentityKeyReceivingErrorMessage.m in Sources */,
C33FDD2E255A582000E217F9 /* TSInvalidIdentityKeyErrorMessage.m in Sources */,
C33FDDBB255A582000E217F9 /* TSGroupThread.m in Sources */,
C33FDD4A255A582000E217F9 /* OWSMessageDecrypter.m in Sources */,
C38EF40C255B6DF7007E1867 /* GradientView.swift in Sources */,
C33FDD14255A582000E217F9 /* OWSUDManager.swift in Sources */,
C33FDC6B255A582000E217F9 /* OWSStorage.m in Sources */,
@ -5946,16 +5910,15 @@
C33FDCBA255A582000E217F9 /* OWSRequestBuilder.m in Sources */,
C33FDC2B255A581F00E217F9 /* OWSReadReceiptManager.m in Sources */,
C38EF326255B6DBF007E1867 /* ConversationStyle.swift in Sources */,
C33FDC86255A582000E217F9 /* OWSMessageSend.swift in Sources */,
C38EF312255B6DBF007E1867 /* OWSGroupAvatarBuilder.m in Sources */,
C38EF3B8255B6DE7007E1867 /* ImageEditorTextViewController.swift in Sources */,
C33FDD91255A582000E217F9 /* OWSMessageUtils.m in Sources */,
C38EF40B255B6DF7007E1867 /* TappableStackView.swift in Sources */,
C33FDCF7255A582000E217F9 /* OWSProfileKeyMessage.m in Sources */,
C3CA3B1D255CF3C800F4C6D4 /* MessageSender+Utilities.swift in Sources */,
C38EF31D255B6DBF007E1867 /* UIImage+OWS.swift in Sources */,
C38EF359255B6DCC007E1867 /* SheetViewController.swift in Sources */,
C38EF362255B6DCC007E1867 /* ContactShareApprovalViewController.swift in Sources */,
C33FDD86255A582000E217F9 /* MultiDeviceProtocol.swift in Sources */,
C33FDCAD255A582000E217F9 /* OWSPrimaryStorage+SessionStore.m in Sources */,
C38EF386255B6DD2007E1867 /* AttachmentApprovalInputAccessoryView.swift in Sources */,
C33FDC92255A582000E217F9 /* OWSGroupsOutputStream.m in Sources */,
@ -6037,6 +6000,7 @@
C3471F4C25553AB000297E91 /* MessageReceiver+Decryption.swift in Sources */,
C3A722802558C4E10043A11F /* AttachmentStream.swift in Sources */,
C300A5D32554B05A00555489 /* TypingIndicator.swift in Sources */,
C3CA3B2F255CF84E00F4C6D4 /* NullMessage.swift in Sources */,
C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */,
C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */,
C300A5F22554B09800555489 /* MessageSender.swift in Sources */,

7
SignalUtilitiesKit/ClosedGroupPoller.swift

@ -27,7 +27,7 @@ public final class ClosedGroupPoller : NSObject {
guard !isPolling else { return }
isPolling = true
timer = Timer.scheduledTimer(withTimeInterval: ClosedGroupPoller.pollInterval, repeats: true) { [weak self] _ in
self?.poll()
let _ = self?.poll()
}
}
@ -64,7 +64,10 @@ public final class ClosedGroupPoller : NSObject {
guard let envelope = SSKProtoEnvelope.from(json) else { return }
do {
let data = try envelope.serializedData()
SSKEnvironment.shared.messageReceiver.handleReceivedEnvelopeData(data)
let job = MessageReceiveJob(data: data)
Storage.write { transaction in
SessionMessagingKit.JobQueue.shared.add(job, using: transaction)
}
} catch {
print("[Loki] Failed to deserialize envelope due to error: \(error).")
}

92
SignalUtilitiesKit/ClosedGroupsProtocol.swift

@ -37,7 +37,6 @@ public final class ClosedGroupsProtocol : NSObject {
public static func createClosedGroup(name: String, members: Set<String>, transaction: YapDatabaseReadWriteTransaction) -> Promise<TSGroupThread> {
// Prepare
var members = members
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
let userPublicKey = getUserHexEncodedPublicKey()
// Generate a key pair for the group
let groupKeyPair = Curve25519.generateKeyPair()
@ -73,10 +72,12 @@ public final class ClosedGroupsProtocol : NSObject {
guard member != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.new(groupPublicKey: Data(hex: groupPublicKey), name: name,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(groupPublicKey: Data(hex: groupPublicKey), name: name,
groupPrivateKey: groupKeyPair.privateKey, senderKeys: senderKeys, members: membersAsData, admins: adminsAsData)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
promises.append(SSKEnvironment.shared.messageSender.sendPromise(message: closedGroupUpdateMessage))
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
let promise = MessageSender.sendNonDurably(closedGroupUpdate, in: thread, using: transaction)
promises.append(promise)
}
// Add the group to the user's set of public keys to poll for
Storage.setClosedGroupPrivateKey(groupKeyPair.privateKey.toHexString(), for: groupPublicKey, using: transaction)
@ -92,7 +93,6 @@ public final class ClosedGroupsProtocol : NSObject {
/// - Note: The returned promise is only relevant for group leaving.
public static func update(_ groupPublicKey: String, with members: Set<String>, name: String, transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> {
let (promise, seal) = Promise<Void>.pending()
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
let userPublicKey = getUserHexEncodedPublicKey()
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
guard let thread = TSGroupThread.fetch(uniqueId: TSGroupThread.threadId(fromGroupId: groupID), transaction: transaction) else {
@ -124,13 +124,14 @@ public final class ClosedGroupsProtocol : NSObject {
let promises: [Promise<Void>] = oldMembers.map { member in
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name, senderKeys: [],
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name, senderKeys: [],
members: membersAsData, admins: adminsAsData)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
return SSKEnvironment.shared.messageSender.sendPromise(message: closedGroupUpdateMessage)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
return MessageSender.sendNonDurably(closedGroupUpdate, in: thread, using: transaction)
}
when(resolved: promises).done2 { _ in seal.fulfill(()) }.catch2 { seal.reject($0) }
promise.done {
let _ = promise.done {
Storage.writeSync { transaction in
let allOldRatchets = Storage.getAllClosedGroupRatchets(for: groupPublicKey)
for (senderPublicKey, oldRatchet) in allOldRatchets {
@ -144,16 +145,17 @@ public final class ClosedGroupsProtocol : NSObject {
if isUserLeaving {
Storage.removeClosedGroupPrivateKey(for: groupPublicKey, using: transaction)
// Notify the PN server
LokiPushNotificationManager.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey)
let _ = LokiPushNotificationManager.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey)
} else {
// Send closed group update messages to any new members using established channels
for member in newMembers {
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.new(groupPublicKey: Data(hex: groupPublicKey), name: name,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(groupPublicKey: Data(hex: groupPublicKey), name: name,
groupPrivateKey: Data(hex: groupPrivateKey), senderKeys: [], members: membersAsData, admins: adminsAsData)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
// Send out the user's new ratchet to all members (minus the removed ones) using established channels
let userRatchet = SharedSenderKeysImplementation.shared.generateRatchet(for: groupPublicKey, senderPublicKey: userPublicKey, using: transaction)
@ -162,9 +164,10 @@ public final class ClosedGroupsProtocol : NSObject {
guard member != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
}
}
@ -177,10 +180,11 @@ public final class ClosedGroupsProtocol : NSObject {
return ClosedGroupSenderKey(chainKey: Data(hex: ratchet.chainKey), keyIndex: ratchet.keyIndex, publicKey: Data(hex: publicKey))
}
// Send a closed group update message to the existing members with the new members' ratchets (this message is aimed at the group)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name, senderKeys: newSenderKeys,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name, senderKeys: newSenderKeys,
members: membersAsData, admins: adminsAsData)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
// Establish sessions if needed
establishSessionsIfNeeded(with: [String](newMembers), using: transaction)
// Send closed group update messages to the new members using established channels
@ -189,18 +193,20 @@ public final class ClosedGroupsProtocol : NSObject {
for member in newMembers {
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.new(groupPublicKey: Data(hex: groupPublicKey), name: name,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(groupPublicKey: Data(hex: groupPublicKey), name: name,
groupPrivateKey: Data(hex: groupPrivateKey), senderKeys: [ClosedGroupSenderKey](allSenderKeys), members: membersAsData, admins: adminsAsData)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
} else {
seal.fulfill(())
let allSenderKeys = Storage.getAllClosedGroupSenderKeys(for: groupPublicKey)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name,
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.info(groupPublicKey: Data(hex: groupPublicKey), name: name,
senderKeys: [ClosedGroupSenderKey](allSenderKeys), members: membersAsData, admins: adminsAsData)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
// Update the group
let newGroupModel = TSGroupModel(title: name, memberIds: [String](members), image: nil, groupId: groupID, groupType: .closedGroup, adminIds: admins)
@ -240,10 +246,10 @@ public final class ClosedGroupsProtocol : NSObject {
// Send the request
let thread = TSContactThread.getOrCreateThread(withContactId: senderPublicKey, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.senderKeyRequest(groupPublicKey: Data(hex: groupPublicKey))
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.senderKeyRequest(groupPublicKey: Data(hex: groupPublicKey))
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
// MARK: - Receiving
@ -273,7 +279,6 @@ public final class ClosedGroupsProtocol : NSObject {
}
private static func handleNewGroupMessage(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate, using transaction: YapDatabaseReadWriteTransaction) {
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
// Unwrap the message
let groupPublicKey = closedGroupUpdate.groupPublicKey.toHexString()
let name = closedGroupUpdate.name
@ -298,9 +303,10 @@ public final class ClosedGroupsProtocol : NSObject {
guard member != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction)
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
}
for publicKey in missingSenderKeys.subtracting([ userPublicKey ]) {
@ -322,7 +328,7 @@ public final class ClosedGroupsProtocol : NSObject {
// Add the group to the user's set of public keys to poll for
Storage.setClosedGroupPrivateKey(groupPrivateKey.toHexString(), for: groupPublicKey, using: transaction)
// Notify the PN server
LokiPushNotificationManager.performOperation(.subscribe, for: groupPublicKey, publicKey: getUserHexEncodedPublicKey())
let _ = LokiPushNotificationManager.performOperation(.subscribe, for: groupPublicKey, publicKey: getUserHexEncodedPublicKey())
// Notify the user
let infoMessage = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(), in: thread, messageType: .typeGroupUpdate)
infoMessage.save(with: transaction)
@ -335,7 +341,6 @@ public final class ClosedGroupsProtocol : NSObject {
private static func handleInfoMessage(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate, from senderPublicKey: String,
using transaction: YapDatabaseReadWriteTransaction) {
// Unwrap the message
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
let groupPublicKey = closedGroupUpdate.groupPublicKey.toHexString()
let name = closedGroupUpdate.name
let senderKeys = closedGroupUpdate.senderKeys
@ -377,7 +382,7 @@ public final class ClosedGroupsProtocol : NSObject {
if wasUserRemoved {
Storage.removeClosedGroupPrivateKey(for: groupPublicKey, using: transaction)
// Notify the PN server
LokiPushNotificationManager.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey)
let _ = LokiPushNotificationManager.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey)
} else {
establishSessionsIfNeeded(with: members, using: transaction) // This internally takes care of multi device
let userRatchet = SharedSenderKeysImplementation.shared.generateRatchet(for: groupPublicKey, senderPublicKey: userPublicKey, using: transaction)
@ -386,9 +391,10 @@ public final class ClosedGroupsProtocol : NSObject {
guard member != userPublicKey else { continue }
let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction) // This internally takes care of multi device
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
}
}
@ -406,7 +412,6 @@ public final class ClosedGroupsProtocol : NSObject {
private static func handleSenderKeyRequestMessage(_ closedGroupUpdate: SSKProtoDataMessageClosedGroupUpdate, from senderPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) {
// Prepare
let messageSenderJobQueue = SSKEnvironment.shared.messageSenderJobQueue
let userPublicKey = getUserHexEncodedPublicKey()
let groupPublicKey = closedGroupUpdate.groupPublicKey.toHexString()
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
@ -431,9 +436,10 @@ public final class ClosedGroupsProtocol : NSObject {
let userSenderKey = ClosedGroupSenderKey(chainKey: Data(hex: userRatchet.chainKey), keyIndex: userRatchet.keyIndex, publicKey: Data(hex: userPublicKey))
let thread = TSContactThread.getOrCreateThread(withContactId: senderPublicKey, transaction: transaction)
thread.save(with: transaction)
let closedGroupUpdateMessageKind = ClosedGroupUpdateMessage.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdateMessage = ClosedGroupUpdateMessage(thread: thread, kind: closedGroupUpdateMessageKind)
messageSenderJobQueue.add(message: closedGroupUpdateMessage, transaction: transaction) // This internally takes care of multi device
let closedGroupUpdateKind = ClosedGroupUpdate.Kind.senderKey(groupPublicKey: Data(hex: groupPublicKey), senderKey: userSenderKey)
let closedGroupUpdate = ClosedGroupUpdate()
closedGroupUpdate.kind = closedGroupUpdateKind
MessageSender.send(closedGroupUpdate, in: thread, using: transaction)
}
/// Invoked upon receiving a sender key from another user.

25
SignalUtilitiesKit/MessageSender+Promise.swift

@ -1,25 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
import PromiseKit
public extension MessageSender {
/**
* Wrap message sending in a Promise for easier callback chaining.
*/
func sendPromise(message: TSOutgoingMessage) -> Promise<Void> {
let promise: Promise<Void> = Promise { resolver in
self.send(message, success: { resolver.fulfill(()) }, failure: resolver.reject)
}
// Ensure sends complete before they're GC'd.
// This *should* be redundant, since we should be calling retainUntilComplete
// at all call sites where the promise isn't otherwise retained.
promise.retainUntilComplete()
return promise
}
}

256
SignalUtilitiesKit/MessageSenderJobQueue.swift

@ -1,256 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
/// Durably enqueues a message for sending.
///
/// The queue's operations (`MessageSenderOperation`) uses `MessageSender` to send a message.
///
/// ## Retry behavior
///
/// Like all JobQueue's, MessageSenderJobQueue implements retry handling for operation errors.
///
/// `MessageSender` also includes it's own retry logic necessary to encapsulate business logic around
/// a user changing their Registration ID, or adding/removing devices. That is, it is sometimes *normal*
/// for MessageSender to have to resend to a recipient multiple times before it is accepted, and doesn't
/// represent a "failure" from the application standpoint.
///
/// So we have an inner non-durable retry (MessageSender) and an outer durable retry (MessageSenderJobQueue).
///
/// Both respect the `error.isRetryable` convention to be sure we don't keep retrying in some situations
/// (e.g. rate limiting)
@objc(SSKMessageSenderJobQueue)
public class MessageSenderJobQueue: NSObject, JobQueue {
@objc
public override init() {
super.init()
AppReadiness.runNowOrWhenAppWillBecomeReady {
self.setup()
}
}
@objc(addMessage:transaction:)
public func add(message: TSOutgoingMessage, transaction: YapDatabaseReadWriteTransaction) {
self.add(message: message, removeMessageAfterSending: false, transaction: transaction)
}
@objc(addMediaMessage:dataSource:contentType:sourceFilename:caption:albumMessageId:isTemporaryAttachment:)
public func add(mediaMessage: TSOutgoingMessage, dataSource: DataSource, contentType: String, sourceFilename: String?, caption: String?, albumMessageId: String?, isTemporaryAttachment: Bool) {
let attachmentInfo = OutgoingAttachmentInfo(dataSource: dataSource, contentType: contentType, sourceFilename: sourceFilename, caption: caption, albumMessageId: albumMessageId)
add(mediaMessage: mediaMessage, attachmentInfos: [attachmentInfo], isTemporaryAttachment: isTemporaryAttachment)
}
@objc(addMediaMessage:attachmentInfos:isTemporaryAttachment:)
public func add(mediaMessage: TSOutgoingMessage, attachmentInfos: [OutgoingAttachmentInfo], isTemporaryAttachment: Bool) {
OutgoingMessagePreparer.prepareAttachments(attachmentInfos,
inMessage: mediaMessage,
completionHandler: { error in
if let error = error {
Storage.writeSync { transaction in
mediaMessage.update(sendingError: error, transaction: transaction)
}
} else {
Storage.writeSync { transaction in
self.add(message: mediaMessage, removeMessageAfterSending: isTemporaryAttachment, transaction: transaction)
}
}
})
}
private func add(message: TSOutgoingMessage, removeMessageAfterSending: Bool, transaction: YapDatabaseReadWriteTransaction) {
assert(AppReadiness.isAppReady() || CurrentAppContext().isRunningTests)
let jobRecord: SSKMessageSenderJobRecord
do {
jobRecord = try SSKMessageSenderJobRecord(message: message, removeMessageAfterSending: false, label: self.jobRecordLabel)
} catch {
owsFailDebug("Failed to build job due to error: \(error).")
return
}
self.add(jobRecord: jobRecord, transaction: transaction)
}
// MARK: JobQueue
public typealias DurableOperationType = MessageSenderOperation
public static let jobRecordLabel: String = "MessageSender"
public static let maxRetries: UInt = 1 // Loki: We have our own retrying
public let requiresInternet: Bool = true
public var runningOperations: [MessageSenderOperation] = []
public var jobRecordLabel: String {
return type(of: self).jobRecordLabel
}
@objc
public func setup() {
defaultSetup()
}
public var isSetup: Bool = false
/// Used when the user clears their database to cancel any outstanding jobs.
@objc public func clearAllJobs() {
Storage.writeSync { transaction in
let statuses: [SSKJobRecordStatus] = [ .unknown, .ready, .running, .permanentlyFailed ]
var records: [SSKJobRecord] = []
statuses.forEach {
records += self.finder.allRecords(label: self.jobRecordLabel, status: $0, transaction: transaction)
}
records.forEach { $0.remove(with: transaction) }
}
}
public func didMarkAsReady(oldJobRecord: SSKMessageSenderJobRecord, transaction: YapDatabaseReadWriteTransaction) {
if let messageId = oldJobRecord.messageId, let message = TSOutgoingMessage.fetch(uniqueId: messageId, transaction: transaction) {
message.updateWithMarkingAllUnsentRecipientsAsSending(with: transaction)
}
}
public func buildOperation(jobRecord: SSKMessageSenderJobRecord, transaction: YapDatabaseReadTransaction) throws -> MessageSenderOperation {
let message: TSOutgoingMessage
if let invisibleMessage = jobRecord.invisibleMessage {
message = invisibleMessage
} else if let messageId = jobRecord.messageId, let fetchedMessage = TSOutgoingMessage.fetch(uniqueId: messageId, transaction: transaction) {
message = fetchedMessage
} else {
assert(jobRecord.messageId != nil)
throw JobError.obsolete(description: "Message no longer exists.")
}
return MessageSenderOperation(message: message, jobRecord: jobRecord)
}
var senderQueues: [String: OperationQueue] = [:]
let defaultQueue: OperationQueue = {
let operationQueue = OperationQueue()
operationQueue.name = "DefaultSendingQueue"
operationQueue.maxConcurrentOperationCount = 1
operationQueue.qualityOfService = .userInitiated
return operationQueue
}()
// We use a per-thread serial OperationQueue to ensure messages are delivered to the
// service in the order the user sent them.
public func operationQueue(jobRecord: SSKMessageSenderJobRecord) -> OperationQueue {
guard let threadId = jobRecord.threadId else {
return defaultQueue
}
guard let existingQueue = senderQueues[threadId] else {
let operationQueue = OperationQueue()
operationQueue.name = "SendingQueue:\(threadId)"
operationQueue.maxConcurrentOperationCount = 1
operationQueue.qualityOfService = .userInitiated
senderQueues[threadId] = operationQueue
return operationQueue
}
return existingQueue
}
}
public class MessageSenderOperation: OWSOperation, DurableOperation {
// MARK: DurableOperation
public let jobRecord: SSKMessageSenderJobRecord
weak public var durableOperationDelegate: MessageSenderJobQueue?
public var operation: OWSOperation {
return self
}
// MARK: Init
let message: TSOutgoingMessage
init(message: TSOutgoingMessage, jobRecord: SSKMessageSenderJobRecord) {
self.message = message
self.jobRecord = jobRecord
super.init()
}
// MARK: Dependencies
var messageSender: MessageSender {
return SSKEnvironment.shared.messageSender
}
// MARK: OWSOperation
override public func run() {
self.messageSender.send(message, success: reportSuccess, failure: reportError)
}
override public func didSucceed() {
Storage.writeSync { transaction in
self.durableOperationDelegate?.durableOperationDidSucceed(self, transaction: transaction)
if self.jobRecord.removeMessageAfterSending {
self.message.remove(with: transaction)
}
}
}
override public func didReportError(_ error: Error) {
let message = self.message
var isFailedSessionRequest = false
if message is SessionRequestMessage, let publicKey = message.thread.contactIdentifier() {
isFailedSessionRequest = (Storage.getSessionRequestSentTimestamp(for: publicKey) == message.timestamp)
}
Storage.writeSync { transaction in
if isFailedSessionRequest, let publicKey = message.thread.contactIdentifier() {
Storage.setSessionRequestSentTimestamp(for: publicKey, to: 0, using: transaction)
}
self.durableOperationDelegate?.durableOperation(self, didReportError: error, transaction: transaction)
}
}
override public func retryInterval() -> TimeInterval {
// Arbitrary backoff factor...
// With backOffFactor of 1.9
// try 1 delay: 0.00s
// try 2 delay: 0.19s
// ...
// try 5 delay: 1.30s
// ...
// try 11 delay: 61.31s
let backoffFactor = 1.9
let maxBackoff = 15 * kMinuteInterval
let seconds = 0.1 * min(maxBackoff, pow(backoffFactor, Double(self.jobRecord.failureCount)))
return seconds
}
override public func didFail(error: Error) {
let message = self.message
var isFailedSessionRequest = false
if message is SessionRequestMessage, let publicKey = message.thread.contactIdentifier() {
isFailedSessionRequest = (Storage.getSessionRequestSentTimestamp(for: publicKey) == message.timestamp)
}