From 28172b4ed2227920f16c39dacebe74a6877ffc0a Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Sun, 8 Nov 2020 12:34:08 +1100 Subject: [PATCH] Create AttachmentUploadJob & AttachmentDownloadJob Also conform SnodeMessage to NSCoding --- SessionMessagingKit/Configuration.swift | 2 + .../Jobs/AttachmentDownloadJob.swift | 22 +++++++ .../Jobs/AttachmentUploadJob.swift | 22 +++++++ .../Jobs/MessageReceiveJob.swift | 3 + SessionMessagingKit/Jobs/MessageSendJob.swift | 2 + .../Jobs/NotifyPNServerJob.swift | 47 +++++++++++++++ .../MessageReceiver+Decryption.swift | 2 +- .../Sending & Receiving/MessageReceiver.swift | 12 ++-- .../MessageSender+Encryption.swift | 2 +- .../Sending & Receiving/MessageSender.swift | 14 +++-- SessionMessagingKit/Storage.swift | 1 + SessionSnodeKit/Message.swift | 35 ----------- SessionSnodeKit/OnionRequestAPI.swift | 8 +-- SessionSnodeKit/Snode.swift | 2 +- SessionSnodeKit/SnodeMessage.swift | 60 +++++++++++++++++++ Signal.xcodeproj/project.pbxproj | 22 +++++-- 16 files changed, 199 insertions(+), 57 deletions(-) create mode 100644 SessionMessagingKit/Jobs/AttachmentDownloadJob.swift create mode 100644 SessionMessagingKit/Jobs/AttachmentUploadJob.swift create mode 100644 SessionMessagingKit/Jobs/NotifyPNServerJob.swift delete mode 100644 SessionSnodeKit/Message.swift create mode 100644 SessionSnodeKit/SnodeMessage.swift diff --git a/SessionMessagingKit/Configuration.swift b/SessionMessagingKit/Configuration.swift index 3399c110d..bc60556ac 100644 --- a/SessionMessagingKit/Configuration.swift +++ b/SessionMessagingKit/Configuration.swift @@ -1,6 +1,8 @@ public struct Configuration { public let storage: SessionMessagingKitStorageProtocol + public let pnServerURL: String + public let pnServerPublicKey: String internal static var shared: Configuration! } diff --git a/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift b/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift new file mode 100644 index 000000000..6b0e041a1 --- /dev/null +++ b/SessionMessagingKit/Jobs/AttachmentDownloadJob.swift @@ -0,0 +1,22 @@ +import SessionUtilities + +// TODO: Implementation + +public final class AttachmentDownloadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility + + // MARK: Settings + private static let maxRetryCount: UInt = 20 + + // MARK: Coding + public init?(coder: NSCoder) { } + + public func encode(with coder: NSCoder) { } + + // MARK: Running + public func execute() { } + + private func handleSuccess() { } + + private func handleFailure(error: Error) { } +} + diff --git a/SessionMessagingKit/Jobs/AttachmentUploadJob.swift b/SessionMessagingKit/Jobs/AttachmentUploadJob.swift new file mode 100644 index 000000000..a1f9a2c4d --- /dev/null +++ b/SessionMessagingKit/Jobs/AttachmentUploadJob.swift @@ -0,0 +1,22 @@ +import SessionUtilities + +// TODO: Implementation + +public final class AttachmentUploadJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility + + // MARK: Settings + private static let maxRetryCount: UInt = 20 + + // MARK: Coding + public init?(coder: NSCoder) { } + + public func encode(with coder: NSCoder) { } + + // MARK: Running + public func execute() { } + + private func handleSuccess() { } + + private func handleFailure(error: Error) { } +} + diff --git a/SessionMessagingKit/Jobs/MessageReceiveJob.swift b/SessionMessagingKit/Jobs/MessageReceiveJob.swift index 15289800a..477d29558 100644 --- a/SessionMessagingKit/Jobs/MessageReceiveJob.swift +++ b/SessionMessagingKit/Jobs/MessageReceiveJob.swift @@ -1,5 +1,8 @@ import SessionUtilities +// TODO: Result handling +// TODO: Retrying + public final class MessageReceiveJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility private let data: Data private var failureCount: UInt diff --git a/SessionMessagingKit/Jobs/MessageSendJob.swift b/SessionMessagingKit/Jobs/MessageSendJob.swift index f4e0fba2c..7bf090140 100644 --- a/SessionMessagingKit/Jobs/MessageSendJob.swift +++ b/SessionMessagingKit/Jobs/MessageSendJob.swift @@ -1,6 +1,8 @@ import SessionUtilities // TODO: Destination encoding & decoding +// TODO: Result handling +// TODO: Retrying public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility private let message: Message diff --git a/SessionMessagingKit/Jobs/NotifyPNServerJob.swift b/SessionMessagingKit/Jobs/NotifyPNServerJob.swift new file mode 100644 index 000000000..7924f368a --- /dev/null +++ b/SessionMessagingKit/Jobs/NotifyPNServerJob.swift @@ -0,0 +1,47 @@ +import PromiseKit +import SessionSnodeKit +import SessionUtilities + +// TODO: Implementation +// TODO: Result handling +// TODO: Retrying + +public final class NotifyPNServerJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility + private let message: SnodeMessage + private var failureCount: UInt + + // MARK: Settings + private static let maxRetryCount: UInt = 20 + + // MARK: Initialization + init(message: SnodeMessage) { + self.message = message + self.failureCount = 0 + } + + // MARK: Coding + public init?(coder: NSCoder) { + guard let message = coder.decodeObject(forKey: "message") as! SnodeMessage? else { return nil } + self.message = message + self.failureCount = coder.decodeObject(forKey: "failureCount") as! UInt? ?? 0 + } + + public func encode(with coder: NSCoder) { + coder.encode(message, forKey: "message") + coder.encode(failureCount, forKey: "failureCount") + } + + // MARK: Running + public func execute() { + + } + + private func handleSuccess() { + + } + + private func handleFailure(error: Error) { + self.failureCount += 1 + } +} + diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Decryption.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Decryption.swift index f93b5779a..ba132c0b4 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Decryption.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Decryption.swift @@ -2,7 +2,7 @@ import CryptoSwift import SessionProtocolKit import SessionUtilities -public extension MessageReceiver { +internal extension MessageReceiver { static func decryptWithSharedSenderKeys(envelope: SNProtoEnvelope, using transaction: Any) throws -> (plaintext: Data, senderPublicKey: String) { // 1. ) Check preconditions diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index 7858d6209..473a99449 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -1,8 +1,10 @@ import SessionUtilities -public enum MessageReceiver { +// TODO: Decryption - public enum Error : LocalizedError { +internal enum MessageReceiver { + + internal enum Error : LocalizedError { case invalidMessage case unknownMessage // Shared sender keys @@ -12,7 +14,7 @@ public enum MessageReceiver { case sharedSecretGenerationFailed case selfSend - public var errorDescription: String? { + internal var errorDescription: String? { switch self { case .invalidMessage: return "Invalid message." case .unknownMessage: return "Unknown message type." @@ -26,8 +28,8 @@ public enum MessageReceiver { } } - public static func parse(_ ciphertext: Data) throws -> Message { - let plaintext = ciphertext // TODO: Decryption + internal static func parse(_ ciphertext: Data) throws -> Message { + let plaintext = ciphertext let proto: SNProtoContent do { proto = try SNProtoContent.parseData(plaintext) diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender+Encryption.swift b/SessionMessagingKit/Sending & Receiving/MessageSender+Encryption.swift index 950c006d6..55f83db85 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender+Encryption.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender+Encryption.swift @@ -1,7 +1,7 @@ import SessionProtocolKit import SessionUtilities -public extension MessageSender { +internal extension MessageSender { static func encryptWithSignalProtocol(_ plaintext: Data, for publicKey: String, using transaction: Any) throws -> Data { return Data() diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 061c94cb3..d442259f6 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -2,17 +2,18 @@ import PromiseKit import SessionSnodeKit import SessionUtilities -// TODO: Notify PN server +// TODO: Open group encryption +// TODO: Signal protocol encryption -public enum MessageSender { +internal enum MessageSender { - public enum Error : LocalizedError { + internal enum Error : LocalizedError { case invalidMessage case protoConversionFailed case proofOfWorkCalculationFailed case noUserPublicKey - public var errorDescription: String? { + internal var errorDescription: String? { switch self { case .invalidMessage: return "Invalid message." case .protoConversionFailed: return "Couldn't convert message to proto." @@ -22,7 +23,7 @@ public enum MessageSender { } } - public static func send(_ message: Message, to destination: Message.Destination, using transaction: Any) -> Promise { + internal static func send(_ message: Message, to destination: Message.Destination, using transaction: Any) -> Promise { // Validate the message guard message.isValid else { return Promise(error: Error.invalidMessage) } // Convert it to protobuf @@ -96,6 +97,9 @@ public enum MessageSender { if case .contact(_) = destination { NotificationCenter.default.post(name: .messageSent, object: NSNumber(value: message.sentTimestamp!)) } + let notifyPNServerJob = NotifyPNServerJob(message: snodeMessage) + Configuration.shared.storage.persist(notifyPNServerJob) + notifyPNServerJob.execute() } let _ = promise.catch(on: DispatchQueue.main) { _ in if case .contact(_) = destination { diff --git a/SessionMessagingKit/Storage.swift b/SessionMessagingKit/Storage.swift index 0a5b81809..8d1f07e70 100644 --- a/SessionMessagingKit/Storage.swift +++ b/SessionMessagingKit/Storage.swift @@ -8,4 +8,5 @@ public protocol SessionMessagingKitStorageProtocol { func getOrGenerateRegistrationID(using transaction: Any) -> UInt32 func isClosedGroup(_ publicKey: String) -> Bool func getClosedGroupPrivateKey(for publicKey: String) -> String? + func persist(_ job: Job) } diff --git a/SessionSnodeKit/Message.swift b/SessionSnodeKit/Message.swift deleted file mode 100644 index 01ed7ab37..000000000 --- a/SessionSnodeKit/Message.swift +++ /dev/null @@ -1,35 +0,0 @@ -import PromiseKit -import SessionUtilities - -public struct SnodeMessage { - /// The hex encoded public key of the recipient. - let recipient: String - /// The content of the message. - let data: LosslessStringConvertible - /// The time to live for the message in milliseconds. - let ttl: UInt64 - /// When the proof of work was calculated. - /// - /// - Note: Expressed as milliseconds since 00:00:00 UTC on 1 January 1970. - let timestamp: UInt64 - /// The base 64 encoded proof of work. - let nonce: String - - public init(recipient: String, data: LosslessStringConvertible, ttl: UInt64, timestamp: UInt64, nonce: String) { - self.recipient = recipient - self.data = data - self.ttl = ttl - self.timestamp = timestamp - self.nonce = nonce - } - - public func toJSON() -> JSON { - return [ - "pubKey" : recipient, - "data" : data.description, - "ttl" : String(ttl), - "timestamp" : String(timestamp), - "nonce" : nonce - ] - } -} diff --git a/SessionSnodeKit/OnionRequestAPI.swift b/SessionSnodeKit/OnionRequestAPI.swift index 9e37de9ff..fe8e08fbd 100644 --- a/SessionSnodeKit/OnionRequestAPI.swift +++ b/SessionSnodeKit/OnionRequestAPI.swift @@ -24,7 +24,7 @@ public enum OnionRequestAPI { private static var targetGuardSnodeCount: UInt { return targetPathCount } // One per path // MARK: Destination - internal enum Destination { + public enum Destination { case snode(Snode) case server(host: String, x25519PublicKey: String) } @@ -275,7 +275,7 @@ public enum OnionRequestAPI { // MARK: Internal API /// Sends an onion request to `snode`. Builds new paths as needed. - internal static func sendOnionRequest(to snode: Snode, invoking method: Snode.Method, with parameters: JSON, associatedWith publicKey: String) -> Promise { + public static func sendOnionRequest(to snode: Snode, invoking method: Snode.Method, with parameters: JSON, associatedWith publicKey: String) -> Promise { let payload: JSON = [ "method" : method.rawValue, "params" : parameters ] return sendOnionRequest(with: payload, to: Destination.snode(snode)).recover2 { error -> Promise in guard case OnionRequestAPI.Error.httpRequestFailedAtDestination(let statusCode, let json) = error else { throw error } @@ -284,7 +284,7 @@ public enum OnionRequestAPI { } /// Sends an onion request to `server`. Builds new paths as needed. - internal static func sendOnionRequest(_ request: NSURLRequest, to server: String, using x25519PublicKey: String, isJSONRequired: Bool = true) -> Promise { + public static func sendOnionRequest(_ request: NSURLRequest, to server: String, using x25519PublicKey: String, isJSONRequired: Bool = true) -> Promise { var rawHeaders = request.allHTTPHeaderFields ?? [:] rawHeaders.removeValue(forKey: "User-Agent") var headers: JSON = rawHeaders.mapValues { value in @@ -322,7 +322,7 @@ public enum OnionRequestAPI { return promise } - internal static func sendOnionRequest(with payload: JSON, to destination: Destination, isJSONRequired: Bool = true) -> Promise { + public static func sendOnionRequest(with payload: JSON, to destination: Destination, isJSONRequired: Bool = true) -> Promise { let (promise, seal) = Promise.pending() var guardSnode: Snode! Threading.workQueue.async { // Avoid race conditions on `guardSnodes` and `paths` diff --git a/SessionSnodeKit/Snode.swift b/SessionSnodeKit/Snode.swift index 31e639737..6392787a3 100644 --- a/SessionSnodeKit/Snode.swift +++ b/SessionSnodeKit/Snode.swift @@ -10,7 +10,7 @@ public final class Snode : NSObject, NSCoding { // NSObject/NSCoding conformance } // MARK: Nested Types - internal enum Method : String { + public enum Method : String { case getSwarm = "get_snodes_for_pubkey" case getMessages = "retrieve" case sendMessage = "store" diff --git a/SessionSnodeKit/SnodeMessage.swift b/SessionSnodeKit/SnodeMessage.swift new file mode 100644 index 000000000..7fc3c21c1 --- /dev/null +++ b/SessionSnodeKit/SnodeMessage.swift @@ -0,0 +1,60 @@ +import PromiseKit +import SessionUtilities + +public final class SnodeMessage : NSObject, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility + /// The hex encoded public key of the recipient. + public let recipient: String + /// The content of the message. + public let data: LosslessStringConvertible + /// The time to live for the message in milliseconds. + public let ttl: UInt64 + /// When the proof of work was calculated. + /// + /// - Note: Expressed as milliseconds since 00:00:00 UTC on 1 January 1970. + public let timestamp: UInt64 + /// The base 64 encoded proof of work. + public let nonce: String + + // MARK: Initialization + public init(recipient: String, data: LosslessStringConvertible, ttl: UInt64, timestamp: UInt64, nonce: String) { + self.recipient = recipient + self.data = data + self.ttl = ttl + self.timestamp = timestamp + self.nonce = nonce + } + + // MARK: Coding + public init?(coder: NSCoder) { + guard let recipient = coder.decodeObject(forKey: "recipient") as! String?, + let data = coder.decodeObject(forKey: "data") as! String?, + let ttl = coder.decodeObject(forKey: "ttl") as! UInt64?, + let timestamp = coder.decodeObject(forKey: "timestamp") as! UInt64?, + let nonce = coder.decodeObject(forKey: "nonce") as! String? else { return nil } + self.recipient = recipient + self.data = data + self.ttl = ttl + self.timestamp = timestamp + self.nonce = nonce + super.init() + } + + public func encode(with coder: NSCoder) { + coder.encode(recipient, forKey: "recipient") + coder.encode(data, forKey: "data") + coder.encode(ttl, forKey: "ttl") + coder.encode(timestamp, forKey: "timestamp") + coder.encode(nonce, forKey: "nonce") + } + + // MARK: JSON Conversion + public func toJSON() -> JSON { + return [ + "pubKey" : recipient, + "data" : data.description, + "ttl" : String(ttl), + "timestamp" : String(timestamp), + "nonce" : nonce + ] + } +} diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 78e5c8c3a..6ad4584a0 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -600,6 +600,9 @@ C352A2FF25574B6300338F3E /* MessageSendJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A2FE25574B6300338F3E /* MessageSendJob.swift */; }; C352A30925574D8500338F3E /* Message+Destination.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A30825574D8400338F3E /* Message+Destination.swift */; }; C352A31325574F5200338F3E /* MessageReceiveJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A31225574F5200338F3E /* MessageReceiveJob.swift */; }; + C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A32E2557549C00338F3E /* NotifyPNServerJob.swift */; }; + C352A349255781F400338F3E /* AttachmentDownloadJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A348255781F400338F3E /* AttachmentDownloadJob.swift */; }; + C352A35B2557824E00338F3E /* AttachmentUploadJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */; }; C353F8F9244809150011121A /* PNOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C353F8F8244809150011121A /* PNOptionView.swift */; }; C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; }; C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */; }; @@ -634,7 +637,7 @@ C3C2A5A3255385C100C340D1 /* SessionSnodeKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C3C2A5A1255385C100C340D1 /* SessionSnodeKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; C3C2A5A6255385C100C340D1 /* SessionSnodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A59F255385C100C340D1 /* SessionSnodeKit.framework */; }; C3C2A5A7255385C100C340D1 /* SessionSnodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A59F255385C100C340D1 /* SessionSnodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - C3C2A5BF255385EE00C340D1 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5B6255385EC00C340D1 /* Message.swift */; }; + C3C2A5BF255385EE00C340D1 /* SnodeMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5B6255385EC00C340D1 /* SnodeMessage.swift */; }; C3C2A5C0255385EE00C340D1 /* Snode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5B7255385EC00C340D1 /* Snode.swift */; }; C3C2A5C1255385EE00C340D1 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5B8255385EC00C340D1 /* Storage.swift */; }; C3C2A5C2255385EE00C340D1 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5B9255385ED00C340D1 /* Configuration.swift */; }; @@ -1603,6 +1606,9 @@ C352A2FE25574B6300338F3E /* MessageSendJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSendJob.swift; sourceTree = ""; }; C352A30825574D8400338F3E /* Message+Destination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Message+Destination.swift"; sourceTree = ""; }; C352A31225574F5200338F3E /* MessageReceiveJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageReceiveJob.swift; sourceTree = ""; }; + C352A32E2557549C00338F3E /* NotifyPNServerJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyPNServerJob.swift; sourceTree = ""; }; + C352A348255781F400338F3E /* AttachmentDownloadJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentDownloadJob.swift; sourceTree = ""; }; + C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentUploadJob.swift; sourceTree = ""; }; C353F8F8244809150011121A /* PNOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNOptionView.swift; sourceTree = ""; }; C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = ""; }; C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = ""; }; @@ -1636,7 +1642,7 @@ C3C2A59F255385C100C340D1 /* SessionSnodeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SessionSnodeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C3C2A5A1255385C100C340D1 /* SessionSnodeKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SessionSnodeKit.h; sourceTree = ""; }; C3C2A5A2255385C100C340D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C3C2A5B6255385EC00C340D1 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; + C3C2A5B6255385EC00C340D1 /* SnodeMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnodeMessage.swift; sourceTree = ""; }; C3C2A5B7255385EC00C340D1 /* Snode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Snode.swift; sourceTree = ""; }; C3C2A5B8255385EC00C340D1 /* Storage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; C3C2A5B9255385ED00C340D1 /* Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; @@ -3244,8 +3250,11 @@ isa = PBXGroup; children = ( C352A2F425574B4700338F3E /* Job.swift */, - C352A2FE25574B6300338F3E /* MessageSendJob.swift */, + C352A348255781F400338F3E /* AttachmentDownloadJob.swift */, + C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */, C352A31225574F5200338F3E /* MessageReceiveJob.swift */, + C352A2FE25574B6300338F3E /* MessageSendJob.swift */, + C352A32E2557549C00338F3E /* NotifyPNServerJob.swift */, ); path = Jobs; sourceTree = ""; @@ -3296,12 +3305,12 @@ children = ( C3C2A5B0255385C700C340D1 /* Meta */, C3C2A5B9255385ED00C340D1 /* Configuration.swift */, - C3C2A5B6255385EC00C340D1 /* Message.swift */, C3C2A5BD255385EE00C340D1 /* Notification+OnionRequestAPI.swift */, C3C2A5BA255385ED00C340D1 /* OnionRequestAPI.swift */, C3C2A5BB255385ED00C340D1 /* OnionRequestAPI+Encryption.swift */, C3C2A5B7255385EC00C340D1 /* Snode.swift */, C3C2A5BE255385EE00C340D1 /* SnodeAPI.swift */, + C3C2A5B6255385EC00C340D1 /* SnodeMessage.swift */, C3C2A5B8255385EC00C340D1 /* Storage.swift */, C3C2A5CD255385F300C340D1 /* Utilities */, ); @@ -4889,7 +4898,7 @@ buildActionMask = 2147483647; files = ( C3C2A5E02553860B00C340D1 /* Threading.swift in Sources */, - C3C2A5BF255385EE00C340D1 /* Message.swift in Sources */, + C3C2A5BF255385EE00C340D1 /* SnodeMessage.swift in Sources */, C3C2A5C0255385EE00C340D1 /* Snode.swift in Sources */, C3C2A5C7255385EE00C340D1 /* SnodeAPI.swift in Sources */, C3C2A5C6255385EE00C340D1 /* Notification+OnionRequestAPI.swift in Sources */, @@ -4930,6 +4939,7 @@ C3471F4C25553AB000297E91 /* MessageReceiver+Decryption.swift in Sources */, C300A5D32554B05A00555489 /* TypingIndicator.swift in Sources */, C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */, + C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */, C300A5F22554B09800555489 /* MessageSender.swift in Sources */, C3C2A74D2553A39700C340D1 /* VisibleMessage.swift in Sources */, C352A31325574F5200338F3E /* MessageReceiveJob.swift in Sources */, @@ -4946,12 +4956,14 @@ C3471F4225553A4D00297E91 /* Threading.swift in Sources */, C300A5DD2554B06600555489 /* ClosedGroupUpdate.swift in Sources */, C3471FA42555439E00297E91 /* Notification+MessageSender.swift in Sources */, + C352A349255781F400338F3E /* AttachmentDownloadJob.swift in Sources */, C352A30925574D8500338F3E /* Message+Destination.swift in Sources */, C300A5E72554B07300555489 /* ExpirationTimerUpdate.swift in Sources */, C352A2FF25574B6300338F3E /* MessageSendJob.swift in Sources */, C3C2A75F2553A3C500C340D1 /* VisibleMessage+LinkPreview.swift in Sources */, C3C2A74425539EB700C340D1 /* Message.swift in Sources */, C300A5C92554B04E00555489 /* SessionRequest.swift in Sources */, + C352A35B2557824E00338F3E /* AttachmentUploadJob.swift in Sources */, C3BBE0C72554F1570050F1E3 /* FixedWidthInteger+BigEndian.swift in Sources */, C300A5B22554AF9800555489 /* VisibleMessage+Profile.swift in Sources */, C352A2F525574B4700338F3E /* Job.swift in Sources */,