From 41c168a29ac468d1c060f356dda5d03b11e606ec Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 6 Mar 2015 16:29:13 -0500 Subject: [PATCH] Fixes. Add onAny method --- README.md | 3 +- SwiftIO/SocketEngine.swift | 69 +++++++++++++++++++++++------------- SwiftIO/SocketIOClient.swift | 24 +++++++++---- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index eaf9169..620b4f7 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ Constructor Methods ------- 1. `socket.on(name:String, callback:((data:NSArray?, ack:AckEmitter?) -> Void))` - Adds a handler for an event. Items are passed by an array. `ack` can be used to send an ack when one is requested. See example. +2. `socket.onAny(callback:((event:String, items:AnyObject?)) -> Void)` - Adds a handler for all events. It will be called on any received event. 3. `socket.emit(event:String, args:AnyObject...)` - Sends a message. Can send multiple args. -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. +4. `socket.emitWithAck(event:String, args:AnyObject...) -> SocketAckHandler` - Sends a message that requests an acknowledgement from the server. Returns a SocketAckHandler which you can use to add an onAck handler. See example. 5. `socket.connect()` - Establishes a connection to the server. A "connect" event is fired upon successful connection. 6. `socket.connectWithParams(params:[String: AnyObject])` - Establishes a connection to the server passing the specified params. A "connect" event is fired upon successful connection. 7. `socket.close()` - Closes the socket. Once a socket is closed it should not be reopened. diff --git a/SwiftIO/SocketEngine.swift b/SwiftIO/SocketEngine.swift index cedb457..a45e49e 100644 --- a/SwiftIO/SocketEngine.swift +++ b/SwiftIO/SocketEngine.swift @@ -51,6 +51,8 @@ class SocketEngine: NSObject, SRWebSocketDelegate { private let workQueue = NSOperationQueue() private let emitQueue = dispatch_queue_create( "emitQueue".cStringUsingEncoding(NSUTF8StringEncoding), DISPATCH_QUEUE_SERIAL) + private let parseQueue = dispatch_queue_create( + "parseQueue".cStringUsingEncoding(NSUTF8StringEncoding), DISPATCH_QUEUE_SERIAL) private let handleQueue = dispatch_queue_create( "handleQueue".cStringUsingEncoding(NSUTF8StringEncoding), DISPATCH_QUEUE_SERIAL) private var forcePolling = false @@ -162,7 +164,7 @@ class SocketEngine: NSObject, SRWebSocketDelegate { if let str = NSString(data: data, encoding: NSUTF8StringEncoding) { // println(str) - dispatch_async(self?.handleQueue) {[weak self] in + dispatch_async(self?.parseQueue) {[weak self] in self?.parsePollingMessage(str) return } @@ -189,11 +191,21 @@ class SocketEngine: NSObject, SRWebSocketDelegate { } private func flushWaitingForPost() { - if self.postWait.count == 0 || !self.connected || !self.polling { + if self.postWait.count == 0 || !self.connected { + return + } else if self.websocket { + self.flushWaitingForPostToWebSocket() return } - let postStr = self.postWait.reduce("") {$0 + $1} + var postStr = "" + + for packet in self.postWait { + let len = countElements(packet) + + postStr += "\(len):\(packet)" + } + self.postWait.removeAll(keepCapacity: true) var req = NSMutableURLRequest(URL: @@ -220,9 +232,20 @@ class SocketEngine: NSObject, SRWebSocketDelegate { self?.flushWaitingForPost() self?.waitingForPost = false + self?.doPoll() } } + // We had packets waiting for send when we upgraded + // Send them raw + private func flushWaitingForPostToWebSocket() { + for msg in self.postWait { + self.ws?.send(msg) + } + + self.postWait.removeAll(keepCapacity: true) + } + // A poll failed, tell the client about it // We check to see if we were closed by the server first private func handlePollingFailed(reason:NSError?) { @@ -313,6 +336,7 @@ class SocketEngine: NSObject, SRWebSocketDelegate { // println(str) + let strArray = Array(str) var length = "" var n = 0 var msg = "" @@ -328,7 +352,6 @@ class SocketEngine: NSObject, SRWebSocketDelegate { } for var i = 0, l = str.length; i < l; i = i &+ 1 { - let strArray = Array(str) let chr = String(strArray[i]) if chr != ":" { @@ -349,8 +372,12 @@ class SocketEngine: NSObject, SRWebSocketDelegate { } if msg.length != 0 { - fixSwift = msg - self.parseEngineMessage(fixSwift) + // Be sure to capture the value of the msg + dispatch_async(self.handleQueue) {[weak self, msg] in + fixSwift = msg + self?.parseEngineMessage(fixSwift) + return + } } i += n @@ -360,7 +387,7 @@ class SocketEngine: NSObject, SRWebSocketDelegate { } private func parseEngineMessage(message:AnyObject?) { - // println(message) + // println(message!) if let data = message as? NSData { // Strip off message type self.client.parseSocketMessage(data.subdataWithRange(NSMakeRange(1, data.length - 1))) @@ -382,6 +409,7 @@ class SocketEngine: NSObject, SRWebSocketDelegate { // TODO Handle other packets if messageString.hasPrefix("b4") { // binary in base64 string + messageString.removeRange(Range(start: messageString.startIndex, end: advance(messageString.startIndex, 2))) @@ -391,6 +419,9 @@ class SocketEngine: NSObject, SRWebSocketDelegate { self.client.parseSocketMessage(data) } + return + } else if type == PacketType.NOOP.rawValue { + self.doPoll() return } @@ -456,32 +487,19 @@ class SocketEngine: NSObject, SRWebSocketDelegate { } private func sendPollMessage(msg:String, withType type:PacketType, datas:[NSData]? = nil) { - // println("Sending: \(msg)") - var postData:NSData - var bDatas:[String]? + // println("Sending: poll: \(msg) as type: \(type.rawValue)") + let strMsg = "\(type.rawValue)\(msg)" + + self.postWait.append(strMsg) if datas != nil { - bDatas = [String]() for data in datas! { let (nilData, b64Data) = self.createBinaryDataForSend(data) - let dataLen = countElements(b64Data!) - bDatas!.append("\(dataLen):\(b64Data!)") + self.postWait.append(b64Data!) } } - let strMsg = "\(type.rawValue)\(msg)" - let postCount = countElements(strMsg) - var postStr = "\(postCount):\(strMsg)" - - if bDatas != nil { - for data in bDatas! { - postStr += data - } - } - - self.postWait.append(postStr) - if waitingForPost { self.doPoll() return @@ -491,6 +509,7 @@ class SocketEngine: NSObject, SRWebSocketDelegate { } private func sendWebSocketMessage(str:String, withType type:PacketType, datas:[NSData]? = nil) { + // println("Sending: ws: \(str) as type: \(type.rawValue)") self.ws?.send("\(type.rawValue)\(str)") if datas != nil { diff --git a/SwiftIO/SocketIOClient.swift b/SwiftIO/SocketIOClient.swift index 516ee09..c3d76c8 100644 --- a/SwiftIO/SocketIOClient.swift +++ b/SwiftIO/SocketIOClient.swift @@ -36,6 +36,7 @@ class SocketIOClient { let reconnectAttempts:Int! private lazy var params = [String: AnyObject]() private var ackHandlers = [SocketAckHandler]() + private var anyHandler:((AnyHandler) -> Void)? private var currentAck = -1 private var currentReconnectAttempt = 0 private var forcePolling = false @@ -269,13 +270,17 @@ class SocketIOClient { 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)") - dispatch_async(dispatch_get_main_queue()) { - if !self.connected && !isInternalMessage { - return - } - - for handler in self.handlers { - if handler.event == event { + if !self.connected && !isInternalMessage { + return + } + + dispatch_async(dispatch_get_main_queue()) {[weak self] in + self?.anyHandler?((event, data)) + return + } + for handler in self.handlers { + if handler.event == event { + dispatch_async(dispatch_get_main_queue()) { if data is NSArray { if ack != nil { handler.executeCallback(data as? NSArray, withAck: ack!, @@ -318,6 +323,11 @@ class SocketIOClient { self.handlers.append(handler) } + // Adds a handler for any event + func onAny(handler:(AnyHandler) -> Void) { + self.anyHandler = handler + } + // Opens the connection to the socket func open() { self.connect()