merge development

This commit is contained in:
Erik 2016-06-24 02:53:31 -04:00
commit c129118496
3 changed files with 71 additions and 72 deletions

View File

@ -88,7 +88,7 @@ Carthage
----------------- -----------------
Add this line to your `Cartfile`: Add this line to your `Cartfile`:
``` ```
github "socketio/socket.io-client-swift" ~> 6.1.2 # Or latest version github "socketio/socket.io-client-swift" ~> 6.1.4 # Or latest version
``` ```
Run `carthage update --platform ios,macosx`. Run `carthage update --platform ios,macosx`.
@ -102,7 +102,7 @@ source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0' platform :ios, '8.0'
use_frameworks! use_frameworks!
pod 'Socket.IO-Client-Swift', '~> 6.1.2' # Or latest version pod 'Socket.IO-Client-Swift', '~> 6.1.4' # Or latest version
``` ```
Install pods: Install pods:
@ -130,7 +130,7 @@ CocoaSeeds
Add this line to your `Seedfile`: Add this line to your `Seedfile`:
``` ```
github "socketio/socket.io-client-swift", "v6.1.2", :files => "Source/*.swift" # Or latest version github "socketio/socket.io-client-swift", "v6.1.4", :files => "Source/*.swift" # Or latest version
``` ```
Run `seed install`. Run `seed install`.

View File

@ -1,7 +1,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "Socket.IO-Client-Swift" s.name = "Socket.IO-Client-Swift"
s.module_name = "SocketIOClientSwift" s.module_name = "SocketIOClientSwift"
s.version = "6.1.2" s.version = "6.1.4"
s.summary = "Socket.IO-client for iOS and OS X" s.summary = "Socket.IO-client for iOS and OS X"
s.description = <<-DESC s.description = <<-DESC
Socket.IO-client for iOS and OS X. Socket.IO-client for iOS and OS X.
@ -14,7 +14,7 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '8.0' s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10' s.osx.deployment_target = '10.10'
s.tvos.deployment_target = '9.0' s.tvos.deployment_target = '9.0'
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v6.1.2' } s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v6.1.4' }
s.source_files = "Source/**/*.swift" s.source_files = "Source/**/*.swift"
s.requires_arc = true s.requires_arc = true
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files # s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files

View File

@ -34,11 +34,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
(urlPolling, urlWebSocket) = createURLs() (urlPolling, urlWebSocket) = createURLs()
} }
} }
public var postWait = [String]() public var postWait = [String]()
public var waitingForPoll = false public var waitingForPoll = false
public var waitingForPost = false public var waitingForPost = false
public private(set) var closed = false public private(set) var closed = false
public private(set) var connected = false public private(set) var connected = false
public private(set) var cookies: [HTTPCookie]? public private(set) var cookies: [HTTPCookie]?
@ -59,19 +59,19 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
public private(set) var ws: WebSocket? public private(set) var ws: WebSocket?
public weak var client: SocketEngineClient? public weak var client: SocketEngineClient?
private weak var sessionDelegate: URLSessionDelegate? private weak var sessionDelegate: URLSessionDelegate?
private let logType = "SocketEngine" private let logType = "SocketEngine"
private let url: URL private let url: URL
private var pingInterval: Double? private var pingInterval: Double?
private var pingTimeout = 0.0 { private var pingTimeout = 0.0 {
didSet { didSet {
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25)) pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
} }
} }
private var pongsMissed = 0 private var pongsMissed = 0
private var pongsMissedMax = 0 private var pongsMissedMax = 0
private var probeWait = ProbeWaitQueue() private var probeWait = ProbeWaitQueue()
@ -83,7 +83,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
public init(client: SocketEngineClient, url: URL, options: Set<SocketIOClientOption>) { public init(client: SocketEngineClient, url: URL, options: Set<SocketIOClientOption>) {
self.client = client self.client = client
self.url = url self.url = url
for option in options { for option in options {
switch option { switch option {
case let .connectParams(params): case let .connectParams(params):
@ -114,30 +114,30 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
continue continue
} }
} }
super.init() super.init()
(urlPolling, urlWebSocket) = createURLs() (urlPolling, urlWebSocket) = createURLs()
} }
public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) { public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) {
self.init(client: client, url: url, options: options?.toSocketOptionsSet() ?? []) self.init(client: client, url: url, options: options?.toSocketOptionsSet() ?? [])
} }
deinit { deinit {
DefaultSocketLogger.Logger.log("Engine is being released", type: logType) DefaultSocketLogger.Logger.log("Engine is being released", type: logType)
closed = true closed = true
stopPolling() stopPolling()
} }
private func checkAndHandleEngineError(_ msg: String) { private func checkAndHandleEngineError(_ msg: String) {
guard let stringData = msg.data(using: String.Encoding.utf8, guard let stringData = msg.data(using: String.Encoding.utf8,
allowLossyConversion: false) else { return } allowLossyConversion: false) else { return }
do { do {
if let dict = try JSONSerialization.jsonObject(with: stringData, options: .mutableContainers) as? NSDictionary { if let dict = try JSONSerialization.jsonObject(with: stringData, options: .mutableContainers) as? NSDictionary {
guard let error = dict["message"] as? String else { return } guard let error = dict["message"] as? String else { return }
/* /*
0: Unknown transport 0: Unknown transport
1: Unknown sid 1: Unknown sid
@ -147,7 +147,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
didError(reason: error) didError(reason: error)
} }
} catch { } catch {
didError(reason: "Got unknown error from server \(msg)") client?.engineDidError(reason: "Got unknown error from server \(msg)")
} }
} }
@ -155,59 +155,60 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
if message.hasPrefix("b4") { if message.hasPrefix("b4") {
// binary in base64 string // binary in base64 string
let noPrefix = message[message.characters.index(message.startIndex, offsetBy: 2)..<message.endIndex] let noPrefix = message[message.characters.index(message.startIndex, offsetBy: 2)..<message.endIndex]
if let data = Data(base64Encoded: noPrefix, options: Data.Base64EncodingOptions(rawValue: 0)) { if let data = Data(base64Encoded: noPrefix, options: Data.Base64EncodingOptions(rawValue: 0)) {
client?.parseEngineBinaryData(data) client?.parseEngineBinaryData(data)
} }
return true return true
} else { } else {
return false return false
} }
} }
private func closeOutEngine() { private func closeOutEngine(reason: String) {
sid = "" sid = ""
closed = true closed = true
invalidated = true invalidated = true
connected = false connected = false
ws?.disconnect() ws?.disconnect()
stopPolling() stopPolling()
client?.engineDidClose(reason: reason)
} }
/// Starts the connection to the server /// Starts the connection to the server
public func connect() { public func connect() {
if connected { if connected {
DefaultSocketLogger.Logger.error("Engine tried opening while connected. Assuming this was a reconnect", type: logType) DefaultSocketLogger.Logger.error("Engine tried opening while connected. Assuming this was a reconnect", type: logType)
disconnect(reason: "reconnect") disconnect(reason: "reconnect")
} }
DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: logType, args: url) DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: logType, args: url)
DefaultSocketLogger.Logger.log("Handshaking", type: logType) DefaultSocketLogger.Logger.log("Handshaking", type: logType)
resetEngine() resetEngine()
if forceWebsockets { if forceWebsockets {
polling = false polling = false
websocket = true websocket = true
createWebsocketAndConnect() createWebsocketAndConnect()
return return
} }
let reqPolling = NSMutableURLRequest(url: urlPolling) let reqPolling = NSMutableURLRequest(url: urlPolling)
if cookies != nil { if cookies != nil {
let headers = HTTPCookie.requestHeaderFields(with: cookies!) let headers = HTTPCookie.requestHeaderFields(with: cookies!)
reqPolling.allHTTPHeaderFields = headers reqPolling.allHTTPHeaderFields = headers
} }
if let extraHeaders = extraHeaders { if let extraHeaders = extraHeaders {
for (headerName, value) in extraHeaders { for (headerName, value) in extraHeaders {
reqPolling.setValue(value, forHTTPHeaderField: headerName) reqPolling.setValue(value, forHTTPHeaderField: headerName)
} }
} }
emitQueue.async { self.doLongPoll(for: reqPolling as URLRequest) } emitQueue.async { self.doLongPoll(for: reqPolling as URLRequest) }
} }
@ -219,7 +220,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
var urlPolling = URLComponents(string: url.absoluteString!)! var urlPolling = URLComponents(string: url.absoluteString!)!
var urlWebSocket = URLComponents(string: url.absoluteString!)! var urlWebSocket = URLComponents(string: url.absoluteString!)!
var queryString = "" var queryString = ""
urlWebSocket.path = socketPath urlWebSocket.path = socketPath
urlPolling.path = socketPath urlPolling.path = socketPath
@ -242,13 +243,13 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
urlWebSocket.percentEncodedQuery = "transport=websocket" + queryString urlWebSocket.percentEncodedQuery = "transport=websocket" + queryString
urlPolling.percentEncodedQuery = "transport=polling&b64=1" + queryString urlPolling.percentEncodedQuery = "transport=polling&b64=1" + queryString
return (urlPolling.url!, urlWebSocket.url!) return (urlPolling.url!, urlWebSocket.url!)
} }
private func createWebsocketAndConnect() { private func createWebsocketAndConnect() {
ws = WebSocket(url: urlWebSocketWithSid) ws = WebSocket(url: urlWebSocketWithSid)
if cookies != nil { if cookies != nil {
let headers = HTTPCookie.requestHeaderFields(with: cookies!) let headers = HTTPCookie.requestHeaderFields(with: cookies!)
for (key, value) in headers { for (key, value) in headers {
@ -270,40 +271,38 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
ws?.connect() ws?.connect()
} }
public func didError(reason: String) { public func didError(reason: String) {
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason) DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
client?.engineDidError(reason: reason) client?.engineDidError(reason: reason)
disconnect(reason: reason) disconnect(reason: reason)
} }
public func disconnect(reason: String) { public func disconnect(reason: String) {
guard connected else { return closeOutEngine() } guard connected else { return closeOutEngine(reason: reason) }
DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType) DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType)
if closed { if closed {
closeOutEngine() return closeOutEngine(reason: reason)
client?.engineDidClose(reason: reason)
return
} }
if websocket { if websocket {
sendWebSocketMessage("", withType: .close, withData: []) sendWebSocketMessage("", withType: .close, withData: [])
closeOutEngine() closeOutEngine(reason: reason)
} else { } else {
disconnectPolling() disconnectPolling(reason: reason)
} }
} }
// We need to take special care when we're polling that we send it ASAP // We need to take special care when we're polling that we send it ASAP
// Also make sure we're on the emitQueue since we're touching postWait // Also make sure we're on the emitQueue since we're touching postWait
private func disconnectPolling() { private func disconnectPolling(reason: String) {
emitQueue.sync { emitQueue.sync {
self.postWait.append(String(SocketEnginePacketType.close.rawValue)) self.postWait.append(String(SocketEnginePacketType.close.rawValue))
let req = self.createRequestForPostWithPostWait() let req = self.createRequestForPostWithPostWait()
self.doRequest(for: req) {_, _, _ in } self.doRequest(for: req) {_, _, _ in }
self.closeOutEngine() self.closeOutEngine(reason: reason)
} }
} }
@ -328,24 +327,24 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
for waiter in self.probeWait { for waiter in self.probeWait {
self.write(waiter.msg, withType: waiter.type, withData: waiter.data) self.write(waiter.msg, withType: waiter.type, withData: waiter.data)
} }
self.probeWait.removeAll(keepingCapacity: false) self.probeWait.removeAll(keepingCapacity: false)
if self.postWait.count != 0 { if self.postWait.count != 0 {
self.flushWaitingForPostToWebSocket() self.flushWaitingForPostToWebSocket()
} }
} }
} }
// We had packets waiting for send when we upgraded // We had packets waiting for send when we upgraded
// Send them raw // Send them raw
public func flushWaitingForPostToWebSocket() { public func flushWaitingForPostToWebSocket() {
guard let ws = self.ws else { return } guard let ws = self.ws else { return }
for msg in postWait { for msg in postWait {
ws.writeString(msg) ws.writeString(msg)
} }
postWait.removeAll(keepingCapacity: true) postWait.removeAll(keepingCapacity: true)
} }
@ -386,13 +385,13 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
if !forcePolling && !forceWebsockets && upgradeWs { if !forcePolling && !forceWebsockets && upgradeWs {
createWebsocketAndConnect() createWebsocketAndConnect()
} }
sendPing() sendPing()
if !forceWebsockets { if !forceWebsockets {
doPoll() doPoll()
} }
client?.engineDidOpen(reason: "Connect") client?.engineDidOpen(reason: "Connect")
} }
} catch { } catch {
@ -408,16 +407,16 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
upgradeTransport() upgradeTransport()
} }
} }
public func parseEngineData(_ data: Data) { public func parseEngineData(_ data: Data) {
DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data) DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data)
client?.parseEngineBinaryData(data.subdata(in: Range<Int>(uncheckedBounds: (1, data.count - 1)))) client?.parseEngineBinaryData(data.subdata(in: Range<Int>(uncheckedBounds: (1, data.count - 1))))
} }
public func parseEngineMessage(_ message: String, fromPolling: Bool) { public func parseEngineMessage(_ message: String, fromPolling: Bool) {
DefaultSocketLogger.Logger.log("Got message: %@", type: logType, args: message) DefaultSocketLogger.Logger.log("Got message: %@", type: logType, args: message)
let reader = SocketStringReader(message: message) let reader = SocketStringReader(message: message)
let fixedString: String let fixedString: String
@ -425,7 +424,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
if !checkIfMessageIsBase64Binary(message) { if !checkIfMessageIsBase64Binary(message) {
checkAndHandleEngineError(message) checkAndHandleEngineError(message)
} }
return return
} }
@ -451,7 +450,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType) DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType)
} }
} }
// Puts the engine back in its default state // Puts the engine back in its default state
private func resetEngine() { private func resetEngine() {
closed = false closed = false
@ -473,22 +472,22 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
if !connected { if !connected {
return return
} }
//Server is not responding //Server is not responding
if pongsMissed > pongsMissedMax { if pongsMissed > pongsMissedMax {
client?.engineDidClose(reason: "Ping timeout") client?.engineDidClose(reason: "Ping timeout")
return return
} }
if let pingInterval = pingInterval { if let pingInterval = pingInterval {
pongsMissed += 1 pongsMissed += 1
write("", withType: .ping, withData: []) write("", withType: .ping, withData: [])
let time = DispatchTime.now() + Double(Int64(pingInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC) let time = DispatchTime.now() + Double(Int64(pingInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.after(when: time) {[weak self] in self?.sendPing() } DispatchQueue.main.after(when: time) {[weak self] in self?.sendPing() }
} }
} }
// Moves from long-polling to websockets // Moves from long-polling to websockets
private func upgradeTransport() { private func upgradeTransport() {
if ws?.isConnected ?? false { if ws?.isConnected ?? false {
@ -504,7 +503,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) { public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) {
emitQueue.async { emitQueue.async {
guard self.connected else { return } guard self.connected else { return }
if self.websocket { if self.websocket {
DefaultSocketLogger.Logger.log("Writing ws: %@ has data: %@", DefaultSocketLogger.Logger.log("Writing ws: %@ has data: %@",
type: self.logType, args: msg, data.count != 0) type: self.logType, args: msg, data.count != 0)
@ -518,7 +517,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
} }
} }
// Delegate methods // Delegate methods
public func websocketDidConnect(_ socket: WebSocket) { public func websocketDidConnect(_ socket: WebSocket) {
if !forceWebsockets { if !forceWebsockets {
@ -530,19 +529,19 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
polling = false polling = false
} }
} }
public func websocketDidDisconnect(_ socket: WebSocket, error: NSError?) { public func websocketDidDisconnect(_ socket: WebSocket, error: NSError?) {
probing = false probing = false
if closed { if closed {
client?.engineDidClose(reason: "Disconnect") client?.engineDidClose(reason: "Disconnect")
return return
} }
if websocket { if websocket {
connected = false connected = false
websocket = false websocket = false
if let reason = error?.localizedDescription { if let reason = error?.localizedDescription {
didError(reason: reason) didError(reason: reason)
} else { } else {