From 76637d160e08c82ad3f602a3866f2a65b91f9d8b Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 19 Jun 2015 08:00:09 -0400 Subject: [PATCH] use struct for socketpacket --- SocketIOClientSwift/SocketEngine.swift | 12 +- SocketIOClientSwift/SocketIOClient.swift | 14 +- SocketIOClientSwift/SocketPacket.swift | 487 ++++++++++++++++++----- SocketIOClientSwift/SocketParser.swift | 103 +---- 4 files changed, 413 insertions(+), 203 deletions(-) diff --git a/SocketIOClientSwift/SocketEngine.swift b/SocketIOClientSwift/SocketEngine.swift index f449252..384cf95 100644 --- a/SocketIOClientSwift/SocketEngine.swift +++ b/SocketIOClientSwift/SocketEngine.swift @@ -25,7 +25,7 @@ import Foundation public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient { - private typealias Probe = (msg:String, type:PacketType, data:ContiguousArray?) + private typealias Probe = (msg:String, type:PacketType, data:[NSData]?) private typealias ProbeWaitQueue = [Probe] private let allowedCharacterSet = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?%#[]\" {}").invertedSet @@ -579,7 +579,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient { } /// Send an engine message (4) - public func send(msg:String, withData datas:ContiguousArray?) { + public func send(msg:String, withData datas:[NSData]?) { if probing { probeWait.append((msg, PacketType.MESSAGE, datas)) } else { @@ -602,7 +602,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient { /// Send polling message. /// Only call on emitQueue private func sendPollMessage(var msg:String, withType type:PacketType, - datas:ContiguousArray? = nil) { + datas:[NSData]? = nil) { SocketLogger.log("Sending poll: %@ as type: %@", client: self, args: msg, type.rawValue) doubleEncodeUTF8(&msg) @@ -626,7 +626,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient { /// Send message on WebSockets /// Only call on emitQueue private func sendWebSocketMessage(str:String, withType type:PacketType, - datas:ContiguousArray? = nil) { + datas:[NSData]? = nil) { SocketLogger.log("Sending ws: %@ as type: %@", client: self, args: str, type.rawValue) ws?.writeString("\(type.rawValue)\(str)") @@ -674,7 +674,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient { /** Write a message, independent of transport. */ - public func write(msg:String, withType type:PacketType, withData data:ContiguousArray?) { + public func write(msg:String, withType type:PacketType, withData data:[NSData]?) { dispatch_async(emitQueue) {[weak self] in if let this = self where this.connected { if this.websocket { @@ -695,7 +695,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient { */ public func writeObjc(msg:String, withType type:Int, withData data:NSArray?) { if let pType = PacketType(rawValue: type) { - var arr = ContiguousArray() + var arr = [NSData]() if data != nil { for d in data! { diff --git a/SocketIOClientSwift/SocketIOClient.swift b/SocketIOClientSwift/SocketIOClient.swift index f8aca1c..662d8df 100644 --- a/SocketIOClientSwift/SocketIOClient.swift +++ b/SocketIOClientSwift/SocketIOClient.swift @@ -312,11 +312,8 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient return } - let packet = SocketPacket(type: nil, data: args, nsp: nsp, id: ack) - let str:String - - SocketParser.parseForEmit(packet) - str = packet.createMessageForEvent(event) + let packet = SocketPacket.packetFromEmitWithData(args, id: ack ?? -1, nsp: nsp) + let str = packet.createMessageForEvent(event) SocketLogger.log("Emitting: %@", client: self, args: str) @@ -331,11 +328,8 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient func emitAck(ack:Int, withData args:[AnyObject]) { dispatch_async(emitQueue) {[weak self] in if let this = self where this.connected { - let packet = SocketPacket(type: nil, data: args, nsp: this.nsp, id: ack) - let str:String - - SocketParser.parseForEmit(packet) - str = packet.createAck() + let packet = SocketPacket.packetFromEmitWithData(args, id: ack ?? -1, nsp: this.nsp) + let str = packet.createAck() SocketLogger.log("Emitting Ack: %@", client: this, args: str) diff --git a/SocketIOClientSwift/SocketPacket.swift b/SocketIOClientSwift/SocketPacket.swift index 0f4260c..9270d5a 100644 --- a/SocketIOClientSwift/SocketPacket.swift +++ b/SocketIOClientSwift/SocketPacket.swift @@ -24,27 +24,7 @@ import Foundation -final class SocketPacket: CustomStringConvertible { - var binary = ContiguousArray() - var currentPlace = 0 - var data:[AnyObject]? - var description:String { - var better = "SocketPacket {type: ~~0; data: ~~1; " + - "id: ~~2; placeholders: ~~3;}" - - better = better["~~0"] ~= (type != nil ? String(type!.rawValue) : "nil") - better = better["~~1"] ~= (data != nil ? "\(data!)" : "nil") - better = better["~~2"] ~= (id != nil ? String(id!) : "nil") - better = better["~~3"] ~= (placeholders != nil ? String(placeholders!) : "nil") - - return better - } - var id:Int? - var justAck = false - var nsp = "" - var placeholders:Int? - var type:PacketType? - +struct SocketPacket { enum PacketType:Int { case CONNECT = 0 case DISCONNECT = 1 @@ -63,20 +43,69 @@ final class SocketPacket: CustomStringConvertible { } } - init(type:PacketType?, 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 + var currentPlace = 0 + var binary:[NSData] + var data:[AnyObject] + var id:Int = -1 + var nsp = "" + var justAck = false + var placeholders:Int + var type:PacketType + var description:String { + var better = "SocketPacket {type: ~~0; data: ~~1; " + + "id: ~~2; placeholders: ~~3;}" + + better = better["~~0"] ~= String(type.rawValue) + better = better["~~1"] ~= String(data) + better = better["~~2"] ~= String(id) + better = better["~~3"] ~= String(placeholders) + + return better + } + + init(type:SocketPacket.PacketType, data:[AnyObject] = [AnyObject](), id:Int = -1, + nsp:String, placeholders:Int = 0, binary:[NSData] = [NSData]()) { + self.data = data + self.id = id + self.nsp = nsp + self.type = type + self.placeholders = placeholders + self.binary = binary + } + + static func packetFromEmitWithData(data:[AnyObject], id:Int, nsp:String) -> SocketPacket { + func findType(num:Int) -> SocketPacket.PacketType { + switch num { + case 0: + return SocketPacket.PacketType.EVENT + default: + return SocketPacket.PacketType.BINARY_EVENT + } + } + + let (parsedData, binary) = deconstructData(data) + let packet = SocketPacket(type: findType(binary.count), data: parsedData, + id: id, nsp: nsp, placeholders: -1, binary: binary) + + return packet } func getEvent() -> String { - return data?.removeAtIndex(0) as! String + return data[0] as! String } - func addData(data:NSData) -> Bool { + func getArgs() -> [AnyObject]? { + var arr = data + + if data.count == 0 { + return nil + } else { + arr.removeAtIndex(0) + return arr + } + } + + mutating func addData(data:NSData) -> Bool { if placeholders == currentPlace { return true } @@ -92,83 +121,19 @@ final class SocketPacket: CustomStringConvertible { } } - func createMessageForEvent(event:String) -> String { - let message:String - - if binary.count == 0 { - type = PacketType.EVENT - - if nsp == "/" { - if id == nil { - message = "2[\"\(event)\"" - } else { - message = "2\(id!)[\"\(event)\"" - } - } else { - if id == nil { - message = "2/\(nsp),[\"\(event)\"" - } else { - message = "2/\(nsp),\(id!)[\"\(event)\"" - } - } - } else { - type = PacketType.BINARY_EVENT - - if nsp == "/" { - if id == nil { - message = "5\(binary.count)-[\"\(event)\"" - } else { - message = "5\(binary.count)-\(id!)[\"\(event)\"" - } - } else { - if id == nil { - message = "5\(binary.count)-/\(nsp),[\"\(event)\"" - } else { - message = "5\(binary.count)-/\(nsp),\(id!)[\"\(event)\"" - } - } - } - - return completeMessage(message) - } - - func createAck() -> String { - var msg:String - - if binary.count == 0 { - type = PacketType.ACK - - if nsp == "/" { - msg = "3\(id!)[" - } else { - msg = "3/\(nsp),\(id!)[" - } - } else { - type = PacketType.BINARY_ACK - - if nsp == "/" { - msg = "6\(binary.count)-\(id!)[" - } else { - msg = "6\(binary.count)-/\(nsp),\(id!)[" - } - } - - return completeMessage(msg, ack: true) - } - private func completeMessage(var message:String, ack:Bool = false) -> String { - if data == nil || data!.count == 0 { + if data.count == 0 { return message + "]" } else if !ack { message += "," } - for arg in data! { + for arg in data { if arg is NSDictionary || arg is [AnyObject] { let jsonSend: NSData? do { jsonSend = try NSJSONSerialization.dataWithJSONObject(arg, - options: NSJSONWritingOptions(rawValue: 0)) + options: NSJSONWritingOptions(rawValue: 0)) } catch { jsonSend = nil } @@ -194,21 +159,78 @@ final class SocketPacket: CustomStringConvertible { return message + "]" } - func fillInPlaceholders() { - let newArr = NSMutableArray(array: data!) + func createAck() -> String { + var msg:String - for i in 0.. String { + let message:String + + if binary.count == 0 { + if nsp == "/" { + if id == -1 { + message = "2[\"\(event)\"" + } else { + message = "2\(id)[\"\(event)\"" + } + } else { + if id == -1 { + message = "2/\(nsp),[\"\(event)\"" + } else { + message = "2/\(nsp),\(id)[\"\(event)\"" + } + } + } else { + if nsp == "/" { + if id == -1 { + message = "5\(binary.count)-[\"\(event)\"" + } else { + message = "5\(binary.count)-\(id)[\"\(event)\"" + } + } else { + if id == -1 { + message = "5\(binary.count)-/\(nsp),[\"\(event)\"" + } else { + message = "5\(binary.count)-/\(nsp),\(id)[\"\(event)\"" + } + } + } + + return completeMessage(message) + } + + mutating func fillInPlaceholders() { + let newArr = NSMutableArray(array: data) + + for i in 0.. AnyObject { + private mutating func _fillInPlaceholders(data:AnyObject) -> AnyObject { if let str = data as? String { if let num = str["~~(\\d)"].groups() { return binary[Int(num[1])!] @@ -235,4 +257,261 @@ final class SocketPacket: CustomStringConvertible { return data } } + + + private static func shred(data:AnyObject, inout binary:[NSData]) -> AnyObject { + if let bin = data as? NSData { + let placeholder = ["_placeholder" :true, "num": binary.count] + + binary.append(bin) + + return placeholder + } else if let arr = data as? NSArray { + let newArr = NSMutableArray(array: arr) + + for i in 0.. ([AnyObject], [NSData]) { + var binary = [NSData]() + + for i in 0..() +// var currentPlace = 0 +// var data:[AnyObject]? +// var description:String { +// var better = "SocketPacket {type: ~~0; data: ~~1; " + +// "id: ~~2; placeholders: ~~3;}" +// +// better = better["~~0"] ~= (type != nil ? String(type!.rawValue) : "nil") +// better = better["~~1"] ~= (data != nil ? "\(data!)" : "nil") +// better = better["~~2"] ~= (id != nil ? String(id!) : "nil") +// better = better["~~3"] ~= (placeholders != nil ? String(placeholders!) : "nil") +// +// return better +// } +// var id:Int? +// var justAck = false +// var nsp = "" +// var placeholders:Int? +// var type:PacketType? +// +// enum PacketType: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?(str:String) { +// if let int = Int(str), raw = PacketType(rawValue: int) { +// self = raw +// } else { +// return nil +// } +// } +// } +// +// init(type:PacketType?, 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 +// } +// +// func getEvent() -> String { +// return data?.removeAtIndex(0) as! String +// } +// +// func addData(data:NSData) -> Bool { +// if placeholders == currentPlace { +// return true +// } +// +// binary.append(data) +// currentPlace++ +// +// if placeholders == currentPlace { +// currentPlace = 0 +// return true +// } else { +// return false +// } +// } +// +// func createMessageForEvent(event:String) -> String { +// let message:String +// +// if binary.count == 0 { +// type = PacketType.EVENT +// +// if nsp == "/" { +// if id == nil { +// message = "2[\"\(event)\"" +// } else { +// message = "2\(id!)[\"\(event)\"" +// } +// } else { +// if id == nil { +// message = "2/\(nsp),[\"\(event)\"" +// } else { +// message = "2/\(nsp),\(id!)[\"\(event)\"" +// } +// } +// } else { +// type = PacketType.BINARY_EVENT +// +// if nsp == "/" { +// if id == nil { +// message = "5\(binary.count)-[\"\(event)\"" +// } else { +// message = "5\(binary.count)-\(id!)[\"\(event)\"" +// } +// } else { +// if id == nil { +// message = "5\(binary.count)-/\(nsp),[\"\(event)\"" +// } else { +// message = "5\(binary.count)-/\(nsp),\(id!)[\"\(event)\"" +// } +// } +// } +// +// return completeMessage(message) +// } +// +// func createAck() -> String { +// var msg:String +// +// if binary.count == 0 { +// type = PacketType.ACK +// +// if nsp == "/" { +// msg = "3\(id!)[" +// } else { +// msg = "3/\(nsp),\(id!)[" +// } +// } else { +// type = PacketType.BINARY_ACK +// +// if nsp == "/" { +// msg = "6\(binary.count)-\(id!)[" +// } else { +// msg = "6\(binary.count)-/\(nsp),\(id!)[" +// } +// } +// +// return completeMessage(msg, ack: true) +// } + +// private func completeMessage(var message:String, ack:Bool = false) -> String { +// if data == nil || data!.count == 0 { +// return message + "]" +// } else if !ack { +// message += "," +// } +// +// for arg in data! { +// if arg is NSDictionary || arg is [AnyObject] { +// let jsonSend: NSData? +// do { +// jsonSend = try NSJSONSerialization.dataWithJSONObject(arg, +// options: NSJSONWritingOptions(rawValue: 0)) +// } catch { +// jsonSend = nil +// } +// let jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding) +// +// message += jsonString! as String + "," +// } else if var str = arg as? String { +// str = str["\n"] ~= "\\\\n" +// str = str["\r"] ~= "\\\\r" +// +// message += "\"\(str)\"," +// } else if arg is NSNull { +// message += "null," +// } else { +// message += "\(arg)," +// } +// } +// +// if message != "" { +// message.removeAtIndex(message.endIndex.predecessor()) +// } +// +// return message + "]" +// } +// +// func fillInPlaceholders() { +// let newArr = NSMutableArray(array: data!) +// +// for i in 0.. AnyObject { +// if let str = data as? String { +// if let num = str["~~(\\d)"].groups() { +// return binary[Int(num[1])!] +// } else { +// return str +// } +// } else if let dict = data as? NSDictionary { +// let newDict = NSMutableDictionary(dictionary: dict) +// +// for (key, value) in dict { +// newDict[key as! NSCopying] = _fillInPlaceholders(value) +// } +// +// return newDict +// } else if let arr = data as? NSArray { +// let newArr = NSMutableArray(array: arr) +// +// for i in 0..() - - func shred(data:AnyObject) -> AnyObject { - if let bin = data as? NSData { - let placeholder = ["_placeholder" :true, "num": buf.count] - - buf.append(bin) - - return placeholder - } else if let arr = data as? NSArray { - let newArr = NSMutableArray(array: arr) - - for i in 0.. Bool { return nsp == "" && socket.nsp != "/" } @@ -88,7 +32,7 @@ class SocketParser { return } - socket.handleAck(p.id!, data: p.data) + socket.handleAck(p.id, data: p.data) } private static func handleBinaryAck(p:SocketPacket, socket:SocketIOClient) { @@ -96,7 +40,6 @@ class SocketParser { return } - p.justAck = true socket.waitingData.append(p) } @@ -123,7 +66,7 @@ class SocketParser { return } - socket.handleEvent(p.getEvent(), data: p.data, + socket.handleEvent(p.getEvent(), data: p.getArgs(), isInternalMessage: false, wantsAck: p.id) } @@ -133,7 +76,7 @@ class SocketParser { let type = String(arr[0]) if arr.count == 1 { - return SocketPacket(type: SocketPacket.PacketType(str: type)) + return SocketPacket(type: SocketPacket.PacketType(str: type)!, nsp: "/") } var id = nil as Int? @@ -172,8 +115,8 @@ class SocketParser { } if i + 1 >= arr.count { - return SocketPacket(type: SocketPacket.PacketType(str: type), - nsp: nsp, placeholders: placeholders, id: id) + return SocketPacket(type: SocketPacket.PacketType(str: type)!, id: id ?? -1, + nsp: nsp, placeholders: placeholders) } let next = String(arr[i + 1]) @@ -197,8 +140,8 @@ class SocketParser { let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" let data = SocketParser.parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders] - return SocketPacket(type: SocketPacket.PacketType(str: type), data: data, - nsp: nsp, placeholders: placeholders, id: id) + return SocketPacket(type: SocketPacket.PacketType(str: type)!, data: data, id: id ?? -1, + nsp: nsp, placeholders: placeholders) } return nil @@ -225,10 +168,6 @@ class SocketParser { return parsed } - static func parseForEmit(packet:SocketPacket) { - shredder.deconstructPacket(packet) - } - // Parses messages recieved static func parseSocketMessage(stringMessage:String, socket:SocketIOClient) { if stringMessage == "" { @@ -246,25 +185,23 @@ class SocketParser { return } - SocketLogger.log("Decoded packet as: %@", client: socket, altType: "SocketParser", args: p) + SocketLogger.log("Decoded packet as: %@", client: socket, altType: "SocketParser", args: p.description) switch p.type { - case SocketPacket.PacketType.EVENT?: + case SocketPacket.PacketType.EVENT: handleEvent(p, socket: socket) - case SocketPacket.PacketType.ACK?: + case SocketPacket.PacketType.ACK: handleAck(p, socket: socket) - case SocketPacket.PacketType.BINARY_EVENT?: + case SocketPacket.PacketType.BINARY_EVENT: handleBinaryEvent(p, socket: socket) - case SocketPacket.PacketType.BINARY_ACK?: + case SocketPacket.PacketType.BINARY_ACK: handleBinaryAck(p, socket: socket) - case SocketPacket.PacketType.CONNECT?: + case SocketPacket.PacketType.CONNECT: handleConnect(p, socket: socket) - case SocketPacket.PacketType.DISCONNECT?: + case SocketPacket.PacketType.DISCONNECT: socket.didDisconnect("Got Disconnect") - case SocketPacket.PacketType.ERROR?: - socket.didError(p.data == nil ? "Error" : p.data!) - case nil: - SocketLogger.err("Got packet with invalid packet type", client: socket) + case SocketPacket.PacketType.ERROR: + socket.didError("Error: \(p.data)") } } @@ -280,14 +217,14 @@ class SocketParser { return } - let packet = socket.waitingData.removeAtIndex(0) + var packet = socket.waitingData.removeAtIndex(0) packet.fillInPlaceholders() if !packet.justAck { - socket.handleEvent(packet.getEvent(), data: packet.data, + socket.handleEvent(packet.getEvent(), data: packet.getArgs(), wantsAck: packet.id) } else { - socket.handleAck(packet.id!, data: packet.data) + socket.handleAck(packet.id, data: packet.getArgs()) } } }