Skip to content

Commit 95b3bfc

Browse files
committed
more linux work
1 parent afc5a56 commit 95b3bfc

File tree

3 files changed

+169
-63
lines changed

3 files changed

+169
-63
lines changed

Source/SocketIO/Engine/SocketEngine.swift

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424

2525
import Dispatch
2626
import Foundation
27+
#if !os(Linux)
2728
import StarscreamSocketIO
29+
#else
30+
import WebSockets
31+
#endif
2832

2933
/// The class that handles the engine.io protocol and transports.
3034
/// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods.
@@ -60,6 +64,9 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
6064
/// **Do not touch this directly**
6165
public var waitingForPost = false
6266

67+
/// The WebSocket for this engine.
68+
public var ws: WebSocket?
69+
6370
/// `true` if this engine is closed.
6471
public private(set) var closed = false
6572

@@ -95,6 +102,17 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
95102
/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
96103
public private(set) var probing = false
97104

105+
/// Whether or not this engine uses secure transports
106+
public private(set) var secure = false
107+
108+
#if !os(Linux)
109+
/// A custom security validator for Starscream. Useful for SSL pinning.
110+
public private(set) var security: SSLSecurity?
111+
#endif
112+
113+
/// Whether or not to allow self signed certificates.
114+
public private(set) var selfSigned = false
115+
98116
/// The URLSession that will be used for polling.
99117
public private(set) var session: URLSession?
100118

@@ -113,9 +131,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
113131
/// If `true`, then the engine is currently in WebSockets mode.
114132
public private(set) var websocket = false
115133

116-
/// The WebSocket for this engine.
117-
public private(set) var ws: WebSocket?
118-
119134
/// The client for this engine.
120135
public weak var client: SocketEngineClient?
121136

@@ -133,9 +148,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
133148
private var pongsMissed = 0
134149
private var pongsMissedMax = 0
135150
private var probeWait = ProbeWaitQueue()
136-
private var secure = false
137-
private var security: SSLSecurity?
138-
private var selfSigned = false
139151

140152
// MARK: Initializers
141153

@@ -308,32 +320,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
308320
return (urlPolling.url!, urlWebSocket.url!)
309321
}
310322

311-
private func createWebSocketAndConnect() {
312-
ws?.delegate = nil // TODO this seems a bit defensive, is this really needed?
313-
ws = WebSocket(url: urlWebSocketWithSid)
314-
315-
if cookies != nil {
316-
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
317-
for (key, value) in headers {
318-
ws?.headers[key] = value
319-
}
320-
}
321-
322-
if extraHeaders != nil {
323-
for (headerName, value) in extraHeaders! {
324-
ws?.headers[headerName] = value
325-
}
326-
}
327-
328-
ws?.callbackQueue = engineQueue
329-
ws?.enableCompression = compress
330-
ws?.delegate = self
331-
ws?.disableSSLCertValidation = selfSigned
332-
ws?.security = security
333-
334-
ws?.connect()
335-
}
336-
337323
/// Called when an error happens during execution. Causes a disconnection.
338324
public func didError(reason: String) {
339325
DefaultSocketLogger.Logger.error("%@", type: SocketEngine.logType, args: reason)
@@ -486,6 +472,44 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
486472
}
487473
}
488474

475+
/// Called when a successful WebSocket connection is made.
476+
public func handleWSConnect() {
477+
if !forceWebsockets {
478+
probing = true
479+
probeWebSocket()
480+
} else {
481+
connected = true
482+
probing = false
483+
polling = false
484+
}
485+
}
486+
487+
/// Called when the WebSocket disconnects.
488+
public func handleWSDisconnect(error: NSError?) {
489+
probing = false
490+
491+
if closed {
492+
client?.engineDidClose(reason: "Disconnect")
493+
494+
return
495+
}
496+
497+
guard websocket else {
498+
flushProbeWait()
499+
500+
return
501+
}
502+
503+
connected = false
504+
websocket = false
505+
506+
if let reason = error?.localizedDescription {
507+
didError(reason: reason)
508+
} else {
509+
client?.engineDidClose(reason: "Socket Disconnected")
510+
}
511+
}
512+
489513
/// Parses raw binary received from engine.io.
490514
///
491515
/// - parameter data: The data to parse.
@@ -601,45 +625,19 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
601625
}
602626
}
603627

628+
#if !os(Linux)
604629
// MARK: Starscream delegate conformance
605630

606631
/// Delegate method for connection.
607632
public func websocketDidConnect(socket: WebSocket) {
608-
if !forceWebsockets {
609-
probing = true
610-
probeWebSocket()
611-
} else {
612-
connected = true
613-
probing = false
614-
polling = false
615-
}
633+
handleWSConnect()
616634
}
617635

618636
/// Delegate method for disconnection.
619637
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
620-
probing = false
621-
622-
if closed {
623-
client?.engineDidClose(reason: "Disconnect")
624-
625-
return
626-
}
627-
628-
guard websocket else {
629-
flushProbeWait()
630-
631-
return
632-
}
633-
634-
connected = false
635-
websocket = false
636-
637-
if let reason = error?.localizedDescription {
638-
didError(reason: reason)
639-
} else {
640-
client?.engineDidClose(reason: "Socket Disconnected")
641-
}
638+
handleWSDisconnect(error: error)
642639
}
640+
#endif
643641
}
644642

645643
extension SocketEngine {

Source/SocketIO/Engine/SocketEngineSpec.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
//
2525

2626
import Foundation
27+
#if !os(Linux)
2728
import StarscreamSocketIO
29+
#else
30+
import WebSockets
31+
#endif
2832

2933
/// Specifies a SocketEngine.
3034
@objc public protocol SocketEngineSpec {
@@ -40,6 +44,9 @@ import StarscreamSocketIO
4044
/// The connect parameters sent during a connect.
4145
var connectParams: [String: Any]? { get set }
4246

47+
/// Whether or not to use WebSocket compression.
48+
var compress: Bool { get }
49+
4350
/// An array of HTTPCookies that are sent during the connection.
4451
var cookies: [HTTPCookie]? { get }
4552

@@ -64,6 +71,14 @@ import StarscreamSocketIO
6471
/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
6572
var probing: Bool { get }
6673

74+
/// Whether or not this engine uses secure transports
75+
var secure: Bool { get }
76+
77+
var security: SSLSecurity? { get }
78+
79+
/// Whether or not to allow self signed certificates.
80+
var selfSigned: Bool { get }
81+
6782
/// The session id for this engine.
6883
var sid: String { get }
6984

@@ -80,7 +95,7 @@ import StarscreamSocketIO
8095
var websocket: Bool { get }
8196

8297
/// The WebSocket for this engine.
83-
var ws: WebSocket? { get }
98+
var ws: WebSocket? { get set }
8499

85100
/// Creates a new engine.
86101
///

Source/SocketIO/Engine/SocketEngineWebsocket.swift

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,22 @@
2424
//
2525

2626
import Foundation
27+
#if !os(Linux)
2728
import StarscreamSocketIO
29+
#else
30+
import WebSockets
31+
import Sockets
32+
import TLS
33+
#endif
2834

2935
/// Protocol that is used to implement socket.io WebSocket support
3036
public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate {
37+
/// Called when a successful WebSocket connection is made.
38+
func handleWSConnect()
39+
40+
/// Called when the WebSocket disconnects.
41+
func handleWSDisconnect(error: NSError?)
42+
3143
/// Sends an engine.io message through the WebSocket transport.
3244
///
3345
/// You shouldn't call this directly, instead call the `write` method on `SocketEngine`.
@@ -40,6 +52,74 @@ public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate {
4052

4153
// WebSocket methods
4254
extension SocketEngineWebsocket {
55+
#if os(Linux)
56+
func attachWebSocketHandlers() {
57+
ws?.onText = {[weak self] ws, text in
58+
guard let this = self else { return }
59+
60+
this.parseEngineMessage(text)
61+
}
62+
63+
ws?.onBinary = {[weak self] ws, bin in
64+
guard let this = self else { return }
65+
66+
this.parseEngineData(Data(bytes: bin))
67+
}
68+
69+
ws?.onClose = {[weak self] _, _, reason, clean in
70+
guard let this = self else { return }
71+
72+
this.handleWSDisconnect(error: nil)
73+
}
74+
}
75+
#endif
76+
77+
func createWebSocketAndConnect() {
78+
#if !os(Linux)
79+
ws?.delegate = nil // TODO this seems a bit defensive, is this really needed?
80+
ws = WebSocket(url: urlWebSocketWithSid)
81+
82+
if cookies != nil {
83+
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
84+
for (key, value) in headers {
85+
ws?.headers[key] = value
86+
}
87+
}
88+
89+
if extraHeaders != nil {
90+
for (headerName, value) in extraHeaders! {
91+
ws?.headers[headerName] = value
92+
}
93+
}
94+
95+
ws?.callbackQueue = engineQueue
96+
ws?.enableCompression = compress
97+
ws?.delegate = self
98+
ws?.disableSSLCertValidation = selfSigned
99+
ws?.security = security
100+
101+
ws?.connect()
102+
#else
103+
let url = urlWebSocketWithSid
104+
do {
105+
let socket = try TCPInternetSocket(scheme: url.scheme ?? "http",
106+
hostname: url.host ?? "localhost",
107+
port: Port(url.port ?? 80))
108+
let stream = secure ? try TLS.InternetSocket(socket, TLS.Context(.client)) : socket
109+
try WebSocket.background(to: connectURL, using: stream) {[weak self] ws in
110+
guard let this = self else { return }
111+
112+
this.ws = ws
113+
114+
this.attachWebSocketHandlers()
115+
this.handleWSConnect()
116+
}
117+
} catch {
118+
DefaultSocketLogger.Logger.error("Error connecting socket", type: "SocketEngineWebsocket")
119+
}
120+
#endif
121+
}
122+
43123
func probeWebSocket() {
44124
if ws?.isConnected ?? false {
45125
sendWebSocketMessage("probe", withType: .ping, withData: [])
@@ -67,6 +147,7 @@ extension SocketEngineWebsocket {
67147

68148
// MARK: Starscream delegate methods
69149

150+
#if !os(Linux)
70151
/// Delegate method for when a message is received.
71152
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
72153
parseEngineMessage(text)
@@ -76,4 +157,16 @@ extension SocketEngineWebsocket {
76157
public func websocketDidReceiveData(socket: WebSocket, data: Data) {
77158
parseEngineData(data)
78159
}
160+
#endif
161+
}
162+
163+
#if os(Linux)
164+
/// SSLSecurity does nothing on Linux.
165+
public final class SSLSecurity { }
166+
167+
extension WebSocket {
168+
var isConnected: Bool {
169+
return state == .open
170+
}
79171
}
172+
#endif

0 commit comments

Comments
 (0)