Merge branch 'development'

* development:
  Add note about manager not being thread safe
  Make it clear that `handleQueue` should be serial
  remove some redundant connected checking
  get rid of internal emitAck method
  open engine
  Add raw view to ack emitter
  change access level to public for raw view
  rename SocketBinaryView
  Add rawEmitView. Implements #992
  Add way to skip binary inspection.
  bump version
  Set reconnectAttempts in manager. Fixes #989
This commit is contained in:
Erik Little 2018-05-16 18:48:28 -04:00
commit 41af615428
No known key found for this signature in database
GPG Key ID: B8E1F067FE8DCAAF
15 changed files with 269 additions and 50 deletions

View File

@ -1,7 +1,7 @@
language: objective-c language: objective-c
xcode_project: Socket.IO-Client-Swift.xcodeproj # path to your xcodeproj folder xcode_project: Socket.IO-Client-Swift.xcodeproj # path to your xcodeproj folder
xcode_scheme: SocketIO-Mac xcode_scheme: SocketIO-Mac
osx_image: xcode9 osx_image: xcode9.2
branches: branches:
only: only:
- master - master

View File

@ -1,3 +1,13 @@
# v13.2.0
- Add ability to bypass Data inspection in emits. [#992]((https://github.com/socketio/socket.io-client-swift/issues/992))
- Allow `SocketEngine` to be subclassed
# v13.1.3
- Fix setting reconnectAttempts [#989]((https://github.com/socketio/socket.io-client-swift/issues/989))
# v13.1.2 # v13.1.2
- Fix [#950](https://github.com/socketio/socket.io-client-swift/issues/950) - Fix [#950](https://github.com/socketio/socket.io-client-swift/issues/950)

View File

@ -1,15 +1,6 @@
{ {
"object": { "object": {
"pins": [ "pins": [
{
"package": "SSCZLib",
"repositoryURL": "https://github.com/daltoniam/zlib-spm.git",
"state": {
"branch": null,
"revision": "83ac8d719a2f3aa775dbdf116a57f56fb2c49abb",
"version": "1.1.0"
}
},
{ {
"package": "SSCommonCrypto", "package": "SSCommonCrypto",
"repositoryURL": "https://github.com/daltoniam/common-crypto-spm", "repositoryURL": "https://github.com/daltoniam/common-crypto-spm",
@ -27,6 +18,15 @@
"revision": "6cb1c474e09b0a3aa60bcdc7553b570336d6a61a", "revision": "6cb1c474e09b0a3aa60bcdc7553b570336d6a61a",
"version": "3.0.3" "version": "3.0.3"
} }
},
{
"package": "SSCZLib",
"repositoryURL": "https://github.com/daltoniam/zlib-spm.git",
"state": {
"branch": null,
"revision": "83ac8d719a2f3aa775dbdf116a57f56fb2c49abb",
"version": "1.1.0"
}
} }
] ]
}, },

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 = "SocketIO" s.module_name = "SocketIO"
s.version = "13.1.2" s.version = "13.1.3"
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.
@ -18,7 +18,7 @@ Pod::Spec.new do |s|
s.requires_arc = true s.requires_arc = true
s.source = { s.source = {
:git => "https://github.com/socketio/socket.io-client-swift.git", :git => "https://github.com/socketio/socket.io-client-swift.git",
:tag => 'v13.1.2', :tag => 'v13.1.3',
:submodules => true :submodules => true
} }
s.pod_target_xcconfig = { s.pod_target_xcconfig = {

View File

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C65763817782DFAC67BE05C /* SocketManager.swift */; }; 1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C65763817782DFAC67BE05C /* SocketManager.swift */; };
1C6573B22DC9423CDFC32F05 /* SocketRawView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C657533E849FC3E4342C602 /* SocketRawView.swift */; };
1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */; }; 1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */; };
1C686BE21F869AFD007D8627 /* SocketIOClientConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */; }; 1C686BE21F869AFD007D8627 /* SocketIOClientConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */; };
1C686BE31F869AFD007D8627 /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */; }; 1C686BE31F869AFD007D8627 /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */; };
@ -61,6 +62,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManagerSpec.swift; sourceTree = "<group>"; }; 1C6574AF9687A213814753E4 /* SocketManagerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManagerSpec.swift; sourceTree = "<group>"; };
1C657533E849FC3E4342C602 /* SocketRawView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketRawView.swift; sourceTree = "<group>"; };
1C65763817782DFAC67BE05C /* SocketManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManager.swift; sourceTree = "<group>"; }; 1C65763817782DFAC67BE05C /* SocketManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketManager.swift; sourceTree = "<group>"; };
1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketIOClientConfigurationTest.swift; sourceTree = "<group>"; }; 1C686BD21F869AF1007D8627 /* SocketIOClientConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketIOClientConfigurationTest.swift; sourceTree = "<group>"; };
1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = "<group>"; }; 1C686BD31F869AF1007D8627 /* SocketEngineTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = "<group>"; };
@ -300,6 +302,7 @@
DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */, DD52B078DB0A3C3D1BB507CD /* SocketIOClientOption.swift */,
DD52B1D9BC4AE46D38D827DE /* SocketIOStatus.swift */, DD52B1D9BC4AE46D38D827DE /* SocketIOStatus.swift */,
DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */, DD52B57FFEE8560CFFD793B3 /* SocketIOClientConfiguration.swift */,
1C657533E849FC3E4342C602 /* SocketRawView.swift */,
); );
name = Client; name = Client;
path = Source/SocketIO/Client; path = Source/SocketIO/Client;
@ -480,6 +483,7 @@
DD52B9412F660F828B683422 /* SocketParsable.swift in Sources */, DD52B9412F660F828B683422 /* SocketParsable.swift in Sources */,
1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */, 1C6572803D7E252A77A86E5F /* SocketManager.swift in Sources */,
1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */, 1C657FBB3F670261780FD72E /* SocketManagerSpec.swift in Sources */,
1C6573B22DC9423CDFC32F05 /* SocketRawView.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -29,8 +29,20 @@ import Foundation
/// ///
/// **NOTE**: You should not store this beyond the life of the event handler. /// **NOTE**: You should not store this beyond the life of the event handler.
public final class SocketAckEmitter : NSObject { public final class SocketAckEmitter : NSObject {
let socket: SocketIOClient private unowned let socket: SocketIOClient
let ackNum: Int private let ackNum: Int
/// A view into this emitter where emits do not check for binary data.
///
/// Usage:
///
/// ```swift
/// ack.rawEmitView.with(myObject)
/// ```
///
/// **NOTE**: It is not safe to hold on to this view beyond the life of the socket.
@objc
public private(set) lazy var rawEmitView = SocketRawAckView(socket: socket, ackNum: ackNum)
// MARK: Properties // MARK: Properties
@ -91,13 +103,16 @@ public final class SocketAckEmitter : NSObject {
/// ``` /// ```
public final class OnAckCallback : NSObject { public final class OnAckCallback : NSObject {
private let ackNumber: Int private let ackNumber: Int
private let binary: Bool
private let items: [Any] private let items: [Any]
private weak var socket: SocketIOClient? private weak var socket: SocketIOClient?
init(ackNumber: Int, items: [Any], socket: SocketIOClient) { init(ackNumber: Int, items: [Any], socket: SocketIOClient, binary: Bool = true) {
self.ackNumber = ackNumber self.ackNumber = ackNumber
self.items = items self.items = items
self.socket = socket self.socket = socket
self.binary = binary
} }
deinit { deinit {
@ -116,7 +131,7 @@ public final class OnAckCallback : NSObject {
guard let socket = self.socket, ackNumber != -1 else { return } guard let socket = self.socket, ackNumber != -1 else { return }
socket.ackHandlers.addAck(ackNumber, callback: callback) socket.ackHandlers.addAck(ackNumber, callback: callback)
socket.emit(items, ack: ackNumber) socket.emit(items, ack: ackNumber, binary: binary)
guard seconds != 0 else { return } guard seconds != 0 else { return }

View File

@ -67,6 +67,18 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
@objc @objc
public private(set) weak var manager: SocketManagerSpec? public private(set) weak var manager: SocketManagerSpec?
/// A view into this socket where emits do not check for binary data.
///
/// Usage:
///
/// ```swift
/// socket.rawEmitView.emit("myEvent", myObject)
/// ```
///
/// **NOTE**: It is not safe to hold on to this view beyond the life of the socket.
@objc
public private(set) lazy var rawEmitView = SocketRawView(socket: self)
/// The status of this client. /// The status of this client.
@objc @objc
public private(set) var status = SocketIOStatus.notConnected { public private(set) var status = SocketIOStatus.notConnected {
@ -148,7 +160,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
} }
} }
private func createOnAck(_ items: [Any]) -> OnAckCallback { func createOnAck(_ items: [Any], binary: Bool = true) -> OnAckCallback {
currentAck += 1 currentAck += 1
return OnAckCallback(ackNumber: currentAck, items: items, socket: self) return OnAckCallback(ackNumber: currentAck, items: items, socket: self)
@ -216,11 +228,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
/// - parameter items: The items to send with this event. Send an empty array to send no data. /// - parameter items: The items to send with this event. Send an empty array to send no data.
@objc @objc
open func emit(_ event: String, with items: [Any]) { open func emit(_ event: String, with items: [Any]) {
guard status == .connected else {
handleClientEvent(.error, data: ["Tried emitting \(event) when not connected"])
return
}
emit([event] + items) emit([event] + items)
} }
@ -277,16 +284,16 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
return createOnAck([event] + items) return createOnAck([event] + items)
} }
func emit(_ data: [Any], ack: Int? = nil) { func emit(_ data: [Any], ack: Int? = nil, binary: Bool = true, isAck: Bool = false) {
guard status == .connected else { guard status == .connected else {
handleClientEvent(.error, data: ["Tried emitting when not connected"]) handleClientEvent(.error, data: ["Tried emitting when not connected"])
return return
} }
let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false) let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: isAck, checkForBinary: binary)
let str = packet.packetString let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting: \(str)", type: logType) DefaultSocketLogger.Logger.log("Emitting: \(str), Ack: \(isAck)", type: logType)
manager?.engine?.send(str, withData: packet.binary) manager?.engine?.send(str, withData: packet.binary)
} }
@ -298,14 +305,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
/// - parameter ack: The ack number. /// - parameter ack: The ack number.
/// - parameter with: The data for this ack. /// - parameter with: The data for this ack.
open func emitAck(_ ack: Int, with items: [Any]) { open func emitAck(_ ack: Int, with items: [Any]) {
guard status == .connected else { return } emit(items, ack: ack, binary: true, isAck: true)
let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: nsp, ack: true)
let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting Ack: \(str)", type: logType)
manager?.engine?.send(str, withData: packet.binary)
} }
/// Called when socket.io has acked one of our emits. Causes the corresponding ack callback to be called. /// Called when socket.io has acked one of our emits. Causes the corresponding ack callback to be called.

View File

@ -55,6 +55,8 @@ public enum SocketIOClientOption : ClientOption {
/// The queue that all interaction with the client should occur on. This is the queue that event handlers are /// The queue that all interaction with the client should occur on. This is the queue that event handlers are
/// called on. /// called on.
///
/// **This should be a serial queue! Concurrent queues are not supported and might cause crashes and races**.
case handleQueue(DispatchQueue) case handleQueue(DispatchQueue)
/// If passed `true`, the client will log debug information. This should be turned off in production code. /// If passed `true`, the client will log debug information. This should be turned off in production code.

View File

@ -43,6 +43,17 @@ public protocol SocketIOClientSpec : class {
/// **Must** start with a `/`. /// **Must** start with a `/`.
var nsp: String { get } var nsp: String { get }
/// A view into this socket where emits do not check for binary data.
///
/// Usage:
///
/// ```swift
/// socket.rawEmitView.emit("myEvent", myObject)
/// ```
///
/// **NOTE**: It is not safe to hold on to this view beyond the life of the socket.
var rawEmitView: SocketRawView { get }
/// The status of this client. /// The status of this client.
var status: SocketIOStatus { get } var status: SocketIOStatus { get }

View File

@ -0,0 +1,163 @@
//
// SocketRawView.swift
// Socket.IO-Client-Swift
//
// Created by Erik Little on 3/30/18.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
/// Class that gives a backwards compatible way to cause an emit not to recursively check for Data objects.
///
/// Usage:
///
/// ```swift
/// socket.rawEmitView.emit("myEvent", myObject)
/// ```
public final class SocketRawView : NSObject {
private unowned let socket: SocketIOClient
init(socket: SocketIOClient) {
self.socket = socket
}
/// Send an event to the server, with optional data items.
///
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
/// will be emitted. The structure of the error data is `[eventName, items, theError]`
///
/// - parameter event: The event to send.
/// - parameter items: The items to send with this event. May be left out.
public func emit(_ event: String, _ items: SocketData...) {
do {
try emit(event, with: items.map({ try $0.socketRepresentation() }))
} catch let err {
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
type: "SocketIOClient")
socket.handleClientEvent(.error, data: [event, items, err])
}
}
/// Same as emit, but meant for Objective-C
///
/// - parameter event: The event to send.
/// - parameter items: The items to send with this event. Send an empty array to send no data.
@objc
public func emit(_ event: String, with items: [Any]) {
socket.emit([event] + items, binary: false)
}
/// Sends a message to the server, requesting an ack.
///
/// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack.
/// Check that your server's api will ack the event being sent.
///
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
/// will be emitted. The structure of the error data is `[eventName, items, theError]`
///
/// Example:
///
/// ```swift
/// socket.emitWithAck("myEvent", 1).timingOut(after: 1) {data in
/// ...
/// }
/// ```
///
/// - parameter event: The event to send.
/// - parameter items: The items to send with this event. May be left out.
/// - returns: An `OnAckCallback`. You must call the `timingOut(after:)` method before the event will be sent.
public func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback {
do {
return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() }))
} catch let err {
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
type: "SocketIOClient")
socket.handleClientEvent(.error, data: [event, items, err])
return OnAckCallback(ackNumber: -1, items: [], socket: socket)
}
}
/// Same as emitWithAck, but for Objective-C
///
/// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack.
/// Check that your server's api will ack the event being sent.
///
/// Example:
///
/// ```swift
/// socket.emitWithAck("myEvent", with: [1]).timingOut(after: 1) {data in
/// ...
/// }
/// ```
///
/// - parameter event: The event to send.
/// - parameter items: The items to send with this event. Use `[]` to send nothing.
/// - returns: An `OnAckCallback`. You must call the `timingOut(after:)` method before the event will be sent.
@objc
public func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback {
return socket.createOnAck([event] + items, binary: false)
}
}
/// Class that gives a backwards compatible way to cause an emit not to recursively check for Data objects.
///
/// Usage:
///
/// ```swift
/// ack.rawEmitView.with(myObject)
/// ```
public final class SocketRawAckView : NSObject {
private unowned let socket: SocketIOClient
private let ackNum: Int
init(socket: SocketIOClient, ackNum: Int) {
self.socket = socket
self.ackNum = ackNum
}
/// Call to ack receiving this event.
///
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
/// will be emitted. The structure of the error data is `[ackNum, items, theError]`
///
/// - parameter items: A variable number of items to send when acking.
public func with(_ items: SocketData...) {
guard ackNum != -1 else { return }
do {
socket.emit(try items.map({ try $0.socketRepresentation() }), ack: ackNum, binary: false, isAck: true)
} catch let err {
socket.handleClientEvent(.error, data: [ackNum, items, err])
}
}
/// Call to ack receiving this event.
///
/// - parameter items: An array of items to send when acking. Use `[]` to send nothing.
@objc
public func with(_ items: [Any]) {
guard ackNum != -1 else { return }
socket.emit(items, ack: ackNum, binary: false, isAck: true)
}
}

View File

@ -28,8 +28,7 @@ import Starscream
/// The class that handles the engine.io protocol and transports. /// The class that handles the engine.io protocol and transports.
/// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods. /// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods.
public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, ConfigSettable {
ConfigSettable {
// MARK: Properties // MARK: Properties
private static let logType = "SocketEngine" private static let logType = "SocketEngine"
@ -164,7 +163,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// - parameter client: The client for this engine. /// - parameter client: The client for this engine.
/// - parameter url: The url for this engine. /// - parameter url: The url for this engine.
/// - parameter options: The options for this engine. /// - parameter options: The options for this engine.
public convenience init(client: SocketEngineClient, url: URL, options: [String: Any]?) { public required convenience init(client: SocketEngineClient, url: URL, options: [String: Any]?) {
self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? []) self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? [])
} }
@ -214,7 +213,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
} }
/// Starts the connection to the server. /// Starts the connection to the server.
public func connect() { open func connect() {
engineQueue.async { engineQueue.async {
self._connect() self._connect()
} }
@ -318,7 +317,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
} }
/// Called when an error happens during execution. Causes a disconnection. /// Called when an error happens during execution. Causes a disconnection.
public func didError(reason: String) { open func didError(reason: String) {
DefaultSocketLogger.Logger.error("\(reason)", type: SocketEngine.logType) DefaultSocketLogger.Logger.error("\(reason)", type: SocketEngine.logType)
client?.engineDidError(reason: reason) client?.engineDidError(reason: reason)
disconnect(reason: reason) disconnect(reason: reason)
@ -327,7 +326,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// Disconnects from the server. /// Disconnects from the server.
/// ///
/// - parameter reason: The reason for the disconnection. This is communicated up to the client. /// - parameter reason: The reason for the disconnection. This is communicated up to the client.
public func disconnect(reason: String) { open func disconnect(reason: String) {
engineQueue.async { engineQueue.async {
self._disconnect(reason: reason) self._disconnect(reason: reason)
} }
@ -359,7 +358,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// WebSocket mode. /// WebSocket mode.
/// ///
/// **You shouldn't call this directly** /// **You shouldn't call this directly**
public func doFastUpgrade() { open func doFastUpgrade() {
if waitingForPoll { if waitingForPoll {
DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," + DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," +
"we'll probably disconnect soon. You should report this.", type: SocketEngine.logType) "we'll probably disconnect soon. You should report this.", type: SocketEngine.logType)
@ -392,7 +391,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// the engine is attempting to upgrade to WebSocket it does not do any POSTing. /// the engine is attempting to upgrade to WebSocket it does not do any POSTing.
/// ///
/// **You shouldn't call this directly** /// **You shouldn't call this directly**
public func flushWaitingForPostToWebSocket() { open func flushWaitingForPostToWebSocket() {
guard let ws = self.ws else { return } guard let ws = self.ws else { return }
for msg in postWait { for msg in postWait {
@ -474,7 +473,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// Parses raw binary received from engine.io. /// Parses raw binary received from engine.io.
/// ///
/// - parameter data: The data to parse. /// - parameter data: The data to parse.
public func parseEngineData(_ data: Data) { open func parseEngineData(_ data: Data) {
DefaultSocketLogger.Logger.log("Got binary data: \(data)", type: SocketEngine.logType) DefaultSocketLogger.Logger.log("Got binary data: \(data)", type: SocketEngine.logType)
client?.parseEngineBinaryData(data.subdata(in: 1..<data.endIndex)) client?.parseEngineBinaryData(data.subdata(in: 1..<data.endIndex))
@ -483,7 +482,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// Parses a raw engine.io packet. /// Parses a raw engine.io packet.
/// ///
/// - parameter message: The message to parse. /// - parameter message: The message to parse.
public func parseEngineMessage(_ message: String) { open func parseEngineMessage(_ message: String) {
DefaultSocketLogger.Logger.log("Got message: \(message)", type: SocketEngine.logType) DefaultSocketLogger.Logger.log("Got message: \(message)", type: SocketEngine.logType)
let reader = SocketStringReader(message: message) let reader = SocketStringReader(message: message)
@ -608,7 +607,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// - parameter msg: The message to send. /// - parameter msg: The message to send.
/// - parameter type: The type of this message. /// - parameter type: The type of this message.
/// - parameter data: Any data that this message has. /// - parameter data: Any data that this message has.
public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) { open func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) {
engineQueue.async { engineQueue.async {
guard self.connected else { return } guard self.connected else { return }
guard !self.probing else { guard !self.probing else {

View File

@ -43,6 +43,8 @@ import Foundation
/// To disconnect a socket and remove it from the manager, either call `SocketIOClient.disconnect()` on the socket, /// To disconnect a socket and remove it from the manager, either call `SocketIOClient.disconnect()` on the socket,
/// or call one of the `disconnectSocket` methods on this class. /// or call one of the `disconnectSocket` methods on this class.
/// ///
/// **NOTE**: The manager is not thread/queue safe, all interaction with the manager should be done on the `handleQueue`
///
open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDataBufferable, ConfigSettable { open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDataBufferable, ConfigSettable {
private static let logType = "SocketManager" private static let logType = "SocketManager"
@ -476,6 +478,8 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa
self.handleQueue = queue self.handleQueue = queue
case let .reconnects(reconnects): case let .reconnects(reconnects):
self.reconnects = reconnects self.reconnects = reconnects
case let .reconnectAttempts(attempts):
self.reconnectAttempts = attempts
case let .reconnectWait(wait): case let .reconnectWait(wait):
reconnectWait = abs(wait) reconnectWait = abs(wait)
case let .log(log): case let .log(log):

View File

@ -200,11 +200,15 @@ extension SocketPacket {
} }
} }
static func packetFromEmit(_ items: [Any], id: Int, nsp: String, ack: Bool) -> SocketPacket { static func packetFromEmit(_ items: [Any], id: Int, nsp: String, ack: Bool, checkForBinary: Bool = true) -> SocketPacket {
let (parsedData, binary) = deconstructData(items) if checkForBinary {
let (parsedData, binary) = deconstructData(items)
return SocketPacket(type: findType(binary.count, ack: ack), data: parsedData, id: id, nsp: nsp, return SocketPacket(type: findType(binary.count, ack: ack), data: parsedData, id: id, nsp: nsp,
binary: binary) binary: binary)
} else {
return SocketPacket(type: findType(0, ack: ack), data: items, id: id, nsp: nsp)
}
} }
} }

View File

@ -79,13 +79,15 @@ class SocketMangerTest : XCTestCase {
.handleQueue(queue), .handleQueue(queue),
.forceNew(true), .forceNew(true),
.reconnects(false), .reconnects(false),
.reconnectWait(5) .reconnectWait(5),
.reconnectAttempts(5)
]) ])
XCTAssertEqual(manager.handleQueue, queue) XCTAssertEqual(manager.handleQueue, queue)
XCTAssertTrue(manager.forceNew) XCTAssertTrue(manager.forceNew)
XCTAssertFalse(manager.reconnects) XCTAssertFalse(manager.reconnects)
XCTAssertEqual(manager.reconnectWait, 5) XCTAssertEqual(manager.reconnectWait, 5)
XCTAssertEqual(manager.reconnectAttempts, 5)
} }
func testManagerRemovesSocket() { func testManagerRemovesSocket() {

View File

@ -26,6 +26,7 @@
- (void)testOnSyntax { - (void)testOnSyntax {
[self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) { [self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) {
[ack with:@[@1]]; [ack with:@[@1]];
[[ack rawEmitView] with:@[@"hello"]];
}]; }];
} }
@ -66,6 +67,10 @@
[self.socket emit:@"testEmit" with:@[@YES]]; [self.socket emit:@"testEmit" with:@[@YES]];
} }
- (void)testRawEmitSyntax {
[[self.socket rawEmitView] emit:@"myEvent" with:@[@1]];
}
- (void)testEmitWithAckSyntax { - (void)testEmitWithAckSyntax {
[[self.socket emitWithAck:@"testAckEmit" with:@[@YES]] timingOutAfter:0 callback:^(NSArray* data) { }]; [[self.socket emitWithAck:@"testAckEmit" with:@[@YES]] timingOutAfter:0 callback:^(NSArray* data) { }];
} }