mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Started working on MessageRequestResponse
handling for SOGS message requests
Pointing Curve25519 to use a fork that exposes an XEd25519 conversion method Fixed an issue where I had broken all message sending due to the SnodeAPI casting Onion responses to `Any`
This commit is contained in:
parent
dbead5e3c8
commit
cc2a077a6c
3
Podfile
3
Podfile
|
@ -24,7 +24,8 @@ abstract_target 'GlobalDependencies' do
|
||||||
|
|
||||||
# Dependencies to be included only in all extensions/frameworks
|
# Dependencies to be included only in all extensions/frameworks
|
||||||
abstract_target 'FrameworkAndExtensionDependencies' do
|
abstract_target 'FrameworkAndExtensionDependencies' do
|
||||||
pod 'Curve25519Kit', git: 'https://github.com/signalapp/Curve25519Kit.git'
|
# TODO: Swap this to use an oxen-io fork
|
||||||
|
pod 'Curve25519Kit', git: 'https://github.com/mpretty-cyro/session-ios-curve-25519-kit.git', branch: 'session'
|
||||||
pod 'SignalCoreKit', git: 'https://github.com/oxen-io/session-ios-core-kit', branch: 'session-version'
|
pod 'SignalCoreKit', git: 'https://github.com/oxen-io/session-ios-core-kit', branch: 'session-version'
|
||||||
|
|
||||||
target 'SessionNotificationServiceExtension'
|
target 'SessionNotificationServiceExtension'
|
||||||
|
|
11
Podfile.lock
11
Podfile.lock
|
@ -123,7 +123,7 @@ PODS:
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- AFNetworking
|
- AFNetworking
|
||||||
- CryptoSwift
|
- CryptoSwift
|
||||||
- Curve25519Kit (from `https://github.com/signalapp/Curve25519Kit.git`)
|
- Curve25519Kit (from `https://github.com/mpretty-cyro/session-ios-curve-25519-kit.git`, branch `session`)
|
||||||
- Mantle (from `https://github.com/signalapp/Mantle`, branch `signal-master`)
|
- Mantle (from `https://github.com/signalapp/Mantle`, branch `signal-master`)
|
||||||
- Nimble
|
- Nimble
|
||||||
- NVActivityIndicatorView
|
- NVActivityIndicatorView
|
||||||
|
@ -156,7 +156,8 @@ SPEC REPOS:
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
Curve25519Kit:
|
Curve25519Kit:
|
||||||
:git: https://github.com/signalapp/Curve25519Kit.git
|
:branch: session
|
||||||
|
:git: https://github.com/mpretty-cyro/session-ios-curve-25519-kit.git
|
||||||
Mantle:
|
Mantle:
|
||||||
:branch: signal-master
|
:branch: signal-master
|
||||||
:git: https://github.com/signalapp/Mantle
|
:git: https://github.com/signalapp/Mantle
|
||||||
|
@ -174,8 +175,8 @@ EXTERNAL SOURCES:
|
||||||
|
|
||||||
CHECKOUT OPTIONS:
|
CHECKOUT OPTIONS:
|
||||||
Curve25519Kit:
|
Curve25519Kit:
|
||||||
:commit: 4fc1c10e98fff2534b5379a9bb587430fdb8e577
|
:commit: a23049232dc6c18928cdacfbcef287dad954c5c6
|
||||||
:git: https://github.com/signalapp/Curve25519Kit.git
|
:git: https://github.com/mpretty-cyro/session-ios-curve-25519-kit.git
|
||||||
Mantle:
|
Mantle:
|
||||||
:commit: e7e46253bb01ce39525d90aa69ed9e85e758bfc4
|
:commit: e7e46253bb01ce39525d90aa69ed9e85e758bfc4
|
||||||
:git: https://github.com/signalapp/Mantle
|
:git: https://github.com/signalapp/Mantle
|
||||||
|
@ -213,6 +214,6 @@ SPEC CHECKSUMS:
|
||||||
YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331
|
YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331
|
||||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||||
|
|
||||||
PODFILE CHECKSUM: 42874150fd08761ee6907c5bacf22b95ae849d8c
|
PODFILE CHECKSUM: b3b9b5446a109dbcdb5381176ebe431f7762558d
|
||||||
|
|
||||||
COCOAPODS: 1.11.2
|
COCOAPODS: 1.11.2
|
||||||
|
|
|
@ -3,6 +3,34 @@ import Sodium
|
||||||
|
|
||||||
extension Storage {
|
extension Storage {
|
||||||
|
|
||||||
|
public func getAllMessageRequestThreads() -> [String: TSContactThread] {
|
||||||
|
var result: [String: TSContactThread] = [:]
|
||||||
|
|
||||||
|
Storage.read { transaction in
|
||||||
|
result = self.getAllMessageRequestThreads(using: transaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
public func getAllMessageRequestThreads(using transaction: YapDatabaseReadTransaction) -> [String: TSContactThread] {
|
||||||
|
var result = [String: TSContactThread]()
|
||||||
|
|
||||||
|
// FIXME: We might be able to optimise this further by filtering the SQL query `WHERE uniqueId LIKE '_c15'
|
||||||
|
let blindedThreadPrefix: String = TSContactThread.threadID(fromContactSessionID: SessionId.Prefix.blinded.rawValue)
|
||||||
|
|
||||||
|
transaction.enumerateKeysAndObjects(
|
||||||
|
inCollection: TSContactThread.collection(),
|
||||||
|
using: { threadID, object, _ in
|
||||||
|
guard let contactThread = object as? TSContactThread else { return }
|
||||||
|
result[threadID] = contactThread
|
||||||
|
},
|
||||||
|
withFilter: { key -> Bool in key.starts(with: blindedThreadPrefix) }
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the ID of the thread.
|
/// Returns the ID of the thread.
|
||||||
public func getOrCreateThread(for publicKey: String, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? {
|
public func getOrCreateThread(for publicKey: String, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? {
|
||||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||||
|
|
|
@ -115,7 +115,7 @@ public final class OpenGroupAPI: NSObject {
|
||||||
// TODO: Limit?
|
// TODO: Limit?
|
||||||
// queryParameters: [ .limit: 256 ]
|
// queryParameters: [ .limit: 256 ]
|
||||||
),
|
),
|
||||||
responseType: [DirectMessage].self
|
responseType: [DirectMessage]?.self // 'inboxSince' will return a `304` with an empty response if no messages
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -507,30 +507,30 @@ public final class OpenGroupAPI: NSObject {
|
||||||
/// method, in order to call this directly remove the `@available` line and make sure to route the response of this method to the
|
/// method, in order to call this directly remove the `@available` line and make sure to route the response of this method to the
|
||||||
/// `OpenGroupManager.handleInbox` method to ensure things are processed correctly
|
/// `OpenGroupManager.handleInbox` method to ensure things are processed correctly
|
||||||
@available(*, unavailable, message: "Avoid using this directly, use the pre-build `poll()` method instead")
|
@available(*, unavailable, message: "Avoid using this directly, use the pre-build `poll()` method instead")
|
||||||
public static func inbox(on server: String, using dependencies: Dependencies = Dependencies()) -> Promise<(OnionRequestResponseInfoType, [DirectMessage])> {
|
public static func inbox(on server: String, using dependencies: Dependencies = Dependencies()) -> Promise<(OnionRequestResponseInfoType, [DirectMessage]?)> {
|
||||||
let request: Request = Request<NoBody>(
|
let request: Request = Request<NoBody>(
|
||||||
server: server,
|
server: server,
|
||||||
endpoint: .inbox
|
endpoint: .inbox
|
||||||
)
|
)
|
||||||
|
|
||||||
return send(request, using: dependencies)
|
return send(request, using: dependencies)
|
||||||
.decoded(as: [DirectMessage].self, on: OpenGroupAPI.workQueue, error: Error.parsingFailed, using: dependencies)
|
.decoded(as: [DirectMessage]?.self, on: OpenGroupAPI.workQueue, error: Error.parsingFailed, using: dependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polls for any DMs received since the given id
|
/// Polls for any DMs received since the given id, this method will return a `304` with an empty response if there are no messages
|
||||||
///
|
///
|
||||||
/// **Note:** This is the direct request to retrieve messages requests for a specific Open Group since a given messages so should be retrieved
|
/// **Note:** This is the direct request to retrieve messages requests for a specific Open Group since a given messages so should be retrieved
|
||||||
/// automatically from the `poll()` method, in order to call this directly remove the `@available` line and make sure to route the response
|
/// automatically from the `poll()` method, in order to call this directly remove the `@available` line and make sure to route the response
|
||||||
/// of this method to the `OpenGroupManager.handleInbox` method to ensure things are processed correctly
|
/// of this method to the `OpenGroupManager.handleInbox` method to ensure things are processed correctly
|
||||||
@available(*, unavailable, message: "Avoid using this directly, use the pre-build `poll()` method instead")
|
@available(*, unavailable, message: "Avoid using this directly, use the pre-build `poll()` method instead")
|
||||||
public static func inboxSince(id: Int64, on server: String, using dependencies: Dependencies = Dependencies()) -> Promise<(OnionRequestResponseInfoType, [DirectMessage])> {
|
public static func inboxSince(id: Int64, on server: String, using dependencies: Dependencies = Dependencies()) -> Promise<(OnionRequestResponseInfoType, [DirectMessage]?)> {
|
||||||
let request: Request = Request<NoBody>(
|
let request: Request = Request<NoBody>(
|
||||||
server: server,
|
server: server,
|
||||||
endpoint: .inboxSince(id: id)
|
endpoint: .inboxSince(id: id)
|
||||||
)
|
)
|
||||||
|
|
||||||
return send(request, using: dependencies)
|
return send(request, using: dependencies)
|
||||||
.decoded(as: [DirectMessage].self, on: OpenGroupAPI.workQueue, error: Error.parsingFailed, using: dependencies)
|
.decoded(as: [DirectMessage]?.self, on: OpenGroupAPI.workQueue, error: Error.parsingFailed, using: dependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delivers a direct message to a user via their blinded Session ID
|
/// Delivers a direct message to a user via their blinded Session ID
|
||||||
|
|
|
@ -319,6 +319,8 @@ public final class OpenGroupManager: NSObject {
|
||||||
isBackgroundPoll: Bool,
|
isBackgroundPoll: Bool,
|
||||||
using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()
|
using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()
|
||||||
) {
|
) {
|
||||||
|
// Don't need to do anything if we have no messages (it's a valid case)
|
||||||
|
guard !messages.isEmpty else { return }
|
||||||
guard let serverPublicKey: String = dependencies.storage.getOpenGroupPublicKey(for: server) else {
|
guard let serverPublicKey: String = dependencies.storage.getOpenGroupPublicKey(for: server) else {
|
||||||
SNLog("Couldn't receive inbox message.")
|
SNLog("Couldn't receive inbox message.")
|
||||||
return
|
return
|
||||||
|
|
|
@ -15,6 +15,8 @@ public protocol SodiumType {
|
||||||
|
|
||||||
func combineKeys(lhsKeyBytes: Bytes, rhsKeyBytes: Bytes) -> Bytes?
|
func combineKeys(lhsKeyBytes: Bytes, rhsKeyBytes: Bytes) -> Bytes?
|
||||||
func sharedBlindedEncryptionKey(secretKey a: Bytes, otherBlindedPublicKey: Bytes, fromBlindedPublicKey kA: Bytes, toBlindedPublicKey kB: Bytes, genericHash: GenericHashType) -> Bytes?
|
func sharedBlindedEncryptionKey(secretKey a: Bytes, otherBlindedPublicKey: Bytes, fromBlindedPublicKey kA: Bytes, toBlindedPublicKey kB: Bytes, genericHash: GenericHashType) -> Bytes?
|
||||||
|
|
||||||
|
func sessionId(_ sessionId: String, matchesBlindedId blindedSessionId: String, serverPublicKey: String) -> Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol AeadXChaCha20Poly1305IetfType {
|
public protocol AeadXChaCha20Poly1305IetfType {
|
||||||
|
|
|
@ -124,13 +124,13 @@ extension OpenGroupAPI {
|
||||||
)
|
)
|
||||||
|
|
||||||
case .inbox, .inboxSince:
|
case .inbox, .inboxSince:
|
||||||
guard let responseData: BatchSubResponse<[DirectMessage]> = endpointResponse.data as? BatchSubResponse<[DirectMessage]>, let responseBody: [DirectMessage] = responseData.body else {
|
guard let responseData: BatchSubResponse<[DirectMessage]?> = endpointResponse.data as? BatchSubResponse<[DirectMessage]?>, let responseBody: [DirectMessage]? = responseData.body else {
|
||||||
SNLog("Open group polling failed due to invalid data.")
|
SNLog("Open group polling failed due to invalid data.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGroupManager.handleInbox(
|
OpenGroupManager.handleInbox(
|
||||||
responseBody,
|
(responseBody ?? []),
|
||||||
on: server,
|
on: server,
|
||||||
isBackgroundPoll: isBackgroundPoll
|
isBackgroundPoll: isBackgroundPoll
|
||||||
)
|
)
|
||||||
|
|
|
@ -80,6 +80,9 @@ public protocol SessionMessagingKitStorageProtocol {
|
||||||
|
|
||||||
// MARK: - Message Handling
|
// MARK: - Message Handling
|
||||||
|
|
||||||
|
func getAllMessageRequestThreads() -> [String: TSContactThread]
|
||||||
|
func getAllMessageRequestThreads(using transaction: YapDatabaseReadTransaction) -> [String: TSContactThread]
|
||||||
|
|
||||||
func getReceivedMessageTimestamps(using transaction: Any) -> [UInt64]
|
func getReceivedMessageTimestamps(using transaction: Any) -> [UInt64]
|
||||||
func addReceivedMessageTimestamp(_ timestamp: UInt64, using transaction: Any)
|
func addReceivedMessageTimestamp(_ timestamp: UInt64, using transaction: Any)
|
||||||
/// Returns the ID of the thread.
|
/// Returns the ID of the thread.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Clibsodium
|
import Clibsodium
|
||||||
import Sodium
|
import Sodium
|
||||||
|
import Curve25519Kit
|
||||||
|
|
||||||
extension Sign {
|
extension Sign {
|
||||||
|
|
||||||
|
@ -232,6 +233,33 @@ extension Sodium {
|
||||||
|
|
||||||
return genericHash.hash(message: (combinedKeyBytes + kA + kB), outputLength: 32)
|
return genericHash.hash(message: (combinedKeyBytes + kA + kB), outputLength: 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method should be used to check if a users standard sessionId matches a blinded one
|
||||||
|
public func sessionId(_ standardSessionId: String, matchesBlindedId blindedSessionId: String, serverPublicKey: String) -> Bool {
|
||||||
|
// Only support generating blinded keys for standard session ids
|
||||||
|
guard let sessionId: SessionId = SessionId(from: standardSessionId), sessionId.prefix == .standard else { return false }
|
||||||
|
guard let blindedId: SessionId = SessionId(from: blindedSessionId), blindedId.prefix == .blinded else { return false }
|
||||||
|
guard let kBytes: Bytes = generateBlindingFactor(serverPublicKey: serverPublicKey) else { return false }
|
||||||
|
|
||||||
|
/// From the session id (ignoring 05 prefix) we have two possible ed25519 pubkeys; the first is the positive (which is what
|
||||||
|
/// Signal's XEd25519 conversion always uses)
|
||||||
|
///
|
||||||
|
/// Note: The below method is code we have exposed from the `curve25519_verify` method within the Curve25519 library
|
||||||
|
/// rather than custom code we have written
|
||||||
|
guard let xEd25519Key: Data = try? Ed25519.publicKey(from: Data(hex: sessionId.publicKey)) else { return false }
|
||||||
|
|
||||||
|
/// Blind the positive public key
|
||||||
|
guard let pk1: Bytes = combineKeys(lhsKeyBytes: kBytes, rhsKeyBytes: xEd25519Key.bytes) else { return false }
|
||||||
|
|
||||||
|
/// For the negative, what we're going to get out of the above is simply the negative of pk1, so flip the sign bit to get pk2
|
||||||
|
/// pk2 = pk1[0:31] + bytes([pk1[31] ^ 0b1000_0000])
|
||||||
|
let pk2: Bytes = (pk1[0..<31] + [(pk1[31] ^ 0b1000_0000)])
|
||||||
|
|
||||||
|
return (
|
||||||
|
SessionId(.blinded, publicKey: pk1).publicKey == blindedId.publicKey ||
|
||||||
|
SessionId(.blinded, publicKey: pk2).publicKey == blindedId.publicKey
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension GenericHash {
|
extension GenericHash {
|
||||||
|
|
|
@ -14,44 +14,28 @@ internal extension OnionRequestAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encrypts `payload` for `destination` and returns the result. Use this to build the core of an onion request.
|
/// Encrypts `payload` for `destination` and returns the result. Use this to build the core of an onion request.
|
||||||
static func encrypt(_ payload: String, for destination: Destination) -> Promise<AESGCM.EncryptionResult> {
|
static func encrypt(_ payload: String, for destination: Destination, with version: Version) -> Promise<AESGCM.EncryptionResult> {
|
||||||
let (promise, seal) = Promise<AESGCM.EncryptionResult>.pending()
|
let (promise, seal) = Promise<AESGCM.EncryptionResult>.pending()
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
DispatchQueue.global(qos: .userInitiated).async {
|
||||||
do {
|
do {
|
||||||
guard let data = payload.data(using: .utf8) else {
|
guard let payloadAsData: Data = payload.data(using: .utf8) else { throw Error.invalidRequestInfo }
|
||||||
throw Error.invalidRequestInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = try encrypt(data, for: destination)
|
let data: Data
|
||||||
seal.fulfill(result)
|
|
||||||
}
|
|
||||||
catch (let error) {
|
|
||||||
seal.reject(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise
|
switch version {
|
||||||
}
|
case .v2, .v3:
|
||||||
|
// Wrapping is only needed for snode requests
|
||||||
static func encrypt(_ payload: JSON, for destination: Destination) -> Promise<AESGCM.EncryptionResult> {
|
|
||||||
let (promise, seal) = Promise<AESGCM.EncryptionResult>.pending()
|
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
|
||||||
do {
|
|
||||||
guard JSONSerialization.isValidJSONObject(payload) else { return seal.reject(HTTP.Error.invalidJSON) }
|
|
||||||
|
|
||||||
// Wrapping isn't needed for file server or open group onion requests
|
|
||||||
switch destination {
|
switch destination {
|
||||||
case .snode:
|
case .snode: data = try encode(ciphertext: payloadAsData, json: [ "headers" : "" ])
|
||||||
let payloadAsData = try JSONSerialization.data(withJSONObject: payload, options: [ .fragmentsAllowed ])
|
case .server: data = payloadAsData
|
||||||
let data = try encode(ciphertext: payloadAsData, json: [ "headers" : "" ])
|
|
||||||
let result = try encrypt(data, for: destination)
|
|
||||||
seal.fulfill(result)
|
|
||||||
|
|
||||||
case .server:
|
|
||||||
let data = try JSONSerialization.data(withJSONObject: payload, options: [ .fragmentsAllowed ])
|
|
||||||
let result = try encrypt(data, for: destination)
|
|
||||||
seal.fulfill(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case .v4:
|
||||||
|
data = payloadAsData
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = try encrypt(data, for: destination)
|
||||||
|
seal.fulfill(result)
|
||||||
}
|
}
|
||||||
catch (let error) {
|
catch (let error) {
|
||||||
seal.reject(error)
|
seal.reject(error)
|
||||||
|
|
|
@ -245,7 +245,7 @@ public enum OnionRequestAPI: OnionRequestAPIType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds an onion around `payload` and returns the result.
|
/// Builds an onion around `payload` and returns the result.
|
||||||
private static func buildOnion(around payload: String, targetedAt destination: Destination) -> Promise<OnionBuildingResult> {
|
private static func buildOnion(around payload: String, targetedAt destination: Destination, version: Version) -> Promise<OnionBuildingResult> {
|
||||||
var guardSnode: Snode!
|
var guardSnode: Snode!
|
||||||
var targetSnodeSymmetricKey: Data! // Needed by invoke(_:on:with:) to decrypt the response sent back by the destination
|
var targetSnodeSymmetricKey: Data! // Needed by invoke(_:on:with:) to decrypt the response sent back by the destination
|
||||||
var encryptionResult: AESGCM.EncryptionResult!
|
var encryptionResult: AESGCM.EncryptionResult!
|
||||||
|
@ -254,7 +254,7 @@ public enum OnionRequestAPI: OnionRequestAPIType {
|
||||||
return getPath(excluding: snodeToExclude).then2 { path -> Promise<AESGCM.EncryptionResult> in
|
return getPath(excluding: snodeToExclude).then2 { path -> Promise<AESGCM.EncryptionResult> in
|
||||||
guardSnode = path.first!
|
guardSnode = path.first!
|
||||||
// Encrypt in reverse order, i.e. the destination first
|
// Encrypt in reverse order, i.e. the destination first
|
||||||
return encrypt(payload, for: destination).then2 { r -> Promise<AESGCM.EncryptionResult> in
|
return encrypt(payload, for: destination, with: version).then2 { r -> Promise<AESGCM.EncryptionResult> in
|
||||||
targetSnodeSymmetricKey = r.symmetricKey
|
targetSnodeSymmetricKey = r.symmetricKey
|
||||||
// Recursively encrypt the layers of the onion (again in reverse order)
|
// Recursively encrypt the layers of the onion (again in reverse order)
|
||||||
encryptionResult = r
|
encryptionResult = r
|
||||||
|
@ -328,7 +328,7 @@ public enum OnionRequestAPI: OnionRequestAPIType {
|
||||||
let (promise, seal) = Promise<(OnionRequestResponseInfoType, Data?)>.pending()
|
let (promise, seal) = Promise<(OnionRequestResponseInfoType, Data?)>.pending()
|
||||||
var guardSnode: Snode?
|
var guardSnode: Snode?
|
||||||
Threading.workQueue.async { // Avoid race conditions on `guardSnodes` and `paths`
|
Threading.workQueue.async { // Avoid race conditions on `guardSnodes` and `paths`
|
||||||
buildOnion(around: payload, targetedAt: destination).done2 { intermediate in
|
buildOnion(around: payload, targetedAt: destination, version: version).done2 { intermediate in
|
||||||
guardSnode = intermediate.guardSnode
|
guardSnode = intermediate.guardSnode
|
||||||
let url = "\(guardSnode!.address):\(guardSnode!.port)/onion_req/v2"
|
let url = "\(guardSnode!.address):\(guardSnode!.port)/onion_req/v2"
|
||||||
let finalEncryptionResult = intermediate.finalEncryptionResult
|
let finalEncryptionResult = intermediate.finalEncryptionResult
|
||||||
|
|
|
@ -131,8 +131,15 @@ public final class SnodeAPI : NSObject {
|
||||||
// MARK: Internal API
|
// MARK: Internal API
|
||||||
internal static func invoke(_ method: Snode.Method, on snode: Snode, associatedWith publicKey: String? = nil, parameters: JSON) -> RawResponsePromise {
|
internal static func invoke(_ method: Snode.Method, on snode: Snode, associatedWith publicKey: String? = nil, parameters: JSON) -> RawResponsePromise {
|
||||||
if Features.useOnionRequests {
|
if Features.useOnionRequests {
|
||||||
// TODO: Ensure this should use the v3 request?
|
return OnionRequestAPI.sendOnionRequest(to: snode, invoking: method, with: parameters, using: .v3, associatedWith: publicKey)
|
||||||
return OnionRequestAPI.sendOnionRequest(to: snode, invoking: method, with: parameters, using: .v3, associatedWith: publicKey).map2 { $0 as Any }
|
.map2 { responseData in
|
||||||
|
guard let responseJson: JSON = try? JSONSerialization.jsonObject(with: responseData, options: [ .fragmentsAllowed ]) as? JSON else {
|
||||||
|
throw Error.generic
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Would be nice to change this to not send 'Any'
|
||||||
|
return responseJson as Any
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let url = "\(snode.address):\(snode.port)/storage_rpc/v1"
|
let url = "\(snode.address):\(snode.port)/storage_rpc/v1"
|
||||||
return HTTP.execute(.post, url, parameters: parameters).map2 { $0 as Any }.recover2 { error -> Promise<Any> in
|
return HTTP.execute(.post, url, parameters: parameters).map2 { $0 as Any }.recover2 { error -> Promise<Any> in
|
||||||
|
|
Loading…
Reference in a new issue