Merge branch 'development' of https://github.com/socketio/socket.io-client-swift into development
* 'development' of https://github.com/socketio/socket.io-client-swift: SocketAckEmitter.isExpected => .expected change isRequired() to isExpected() remove semicolon Update README.md add SocketAckEmitter.isRequired() Update README.md bump version bump websocket version fix Use Legacy Swift issue bump websocket version Update README.md
This commit is contained in:
commit
56278795ea
@ -39,7 +39,7 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{
|
|||||||
[socket on:@"currentAmount" callback:^(NSArray* data, SocketAckEmitter* ack) {
|
[socket on:@"currentAmount" callback:^(NSArray* data, SocketAckEmitter* ack) {
|
||||||
double cur = [[data objectAtIndex:0] floatValue];
|
double cur = [[data objectAtIndex:0] floatValue];
|
||||||
|
|
||||||
[[socket emitWithAck:@"canUpdate" withItems:@[@(cur)]] timingOutAfter:0 callback:^(NSArray* data) {
|
[[socket emitWithAck:@"canUpdate" with:@[@(cur)]] timingOutAfter:0 callback:^(NSArray* data) {
|
||||||
[socket emit:@"update" withItems:@[@{@"amount": @(cur + 2.50)}]];
|
[socket emit:@"update" withItems:@[@{@"amount": @(cur + 2.50)}]];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ Carthage
|
|||||||
-----------------
|
-----------------
|
||||||
Add this line to your `Cartfile`:
|
Add this line to your `Cartfile`:
|
||||||
```
|
```
|
||||||
github "socketio/socket.io-client-swift" ~> 8.0.2 # Or latest version
|
github "socketio/socket.io-client-swift" ~> 8.1.0 # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `carthage update --platform ios,macosx`.
|
Run `carthage update --platform ios,macosx`.
|
||||||
@ -108,7 +108,7 @@ Create `Podfile` and add `pod 'Socket.IO-Client-Swift'`:
|
|||||||
use_frameworks!
|
use_frameworks!
|
||||||
|
|
||||||
target 'YourApp' do
|
target 'YourApp' do
|
||||||
pod 'Socket.IO-Client-Swift', '~> 8.0.2' # Or latest version
|
pod 'Socket.IO-Client-Swift', '~> 8.1.0' # Or latest version
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ CocoaSeeds
|
|||||||
Add this line to your `Seedfile`:
|
Add this line to your `Seedfile`:
|
||||||
|
|
||||||
```
|
```
|
||||||
github "socketio/socket.io-client-swift", "v8.0.2", :files => "Source/*.swift" # Or latest version
|
github "socketio/socket.io-client-swift", "v8.1.0", :files => "Source/*.swift" # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `seed install`.
|
Run `seed install`.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "Socket.IO-Client-Swift"
|
s.name = "Socket.IO-Client-Swift"
|
||||||
s.module_name = "SocketIO"
|
s.module_name = "SocketIO"
|
||||||
s.version = "8.0.2"
|
s.version = "8.1.0"
|
||||||
s.summary = "Socket.IO-client for iOS and OS X"
|
s.summary = "Socket.IO-client for iOS and OS X"
|
||||||
s.description = <<-DESC
|
s.description = <<-DESC
|
||||||
Socket.IO-client for iOS and OS X.
|
Socket.IO-client for iOS and OS X.
|
||||||
@ -14,8 +14,9 @@ Pod::Spec.new do |s|
|
|||||||
s.ios.deployment_target = '8.0'
|
s.ios.deployment_target = '8.0'
|
||||||
s.osx.deployment_target = '10.10'
|
s.osx.deployment_target = '10.10'
|
||||||
s.tvos.deployment_target = '9.0'
|
s.tvos.deployment_target = '9.0'
|
||||||
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v8.0.2' }
|
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v8.1.0' }
|
||||||
s.source_files = "Source/**/*.swift"
|
s.source_files = "Source/**/*.swift"
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
|
s.pod_target_xcconfig = {'SWIFT_VERSION' => '3.0'}
|
||||||
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files
|
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
// Starscream
|
// Starscream
|
||||||
//
|
//
|
||||||
// Created by Dalton Cherry on 5/16/15.
|
// Created by Dalton Cherry on 5/16/15.
|
||||||
// Copyright (c) 2014-2015 Dalton Cherry.
|
// Copyright (c) 2014-2016 Dalton Cherry.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -19,11 +19,14 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Security
|
import Security
|
||||||
|
|
||||||
public class SSLCert : NSObject {
|
public protocol SSLTrustValidator {
|
||||||
|
func isValid(_ trust: SecTrust, domain: String?) -> Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
open class SSLCert {
|
||||||
var certData: Data?
|
var certData: Data?
|
||||||
var key: SecKey?
|
var key: SecKey?
|
||||||
|
|
||||||
@ -50,7 +53,7 @@ public class SSLCert : NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SSLSecurity : NSObject {
|
open class SSLSecurity : SSLTrustValidator {
|
||||||
public var validatedDN = true //should the domain name be validated?
|
public var validatedDN = true //should the domain name be validated?
|
||||||
|
|
||||||
var isReady = false //is the key processing done?
|
var isReady = false //is the key processing done?
|
||||||
@ -82,7 +85,7 @@ public class SSLSecurity : NSObject {
|
|||||||
/**
|
/**
|
||||||
Designated init
|
Designated init
|
||||||
|
|
||||||
- parameter keys: is the certificates or public keys to use
|
- parameter certs: is the certificates or public keys to use
|
||||||
- parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation
|
- parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation
|
||||||
|
|
||||||
- returns: a representation security object to be used with
|
- returns: a representation security object to be used with
|
||||||
@ -90,8 +93,6 @@ public class SSLSecurity : NSObject {
|
|||||||
public init(certs: [SSLCert], usePublicKeys: Bool) {
|
public init(certs: [SSLCert], usePublicKeys: Bool) {
|
||||||
self.usePublicKeys = usePublicKeys
|
self.usePublicKeys = usePublicKeys
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
if self.usePublicKeys {
|
if self.usePublicKeys {
|
||||||
DispatchQueue.global(qos: .default).async {
|
DispatchQueue.global(qos: .default).async {
|
||||||
let pubKeys = certs.reduce([SecKey]()) { (pubKeys: [SecKey], cert: SSLCert) -> [SecKey] in
|
let pubKeys = certs.reduce([SecKey]()) { (pubKeys: [SecKey], cert: SSLCert) -> [SecKey] in
|
||||||
|
|||||||
@ -27,6 +27,10 @@ import Foundation
|
|||||||
public final class SocketAckEmitter : NSObject {
|
public final class SocketAckEmitter : NSObject {
|
||||||
let socket: SocketIOClient
|
let socket: SocketIOClient
|
||||||
let ackNum: Int
|
let ackNum: Int
|
||||||
|
|
||||||
|
public var expected: Bool {
|
||||||
|
return ackNum != -1
|
||||||
|
}
|
||||||
|
|
||||||
init(socket: SocketIOClient, ackNum: Int) {
|
init(socket: SocketIOClient, ackNum: Int) {
|
||||||
self.socket = socket
|
self.socket = socket
|
||||||
@ -44,6 +48,7 @@ public final class SocketAckEmitter : NSObject {
|
|||||||
|
|
||||||
socket.emitAck(ackNum, with: items)
|
socket.emitAck(ackNum, with: items)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class OnAckCallback : NSObject {
|
public final class OnAckCallback : NSObject {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
// Websocket.swift
|
// Websocket.swift
|
||||||
//
|
//
|
||||||
// Created by Dalton Cherry on 7/16/14.
|
// Created by Dalton Cherry on 7/16/14.
|
||||||
// Copyright (c) 2014-2015 Dalton Cherry.
|
// Copyright (c) 2014-2016 Dalton Cherry.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -18,7 +18,6 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreFoundation
|
import CoreFoundation
|
||||||
import Security
|
import Security
|
||||||
@ -38,7 +37,7 @@ public protocol WebSocketPongDelegate: class {
|
|||||||
func websocketDidReceivePong(socket: WebSocket, data: Data?)
|
func websocketDidReceivePong(socket: WebSocket, data: Data?)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WebSocket : NSObject, StreamDelegate {
|
open class WebSocket : NSObject, StreamDelegate {
|
||||||
|
|
||||||
enum OpCode : UInt8 {
|
enum OpCode : UInt8 {
|
||||||
case continueFrame = 0x0
|
case continueFrame = 0x0
|
||||||
@ -77,7 +76,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
var optionalProtocols: [String]?
|
var optionalProtocols: [String]?
|
||||||
|
|
||||||
// MARK: - Constants
|
// MARK: - Constants
|
||||||
|
|
||||||
let headerWSUpgradeName = "Upgrade"
|
let headerWSUpgradeName = "Upgrade"
|
||||||
let headerWSUpgradeValue = "websocket"
|
let headerWSUpgradeValue = "websocket"
|
||||||
let headerWSHostName = "Host"
|
let headerWSHostName = "Host"
|
||||||
@ -108,7 +106,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Delegates
|
// MARK: - Delegates
|
||||||
|
|
||||||
/// Responds to callback about new messages coming in over the WebSocket
|
/// Responds to callback about new messages coming in over the WebSocket
|
||||||
/// and also connection/disconnect messages.
|
/// and also connection/disconnect messages.
|
||||||
public weak var delegate: WebSocketDelegate?
|
public weak var delegate: WebSocketDelegate?
|
||||||
@ -118,7 +115,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
|
|
||||||
|
|
||||||
// MARK: - Block based API.
|
// MARK: - Block based API.
|
||||||
|
|
||||||
public var onConnect: ((Void) -> Void)?
|
public var onConnect: ((Void) -> Void)?
|
||||||
public var onDisconnect: ((NSError?) -> Void)?
|
public var onDisconnect: ((NSError?) -> Void)?
|
||||||
public var onText: ((String) -> Void)?
|
public var onText: ((String) -> Void)?
|
||||||
@ -128,7 +124,7 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
public var headers = [String: String]()
|
public var headers = [String: String]()
|
||||||
public var voipEnabled = false
|
public var voipEnabled = false
|
||||||
public var disableSSLCertValidation = false
|
public var disableSSLCertValidation = false
|
||||||
public var security: SSLSecurity?
|
public var security: SSLTrustValidator?
|
||||||
public var enabledSSLCipherSuites: [SSLCipherSuite]?
|
public var enabledSSLCipherSuites: [SSLCipherSuite]?
|
||||||
public var origin: String?
|
public var origin: String?
|
||||||
public var timeout = 5
|
public var timeout = 5
|
||||||
@ -139,7 +135,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
public var currentURL: URL { return url }
|
public var currentURL: URL { return url }
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private var url: URL
|
private var url: URL
|
||||||
private var inputStream: InputStream?
|
private var inputStream: InputStream?
|
||||||
private var outputStream: OutputStream?
|
private var outputStream: OutputStream?
|
||||||
@ -198,7 +193,8 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
public func disconnect(forceTimeout: TimeInterval? = nil, closeCode: UInt16 = CloseCode.normal.rawValue) {
|
public func disconnect(forceTimeout: TimeInterval? = nil, closeCode: UInt16 = CloseCode.normal.rawValue) {
|
||||||
switch forceTimeout {
|
switch forceTimeout {
|
||||||
case .some(let seconds) where seconds > 0:
|
case .some(let seconds) where seconds > 0:
|
||||||
callbackQueue.asyncAfter(deadline: DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { [weak self] in
|
let milliseconds = Int(seconds * 1_000)
|
||||||
|
callbackQueue.asyncAfter(deadline: .now() + .milliseconds(milliseconds)) { [weak self] in
|
||||||
self?.disconnectStream(nil)
|
self?.disconnectStream(nil)
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -213,7 +209,7 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
/**
|
/**
|
||||||
Write a string to the websocket. This sends it as a text frame.
|
Write a string to the websocket. This sends it as a text frame.
|
||||||
If you supply a non-nil completion block, I will perform it when the write completes.
|
If you supply a non-nil completion block, I will perform it when the write completes.
|
||||||
- parameter str: The string to write.
|
- parameter string: The string to write.
|
||||||
- parameter completion: The (optional) completion handler.
|
- parameter completion: The (optional) completion handler.
|
||||||
*/
|
*/
|
||||||
public func write(string: String, completion: (() -> ())? = nil) {
|
public func write(string: String, completion: (() -> ())? = nil) {
|
||||||
@ -305,7 +301,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
private func initStreamsWithData(_ data: Data, _ port: Int) {
|
private func initStreamsWithData(_ data: Data, _ port: Int) {
|
||||||
//higher level API we will cut over to at some point
|
//higher level API we will cut over to at some point
|
||||||
//NSStream.getStreamsToHostWithName(url.host, port: url.port.integerValue, inputStream: &inputStream, outputStream: &outputStream)
|
//NSStream.getStreamsToHostWithName(url.host, port: url.port.integerValue, inputStream: &inputStream, outputStream: &outputStream)
|
||||||
|
|
||||||
var readStream: Unmanaged<CFReadStream>?
|
var readStream: Unmanaged<CFReadStream>?
|
||||||
var writeStream: Unmanaged<CFWriteStream>?
|
var writeStream: Unmanaged<CFWriteStream>?
|
||||||
let h = url.host! as NSString
|
let h = url.host! as NSString
|
||||||
@ -318,6 +313,28 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
if supportedSSLSchemes.contains(url.scheme!) {
|
if supportedSSLSchemes.contains(url.scheme!) {
|
||||||
inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
|
inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
|
||||||
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
|
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
|
||||||
|
if disableSSLCertValidation {
|
||||||
|
let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull]
|
||||||
|
inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
|
||||||
|
outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
|
||||||
|
}
|
||||||
|
if let cipherSuites = self.enabledSSLCipherSuites {
|
||||||
|
if let sslContextIn = CFReadStreamCopyProperty(inputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext?,
|
||||||
|
let sslContextOut = CFWriteStreamCopyProperty(outputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext? {
|
||||||
|
let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count)
|
||||||
|
let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count)
|
||||||
|
if resIn != errSecSuccess {
|
||||||
|
let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn))
|
||||||
|
disconnectStream(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resOut != errSecSuccess {
|
||||||
|
let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut))
|
||||||
|
disconnectStream(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
certValidated = true //not a https session, so no need to check SSL pinning
|
certValidated = true //not a https session, so no need to check SSL pinning
|
||||||
}
|
}
|
||||||
@ -325,28 +342,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
inStream.setProperty(StreamNetworkServiceTypeValue.voIP as AnyObject, forKey: Stream.PropertyKey.networkServiceType)
|
inStream.setProperty(StreamNetworkServiceTypeValue.voIP as AnyObject, forKey: Stream.PropertyKey.networkServiceType)
|
||||||
outStream.setProperty(StreamNetworkServiceTypeValue.voIP as AnyObject, forKey: Stream.PropertyKey.networkServiceType)
|
outStream.setProperty(StreamNetworkServiceTypeValue.voIP as AnyObject, forKey: Stream.PropertyKey.networkServiceType)
|
||||||
}
|
}
|
||||||
if disableSSLCertValidation {
|
|
||||||
let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull]
|
|
||||||
inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
|
|
||||||
outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
|
|
||||||
}
|
|
||||||
if let cipherSuites = self.enabledSSLCipherSuites {
|
|
||||||
if let sslContextIn = CFReadStreamCopyProperty(inputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext?,
|
|
||||||
let sslContextOut = CFWriteStreamCopyProperty(outputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext? {
|
|
||||||
let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count)
|
|
||||||
let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count)
|
|
||||||
if resIn != errSecSuccess {
|
|
||||||
let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn))
|
|
||||||
disconnectStream(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resOut != errSecSuccess {
|
|
||||||
let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut))
|
|
||||||
disconnectStream(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue)
|
CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue)
|
||||||
CFWriteStreamSetDispatchQueue(outStream, WebSocket.sharedWorkQueue)
|
CFWriteStreamSetDispatchQueue(outStream, WebSocket.sharedWorkQueue)
|
||||||
@ -358,7 +353,7 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
self.mutex.unlock()
|
self.mutex.unlock()
|
||||||
|
|
||||||
let bytes = UnsafeRawPointer((data as NSData).bytes).assumingMemoryBound(to: UInt8.self)
|
let bytes = UnsafeRawPointer((data as NSData).bytes).assumingMemoryBound(to: UInt8.self)
|
||||||
var out = timeout * 1000000 // wait 5 seconds before giving up
|
var out = timeout * 1_000_000 // wait 5 seconds before giving up
|
||||||
writeQueue.addOperation { [weak self] in
|
writeQueue.addOperation { [weak self] in
|
||||||
while !outStream.hasSpaceAvailable {
|
while !outStream.hasSpaceAvailable {
|
||||||
usleep(100) // wait until the socket is ready
|
usleep(100) // wait until the socket is ready
|
||||||
@ -380,9 +375,9 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
*/
|
*/
|
||||||
public func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
|
public func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
|
||||||
if let sec = security, !certValidated && [.hasBytesAvailable, .hasSpaceAvailable].contains(eventCode) {
|
if let sec = security, !certValidated && [.hasBytesAvailable, .hasSpaceAvailable].contains(eventCode) {
|
||||||
let trust = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as AnyObject
|
let trust = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust
|
||||||
let domain = aStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String
|
let domain = aStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String
|
||||||
if sec.isValid(trust as! SecTrust, domain: domain) {
|
if sec.isValid(trust, domain: domain) {
|
||||||
certValidated = true
|
certValidated = true
|
||||||
} else {
|
} else {
|
||||||
let error = errorWithDetail("Invalid SSL certificate", code: 1)
|
let error = errorWithDetail("Invalid SSL certificate", code: 1)
|
||||||
@ -439,7 +434,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
let buf = NSMutableData(capacity: BUFFER_MAX)
|
let buf = NSMutableData(capacity: BUFFER_MAX)
|
||||||
let buffer = UnsafeMutableRawPointer(mutating: buf!.bytes).assumingMemoryBound(to: UInt8.self)
|
let buffer = UnsafeMutableRawPointer(mutating: buf!.bytes).assumingMemoryBound(to: UInt8.self)
|
||||||
let length = inputStream!.read(buffer, maxLength: BUFFER_MAX)
|
let length = inputStream!.read(buffer, maxLength: BUFFER_MAX)
|
||||||
|
|
||||||
guard length > 0 else { return }
|
guard length > 0 else { return }
|
||||||
var process = false
|
var process = false
|
||||||
if inputQueue.count == 0 {
|
if inputQueue.count == 0 {
|
||||||
@ -635,34 +629,22 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return emptyBuffer
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
|
var closeCode = CloseCode.normal.rawValue
|
||||||
if receivedOpcode == .connectionClose {
|
if receivedOpcode == .connectionClose {
|
||||||
var code = CloseCode.normal.rawValue
|
|
||||||
if payloadLen == 1 {
|
if payloadLen == 1 {
|
||||||
code = CloseCode.protocolError.rawValue
|
closeCode = CloseCode.protocolError.rawValue
|
||||||
} else if payloadLen > 1 {
|
} else if payloadLen > 1 {
|
||||||
code = WebSocket.readUint16(baseAddress, offset: offset)
|
closeCode = WebSocket.readUint16(baseAddress, offset: offset)
|
||||||
if code < 1000 || (code > 1003 && code < 1007) || (code > 1011 && code < 3000) {
|
if closeCode < 1000 || (closeCode > 1003 && closeCode < 1007) || (closeCode > 1011 && closeCode < 3000) {
|
||||||
code = CloseCode.protocolError.rawValue
|
closeCode = CloseCode.protocolError.rawValue
|
||||||
}
|
|
||||||
offset += 2
|
|
||||||
}
|
|
||||||
var closeReason = "connection closed by server"
|
|
||||||
if payloadLen > 2 {
|
|
||||||
let len = Int(payloadLen - 2)
|
|
||||||
if len > 0 {
|
|
||||||
let bytes = baseAddress + offset
|
|
||||||
if let customCloseReason = String(data: Data(bytes: bytes, count: len), encoding: .utf8) {
|
|
||||||
closeReason = customCloseReason
|
|
||||||
} else {
|
|
||||||
code = CloseCode.protocolError.rawValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doDisconnect(errorWithDetail(closeReason, code: code))
|
if payloadLen < 2 {
|
||||||
writeError(code)
|
doDisconnect(errorWithDetail("connection closed by server", code: closeCode))
|
||||||
return emptyBuffer
|
writeError(closeCode)
|
||||||
}
|
return emptyBuffer
|
||||||
if isControlFrame && payloadLen > 125 {
|
}
|
||||||
|
} else if isControlFrame && payloadLen > 125 {
|
||||||
writeError(CloseCode.protocolError.rawValue)
|
writeError(CloseCode.protocolError.rawValue)
|
||||||
return emptyBuffer
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
@ -687,8 +669,24 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
len = 0
|
len = 0
|
||||||
data = Data()
|
data = Data()
|
||||||
} else {
|
} else {
|
||||||
|
if receivedOpcode == .connectionClose && len > 0 {
|
||||||
|
let size = MemoryLayout<UInt16>.size
|
||||||
|
offset += size
|
||||||
|
len -= UInt64(size)
|
||||||
|
}
|
||||||
data = Data(bytes: baseAddress+offset, count: Int(len))
|
data = Data(bytes: baseAddress+offset, count: Int(len))
|
||||||
}
|
}
|
||||||
|
if receivedOpcode == .connectionClose {
|
||||||
|
var closeReason = "connection closed by server"
|
||||||
|
if let customCloseReason = String(data: data, encoding: .utf8) {
|
||||||
|
closeReason = customCloseReason
|
||||||
|
} else {
|
||||||
|
closeCode = CloseCode.protocolError.rawValue
|
||||||
|
}
|
||||||
|
doDisconnect(errorWithDetail(closeReason, code: closeCode))
|
||||||
|
writeError(closeCode)
|
||||||
|
return emptyBuffer
|
||||||
|
}
|
||||||
if receivedOpcode == .pong {
|
if receivedOpcode == .pong {
|
||||||
if canDispatch {
|
if canDispatch {
|
||||||
callbackQueue.async { [weak self] in
|
callbackQueue.async { [weak self] in
|
||||||
@ -902,7 +900,6 @@ public class WebSocket : NSObject, StreamDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Deinit
|
// MARK: - Deinit
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
mutex.lock()
|
mutex.lock()
|
||||||
readyToWrite = false
|
readyToWrite = false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user