From 718caba9d9a1548f012e6d958545b90374185c69 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 22 Mar 2016 09:56:56 -0400 Subject: [PATCH 01/10] remove nstimer --- Source/SocketEngine.swift | 32 +++++++++++++------------------- Source/SocketEngineSpec.swift | 1 - 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 1a23fc7..37d5766 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -47,7 +47,6 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb public private(set) var forcePolling = false public private(set) var forceWebsockets = false public private(set) var invalidated = false - public private(set) var pingTimer: NSTimer? public private(set) var polling = true public private(set) var probing = false public private(set) var session: NSURLSession? @@ -295,7 +294,6 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb invalidated = true connected = false - pingTimer?.invalidate() ws?.disconnect() stopPolling() client?.engineDidClose(reason) @@ -401,8 +399,7 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb createWebsocketAndConnect() } - - startPingTimer() + sendPing() if !forceWebsockets { doPoll() @@ -487,30 +484,28 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb websocket = false } - @objc private func sendPing() { + private func sendPing() { + if !connected { + return + } + //Server is not responding if pongsMissed > pongsMissedMax { - pingTimer?.invalidate() client?.engineDidClose("Ping timeout") return } - - pongsMissed += 1 - write("", withType: .Ping, withData: []) - } - - private func startPingTimer() { + if let pingInterval = pingInterval { - pingTimer?.invalidate() - pingTimer = nil + pongsMissed += 1 + write("", withType: .Ping, withData: []) - dispatch_async(dispatch_get_main_queue()) { - self.pingTimer = NSTimer.scheduledTimerWithTimeInterval(pingInterval, target: self, - selector: #selector(SocketEngine.sendPing), userInfo: nil, repeats: true) + let time = dispatch_time(DISPATCH_TIME_NOW, Int64(pingInterval * Double(NSEC_PER_SEC))) + dispatch_after(time, dispatch_get_main_queue()) {[weak self] in + self?.sendPing() } } } - + // Moves from long-polling to websockets private func upgradeTransport() { if ws?.isConnected ?? false { @@ -562,7 +557,6 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb } if websocket { - pingTimer?.invalidate() connected = false websocket = false diff --git a/Source/SocketEngineSpec.swift b/Source/SocketEngineSpec.swift index 5846ac8..c295b82 100644 --- a/Source/SocketEngineSpec.swift +++ b/Source/SocketEngineSpec.swift @@ -37,7 +37,6 @@ import Foundation var forcePolling: Bool { get } var forceWebsockets: Bool { get } var parseQueue: dispatch_queue_t! { get } - var pingTimer: NSTimer? { get } var polling: Bool { get } var probing: Bool { get } var emitQueue: dispatch_queue_t! { get } From 4f5837afa7df1150dc2cb47cb1d09d7c2539a0c5 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 22 Mar 2016 10:15:09 -0400 Subject: [PATCH 02/10] don't need objc on this method anymore --- Source/SocketIOClient.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 981f744..431b96c 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -443,7 +443,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable } } - @objc private func _tryReconnect() { + private func _tryReconnect() { if !reconnecting { return } From a0167ae2138e529b6781a3177b19bca00bbd4d29 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 23 Mar 2016 13:39:22 -0400 Subject: [PATCH 03/10] remove deprecated methods --- Source/SocketEngine.swift | 26 +++----------------------- Source/SocketEngineSpec.swift | 2 -- Source/SocketIOClient.swift | 22 ---------------------- 3 files changed, 3 insertions(+), 47 deletions(-) diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 37d5766..0a8163b 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -122,18 +122,6 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb self.init(client: client, url: url, options: options?.toSocketOptionsSet() ?? []) } - @available(*, deprecated=5.3, message="Please use the NSURL based init") - public convenience init(client: SocketEngineClient, urlString: String, options: Set) { - guard let url = NSURL(string: urlString) else { fatalError("Incorrect url") } - self.init(client: client, url: url, options: options) - } - - @available(*, deprecated=5.3, message="Please use the NSURL based init") - public convenience init(client: SocketEngineClient, urlString: String, options: NSDictionary?) { - guard let url = NSURL(string: urlString) else { fatalError("Incorrect url") } - self.init(client: client, url: url, options: options?.toSocketOptionsSet() ?? []) - } - deinit { DefaultSocketLogger.Logger.log("Engine is being released", type: logType) closed = true @@ -183,16 +171,12 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb return false } } - - public func close(reason: String) { - disconnect(reason) - } /// Starts the connection to the server public func connect() { if connected { DefaultSocketLogger.Logger.error("Engine tried opening while connected. Assuming this was a reconnect", type: logType) - close("reconnect") + disconnect("reconnect") } DefaultSocketLogger.Logger.log("Starting engine", type: logType) @@ -284,7 +268,7 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb public func didError(error: String) { DefaultSocketLogger.Logger.error(error, type: logType) client?.engineDidError(error) - close(error) + disconnect(error) } public func disconnect(reason: String) { @@ -421,11 +405,7 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb upgradeTransport() } } - - public func open() { - connect() - } - + public func parseEngineData(data: NSData) { DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data) client?.parseEngineBinaryData(data.subdataWithRange(NSMakeRange(1, data.length - 1))) diff --git a/Source/SocketEngineSpec.swift b/Source/SocketEngineSpec.swift index c295b82..785fc6f 100644 --- a/Source/SocketEngineSpec.swift +++ b/Source/SocketEngineSpec.swift @@ -49,13 +49,11 @@ import Foundation init(client: SocketEngineClient, url: NSURL, options: NSDictionary?) - @available(*, deprecated=5.5, message="Please use disconnect") func close(reason: String) func connect() func didError(error: String) func disconnect(reason: String) func doFastUpgrade() func flushWaitingForPostToWebSocket() - @available(*, deprecated=5.5, message="Please use connect") func open() func parseEngineData(data: NSData) func parseEngineMessage(message: String, fromPolling: Bool) func write(msg: String, withType type: SocketEnginePacketType, withData data: [NSData]) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 431b96c..a1d422d 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -108,18 +108,6 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable self.init(socketURL: socketURL, options: options?.toSocketOptionsSet() ?? []) } - @available(*, deprecated=5.3, message="Please use the NSURL based init") - public convenience init(socketURLString: String, options: Set = []) { - guard let url = NSURL(string: socketURLString) else { fatalError("Incorrect url") } - self.init(socketURL: url, options: options) - } - - @available(*, deprecated=5.3, message="Please use the NSURL based init") - public convenience init(socketURLString: String, options: NSDictionary?) { - guard let url = NSURL(string: socketURLString) else { fatalError("Incorrect url") } - self.init(socketURL: url, options: options?.toSocketOptionsSet() ?? []) - } - deinit { DefaultSocketLogger.Logger.log("Client is being released", type: logType) engine?.disconnect("Client Deinit") @@ -133,11 +121,6 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable return engine! } - @available(*, deprecated=5.3, message="Please use disconnect()") - public func close() { - disconnect() - } - /// Connect to the server. public func connect() { connect(timeoutAfter: 0, withTimeoutHandler: nil) @@ -402,11 +385,6 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable anyHandler = handler } - @available(*, deprecated=5.3, message="Please use one of the connect methods)") - public func open() { - connect() - } - public func parseEngineMessage(msg: String) { DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg) From 8f8d5acdba1d18b40c95f8322466cb0217465ed5 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 24 Mar 2016 14:17:49 -0400 Subject: [PATCH 04/10] use 7.3 image --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4c29e82..c37d53c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: objective-c xcode_project: Socket.IO-Client-Swift.xcodeproj # path to your xcodeproj folder xcode_scheme: SocketIO-iOS -osx_image: xcode7 +osx_image: xcode7.3 before_install: - cd Socket.IO-Test-Server/ - npm install From d4c01183ab4e1527feeaa2184fe9341c96455b73 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Mar 2016 09:48:04 -0400 Subject: [PATCH 05/10] style --- Source/SocketAckEmitter.swift | 2 +- Source/SocketAckManager.swift | 2 +- Source/SocketAnyEvent.swift | 2 +- Source/SocketClientSpec.swift | 2 +- Source/SocketEngine.swift | 2 +- Source/SocketEnginePacketType.swift | 2 +- Source/SocketEnginePollable.swift | 2 +- Source/SocketEngineWebsocket.swift | 2 +- Source/SocketIOClient.swift | 2 +- Source/SocketIOClientOption.swift | 6 +++--- Source/SocketIOClientStatus.swift | 2 +- Source/SocketLogger.swift | 4 ++-- Source/SocketParsable.swift | 2 +- Source/SwiftRegex.swift | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Source/SocketAckEmitter.swift b/Source/SocketAckEmitter.swift index 678f084..edb2522 100644 --- a/Source/SocketAckEmitter.swift +++ b/Source/SocketAckEmitter.swift @@ -24,7 +24,7 @@ import Foundation -public final class SocketAckEmitter: NSObject { +public final class SocketAckEmitter : NSObject { let socket: SocketIOClient let ackNum: Int diff --git a/Source/SocketAckManager.swift b/Source/SocketAckManager.swift index e48d48c..972e1da 100644 --- a/Source/SocketAckManager.swift +++ b/Source/SocketAckManager.swift @@ -24,7 +24,7 @@ import Foundation -private struct SocketAck: Hashable, Equatable { +private struct SocketAck : Hashable, Equatable { let ack: Int var callback: AckCallback! var hashValue: Int { diff --git a/Source/SocketAnyEvent.swift b/Source/SocketAnyEvent.swift index 304410c..4c26f0e 100644 --- a/Source/SocketAnyEvent.swift +++ b/Source/SocketAnyEvent.swift @@ -24,7 +24,7 @@ import Foundation -public final class SocketAnyEvent: NSObject { +public final class SocketAnyEvent : NSObject { public let event: String public let items: NSArray? override public var description: String { diff --git a/Source/SocketClientSpec.swift b/Source/SocketClientSpec.swift index c0f8c9e..48b3b17 100644 --- a/Source/SocketClientSpec.swift +++ b/Source/SocketClientSpec.swift @@ -22,7 +22,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -protocol SocketClientSpec: class { +protocol SocketClientSpec : class { var nsp: String { get set } var waitingPackets: [SocketPacket] { get set } diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 0a8163b..e886cad 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -24,7 +24,7 @@ import Foundation -public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWebsocket { +public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWebsocket { public let emitQueue = dispatch_queue_create("com.socketio.engineEmitQueue", DISPATCH_QUEUE_SERIAL) public let handleQueue = dispatch_queue_create("com.socketio.engineHandleQueue", DISPATCH_QUEUE_SERIAL) public let parseQueue = dispatch_queue_create("com.socketio.engineParseQueue", DISPATCH_QUEUE_SERIAL) diff --git a/Source/SocketEnginePacketType.swift b/Source/SocketEnginePacketType.swift index f899721..592d79b 100644 --- a/Source/SocketEnginePacketType.swift +++ b/Source/SocketEnginePacketType.swift @@ -25,6 +25,6 @@ import Foundation -@objc public enum SocketEnginePacketType: Int { +@objc public enum SocketEnginePacketType : Int { case Open, Close, Ping, Pong, Message, Upgrade, Noop } \ No newline at end of file diff --git a/Source/SocketEnginePollable.swift b/Source/SocketEnginePollable.swift index 355429a..86291cd 100644 --- a/Source/SocketEnginePollable.swift +++ b/Source/SocketEnginePollable.swift @@ -25,7 +25,7 @@ import Foundation /// Protocol that is used to implement socket.io polling support -public protocol SocketEnginePollable: SocketEngineSpec { +public protocol SocketEnginePollable : SocketEngineSpec { var invalidated: Bool { get } /// Holds strings waiting to be sent over polling. /// You shouldn't need to mess with this. diff --git a/Source/SocketEngineWebsocket.swift b/Source/SocketEngineWebsocket.swift index 4b1be7f..a173250 100644 --- a/Source/SocketEngineWebsocket.swift +++ b/Source/SocketEngineWebsocket.swift @@ -26,7 +26,7 @@ import Foundation /// Protocol that is used to implement socket.io WebSocket support -public protocol SocketEngineWebsocket: SocketEngineSpec, WebSocketDelegate { +public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate { var ws: WebSocket? { get } func sendWebSocketMessage(str: String, withType type: SocketEnginePacketType, withData datas: [NSData]) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index a1d422d..12bd49d 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -24,7 +24,7 @@ import Foundation -public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable { +public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable { public let socketURL: NSURL public private(set) var engine: SocketEngineSpec? diff --git a/Source/SocketIOClientOption.swift b/Source/SocketIOClientOption.swift index 72a444f..93626f5 100644 --- a/Source/SocketIOClientOption.swift +++ b/Source/SocketIOClientOption.swift @@ -24,11 +24,11 @@ import Foundation -protocol ClientOption: CustomStringConvertible, Hashable { +protocol ClientOption : CustomStringConvertible, Hashable { func getSocketIOOptionValue() -> AnyObject } -public enum SocketIOClientOption: ClientOption { +public enum SocketIOClientOption : ClientOption { case ConnectParams([String: AnyObject]) case Cookies([NSHTTPCookie]) case DoubleEncodeUTF8(Bool) @@ -152,7 +152,7 @@ public func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool { return lhs.description == rhs.description } -extension Set where Element: ClientOption { +extension Set where Element : ClientOption { mutating func insertIgnore(element: Element) { if !contains(element) { insert(element) diff --git a/Source/SocketIOClientStatus.swift b/Source/SocketIOClientStatus.swift index 13e82b9..09626b8 100644 --- a/Source/SocketIOClientStatus.swift +++ b/Source/SocketIOClientStatus.swift @@ -24,7 +24,7 @@ import Foundation -@objc public enum SocketIOClientStatus: Int, CustomStringConvertible { +@objc public enum SocketIOClientStatus : Int, CustomStringConvertible { case NotConnected, Closed, Connecting, Connected public var description: String { diff --git a/Source/SocketLogger.swift b/Source/SocketLogger.swift index bbb8578..9ba7d34 100644 --- a/Source/SocketLogger.swift +++ b/Source/SocketLogger.swift @@ -24,7 +24,7 @@ import Foundation -public protocol SocketLogger: class { +public protocol SocketLogger : class { /// Whether to log or not var log: Bool {get set} @@ -54,7 +54,7 @@ public extension SocketLogger { } } -class DefaultSocketLogger: SocketLogger { +class DefaultSocketLogger : SocketLogger { static var Logger: SocketLogger = DefaultSocketLogger() var log = false diff --git a/Source/SocketParsable.swift b/Source/SocketParsable.swift index 4125351..537a614 100644 --- a/Source/SocketParsable.swift +++ b/Source/SocketParsable.swift @@ -22,7 +22,7 @@ import Foundation -protocol SocketParsable: SocketClientSpec { +protocol SocketParsable : SocketClientSpec { func parseBinaryData(data: NSData) func parseSocketMessage(message: String) } diff --git a/Source/SwiftRegex.swift b/Source/SwiftRegex.swift index efe47d9..b704afd 100644 --- a/Source/SwiftRegex.swift +++ b/Source/SwiftRegex.swift @@ -18,7 +18,7 @@ infix operator <~ { associativity none precedence 130 } private let lock = dispatch_semaphore_create(1) private var swiftRegexCache = [String: NSRegularExpression]() -internal final class SwiftRegex: NSObject, BooleanType { +internal final class SwiftRegex : NSObject, BooleanType { var target: String var regex: NSRegularExpression From 2f1f77141ec2440b3a50def206fc78e1f481fe66 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Mar 2016 10:00:14 -0400 Subject: [PATCH 06/10] add test for objc api --- .../project.pbxproj | 7 ++- SocketIO-MacTests/SocketObjectiveCTest.m | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 SocketIO-MacTests/SocketObjectiveCTest.m diff --git a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj index edd4894..b60ca29 100644 --- a/Socket.IO-Client-Swift.xcodeproj/project.pbxproj +++ b/Socket.IO-Client-Swift.xcodeproj/project.pbxproj @@ -116,6 +116,7 @@ 7420CB791C49629E00956AA4 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */; }; 7420CB7A1C49629E00956AA4 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */; }; 7420CB7B1C49629E00956AA4 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */; }; + 742D150C1CA5794B00BD987D /* SocketObjectiveCTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 742D150B1CA5794B00BD987D /* SocketObjectiveCTest.m */; }; 74321DCB1C2D939A00CF6F43 /* SocketAckManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74321DC91C2D939A00CF6F43 /* SocketAckManagerTest.swift */; }; 74321DCC1C2D939A00CF6F43 /* SocketParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74321DCA1C2D939A00CF6F43 /* SocketParserTest.swift */; }; 7471CCEA1C39926300364B59 /* SocketClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74ABF7761C3991C10078C657 /* SocketClientSpec.swift */; }; @@ -187,6 +188,7 @@ 74171E621C10CD240062D398 /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = Source/WebSocket.swift; sourceTree = ""; }; 741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = ""; }; 7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketEnginePollable.swift; path = Source/SocketEnginePollable.swift; sourceTree = ""; }; + 742D150B1CA5794B00BD987D /* SocketObjectiveCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SocketObjectiveCTest.m; sourceTree = ""; }; 74321DC91C2D939A00CF6F43 /* SocketAckManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketAckManagerTest.swift; sourceTree = ""; }; 74321DCA1C2D939A00CF6F43 /* SocketParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketParserTest.swift; sourceTree = ""; }; 7472C65B1BCAB53E003CA70D /* SocketNamespacePacketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespacePacketTest.swift; sourceTree = ""; }; @@ -326,6 +328,7 @@ 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */, 741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */, 7472C65B1BCAB53E003CA70D /* SocketNamespacePacketTest.swift */, + 742D150B1CA5794B00BD987D /* SocketObjectiveCTest.m */, 74321DCA1C2D939A00CF6F43 /* SocketParserTest.swift */, 7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */, 572EF2471B51F18A00EEBB58 /* Supporting Files */, @@ -513,7 +516,7 @@ 572EF20E1B51F12F00EEBB58 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0710; + LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0720; TargetAttributes = { 572EF2181B51F16C00EEBB58 = { @@ -687,6 +690,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 742D150C1CA5794B00BD987D /* SocketObjectiveCTest.m in Sources */, 74321DCB1C2D939A00CF6F43 /* SocketAckManagerTest.swift in Sources */, 74321DCC1C2D939A00CF6F43 /* SocketParserTest.swift in Sources */, 7472C6601BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */, @@ -1169,6 +1173,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; diff --git a/SocketIO-MacTests/SocketObjectiveCTest.m b/SocketIO-MacTests/SocketObjectiveCTest.m new file mode 100644 index 0000000..8372112 --- /dev/null +++ b/SocketIO-MacTests/SocketObjectiveCTest.m @@ -0,0 +1,45 @@ +// +// SocketObjectiveCTest.m +// Socket.IO-Client-Swift +// +// Created by Erik Little on 3/25/16. +// +// Merely tests whether the Objective-C api breaks +// + +#import +@import SocketIOClientSwift; + +@interface SocketObjectiveCTest : XCTestCase + +@property SocketIOClient* socket; + +@end + +@implementation SocketObjectiveCTest + +- (void)setUp { + [super setUp]; + NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"]; + self.socket = [[SocketIOClient alloc] initWithSocketURL:url options:nil]; +} + +- (void)testOnSyntax { + [self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) { + [ack with:@[@1]]; + }]; +} + +- (void)testEmitSyntax { + [self.socket emit:@"testEmit" withItems:@[@YES]]; +} + +- (void)testEmitWithAckSyntax { + [self.socket emitWithAck:@"testAckEmit" withItems:@[@YES]]; +} + +- (void)testOffSyntax { + [self.socket off:@"test"]; +} + +@end From baca9fc8da134f8ec8ef39caac72368f7bae4288 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 31 Mar 2016 21:31:24 -0400 Subject: [PATCH 07/10] small refactors --- Source/SocketIOClient.swift | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 12bd49d..183bcc3 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -164,10 +164,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable return {[weak self, ack = currentAck] timeout, callback in if let this = self { this.ackHandlers.addAck(ack, callback: callback) - - dispatch_async(this.emitQueue) { - this._emit(items, ack: ack) - } + this._emit(items, ack: ack) if timeout != 0 { let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * NSEC_PER_SEC)) @@ -223,9 +220,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable return } - dispatch_async(emitQueue) {[emitData = [event] + items] in - self._emit(emitData) - } + _emit([event] + items) } /** @@ -244,17 +239,19 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable } private func _emit(data: [AnyObject], ack: Int? = nil) { - guard status == .Connected else { - handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) - return + dispatch_async(emitQueue) { + guard self.status == .Connected else { + self.handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) + return + } + + let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: self.nsp, ack: false) + let str = packet.packetString + + DefaultSocketLogger.Logger.log("Emitting: %@", type: self.logType, args: str) + + self.engine?.send(str, withData: packet.binary) } - - let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false) - let str = packet.packetString - - DefaultSocketLogger.Logger.log("Emitting: %@", type: logType, args: str) - - engine?.send(str, withData: packet.binary) } // If the server wants to know that the client received data @@ -295,7 +292,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable // Called when the socket gets an ack for something it sent func handleAck(ack: Int, data: [AnyObject]) { - guard status == .Connected else {return} + guard status == .Connected else { return } DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: logType, args: ack, data ?? "") @@ -427,9 +424,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable } if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects { - didDisconnect("Reconnect Failed") - - return + return didDisconnect("Reconnect Failed") } DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType) From 4ee196c5fb7f6ccfea4f7dc0d7c0139b3067ea7b Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 4 Apr 2016 11:28:20 -0400 Subject: [PATCH 08/10] add default value to namespace in socketparsable --- Source/SocketIOClient.swift | 10 +++------- Source/SocketParsable.swift | 11 ++++++----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 183bcc3..5d36444 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -223,17 +223,13 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable _emit([event] + items) } - /** - Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add - an ack. - */ + /// Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add + /// an ack. public func emitWithAck(event: String, _ items: AnyObject...) -> OnAckCallback { return emitWithAck(event, withItems: items) } - /** - Same as emitWithAck, but for Objective-C - */ + /// Same as emitWithAck, but for Objective-C public func emitWithAck(event: String, withItems items: [AnyObject]) -> OnAckCallback { return createOnAck([event] + items) } diff --git a/Source/SocketParsable.swift b/Source/SocketParsable.swift index 537a614..cd539a1 100644 --- a/Source/SocketParsable.swift +++ b/Source/SocketParsable.swift @@ -76,7 +76,7 @@ extension SocketParsable { return .Right(SocketPacket(type: type, nsp: "/")) } - var namespace: String? + var namespace = "/" var placeholders = -1 if type == .BinaryEvent || type == .BinaryAck { @@ -119,23 +119,24 @@ extension SocketParsable { // If first you don't succeed, try again if case let .Right(data) = parseData("\([noPlaceholders as AnyObject])") { return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, - nsp: namespace ?? "/", placeholders: placeholders)) + nsp: namespace, placeholders: placeholders)) } else { return .Left(err) } case let .Right(data): return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, - nsp: namespace ?? "/", placeholders: placeholders)) + nsp: namespace, placeholders: placeholders)) } } // Parses data for events private func parseData(data: String) -> Either { let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) + do { if let arr = try NSJSONSerialization.JSONObjectWithData(stringData!, - options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] { - return .Right(arr) + options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] { + return .Right(arr) } else { return .Left("Expected data array") } From ed3d49001f34d09768b983f677b0a2276ed7f245 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 10 Apr 2016 13:59:21 -0400 Subject: [PATCH 09/10] bump websocket version --- SocketIO-MacTests/SocketParserTest.swift | 6 ++ Source/SocketParsable.swift | 2 +- Source/WebSocket.swift | 74 +++++++++++++++--------- 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/SocketIO-MacTests/SocketParserTest.swift b/SocketIO-MacTests/SocketParserTest.swift index 9513fcd..b205556 100644 --- a/SocketIO-MacTests/SocketParserTest.swift +++ b/SocketIO-MacTests/SocketParserTest.swift @@ -25,6 +25,7 @@ class SocketParserTest: XCTestCase { "0/swift": ("/swift", [], [], -1), "1/swift": ("/swift", [], [], -1), "4\"ERROR\"": ("/", ["ERROR"], [], -1), + "4{\"test\":2}": ("/", [["test": 2]], [], -1), "41": ("/", [1], [], -1)] func testDisconnect() { @@ -87,6 +88,11 @@ class SocketParserTest: XCTestCase { validateParseResult(message) } + func testErrorTypeDictionary() { + let message = "4{\"test\":2}" + validateParseResult(message) + } + func testErrorTypeInt() { let message = "41" validateParseResult(message) diff --git a/Source/SocketParsable.swift b/Source/SocketParsable.swift index cd539a1..1c4084a 100644 --- a/Source/SocketParsable.swift +++ b/Source/SocketParsable.swift @@ -116,7 +116,7 @@ extension SocketParsable { switch parseData(noPlaceholders) { case let .Left(err): - // If first you don't succeed, try again + // Errors aren't always enclosed in an array if case let .Right(data) = parseData("\([noPlaceholders as AnyObject])") { return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, nsp: namespace, placeholders: placeholders)) diff --git a/Source/WebSocket.swift b/Source/WebSocket.swift index 163ce7a..833eece 100644 --- a/Source/WebSocket.swift +++ b/Source/WebSocket.swift @@ -180,30 +180,42 @@ public class WebSocket : NSObject, NSStreamDelegate { } } - ///write a string to the websocket. This sends it as a text frame. - public func writeString(str: String) { + /** + Write a string to the websocket. This sends it as a text frame. + + If you supply a non-nil completion block, I will perform it when the write completes. + - parameter str: The string to write. + - parameter completion: The (optional) completion handler. + */ + public func writeString(str: String, completion: (() -> ())? = nil) { guard isConnected else { return } - dequeueWrite(str.dataUsingEncoding(NSUTF8StringEncoding)!, code: .TextFrame) + dequeueWrite(str.dataUsingEncoding(NSUTF8StringEncoding)!, code: .TextFrame, writeCompletion: completion) } - ///write binary data to the websocket. This sends it as a binary frame. - public func writeData(data: NSData) { + /** + Write binary data to the websocket. This sends it as a binary frame. + + If you supply a non-nil completion block, I will perform it when the write completes. + - parameter data: The data to write. + - parameter completion: The (optional) completion handler. + */ + public func writeData(data: NSData, completion: (() -> ())? = nil) { guard isConnected else { return } - dequeueWrite(data, code: .BinaryFrame) + dequeueWrite(data, code: .BinaryFrame, writeCompletion: completion) } //write a ping to the websocket. This sends it as a control frame. //yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s - public func writePing(data: NSData) { + public func writePing(data: NSData, completion: (() -> ())? = nil) { guard isConnected else { return } - dequeueWrite(data, code: .Ping) + dequeueWrite(data, code: .Ping, writeCompletion: completion) } //private method that starts the connection private func createHTTPRequest() { let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET", - url, kCFHTTPVersion1_1).takeRetainedValue() + url, kCFHTTPVersion1_1).takeRetainedValue() var port = url.port if port == nil { @@ -283,18 +295,18 @@ public class WebSocket : NSObject, NSStreamDelegate { if let cipherSuites = self.enabledSSLCipherSuites { if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContextRef?, sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContextRef? { - let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count) - let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count) - if resIn != errSecSuccess { - let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn)) - disconnectStream(error) - return - } - if resOut != errSecSuccess { - let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut)) - disconnectStream(error) - return - } + let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count) + let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count) + if resIn != errSecSuccess { + let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn)) + disconnectStream(error) + return + } + if resOut != errSecSuccess { + let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut)) + disconnectStream(error) + return + } } } CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue) @@ -428,7 +440,7 @@ public class WebSocket : NSObject, NSStreamDelegate { } case -1: fragBuffer = NSData(bytes: buffer, length: bufferLen) - break //do nothing, we are going to collect more data + break //do nothing, we are going to collect more data default: doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: UInt16(code))) } @@ -547,10 +559,10 @@ public class WebSocket : NSObject, NSStreamDelegate { let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping) if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame && receivedOpcode != .TextFrame && receivedOpcode != .Pong) { - let errCode = CloseCode.ProtocolError.rawValue - doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode)) - writeError(errCode) - return + let errCode = CloseCode.ProtocolError.rawValue + doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode)) + writeError(errCode) + return } if isControlFrame && isFin == 0 { let errCode = CloseCode.ProtocolError.rawValue @@ -603,7 +615,7 @@ public class WebSocket : NSObject, NSStreamDelegate { if dataLength > UInt64(bufferLen) { len = UInt64(bufferLen-offset) } - var data: NSData! + let data: NSData if len < 0 { len = 0 data = NSData() @@ -739,7 +751,7 @@ public class WebSocket : NSObject, NSStreamDelegate { dequeueWrite(NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose) } ///used to write things to the stream - private func dequeueWrite(data: NSData, code: OpCode) { + private func dequeueWrite(data: NSData, code: OpCode, writeCompletion: (() -> ())? = nil) { writeQueue.addOperationWithBlock { [weak self] in //stream isn't ready, let's wait guard let s = self else { return } @@ -788,6 +800,12 @@ public class WebSocket : NSObject, NSStreamDelegate { total += len } if total >= offset { + if let queue = self?.queue, callback = writeCompletion { + dispatch_async(queue) { + callback() + } + } + break } } From 30731305989a65b20a3ab535346e6094aa75b7c1 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 11 Apr 2016 18:51:22 -0400 Subject: [PATCH 10/10] change to how server gives id --- Source/SocketIOClient.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 5d36444..99fa5f8 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -46,7 +46,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable public var reconnects = true public var reconnectWait = 10 public var sid: String? { - return engine?.sid + return nsp + "#" + (engine?.sid ?? "") } private let emitQueue = dispatch_queue_create("com.socketio.emitQueue", DISPATCH_QUEUE_SERIAL)