diff --git a/SwiftIO/SocketEngine.swift b/SwiftIO/SocketEngine.swift index 911c12b..3dc183c 100644 --- a/SwiftIO/SocketEngine.swift +++ b/SwiftIO/SocketEngine.swift @@ -587,6 +587,7 @@ public class SocketEngine: NSObject, WebSocketDelegate { self.probing = false if self.websocket { + println(error) self.pingTimer?.invalidate() self._connected = false self._websocket = false diff --git a/SwiftIO/SocketEngineClient.swift b/SwiftIO/SocketEngineClient.swift index 22e2aab..b6fd2e3 100644 --- a/SwiftIO/SocketEngineClient.swift +++ b/SwiftIO/SocketEngineClient.swift @@ -35,7 +35,7 @@ import Foundation func parseSocketMessage(msg:String) func parseBinaryData(data:NSData) - func pollingDidFail(err:NSError?) + func pollingDidFail(err:NSError) func webSocketDidCloseWithCode(code:Int, reason:String, wasClean:Bool) func webSocketDidFailWithError(error:NSError) } \ No newline at end of file diff --git a/SwiftIO/SocketIOClient.swift b/SwiftIO/SocketIOClient.swift index 3a61d51..425d949 100644 --- a/SwiftIO/SocketIOClient.swift +++ b/SwiftIO/SocketIOClient.swift @@ -42,7 +42,7 @@ public class SocketIOClient: NSObject, SocketEngineClient { private var reconnectTimer:NSTimer? internal var currentAck = -1 - internal var waitingData = [SocketEvent]() + internal var waitingData = [SocketPacket]() public let socketURL:String public let ackQueue = dispatch_queue_create("ackQueue".cStringUsingEncoding(NSUTF8StringEncoding), @@ -244,7 +244,7 @@ public class SocketIOClient: NSObject, SocketEngineClient { } private func _emit(event:String, _ args:[AnyObject], ack:Int? = nil) { - var frame:SocketEvent + var frame:SocketPacket var str:String let (items, hasBinary, emitDatas) = SocketParser.parseEmitArgs(args) @@ -255,20 +255,20 @@ public class SocketIOClient: NSObject, SocketEngineClient { if hasBinary { if ack == nil { - str = SocketEvent.createMessageForEvent(event, withArgs: items, + str = SocketPacket.createMessageForEvent(event, withArgs: items, hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp) } else { - str = SocketEvent.createMessageForEvent(event, withArgs: items, + str = SocketPacket.createMessageForEvent(event, withArgs: items, hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp, wantsAck: ack) } self.engine?.send(str, withData: emitDatas) } else { if ack == nil { - str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false, + str = SocketPacket.createMessageForEvent(event, withArgs: items, hasBinary: false, withDatas: 0, toNamespace: self.nsp) } else { - str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false, + str = SocketPacket.createMessageForEvent(event, withArgs: items, hasBinary: false, withDatas: 0, toNamespace: self.nsp, wantsAck: ack) } @@ -289,20 +289,20 @@ public class SocketIOClient: NSObject, SocketEngineClient { if !hasBinary { if self?.nsp == nil { - str = SocketEvent.createAck(ack, withArgs: items, + str = SocketPacket.createAck(ack, withArgs: items, withAckType: 3, withNsp: "/") } else { - str = SocketEvent.createAck(ack, withArgs: items, + str = SocketPacket.createAck(ack, withArgs: items, withAckType: 3, withNsp: self!.nsp!) } self?.engine?.send(str, withData: nil) } else { if self?.nsp == nil { - str = SocketEvent.createAck(ack, withArgs: items, + str = SocketPacket.createAck(ack, withArgs: items, withAckType: 6, withNsp: "/", withBinary: emitDatas.count) } else { - str = SocketEvent.createAck(ack, withArgs: items, + str = SocketPacket.createAck(ack, withArgs: items, withAckType: 6, withNsp: self!.nsp!, withBinary: emitDatas.count) } @@ -333,7 +333,7 @@ public class SocketIOClient: NSObject, SocketEngineClient { /** Causes an event to be handled. Only use if you know what you're doing. */ - public func handleEvent(event:String, data:NSArray?, isInternalMessage:Bool = false, + public func handleEvent(event:String, data:[AnyObject]?, isInternalMessage:Bool = false, wantsAck ack:Int? = nil, withAckType ackType:Int = 3) { // println("Should do event: \(event) with data: \(data)") if !self.connected && !isInternalMessage { diff --git a/SwiftIO/SocketEvent.swift b/SwiftIO/SocketPacket.swift similarity index 76% rename from SwiftIO/SocketEvent.swift rename to SwiftIO/SocketPacket.swift index bd15dd6..7d7c063 100644 --- a/SwiftIO/SocketEvent.swift +++ b/SwiftIO/SocketPacket.swift @@ -1,5 +1,5 @@ // -// Event.swift +// SocketPacket.swift // Socket.IO-Swift // // Created by Erik Little on 1/18/15. @@ -24,21 +24,51 @@ import Foundation -class SocketEvent { - let justAck:Bool! - var ack:Int? - var args:AnyObject! - lazy var currentPlace = 0 - lazy var datas = [NSData]() - var event:String! - var placeholders:Int! +enum SocketPacketType: Int { + case CONNECT = 0 + case DISCONNECT = 1 + case EVENT = 2 + case ACK = 3 + case ERROR = 4 + case BINARY_EVENT = 5 + case BINARY_ACK = 6 - init(event:String, args:AnyObject?, placeholders:Int = 0, ackNum:Int? = nil, justAck:Bool = false) { - self.event = event - self.args = args - self.placeholders = placeholders - self.ack = ackNum - self.justAck = justAck + init(str:String) { + if let int = str.toInt() { + self = SocketPacketType(rawValue: int)! + } else { + self = SocketPacketType(rawValue: 4)! + } + } +} + +class SocketPacket { + let type:SocketPacketType + var binary = [NSData]() + var currentPlace = 0 + var data:[AnyObject]? + var id:Int? + var justAck = false + var nsp = "" + var placeholders:Int? + + init(type:SocketPacketType, data:[AnyObject]? = nil, nsp:String = "", + placeholders:Int? = nil, id:Int? = nil) { + self.type = type + self.data = data + self.nsp = nsp + self.placeholders = placeholders + self.id = id + } + + /// Only call if you know data is not nil + func createBinaryPlaceHolders() { + var strData = "\(self.data!)" + println(strData) + } + + func getEvent() -> String { + return data?.removeAtIndex(0) as String } func addData(data:NSData) -> Bool { @@ -54,7 +84,7 @@ class SocketEvent { return true } - self.datas.append(data) + self.binary.append(data) self.currentPlace++ if checkDoEvent() { @@ -174,7 +204,7 @@ class SocketEvent { newArr[i] = self.fillInDict(dict) } else if let str = arr[i] as? String { if let num = str["~~(\\d)"].groups() { - newArr[i] = self.datas[num[1].toInt()!] + newArr[i] = self.binary[num[1].toInt()!] } else { newArr[i] = arr[i] } @@ -196,7 +226,7 @@ class SocketEvent { // if it is a placeholder for data if let str = value as? String { if let num = str["~~(\\d)"].groups() { - newDict[key as String] = self.datas[num[1].toInt()!] + newDict[key as String] = self.binary[num[1].toInt()!] } else { newDict[key as String] = str } @@ -210,29 +240,25 @@ class SocketEvent { return newDict } - func fillInPlaceholders() -> NSArray? { - let argsAsArray = "[\(self.args)]" - if let parsedArr:AnyObject = SocketParser.parseData(argsAsArray) { - var returnArr = [AnyObject](count: parsedArr.count, repeatedValue: 0) - - for i in 0.. SocketPacket? { + let arr = Array(str) + let type = String(arr[0]) + + if arr.count == 1 { + return SocketPacket(type: SocketPacketType(str: type)) + } + + var id = nil as Int? + var nsp = "" + var i = 0 + var placeholders = -1 + + if type == "5" || type == "6" { + var buf = "" + + while arr[++i] != "-" { + buf += String(arr[i]) + if i == arr.count { + break + } + } + + if buf.toInt() == nil || arr[i] != "-" { + println(buf) + NSLog("Error parsing \(str)") + return nil + } else { + placeholders = buf.toInt()! + } + } + + if arr[i + 1] == "/" { + while ++i < arr.count { + let c = arr[i] + + if c == "," { + break + } + + nsp += String(c) + } + } + + if i + 1 >= arr.count { + return SocketPacket(type: SocketPacketType(str: type), + nsp: nsp, placeholders: placeholders, id: id) + } + + let next = String(arr[i + 1]) + + if next.toInt() != nil { + var c = "" + while ++i < arr.count { + if let int = String(arr[i]).toInt() { + c += String(arr[i]) + } else { + --i + break + } + } + + id = c.toInt() + } + + if i + 1 < arr.count { + let d = String(arr[++i...arr.count-1]) + let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" + + let data = SocketParser.parseData(noPlaceholders) as [AnyObject] + + return SocketPacket(type: SocketPacketType(str: type), data: data, + nsp: nsp, placeholders: placeholders, id: id) + } + + return nil + } + // Parse an NSArray looking for binary data class func parseArray(arr:NSArray, var currentPlaceholder:Int) -> (NSArray, Bool, [NSData]) { var replacementArr = [AnyObject](count: arr.count, repeatedValue: 1) @@ -186,64 +265,51 @@ class SocketParser { return } - // NSLog(stringMessage) - - let type = stringMessage.removeAtIndex(stringMessage.startIndex) - - if type == "2" { - if let groups = stringMessage["(\\/(\\w*))?,?(\\d*)?\\[\"(.*?)\",?(.*?)?\\]$", - NSRegularExpressionOptions.DotMatchesLineSeparators].groups() { - let namespace = groups[2] - let ackNum = groups[3] - let event = groups[4] - let data = "[\(groups[5])]" - - if namespace == "" && socket.nsp != nil { - return - } - - if let parsed:AnyObject? = self.parseData(data) { - if ackNum == "" { - socket.handleEvent(event, data: parsed as? NSArray) - } else { - socket.currentAck = ackNum.toInt()! - socket.handleEvent(event, data: parsed as? NSArray, wantsAck: ackNum.toInt(), withAckType: 3) - } - } + func checkNSP(nsp:String) -> Bool { + if nsp == "" && socket.nsp != nil { + return true + } else { + return false } - } else if type == "3" { - if let ackGroup = stringMessage["(\\/(\\w*))?,?(\\d*)?\\[(.*?)?\\]$", - NSRegularExpressionOptions.DotMatchesLineSeparators].groups() { - let nsp = ackGroup[2] - let ackNum = ackGroup[3] - let ackData:AnyObject? = self.parseData("[\(ackGroup[4])]") - - if nsp == "" && socket.nsp != nil { - return - } - - socket.handleAck(ackNum.toInt()!, data: ackData) - } - } else if type == "4" { - NSLog("Got Error packet") - } else if type == "5" { - self.parseBinaryMessage(stringMessage, socket: socket, type: "5") - } else if type == "6" { - self.parseBinaryMessage(stringMessage, socket: socket, type: "6") - } else if type == "0" { - if socket.nsp != nil && stringMessage == "/\(socket.nsp!)" { - socket.didConnect() + } + + var p = parseString(stringMessage) as SocketPacket! + + + if p.type == SocketPacketType.EVENT { + if checkNSP(p.nsp) { return - } else if socket.nsp != nil { + } + + socket.handleEvent(p.getEvent(), data: p.data, isInternalMessage: false, wantsAck: p.id, withAckType: 3) + } else if p.type == SocketPacketType.ACK { + if checkNSP(p.nsp) { + return + } + + socket.handleAck(p.id!, data: p.data) + } else if p.type == SocketPacketType.BINARY_EVENT { + if checkNSP(p.nsp) { + return + } + + socket.waitingData.append(p) + } else if p.type == SocketPacketType.BINARY_ACK { + if checkNSP(p.nsp) { + return + } + + socket.waitingData.append(p) + } else if p.type == SocketPacketType.CONNECT { + if p.nsp == "" && socket.nsp != nil { socket.joinNamespace() + } else if p.nsp != "" && socket.nsp == nil { + socket.didConnect() } else { socket.didConnect() - return } - } else if type == "1" { - socket.didForceClose(message: "Got disconnect") - } else { - NSLog("Error in parsing message: %s", stringMessage) + } else if p.type == SocketPacketType.DISCONNECT { + socket.didForceClose(message: "Got Disconnect") } } @@ -258,100 +324,18 @@ class SocketParser { let shouldExecute = socket.waitingData[0].addData(data) - if shouldExecute { - let socketEvent = socket.waitingData.removeAtIndex(0) - var event = socketEvent.event - - if let args:AnyObject = self.parseData(socketEvent.args as String) { - let filledInArgs = socketEvent.fillInPlaceholders() - - if socketEvent.justAck! { - // Should handle ack - socket.handleAck(socketEvent.ack!, data: filledInArgs) - return - } - - // Should do event - if socketEvent.ack != nil { - socket.handleEvent(event, data: filledInArgs, isInternalMessage: false, - wantsAck: socketEvent.ack!, withAckType: 6) - } else { - socket.handleEvent(event, data: filledInArgs) - } - } else { - let filledInArgs = socketEvent.fillInPlaceholders() - - // Should handle ack - if socketEvent.justAck! { - socket.handleAck(socketEvent.ack!, data: filledInArgs) - return - } - - // Should handle ack - if socketEvent.ack != nil { - socket.handleEvent(event, data: filledInArgs, isInternalMessage: false, - wantsAck: socketEvent.ack!, withAckType: 6) - } else { - socket.handleEvent(event, data: filledInArgs) - } - } - } - } - - // Tries to parse a message that contains binary - class func parseBinaryMessage(stringMessage:String, socket:SocketIOClient, type:String) { - // NSLog(message) - - if type == "5" { - if let groups = stringMessage["^(\\d*)-(\\/(\\w*))?,?(\\d*)?\\[\"(.*?)\",?(.*)?\\]$", - NSRegularExpressionOptions.DotMatchesLineSeparators].groups() { - let numberOfPlaceholders = groups[1] - let namespace = groups[3] - let ackNum = groups[4] - let event = groups[5] - let mutMessageObject = groups[6] - - if namespace == "" && socket.nsp != nil { - return - } - - let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] - ~= "\"~~$2\"" - - var mes:SocketEvent - if ackNum == "" { - mes = SocketEvent(event: event, args: placeholdersRemoved, - placeholders: numberOfPlaceholders.toInt()!) - } else { - socket.currentAck = ackNum.toInt()! - mes = SocketEvent(event: event, args: placeholdersRemoved, - placeholders: numberOfPlaceholders.toInt()!, ackNum: ackNum.toInt()) - } - - socket.waitingData.append(mes) - } - } else if type == "6" { - if let groups = stringMessage["^(\\d*)-(\\/(\\w*))?,?(\\d*)?\\[(.*?)?\\]$", - NSRegularExpressionOptions.DotMatchesLineSeparators].groups() { - let numberOfPlaceholders = groups[1] - let namespace = groups[3] - let ackNum = groups[4] - let mutMessageObject = groups[5] - - if namespace == "" && socket.nsp != nil { - return - } - let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] - ~= "\"~~$2\"" - - let event = SocketEvent(event: "", args: placeholdersRemoved, - placeholders: numberOfPlaceholders.toInt()!, ackNum: ackNum.toInt(), justAck: true) - - socket.waitingData.append(event) - } - } else { - NSLog("Error in parsing binary message: %s", stringMessage) + if !shouldExecute { return } + + let packet = socket.waitingData.removeAtIndex(0) + packet.fillInPlaceholders() + + if !packet.justAck { + socket.handleEvent(packet.getEvent(), data: packet.data, + wantsAck: packet.id, withAckType: 6) + } else { + socket.handleAck(packet.id!, data: packet.data) + } } }