diff --git a/SocketIOClientSwift/SocketEngine.swift b/SocketIOClientSwift/SocketEngine.swift index d2a34f9..f714059 100644 --- a/SocketIOClientSwift/SocketEngine.swift +++ b/SocketIOClientSwift/SocketEngine.swift @@ -214,6 +214,7 @@ public final class SocketEngine: NSObject, SocketEngineSpec, WebSocketDelegate { let wsUrl = urlWebSocket + (sid == "" ? "" : "&sid=\(sid)") ws = WebSocket(url: NSURL(string: wsUrl)!) + if cookies != nil { let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!) for (key, value) in headers { @@ -268,10 +269,8 @@ public final class SocketEngine: NSObject, SocketEngineSpec, WebSocketDelegate { } } - private func handleClose() { - if let client = client where polling == true { - client.engineDidClose("Disconnect") - } + private func handleClose(reason: String) { + client?.engineDidClose(reason) } private func handleMessage(message: String) { @@ -419,7 +418,7 @@ public final class SocketEngine: NSObject, SocketEngineSpec, WebSocketDelegate { message.removeAtIndex(message.startIndex) handleOpen(message) case .Close: - handleClose() + handleClose(message) default: DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType) } @@ -540,11 +539,12 @@ extension SocketEngine { guard let this = self else {return} if err != nil || data == nil { + DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: this.logType) + if this.polling { this.handlePollingFailed(err?.localizedDescription ?? "Error") - } else { - DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: this.logType) } + return } @@ -602,22 +602,24 @@ extension SocketEngine { DefaultSocketLogger.Logger.log("POSTing: %@", type: logType, args: postStr) doRequest(req) {[weak self] data, res, err in - if let this = self { - if err != nil && this.polling { + guard let this = self else {return} + + if err != nil { + DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: this.logType) + + if this.polling { this.handlePollingFailed(err?.localizedDescription ?? "Error") - return - } else if err != nil { - DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: this.logType) - return } - this.waitingForPost = false - - dispatch_async(this.emitQueue) {[weak this] in - if !(this?.fastUpgrade ?? true) { - this?.flushWaitingForPost() - this?.doPoll() - } + return + } + + this.waitingForPost = false + + dispatch_async(this.emitQueue) {[weak this] in + if !(this?.fastUpgrade ?? true) { + this?.flushWaitingForPost() + this?.doPoll() } } } diff --git a/SocketIOClientSwift/WebSocket.swift b/SocketIOClientSwift/WebSocket.swift index 21245cb..4af04fa 100644 --- a/SocketIOClientSwift/WebSocket.swift +++ b/SocketIOClientSwift/WebSocket.swift @@ -34,7 +34,7 @@ public class WebSocket : NSObject, NSStreamDelegate { //B-F reserved. } - enum CloseCode : UInt16 { + public enum CloseCode : UInt16 { case Normal = 1000 case GoingAway = 1001 case ProtocolError = 1002 @@ -47,6 +47,8 @@ public class WebSocket : NSObject, NSStreamDelegate { case MessageTooBig = 1009 } + public static let ErrorDomain = "WebSocket" + enum InternalErrorCode : UInt16 { // 0-999 WebSocket status codes not used case OutputStreamWriteError = 1 @@ -138,9 +140,29 @@ public class WebSocket : NSObject, NSStreamDelegate { }) } - ///disconnect from the websocket server - public func disconnect() { - writeError(CloseCode.Normal.rawValue) + /** + Disconnect from the server. I send a Close control frame to the server, then expect the server to respond with a Close control frame and close the socket from its end. I notify my delegate once the socket has been closed. + + If you supply a non-nil `forceTimeout`, I wait at most that long (in seconds) for the server to close the socket. After the timeout expires, I close the socket and notify my delegate. + + If you supply a zero (or negative) `forceTimeout`, I immediately close the socket (without sending a Close control frame) and notify my delegate. + + - Parameter forceTimeout: Maximum time to wait for the server to close the socket. + */ + public func disconnect(forceTimeout forceTimeout: NSTimeInterval? = nil) { + switch forceTimeout { + case .Some(let seconds) where seconds > 0: + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC))), queue, { [unowned self] in + self.disconnectStream(nil) + }) + fallthrough + case .None: + writeError(CloseCode.Normal.rawValue) + + default: + self.disconnectStream(nil) + break + } } ///write a string to the websocket. This sends it as a text frame. @@ -400,9 +422,10 @@ public class WebSocket : NSObject, NSStreamDelegate { } if let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response) { let headers = cfHeaders.takeRetainedValue() as NSDictionary - let acceptKey = headers[headerWSAcceptName] as! NSString - if acceptKey.length > 0 { - return true + if let acceptKey = headers[headerWSAcceptName] as? NSString { + if acceptKey.length > 0 { + return true + } } } return false @@ -632,7 +655,7 @@ public class WebSocket : NSObject, NSStreamDelegate { private func errorWithDetail(detail: String, code: UInt16) -> NSError { var details = Dictionary() details[NSLocalizedDescriptionKey] = detail - return NSError(domain: "Websocket", code: Int(code), userInfo: details) + return NSError(domain: WebSocket.ErrorDomain, code: Int(code), userInfo: details) } ///write a an error to the socket