add forcewebsockets option

This commit is contained in:
Erik 2015-03-27 09:35:39 -04:00
parent 2cae405d29
commit 98e0c355f9
3 changed files with 100 additions and 70 deletions

View File

@ -57,6 +57,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
private var _connected = false private var _connected = false
private var fastUpgrade = false private var fastUpgrade = false
private var forcePolling = false private var forcePolling = false
private var forceWebsockets = false
private var pingTimer:NSTimer? private var pingTimer:NSTimer?
private var postWait = [String]() private var postWait = [String]()
private var _polling = true private var _polling = true
@ -82,12 +83,14 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
var ws:WebSocket? var ws:WebSocket?
public init(client:SocketEngineClient, forcePolling:Bool, withCookies cookies:[NSHTTPCookie]?) { public init(client:SocketEngineClient, forcePolling:Bool,
self.client = client forceWebsockets:Bool, withCookies cookies:[NSHTTPCookie]?) {
self.forcePolling = forcePolling self.client = client
self.cookies = cookies self.forcePolling = forcePolling
self.session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration(), self.forceWebsockets = forceWebsockets
delegate: nil, delegateQueue: self.workQueue) self.cookies = cookies
self.session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration(),
delegate: nil, delegateQueue: self.workQueue)
} }
public func close(#fast:Bool) { public func close(#fast:Bool) {
@ -157,6 +160,16 @@ public class SocketEngine: NSObject, WebSocketDelegate {
return (urlPolling, urlWebSocket) return (urlPolling, urlWebSocket)
} }
private func createWebsocket(andConnect connect:Bool) {
self.ws = WebSocket(url: NSURL(string: self.urlWebSocket! + "&sid=\(self.sid)")!)
self.ws?.queue = self.handleQueue
self.ws?.delegate = self
if connect {
self.ws?.connect()
}
}
private func doFastUpgrade() { private func doFastUpgrade() {
self.sendWebSocketMessage("", withType: PacketType.UPGRADE) self.sendWebSocketMessage("", withType: PacketType.UPGRADE)
self._websocket = true self._websocket = true
@ -171,16 +184,16 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
self.waitingForPoll = true self.waitingForPoll = true
self.doRequest(self.parsePollingMessage) let req = NSURLRequest(URL: NSURL(string: self.urlPolling! + "&sid=\(self.sid)&b64=1")!)
self.doRequest(req)
} }
private func doRequest(callback:(String) -> Void) { private func doRequest(req:NSURLRequest) {
if !self.polling { if !self.polling {
return return
} }
let req = NSURLRequest(URL: NSURL(string: self.urlPolling! + "&sid=\(self.sid)")!)
self.session.dataTaskWithRequest(req) {[weak self] data, res, err in self.session.dataTaskWithRequest(req) {[weak self] data, res, err in
if self == nil { if self == nil {
return return
@ -195,7 +208,10 @@ public class SocketEngine: NSObject, WebSocketDelegate {
// println(data) // println(data)
if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String { if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
dispatch_async(self!.parseQueue) {callback(str)} dispatch_async(self!.parseQueue) {
self?.parsePollingMessage(str)
return
}
} }
self?.waitingForPoll = false self?.waitingForPoll = false
@ -305,6 +321,14 @@ public class SocketEngine: NSObject, WebSocketDelegate {
let (urlPolling, urlWebSocket) = self.createURLs(opts) let (urlPolling, urlWebSocket) = self.createURLs(opts)
self.urlPolling = urlPolling self.urlPolling = urlPolling
self.urlWebSocket = urlWebSocket self.urlWebSocket = urlWebSocket
if self.forceWebsockets {
self._polling = false
self._websocket = true
self.createWebsocket(andConnect: true)
return
}
let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&b64=1")!) let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&b64=1")!)
if self.cookies != nil { if self.cookies != nil {
@ -312,58 +336,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
reqPolling.allHTTPHeaderFields = headers reqPolling.allHTTPHeaderFields = headers
} }
self.doRequest(reqPolling)
self.session.dataTaskWithRequest(reqPolling) {[weak self] data, res, err in
var err2:NSError?
if self == nil {
return
} else if err != nil || data == nil {
self?.handlePollingFailed(err.localizedDescription)
return
}
if let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
let parsed:[String]? = dataString["(\\d*):(\\d)(\\{.*\\})?"].groups()
if parsed == nil || parsed?.count != 4 {
return
}
let length = parsed![1]
let type = parsed![2]
let jsonData = parsed![3].dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
if type != "0" {
NSLog("Error handshaking")
return
}
if let json = NSJSONSerialization.JSONObjectWithData(jsonData!,
options: NSJSONReadingOptions.AllowFragments, error: &err2) as? NSDictionary {
if let sid = json["sid"] as? String {
// println(json)
self?.sid = sid
self?._connected = true
if !self!.forcePolling {
self?.ws = WebSocket(url: NSURL(string: urlWebSocket + "&sid=\(self!.sid)")!)
self?.ws?.queue = self?.handleQueue
self?.ws?.delegate = self
self?.ws?.connect()
}
} else {
NSLog("Error handshaking")
return
}
if let pingInterval = json["pingInterval"] as? Int {
self?.pingInterval = pingInterval / 1000
}
}
self?.doPoll()
self?.startPingTimer()
}}.resume()
} }
// Translatation of engine.io-parser#decodePayload // Translatation of engine.io-parser#decodePayload
@ -465,6 +438,40 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.upgradeTransport() self.upgradeTransport()
return return
} }
} else if type == PacketType.OPEN.rawValue {
var err:NSError?
message.removeAtIndex(message.startIndex)
let mesData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
if let json = NSJSONSerialization.JSONObjectWithData(mesData,
options: NSJSONReadingOptions.AllowFragments, error: &err) as? NSDictionary {
if let sid = json["sid"] as? String {
// println(json)
self.sid = sid
self._connected = true
if !self.forcePolling && !self.forceWebsockets {
self.createWebsocket(andConnect: true)
}
} else {
NSLog("Error handshaking")
return
}
if let pingInterval = json["pingInterval"] as? Int {
self.pingInterval = pingInterval / 1000
}
} else {
fatalError("Error parsing engine connect")
}
if !self.forceWebsockets {
self.doPoll()
}
self.startPingTimer()
return
} else if type == PacketType.CLOSE.rawValue { } else if type == PacketType.CLOSE.rawValue {
if self.polling { if self.polling {
self.client.didForceClose("Disconnect") self.client.didForceClose("Disconnect")
@ -587,8 +594,15 @@ public class SocketEngine: NSObject, WebSocketDelegate {
public func websocketDidConnect(socket:WebSocket) { public func websocketDidConnect(socket:WebSocket) {
self.websocketConnected = true self.websocketConnected = true
self.probing = true
self.probeWebSocket() if !self.forceWebsockets {
self.probing = true
self.probeWebSocket()
} else {
self._connected = true
self.probing = false
self._polling = false
}
} }
public func websocketDidDisconnect(socket:WebSocket, error:NSError?) { public func websocketDidDisconnect(socket:WebSocket, error:NSError?) {
@ -599,8 +613,10 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.pingTimer?.invalidate() self.pingTimer?.invalidate()
self._connected = false self._connected = false
self._websocket = false self._websocket = false
self._polling = true
self.client.webSocketDidCloseWithCode(1, reason: "Socket Disconnect", wasClean: true) let reason = error?.localizedDescription
self.client.webSocketDidCloseWithCode(1,
reason: reason == nil ? "Socket Disconnected" : reason!)
} else { } else {
self.flushProbeWait() self.flushProbeWait()
} }

View File

@ -36,6 +36,6 @@ import Foundation
func parseSocketMessage(msg:String) func parseSocketMessage(msg:String)
func parseBinaryData(data:NSData) func parseBinaryData(data:NSData)
func pollingDidFail(err:String) func pollingDidFail(err:String)
func webSocketDidCloseWithCode(code:Int, reason:String, wasClean:Bool) func webSocketDidCloseWithCode(code:Int, reason:String)
func webSocketDidFailWithError(error:NSError) func webSocketDidFailWithError(error:NSError)
} }

View File

@ -34,6 +34,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
private var _connecting = false private var _connecting = false
private var currentReconnectAttempt = 0 private var currentReconnectAttempt = 0
private var forcePolling = false private var forcePolling = false
private var forceWebsockets = false
private var handlers = ContiguousArray<SocketEventHandler>() private var handlers = ContiguousArray<SocketEventHandler>()
private var paramConnect = false private var paramConnect = false
private var _secure = false private var _secure = false
@ -110,6 +111,10 @@ public class SocketIOClient: NSObject, SocketEngineClient {
self.forcePolling = polling self.forcePolling = polling
} }
if let ws = opts!["forceWebsockets"] as? Bool {
self.forceWebsockets = ws
}
if let cookies = opts!["cookies"] as? [NSHTTPCookie] { if let cookies = opts!["cookies"] as? [NSHTTPCookie] {
self.cookies = cookies self.cookies = cookies
} }
@ -127,6 +132,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
private func addEngine() { private func addEngine() {
self.engine = SocketEngine(client: self, self.engine = SocketEngine(client: self,
forcePolling: self.forcePolling, forcePolling: self.forcePolling,
forceWebsockets: self.forceWebsockets,
withCookies: self.cookies) withCookies: self.cookies)
} }
@ -152,6 +158,10 @@ public class SocketIOClient: NSObject, SocketEngineClient {
self._closed = false self._closed = false
} }
if self.connected {
return
}
self.addEngine() self.addEngine()
self.engine?.open() self.engine?.open()
} }
@ -165,6 +175,10 @@ public class SocketIOClient: NSObject, SocketEngineClient {
self._closed = false self._closed = false
} }
if self.connected {
return
}
self.params = params self.params = params
self.paramConnect = true self.paramConnect = true
@ -452,12 +466,12 @@ public class SocketIOClient: NSObject, SocketEngineClient {
} }
// Called when the socket is closed // Called when the socket is closed
public func webSocketDidCloseWithCode(code:Int, reason:String, wasClean:Bool) { public func webSocketDidCloseWithCode(code:Int, reason:String) {
self._connected = false self._connected = false
self._connecting = false self._connecting = false
if self.closed || !self.reconnects { if self.closed || !self.reconnects {
self.didForceClose("WebSocket closed") self.didForceClose("WebSocket closed")
} else { } else if !self.reconnecting {
self.handleEvent("reconnect", data: [reason], isInternalMessage: true) self.handleEvent("reconnect", data: [reason], isInternalMessage: true)
self.tryReconnect() self.tryReconnect()
} }