This commit is contained in:
Erik 2015-03-21 18:16:09 -04:00
parent 6985efd7fb
commit 8b893ad85e
5 changed files with 129 additions and 243 deletions

View File

@ -476,9 +476,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
}
}
/*
Send a message with type 4
*/
/// Send an engine message (4)
public func send(msg:String, withData datas:[NSData]?) {
if self.probing {
self.probeWait.append((msg, PacketType.MESSAGE, datas))
@ -565,10 +563,10 @@ public class SocketEngine: NSObject, WebSocketDelegate {
}
if self!.websocket {
// NSLog("writing ws: \(msg):\(datas)")
// NSLog("writing ws: \(msg):\(data)")
self?.sendWebSocketMessage(msg, withType: type, datas: data)
} else {
// NSLog("writing poll: \(msg):\(datas)")
// NSLog("writing poll: \(msg):\(data)")
self?.sendPollMessage(msg, withType: type, datas: data)
}
}

View File

@ -28,10 +28,10 @@ public typealias NormalCallback = (NSArray?, AckEmitter?) -> Void
public typealias AnyHandler = (event:String, items:AnyObject?)
public typealias AckEmitter = (AnyObject...) -> Void
private func emitAckCallback(socket:SocketIOClient, num:Int, type:Int)
private func emitAckCallback(socket:SocketIOClient, num:Int)
// Curried
(items:AnyObject...) -> Void {
socket.emitAck(num, withData: items, withAckType: type)
socket.emitAck(num, withData: items)
}
class SocketEventHandler {
@ -46,7 +46,7 @@ class SocketEventHandler {
func executeCallback(_ items:NSArray? = nil, withAck ack:Int? = nil, withAckType type:Int? = nil,
withSocket socket:SocketIOClient? = nil) {
dispatch_async(dispatch_get_main_queue()) {[weak self] in
self?.callback?(items, ack != nil ? emitAckCallback(socket!, ack!, type!) : nil)
self?.callback?(items, ack != nil ? emitAckCallback(socket!, ack!) : nil)
return
}
}

View File

@ -27,22 +27,22 @@ import Foundation
public class SocketIOClient: NSObject, SocketEngineClient {
let reconnectAttempts:Int!
private lazy var params = [String: AnyObject]()
private var ackHandlers = [SocketAckHandler]()
private var ackHandlers = ContiguousArray<SocketAckHandler>()
private var anyHandler:((AnyHandler) -> Void)?
private var _closed = false
private var _connected = false
private var _connecting = false
private var currentReconnectAttempt = 0
private var forcePolling = false
private var handlers = [SocketEventHandler]()
private var handlers = ContiguousArray<SocketEventHandler>()
private var paramConnect = false
private var _secure = false
private var _sid:String?
private var _reconnecting = false
private var reconnectTimer:NSTimer?
internal var currentAck = -1
internal var waitingData = [SocketPacket]()
var currentAck = -1
var waitingData = ContiguousArray<SocketPacket>()
public let socketURL:String
public let ackQueue = dispatch_queue_create("ackQueue".cStringUsingEncoding(NSUTF8StringEncoding),
@ -62,7 +62,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
}
public var cookies:[NSHTTPCookie]?
public var engine:SocketEngine?
public var nsp:String?
public var nsp = "/"
public var reconnects = true
public var reconnecting:Bool {
return self._reconnecting
@ -244,69 +244,40 @@ public class SocketIOClient: NSObject, SocketEngineClient {
}
private func _emit(event:String, _ args:[AnyObject], ack:Int? = nil) {
var frame:SocketPacket
var str:String
let (items, hasBinary, emitDatas) = SocketParser.parseEmitArgs(args)
if !self.connected {
return
}
if hasBinary {
if ack == nil {
str = SocketPacket.createMessageForEvent(event, withArgs: items,
hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp)
} else {
str = SocketPacket.createMessageForEvent(event, withArgs: items,
hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp, wantsAck: ack)
}
self.engine?.send(str, withData: emitDatas)
let packet = SocketPacket(type: nil, data: args, nsp: self.nsp, id: ack)
var str:String
SocketParser.parseForEmit(packet)
str = packet.createMessageForEvent(event)
if packet.type == SocketPacketType.BINARY_EVENT {
self.engine?.send(str, withData: packet.binary)
} else {
if ack == nil {
str = SocketPacket.createMessageForEvent(event, withArgs: items, hasBinary: false,
withDatas: 0, toNamespace: self.nsp)
} else {
str = SocketPacket.createMessageForEvent(event, withArgs: items, hasBinary: false,
withDatas: 0, toNamespace: self.nsp, wantsAck: ack)
}
self.engine?.send(str, withData: nil)
}
}
// If the server wants to know that the client received data
func emitAck(ack:Int, withData data:[AnyObject]?, withAckType ackType:Int) {
func emitAck(ack:Int, withData args:[AnyObject]?) {
dispatch_async(self.ackQueue) {[weak self] in
if self == nil || !self!.connected || data == nil {
if self == nil || !self!.connected || args == nil {
return
}
// println("sending ack: \(ack) \(data)")
let (items, hasBinary, emitDatas) = SocketParser.parseEmitArgs(data!)
let packet = SocketPacket(type: nil, data: args, nsp: self!.nsp, id: ack)
var str:String
if !hasBinary {
if self?.nsp == nil {
str = SocketPacket.createAck(ack, withArgs: items,
withAckType: 3, withNsp: "/")
} else {
str = SocketPacket.createAck(ack, withArgs: items,
withAckType: 3, withNsp: self!.nsp!)
}
self?.engine?.send(str, withData: nil)
SocketParser.parseForEmit(packet)
str = packet.createAck()
if packet.type == SocketPacketType.BINARY_ACK {
self?.engine?.send(str, withData: packet.binary)
} else {
if self?.nsp == nil {
str = SocketPacket.createAck(ack, withArgs: items,
withAckType: 6, withNsp: "/", withBinary: emitDatas.count)
} else {
str = SocketPacket.createAck(ack, withArgs: items,
withAckType: 6, withNsp: self!.nsp!, withBinary: emitDatas.count)
}
self?.engine?.send(str, withData: emitDatas)
self?.engine?.send(str, withData: nil)
}
}
}
@ -361,8 +332,8 @@ public class SocketIOClient: NSObject, SocketEngineClient {
// Should be removed and moved to SocketEngine
func joinNamespace() {
if self.nsp != nil {
self.engine?.send("0/\(self.nsp!)", withData: nil)
if self.nsp != "/" {
self.engine?.send("0/\(self.nsp)", withData: nil)
}
}

View File

@ -43,7 +43,6 @@ enum SocketPacketType: Int {
}
class SocketPacket {
let type:SocketPacketType
var binary = [NSData]()
var currentPlace = 0
var data:[AnyObject]?
@ -51,8 +50,9 @@ class SocketPacket {
var justAck = false
var nsp = ""
var placeholders:Int?
var type:SocketPacketType?
init(type:SocketPacketType, data:[AnyObject]? = nil, nsp:String = "",
init(type:SocketPacketType?, data:[AnyObject]? = nil, nsp:String = "",
placeholders:Int? = nil, id:Int? = nil) {
self.type = type
self.data = data
@ -62,10 +62,9 @@ class SocketPacket {
}
/// Only call if you know data is not nil
func createBinaryPlaceHolders() {
var strData = "\(self.data!)"
println(strData)
}
// func createBinaryPlaceHolders() {
// var strData = "\(self.data!)"
// }
func getEvent() -> String {
return data?.removeAtIndex(0) as String
@ -95,76 +94,77 @@ class SocketPacket {
}
}
class func createMessageForEvent(event:String, withArgs args:[AnyObject],
hasBinary:Bool, withDatas datas:Int = 0, toNamespace nsp:String?, wantsAck ack:Int? = nil) -> String {
func createMessageForEvent(event:String) -> String {
var message:String
var jsonSendError:NSError?
if !hasBinary {
if nsp == nil {
if ack == nil {
if self.binary.count == 0 {
self.type = SocketPacketType.EVENT
if self.nsp == "/" {
if self.id == nil {
message = "2[\"\(event)\""
} else {
message = "2\(ack!)[\"\(event)\""
message = "2\(self.id!)[\"\(event)\""
}
} else {
if ack == nil {
message = "2/\(nsp!),[\"\(event)\""
if self.id == nil {
message = "2/\(self.nsp),[\"\(event)\""
} else {
message = "2/\(nsp!),\(ack!)[\"\(event)\""
message = "2/\(self.nsp),\(self.id!)[\"\(event)\""
}
}
} else {
if nsp == nil {
if ack == nil {
message = "5\(datas)-[\"\(event)\""
self.type = SocketPacketType.BINARY_EVENT
if self.nsp == "/" {
if self.id == nil {
message = "5\(self.binary.count)-[\"\(event)\""
} else {
message = "5\(datas)-\(ack!)[\"\(event)\""
message = "5\(self.binary.count)-\(self.id!)[\"\(event)\""
}
} else {
if ack == nil {
message = "5\(datas)-/\(nsp!),[\"\(event)\""
if self.id == nil {
message = "5\(self.binary.count)-/\(self.nsp),[\"\(event)\""
} else {
message = "5\(datas)-/\(nsp!),\(ack!)[\"\(event)\""
message = "5\(self.binary.count)-/\(self.nsp),\(self.id!)[\"\(event)\""
}
}
}
return self.completeMessage(message, args: args)
return self.completeMessage(message)
}
class func createAck(ack:Int, withArgs args:[AnyObject], withAckType ackType:Int,
withNsp nsp:String, withBinary binary:Int = 0) -> String {
func createAck() -> String {
var msg:String
if ackType == 3 {
if self.binary.count == 0 {
if nsp == "/" {
msg = "3\(ack)["
msg = "3\(self.id!)["
} else {
msg = "3/\(nsp),\(ack)["
msg = "3/\(self.nsp),\(self.id!)["
}
} else {
if nsp == "/" {
msg = "6\(binary)-\(ack)["
msg = "6\(self.binary.count)-\(self.id!)["
} else {
msg = "6\(binary)-/\(nsp),\(ack)["
msg = "6\(self.binary.count)-/\(self.nsp),\(self.id!)["
}
}
return self.completeMessage(msg, args: args, ack: true)
return self.completeMessage(msg, ack: true)
}
private class func completeMessage(var message:String, args:[AnyObject], ack:Bool = false) -> String {
func completeMessage(var message:String, ack:Bool = false) -> String {
var err:NSError?
if args.count == 0 {
if self.data == nil || self.data!.count == 0 {
return message + "]"
} else if !ack {
message += ","
}
for arg in args {
for arg in self.data! {
if arg is NSDictionary || arg is [AnyObject] {
let jsonSend = NSJSONSerialization.dataWithJSONObject(arg,

View File

@ -22,7 +22,64 @@
import Foundation
private let shredder = SocketParser.Deconstructor()
class SocketParser {
// Translation of socket.io-parser#deconstructPacket
private class Deconstructor {
var buf = [NSData]()
func ripAndTear(data:AnyObject) -> AnyObject {
if let bin = data as? NSData {
let placeholder = ["_placeholder" :true, "num": buf.count]
buf.append(bin)
return placeholder
}
if var arr = data as? [AnyObject] {
// var arr = data as [AnyObject]
for i in 0..<arr.count {
arr[i] = ripAndTear(arr[i])
}
return arr
} else if var newDict = data as? [String: AnyObject] {
// var newDict = data as [String: AnyObject]
for (key, value) in newDict {
newDict[key] = ripAndTear(value)
}
return newDict
} else {
return data
}
}
func deconstructPacket(packet:SocketPacket) {
if packet.data == nil {
return
}
var data = packet.data!
for i in 0..<data.count {
if data[i] is NSArray || data[i] is NSDictionary {
data[i] = ripAndTear(data[i])
} else if let bin = data[i] as? NSData {
data[i] = ["_placeholder" :true, "num": buf.count]
buf.append(bin)
}
}
packet.data = data
packet.binary = buf
buf.removeAll(keepCapacity: true)
}
}
// Translation of socket.io-client#decodeString
class func parseString(str:String) -> SocketPacket? {
let arr = Array(str)
@ -48,7 +105,6 @@ class SocketParser {
}
if buf.toInt() == nil || arr[i] != "-" {
println(buf)
NSLog("Error parsing \(str)")
return nil
} else {
@ -102,54 +158,6 @@ class SocketParser {
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)
var hasBinary = false
var arrayDatas = [NSData]()
for g in 0..<arr.count {
if arr[g] is NSData {
hasBinary = true
currentPlaceholder++
let sendData = arr[g] as NSData
arrayDatas.append(sendData)
replacementArr[g] = ["_placeholder": true,
"num": currentPlaceholder]
} else if let dict = arr[g] as? NSDictionary {
let (nestDict, hadBinary, dictArrs) = self.parseNSDictionary(dict,
currentPlaceholder: currentPlaceholder)
if hadBinary {
hasBinary = true
currentPlaceholder += dictArrs.count
replacementArr[g] = nestDict
arrayDatas.extend(dictArrs)
} else {
replacementArr[g] = dict
}
} else if let nestArr = arr[g] as? NSArray {
// Recursive
let (nested, hadBinary, nestDatas) = self.parseArray(nestArr,
currentPlaceholder: currentPlaceholder)
if hadBinary {
hasBinary = true
currentPlaceholder += nestDatas.count
replacementArr[g] = nested
arrayDatas.extend(nestDatas)
} else {
replacementArr[g] = arr[g]
}
} else {
replacementArr[g] = arr[g]
}
}
return (replacementArr, hasBinary, arrayDatas)
}
// Parses data for events
class func parseData(data:String) -> AnyObject? {
var err:NSError?
@ -165,116 +173,25 @@ class SocketParser {
return parsed
}
class func parseEmitArgs(args:[AnyObject]) -> ([AnyObject], Bool, [NSData]) {
var items = [AnyObject](count: args.count, repeatedValue: 1)
var currentPlaceholder = -1
var hasBinary = false
var emitDatas = [NSData]()
for i in 0..<args.count {
if let dict = args[i] as? NSDictionary {
// Check for binary data
let (newDict, hadBinary, binaryDatas) = self.parseNSDictionary(dict,
currentPlaceholder: currentPlaceholder)
if hadBinary {
currentPlaceholder += binaryDatas.count
emitDatas.extend(binaryDatas)
hasBinary = true
items[i] = newDict
} else {
items[i] = dict
}
} else if let arr = args[i] as? NSArray {
// arg is array, check for binary
let (replace, hadData, newDatas) = self.parseArray(arr,
currentPlaceholder: currentPlaceholder)
if hadData {
hasBinary = true
currentPlaceholder += newDatas.count
for data in newDatas {
emitDatas.append(data)
}
items[i] = replace
} else {
items[i] = arr
}
} else if let binaryData = args[i] as? NSData {
// args is just binary
hasBinary = true
currentPlaceholder++
items[i] = ["_placeholder": true, "num": currentPlaceholder]
emitDatas.append(binaryData)
} else {
items[i] = args[i]
}
}
return (items, hasBinary, emitDatas)
}
// Parses a NSDictionary, looking for NSData objects
class func parseNSDictionary(dict:NSDictionary, var currentPlaceholder:Int) -> (NSDictionary, Bool, [NSData]) {
var returnDict = NSMutableDictionary()
var hasBinary = false
var returnDatas = [NSData]()
for (key, value) in dict {
if let binaryData = value as? NSData {
currentPlaceholder++
hasBinary = true
returnDatas.append(binaryData)
returnDict[key as String] = ["_placeholder": true, "num": currentPlaceholder]
} else if let arr = value as? NSArray {
let (replace, hadBinary, arrDatas) = self.parseArray(arr, currentPlaceholder: currentPlaceholder)
if hadBinary {
hasBinary = true
returnDict[key as String] = replace
currentPlaceholder += arrDatas.count
returnDatas.extend(arrDatas)
} else {
returnDict[key as String] = arr
}
} else if let dict = value as? NSDictionary {
// Recursive
let (nestDict, hadBinary, nestDatas) = self.parseNSDictionary(dict, currentPlaceholder: currentPlaceholder)
if hadBinary {
hasBinary = true
returnDict[key as String] = nestDict
currentPlaceholder += nestDatas.count
returnDatas.extend(nestDatas)
} else {
returnDict[key as String] = dict
}
} else {
returnDict[key as String] = value
}
}
return (returnDict, hasBinary, returnDatas)
class func parseForEmit(packet:SocketPacket) {
shredder.deconstructPacket(packet)
}
// Parses messages recieved
class func parseSocketMessage(var stringMessage:String, socket:SocketIOClient) {
class func parseSocketMessage(stringMessage:String, socket:SocketIOClient) {
if stringMessage == "" {
return
}
func checkNSP(nsp:String) -> Bool {
if nsp == "" && socket.nsp != nil {
if nsp == "" && socket.nsp != "/" {
return true
} else {
return false
}
}
var p = parseString(stringMessage) as SocketPacket!
let p = parseString(stringMessage) as SocketPacket!
if p.type == SocketPacketType.EVENT {
if checkNSP(p.nsp) {
@ -302,9 +219,9 @@ class SocketParser {
p.justAck = true
socket.waitingData.append(p)
} else if p.type == SocketPacketType.CONNECT {
if p.nsp == "" && socket.nsp != nil {
if p.nsp == "" && socket.nsp != "/" {
socket.joinNamespace()
} else if p.nsp != "" && socket.nsp == nil {
} else if p.nsp != "" && socket.nsp == "/" {
socket.didConnect()
} else {
socket.didConnect()