From 7e494f4bcb135be5b4f57c6538e590ced8391688 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 21:20:34 -0400 Subject: [PATCH 1/5] add ignore for appcode --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 9f4b1d3..069348b 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ DerivedData *.xcuserstate Socket.IO-Test-Server/node_modules/* + +.idea/ From ed049e888d5d83c784540c1980a4d259614a823c Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 3 May 2017 22:48:25 -0400 Subject: [PATCH 2/5] Make engine single queued Fix polling allow building of refactor branch remove self reference Some refactoring --- .travis.yml | 1 + Source/SocketEngine.swift | 113 +++++++++++++++------------- Source/SocketEnginePollable.swift | 119 ++++++++++++++---------------- Source/SocketEngineSpec.swift | 4 +- 4 files changed, 119 insertions(+), 118 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c99082..cd54215 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ branches: only: - master - development + - refactor-engine before_install: - brew update - brew outdated xctool || brew upgrade xctool diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 02b1d81..cd1e8d0 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -22,12 +22,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket { - public let emitQueue = DispatchQueue(label: "com.socketio.engineEmitQueue", attributes: []) - public let handleQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: []) - public let parseQueue = DispatchQueue(label: "com.socketio.engineParseQueue", attributes: []) + public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: []) public var connectParams: [String: Any]? { didSet { @@ -101,7 +100,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll forceWebsockets = force case let .path(path): socketPath = path - + if !socketPath.hasSuffix("/") { socketPath += "/" } @@ -119,12 +118,12 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll } super.init() - + sessionDelegate = sessionDelegate ?? self - + (urlPolling, urlWebSocket) = createURLs() } - + public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) { self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? []) } @@ -139,7 +138,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll do { let dict = try msg.toNSDictionary() guard let error = dict["message"] as? String else { return } - + /* 0: Unknown transport 1: Unknown sid @@ -155,7 +154,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll private func handleBase64(message: String) { // binary in base64 string let noPrefix = message[message.index(message.startIndex, offsetBy: 2).. pongsMissedMax { client?.engineDidClose(reason: "Ping timeout") - + return } guard let pingInterval = pingInterval else { return } - + pongsMissed += 1 write("", withType: .ping, withData: []) - - let time = DispatchTime.now() + Double(Int64(pingInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC) - DispatchQueue.main.asyncAfter(deadline: time) {[weak self] in self?.sendPing() } + + engineQueue.asyncAfter(deadline: DispatchTime.now() + Double(pingInterval)) {[weak self] in self?.sendPing() } } // Moves from long-polling to websockets @@ -501,16 +508,16 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll /// Write a message, independent of transport. public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) { - emitQueue.async { + engineQueue.async { guard self.connected else { return } if self.websocket { DefaultSocketLogger.Logger.log("Writing ws: %@ has data: %@", - type: self.logType, args: msg, data.count != 0) + type: self.logType, args: msg, data.count != 0) self.sendWebSocketMessage(msg, withType: type, withData: data) } else if !self.probing { DefaultSocketLogger.Logger.log("Writing poll: %@ has data: %@", - type: self.logType, args: msg, data.count != 0) + type: self.logType, args: msg, data.count != 0) self.sendPollMessage(msg, withType: type, withData: data) } else { self.probeWait.append((msg, type, data)) @@ -535,7 +542,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll if closed { client?.engineDidClose(reason: "Disconnect") - + return } @@ -557,7 +564,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll extension SocketEngine { public func URLSession(session: URLSession, didBecomeInvalidWithError error: NSError?) { DefaultSocketLogger.Logger.error("Engine URLSession became invalid", type: "SocketEngine") - + didError(reason: "Engine URLSession became invalid") } } diff --git a/Source/SocketEnginePollable.swift b/Source/SocketEnginePollable.swift index b050975..4bb4905 100644 --- a/Source/SocketEnginePollable.swift +++ b/Source/SocketEnginePollable.swift @@ -27,7 +27,7 @@ import Foundation /// Protocol that is used to implement socket.io polling support public protocol SocketEnginePollable : SocketEngineSpec { var invalidated: Bool { get } - /// Holds strings waiting to be sent over polling. + /// Holds strings waiting to be sent over polling. /// You shouldn't need to mess with this. var postWait: [String] { get set } var session: URLSession? { get } @@ -37,7 +37,7 @@ public protocol SocketEnginePollable : SocketEngineSpec { /// Because socket.io doesn't let you send two post request at the same time /// we have to keep track if there's an outstanding post var waitingForPost: Bool { get set } - + func doPoll() func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) func stopPolling() @@ -47,95 +47,94 @@ public protocol SocketEnginePollable : SocketEngineSpec { extension SocketEnginePollable { private func addHeaders(for req: URLRequest) -> URLRequest { var req = req - + if cookies != nil { let headers = HTTPCookie.requestHeaderFields(with: cookies!) req.allHTTPHeaderFields = headers } - + if extraHeaders != nil { for (headerName, value) in extraHeaders! { req.setValue(value, forHTTPHeaderField: headerName) } } - + return req } - + func createRequestForPostWithPostWait() -> URLRequest { defer { postWait.removeAll(keepingCapacity: true) } var postStr = "" - + for packet in postWait { let len = packet.characters.count - + postStr += "\(len):\(packet)" } - + DefaultSocketLogger.Logger.log("Created POST string: %@", type: "SocketEnginePolling", args: postStr) - + var req = URLRequest(url: urlPollingWithSid) let postData = postStr.data(using: .utf8, allowLossyConversion: false)! - + req = addHeaders(for: req) - + req.httpMethod = "POST" req.setValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type") req.httpBody = postData req.setValue(String(postData.count), forHTTPHeaderField: "Content-Length") - - return req as URLRequest + + return req } - + public func doPoll() { if websocket || waitingForPoll || !connected || closed { return } - - waitingForPoll = true - + var req = URLRequest(url: urlPollingWithSid) - req = addHeaders(for: req) + doLongPoll(for: req ) } - + func doRequest(for req: URLRequest, callbackWith callback: @escaping (Data?, URLResponse?, Error?) -> Void) { if !polling || closed || invalidated || fastUpgrade { return } - - DefaultSocketLogger.Logger.log("Doing polling request", type: "SocketEnginePolling") - + + DefaultSocketLogger.Logger.log("Doing polling %@ %@", type: "SocketEnginePolling", + args: req.httpMethod ?? "", req) + session?.dataTask(with: req, completionHandler: callback).resume() } - + func doLongPoll(for req: URLRequest) { + waitingForPoll = true + doRequest(for: req) {[weak self] data, res, err in guard let this = self, this.polling else { return } - + if err != nil || data == nil { DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling") - + if this.polling { this.didError(reason: err?.localizedDescription ?? "Error") } - + return } - + DefaultSocketLogger.Logger.log("Got polling response", type: "SocketEnginePolling") - + if let str = String(data: data!, encoding: String.Encoding.utf8) { - this.parseQueue.async { - this.parsePollingMessage(str) - } + this.parsePollingMessage(str) } - + this.waitingForPoll = false - + if this.fastUpgrade { this.doFastUpgrade() } else if !this.closed && this.polling { @@ -143,7 +142,7 @@ extension SocketEnginePollable { } } } - + private func flushWaitingForPost() { if postWait.count == 0 || !connected { return @@ -151,79 +150,75 @@ extension SocketEnginePollable { flushWaitingForPostToWebSocket() return } - + let req = createRequestForPostWithPostWait() - + waitingForPost = true - + DefaultSocketLogger.Logger.log("POSTing", type: "SocketEnginePolling") - + doRequest(for: req) {[weak self] data, res, err in guard let this = self else { return } - + if err != nil { DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling") - + if this.polling { this.didError(reason: err?.localizedDescription ?? "Error") } - + return } - + this.waitingForPost = false - - this.emitQueue.async { - if !this.fastUpgrade { - this.flushWaitingForPost() - this.doPoll() - } + + if !this.fastUpgrade { + this.flushWaitingForPost() + this.doPoll() } } } - + func parsePollingMessage(_ str: String) { guard str.characters.count != 1 else { return } - + var reader = SocketStringReader(message: str) - + while reader.hasNext { if let n = Int(reader.readUntilOccurence(of: ":")) { - let str = reader.read(count: n) - - handleQueue.async { self.parseEngineMessage(str, fromPolling: true) } + parseEngineMessage(reader.read(count: n), fromPolling: true) } else { - handleQueue.async { self.parseEngineMessage(str, fromPolling: true) } + parseEngineMessage(str, fromPolling: true) break } } } - + /// Send polling message. /// Only call on emitQueue public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) { DefaultSocketLogger.Logger.log("Sending poll: %@ as type: %@", type: "SocketEnginePolling", args: message, type.rawValue) let fixedMessage: String - + if doubleEncodeUTF8 { fixedMessage = doubleEncodeUTF8(message) } else { fixedMessage = message } - + postWait.append(String(type.rawValue) + fixedMessage) - + for data in datas { if case let .right(bin) = createBinaryDataForSend(using: data) { postWait.append(bin) } } - + if !waitingForPost { flushWaitingForPost() } } - + public func stopPolling() { waitingForPoll = false waitingForPost = false diff --git a/Source/SocketEngineSpec.swift b/Source/SocketEngineSpec.swift index f862889..46a7947 100644 --- a/Source/SocketEngineSpec.swift +++ b/Source/SocketEngineSpec.swift @@ -32,15 +32,13 @@ import Foundation var connectParams: [String: Any]? { get set } var doubleEncodeUTF8: Bool { get } var cookies: [HTTPCookie]? { get } + var engineQueue: DispatchQueue { get } var extraHeaders: [String: String]? { get } var fastUpgrade: Bool { get } var forcePolling: Bool { get } var forceWebsockets: Bool { get } - var parseQueue: DispatchQueue { get } var polling: Bool { get } var probing: Bool { get } - var emitQueue: DispatchQueue { get } - var handleQueue: DispatchQueue { get } var sid: String { get } var socketPath: String { get } var urlPolling: URL { get } From 84dd3078d80d4a84f6ab41af4c70bcbc3bf78c28 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 21:07:34 -0400 Subject: [PATCH 3/5] Make client single queued Shouldn't need to protoct ack generation now that client is single queued --- Source/SocketAckEmitter.swift | 36 ++++----- Source/SocketIOClient.swift | 135 +++++++++++++++----------------- Source/SocketIOClientSpec.swift | 7 +- 3 files changed, 84 insertions(+), 94 deletions(-) diff --git a/Source/SocketAckEmitter.swift b/Source/SocketAckEmitter.swift index 4af43e7..9dead5c 100644 --- a/Source/SocketAckEmitter.swift +++ b/Source/SocketAckEmitter.swift @@ -22,6 +22,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation public final class SocketAckEmitter : NSObject { @@ -31,57 +32,52 @@ public final class SocketAckEmitter : NSObject { public var expected: Bool { return ackNum != -1 } - + init(socket: SocketIOClient, ackNum: Int) { self.socket = socket self.ackNum = ackNum } - + public func with(_ items: SocketData...) { guard ackNum != -1 else { return } - + socket.emitAck(ackNum, with: items) } - + public func with(_ items: [Any]) { guard ackNum != -1 else { return } - + socket.emitAck(ackNum, with: items) } - + } public final class OnAckCallback : NSObject { private let ackNumber: Int private let items: [Any] private weak var socket: SocketIOClient? - + init(ackNumber: Int, items: [Any], socket: SocketIOClient) { self.ackNumber = ackNumber self.items = items self.socket = socket } - + deinit { DefaultSocketLogger.Logger.log("OnAckCallback for \(ackNumber) being released", type: "OnAckCallback") } - + public func timingOut(after seconds: Int, callback: @escaping AckCallback) { guard let socket = self.socket else { return } - - socket.ackQueue.sync() { - socket.ackHandlers.addAck(ackNumber, callback: callback) - } - + + socket.ackHandlers.addAck(ackNumber, callback: callback) socket._emit(items, ack: ackNumber) - + guard seconds != 0 else { return } - - let time = DispatchTime.now() + Double(UInt64(seconds) * NSEC_PER_SEC) / Double(NSEC_PER_SEC) - - socket.handleQueue.asyncAfter(deadline: time) { + + socket.handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(seconds)) { socket.ackHandlers.timeoutAck(self.ackNumber, onQueue: socket.handleQueue) } } - + } diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 31f0c37..f23b42b 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -22,6 +22,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch import Foundation public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { @@ -41,43 +42,38 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } public var forceNew = false + public var handleQueue = DispatchQueue.main public var nsp = "/" public var config: SocketIOClientConfiguration public var reconnects = true public var reconnectWait = 10 private let logType = "SocketIOClient" - private let parseQueue = DispatchQueue(label: "com.socketio.parseQueue") private var anyHandler: ((SocketAnyEvent) -> Void)? private var currentReconnectAttempt = 0 private var handlers = [SocketEventHandler]() private var reconnecting = false - private let ackSemaphore = DispatchSemaphore(value: 1) private(set) var currentAck = -1 - private(set) var handleQueue = DispatchQueue.main private(set) var reconnectAttempts = -1 - - let ackQueue = DispatchQueue(label: "com.socketio.ackQueue") - let emitQueue = DispatchQueue(label: "com.socketio.emitQueue") var ackHandlers = SocketAckManager() var waitingPackets = [SocketPacket]() - + public var sid: String? { return engine?.sid } - + /// Type safe way to create a new SocketIOClient. opts can be omitted public init(socketURL: URL, config: SocketIOClientConfiguration = []) { self.config = config self.socketURL = socketURL - + if socketURL.absoluteString.hasPrefix("https://") { self.config.insert(.secure(true)) } - + for option in config { switch option { case let .reconnects(reconnects): @@ -102,10 +98,10 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } self.config.insert(.path("/socket.io/"), replacing: false) - + super.init() } - + /// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. /// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set)` public convenience init(socketURL: NSURL, config: NSDictionary?) { @@ -148,30 +144,25 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } else { engine?.connect() } - + guard timeoutAfter != 0 else { return } let time = DispatchTime.now() + Double(UInt64(timeoutAfter) * NSEC_PER_SEC) / Double(NSEC_PER_SEC) handleQueue.asyncAfter(deadline: time) {[weak self] in guard let this = self, this.status != .connected && this.status != .disconnected else { return } - + this.status = .disconnected this.engine?.disconnect(reason: "Connect timeout") - + handler?() } } - private func nextAck() -> Int { - ackSemaphore.wait() - defer { ackSemaphore.signal() } - currentAck += 1 - return currentAck - } - private func createOnAck(_ items: [Any]) -> OnAckCallback { - return OnAckCallback(ackNumber: nextAck(), items: items, socket: self) + currentAck += 1 + + return OnAckCallback(ackNumber: currentAck, items: items, socket: self) } func didConnect() { @@ -214,7 +205,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true) return } - + _emit([event] + items) } @@ -230,40 +221,40 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } func _emit(_ data: [Any], ack: Int? = nil) { - emitQueue.async { - 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) + guard status == .connected else { + handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) + return } + + 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 func emitAck(_ ack: Int, with items: [Any]) { - emitQueue.async { - guard self.status == .connected else { return } - - let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: self.nsp, ack: true) - let str = packet.packetString - - DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: self.logType, args: str) - - self.engine?.send(str, withData: packet.binary) - } + guard status == .connected else { return } + + let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: nsp, ack: true) + let str = packet.packetString + + DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: logType, args: str) + + engine?.send(str, withData: packet.binary) } public func engineDidClose(reason: String) { - parseQueue.async { - self.waitingPackets.removeAll() + handleQueue.async { + self._engineDidClose(reason: reason) } - + } + + private func _engineDidClose(reason: String) { + waitingPackets.removeAll() + if status != .disconnected { status = .notConnected } @@ -276,13 +267,19 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } } - /// error public func engineDidError(reason: String) { + handleQueue.async { + self._engineDidError(reason: reason) + } + } + + /// error + private func _engineDidError(reason: String) { DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) handleEvent("error", data: [reason], isInternalMessage: true) } - + public func engineDidOpen(reason: String) { DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient") } @@ -293,9 +290,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: logType, args: ack, data) - handleQueue.async() { - self.ackHandlers.executeAck(ack, with: data, onQueue: self.handleQueue) - } + ackHandlers.executeAck(ack, with: data, onQueue: handleQueue) } /// Causes an event to be handled. Only use if you know what you're doing. @@ -304,12 +299,10 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data) - handleQueue.async { - self.anyHandler?(SocketAnyEvent(event: event, items: data)) + anyHandler?(SocketAnyEvent(event: event, items: data)) - for handler in self.handlers where handler.event == event { - handler.executeCallback(with: data, withAck: ack, withSocket: self) - } + for handler in handlers where handler.event == event { + handler.executeCallback(with: data, withAck: ack, withSocket: self) } } @@ -384,17 +377,17 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl public func parseEngineMessage(_ msg: String) { DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg) - parseQueue.async { self.parseSocketMessage(msg) } + handleQueue.async { self.parseSocketMessage(msg) } } public func parseEngineBinaryData(_ data: Data) { - parseQueue.async { self.parseBinaryData(data) } + handleQueue.async { self.parseBinaryData(data) } } /// Tries to reconnect to the server. public func reconnect() { guard !reconnecting else { return } - + engine?.disconnect(reason: "manual reconnect") } @@ -409,7 +402,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl DefaultSocketLogger.Logger.log("Starting reconnect", type: logType) handleEvent("reconnect", data: [reason], isInternalMessage: true) - + _tryReconnect() } @@ -425,26 +418,24 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl currentReconnectAttempt += 1 connect() - - let deadline = DispatchTime.now() + Double(Int64(UInt64(reconnectWait) * NSEC_PER_SEC)) / Double(NSEC_PER_SEC) - - DispatchQueue.main.asyncAfter(deadline: deadline, execute: _tryReconnect) + + handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(reconnectWait), execute: _tryReconnect) } - + // Test properties - + var testHandlers: [SocketEventHandler] { return handlers } - + func setTestable() { status = .connected } - + func setTestEngine(_ engine: SocketEngineSpec?) { self.engine = engine } - + func emitTest(event: String, _ data: Any...) { _emit([event] + data) } diff --git a/Source/SocketIOClientSpec.swift b/Source/SocketIOClientSpec.swift index e91c840..539c4ec 100644 --- a/Source/SocketIOClientSpec.swift +++ b/Source/SocketIOClientSpec.swift @@ -22,10 +22,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +import Dispatch + protocol SocketIOClientSpec : class { + var handleQueue: DispatchQueue { get set } var nsp: String { get set } var waitingPackets: [SocketPacket] { get set } - + func didConnect() func didDisconnect(reason: String) func didError(reason: String) @@ -37,7 +40,7 @@ protocol SocketIOClientSpec : class { extension SocketIOClientSpec { func didError(reason: String) { DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason) - + handleEvent("error", data: [reason], isInternalMessage: true, withAck: -1) } } From abdffb9a4f1831dee17bd382fe6de269d8c201eb Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 21:19:52 -0400 Subject: [PATCH 4/5] Open client --- Source/SocketIOClient.swift | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index f23b42b..6494656 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -25,7 +25,7 @@ import Dispatch import Foundation -public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { +open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable { public let socketURL: URL public private(set) var engine: SocketEngineSpec? @@ -123,13 +123,13 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Connect to the server. - public func connect() { + open func connect() { connect(timeoutAfter: 0, withHandler: nil) } /// Connect to the server. If we aren't connected after timeoutAfter, call withHandler /// 0 Never times out - public func connect(timeoutAfter: Int, withHandler handler: (() -> Void)?) { + open func connect(timeoutAfter: Int, withHandler handler: (() -> Void)?) { assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)") guard status != .connected else { @@ -188,19 +188,19 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Disconnects the socket. - public func disconnect() { + open func disconnect() { DefaultSocketLogger.Logger.log("Closing socket", type: logType) didDisconnect(reason: "Disconnect") } /// Send a message to the server - public func emit(_ event: String, _ items: SocketData...) { + open func emit(_ event: String, _ items: SocketData...) { emit(event, with: items) } /// Same as emit, but meant for Objective-C - public func emit(_ event: String, with items: [Any]) { + open func emit(_ event: String, with items: [Any]) { guard status == .connected else { handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true) return @@ -211,12 +211,12 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// 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: SocketData...) -> OnAckCallback { + open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { return emitWithAck(event, with: items) } /// Same as emitWithAck, but for Objective-C - public func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback { + open func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback { return createOnAck([event] + items) } @@ -246,7 +246,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl engine?.send(str, withData: packet.binary) } - public func engineDidClose(reason: String) { + open func engineDidClose(reason: String) { handleQueue.async { self._engineDidClose(reason: reason) } @@ -267,7 +267,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } } - public func engineDidError(reason: String) { + open func engineDidError(reason: String) { handleQueue.async { self._engineDidError(reason: reason) } @@ -280,7 +280,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl handleEvent("error", data: [reason], isInternalMessage: true) } - public func engineDidOpen(reason: String) { + open func engineDidOpen(reason: String) { DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient") } @@ -294,7 +294,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Causes an event to be handled. Only use if you know what you're doing. - public func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) { + open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) { guard status == .connected || isInternalMessage else { return } DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data) @@ -307,7 +307,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Leaves nsp and goes back to / - public func leaveNamespace() { + open func leaveNamespace() { if nsp != "/" { engine?.send("1\(nsp)", withData: []) nsp = "/" @@ -315,7 +315,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Joins namespace - public func joinNamespace(_ namespace: String) { + open func joinNamespace(_ namespace: String) { nsp = namespace if nsp != "/" { @@ -325,14 +325,14 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Removes handler(s) based on name - public func off(_ event: String) { + open func off(_ event: String) { DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event) handlers = handlers.filter({ $0.event != event }) } /// Removes a handler with the specified UUID gotten from an `on` or `once` - public func off(id: UUID) { + open func off(id: UUID) { DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id) handlers = handlers.filter({ $0.id != id }) @@ -341,7 +341,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Adds a handler for an event. /// Returns: A unique id for the handler @discardableResult - public func on(_ event: String, callback: @escaping NormalCallback) -> UUID { + open func on(_ event: String, callback: @escaping NormalCallback) -> UUID { DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event) let handler = SocketEventHandler(event: event, id: UUID(), callback: callback) @@ -353,7 +353,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Adds a single-use handler for an event. /// Returns: A unique id for the handler @discardableResult - public func once(_ event: String, callback: @escaping NormalCallback) -> UUID { + open func once(_ event: String, callback: @escaping NormalCallback) -> UUID { DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event) let id = UUID() @@ -370,7 +370,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Adds a handler that will be called on every event. - public func onAny(_ handler: @escaping (SocketAnyEvent) -> Void) { + open func onAny(_ handler: @escaping (SocketAnyEvent) -> Void) { anyHandler = handler } @@ -385,7 +385,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl } /// Tries to reconnect to the server. - public func reconnect() { + open func reconnect() { guard !reconnecting else { return } engine?.disconnect(reason: "manual reconnect") @@ -393,7 +393,7 @@ public final class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineCl /// Removes all handlers. /// Can be used after disconnecting to break any potential remaining retain cycles. - public func removeAllHandlers() { + open func removeAllHandlers() { handlers.removeAll(keepingCapacity: false) } From 9edd322a70a09de6bfc0085fa3ff4766c99f710b Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 5 May 2017 22:09:59 -0400 Subject: [PATCH 5/5] remove refactor build --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cd54215..1c99082 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ branches: only: - master - development - - refactor-engine before_install: - brew update - brew outdated xctool || brew upgrade xctool