Browse Source

replace SocketRocket with Starscream

Michael Kirk 10 months ago
parent
commit
16c8a1a76e

+ 3 - 6
Podfile

@@ -38,12 +38,6 @@ def shared_pods
   pod 'Mantle', git: 'https://github.com/signalapp/Mantle', branch: 'signal-master'
   # 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.
   pod 'YapDatabase/SQLCipher', :git => 'https://github.com/signalapp/YapDatabase.git', branch: 'signal-release'
   # pod 'YapDatabase/SQLCipher', path: '../YapDatabase'
@@ -52,6 +46,9 @@ def shared_pods
   pod 'GRKOpenSSLFramework', git: 'https://github.com/signalapp/GRKOpenSSLFramework'
   #pod 'GRKOpenSSLFramework', path: '../GRKOpenSSLFramework'
 
+  pod 'Starscream', git: 'git@github.com:signalapp/Starscream.git', branch: 'signal-release'
+  # pod 'Starscream', path: '../Starscream'
+
   ###
   # third party pods
   ####

+ 13 - 13
Podfile.lock

@@ -94,7 +94,7 @@ PODS:
     - SAMKeychain
     - SignalCoreKit
     - SignalMetadataKit
-    - SocketRocket
+    - Starscream
     - SwiftProtobuf
     - YapDatabase/SQLCipher
   - SignalServiceKit/Tests (0.9.0):
@@ -110,16 +110,16 @@ PODS:
     - SAMKeychain
     - SignalCoreKit
     - SignalMetadataKit
-    - SocketRocket
+    - Starscream
     - SwiftProtobuf
     - YapDatabase/SQLCipher
-  - SocketRocket (0.5.1)
   - SQLCipher (4.0.1):
     - SQLCipher/standard (= 4.0.1)
   - SQLCipher/common (4.0.1)
   - SQLCipher/standard (4.0.1):
     - SQLCipher/common
   - SSZipArchive (2.1.4)
+  - Starscream (3.0.6)
   - SwiftProtobuf (1.2.0)
   - YapDatabase/SQLCipher (3.1.1):
     - YapDatabase/SQLCipher/Core (= 3.1.1)
@@ -205,9 +205,9 @@ DEPENDENCIES:
   - SignalMetadataKit/Tests (from `https://github.com/signalapp/SignalMetadataKit`)
   - SignalServiceKit (from `.`)
   - SignalServiceKit/Tests (from `.`)
-  - SocketRocket (from `https://github.com/signalapp/SocketRocket.git`, branch `mkirk/handle-sec-err`)
   - SQLCipher (>= 4.0.1)
   - SSZipArchive
+  - "Starscream (from `git@github.com:signalapp/Starscream.git`, branch `signal-release`)"
   - YapDatabase/SQLCipher (from `https://github.com/signalapp/YapDatabase.git`, branch `signal-release`)
   - YYImage
 
@@ -244,9 +244,9 @@ EXTERNAL SOURCES:
     :git: https://github.com/signalapp/SignalMetadataKit
   SignalServiceKit:
     :path: "."
-  SocketRocket:
-    :branch: mkirk/handle-sec-err
-    :git: https://github.com/signalapp/SocketRocket.git
+  Starscream:
+    :branch: signal-release
+    :git: "git@github.com:signalapp/Starscream.git"
   YapDatabase:
     :branch: signal-release
     :git: https://github.com/signalapp/YapDatabase.git
@@ -273,9 +273,9 @@ CHECKOUT OPTIONS:
   SignalMetadataKit:
     :commit: 56f28fc3a6e35d548d034ef7d0009f233ca0aa62
     :git: https://github.com/signalapp/SignalMetadataKit
-  SocketRocket:
-    :commit: 9f9563a83cd8960503074aa8de72206f83fb7a69
-    :git: https://github.com/signalapp/SocketRocket.git
+  Starscream:
+    :commit: edfb5964c5375ca55b3b0c517e1b5b7d0ac4519a
+    :git: "git@github.com:signalapp/Starscream.git"
   YapDatabase:
     :commit: 8e2b69110efd9499a5b553fda0165d2cea4e818d
     :git: https://github.com/signalapp/YapDatabase.git
@@ -295,14 +295,14 @@ SPEC CHECKSUMS:
   SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
   SignalCoreKit: c2d8132cdedb95d35eb2f8ae7eac0957695d0a8b
   SignalMetadataKit: 6fa5e9a53c7f104568662521a2f3874672ff7a02
-  SignalServiceKit: 80d774c32b22567682f63c36bf9da265d82083bb
-  SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e
+  SignalServiceKit: c637b66e485538dda76836a1ec560dc556035430
   SQLCipher: 4636a257060f6f1b4e143a143028b61a2b462d0d
   SSZipArchive: 41455d4b8d2b6ab93990820b50dc697c2554a322
+  Starscream: ef3ece99d765eeccb67de105bfa143f929026cf5
   SwiftProtobuf: 91a9856079044ef4ec762b2344c763cd9e5a73c1
   YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
   YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
 
-PODFILE CHECKSUM: 7ccd091c65f353c7fcc3021a13b557a576d48509
+PODFILE CHECKSUM: 7856bf087f931a4089ebd9a08ed1dfe8389b8afc
 
 COCOAPODS: 1.5.3

+ 1 - 1
Pods

@@ -1 +1 @@
-Subproject commit 527dca96c23f0ac15664e9762987ff017cabdf90
+Subproject commit c653092655ec0c592d7e733e1bd5eee342849ae0

+ 4 - 4
Signal.xcodeproj/project.pbxproj

@@ -3145,7 +3145,7 @@
 				"${BUILT_PRODUCTS_DIR}/SignalCoreKit/SignalCoreKit.framework",
 				"${BUILT_PRODUCTS_DIR}/SignalMetadataKit/SignalMetadataKit.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}/YYImage/YYImage.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}/SignalMetadataKit.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}/YYImage.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",
@@ -3220,7 +3220,7 @@
 				"${BUILT_PRODUCTS_DIR}/SignalCoreKit/SignalCoreKit.framework",
 				"${BUILT_PRODUCTS_DIR}/SignalMetadataKit/SignalMetadataKit.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}/YYImage/YYImage.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}/SignalMetadataKit.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}/YYImage.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YapDatabase.framework",

+ 1 - 1
SignalServiceKit.podspec

@@ -44,7 +44,7 @@ An Objective-C library for communicating with the Signal messaging service.
   s.dependency 'AxolotlKit'
   s.dependency 'Mantle'
   s.dependency 'YapDatabase/SQLCipher'
-  s.dependency 'SocketRocket'
+  s.dependency 'Starscream'
   s.dependency 'libPhoneNumber-iOS'
   s.dependency 'GRKOpenSSLFramework'
   s.dependency 'SAMKeychain'

+ 176 - 0
SignalServiceKit/src/Network/SSKWebSocket.swift

@@ -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")
+    }
+}

+ 27 - 52
SignalServiceKit/src/Network/WebSockets/OWSWebSocket.m

@@ -15,7 +15,6 @@
 #import "OWSMessageReceiver.h"
 #import "OWSPrimaryStorage.h"
 #import "OWSSignalService.h"
-#import "OWSWebsocketSecurityPolicy.h"
 #import "SSKEnvironment.h"
 #import "TSAccountManager.h"
 #import "TSConstants.h"
@@ -24,7 +23,6 @@
 #import <SignalCoreKit/Cryptography.h>
 #import <SignalCoreKit/Threading.h>
 #import <SignalServiceKit/SignalServiceKit-Swift.h>
-#import <SocketRocket/SRWebSocket.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -144,13 +142,13 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
 #pragma mark -
 
 // 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.
 //
 // The first tier is the actual websocket and the timers used
 // 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 *reconnectTimer;
 
@@ -257,11 +255,6 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
     return SSKEnvironment.shared.notificationsManager;
 }
 
-- (OWSWebsocketSecurityPolicy *)websocketSecurityPolicy
-{
-    return OWSWebsocketSecurityPolicy.sharedPolicy;
-}
-
 - (id<OWSUDManager>)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.
     if (self.websocket) {
-        switch ([self.websocket readyState]) {
-            case SR_OPEN:
+        switch (self.websocket.state) {
+            case SSKWebSocketStateOpen:
                 self.state = OWSWebSocketStateOpen;
                 return;
-            case SR_CONNECTING:
+            case SSKWebSocketStateConnecting:
                 OWSLogVerbose(@"WebSocket is already connecting");
                 self.state = OWSWebSocketStateConnecting;
                 return;
@@ -355,8 +348,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
 // and class state to reflect changes in app state.
 //
 // We learn about changes to socket state through websocket
-// delegate methods like [webSocketDidOpen:], [didFailWithError:...]
-// and [didCloseWithCode:...].  These delegate methods are sometimes
+// delegate methods. These delegate methods are sometimes
 // invoked _after_ web socket state changes, so we sometimes learn
 // about changes to socket state in [ensureWebsocket].  Put another way,
 // 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];
             NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:webSocketConnectURL];
 
-            SRWebSocket *socket =
-                [[SRWebSocket alloc] initWithURLRequest:request securityPolicy:self.websocketSecurityPolicy];
+            id<SSKWebSocket> socket = [SSKWebSocketManager buildSocketWithRequest:request];
             socket.delegate = self;
 
             [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
             // _before_ calling it, not after.
             _state = state;
             self.canMakeRequests = state == OWSWebSocketStateOpen;
-            [socket open];
+            [socket connect];
             [self failAllPendingSocketMessagesIfNecessary];
             return;
         }
@@ -463,7 +454,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
     OWSAssertIsOnMainThread();
 
     self.websocket.delegate = nil;
-    [self.websocket close];
+    [self.websocket disconnect];
     self.websocket = nil;
     [self.heartbeatTimer invalidate];
     self.heartbeatTimer = nil;
@@ -554,7 +545,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
         return;
     }
 
-    BOOL wasScheduled = [self.websocket sendDataNoCopy:messageData error:&error];
+    BOOL wasScheduled = [self.websocket writeData:messageData error:&error];
     if (!wasScheduled || error) {
         OWSFailDebug(@"could not send socket request: %@", error);
         [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();
-    OWSAssertDebug(webSocket);
-    if (webSocket != self.websocket) {
+    OWSAssertDebug(websocket);
+    if (websocket != self.websocket) {
         // Ignore events from obsolete web sockets.
         return;
     }
@@ -695,19 +686,18 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
     [self.outageDetection reportConnectionSuccess];
 }
 
-- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
+- (void)websocketDidDisconnectWithSocket:(id<SSKWebSocket>)websocket error:(nullable NSError *)error
 {
     OWSAssertIsOnMainThread();
-    OWSAssertDebug(webSocket);
-    if (webSocket != self.websocket) {
+    OWSAssertDebug(websocket);
+    if (websocket != self.websocket) {
         // Ignore events from obsolete web sockets.
         return;
     }
 
     OWSLogError(@"Websocket did fail with error: %@", error);
-
-    if ([error.domain isEqualToString:SRWebSocketErrorDomain] && error.code == 2132) {
-        NSNumber *_Nullable statusCode = error.userInfo[SRHTTPResponseErrorKey];
+    if ([error.domain isEqualToString:SSKWebSocketError.errorDomain]) {
+        NSNumber *_Nullable statusCode = error.userInfo[SSKWebSocketError.kStatusCodeKey];
         if (statusCode.unsignedIntegerValue == 403) {
             if (self.tsAccountManager.isRegisteredAndReady) {
                 [self.tsAccountManager setIsDeregistered:YES];
@@ -720,12 +710,12 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
     [self handleSocketFailure];
 }
 
-- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(NSData *)data
+- (void)websocketDidReceiveDataWithSocket:(id<SSKWebSocket>)websocket data:(NSData *)data
 {
     OWSAssertIsOnMainThread();
-    OWSAssertDebug(webSocket);
+    OWSAssertDebug(websocket);
 
-    if (webSocket != self.websocket) {
+    if (websocket != self.websocket) {
         // Ignore events from obsolete web sockets.
         return;
     }
@@ -749,6 +739,8 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
     }
 }
 
+#pragma mark -
+
 - (dispatch_queue_t)serialQueue
 {
     static dispatch_queue_t _serialQueue;
@@ -853,7 +845,7 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
         return;
     }
 
-    [self.websocket sendDataNoCopy:messageData error:&error];
+    [self.websocket writeData:messageData error:&error];
     if (error) {
         OWSLogWarn(@"Error while trying to write on websocket %@", error);
         [self handleSocketFailure];
@@ -887,30 +879,13 @@ NSString *const kNSNotification_OWSWebSocketStateDidChange = @"kNSNotification_O
     [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
 {
     OWSAssertIsOnMainThread();
 
     if ([self shouldSocketBeOpen]) {
         NSError *error;
-        [self.websocket sendPing:nil error:&error];
+        [self.websocket writePingAndReturnError:&error];
         if (error) {
             OWSLogWarn(@"Error in websocket heartbeat: %@", error.localizedDescription);
             [self handleSocketFailure];

+ 7 - 2
SignalServiceKit/src/Security/OWSHTTPSecurityPolicy.h

@@ -1,12 +1,17 @@
 //
-//  Created by Fred on 01/09/15.
-//  Copyright © 2015 Open Whisper Systems. All rights reserved.
+//  Copyright (c) 2019 Open Whisper Systems. All rights reserved.
 //
 
 #import <AFNetworking/AFSecurityPolicy.h>
 
+NS_ASSUME_NONNULL_BEGIN
+
+extern NSData *SSKTextSecureServiceCertificateData(void);
+
 @interface OWSHTTPSecurityPolicy : AFSecurityPolicy
 
 + (instancetype)sharedPolicy;
 
 @end
+
+NS_ASSUME_NONNULL_END

+ 24 - 16
SignalServiceKit/src/Security/OWSHTTPSecurityPolicy.m

@@ -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 <AssertMacros.h>
 
+NS_ASSUME_NONNULL_BEGIN
+
 @implementation OWSHTTPSecurityPolicy
 
 + (instancetype)sharedPolicy {
@@ -21,24 +23,15 @@
 
     if (self) {
         self.pinnedCertificates = [NSSet setWithArray:@[
-            [self certificateDataForService:@"textsecure"],
+            [self.class certificateDataForService:@"textsecure"]
         ]];
     }
 
     return self;
 }
 
-- (NSArray *)certs {
-    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 {
-    
++ (NSData *)dataFromCertificateFileForService:(NSString *)service
+{
     NSBundle *bundle = [NSBundle bundleForClass:self.class];
     NSString *path = [bundle pathForResource:service ofType:@"cer"];
 
@@ -46,12 +39,25 @@
         OWSFail(@"Missing signing certificate for service %@", service);
     }
 
-    NSData *certificateData = [NSData dataWithContentsOfFile:path];
-    return SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData));
+    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));
+}
 
-- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
+- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(nullable NSString *)domain
+{
     NSMutableArray *policies = [NSMutableArray array];
     [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
 
@@ -90,3 +96,5 @@ _out:
 }
 
 @end
+
+NS_ASSUME_NONNULL_END

+ 0 - 9
SignalServiceKit/src/Security/OWSWebsocketSecurityPolicy.h

@@ -1,9 +0,0 @@
-//  Copyright © 2016 Open Whisper Systems. All rights reserved.
-
-#import <SocketRocket/SRSecurityPolicy.h>
-
-@interface OWSWebsocketSecurityPolicy : SRSecurityPolicy
-
-+ (instancetype)sharedPolicy;
-
-@end

+ 0 - 29
SignalServiceKit/src/Security/OWSWebsocketSecurityPolicy.m

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