refactor engine erroring

This commit is contained in:
Erik 2016-01-16 15:04:03 -05:00
parent d15fb90950
commit dbc8b6fadc
7 changed files with 89 additions and 65 deletions

View File

@ -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)
}
}

View File

@ -33,3 +33,12 @@ protocol SocketClientSpec: class {
func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int)
func joinNamespace(namespace: String)
}
extension SocketClientSpec {
func didError(reason: AnyObject) {
DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason)
handleEvent("error", data: reason as? [AnyObject] ?? [reason],
isInternalMessage: true, withAck: -1)
}
}

View File

@ -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)")
}
}
@ -251,6 +249,17 @@ public final class SocketEngine: NSObject, SocketEnginePollable, SocketEngineWeb
}
}
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 {
DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," +
@ -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)

View File

@ -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)

View File

@ -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()
}
}

View File

@ -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]?)

View File

@ -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)
}
}
}
}
/**