handle acks from the server
This commit is contained in:
parent
12b8f3ef1f
commit
3754bd572a
@ -18,9 +18,10 @@ Methods
|
|||||||
-------
|
-------
|
||||||
1. `socket.on(name:String, callback:((data:AnyObject?) -> Void)) -> SocketAckHandler` - Adds a handler for an event. Returns a SocketAckHandler which can be used to ack an event. See example.
|
1. `socket.on(name:String, callback:((data:AnyObject?) -> Void)) -> SocketAckHandler` - Adds a handler for an event. Returns a SocketAckHandler which can be used to ack an event. See example.
|
||||||
2. `socket.onMultipleItems(name:String, callback:((data:NSArray?) -> Void)) -> SocketAckHandler` - Adds a handler for an event that can have multiple items. Items are stored in an array. Returns a SocketAckHandler which can be used to ack an event. See example.
|
2. `socket.onMultipleItems(name:String, callback:((data:NSArray?) -> Void)) -> SocketAckHandler` - Adds a handler for an event that can have multiple items. Items are stored in an array. Returns a SocketAckHandler which can be used to ack an event. See example.
|
||||||
3. `socket.emit(event:String, args:AnyObject...) -> SocketAckHandler` - Sends a message. Can send multiple args. Returns a SocketAckHandler that can be used to request an ack. See example.
|
3. `socket.emit(event:String, args:AnyObject...)` - Sends a message. Can send multiple args.
|
||||||
4. `socket.connect()` - Establishes a connection to the server. A "connect" event is fired upon successful connection.
|
4. `socket.emitWithAck(event:String, args:AnyObject...) -> SocketAckHandler` - Sends a message that requests an acknoweldgement from the server. Returns a SocketAckHandler which you can use to add an onAck handler. See example.
|
||||||
5. `socket.close()` - Closes the socket. Once a socket is closed it should not be reopened.
|
5. `socket.connect()` - Establishes a connection to the server. A "connect" event is fired upon successful connection.
|
||||||
|
6. `socket.close()` - Closes the socket. Once a socket is closed it should not be reopened.
|
||||||
|
|
||||||
Events
|
Events
|
||||||
------
|
------
|
||||||
|
|||||||
@ -24,14 +24,16 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
typealias AckCallback = ([AnyObject]?) -> Void
|
typealias AckCallback = (AnyObject?) -> Void
|
||||||
|
|
||||||
class SocketAckHandler {
|
class SocketAckHandler {
|
||||||
|
let ackNum:Int!
|
||||||
let event:String!
|
let event:String!
|
||||||
var ackData:[AnyObject]?
|
var ackData:[AnyObject]?
|
||||||
var callback:AckCallback?
|
var callback:AckCallback?
|
||||||
|
|
||||||
init(event:String) {
|
init(event:String, ackNum:Int = 0) {
|
||||||
|
self.ackNum = ackNum
|
||||||
self.event = event
|
self.event = event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class SocketEvent {
|
class SocketEvent {
|
||||||
|
let justAck:Bool!
|
||||||
var ack:Int?
|
var ack:Int?
|
||||||
var args:AnyObject!
|
var args:AnyObject!
|
||||||
lazy var currentPlace = 0
|
lazy var currentPlace = 0
|
||||||
@ -32,11 +33,12 @@ class SocketEvent {
|
|||||||
var event:String!
|
var event:String!
|
||||||
var placeholders:Int!
|
var placeholders:Int!
|
||||||
|
|
||||||
init(event:String, args:AnyObject?, placeholders:Int = 0, ack:Int? = nil) {
|
init(event:String, args:AnyObject?, placeholders:Int = 0, ackNum:Int? = nil, justAck:Bool = false) {
|
||||||
self.event = event
|
self.event = event
|
||||||
self.args = args
|
self.args = args
|
||||||
self.placeholders = placeholders
|
self.placeholders = placeholders
|
||||||
self.ack = ack
|
self.ack = ackNum
|
||||||
|
self.justAck = justAck
|
||||||
}
|
}
|
||||||
|
|
||||||
func addData(data:NSData) -> Bool {
|
func addData(data:NSData) -> Bool {
|
||||||
@ -64,22 +66,38 @@ class SocketEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func createMessageForEvent(event:String, withArgs args:[AnyObject],
|
static func createMessageForEvent(event:String, withArgs args:[AnyObject],
|
||||||
hasBinary:Bool, withDatas datas:Int = 0, toNamespace nsp:String?) -> String {
|
hasBinary:Bool, withDatas datas:Int = 0, toNamespace nsp:String?, wantsAck ack:Int? = nil) -> String {
|
||||||
|
|
||||||
var message:String
|
var message:String
|
||||||
var jsonSendError:NSError?
|
var jsonSendError:NSError?
|
||||||
|
|
||||||
if !hasBinary {
|
if !hasBinary {
|
||||||
if nsp == nil {
|
if nsp == nil {
|
||||||
message = "42[\"\(event)\","
|
if ack == nil {
|
||||||
|
message = "42[\"\(event)\","
|
||||||
|
} else {
|
||||||
|
message = "42\(ack!)[\"\(event)\","
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message = "42/\(nsp!),[\"\(event)\","
|
if ack == nil {
|
||||||
|
message = "42/\(nsp!),[\"\(event)\","
|
||||||
|
} else {
|
||||||
|
message = "42/\(nsp!),\(ack!)[\"\(event)\","
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if nsp == nil {
|
if nsp == nil {
|
||||||
message = "45\(datas)-[\"\(event)\","
|
if ack == nil {
|
||||||
|
message = "45\(datas)-[\"\(event)\","
|
||||||
|
} else {
|
||||||
|
message = "45\(datas)-\(ack!)[\"\(event)\","
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message = "45\(datas)-/\(nsp!),[\"\(event)\","
|
if ack == nil {
|
||||||
|
message = "45\(datas)-/\(nsp!),[\"\(event)\","
|
||||||
|
} else {
|
||||||
|
message = "45\(datas)-/\(nsp!),\(ack!)[\"\(event)\","
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,10 +36,11 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
let emitQueue = dispatch_queue_create("emitQueue".cStringUsingEncoding(NSUTF8StringEncoding),
|
let emitQueue = dispatch_queue_create("emitQueue".cStringUsingEncoding(NSUTF8StringEncoding),
|
||||||
DISPATCH_QUEUE_SERIAL)
|
DISPATCH_QUEUE_SERIAL)
|
||||||
private var ackHandlers = [SocketAckHandler]()
|
private var ackHandlers = [SocketAckHandler]()
|
||||||
private var secure = false
|
private var currentAck = -1
|
||||||
private var handlers = [SocketEventHandler]()
|
private var handlers = [SocketEventHandler]()
|
||||||
private var lastSocketMessage:SocketEvent?
|
private var lastSocketMessage:SocketEvent?
|
||||||
private var pingTimer:NSTimer!
|
private var pingTimer:NSTimer!
|
||||||
|
private var secure = false
|
||||||
var closed = false
|
var closed = false
|
||||||
var connected = false
|
var connected = false
|
||||||
var connecting = false
|
var connecting = false
|
||||||
@ -126,14 +127,11 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
// Sends a message with multiple args
|
// Sends a message with multiple args
|
||||||
// If a message contains binary we have to send those
|
// If a message contains binary we have to send those
|
||||||
// seperately.
|
// seperately.
|
||||||
func emit(event:String, _ args:AnyObject...) -> SocketAckHandler {
|
func emit(event:String, _ args:AnyObject...) {
|
||||||
if !self.connected {
|
if !self.connected {
|
||||||
return SocketAckHandler(event: "fail")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let ackHandler = SocketAckHandler(event: event)
|
|
||||||
self.ackHandlers.append(ackHandler)
|
|
||||||
|
|
||||||
dispatch_async(self.emitQueue) {[weak self] in
|
dispatch_async(self.emitQueue) {[weak self] in
|
||||||
if self == nil {
|
if self == nil {
|
||||||
return
|
return
|
||||||
@ -141,11 +139,29 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
|
|
||||||
self?._emit(event, args)
|
self?._emit(event, args)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func emitWithAck(event:String, _ args:AnyObject...) -> SocketAckHandler {
|
||||||
|
if !self.connected {
|
||||||
|
return SocketAckHandler(event: "fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.currentAck++
|
||||||
|
let ackHandler = SocketAckHandler(event: event, ackNum: self.currentAck)
|
||||||
|
self.ackHandlers.append(ackHandler)
|
||||||
|
|
||||||
|
dispatch_async(self.emitQueue) {[weak self] in
|
||||||
|
if self == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self?._emit(event, args, ack: true)
|
||||||
|
}
|
||||||
|
|
||||||
return ackHandler
|
return ackHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
private func _emit(event:String, _ args:[AnyObject]) {
|
private func _emit(event:String, _ args:[AnyObject], ack:Bool = false) {
|
||||||
var frame:SocketEvent
|
var frame:SocketEvent
|
||||||
var str:String
|
var str:String
|
||||||
|
|
||||||
@ -156,16 +172,27 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hasBinary {
|
if hasBinary {
|
||||||
str = SocketEvent.createMessageForEvent(event, withArgs: items,
|
if !ack {
|
||||||
hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp)
|
str = SocketEvent.createMessageForEvent(event, withArgs: items,
|
||||||
|
hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp)
|
||||||
|
} else {
|
||||||
|
str = SocketEvent.createMessageForEvent(event, withArgs: items,
|
||||||
|
hasBinary: true, withDatas: emitDatas.count, toNamespace: self.nsp, wantsAck: self.currentAck)
|
||||||
|
}
|
||||||
|
|
||||||
self.io?.send(str)
|
self.io?.send(str)
|
||||||
for data in emitDatas {
|
for data in emitDatas {
|
||||||
self.io?.send(data)
|
self.io?.send(data)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false,
|
if !ack {
|
||||||
withDatas: 0, toNamespace: self.nsp)
|
str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false,
|
||||||
|
withDatas: 0, toNamespace: self.nsp)
|
||||||
|
} else {
|
||||||
|
str = SocketEvent.createMessageForEvent(event, withArgs: items, hasBinary: false,
|
||||||
|
withDatas: 0, toNamespace: self.nsp, wantsAck: self.currentAck)
|
||||||
|
}
|
||||||
|
|
||||||
self.io?.send(str)
|
self.io?.send(str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,6 +234,16 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when the socket gets an ack for something it sent
|
||||||
|
private func handleAck(ack:Int, data:AnyObject?) {
|
||||||
|
for handler in self.ackHandlers {
|
||||||
|
if handler.ackNum == ack {
|
||||||
|
handler.callback?(data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handles events
|
// Handles events
|
||||||
func handleEvent(event:String, data:AnyObject?, isInternalMessage:Bool = false,
|
func handleEvent(event:String, data:AnyObject?, isInternalMessage:Bool = false,
|
||||||
wantsAck ack:Int? = nil, withAckType ackType:Int = 3) {
|
wantsAck ack:Int? = nil, withAckType ackType:Int = 3) {
|
||||||
@ -264,7 +301,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse an NSArray looking for binary data
|
// Parse an NSArray looking for binary data
|
||||||
private class func parseArray(arr:NSArray, var placeholders:Int) -> (NSArray, Bool, [NSData]) {
|
private static func parseArray(arr:NSArray, var placeholders:Int) -> (NSArray, Bool, [NSData]) {
|
||||||
var replacementArr = [AnyObject](count: arr.count, repeatedValue: 1)
|
var replacementArr = [AnyObject](count: arr.count, repeatedValue: 1)
|
||||||
var hasBinary = false
|
var hasBinary = false
|
||||||
var arrayDatas = [NSData]()
|
var arrayDatas = [NSData]()
|
||||||
@ -512,6 +549,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
if ackNum == "" {
|
if ackNum == "" {
|
||||||
self.handleEvent(event, data: parsed)
|
self.handleEvent(event, data: parsed)
|
||||||
} else {
|
} else {
|
||||||
|
self.currentAck = ackNum.toInt()!
|
||||||
self.handleEvent(event, data: parsed, isInternalMessage: false,
|
self.handleEvent(event, data: parsed, isInternalMessage: false,
|
||||||
wantsAck: ackNum.toInt(), withAckType: 3)
|
wantsAck: ackNum.toInt(), withAckType: 3)
|
||||||
}
|
}
|
||||||
@ -525,6 +563,7 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
if ackNum == "" {
|
if ackNum == "" {
|
||||||
self.handleEvent(event, data: parsed)
|
self.handleEvent(event, data: parsed)
|
||||||
} else {
|
} else {
|
||||||
|
self.currentAck = ackNum.toInt()!
|
||||||
self.handleEvent(event, data: parsed, isInternalMessage: false,
|
self.handleEvent(event, data: parsed, isInternalMessage: false,
|
||||||
wantsAck: ackNum.toInt(), withAckType: 3)
|
wantsAck: ackNum.toInt(), withAckType: 3)
|
||||||
}
|
}
|
||||||
@ -540,11 +579,31 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
if ackNum == "" {
|
if ackNum == "" {
|
||||||
self.handleEvent(event, data: nil)
|
self.handleEvent(event, data: nil)
|
||||||
} else {
|
} else {
|
||||||
|
self.currentAck = ackNum.toInt()!
|
||||||
self.handleEvent(event, data: nil, isInternalMessage: false,
|
self.handleEvent(event, data: nil, isInternalMessage: false,
|
||||||
wantsAck: ackNum.toInt(), withAckType: 3)
|
wantsAck: ackNum.toInt(), withAckType: 3)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if messageGroups[1].hasPrefix("43") {
|
||||||
|
let arr = Array(messageGroups[1])
|
||||||
|
let ackNum:String
|
||||||
|
let nsp = messageGroups[2]
|
||||||
|
|
||||||
|
if nsp == "" && self.nsp != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if nsp == "" {
|
||||||
|
ackNum = String(arr[2...arr.count-1])
|
||||||
|
} else {
|
||||||
|
ackNum = messageGroups[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
let ackData:AnyObject? = SocketIOClient.parseData(messageGroups[4])
|
||||||
|
self.handleAck(ackNum.toInt()!, data: ackData)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
End Check for message
|
End Check for message
|
||||||
@ -574,9 +633,13 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
/**
|
/**
|
||||||
Begin check for binary placeholders
|
Begin check for binary placeholders
|
||||||
**/
|
**/
|
||||||
let binaryGroup = mutMessage["^(\\d*)-\\/?(\\w*)?,?(\\d*)?\\[(\".*?\"),(.*)\\]$"].groups()
|
let binaryGroup = mutMessage["^(\\d*)-\\/?(\\w*)?,?(\\d*)?\\[(\".*?\")?,?(.*)?\\]$"].groups()
|
||||||
|
|
||||||
if binaryGroup != nil {
|
if binaryGroup == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if binaryGroup[1].hasPrefix("45") {
|
||||||
// println(binaryGroup)
|
// println(binaryGroup)
|
||||||
var ackNum:String
|
var ackNum:String
|
||||||
var event:String
|
var event:String
|
||||||
@ -611,11 +674,35 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
mes = SocketEvent(event: event, args: placeholdersRemoved,
|
mes = SocketEvent(event: event, args: placeholdersRemoved,
|
||||||
placeholders: numberOfPlaceholders.toInt()!)
|
placeholders: numberOfPlaceholders.toInt()!)
|
||||||
} else {
|
} else {
|
||||||
|
self.currentAck = ackNum.toInt()!
|
||||||
mes = SocketEvent(event: event, args: placeholdersRemoved,
|
mes = SocketEvent(event: event, args: placeholdersRemoved,
|
||||||
placeholders: numberOfPlaceholders.toInt()!, ack: ackNum.toInt())
|
placeholders: numberOfPlaceholders.toInt()!, ackNum: ackNum.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lastSocketMessage = mes
|
self.lastSocketMessage = mes
|
||||||
|
} else if binaryGroup[1].hasPrefix("46") {
|
||||||
|
let messageType = RegexMutable(binaryGroup[1])
|
||||||
|
let numberOfPlaceholders = (messageType["46"] ~= "") as String
|
||||||
|
let ackNum:String
|
||||||
|
let nsp:String
|
||||||
|
|
||||||
|
if binaryGroup[3] == "" {
|
||||||
|
ackNum = binaryGroup[2]
|
||||||
|
nsp = ""
|
||||||
|
} else {
|
||||||
|
ackNum = binaryGroup[3]
|
||||||
|
nsp = binaryGroup[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
if nsp == "" && self.nsp != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var mutMessageObject = RegexMutable(binaryGroup[5])
|
||||||
|
let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"]
|
||||||
|
~= "\"~~$2\""
|
||||||
|
|
||||||
|
self.lastSocketMessage = SocketEvent(event: "", args: placeholdersRemoved,
|
||||||
|
placeholders: numberOfPlaceholders.toInt()!, ackNum: ackNum.toInt(), justAck: true)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
End check for binary placeholders
|
End check for binary placeholders
|
||||||
@ -634,6 +721,11 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
if let args:AnyObject = parsedArgs {
|
if let args:AnyObject = parsedArgs {
|
||||||
let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders(args)
|
let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders(args)
|
||||||
|
|
||||||
|
if self.lastSocketMessage!.justAck! {
|
||||||
|
self.handleAck(self.lastSocketMessage!.ack!, data: filledInArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if self.lastSocketMessage!.ack != nil {
|
if self.lastSocketMessage!.ack != nil {
|
||||||
self.handleEvent(event, data: filledInArgs, isInternalMessage: false,
|
self.handleEvent(event, data: filledInArgs, isInternalMessage: false,
|
||||||
wantsAck: self.lastSocketMessage!.ack!, withAckType: 6)
|
wantsAck: self.lastSocketMessage!.ack!, withAckType: 6)
|
||||||
@ -643,6 +735,11 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
|||||||
} else {
|
} else {
|
||||||
let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders()
|
let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders()
|
||||||
|
|
||||||
|
if self.lastSocketMessage!.justAck! {
|
||||||
|
self.handleAck(self.lastSocketMessage!.ack!, data: filledInArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if self.lastSocketMessage!.ack != nil {
|
if self.lastSocketMessage!.ack != nil {
|
||||||
self.handleEvent(event, data: filledInArgs, isInternalMessage: false,
|
self.handleEvent(event, data: filledInArgs, isInternalMessage: false,
|
||||||
wantsAck: self.lastSocketMessage!.ack!, withAckType: 6)
|
wantsAck: self.lastSocketMessage!.ack!, withAckType: 6)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user