more linux work
This commit is contained in:
parent
afc5a561d0
commit
95b3bfc802
@ -24,7 +24,11 @@
|
|||||||
|
|
||||||
import Dispatch
|
import Dispatch
|
||||||
import Foundation
|
import Foundation
|
||||||
|
#if !os(Linux)
|
||||||
import StarscreamSocketIO
|
import StarscreamSocketIO
|
||||||
|
#else
|
||||||
|
import WebSockets
|
||||||
|
#endif
|
||||||
|
|
||||||
/// The class that handles the engine.io protocol and transports.
|
/// The class that handles the engine.io protocol and transports.
|
||||||
/// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods.
|
/// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods.
|
||||||
@ -60,6 +64,9 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
/// **Do not touch this directly**
|
/// **Do not touch this directly**
|
||||||
public var waitingForPost = false
|
public var waitingForPost = false
|
||||||
|
|
||||||
|
/// The WebSocket for this engine.
|
||||||
|
public var ws: WebSocket?
|
||||||
|
|
||||||
/// `true` if this engine is closed.
|
/// `true` if this engine is closed.
|
||||||
public private(set) var closed = false
|
public private(set) var closed = false
|
||||||
|
|
||||||
@ -95,6 +102,17 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
|
/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
|
||||||
public private(set) var probing = false
|
public private(set) var probing = false
|
||||||
|
|
||||||
|
/// Whether or not this engine uses secure transports
|
||||||
|
public private(set) var secure = false
|
||||||
|
|
||||||
|
#if !os(Linux)
|
||||||
|
/// A custom security validator for Starscream. Useful for SSL pinning.
|
||||||
|
public private(set) var security: SSLSecurity?
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Whether or not to allow self signed certificates.
|
||||||
|
public private(set) var selfSigned = false
|
||||||
|
|
||||||
/// The URLSession that will be used for polling.
|
/// The URLSession that will be used for polling.
|
||||||
public private(set) var session: URLSession?
|
public private(set) var session: URLSession?
|
||||||
|
|
||||||
@ -113,9 +131,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
/// If `true`, then the engine is currently in WebSockets mode.
|
/// If `true`, then the engine is currently in WebSockets mode.
|
||||||
public private(set) var websocket = false
|
public private(set) var websocket = false
|
||||||
|
|
||||||
/// The WebSocket for this engine.
|
|
||||||
public private(set) var ws: WebSocket?
|
|
||||||
|
|
||||||
/// The client for this engine.
|
/// The client for this engine.
|
||||||
public weak var client: SocketEngineClient?
|
public weak var client: SocketEngineClient?
|
||||||
|
|
||||||
@ -133,9 +148,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
private var pongsMissed = 0
|
private var pongsMissed = 0
|
||||||
private var pongsMissedMax = 0
|
private var pongsMissedMax = 0
|
||||||
private var probeWait = ProbeWaitQueue()
|
private var probeWait = ProbeWaitQueue()
|
||||||
private var secure = false
|
|
||||||
private var security: SSLSecurity?
|
|
||||||
private var selfSigned = false
|
|
||||||
|
|
||||||
// MARK: Initializers
|
// MARK: Initializers
|
||||||
|
|
||||||
@ -308,32 +320,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
return (urlPolling.url!, urlWebSocket.url!)
|
return (urlPolling.url!, urlWebSocket.url!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createWebSocketAndConnect() {
|
|
||||||
ws?.delegate = nil // TODO this seems a bit defensive, is this really needed?
|
|
||||||
ws = WebSocket(url: urlWebSocketWithSid)
|
|
||||||
|
|
||||||
if cookies != nil {
|
|
||||||
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
|
||||||
for (key, value) in headers {
|
|
||||||
ws?.headers[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if extraHeaders != nil {
|
|
||||||
for (headerName, value) in extraHeaders! {
|
|
||||||
ws?.headers[headerName] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ws?.callbackQueue = engineQueue
|
|
||||||
ws?.enableCompression = compress
|
|
||||||
ws?.delegate = self
|
|
||||||
ws?.disableSSLCertValidation = selfSigned
|
|
||||||
ws?.security = security
|
|
||||||
|
|
||||||
ws?.connect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called when an error happens during execution. Causes a disconnection.
|
/// Called when an error happens during execution. Causes a disconnection.
|
||||||
public func didError(reason: String) {
|
public func didError(reason: String) {
|
||||||
DefaultSocketLogger.Logger.error("%@", type: SocketEngine.logType, args: reason)
|
DefaultSocketLogger.Logger.error("%@", type: SocketEngine.logType, args: reason)
|
||||||
@ -486,6 +472,44 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called when a successful WebSocket connection is made.
|
||||||
|
public func handleWSConnect() {
|
||||||
|
if !forceWebsockets {
|
||||||
|
probing = true
|
||||||
|
probeWebSocket()
|
||||||
|
} else {
|
||||||
|
connected = true
|
||||||
|
probing = false
|
||||||
|
polling = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called when the WebSocket disconnects.
|
||||||
|
public func handleWSDisconnect(error: NSError?) {
|
||||||
|
probing = false
|
||||||
|
|
||||||
|
if closed {
|
||||||
|
client?.engineDidClose(reason: "Disconnect")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard websocket else {
|
||||||
|
flushProbeWait()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = false
|
||||||
|
websocket = false
|
||||||
|
|
||||||
|
if let reason = error?.localizedDescription {
|
||||||
|
didError(reason: reason)
|
||||||
|
} else {
|
||||||
|
client?.engineDidClose(reason: "Socket Disconnected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses raw binary received from engine.io.
|
/// Parses raw binary received from engine.io.
|
||||||
///
|
///
|
||||||
/// - parameter data: The data to parse.
|
/// - parameter data: The data to parse.
|
||||||
@ -601,45 +625,19 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !os(Linux)
|
||||||
// MARK: Starscream delegate conformance
|
// MARK: Starscream delegate conformance
|
||||||
|
|
||||||
/// Delegate method for connection.
|
/// Delegate method for connection.
|
||||||
public func websocketDidConnect(socket: WebSocket) {
|
public func websocketDidConnect(socket: WebSocket) {
|
||||||
if !forceWebsockets {
|
handleWSConnect()
|
||||||
probing = true
|
|
||||||
probeWebSocket()
|
|
||||||
} else {
|
|
||||||
connected = true
|
|
||||||
probing = false
|
|
||||||
polling = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delegate method for disconnection.
|
/// Delegate method for disconnection.
|
||||||
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
|
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
|
||||||
probing = false
|
handleWSDisconnect(error: error)
|
||||||
|
|
||||||
if closed {
|
|
||||||
client?.engineDidClose(reason: "Disconnect")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard websocket else {
|
|
||||||
flushProbeWait()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
connected = false
|
|
||||||
websocket = false
|
|
||||||
|
|
||||||
if let reason = error?.localizedDescription {
|
|
||||||
didError(reason: reason)
|
|
||||||
} else {
|
|
||||||
client?.engineDidClose(reason: "Socket Disconnected")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SocketEngine {
|
extension SocketEngine {
|
||||||
|
|||||||
@ -24,7 +24,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
#if !os(Linux)
|
||||||
import StarscreamSocketIO
|
import StarscreamSocketIO
|
||||||
|
#else
|
||||||
|
import WebSockets
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Specifies a SocketEngine.
|
/// Specifies a SocketEngine.
|
||||||
@objc public protocol SocketEngineSpec {
|
@objc public protocol SocketEngineSpec {
|
||||||
@ -40,6 +44,9 @@ import StarscreamSocketIO
|
|||||||
/// The connect parameters sent during a connect.
|
/// The connect parameters sent during a connect.
|
||||||
var connectParams: [String: Any]? { get set }
|
var connectParams: [String: Any]? { get set }
|
||||||
|
|
||||||
|
/// Whether or not to use WebSocket compression.
|
||||||
|
var compress: Bool { get }
|
||||||
|
|
||||||
/// An array of HTTPCookies that are sent during the connection.
|
/// An array of HTTPCookies that are sent during the connection.
|
||||||
var cookies: [HTTPCookie]? { get }
|
var cookies: [HTTPCookie]? { get }
|
||||||
|
|
||||||
@ -64,6 +71,14 @@ import StarscreamSocketIO
|
|||||||
/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
|
/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
|
||||||
var probing: Bool { get }
|
var probing: Bool { get }
|
||||||
|
|
||||||
|
/// Whether or not this engine uses secure transports
|
||||||
|
var secure: Bool { get }
|
||||||
|
|
||||||
|
var security: SSLSecurity? { get }
|
||||||
|
|
||||||
|
/// Whether or not to allow self signed certificates.
|
||||||
|
var selfSigned: Bool { get }
|
||||||
|
|
||||||
/// The session id for this engine.
|
/// The session id for this engine.
|
||||||
var sid: String { get }
|
var sid: String { get }
|
||||||
|
|
||||||
@ -80,7 +95,7 @@ import StarscreamSocketIO
|
|||||||
var websocket: Bool { get }
|
var websocket: Bool { get }
|
||||||
|
|
||||||
/// The WebSocket for this engine.
|
/// The WebSocket for this engine.
|
||||||
var ws: WebSocket? { get }
|
var ws: WebSocket? { get set }
|
||||||
|
|
||||||
/// Creates a new engine.
|
/// Creates a new engine.
|
||||||
///
|
///
|
||||||
|
|||||||
@ -24,10 +24,22 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
#if !os(Linux)
|
||||||
import StarscreamSocketIO
|
import StarscreamSocketIO
|
||||||
|
#else
|
||||||
|
import WebSockets
|
||||||
|
import Sockets
|
||||||
|
import TLS
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Protocol that is used to implement socket.io WebSocket support
|
/// Protocol that is used to implement socket.io WebSocket support
|
||||||
public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate {
|
public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate {
|
||||||
|
/// Called when a successful WebSocket connection is made.
|
||||||
|
func handleWSConnect()
|
||||||
|
|
||||||
|
/// Called when the WebSocket disconnects.
|
||||||
|
func handleWSDisconnect(error: NSError?)
|
||||||
|
|
||||||
/// Sends an engine.io message through the WebSocket transport.
|
/// Sends an engine.io message through the WebSocket transport.
|
||||||
///
|
///
|
||||||
/// You shouldn't call this directly, instead call the `write` method on `SocketEngine`.
|
/// You shouldn't call this directly, instead call the `write` method on `SocketEngine`.
|
||||||
@ -40,6 +52,74 @@ public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate {
|
|||||||
|
|
||||||
// WebSocket methods
|
// WebSocket methods
|
||||||
extension SocketEngineWebsocket {
|
extension SocketEngineWebsocket {
|
||||||
|
#if os(Linux)
|
||||||
|
func attachWebSocketHandlers() {
|
||||||
|
ws?.onText = {[weak self] ws, text in
|
||||||
|
guard let this = self else { return }
|
||||||
|
|
||||||
|
this.parseEngineMessage(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws?.onBinary = {[weak self] ws, bin in
|
||||||
|
guard let this = self else { return }
|
||||||
|
|
||||||
|
this.parseEngineData(Data(bytes: bin))
|
||||||
|
}
|
||||||
|
|
||||||
|
ws?.onClose = {[weak self] _, _, reason, clean in
|
||||||
|
guard let this = self else { return }
|
||||||
|
|
||||||
|
this.handleWSDisconnect(error: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
func createWebSocketAndConnect() {
|
||||||
|
#if !os(Linux)
|
||||||
|
ws?.delegate = nil // TODO this seems a bit defensive, is this really needed?
|
||||||
|
ws = WebSocket(url: urlWebSocketWithSid)
|
||||||
|
|
||||||
|
if cookies != nil {
|
||||||
|
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
||||||
|
for (key, value) in headers {
|
||||||
|
ws?.headers[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if extraHeaders != nil {
|
||||||
|
for (headerName, value) in extraHeaders! {
|
||||||
|
ws?.headers[headerName] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ws?.callbackQueue = engineQueue
|
||||||
|
ws?.enableCompression = compress
|
||||||
|
ws?.delegate = self
|
||||||
|
ws?.disableSSLCertValidation = selfSigned
|
||||||
|
ws?.security = security
|
||||||
|
|
||||||
|
ws?.connect()
|
||||||
|
#else
|
||||||
|
let url = urlWebSocketWithSid
|
||||||
|
do {
|
||||||
|
let socket = try TCPInternetSocket(scheme: url.scheme ?? "http",
|
||||||
|
hostname: url.host ?? "localhost",
|
||||||
|
port: Port(url.port ?? 80))
|
||||||
|
let stream = secure ? try TLS.InternetSocket(socket, TLS.Context(.client)) : socket
|
||||||
|
try WebSocket.background(to: connectURL, using: stream) {[weak self] ws in
|
||||||
|
guard let this = self else { return }
|
||||||
|
|
||||||
|
this.ws = ws
|
||||||
|
|
||||||
|
this.attachWebSocketHandlers()
|
||||||
|
this.handleWSConnect()
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
DefaultSocketLogger.Logger.error("Error connecting socket", type: "SocketEngineWebsocket")
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
func probeWebSocket() {
|
func probeWebSocket() {
|
||||||
if ws?.isConnected ?? false {
|
if ws?.isConnected ?? false {
|
||||||
sendWebSocketMessage("probe", withType: .ping, withData: [])
|
sendWebSocketMessage("probe", withType: .ping, withData: [])
|
||||||
@ -67,6 +147,7 @@ extension SocketEngineWebsocket {
|
|||||||
|
|
||||||
// MARK: Starscream delegate methods
|
// MARK: Starscream delegate methods
|
||||||
|
|
||||||
|
#if !os(Linux)
|
||||||
/// Delegate method for when a message is received.
|
/// Delegate method for when a message is received.
|
||||||
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
|
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
|
||||||
parseEngineMessage(text)
|
parseEngineMessage(text)
|
||||||
@ -76,4 +157,16 @@ extension SocketEngineWebsocket {
|
|||||||
public func websocketDidReceiveData(socket: WebSocket, data: Data) {
|
public func websocketDidReceiveData(socket: WebSocket, data: Data) {
|
||||||
parseEngineData(data)
|
parseEngineData(data)
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(Linux)
|
||||||
|
/// SSLSecurity does nothing on Linux.
|
||||||
|
public final class SSLSecurity { }
|
||||||
|
|
||||||
|
extension WebSocket {
|
||||||
|
var isConnected: Bool {
|
||||||
|
return state == .open
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user