Implement destination coding

This commit is contained in:
nielsandriesse 2020-11-08 16:31:48 +11:00
parent 71d51a873a
commit b9f2881c9d
7 changed files with 160 additions and 11 deletions

View File

@ -1,7 +1,5 @@
import SessionUtilities
// TODO: Destination encoding & decoding
public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
public var delegate: JobDelegate?
private let message: Message
@ -20,15 +18,35 @@ public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCodi
// MARK: Coding
public init?(coder: NSCoder) {
guard let message = coder.decodeObject(forKey: "message") as! Message?,
let destination = coder.decodeObject(forKey: "destination") as! Message.Destination? else { return nil }
var rawDestination = coder.decodeObject(forKey: "destination") as! String? else { return nil }
self.message = message
self.destination = destination
if rawDestination.removePrefix("contact(") {
guard rawDestination.removeSuffix(")") else { return nil }
let publicKey = rawDestination
destination = .contact(publicKey: publicKey)
} else if rawDestination.removePrefix("closedGroup") {
guard rawDestination.removeSuffix(")") else { return nil }
let groupPublicKey = rawDestination
destination = .closedGroup(groupPublicKey: groupPublicKey)
} else if rawDestination.removePrefix("openGroup") {
guard rawDestination.removeSuffix(")") else { return nil }
let components = rawDestination.split(separator: ",").map { String($0).trimmingCharacters(in: .whitespacesAndNewlines) }
guard components.count == 2, let channel = UInt64(components[0]) else { return nil }
let server = components[1]
destination = .openGroup(channel: channel, server: server)
} else {
return nil
}
self.failureCount = coder.decodeObject(forKey: "failureCount") as! UInt? ?? 0
}
public func encode(with coder: NSCoder) {
coder.encode(message, forKey: "message")
coder.encode(destination, forKey: "destination")
switch destination {
case .contact(let publicKey): coder.encode("contact(\(publicKey))", forKey: "destination")
case .closedGroup(let groupPublicKey): coder.encode("closedGroup(\(groupPublicKey))", forKey: "destination")
case .openGroup(let channel, let server): coder.encode("openGroup(\(channel), \(server))")
}
coder.encode(failureCount, forKey: "failureCount")
}
@ -55,3 +73,21 @@ public final class MessageSendJob : NSObject, Job, NSCoding { // NSObject/NSCodi
}
}
// MARK: Convenience
private extension String {
@discardableResult
mutating func removePrefix<T : StringProtocol>(_ prefix: T) -> Bool {
guard hasPrefix(prefix) else { return false }
removeFirst(prefix.count)
return true
}
@discardableResult
mutating func removeSuffix<T : StringProtocol>(_ suffix: T) -> Bool {
guard hasSuffix(suffix) else { return false }
removeLast(suffix.count)
return true
}
}

View File

@ -302,11 +302,24 @@ public enum OnionRequestAPI {
endpoint = String(url[endpointStartIndex..<url.endIndex])
}
let parametersAsString: String
headers["Content-Type"] = request.allHTTPHeaderFields!["Content-Type"]
if let parametersAsInputStream = request.httpBodyStream, let parameters = try? Data(from: parametersAsInputStream) {
parametersAsString = "{ \"fileUpload\" : \"\(String(data: parameters.base64EncodedData(), encoding: .utf8) ?? "null")\" }"
if let tsRequest = request as? TSRequest {
headers["Content-Type"] = "application/json"
let tsRequestParameters = tsRequest.parameters
if !tsRequestParameters.isEmpty {
guard let parameters = try? JSONSerialization.data(withJSONObject: tsRequestParameters, options: [ .fragmentsAllowed ]) else {
return Promise(error: HTTP.Error.invalidJSON)
}
parametersAsString = String(bytes: parameters, encoding: .utf8) ?? "null"
} else {
parametersAsString = "null"
}
} else {
parametersAsString = "null"
headers["Content-Type"] = request.allHTTPHeaderFields!["Content-Type"]
if let parametersAsInputStream = request.httpBodyStream, let parameters = try? Data(from: parametersAsInputStream) {
parametersAsString = "{ \"fileUpload\" : \"\(String(data: parameters.base64EncodedData(), encoding: .utf8) ?? "null")\" }"
} else {
parametersAsString = "null"
}
}
let payload: JSON = [
"body" : parametersAsString,

View File

@ -3,6 +3,7 @@
FOUNDATION_EXPORT double SessionUtilitiesVersionNumber;
FOUNDATION_EXPORT const unsigned char SessionUtilitiesVersionString[];
#import <SessionUtilities/ECKeyPair+Utilities.h>
#import <SessionUtilities/NSDate+Timestamp.h>
#import <SessionUtilities/NSTimer+Proxying.h>
#import <SessionUtilities/ECKeyPair+Utilities.h>
#import <SessionUtilities/TSRequest.h>

View File

@ -37,7 +37,6 @@ static void *kNSTimer_SN_Proxy = &kNSTimer_SN_Proxy;
#if DEBUG
assert(proxy != nil);
#endif
objc_setAssociatedObject(self, kNSTimer_SN_Proxy, proxy, OBJC_ASSOCIATION_RETAIN);
}

View File

@ -0,0 +1,29 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#define textSecureHTTPTimeOut 10
@interface TSRequest : NSMutableURLRequest
@property (nonatomic, readonly) NSDictionary<NSString *, id> *parameters;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithURL:(NSURL *)URL;
- (instancetype)initWithURL:(NSURL *)URL
cachePolicy:(NSURLRequestCachePolicy)cachePolicy
timeoutInterval:(NSTimeInterval)timeoutInterval NS_UNAVAILABLE;
- (instancetype)initWithURL:(NSURL *)URL
method:(NSString *)method
parameters:(nullable NSDictionary<NSString *, id> *)parameters;
+ (instancetype)requestWithUrl:(NSURL *)url
method:(NSString *)method
parameters:(nullable NSDictionary<NSString *, id> *)parameters;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,63 @@
#import "TSRequest.h"
NS_ASSUME_NONNULL_BEGIN
@implementation TSRequest
- (id)initWithURL:(NSURL *)URL {
self = [super initWithURL:URL
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:textSecureHTTPTimeOut];
if (!self) {
return nil;
}
_parameters = @{};
return self;
}
- (instancetype)init
{
return nil;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)initWithURL:(NSURL *)URL
cachePolicy:(NSURLRequestCachePolicy)cachePolicy
timeoutInterval:(NSTimeInterval)timeoutInterval
{
return nil;
}
- (instancetype)initWithURL:(NSURL *)URL
method:(NSString *)method
parameters:(nullable NSDictionary<NSString *, id> *)parameters
{
self = [super initWithURL:URL
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:textSecureHTTPTimeOut];
if (!self) {
return nil;
}
_parameters = parameters ?: @{};
[self setHTTPMethod:method];
return self;
}
+ (instancetype)requestWithUrl:(NSURL *)url
method:(NSString *)method
parameters:(nullable NSDictionary<NSString *, id> *)parameters
{
return [[TSRequest alloc] initWithURL:url method:method parameters:parameters];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -607,6 +607,8 @@
C352A3772557864000338F3E /* NSTimer+Proxying.h in Headers */ = {isa = PBXBuildFile; fileRef = C352A3762557859C00338F3E /* NSTimer+Proxying.h */; settings = {ATTRIBUTES = (Public, ); }; };
C352A3892557876500338F3E /* JobQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A3882557876500338F3E /* JobQueue.swift */; };
C352A3932557883D00338F3E /* JobDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A3922557883D00338F3E /* JobDelegate.swift */; };
C352A3A62557B60D00338F3E /* TSRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = C352A3A52557B60D00338F3E /* TSRequest.m */; };
C352A3B72557B6ED00338F3E /* TSRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = C352A3A42557B5F000338F3E /* TSRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
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 */; };
@ -1617,6 +1619,8 @@
C352A3762557859C00338F3E /* NSTimer+Proxying.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSTimer+Proxying.h"; sourceTree = "<group>"; };
C352A3882557876500338F3E /* JobQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobQueue.swift; sourceTree = "<group>"; };
C352A3922557883D00338F3E /* JobDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobDelegate.swift; sourceTree = "<group>"; };
C352A3A42557B5F000338F3E /* TSRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TSRequest.h; sourceTree = "<group>"; };
C352A3A52557B60D00338F3E /* TSRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TSRequest.m; sourceTree = "<group>"; };
C353F8F8244809150011121A /* PNOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNOptionView.swift; sourceTree = "<group>"; };
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = "<group>"; };
@ -3368,6 +3372,8 @@
C352A36C2557858D00338F3E /* NSTimer+Proxying.m */,
C3C2A5D62553860B00C340D1 /* Promise+Retrying.swift */,
C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */,
C352A3A42557B5F000338F3E /* TSRequest.h */,
C352A3A52557B60D00338F3E /* TSRequest.m */,
);
path = SessionUtilities;
sourceTree = "<group>";
@ -3821,6 +3827,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
C352A3B72557B6ED00338F3E /* TSRequest.h in Headers */,
C300A63B2554B72200555489 /* NSDate+Timestamp.h in Headers */,
C352A3772557864000338F3E /* NSTimer+Proxying.h in Headers */,
C3471F5625553E1100297E91 /* ECKeyPair+Utilities.h in Headers */,
@ -4938,6 +4945,7 @@
C3471F6825553E7600297E91 /* ECKeyPair+Utilities.m in Sources */,
C3BBE0AA2554D4DE0050F1E3 /* Dictionary+Description.swift in Sources */,
C3C2AC2E2553CBEB00C340D1 /* String+Trimming.swift in Sources */,
C352A3A62557B60D00338F3E /* TSRequest.m in Sources */,
C3471ED42555386B00297E91 /* AESGCM.swift in Sources */,
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */,
C3BBE0A92554D4DE0050F1E3 /* HTTP.swift in Sources */,