From 2f82de9502d79a9e7932a2f68beeb1cd21110c7c Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 19 Mar 2015 08:37:10 -0400 Subject: [PATCH 1/5] bump version --- Socket.IO-Client-Swift.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Socket.IO-Client-Swift.podspec b/Socket.IO-Client-Swift.podspec index cbb3c13..485685c 100644 --- a/Socket.IO-Client-Swift.podspec +++ b/Socket.IO-Client-Swift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Socket.IO-Client-Swift" - s.version = "1.3.0" + s.version = "1.3.1" s.summary = "Socket.IO-client for Swift" s.description = <<-DESC Socket.IO-client for Swift. @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.author = { "Erik" => "nuclear.ace@gmail.com" } s.ios.deployment_target = '8.0' s.osx.deployment_target = '10.10' - s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.3.0' } + s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.3.1' } s.source_files = "SwiftIO/**/*.swift" s.requires_arc = true # s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files From 517579151332d9e050521ded54c1aadf9cfc7334 Mon Sep 17 00:00:00 2001 From: Erik Little Date: Thu, 19 Mar 2015 11:07:16 -0400 Subject: [PATCH 2/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dd3104e..cb35287 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! -pod 'Socket.IO-Client-Swift', '~> 1.1' +pod 'Socket.IO-Client-Swift', '~> 1.3.2' # Or latest version ``` Install pods: From 54b2da8395689812c45040816b6612567118d5d4 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 19 Mar 2015 13:22:58 -0400 Subject: [PATCH 3/5] work on redesign --- SwiftIO/SocketEngine.swift | 41 ++++++++++++++++++++------------ SwiftIO/SocketEngineClient.swift | 41 ++++++++++++++++++++++++++++++++ SwiftIO/SocketIOClient.swift | 26 ++++++++++---------- 3 files changed, 80 insertions(+), 28 deletions(-) create mode 100644 SwiftIO/SocketEngineClient.swift diff --git a/SwiftIO/SocketEngine.swift b/SwiftIO/SocketEngine.swift index 9bcb27e..c352af0 100644 --- a/SwiftIO/SocketEngine.swift +++ b/SwiftIO/SocketEngine.swift @@ -32,7 +32,7 @@ extension String { private typealias PollWaitQueue = [() -> Void] -private enum PacketType: String { +public enum PacketType: String { case OPEN = "0" case CLOSE = "1" case PING = "2" @@ -43,7 +43,7 @@ private enum PacketType: String { } public class SocketEngine: NSObject, WebSocketDelegate { - unowned let client:SocketIOClient + unowned let client:SocketEngineClient private let workQueue = NSOperationQueue() private let emitQueue = dispatch_queue_create( "emitQueue".cStringUsingEncoding(NSUTF8StringEncoding), DISPATCH_QUEUE_SERIAL) @@ -80,7 +80,7 @@ public class SocketEngine: NSObject, WebSocketDelegate { } var ws:WebSocket? - init(client:SocketIOClient, forcePolling:Bool = false, withCookies cookies:[NSHTTPCookie]?) { + init(client:SocketEngineClient, forcePolling:Bool = false, withCookies cookies:[NSHTTPCookie]?) { self.client = client self.forcePolling = forcePolling self.cookies = cookies @@ -477,20 +477,14 @@ public class SocketEngine: NSObject, WebSocketDelegate { } } + /* + Send a message with type 4 + */ public func send(msg:String, datas:[NSData]? = nil) { let _send = {[weak self] (msg:String, datas:[NSData]?) -> () -> Void in return { - if self == nil || !self!.connected { - return - } - - if self!.websocket { - // NSLog("sending ws: \(msg):\(datas)") - self?.sendWebSocketMessage(msg, withType: PacketType.MESSAGE, datas: datas) - } else { - // NSLog("sending poll: \(msg):\(datas)") - self?.sendPollMessage(msg, withType: PacketType.MESSAGE, datas: datas) - } + self?.write(msg, withType: PacketType.MESSAGE, withData: datas) + return } } @@ -559,7 +553,8 @@ public class SocketEngine: NSObject, WebSocketDelegate { self.pingTimer?.invalidate() dispatch_async(dispatch_get_main_queue()) { - self.pingTimer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(self.pingInterval!), target: self, + self.pingTimer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(self.pingInterval!), + target: self, selector: Selector("sendPing"), userInfo: nil, repeats: true) } } @@ -573,6 +568,22 @@ public class SocketEngine: NSObject, WebSocketDelegate { } } + public func write(msg:String, withType type:PacketType, withData data:[NSData]?) { + if !self.connected { + return + } + + if self.websocket { + // NSLog("writing ws: \(msg):\(datas)") + self.sendWebSocketMessage(msg, withType: type, datas: data) + } else { + // NSLog("writing poll: \(msg):\(datas)") + self.sendPollMessage(msg, withType: type, datas: data) + } + } + + // Delagate methods + public func websocketDidConnect(socket:WebSocket) { self.websocketConnected = true self.probing = true diff --git a/SwiftIO/SocketEngineClient.swift b/SwiftIO/SocketEngineClient.swift new file mode 100644 index 0000000..22e2aab --- /dev/null +++ b/SwiftIO/SocketEngineClient.swift @@ -0,0 +1,41 @@ +// +// SocketEngineClient.swift +// Socket.IO-Swift +// +// Created by Erik Little on 3/19/15. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +@objc public protocol SocketEngineClient { + var ackQueue:dispatch_queue_attr_t! {get} + var handleQueue:dispatch_queue_attr_t! {get} + var emitQueue:dispatch_queue_attr_t! {get} + var reconnecting:Bool {get} + var socketURL:String {get} + var secure:Bool {get} + + func parseSocketMessage(msg:String) + func parseBinaryData(data:NSData) + func pollingDidFail(err:NSError?) + func webSocketDidCloseWithCode(code:Int, reason:String, wasClean:Bool) + func webSocketDidFailWithError(error:NSError) +} \ No newline at end of file diff --git a/SwiftIO/SocketIOClient.swift b/SwiftIO/SocketIOClient.swift index cb67b6e..00a7119 100644 --- a/SwiftIO/SocketIOClient.swift +++ b/SwiftIO/SocketIOClient.swift @@ -24,14 +24,7 @@ import Foundation -public class SocketIOClient: NSObject { - let socketURL:String! - let ackQueue = dispatch_queue_create("ackQueue".cStringUsingEncoding(NSUTF8StringEncoding), - DISPATCH_QUEUE_SERIAL) - let handleQueue = dispatch_queue_create("handleQueue".cStringUsingEncoding(NSUTF8StringEncoding), - DISPATCH_QUEUE_SERIAL) - let emitQueue = dispatch_queue_create("emitQueue".cStringUsingEncoding(NSUTF8StringEncoding), - DISPATCH_QUEUE_SERIAL) +public class SocketIOClient: NSObject, SocketEngineClient { let reconnectAttempts:Int! private lazy var params = [String: AnyObject]() private var ackHandlers = [SocketAckHandler]() @@ -51,6 +44,13 @@ public class SocketIOClient: NSObject { internal var currentAck = -1 internal var waitingData = [SocketEvent]() + public let socketURL:String + public let ackQueue = dispatch_queue_create("ackQueue".cStringUsingEncoding(NSUTF8StringEncoding), + DISPATCH_QUEUE_SERIAL) + public let handleQueue = dispatch_queue_create("handleQueue".cStringUsingEncoding(NSUTF8StringEncoding), + DISPATCH_QUEUE_SERIAL) + public let emitQueue = dispatch_queue_create("emitQueue".cStringUsingEncoding(NSUTF8StringEncoding), + DISPATCH_QUEUE_SERIAL) public var closed:Bool { return self._closed } @@ -379,16 +379,16 @@ public class SocketIOClient: NSObject { self.connect() } - func parseSocketMessage(msg:String) { + public func parseSocketMessage(msg:String) { SocketParser.parseSocketMessage(msg, socket: self) } - func parseBinaryData(data:NSData) { + public func parseBinaryData(data:NSData) { SocketParser.parseBinaryData(data, socket: self) } // Something happened while polling - func pollingDidFail(err:NSError?) { + public func pollingDidFail(err:NSError?) { if !self.reconnecting { self._connected = false self.handleEvent("reconnect", data: err?.localizedDescription, isInternalMessage: true) @@ -437,7 +437,7 @@ public class SocketIOClient: NSObject { } // Called when the socket is closed - func webSocketDidCloseWithCode(code:Int, reason:String!, wasClean:Bool) { + public func webSocketDidCloseWithCode(code:Int, reason:String, wasClean:Bool) { self._connected = false self._connecting = false if self.closed || !self.reconnects { @@ -449,7 +449,7 @@ public class SocketIOClient: NSObject { } // Called when an error occurs. - func webSocketDidFailWithError(error:NSError!) { + public func webSocketDidFailWithError(error:NSError) { self._connected = false self._connecting = false self.handleEvent("error", data: error.localizedDescription, isInternalMessage: true) From 72d5c07de1097ba5a5b898ef380c964dd8df6a21 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 19 Mar 2015 14:04:02 -0400 Subject: [PATCH 4/5] refactor --- SwiftIO/SocketEngine.swift | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/SwiftIO/SocketEngine.swift b/SwiftIO/SocketEngine.swift index c352af0..d21d2a6 100644 --- a/SwiftIO/SocketEngine.swift +++ b/SwiftIO/SocketEngine.swift @@ -30,7 +30,8 @@ extension String { } } -private typealias PollWaitQueue = [() -> Void] +private typealias Probe = (msg:String, type:PacketType, data:[NSData]?) +private typealias ProbeWaitQueue = [Probe] public enum PacketType: String { case OPEN = "0" @@ -59,7 +60,7 @@ public class SocketEngine: NSObject, WebSocketDelegate { private var postWait = [String]() private var _polling = true private var probing = false - private var probeWait = PollWaitQueue() + private var probeWait = ProbeWaitQueue() private var waitingForPoll = false private var waitingForPost = false private var _websocket = false @@ -204,7 +205,7 @@ public class SocketEngine: NSObject, WebSocketDelegate { } for waiter in self!.probeWait { - waiter() + self?.write(waiter.msg, withType: waiter.type, withData: waiter.data) } self?.probeWait.removeAll(keepCapacity: false) @@ -481,23 +482,10 @@ public class SocketEngine: NSObject, WebSocketDelegate { Send a message with type 4 */ public func send(msg:String, datas:[NSData]? = nil) { - let _send = {[weak self] (msg:String, datas:[NSData]?) -> () -> Void in - return { - self?.write(msg, withType: PacketType.MESSAGE, withData: datas) - return - } - } - - dispatch_async(self.emitQueue) {[weak self] in - if self == nil { - return - } - - if self!.probing { - self?.probeWait.append(_send(msg, datas)) - } else { - _send(msg, datas)() - } + if self.probing { + self.probeWait.append((msg, PacketType.MESSAGE, datas)) + } else { + self.write(msg, withType: PacketType.MESSAGE, withData: datas) } } From cbc59d600453c3c8eb330be700d2d130810d6706 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 19 Mar 2015 14:13:03 -0400 Subject: [PATCH 5/5] fix race condition --- SwiftIO/SocketEngine.swift | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/SwiftIO/SocketEngine.swift b/SwiftIO/SocketEngine.swift index d21d2a6..40b9eb9 100644 --- a/SwiftIO/SocketEngine.swift +++ b/SwiftIO/SocketEngine.swift @@ -557,16 +557,22 @@ public class SocketEngine: NSObject, WebSocketDelegate { } public func write(msg:String, withType type:PacketType, withData data:[NSData]?) { - if !self.connected { - return - } - - if self.websocket { - // NSLog("writing ws: \(msg):\(datas)") - self.sendWebSocketMessage(msg, withType: type, datas: data) - } else { - // NSLog("writing poll: \(msg):\(datas)") - self.sendPollMessage(msg, withType: type, datas: data) + dispatch_async(self.emitQueue) {[weak self] in + if self == nil { + return + } + + if !self!.connected { + return + } + + if self!.websocket { + // NSLog("writing ws: \(msg):\(datas)") + self?.sendWebSocketMessage(msg, withType: type, datas: data) + } else { + // NSLog("writing poll: \(msg):\(datas)") + self?.sendPollMessage(msg, withType: type, datas: data) + } } }