merge master

This commit is contained in:
Erik 2015-03-27 12:41:49 -04:00
commit a61f1c8484
7 changed files with 123 additions and 85 deletions

View File

@ -72,7 +72,8 @@ let socket = SocketIOClient(socketURL: "https://localhost:8080", opts: [
"reconnectAttempts": 5, // Default is -1 (infinite tries) "reconnectAttempts": 5, // Default is -1 (infinite tries)
"reconnectWait": 5, // Default is 10 "reconnectWait": 5, // Default is 10
"nsp": "swift", // connects to the specified namespace. Default is / "nsp": "swift", // connects to the specified namespace. Default is /
"forcePolling": true, // if true, the socket will only use XHR polling, Default is false (polling/WebSockets) "forcePolling": true, // if true the client will only use XHR polling, Default is false (polling/WebSockets)
"forceWebsockets": false, // if true the client will only use WebSockets. Trumps forcePolling. Default is false. (polling/WebSockets)
"cookies": nil // An array of NSHTTPCookies. Passed during handshake. Default is nil "cookies": nil // An array of NSHTTPCookies. Passed during handshake. Default is nil
]) ])

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "Socket.IO-Client-Swift" s.name = "Socket.IO-Client-Swift"
s.version = "1.4.2" s.version = "1.4.3"
s.summary = "Socket.IO-client for Swift" s.summary = "Socket.IO-client for Swift"
s.description = <<-DESC s.description = <<-DESC
Socket.IO-client for Swift. Socket.IO-client for Swift.
@ -12,7 +12,7 @@ Pod::Spec.new do |s|
s.author = { "Erik" => "nuclear.ace@gmail.com" } s.author = { "Erik" => "nuclear.ace@gmail.com" }
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.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.4.2' } s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.4.3' }
s.source_files = "SwiftIO/**/*.swift" s.source_files = "SwiftIO/**/*.swift"
s.requires_arc = true s.requires_arc = true
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files # s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files

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
@ -196,7 +209,10 @@ public class SocketEngine: NSObject, WebSocketDelegate {
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
@ -307,6 +323,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 {
@ -314,57 +338,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
reqPolling.allHTTPHeaderFields = headers reqPolling.allHTTPHeaderFields = headers
} }
self.session.dataTaskWithRequest(reqPolling) {[weak self] data, res, err in self.doRequest(reqPolling)
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
@ -413,7 +387,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
if msg.length != 0 { if msg.length != 0 {
// Be sure to capture the value of the msg // Be sure to capture the value of the msg
dispatch_async(self.handleQueue) {[weak self, msg] in dispatch_async(self.handleQueue) {[weak self, msg] in
self?.parseEngineMessage(msg) self?.parseEngineMessage(msg, fromPolling: true)
return return
} }
} }
@ -431,9 +405,9 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
} }
private func parseEngineMessage(var message:String) { private func parseEngineMessage(var message:String, fromPolling:Bool) {
// NSLog("Engine got message: \(message)") // NSLog("Engine got message: \(message)")
if self.polling { if fromPolling {
fixDoubleUTF8(&message) fixDoubleUTF8(&message)
} }
@ -466,6 +440,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")
}
self.startPingTimer()
if !self.forceWebsockets {
self.doPoll()
}
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")
@ -588,8 +596,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?) {
@ -600,15 +615,17 @@ 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()
} }
} }
public func websocketDidReceiveMessage(socket:WebSocket, text:String) { public func websocketDidReceiveMessage(socket:WebSocket, text:String) {
self.parseEngineMessage(text) self.parseEngineMessage(text, fromPolling: false)
} }
public func websocketDidReceiveData(socket:WebSocket, data:NSData) { public func websocketDidReceiveData(socket:WebSocket, data:NSData) {

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
@ -102,7 +103,11 @@ public class SocketIOClient: NSObject, SocketEngineClient {
self.reconnectWait = abs(reconnectWait) self.reconnectWait = abs(reconnectWait)
} }
if let nsp = opts!["nsp"] as? String { if var nsp = opts!["nsp"] as? String {
if nsp != "/" && nsp.hasPrefix("/") {
nsp.removeAtIndex(nsp.startIndex)
}
self.nsp = nsp self.nsp = nsp
} }
@ -110,6 +115,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 +136,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 +162,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 +179,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
@ -334,7 +352,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
Causes an event to be handled. Only use if you know what you're doing. Causes an event to be handled. Only use if you know what you're doing.
*/ */
public func handleEvent(event:String, data:[AnyObject]?, isInternalMessage:Bool = false, public func handleEvent(event:String, data:[AnyObject]?, isInternalMessage:Bool = false,
wantsAck ack:Int? = nil, withAckType ackType:Int = 3) { wantsAck ack:Int? = nil) {
// println("Should do event: \(event) with data: \(data)") // println("Should do event: \(event) with data: \(data)")
if !self.connected && !isInternalMessage { if !self.connected && !isInternalMessage {
return return
@ -350,8 +368,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
for handler in self.handlers { for handler in self.handlers {
if handler.event == event { if handler.event == event {
if ack != nil { if ack != nil {
handler.executeCallback(data, withAck: ack!, handler.executeCallback(data, withAck: ack!, withSocket: self)
withAckType: ackType, withSocket: self)
} else { } else {
handler.executeCallback(data) handler.executeCallback(data)
} }
@ -452,12 +469,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()
} }

View File

@ -134,12 +134,16 @@ class SocketPacket {
var msg:String var msg:String
if self.binary.count == 0 { if self.binary.count == 0 {
self.type = SocketPacketType.ACK
if nsp == "/" { if nsp == "/" {
msg = "3\(self.id!)[" msg = "3\(self.id!)["
} else { } else {
msg = "3/\(self.nsp),\(self.id!)[" msg = "3/\(self.nsp),\(self.id!)["
} }
} else { } else {
self.type = SocketPacketType.BINARY_ACK
if nsp == "/" { if nsp == "/" {
msg = "6\(self.binary.count)-\(self.id!)[" msg = "6\(self.binary.count)-\(self.id!)["
} else { } else {
@ -194,8 +198,6 @@ class SocketPacket {
if let str = self.data?[i] as? String { if let str = self.data?[i] as? String {
if let num = str["~~(\\d)"].groups() { if let num = str["~~(\\d)"].groups() {
newArr[i] = self.binary[num[1].toInt()!] newArr[i] = self.binary[num[1].toInt()!]
} else {
newArr[i] = str
} }
} else if self.data?[i] is NSDictionary || self.data?[i] is NSArray { } else if self.data?[i] is NSDictionary || self.data?[i] is NSArray {
newArr[i] = self._fillInPlaceholders(self.data![i]) newArr[i] = self._fillInPlaceholders(self.data![i])

View File

@ -197,7 +197,8 @@ class SocketParser {
return return
} }
socket.handleEvent(p.getEvent(), data: p.data, isInternalMessage: false, wantsAck: p.id, withAckType: 3) socket.handleEvent(p.getEvent(), data: p.data,
isInternalMessage: false, wantsAck: p.id)
} else if p.type == SocketPacketType.ACK { } else if p.type == SocketPacketType.ACK {
if checkNSP(p.nsp) { if checkNSP(p.nsp) {
return return
@ -250,7 +251,7 @@ class SocketParser {
if !packet.justAck { if !packet.justAck {
socket.handleEvent(packet.getEvent(), data: packet.data, socket.handleEvent(packet.getEvent(), data: packet.data,
wantsAck: packet.id, withAckType: 6) wantsAck: packet.id)
} else { } else {
socket.handleAck(packet.id!, data: packet.data) socket.handleAck(packet.id!, data: packet.data)
} }