Implement session request

This commit is contained in:
nielsandriesse 2020-11-06 11:41:01 +11:00
parent d407467279
commit e8892a1f0f
9 changed files with 117 additions and 31 deletions

View file

@ -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
}
}

View file

@ -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).")

View file

@ -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
}
}
}

View file

@ -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 {

View file

@ -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

View file

@ -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
}
}

View file

@ -0,0 +1,8 @@
import SessionProtocolKit
public protocol SessionMessagingKitStorageProtocol {
func with(_ work: (Any) -> Void)
func getOrGenerateRegistrationID(using transaction: Any) -> UInt32
}

View file

@ -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 = "<group>"; };
C3AA6BB824CE8F1B002358B6 /* Migrating Translations from Android.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Migrating Translations from Android.md"; sourceTree = "<group>"; };
C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = translations/fa.lproj/Localizable.strings; sourceTree = "<group>"; };
C3BBE0752554CDA60050F1E3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
C3BBE07F2554CDD70050F1E3 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = "<group>"; };
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 = "<group>"; };
C3C2A5A2255385C100C340D1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -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 = "<group>";
@ -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 */,