add namespace support, needs further testing

This commit is contained in:
Erik 2015-02-04 16:13:57 -05:00
parent 40c70925cc
commit 747a244435
2 changed files with 87 additions and 35 deletions

View File

@ -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 {

View File

@ -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)