From dbc8b6fadce82a22acfa8db7cf90a0c93635feec Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 16 Jan 2016 15:04:03 -0500 Subject: [PATCH] refactor engine erroring --- SocketIO-MacTests/SocketEngineTest.swift | 24 +++++++++ Source/SocketClientSpec.swift | 11 +++- Source/SocketEngine.swift | 65 ++++++++++-------------- Source/SocketEngineClient.swift | 2 +- Source/SocketEnginePollable.swift | 7 +-- Source/SocketEngineSpec.swift | 1 + Source/SocketIOClient.swift | 44 ++++++++-------- 7 files changed, 89 insertions(+), 65 deletions(-) diff --git a/SocketIO-MacTests/SocketEngineTest.swift b/SocketIO-MacTests/SocketEngineTest.swift index 636b562..90a4c22 100644 --- a/SocketIO-MacTests/SocketEngineTest.swift +++ b/SocketIO-MacTests/SocketEngineTest.swift @@ -50,4 +50,28 @@ class SocketEngineTest: XCTestCase { engine.parsePollingMessage("15:42[\"blankTest\"]24:42[\"stringTest\",\"hello\"]") waitForExpectationsWithTimeout(3, handler: nil) } + + func testEngineDoesErrorOnUnknownTransport() { + let finalExpectation = expectationWithDescription("Unknown Transport") + + client.on("error") {data, ack in + if let error = data[0] as? String where error == "Unknown transport" { + finalExpectation.fulfill() + } + } + + engine.parseEngineMessage("{\"code\": 0, \"message\": \"Unknown transport\"}", fromPolling: false) + waitForExpectationsWithTimeout(3, handler: nil) + } + + func testEngineDoesErrorOnUnknownMessage() { + let finalExpectation = expectationWithDescription("Engine Errors") + + client.on("error") {data, ack in + finalExpectation.fulfill() + } + + engine.parseEngineMessage("afafafda", fromPolling: false) + waitForExpectationsWithTimeout(3, handler: nil) + } } diff --git a/Source/SocketClientSpec.swift b/Source/SocketClientSpec.swift index a0314b4..7a72cad 100644 --- a/Source/SocketClientSpec.swift +++ b/Source/SocketClientSpec.swift @@ -32,4 +32,13 @@ protocol SocketClientSpec: class { func handleAck(ack: Int, data: [AnyObject]) func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int) func joinNamespace(namespace: String) -} \ No newline at end of file +} + +extension SocketClientSpec { + func didError(reason: AnyObject) { + DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason) + + handleEvent("error", data: reason as? [AnyObject] ?? [reason], + isInternalMessage: true, withAck: -1) + } +} diff --git a/Source/SocketEngine.swift b/Source/SocketEngine.swift index 1f914fc..8bfd8a1 100644 --- a/Source/SocketEngine.swift +++ b/Source/SocketEngine.swift @@ -60,10 +60,8 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb private typealias ProbeWaitQueue = [Probe] private let allowedCharacterSet = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?%#[]\" {}").invertedSet - private let logType = "SocketEngine" private let url: String - private let workQueue = NSOperationQueue() private var connectParams: [String: AnyObject]? private var pingInterval: Double? @@ -132,20 +130,20 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb switch code { case 0: // Unknown transport - logAndError(error) + didError(error) case 1: // Unknown sid. clear and retry connect sid = "" open(connectParams) case 2: // Bad handshake request - logAndError(error) + didError(error) case 3: // Bad request - logAndError(error) + didError(error) default: - logAndError(error) + didError(error) } } } catch { - logAndError("Got unknown error from server") + didError("Got unknown error from server \(msg)") } } @@ -250,6 +248,17 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb ws?.connect() } } + + public func didError(error: String) { + connected = false + ws?.disconnect() + stopPolling() + pingTimer?.invalidate() + + DefaultSocketLogger.Logger.error(error, type: logType) + client?.engineDidError(error) + client?.engineDidClose(error) + } public func doFastUpgrade() { if waitingForPoll { @@ -331,18 +340,19 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb createWebsocketAndConnect(true) } + + startPingTimer() + + if !forceWebsockets { + doPoll() + } + client?.engineDidOpen?("Connect") } } catch { - DefaultSocketLogger.Logger.error("Error parsing open packet", type: logType) + didError("Error parsing open packet") return } - - startPingTimer() - - if !forceWebsockets { - doPoll() - } } private func handlePong(pongMessage: String) { @@ -354,31 +364,12 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb } } - // A poll failed, tell the client about it - public func handlePollingFailed(reason: String) { - connected = false - ws?.disconnect() - pingTimer?.invalidate() - waitingForPoll = false - waitingForPost = false - - if !closed { - client?.didError(reason) - client?.engineDidClose(reason) - } - } - - private func logAndError(error: String) { - DefaultSocketLogger.Logger.error(error, type: logType) - client?.didError(error) - } - public func open(opts: [String: AnyObject]? = nil) { connectParams = opts if connected { DefaultSocketLogger.Logger.error("Tried to open while connected", type: logType) - client?.didError("Tried to open engine while connected") + didError("Tried to open engine while connected") return } @@ -463,7 +454,7 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb invalidated = false session = NSURLSession(configuration: .defaultSessionConfiguration(), delegate: sessionDelegate, - delegateQueue: workQueue) + delegateQueue: NSOperationQueue()) sid = "" waitingForPoll = false waitingForPost = false @@ -533,7 +524,7 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb } } - // Delagate methods + // Delegate methods public func websocketDidConnect(socket: WebSocket) { if !forceWebsockets { probing = true @@ -561,7 +552,7 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb let reason = error?.localizedDescription ?? "Socket Disconnected" if error != nil { - client?.didError(reason) + didError(reason) } client?.engineDidClose(reason) diff --git a/Source/SocketEngineClient.swift b/Source/SocketEngineClient.swift index 74956aa..f2b997c 100644 --- a/Source/SocketEngineClient.swift +++ b/Source/SocketEngineClient.swift @@ -26,7 +26,7 @@ import Foundation @objc public protocol SocketEngineClient { - func didError(reason: AnyObject) + func engineDidError(reason: AnyObject) func engineDidClose(reason: String) optional func engineDidOpen(reason: String) func parseEngineMessage(msg: String) diff --git a/Source/SocketEnginePollable.swift b/Source/SocketEnginePollable.swift index ca90c5d..0da2ed9 100644 --- a/Source/SocketEnginePollable.swift +++ b/Source/SocketEnginePollable.swift @@ -39,7 +39,6 @@ public protocol SocketEnginePollable: SocketEngineSpec { var waitingForPost: Bool { get set } func doPoll() - func handlePollingFailed(reason: String) func sendPollMessage(message: String, withType type: SocketEnginePacketType, withData datas: [NSData]) func stopPolling() } @@ -91,7 +90,7 @@ extension SocketEnginePollable { DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEngine") if this.polling { - this.handlePollingFailed(err?.localizedDescription ?? "Error") + this.didError(err?.localizedDescription ?? "Error") } return @@ -157,7 +156,7 @@ extension SocketEnginePollable { DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEngine") if this.polling { - this.handlePollingFailed(err?.localizedDescription ?? "Error") + this.didError(err?.localizedDescription ?? "Error") } return @@ -218,6 +217,8 @@ extension SocketEnginePollable { } public func stopPolling() { + waitingForPoll = false + waitingForPost = false session?.finishTasksAndInvalidate() } } diff --git a/Source/SocketEngineSpec.swift b/Source/SocketEngineSpec.swift index 365fdfc..f60fc52 100644 --- a/Source/SocketEngineSpec.swift +++ b/Source/SocketEngineSpec.swift @@ -49,6 +49,7 @@ import Foundation init(client: SocketEngineClient, url: String, options: NSDictionary?) func close() + func didError(error: String) func doFastUpgrade() func flushWaitingForPostToWebSocket() func open(opts: [String: AnyObject]?) diff --git a/Source/SocketIOClient.swift b/Source/SocketIOClient.swift index 16ab0a4..1b0228a 100644 --- a/Source/SocketIOClient.swift +++ b/Source/SocketIOClient.swift @@ -227,14 +227,6 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable handleEvent("disconnect", data: [reason], isInternalMessage: true) } - /// error - public func didError(reason: AnyObject) { - DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) - - handleEvent("error", data: reason as? [AnyObject] ?? [reason], - isInternalMessage: true) - } - /** Same as close */ @@ -318,6 +310,14 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable } } + /// error + public func engineDidError(reason: AnyObject) { + DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) + + handleEvent("error", data: reason as? [AnyObject] ?? [reason], + isInternalMessage: true) + } + // Called when the socket gets an ack for something it sent func handleAck(ack: Int, data: [AnyObject]) { guard status == .Connected else {return} @@ -330,22 +330,20 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketParsable /** Causes an event to be handled. Only use if you know what you're doing. */ - public func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, - withAck ack: Int = -1) { - guard status == .Connected || isInternalMessage else { - return + public func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int = -1) { + guard status == .Connected || isInternalMessage else { + return + } + + DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "") + + dispatch_async(handleQueue) { + self.anyHandler?(SocketAnyEvent(event: event, items: data)) + + for handler in self.handlers where handler.event == event { + handler.executeCallback(data, withAck: ack, withSocket: self) } - - DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "") - - dispatch_async(handleQueue) { - self.anyHandler?(SocketAnyEvent(event: event, items: data)) - - for handler in self.handlers where handler.event == event { - handler.executeCallback(data, withAck: ack, withSocket: self) - } - } - + } } /**