replace SocketRocket with Starscream
This commit is contained in:
parent
4b3c43eed6
commit
16c8a1a76e
9
Podfile
9
Podfile
|
@ -38,12 +38,6 @@ def shared_pods
|
||||||
pod 'Mantle', git: 'https://github.com/signalapp/Mantle', branch: 'signal-master'
|
pod 'Mantle', git: 'https://github.com/signalapp/Mantle', branch: 'signal-master'
|
||||||
# pod 'Mantle', path: '../Mantle'
|
# pod 'Mantle', path: '../Mantle'
|
||||||
|
|
||||||
# SocketRocket has some critical crash fixes on Github, but have published an official release to cocoapods in ages, so
|
|
||||||
# we were following master
|
|
||||||
# Forked and have an open PR with our changes, but they have not been merged.
|
|
||||||
# pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git', inhibit_warnings: true
|
|
||||||
pod 'SocketRocket', :git => 'https://github.com/signalapp/SocketRocket.git', branch: 'mkirk/handle-sec-err', inhibit_warnings: true
|
|
||||||
|
|
||||||
# Forked for compatibily with the ShareExtension, changes have an open PR, but have not been merged.
|
# Forked for compatibily with the ShareExtension, changes have an open PR, but have not been merged.
|
||||||
pod 'YapDatabase/SQLCipher', :git => 'https://github.com/signalapp/YapDatabase.git', branch: 'signal-release'
|
pod 'YapDatabase/SQLCipher', :git => 'https://github.com/signalapp/YapDatabase.git', branch: 'signal-release'
|
||||||
# pod 'YapDatabase/SQLCipher', path: '../YapDatabase'
|
# pod 'YapDatabase/SQLCipher', path: '../YapDatabase'
|
||||||
|
@ -52,6 +46,9 @@ def shared_pods
|
||||||
pod 'GRKOpenSSLFramework', git: 'https://github.com/signalapp/GRKOpenSSLFramework'
|
pod 'GRKOpenSSLFramework', git: 'https://github.com/signalapp/GRKOpenSSLFramework'
|
||||||
#pod 'GRKOpenSSLFramework', path: '../GRKOpenSSLFramework'
|
#pod 'GRKOpenSSLFramework', path: '../GRKOpenSSLFramework'
|
||||||
|
|
||||||
|
pod 'Starscream', git: 'git@github.com:signalapp/Starscream.git', branch: 'signal-release'
|
||||||
|
# pod 'Starscream', path: '../Starscream'
|
||||||
|
|
||||||
###
|
###
|
||||||
# third party pods
|
# third party pods
|
||||||
####
|
####
|
||||||
|
|
26
Podfile.lock
26
Podfile.lock
|
@ -94,7 +94,7 @@ PODS:
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- SignalCoreKit
|
- SignalCoreKit
|
||||||
- SignalMetadataKit
|
- SignalMetadataKit
|
||||||
- SocketRocket
|
- Starscream
|
||||||
- SwiftProtobuf
|
- SwiftProtobuf
|
||||||
- YapDatabase/SQLCipher
|
- YapDatabase/SQLCipher
|
||||||
- SignalServiceKit/Tests (0.9.0):
|
- SignalServiceKit/Tests (0.9.0):
|
||||||
|
@ -110,16 +110,16 @@ PODS:
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- SignalCoreKit
|
- SignalCoreKit
|
||||||
- SignalMetadataKit
|
- SignalMetadataKit
|
||||||
- SocketRocket
|
- Starscream
|
||||||
- SwiftProtobuf
|
- SwiftProtobuf
|
||||||
- YapDatabase/SQLCipher
|
- YapDatabase/SQLCipher
|
||||||
- SocketRocket (0.5.1)
|
|
||||||
- SQLCipher (4.0.1):
|
- SQLCipher (4.0.1):
|
||||||
- SQLCipher/standard (= 4.0.1)
|
- SQLCipher/standard (= 4.0.1)
|
||||||
- SQLCipher/common (4.0.1)
|
- SQLCipher/common (4.0.1)
|
||||||
- SQLCipher/standard (4.0.1):
|
- SQLCipher/standard (4.0.1):
|
||||||
- SQLCipher/common
|
- SQLCipher/common
|
||||||
- SSZipArchive (2.1.4)
|
- SSZipArchive (2.1.4)
|
||||||
|
- Starscream (3.0.6)
|
||||||
- SwiftProtobuf (1.2.0)
|
- SwiftProtobuf (1.2.0)
|
||||||
- YapDatabase/SQLCipher (3.1.1):
|
- YapDatabase/SQLCipher (3.1.1):
|
||||||
- YapDatabase/SQLCipher/Core (= 3.1.1)
|
- YapDatabase/SQLCipher/Core (= 3.1.1)
|
||||||
|
@ -205,9 +205,9 @@ DEPENDENCIES:
|
||||||
- SignalMetadataKit/Tests (from `https://github.com/signalapp/SignalMetadataKit`)
|
- SignalMetadataKit/Tests (from `https://github.com/signalapp/SignalMetadataKit`)
|
||||||
- SignalServiceKit (from `.`)
|
- SignalServiceKit (from `.`)
|
||||||
- SignalServiceKit/Tests (from `.`)
|
- SignalServiceKit/Tests (from `.`)
|
||||||
- SocketRocket (from `https://github.com/signalapp/SocketRocket.git`, branch `mkirk/handle-sec-err`)
|
|
||||||
- SQLCipher (>= 4.0.1)
|
- SQLCipher (>= 4.0.1)
|
||||||
- SSZipArchive
|
- SSZipArchive
|
||||||
|
- "Starscream (from `git@github.com:signalapp/Starscream.git`, branch `signal-release`)"
|
||||||
- YapDatabase/SQLCipher (from `https://github.com/signalapp/YapDatabase.git`, branch `signal-release`)
|
- YapDatabase/SQLCipher (from `https://github.com/signalapp/YapDatabase.git`, branch `signal-release`)
|
||||||
- YYImage
|
- YYImage
|
||||||
|
|
||||||
|
@ -244,9 +244,9 @@ EXTERNAL SOURCES:
|
||||||
:git: https://github.com/signalapp/SignalMetadataKit
|
:git: https://github.com/signalapp/SignalMetadataKit
|
||||||
SignalServiceKit:
|
SignalServiceKit:
|
||||||
:path: "."
|
:path: "."
|
||||||
SocketRocket:
|
Starscream:
|
||||||
:branch: mkirk/handle-sec-err
|
:branch: signal-release
|
||||||
:git: https://github.com/signalapp/SocketRocket.git
|
:git: "git@github.com:signalapp/Starscream.git"
|
||||||
YapDatabase:
|
YapDatabase:
|
||||||
:branch: signal-release
|
:branch: signal-release
|
||||||
:git: https://github.com/signalapp/YapDatabase.git
|
:git: https://github.com/signalapp/YapDatabase.git
|
||||||
|
@ -273,9 +273,9 @@ CHECKOUT OPTIONS:
|
||||||
SignalMetadataKit:
|
SignalMetadataKit:
|
||||||
:commit: 56f28fc3a6e35d548d034ef7d0009f233ca0aa62
|
:commit: 56f28fc3a6e35d548d034ef7d0009f233ca0aa62
|
||||||
:git: https://github.com/signalapp/SignalMetadataKit
|
:git: https://github.com/signalapp/SignalMetadataKit
|
||||||
SocketRocket:
|
Starscream:
|
||||||
:commit: 9f9563a83cd8960503074aa8de72206f83fb7a69
|
:commit: edfb5964c5375ca55b3b0c517e1b5b7d0ac4519a
|
||||||
:git: https://github.com/signalapp/SocketRocket.git
|
:git: "git@github.com:signalapp/Starscream.git"
|
||||||
YapDatabase:
|
YapDatabase:
|
||||||
:commit: 8e2b69110efd9499a5b553fda0165d2cea4e818d
|
:commit: 8e2b69110efd9499a5b553fda0165d2cea4e818d
|
||||||
:git: https://github.com/signalapp/YapDatabase.git
|
:git: https://github.com/signalapp/YapDatabase.git
|
||||||
|
@ -295,14 +295,14 @@ SPEC CHECKSUMS:
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
SignalCoreKit: c2d8132cdedb95d35eb2f8ae7eac0957695d0a8b
|
SignalCoreKit: c2d8132cdedb95d35eb2f8ae7eac0957695d0a8b
|
||||||
SignalMetadataKit: 6fa5e9a53c7f104568662521a2f3874672ff7a02
|
SignalMetadataKit: 6fa5e9a53c7f104568662521a2f3874672ff7a02
|
||||||
SignalServiceKit: 80d774c32b22567682f63c36bf9da265d82083bb
|
SignalServiceKit: c637b66e485538dda76836a1ec560dc556035430
|
||||||
SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e
|
|
||||||
SQLCipher: 4636a257060f6f1b4e143a143028b61a2b462d0d
|
SQLCipher: 4636a257060f6f1b4e143a143028b61a2b462d0d
|
||||||
SSZipArchive: 41455d4b8d2b6ab93990820b50dc697c2554a322
|
SSZipArchive: 41455d4b8d2b6ab93990820b50dc697c2554a322
|
||||||
|
Starscream: ef3ece99d765eeccb67de105bfa143f929026cf5
|
||||||
SwiftProtobuf: 91a9856079044ef4ec762b2344c763cd9e5a73c1
|
SwiftProtobuf: 91a9856079044ef4ec762b2344c763cd9e5a73c1
|
||||||
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
|
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
|
||||||
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
|
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
|
||||||
|
|
||||||
PODFILE CHECKSUM: 7ccd091c65f353c7fcc3021a13b557a576d48509
|
PODFILE CHECKSUM: 7856bf087f931a4089ebd9a08ed1dfe8389b8afc
|
||||||
|
|
||||||
COCOAPODS: 1.5.3
|
COCOAPODS: 1.5.3
|
||||||
|
|
2
Pods
2
Pods
|
@ -1 +1 @@
|
||||||
Subproject commit 527dca96c23f0ac15664e9762987ff017cabdf90
|
Subproject commit c653092655ec0c592d7e733e1bd5eee342849ae0
|
|
@ -3145,7 +3145,7 @@
|
||||||
"${BUILT_PRODUCTS_DIR}/SignalCoreKit/SignalCoreKit.framework",
|
"${BUILT_PRODUCTS_DIR}/SignalCoreKit/SignalCoreKit.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SignalMetadataKit/SignalMetadataKit.framework",
|
"${BUILT_PRODUCTS_DIR}/SignalMetadataKit/SignalMetadataKit.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SignalServiceKit/SignalServiceKit.framework",
|
"${BUILT_PRODUCTS_DIR}/SignalServiceKit/SignalServiceKit.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework",
|
"${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
||||||
|
@ -3169,7 +3169,7 @@
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalCoreKit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalCoreKit.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalMetadataKit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalMetadataKit.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalServiceKit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalServiceKit.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketRocket.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
||||||
|
@ -3220,7 +3220,7 @@
|
||||||
"${BUILT_PRODUCTS_DIR}/SignalCoreKit/SignalCoreKit.framework",
|
"${BUILT_PRODUCTS_DIR}/SignalCoreKit/SignalCoreKit.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SignalMetadataKit/SignalMetadataKit.framework",
|
"${BUILT_PRODUCTS_DIR}/SignalMetadataKit/SignalMetadataKit.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SignalServiceKit/SignalServiceKit.framework",
|
"${BUILT_PRODUCTS_DIR}/SignalServiceKit/SignalServiceKit.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework",
|
"${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
"${BUILT_PRODUCTS_DIR}/YapDatabase/YapDatabase.framework",
|
||||||
|
@ -3243,7 +3243,7 @@
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalCoreKit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalCoreKit.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalMetadataKit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalMetadataKit.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalServiceKit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalServiceKit.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketRocket.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
|
||||||
|
|
|
@ -44,7 +44,7 @@ An Objective-C library for communicating with the Signal messaging service.
|
||||||
s.dependency 'AxolotlKit'
|
s.dependency 'AxolotlKit'
|
||||||
s.dependency 'Mantle'
|
s.dependency 'Mantle'
|
||||||
s.dependency 'YapDatabase/SQLCipher'
|
s.dependency 'YapDatabase/SQLCipher'
|
||||||
s.dependency 'SocketRocket'
|
s.dependency 'Starscream'
|
||||||
s.dependency 'libPhoneNumber-iOS'
|
s.dependency 'libPhoneNumber-iOS'
|
||||||
s.dependency 'GRKOpenSSLFramework'
|
s.dependency 'GRKOpenSSLFramework'
|
||||||
s.dependency 'SAMKeychain'
|
s.dependency 'SAMKeychain'
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Starscream
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public enum SSKWebSocketState: UInt {
|
||||||
|
case open, connecting, disconnected
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class SSKWebSocketError: NSObject, CustomNSError {
|
||||||
|
|
||||||
|
init(underlyingError: Starscream.WSError) {
|
||||||
|
self.underlyingError = underlyingError
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - CustomNSError
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public static let errorDomain = "SignalServiceKit.SSKWebSocketError"
|
||||||
|
|
||||||
|
public var errorUserInfo: [String: Any] {
|
||||||
|
return [
|
||||||
|
type(of: self).kStatusCodeKey: underlyingError.code,
|
||||||
|
NSUnderlyingErrorKey: (underlyingError as NSError)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
@objc
|
||||||
|
static let kStatusCodeKey = "SSKWebSocketErrorStatusCode"
|
||||||
|
|
||||||
|
let underlyingError: Starscream.WSError
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public protocol SSKWebSocket {
|
||||||
|
|
||||||
|
@objc
|
||||||
|
var delegate: SSKWebSocketDelegate? { get set }
|
||||||
|
|
||||||
|
@objc
|
||||||
|
var state: SSKWebSocketState { get }
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func connect()
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func disconnect()
|
||||||
|
|
||||||
|
@objc(writeData:error:)
|
||||||
|
func write(data: Data) throws
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func writePing() throws
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public protocol SSKWebSocketDelegate: class {
|
||||||
|
func websocketDidConnect(socket: SSKWebSocket)
|
||||||
|
|
||||||
|
func websocketDidDisconnect(socket: SSKWebSocket, error: Error?)
|
||||||
|
|
||||||
|
func websocketDidReceiveData(socket: SSKWebSocket, data: Data)
|
||||||
|
|
||||||
|
@objc optional func websocketDidReceiveMessage(socket: SSKWebSocket, text: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class SSKWebSocketManager: NSObject {
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public class func buildSocket(request: URLRequest) -> SSKWebSocket {
|
||||||
|
return SSKWebSocketImpl(request: request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SSKWebSocketImpl: SSKWebSocket {
|
||||||
|
|
||||||
|
private let socket: Starscream.WebSocket
|
||||||
|
|
||||||
|
init(request: URLRequest) {
|
||||||
|
let socket = WebSocket(request: request)
|
||||||
|
|
||||||
|
socket.disableSSLCertValidation = true
|
||||||
|
socket.socketSecurityLevel = StreamSocketSecurityLevel.tlSv1_2
|
||||||
|
let security = SSLSecurity(certs: [TextSecureCertificate()], usePublicKeys: false)
|
||||||
|
security.validateEntireChain = false
|
||||||
|
socket.security = security
|
||||||
|
|
||||||
|
// TODO cipher suite selection
|
||||||
|
// socket.enabledSSLCipherSuites = [TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
|
||||||
|
|
||||||
|
self.socket = socket
|
||||||
|
|
||||||
|
socket.delegate = self
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SSKWebSocket
|
||||||
|
|
||||||
|
weak var delegate: SSKWebSocketDelegate?
|
||||||
|
|
||||||
|
var hasEverConnected = false
|
||||||
|
var state: SSKWebSocketState {
|
||||||
|
if socket.isConnected {
|
||||||
|
return .open
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasEverConnected {
|
||||||
|
return .disconnected
|
||||||
|
}
|
||||||
|
|
||||||
|
return .connecting
|
||||||
|
}
|
||||||
|
|
||||||
|
func connect() {
|
||||||
|
socket.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
func disconnect() {
|
||||||
|
socket.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(data: Data) throws {
|
||||||
|
socket.write(data: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePing() throws {
|
||||||
|
socket.write(ping: Data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SSKWebSocketImpl: WebSocketDelegate {
|
||||||
|
func websocketDidConnect(socket: WebSocketClient) {
|
||||||
|
hasEverConnected = true
|
||||||
|
delegate?.websocketDidConnect(socket: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
|
||||||
|
let websocketError: Error?
|
||||||
|
switch error {
|
||||||
|
case let wsError as WSError:
|
||||||
|
websocketError = SSKWebSocketError(underlyingError: wsError)
|
||||||
|
default:
|
||||||
|
assert(error == nil, "unexpected error type: \(String(describing: error))")
|
||||||
|
websocketError = error
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate?.websocketDidDisconnect(socket: self, error: websocketError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
|
||||||
|
if let websocketDidReceiveMessage = self.delegate?.websocketDidReceiveMessage {
|
||||||
|
websocketDidReceiveMessage(self, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
|
||||||
|
delegate?.websocketDidReceiveData(socket: self, data: data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func TextSecureCertificate() -> SSLCert {
|
||||||
|
let data = OWSHTTPSecurityPolicy.dataFromCertificateFile(forService: "textsecure")
|
||||||
|
return SSLCert(data: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension StreamSocketSecurityLevel {
|
||||||
|
static var tlSv1_2: StreamSocketSecurityLevel {
|
||||||
|
return StreamSocketSecurityLevel(rawValue: "kCFStreamSocketSecurityLevelTLSv1_2")
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,6 @@
|
||||||
#import "OWSMessageReceiver.h"
|
#import "OWSMessageReceiver.h"
|
||||||
#import "OWSPrimaryStorage.h"
|
#import "OWSPrimaryStorage.h"
|
||||||
#import "OWSSignalService.h"
|
#import "OWSSignalService.h"
|
||||||
#import "OWSWebsocketSecurityPolicy.h"
|
|
||||||
#import "SSKEnvironment.h"
|
#import "SSKEnvironment.h"
|
||||||
#import "TSAccountManager.h"
|
#import "TSAccountManager.h"
|
||||||
#import "TSConstants.h"
|
#import "TSConstants.h"
|
||||||
|
@ -24,7 +23,6 @@
|
||||||
#import <SignalCoreKit/Cryptography.h>
|
#import <SignalCoreKit/Cryptography.h>
|
||||||
#import <SignalCoreKit/Threading.h>
|
#import <SignalCoreKit/Threading.h>
|
||||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||||
#import <SocketRocket/SRWebSocket.h>
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@ -144,13 +142,13 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
// OWSWebSocket's properties should only be accessed from the main thread.
|
// OWSWebSocket's properties should only be accessed from the main thread.
|
||||||
@interface OWSWebSocket () <SRWebSocketDelegate>
|
@interface OWSWebSocket () <SSKWebSocketDelegate>
|
||||||
|
|
||||||
// This class has a few "tiers" of state.
|
// This class has a few "tiers" of state.
|
||||||
//
|
//
|
||||||
// The first tier is the actual websocket and the timers used
|
// The first tier is the actual websocket and the timers used
|
||||||
// to keep it alive and connected.
|
// to keep it alive and connected.
|
||||||
@property (nonatomic, nullable) SRWebSocket *websocket;
|
@property (nonatomic, nullable) id<SSKWebSocket> websocket;
|
||||||
@property (nonatomic, nullable) NSTimer *heartbeatTimer;
|
@property (nonatomic, nullable) NSTimer *heartbeatTimer;
|
||||||
@property (nonatomic, nullable) NSTimer *reconnectTimer;
|
@property (nonatomic, nullable) NSTimer *reconnectTimer;
|
||||||
|
|
||||||
|
@ -257,11 +255,6 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
return SSKEnvironment.shared.notificationsManager;
|
return SSKEnvironment.shared.notificationsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (OWSWebsocketSecurityPolicy *)websocketSecurityPolicy
|
|
||||||
{
|
|
||||||
return OWSWebsocketSecurityPolicy.sharedPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id<OWSUDManager>)udManager {
|
- (id<OWSUDManager>)udManager {
|
||||||
return SSKEnvironment.shared.udManager;
|
return SSKEnvironment.shared.udManager;
|
||||||
}
|
}
|
||||||
|
@ -310,11 +303,11 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
|
|
||||||
// Try to reuse the existing socket (if any) if it is in a valid state.
|
// Try to reuse the existing socket (if any) if it is in a valid state.
|
||||||
if (self.websocket) {
|
if (self.websocket) {
|
||||||
switch ([self.websocket readyState]) {
|
switch (self.websocket.state) {
|
||||||
case SR_OPEN:
|
case SSKWebSocketStateOpen:
|
||||||
self.state = OWSWebSocketStateOpen;
|
self.state = OWSWebSocketStateOpen;
|
||||||
return;
|
return;
|
||||||
case SR_CONNECTING:
|
case SSKWebSocketStateConnecting:
|
||||||
OWSLogVerbose(@"WebSocket is already connecting");
|
OWSLogVerbose(@"WebSocket is already connecting");
|
||||||
self.state = OWSWebSocketStateConnecting;
|
self.state = OWSWebSocketStateConnecting;
|
||||||
return;
|
return;
|
||||||
|
@ -355,8 +348,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
// and class state to reflect changes in app state.
|
// and class state to reflect changes in app state.
|
||||||
//
|
//
|
||||||
// We learn about changes to socket state through websocket
|
// We learn about changes to socket state through websocket
|
||||||
// delegate methods like [webSocketDidOpen:], [didFailWithError:...]
|
// delegate methods. These delegate methods are sometimes
|
||||||
// and [didCloseWithCode:...]. These delegate methods are sometimes
|
|
||||||
// invoked _after_ web socket state changes, so we sometimes learn
|
// invoked _after_ web socket state changes, so we sometimes learn
|
||||||
// about changes to socket state in [ensureWebsocket]. Put another way,
|
// about changes to socket state in [ensureWebsocket]. Put another way,
|
||||||
// it's not safe to assume we'll learn of changes to websocket state
|
// it's not safe to assume we'll learn of changes to websocket state
|
||||||
|
@ -425,18 +417,17 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
NSURL *webSocketConnectURL = [NSURL URLWithString:webSocketConnect];
|
NSURL *webSocketConnectURL = [NSURL URLWithString:webSocketConnect];
|
||||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:webSocketConnectURL];
|
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:webSocketConnectURL];
|
||||||
|
|
||||||
SRWebSocket *socket =
|
id<SSKWebSocket> socket = [SSKWebSocketManager buildSocketWithRequest:request];
|
||||||
[[SRWebSocket alloc] initWithURLRequest:request securityPolicy:self.websocketSecurityPolicy];
|
|
||||||
socket.delegate = self;
|
socket.delegate = self;
|
||||||
|
|
||||||
[self setWebsocket:socket];
|
[self setWebsocket:socket];
|
||||||
|
|
||||||
// [SRWebSocket open] could hypothetically call a delegate method (e.g. if
|
// `connect` could hypothetically call a delegate method (e.g. if
|
||||||
// the socket failed immediately for some reason), so we update the state
|
// the socket failed immediately for some reason), so we update the state
|
||||||
// _before_ calling it, not after.
|
// _before_ calling it, not after.
|
||||||
_state = state;
|
_state = state;
|
||||||
self.canMakeRequests = state == OWSWebSocketStateOpen;
|
self.canMakeRequests = state == OWSWebSocketStateOpen;
|
||||||
[socket open];
|
[socket connect];
|
||||||
[self failAllPendingSocketMessagesIfNecessary];
|
[self failAllPendingSocketMessagesIfNecessary];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -463,7 +454,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
|
|
||||||
self.websocket.delegate = nil;
|
self.websocket.delegate = nil;
|
||||||
[self.websocket close];
|
[self.websocket disconnect];
|
||||||
self.websocket = nil;
|
self.websocket = nil;
|
||||||
[self.heartbeatTimer invalidate];
|
[self.heartbeatTimer invalidate];
|
||||||
self.heartbeatTimer = nil;
|
self.heartbeatTimer = nil;
|
||||||
|
@ -554,7 +545,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL wasScheduled = [self.websocket sendDataNoCopy:messageData error:&error];
|
BOOL wasScheduled = [self.websocket writeData:messageData error:&error];
|
||||||
if (!wasScheduled || error) {
|
if (!wasScheduled || error) {
|
||||||
OWSFailDebug(@"could not send socket request: %@", error);
|
OWSFailDebug(@"could not send socket request: %@", error);
|
||||||
[socketMessage didFailBeforeSending];
|
[socketMessage didFailBeforeSending];
|
||||||
|
@ -676,13 +667,13 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Delegate methods
|
#pragma mark - SSKWebSocketDelegate
|
||||||
|
|
||||||
- (void)webSocketDidOpen:(SRWebSocket *)webSocket
|
- (void)websocketDidConnectWithSocket:(id<SSKWebSocket>)websocket
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(webSocket);
|
OWSAssertDebug(websocket);
|
||||||
if (webSocket != self.websocket) {
|
if (websocket != self.websocket) {
|
||||||
// Ignore events from obsolete web sockets.
|
// Ignore events from obsolete web sockets.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -695,19 +686,18 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
[self.outageDetection reportConnectionSuccess];
|
[self.outageDetection reportConnectionSuccess];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
|
- (void)websocketDidDisconnectWithSocket:(id<SSKWebSocket>)websocket error:(nullable NSError *)error
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(webSocket);
|
OWSAssertDebug(websocket);
|
||||||
if (webSocket != self.websocket) {
|
if (websocket != self.websocket) {
|
||||||
// Ignore events from obsolete web sockets.
|
// Ignore events from obsolete web sockets.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OWSLogError(@"Websocket did fail with error: %@", error);
|
OWSLogError(@"Websocket did fail with error: %@", error);
|
||||||
|
if ([error.domain isEqualToString:SSKWebSocketError.errorDomain]) {
|
||||||
if ([error.domain isEqualToString:SRWebSocketErrorDomain] && error.code == 2132) {
|
NSNumber *_Nullable statusCode = error.userInfo[SSKWebSocketError.kStatusCodeKey];
|
||||||
NSNumber *_Nullable statusCode = error.userInfo[SRHTTPResponseErrorKey];
|
|
||||||
if (statusCode.unsignedIntegerValue == 403) {
|
if (statusCode.unsignedIntegerValue == 403) {
|
||||||
if (self.tsAccountManager.isRegisteredAndReady) {
|
if (self.tsAccountManager.isRegisteredAndReady) {
|
||||||
[self.tsAccountManager setIsDeregistered:YES];
|
[self.tsAccountManager setIsDeregistered:YES];
|
||||||
|
@ -720,12 +710,12 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
[self handleSocketFailure];
|
[self handleSocketFailure];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(NSData *)data
|
- (void)websocketDidReceiveDataWithSocket:(id<SSKWebSocket>)websocket data:(NSData *)data
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(webSocket);
|
OWSAssertDebug(websocket);
|
||||||
|
|
||||||
if (webSocket != self.websocket) {
|
if (websocket != self.websocket) {
|
||||||
// Ignore events from obsolete web sockets.
|
// Ignore events from obsolete web sockets.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -749,6 +739,8 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
- (dispatch_queue_t)serialQueue
|
- (dispatch_queue_t)serialQueue
|
||||||
{
|
{
|
||||||
static dispatch_queue_t _serialQueue;
|
static dispatch_queue_t _serialQueue;
|
||||||
|
@ -853,7 +845,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.websocket sendDataNoCopy:messageData error:&error];
|
[self.websocket writeData:messageData error:&error];
|
||||||
if (error) {
|
if (error) {
|
||||||
OWSLogWarn(@"Error while trying to write on websocket %@", error);
|
OWSLogWarn(@"Error while trying to write on websocket %@", error);
|
||||||
[self handleSocketFailure];
|
[self handleSocketFailure];
|
||||||
|
@ -887,30 +879,13 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
|
||||||
[self.outageDetection reportConnectionFailure];
|
[self.outageDetection reportConnectionFailure];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)webSocket:(SRWebSocket *)webSocket
|
|
||||||
didCloseWithCode:(NSInteger)code
|
|
||||||
reason:(nullable NSString *)reason
|
|
||||||
wasClean:(BOOL)wasClean
|
|
||||||
{
|
|
||||||
OWSAssertIsOnMainThread();
|
|
||||||
OWSAssertDebug(webSocket);
|
|
||||||
if (webSocket != self.websocket) {
|
|
||||||
// Ignore events from obsolete web sockets.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OWSLogWarn(@"Websocket did close with code: %ld", (long)code);
|
|
||||||
|
|
||||||
[self handleSocketFailure];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)webSocketHeartBeat
|
- (void)webSocketHeartBeat
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
|
|
||||||
if ([self shouldSocketBeOpen]) {
|
if ([self shouldSocketBeOpen]) {
|
||||||
NSError *error;
|
NSError *error;
|
||||||
[self.websocket sendPing:nil error:&error];
|
[self.websocket writePingAndReturnError:&error];
|
||||||
if (error) {
|
if (error) {
|
||||||
OWSLogWarn(@"Error in websocket heartbeat: %@", error.localizedDescription);
|
OWSLogWarn(@"Error in websocket heartbeat: %@", error.localizedDescription);
|
||||||
[self handleSocketFailure];
|
[self handleSocketFailure];
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
//
|
//
|
||||||
// Created by Fred on 01/09/15.
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||||
// Copyright © 2015 Open Whisper Systems. All rights reserved.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <AFNetworking/AFSecurityPolicy.h>
|
#import <AFNetworking/AFSecurityPolicy.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
extern NSData *SSKTextSecureServiceCertificateData(void);
|
||||||
|
|
||||||
@interface OWSHTTPSecurityPolicy : AFSecurityPolicy
|
@interface OWSHTTPSecurityPolicy : AFSecurityPolicy
|
||||||
|
|
||||||
+ (instancetype)sharedPolicy;
|
+ (instancetype)sharedPolicy;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "OWSHTTPSecurityPolicy.h"
|
#import "OWSHTTPSecurityPolicy.h"
|
||||||
#import <AssertMacros.h>
|
#import <AssertMacros.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@implementation OWSHTTPSecurityPolicy
|
@implementation OWSHTTPSecurityPolicy
|
||||||
|
|
||||||
+ (instancetype)sharedPolicy {
|
+ (instancetype)sharedPolicy {
|
||||||
|
@ -21,24 +23,15 @@
|
||||||
|
|
||||||
if (self) {
|
if (self) {
|
||||||
self.pinnedCertificates = [NSSet setWithArray:@[
|
self.pinnedCertificates = [NSSet setWithArray:@[
|
||||||
[self certificateDataForService:@"textsecure"],
|
[self.class certificateDataForService:@"textsecure"]
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)certs {
|
+ (NSData *)dataFromCertificateFileForService:(NSString *)service
|
||||||
return @[ (__bridge id)[self certificateForService:@"textsecure"] ];
|
{
|
||||||
}
|
|
||||||
|
|
||||||
- (NSData *)certificateDataForService:(NSString *)service {
|
|
||||||
SecCertificateRef certRef = [self certificateForService:service];
|
|
||||||
return (__bridge_transfer NSData *)SecCertificateCopyData(certRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (SecCertificateRef)certificateForService:(NSString *)service {
|
|
||||||
|
|
||||||
NSBundle *bundle = [NSBundle bundleForClass:self.class];
|
NSBundle *bundle = [NSBundle bundleForClass:self.class];
|
||||||
NSString *path = [bundle pathForResource:service ofType:@"cer"];
|
NSString *path = [bundle pathForResource:service ofType:@"cer"];
|
||||||
|
|
||||||
|
@ -46,12 +39,25 @@
|
||||||
OWSFail(@"Missing signing certificate for service %@", service);
|
OWSFail(@"Missing signing certificate for service %@", service);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSData *certificateData = [NSData dataWithContentsOfFile:path];
|
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||||
|
OWSAssert(data.length > 0);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData *)certificateDataForService:(NSString *)service {
|
||||||
|
SecCertificateRef certRef = [self certificateForService:service];
|
||||||
|
return (__bridge_transfer NSData *)SecCertificateCopyData(certRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (SecCertificateRef)certificateForService:(NSString *)service
|
||||||
|
{
|
||||||
|
NSData *certificateData = [self dataFromCertificateFileForService:service];
|
||||||
return SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData));
|
return SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(nullable NSString *)domain
|
||||||
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
|
{
|
||||||
NSMutableArray *policies = [NSMutableArray array];
|
NSMutableArray *policies = [NSMutableArray array];
|
||||||
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
|
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
|
||||||
|
|
||||||
|
@ -90,3 +96,5 @@ _out:
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
|
||||||
|
|
||||||
#import <SocketRocket/SRSecurityPolicy.h>
|
|
||||||
|
|
||||||
@interface OWSWebsocketSecurityPolicy : SRSecurityPolicy
|
|
||||||
|
|
||||||
+ (instancetype)sharedPolicy;
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,29 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "OWSWebsocketSecurityPolicy.h"
|
|
||||||
#import "OWSHTTPSecurityPolicy.h"
|
|
||||||
#import <SocketRocket/SRSecurityPolicy.h>
|
|
||||||
|
|
||||||
@implementation OWSWebsocketSecurityPolicy
|
|
||||||
|
|
||||||
+ (instancetype)sharedPolicy {
|
|
||||||
static OWSWebsocketSecurityPolicy *websocketSecurityPolicy = nil;
|
|
||||||
static dispatch_once_t onceToken;
|
|
||||||
dispatch_once(&onceToken, ^{
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
// We use our own CA
|
|
||||||
websocketSecurityPolicy = [[self alloc] initWithCertificateChainValidationEnabled:NO];
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
});
|
|
||||||
return websocketSecurityPolicy;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
|
|
||||||
// Delegate server trust to our existing HTTP policy.
|
|
||||||
return [[OWSHTTPSecurityPolicy sharedPolicy] evaluateServerTrust:serverTrust forDomain:domain];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
Loading…
Reference in New Issue