diff --git a/SessionMessagingKit/Configuration.swift b/SessionMessagingKit/Configuration.swift new file mode 100644 index 000000000..3399c110d --- /dev/null +++ b/SessionMessagingKit/Configuration.swift @@ -0,0 +1,13 @@ + +public struct Configuration { + public let storage: SessionMessagingKitStorageProtocol + + internal static var shared: Configuration! +} + +public enum SessionMessagingKit { // Just to make the external API nice + + public static func configure(with configuration: Configuration) { + Configuration.shared = configuration + } +} diff --git a/SessionMessagingKit/Messages/Control Message/ExpirationTimerUpdate.swift b/SessionMessagingKit/Messages/Control Message/ExpirationTimerUpdate.swift index e9f94c32b..2a648f622 100644 --- a/SessionMessagingKit/Messages/Control Message/ExpirationTimerUpdate.swift +++ b/SessionMessagingKit/Messages/Control Message/ExpirationTimerUpdate.swift @@ -5,10 +5,8 @@ public final class ExpirationTimerUpdate : ControlMessage { public var duration: UInt32? // MARK: Initialization - init(sentTimestamp: UInt64, receivedTimestamp: UInt64, duration: UInt32) { + init(duration: UInt32) { super.init() - self.sentTimestamp = sentTimestamp - self.receivedTimestamp = receivedTimestamp self.duration = duration } @@ -25,23 +23,24 @@ public final class ExpirationTimerUpdate : ControlMessage { // MARK: Proto Conversion public override class func fromProto(_ proto: SNProtoContent) -> ExpirationTimerUpdate? { - guard let data = proto.dataMessage else { return nil } - let isExpirationTimerUpdate = (data.flags & UInt32(SNProtoDataMessage.SNProtoDataMessageFlags.expirationTimerUpdate.rawValue)) != 0 + guard let dataMessageProto = proto.dataMessage else { return nil } + let isExpirationTimerUpdate = (dataMessageProto.flags & UInt32(SNProtoDataMessage.SNProtoDataMessageFlags.expirationTimerUpdate.rawValue)) != 0 guard isExpirationTimerUpdate else { return nil } - let timestamp = data.timestamp - let now = NSDate.millisecondTimestamp() - let duration = data.expireTimer - return ExpirationTimerUpdate(sentTimestamp: timestamp, receivedTimestamp: now, duration: duration) + let duration = dataMessageProto.expireTimer + return ExpirationTimerUpdate(duration: duration) } public override func toProto() -> SNProtoContent? { - guard let duration = duration else { return nil } - let expirationTimerUpdateProto = SNProtoDataMessage.builder() - expirationTimerUpdateProto.setFlags(UInt32(SNProtoDataMessage.SNProtoDataMessageFlags.expirationTimerUpdate.rawValue)) - expirationTimerUpdateProto.setExpireTimer(duration) + guard let duration = duration else { + SNLog("Couldn't construct expiration timer update proto from: \(self).") + return nil + } + let dataMessageProto = SNProtoDataMessage.builder() + dataMessageProto.setFlags(UInt32(SNProtoDataMessage.SNProtoDataMessageFlags.expirationTimerUpdate.rawValue)) + dataMessageProto.setExpireTimer(duration) let contentProto = SNProtoContent.builder() do { - contentProto.setDataMessage(try expirationTimerUpdateProto.build()) + contentProto.setDataMessage(try dataMessageProto.build()) return try contentProto.build() } catch { SNLog("Couldn't construct expiration timer update proto from: \(self).") diff --git a/SessionMessagingKit/Messages/Control Message/SessionRequest.swift b/SessionMessagingKit/Messages/Control Message/SessionRequest.swift index bb95b6f1c..af66018ba 100644 --- a/SessionMessagingKit/Messages/Control Message/SessionRequest.swift +++ b/SessionMessagingKit/Messages/Control Message/SessionRequest.swift @@ -1,5 +1,70 @@ +import SessionUtilities +import SessionProtocolKit @objc(SNSessionRequest) public final class SessionRequest : ControlMessage { + private var preKeyBundle: PreKeyBundle? + // MARK: Initialization + init(preKeyBundle: PreKeyBundle) { + super.init() + self.preKeyBundle = preKeyBundle + } + + // MARK: Coding + public required init?(coder: NSCoder) { + super.init(coder: coder) + if let preKeyBundle = coder.decodeObject(forKey: "preKeyBundle") as! PreKeyBundle? { self.preKeyBundle = preKeyBundle } + } + + public override func encode(with coder: NSCoder) { + super.encode(with: coder) + coder.encode(preKeyBundle, forKey: "preKeyBundle") + } + + // MARK: Proto Conversion + public override class func fromProto(_ proto: SNProtoContent) -> SessionRequest? { + guard proto.nullMessage != nil, let preKeyBundleProto = proto.prekeyBundleMessage else { return nil } + var registrationID: UInt32 = 0 + Configuration.shared.storage.with { transaction in + registrationID = Configuration.shared.storage.getOrGenerateRegistrationID(using: transaction) + } + guard let preKeyBundle = PreKeyBundle(registrationId: Int32(registrationID), + deviceId: 1, + preKeyId: Int32(preKeyBundleProto.prekeyID), + preKeyPublic: preKeyBundleProto.prekey, + signedPreKeyPublic: preKeyBundleProto.signedKey, + signedPreKeyId: Int32(preKeyBundleProto.signedKeyID), + signedPreKeySignature: preKeyBundleProto.signature, + identityKey: preKeyBundleProto.identityKey) else { return nil } + return SessionRequest(preKeyBundle: preKeyBundle) + } + + public override func toProto() -> SNProtoContent? { + guard let preKeyBundle = preKeyBundle else { + SNLog("Couldn't construct session request proto from: \(self).") + return nil + } + 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 preKeyBundleProto = SNProtoPrekeyBundleMessage.builder() + preKeyBundleProto.setIdentityKey(preKeyBundle.identityKey) + preKeyBundleProto.setDeviceID(UInt32(preKeyBundle.deviceId)) + preKeyBundleProto.setPrekeyID(UInt32(preKeyBundle.preKeyId)) + preKeyBundleProto.setPrekey(preKeyBundle.preKeyPublic) + preKeyBundleProto.setSignedKeyID(UInt32(preKeyBundle.signedPreKeyId)) + preKeyBundleProto.setSignedKey(preKeyBundle.signedPreKeyPublic) + preKeyBundleProto.setSignature(preKeyBundle.signedPreKeySignature) + let contentProto = SNProtoContent.builder() + do { + contentProto.setNullMessage(try nullMessageProto.build()) + contentProto.setPrekeyBundleMessage(try preKeyBundleProto.build()) + return try contentProto.build() + } catch { + SNLog("Couldn't construct session request proto from: \(self).") + return nil + } + } } diff --git a/SessionMessagingKit/Messages/Control Message/TypingIndicator.swift b/SessionMessagingKit/Messages/Control Message/TypingIndicator.swift index 7bb5c5c50..51e2e2c23 100644 --- a/SessionMessagingKit/Messages/Control Message/TypingIndicator.swift +++ b/SessionMessagingKit/Messages/Control Message/TypingIndicator.swift @@ -24,10 +24,8 @@ public final class TypingIndicator : ControlMessage { } // MARK: Initialization - init(sentTimestamp: UInt64, receivedTimestamp: UInt64, kind: Kind) { + init(kind: Kind) { super.init() - self.sentTimestamp = sentTimestamp - self.receivedTimestamp = receivedTimestamp self.kind = kind } @@ -45,14 +43,15 @@ public final class TypingIndicator : ControlMessage { // MARK: Proto Conversion public override class func fromProto(_ proto: SNProtoContent) -> TypingIndicator? { guard let typingIndicatorProto = proto.typingMessage else { return nil } - let timestamp = typingIndicatorProto.timestamp - let now = NSDate.millisecondTimestamp() let kind = Kind.fromProto(typingIndicatorProto.action) - return TypingIndicator(sentTimestamp: timestamp, receivedTimestamp: now, kind: kind) + return TypingIndicator(kind: kind) } public override func toProto() -> SNProtoContent? { - guard let timestamp = sentTimestamp, let kind = kind else { return nil } + guard let timestamp = sentTimestamp, let kind = kind else { + SNLog("Couldn't construct typing indicator proto from: \(self).") + return nil + } let typingIndicatorProto = SNProtoTypingMessage.builder(timestamp: timestamp, action: kind.toProto()) let contentProto = SNProtoContent.builder() do { diff --git a/SessionMessagingKit/Messages/Message.swift b/SessionMessagingKit/Messages/Message.swift index 9a38ecf14..c783be5ac 100644 --- a/SessionMessagingKit/Messages/Message.swift +++ b/SessionMessagingKit/Messages/Message.swift @@ -6,6 +6,7 @@ public class Message : NSObject, NSCoding { // Not a protocol for YapDatabase co public var threadID: String? public var sentTimestamp: UInt64? public var receivedTimestamp: UInt64? + public var recipient: String? public override init() { } @@ -15,6 +16,7 @@ public class Message : NSObject, NSCoding { // Not a protocol for YapDatabase co if let threadID = coder.decodeObject(forKey: "threadID") as! String? { self.threadID = threadID } if let sentTimestamp = coder.decodeObject(forKey: "sentTimestamp") as! UInt64? { self.sentTimestamp = sentTimestamp } if let receivedTimestamp = coder.decodeObject(forKey: "receivedTimestamp") as! UInt64? { self.receivedTimestamp = receivedTimestamp } + if let recipient = coder.decodeObject(forKey: "recipient") as! String? { self.recipient = recipient } } public func encode(with coder: NSCoder) { @@ -22,6 +24,7 @@ public class Message : NSObject, NSCoding { // Not a protocol for YapDatabase co coder.encode(threadID, forKey: "threadID") coder.encode(sentTimestamp, forKey: "sentTimestamp") coder.encode(receivedTimestamp, forKey: "receivedTimestamp") + coder.encode(recipient, forKey: "recipient") } // MARK: Proto Conversion diff --git a/SessionMessagingKit/Messages/Visible Message/VisibleMessage.swift b/SessionMessagingKit/Messages/Visible Message/VisibleMessage.swift index e9e424f4c..75a47f7ef 100644 --- a/SessionMessagingKit/Messages/Visible Message/VisibleMessage.swift +++ b/SessionMessagingKit/Messages/Visible Message/VisibleMessage.swift @@ -7,13 +7,4 @@ public final class VisibleMessage : Message { public var linkPreview: LinkPreview? public var contact: Contact? public var profile: Profile? - - public override class func fromProto(_ proto: SNProtoContent) -> VisibleMessage? { - return nil -// guard let data = proto.dataMessage, -// let text = data.body else { return nil } -// let result = VisibleMessage() -// result.text = text -// return result - } } diff --git a/SessionMessagingKit/Storage.swift b/SessionMessagingKit/Storage.swift new file mode 100644 index 000000000..7dc52f5b8 --- /dev/null +++ b/SessionMessagingKit/Storage.swift @@ -0,0 +1,8 @@ +import SessionProtocolKit + +public protocol SessionMessagingKitStorageProtocol { + + func with(_ work: (Any) -> Void) + + func getOrGenerateRegistrationID(using transaction: Any) -> UInt32 +} diff --git a/SessionProtocolKit/Shared Sender Keys/Storage.swift b/SessionProtocolKit/Storage.swift similarity index 100% rename from SessionProtocolKit/Shared Sender Keys/Storage.swift rename to SessionProtocolKit/Storage.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 336ffd44a..ba7ea3d9b 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -612,6 +612,8 @@ C39DD28A24F3336E008590FC /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C39DD28724F3318C008590FC /* Colors.xcassets */; }; C39DD28B24F3336F008590FC /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C39DD28724F3318C008590FC /* Colors.xcassets */; }; C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D12553860800C340D1 /* Array+Description.swift */; }; + C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE0752554CDA60050F1E3 /* Configuration.swift */; }; + C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE07F2554CDD70050F1E3 /* Storage.swift */; }; 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, ); }; }; @@ -1605,6 +1607,8 @@ C39DD28724F3318C008590FC /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = ""; }; C3AA6BB824CE8F1B002358B6 /* Migrating Translations from Android.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Migrating Translations from Android.md"; sourceTree = ""; }; C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = translations/fa.lproj/Localizable.strings; sourceTree = ""; }; + C3BBE0752554CDA60050F1E3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; + C3BBE07F2554CDD70050F1E3 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; 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 = ""; }; @@ -3311,6 +3315,8 @@ children = ( C3C2A7802553AA6300C340D1 /* Protos */, C3C2A70A25539DF900C340D1 /* Meta */, + C3BBE0752554CDA60050F1E3 /* Configuration.swift */, + C3BBE07F2554CDD70050F1E3 /* Storage.swift */, C300A5BB2554AFFB00555489 /* Messages */, C300A5F02554B08500555489 /* Pipelines */, ); @@ -3348,6 +3354,7 @@ children = ( C3C2A8762553B42C00C340D1 /* Meta */, C3C2AC092553C9A100C340D1 /* Configuration.swift */, + C3C2ABF72553C8A300C340D1 /* Storage.swift */, C3C2AB622553C5D400C340D1 /* Shared Sender Keys */, C3C2AB492553C4A800C340D1 /* Signal */, ); @@ -3528,7 +3535,6 @@ C3C2ABE32553C74400C340D1 /* ClosedGroupRatchet.swift */, C3C2ABED2553C76900C340D1 /* ClosedGroupSenderKey.swift */, C3C2AB632553C5FF00C340D1 /* SharedSenderKeys.swift */, - C3C2ABF72553C8A300C340D1 /* Storage.swift */, ); path = "Shared Sender Keys"; sourceTree = ""; @@ -4872,11 +4878,13 @@ C3C2A74D2553A39700C340D1 /* VisibleMessage.swift in Sources */, C3C2A7562553A3AB00C340D1 /* VisibleMessage+Quote.swift in Sources */, C300A5FC2554B0A000555489 /* ReceivingPipeline.swift in Sources */, + C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */, C3C2A7842553AAF300C340D1 /* SNProto.swift in Sources */, C3C2A7682553A3D900C340D1 /* VisibleMessage+Contact.swift in Sources */, C3C2A7852553AAF300C340D1 /* SessionProtos.pb.swift in Sources */, C3C2A7712553A41E00C340D1 /* ControlMessage.swift in Sources */, C300A5BD2554B00D00555489 /* ReadReceipt.swift in Sources */, + C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */, C300A5DD2554B06600555489 /* ClosedGroupUpdate.swift in Sources */, C300A5E72554B07300555489 /* ExpirationTimerUpdate.swift in Sources */, C3C2A75F2553A3C500C340D1 /* VisibleMessage+LinkPreview.swift in Sources */,