diff --git a/SwiftIO/SocketEvent.swift b/SwiftIO/SocketEvent.swift index a275151..679044b 100644 --- a/SwiftIO/SocketEvent.swift +++ b/SwiftIO/SocketEvent.swift @@ -62,15 +62,23 @@ class SocketEvent { } class func createMessageForEvent(event:String, withArgs args:[AnyObject], - hasBinary:Bool, withDatas datas:Int = 0) -> String { + hasBinary:Bool, withDatas datas:Int = 0, toNamespace nsp:String?) -> String { var message:String var jsonSendError:NSError? if !hasBinary { - message = "42[\"\(event)\"" + if nsp == nil { + message = "42[\"\(event)\"" + } else { + message = "42/\(nsp!),[\"\(event)\"" + } } else { - message = "45\(datas)-[\"\(event)\"" + if nsp == nil { + message = "45\(datas)-[\"\(event)\"" + } else { + message = "45\(datas)-/\(nsp!),[\"\(event)\"" + } } for arg in args { diff --git a/SwiftIO/SocketIOClient.swift b/SwiftIO/SocketIOClient.swift index d1a20df..2ede5ff 100644 --- a/SwiftIO/SocketIOClient.swift +++ b/SwiftIO/SocketIOClient.swift @@ -37,10 +37,12 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { var connected = false var connecting = false var io:SRWebSocket? - var reconnnects = true + var nspString:String? + var reconnects = true var reconnecting = false var reconnectAttempts = -1 var reconnectWait = 10 + var sid:String? init(socketURL:String, opts:[String: AnyObject]? = nil) { super.init() @@ -58,7 +60,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { // Set options if opts != nil { if let reconnects = opts!["reconnects"] as? Bool { - self.reconnnects = reconnects + self.reconnects = reconnects } if let reconnectAttempts = opts!["reconnectAttempts"] as? Int { @@ -68,6 +70,10 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { if let reconnectWait = opts!["reconnectWait"] as? Int { self.reconnectWait = abs(reconnectWait) } + + if let nsp = opts!["nsp"] as? String { + self.nspString = nsp + } } } @@ -171,14 +177,15 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { if hasBinary { str = SocketEvent.createMessageForEvent(event, withArgs: items, - hasBinary: true, withDatas: emitDatas.count) + hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nspString) self.io?.send(str) for data in emitDatas { self.io?.send(data) } } else { - str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false) + str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false, + withDatas: 0, toNamespace: self.nspString) self.io?.send(str) } } @@ -198,6 +205,12 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { } } + private func joinNamespace() { + if self.nspString != nil { + self.io?.send("40/\(self.nspString!)") + } + } + // Adds handler for single arg message func on(name:String, callback:NormalCallback) { let handler = SocketEventHandler(event: name, callback: callback) @@ -338,6 +351,13 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { // println(message!) if let stringMessage = message as? String { + // Check for successful namepsace connect + if self.nspString != nil { + if stringMessage == "40/\(self.nspString!)" { + self.handleEvent(event: "connect", data: nil) + return + } + } /** Begin check for socket info frame **/ @@ -351,6 +371,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { if let json:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) { + self.sid = json!["sid"] as? String self.startPingTimer(interval: (json!["pingInterval"] as Int) / 1000) return } @@ -362,9 +383,21 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { /** Begin check for message **/ - let messageGroups = mutMessage["(\\d*)(\\[.*\\])?"].groups() - if messageGroups.count == 3 && messageGroups[1] == "42" { - let messagePart = messageGroups[2] + let messageGroups = mutMessage["(\\d*)\\/?(\\w*)?,?(\\[.*\\])?"].groups() + + if messageGroups[1] == "42" { + var namespace:String? + var messagePart:String! + + if messageGroups.count == 4 { + namespace = messageGroups[2] + messagePart = messageGroups[3] + } + + if namespace == "" && self.nspString != nil { + return + } + let messageInternals = RegexMutable(messagePart)["\\[\"(.*?)\",(.*?)?\\]$"].groups() if messageInternals != nil && messageInternals.count > 2 { let event = messageInternals[1] @@ -386,7 +419,6 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { // Turn it into a String and run it through // parseData to try and get an array. let asArray = "[\(strData)]" - if let parsed:AnyObject = SocketIOClient.parseData(asArray) { self.handleEvent(event: event, data: parsed, multipleItems: true) return @@ -412,47 +444,52 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { // Message is binary if let binary = message as? NSData { + if self.lastSocketMessage == nil { + return + } + self.parseBinaryData(binary) } } // Tries to parse a message that contains binary private func parseBinaryMessage(#message:AnyObject) { + + // println(message) if let stringMessage = message as? String { var mutMessage = RegexMutable(stringMessage) /** Begin check for binary placeholders **/ - let binaryGroup = mutMessage["(\\d*)-\\[\"(.*)\",(\\{.*\\})\\]$"].groups() + let binaryGroup = mutMessage["(\\d*)-\\/?(\\w*)?,?\\[(\".*?\"),(.*)\\]$"].groups() - // println(binaryGroup) if binaryGroup != nil { + // println(binaryGroup) + var event:String! + var mutMessageObject:NSMutableString! + var namespace:String? let messageType = RegexMutable(binaryGroup[1]) let numberOfPlaceholders = messageType["45"] ~= "" - let event = binaryGroup[2] - let mutMessageObject = RegexMutable(binaryGroup[3]) + + // Check if message came from a namespace + if binaryGroup.count == 5 { + namespace = binaryGroup[2] + event = RegexMutable(binaryGroup[3])["\""] ~= "" + mutMessageObject = RegexMutable(binaryGroup[4]) + } + + if namespace == "" && self.nspString != nil { + self.lastSocketMessage = nil + return + } + let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" + let mes = SocketEvent(event: event, args: placeholdersRemoved, placeholders: numberOfPlaceholders.integerValue) self.lastSocketMessage = mes - return - } else { - // There are multiple items in binary message - let binaryGroups = mutMessage["(\\d*)-\\[(\".*?\"),(.*)\\]$"].groups() - if binaryGroups != nil { - let messageType = RegexMutable(binaryGroups[1]) - let numberOfPlaceholders = messageType["45"] ~= "" - let event = RegexMutable(binaryGroups[2] as String)["\""] ~= "" - let mutMessageObject = RegexMutable(binaryGroups[3]) - let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] - ~= "\"~~$2\"" - let mes = SocketEvent(event: event, args: placeholdersRemoved, - placeholders: numberOfPlaceholders.integerValue) - self.lastSocketMessage = mes - return - } } /** End check for binary placeholders @@ -472,7 +509,6 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders(args) self.handleEvent(event: event, data: filledInArgs) } else { - // We have multiple items let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders() self.handleEvent(event: event, data: filledInArgs, multipleItems: true) return @@ -496,7 +532,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { private func tryReconnect(var #triesLeft:Int) { if triesLeft != -1 && triesLeft <= 0 { self.connecting = false - self.reconnnects = false + self.reconnects = false self.reconnecting = false self.handleEvent(event: "disconnect", data: "Failed to reconnect") return @@ -539,6 +575,13 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { self.connecting = false self.reconnecting = false self.connected = true + + if self.nspString != nil { + // Join namespace + self.joinNamespace() + return + } + self.handleEvent(event: "connect", data: nil) } @@ -547,7 +590,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { self.pingTimer?.invalidate() self.connected = false self.connecting = false - if self.closed || !self.reconnnects { + if self.closed || !self.reconnects { self.handleEvent(event: "disconnect", data: reason) } else { self.handleEvent(event: "reconnect", data: reason) @@ -561,7 +604,8 @@ class SocketIOClient: NSObject, SRWebSocketDelegate { self.pingTimer?.invalidate() self.connected = false self.connecting = false - if self.closed || !self.reconnnects { + self.handleEvent(event: "error", data: error.localizedDescription) + if self.closed || !self.reconnects { self.handleEvent(event: "disconnect", data: error.localizedDescription) } else if !self.reconnecting { self.handleEvent(event: "reconnect", data: error.localizedDescription)