Support socket.io 3 + starscream 4
This commit is contained in:
		
							parent
							
								
									6992ea5250
								
							
						
					
					
						commit
						6cd8f79e8b
					
				@ -1,7 +1,7 @@
 | 
			
		||||
language: objective-c
 | 
			
		||||
xcode_project: Socket.IO-Client-Swift.xcodeproj # path to your xcodeproj folder
 | 
			
		||||
xcode_scheme: SocketIO-Mac
 | 
			
		||||
osx_image: xcode11.2
 | 
			
		||||
osx_image: xcode12.2
 | 
			
		||||
branches:
 | 
			
		||||
  only:
 | 
			
		||||
    - master
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,8 @@
 | 
			
		||||
# v16.0.0
 | 
			
		||||
 | 
			
		||||
- Removed Objective-C support. It's time for you to embrace Swift.
 | 
			
		||||
- Socket.io 3 support.
 | 
			
		||||
 | 
			
		||||
# v15.3.0
 | 
			
		||||
 | 
			
		||||
- Add `==` operators for `SocketAckStatus` and `String`
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								Cartfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Cartfile
									
									
									
									
									
								
							@ -1 +1 @@
 | 
			
		||||
github "daltoniam/Starscream" ~> 3.1
 | 
			
		||||
github "daltoniam/Starscream" ~> 4.0
 | 
			
		||||
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
github "daltoniam/Starscream" "3.1.0"
 | 
			
		||||
github "daltoniam/Starscream" "4.0.4"
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,8 @@
 | 
			
		||||
        "repositoryURL": "https://github.com/daltoniam/Starscream",
 | 
			
		||||
        "state": {
 | 
			
		||||
          "branch": null,
 | 
			
		||||
          "revision": "9c03ef715d1bc9334b446c90df53586dd38cf849",
 | 
			
		||||
          "version": "3.1.0"
 | 
			
		||||
          "revision": "df8d82047f6654d8e4b655d1b1525c64e1059d21",
 | 
			
		||||
          "version": "4.0.4"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
// swift-tools-version:5.0
 | 
			
		||||
// swift-tools-version:5.3
 | 
			
		||||
 | 
			
		||||
import PackageDescription
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ let package = Package(
 | 
			
		||||
        .library(name: "SocketIO", targets: ["SocketIO"])
 | 
			
		||||
    ],
 | 
			
		||||
    dependencies: [
 | 
			
		||||
        .package(url: "https://github.com/daltoniam/Starscream", .upToNextMinor(from: "3.1.0")),
 | 
			
		||||
        .package(url: "https://github.com/daltoniam/Starscream", .upToNextMinor(from: "4.0.0")),
 | 
			
		||||
    ],
 | 
			
		||||
    targets: [
 | 
			
		||||
        .target(name: "SocketIO", dependencies: ["Starscream"]),
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,12 @@
 | 
			
		||||
Pod::Spec.new do |s|
 | 
			
		||||
  s.name         = "Socket.IO-Client-Swift"
 | 
			
		||||
  s.module_name  = "SocketIO"
 | 
			
		||||
  s.version      = "15.2.0"
 | 
			
		||||
  s.version      = "16.0.0"
 | 
			
		||||
  s.summary      = "Socket.IO-client for iOS and OS X"
 | 
			
		||||
  s.description  = <<-DESC
 | 
			
		||||
                   Socket.IO-client for iOS and OS X.
 | 
			
		||||
                   Supports ws/wss/polling connections and binary.
 | 
			
		||||
                   For socket.io 2.0+ and Swift.
 | 
			
		||||
                   For socket.io 3.0+ and Swift.
 | 
			
		||||
                   DESC
 | 
			
		||||
  s.homepage     = "https://github.com/socketio/socket.io-client-swift"
 | 
			
		||||
  s.license      = { :type => 'MIT' }
 | 
			
		||||
@ -18,7 +18,7 @@ Pod::Spec.new do |s|
 | 
			
		||||
  s.requires_arc = true
 | 
			
		||||
  s.source = {
 | 
			
		||||
    :git => "https://github.com/socketio/socket.io-client-swift.git",
 | 
			
		||||
    :tag => 'v15.2.0',
 | 
			
		||||
    :tag => 'v16.0.0',
 | 
			
		||||
    :submodules => true
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -27,5 +27,5 @@ Pod::Spec.new do |s|
 | 
			
		||||
      'SWIFT_VERSION' => '5.0'
 | 
			
		||||
  }
 | 
			
		||||
  s.source_files  = "Source/SocketIO/**/*.swift", "Source/SocketIO/*.swift"
 | 
			
		||||
  s.dependency "Starscream", "~> 3.1"
 | 
			
		||||
  s.dependency "Starscream", "~> 4.0"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -40,23 +40,14 @@ import Foundation
 | 
			
		||||
///
 | 
			
		||||
/// **NOTE**: The client is not thread/queue safe, all interaction with the socket should be done on the `manager.handleQueue`
 | 
			
		||||
///
 | 
			
		||||
open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
open class SocketIOClient: NSObject, SocketIOClientSpec {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
    /// The namespace that this socket is currently connected to.
 | 
			
		||||
    ///
 | 
			
		||||
    /// **Must** start with a `/`.
 | 
			
		||||
    @objc
 | 
			
		||||
    public let nsp: String
 | 
			
		||||
 | 
			
		||||
    /// The session id of this client.
 | 
			
		||||
    @objc
 | 
			
		||||
    public var sid: String {
 | 
			
		||||
        guard let engine = manager?.engine else { return "" }
 | 
			
		||||
 | 
			
		||||
        return nsp == "/" ? engine.sid : "\(nsp)#\(engine.sid)"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// A handler that will be called on any event.
 | 
			
		||||
    public private(set) var anyHandler: ((SocketAnyEvent) -> ())?
 | 
			
		||||
 | 
			
		||||
@ -64,7 +55,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    public private(set) var handlers = [SocketEventHandler]()
 | 
			
		||||
 | 
			
		||||
    /// The manager for this socket.
 | 
			
		||||
    @objc
 | 
			
		||||
    public private(set) weak var manager: SocketManagerSpec?
 | 
			
		||||
 | 
			
		||||
    /// A view into this socket where emits do not check for binary data.
 | 
			
		||||
@ -76,17 +66,18 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// ```
 | 
			
		||||
    ///
 | 
			
		||||
    /// **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.
 | 
			
		||||
    @objc
 | 
			
		||||
    public private(set) var status = SocketIOStatus.notConnected {
 | 
			
		||||
        didSet {
 | 
			
		||||
            handleClientEvent(.statusChange, data: [status, status.rawValue])
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The id of this socket.io connect. This is different from the sid of the engine.io connection.
 | 
			
		||||
    public private(set) var sid: String?
 | 
			
		||||
 | 
			
		||||
    let ackHandlers = SocketAckManager()
 | 
			
		||||
 | 
			
		||||
    private(set) var currentAck = -1
 | 
			
		||||
@ -99,7 +90,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter manager: The manager for this socket.
 | 
			
		||||
    /// - parameter nsp: The namespace of the socket.
 | 
			
		||||
    @objc
 | 
			
		||||
    public init(manager: SocketManagerSpec, nsp: String) {
 | 
			
		||||
        self.manager = manager
 | 
			
		||||
        self.nsp = nsp
 | 
			
		||||
@ -117,7 +107,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// Connect to the server. The same as calling `connect(timeoutAfter:withHandler:)` with a timeout of 0.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Only call after adding your event listeners, unless you know what you're doing.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func connect() {
 | 
			
		||||
        connect(timeoutAfter: 0, withHandler: nil)
 | 
			
		||||
    }
 | 
			
		||||
@ -129,7 +118,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// - parameter timeoutAfter: The number of seconds after which if we are not connected we assume the connection
 | 
			
		||||
    ///                           has failed. Pass 0 to never timeout.
 | 
			
		||||
    /// - parameter handler: The handler to call when the client fails to connect.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func connect(timeoutAfter: Double, withHandler handler: (() -> ())?) {
 | 
			
		||||
        assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)")
 | 
			
		||||
 | 
			
		||||
@ -142,13 +130,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
 | 
			
		||||
        joinNamespace()
 | 
			
		||||
 | 
			
		||||
        if manager.status == .connected && nsp == "/" {
 | 
			
		||||
            // We might not get a connect event for the default nsp, fire immediately
 | 
			
		||||
            didConnect(toNamespace: nsp)
 | 
			
		||||
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        guard timeoutAfter != 0 else { return }
 | 
			
		||||
 | 
			
		||||
        manager.handleQueue.asyncAfter(deadline: DispatchTime.now() + timeoutAfter) {[weak self] in
 | 
			
		||||
@ -171,14 +152,15 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// then this is only called when the client connects to that namespace.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter toNamespace: The namespace that was connected to.
 | 
			
		||||
    open func didConnect(toNamespace namespace: String) {
 | 
			
		||||
    open func didConnect(toNamespace namespace: String, payload: [String: Any]?) {
 | 
			
		||||
        guard status != .connected else { return }
 | 
			
		||||
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Socket connected", type: logType)
 | 
			
		||||
 | 
			
		||||
        status = .connected
 | 
			
		||||
        sid = payload?["sid"] as? String
 | 
			
		||||
 | 
			
		||||
        handleClientEvent(.connect, data: [namespace])
 | 
			
		||||
        handleClientEvent(.connect, data: payload == nil ? [namespace] : [namespace, payload!])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Called when the client has disconnected from socket.io.
 | 
			
		||||
@ -190,6 +172,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Disconnected: \(reason)", type: logType)
 | 
			
		||||
 | 
			
		||||
        status = .disconnected
 | 
			
		||||
        sid = ""
 | 
			
		||||
 | 
			
		||||
        handleClientEvent(.disconnect, data: [reason])
 | 
			
		||||
    }
 | 
			
		||||
@ -198,7 +181,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    ///
 | 
			
		||||
    /// This will cause the socket to leave the namespace it is associated to, as well as remove itself from the
 | 
			
		||||
    /// `manager`.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func disconnect() {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Closing socket", type: logType)
 | 
			
		||||
 | 
			
		||||
@ -215,7 +197,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// - parameter completion: Callback called on transport write completion.
 | 
			
		||||
    open func emit(_ event: String, _ items: SocketData..., completion: (() -> ())? = nil)  {
 | 
			
		||||
        do {
 | 
			
		||||
            try emit(event, with: items.map({ try $0.socketRepresentation() }), completion: completion)
 | 
			
		||||
            emit([event] + (try items.map({ try $0.socketRepresentation() })), completion: completion)
 | 
			
		||||
        } catch {
 | 
			
		||||
            DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
 | 
			
		||||
                                             type: logType)
 | 
			
		||||
@ -224,25 +206,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// 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
 | 
			
		||||
    open func emit(_ event: String, with items: [Any]) {
 | 
			
		||||
        emit([event] + items)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// 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.
 | 
			
		||||
    /// - parameter completion: Callback called on transport write completion.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func emit(_ event: String, with items: [Any], completion: (() -> ())? = nil) {
 | 
			
		||||
        emit([event] + items, completion: completion)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// 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.
 | 
			
		||||
@ -264,7 +227,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// - returns: An `OnAckCallback`. You must call the `timingOut(after:)` method before the event will be sent.
 | 
			
		||||
    open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback {
 | 
			
		||||
        do {
 | 
			
		||||
            return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() }))
 | 
			
		||||
            return createOnAck([event] + (try items.map({ try $0.socketRepresentation() })))
 | 
			
		||||
        } catch {
 | 
			
		||||
            DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
 | 
			
		||||
                                             type: logType)
 | 
			
		||||
@ -275,27 +238,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// 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
 | 
			
		||||
    open func emitWithAck(_ event: String, with items: [Any]) -> OnAckCallback {
 | 
			
		||||
        return createOnAck([event] + items)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func emit(_ data: [Any],
 | 
			
		||||
              ack: Int? = nil,
 | 
			
		||||
              binary: Bool = true,
 | 
			
		||||
@ -338,7 +280,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter ack: The number for this ack.
 | 
			
		||||
    /// - parameter data: The data sent back with this ack.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func handleAck(_ ack: Int, data: [Any]) {
 | 
			
		||||
        guard status == .connected else { return }
 | 
			
		||||
 | 
			
		||||
@ -361,7 +302,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// - parameter data: The data that was sent with this event.
 | 
			
		||||
    /// - parameter isInternalMessage: Whether this event was sent internally. If `true` it is always sent to handlers.
 | 
			
		||||
    /// - parameter ack: If > 0 then this event expects to get an ack back from the client.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) {
 | 
			
		||||
        guard status == .connected || isInternalMessage else { return }
 | 
			
		||||
 | 
			
		||||
@ -387,7 +327,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
        case .ack, .binaryAck:
 | 
			
		||||
            handleAck(packet.id, data: packet.data)
 | 
			
		||||
        case .connect:
 | 
			
		||||
            didConnect(toNamespace: nsp)
 | 
			
		||||
            didConnect(toNamespace: nsp, payload: packet.data.isEmpty ? nil : packet.data[0] as? [String: Any])
 | 
			
		||||
        case .disconnect:
 | 
			
		||||
            didDisconnect(reason: "Got Disconnect")
 | 
			
		||||
        case .error:
 | 
			
		||||
@ -396,13 +336,11 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Call when you wish to leave a namespace and disconnect this socket.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func leaveNamespace() {
 | 
			
		||||
        manager?.disconnectSocket(self)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Joins `nsp`.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func joinNamespace() {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Joining namespace \(nsp)", type: logType)
 | 
			
		||||
 | 
			
		||||
@ -423,7 +361,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// If you wish to remove a specific event, call the `off(id:)` with the UUID received from its `on` call.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter event: The event to remove handlers for.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func off(_ event: String) {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Removing handler for event: \(event)", type: logType)
 | 
			
		||||
 | 
			
		||||
@ -435,7 +372,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// If you want to remove all events for an event, call the off `off(_:)` method with the event name.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter id: The UUID of the handler you wish to remove.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func off(id: UUID) {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Removing handler with id: \(id)", type: logType)
 | 
			
		||||
 | 
			
		||||
@ -447,7 +383,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// - parameter event: The event name for this handler.
 | 
			
		||||
    /// - parameter callback: The callback that will execute when this event is received.
 | 
			
		||||
    /// - returns: A unique id for the handler that can be used to remove it.
 | 
			
		||||
    @objc
 | 
			
		||||
    @discardableResult
 | 
			
		||||
    open func on(_ event: String, callback: @escaping NormalCallback) -> UUID {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Adding handler for event: \(event)", type: logType)
 | 
			
		||||
@ -491,7 +426,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// - parameter event: The event name for this handler.
 | 
			
		||||
    /// - parameter callback: The callback that will execute when this event is received.
 | 
			
		||||
    /// - returns: A unique id for the handler that can be used to remove it.
 | 
			
		||||
    @objc
 | 
			
		||||
    @discardableResult
 | 
			
		||||
    open func once(_ event: String, callback: @escaping NormalCallback) -> UUID {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Adding once handler for event: \(event)", type: logType)
 | 
			
		||||
@ -512,20 +446,17 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// Adds a handler that will be called on every event.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter handler: The callback that will execute whenever an event is received.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func onAny(_ handler: @escaping (SocketAnyEvent) -> ()) {
 | 
			
		||||
        anyHandler = handler
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Tries to reconnect to the server.
 | 
			
		||||
    @objc
 | 
			
		||||
    @available(*, unavailable, message: "Call the manager's reconnect method")
 | 
			
		||||
    open func reconnect() { }
 | 
			
		||||
 | 
			
		||||
    /// Removes all handlers.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Can be used after disconnecting to break any potential remaining retain cycles.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func removeAllHandlers() {
 | 
			
		||||
        handlers.removeAll(keepingCapacity: false)
 | 
			
		||||
    }
 | 
			
		||||
@ -534,7 +465,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec {
 | 
			
		||||
    /// Called when the manager detects a broken connection, or when a manual reconnect is triggered.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter reason: The reason this socket is reconnecting.
 | 
			
		||||
    @objc
 | 
			
		||||
    open func setReconnecting(reason: String) {
 | 
			
		||||
        status = .connecting
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@ public enum SocketIOClientOption : ClientOption {
 | 
			
		||||
 | 
			
		||||
    /// If passed `true`, the only transport that will be used will be WebSockets.
 | 
			
		||||
    case forceWebsockets(Bool)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /// If passed `true`, the WebSocket stream will be configured with the enableSOCKSProxy `true`.
 | 
			
		||||
    case enableSOCKSProxy(Bool)
 | 
			
		||||
 | 
			
		||||
@ -80,10 +80,10 @@ public enum SocketIOClientOption : ClientOption {
 | 
			
		||||
 | 
			
		||||
    /// The minimum number of seconds to wait before reconnect attempts.
 | 
			
		||||
    case reconnectWait(Int)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /// The maximum number of seconds to wait before reconnect attempts.
 | 
			
		||||
    case reconnectWaitMax(Int)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /// The randomization factor for calculating reconnect jitter.
 | 
			
		||||
    case randomizationFactor(Double)
 | 
			
		||||
 | 
			
		||||
@ -91,7 +91,7 @@ public enum SocketIOClientOption : ClientOption {
 | 
			
		||||
    case secure(Bool)
 | 
			
		||||
 | 
			
		||||
    /// Allows you to set which certs are valid. Useful for SSL pinning.
 | 
			
		||||
    case security(SSLSecurity)
 | 
			
		||||
    case security(CertificatePinning)
 | 
			
		||||
 | 
			
		||||
    /// If you're using a self-signed set. Only use for development.
 | 
			
		||||
    case selfSigned(Bool)
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,9 @@ public protocol SocketIOClientSpec : AnyObject {
 | 
			
		||||
    /// **NOTE**: It is not safe to hold on to this view beyond the life of the socket.
 | 
			
		||||
    var rawEmitView: SocketRawView { get }
 | 
			
		||||
 | 
			
		||||
    /// The id of this socket.io connect. This is different from the sid of the engine.io connection.
 | 
			
		||||
    var sid: String? { get }
 | 
			
		||||
 | 
			
		||||
    /// The status of this client.
 | 
			
		||||
    var status: SocketIOStatus { get }
 | 
			
		||||
 | 
			
		||||
@ -77,7 +80,7 @@ public protocol SocketIOClientSpec : AnyObject {
 | 
			
		||||
    /// then this is only called when the client connects to that namespace.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter toNamespace: The namespace that was connected to.
 | 
			
		||||
    func didConnect(toNamespace namespace: String)
 | 
			
		||||
    func didConnect(toNamespace namespace: String, payload: [String: Any]?)
 | 
			
		||||
 | 
			
		||||
    /// Called when the client has disconnected from socket.io.
 | 
			
		||||
    ///
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,8 @@ import Starscream
 | 
			
		||||
 | 
			
		||||
/// The class that handles the engine.io protocol and transports.
 | 
			
		||||
/// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods.
 | 
			
		||||
open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, ConfigSettable {
 | 
			
		||||
open class SocketEngine:
 | 
			
		||||
        NSObject, WebSocketDelegate, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket, ConfigSettable {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
    private static let logType = "SocketEngine"
 | 
			
		||||
@ -120,6 +121,9 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
    /// The WebSocket for this engine.
 | 
			
		||||
    public private(set) var ws: WebSocket?
 | 
			
		||||
 | 
			
		||||
    /// Whether or not the WebSocket is currently connected.
 | 
			
		||||
    public private(set) var wsConnected = false
 | 
			
		||||
 | 
			
		||||
    /// The client for this engine.
 | 
			
		||||
    public weak var client: SocketEngineClient?
 | 
			
		||||
 | 
			
		||||
@ -130,15 +134,15 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
    private var pingInterval: Int?
 | 
			
		||||
    private var pingTimeout = 0 {
 | 
			
		||||
        didSet {
 | 
			
		||||
            pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25000))
 | 
			
		||||
            pingsMissedMax = Int(pingTimeout / (pingInterval ?? 25000))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var pongsMissed = 0
 | 
			
		||||
    private var pongsMissedMax = 0
 | 
			
		||||
    private var pingsMissed = 0
 | 
			
		||||
    private var pingsMissedMax = 0
 | 
			
		||||
    private var probeWait = ProbeWaitQueue()
 | 
			
		||||
    private var secure = false
 | 
			
		||||
    private var security: SocketIO.SSLSecurity?
 | 
			
		||||
    private var certPinner: CertificatePinning?
 | 
			
		||||
    private var selfSigned = false
 | 
			
		||||
 | 
			
		||||
    // MARK: Initializers
 | 
			
		||||
@ -198,7 +202,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
 | 
			
		||||
    private func handleBase64(message: String) {
 | 
			
		||||
        // binary in base64 string
 | 
			
		||||
        let noPrefix = String(message[message.index(message.startIndex, offsetBy: 2)..<message.endIndex])
 | 
			
		||||
        let noPrefix = String(message[message.index(message.startIndex, offsetBy: 1)..<message.endIndex])
 | 
			
		||||
 | 
			
		||||
        if let data = Data(base64Encoded: noPrefix, options: .ignoreUnknownCharacters) {
 | 
			
		||||
            client?.parseEngineBinaryData(data)
 | 
			
		||||
@ -285,45 +289,14 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
    private func createWebSocketAndConnect() {
 | 
			
		||||
        var req = URLRequest(url: urlWebSocketWithSid)
 | 
			
		||||
 | 
			
		||||
        addHeaders(to: &req, includingCookies: session?.configuration.httpCookieStorage?.cookies(for: urlPollingWithSid))
 | 
			
		||||
        addHeaders(
 | 
			
		||||
            to: &req,
 | 
			
		||||
            includingCookies: session?.configuration.httpCookieStorage?.cookies(for: urlPollingWithSid)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        let stream = FoundationStream()
 | 
			
		||||
        stream.enableSOCKSProxy = enableSOCKSProxy
 | 
			
		||||
        ws = WebSocket(request: req, stream: stream)
 | 
			
		||||
        ws = WebSocket(request: req, certPinner: certPinner, compressionHandler: compress ? WSCompression() : nil)
 | 
			
		||||
        ws?.callbackQueue = engineQueue
 | 
			
		||||
        ws?.enableCompression = compress
 | 
			
		||||
        ws?.disableSSLCertValidation = selfSigned
 | 
			
		||||
        ws?.security = security?.security
 | 
			
		||||
 | 
			
		||||
        ws?.onConnect = {[weak self] in
 | 
			
		||||
            guard let this = self else { return }
 | 
			
		||||
 | 
			
		||||
            this.websocketDidConnect()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ws?.onDisconnect = {[weak self] error in
 | 
			
		||||
            guard let this = self else { return }
 | 
			
		||||
 | 
			
		||||
            this.websocketDidDisconnect(error: error)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ws?.onData = {[weak self] data in
 | 
			
		||||
            guard let this = self else { return }
 | 
			
		||||
 | 
			
		||||
            this.parseEngineData(data)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ws?.onText = {[weak self] message in
 | 
			
		||||
            guard let this = self else { return }
 | 
			
		||||
 | 
			
		||||
            this.parseEngineMessage(message)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ws?.onHttpResponseHeaders = {[weak self] headers in
 | 
			
		||||
            guard let this = self else { return }
 | 
			
		||||
 | 
			
		||||
            this.client?.engineDidWebsocketUpgrade(headers: headers)
 | 
			
		||||
        }
 | 
			
		||||
        ws?.delegate = self
 | 
			
		||||
 | 
			
		||||
        ws?.connect()
 | 
			
		||||
    }
 | 
			
		||||
@ -445,7 +418,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
 | 
			
		||||
        self.sid = sid
 | 
			
		||||
        connected = true
 | 
			
		||||
        pongsMissed = 0
 | 
			
		||||
        pingsMissed = 0
 | 
			
		||||
 | 
			
		||||
        if let upgrades = json["upgrades"] as? [String] {
 | 
			
		||||
            upgradeWs = upgrades.contains("websocket")
 | 
			
		||||
@ -462,18 +435,15 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
            createWebSocketAndConnect()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sendPing()
 | 
			
		||||
 | 
			
		||||
        if !forceWebsockets {
 | 
			
		||||
            doPoll()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        checkPings()
 | 
			
		||||
        client?.engineDidOpen(reason: "Connect")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func handlePong(with message: String) {
 | 
			
		||||
        pongsMissed = 0
 | 
			
		||||
 | 
			
		||||
        // We should upgrade
 | 
			
		||||
        if message == "3probe" {
 | 
			
		||||
            DefaultSocketLogger.Logger.log("Received probe response, should upgrade to WebSockets",
 | 
			
		||||
@ -481,8 +451,31 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
 | 
			
		||||
            upgradeTransport()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        client?.engineDidReceivePong()
 | 
			
		||||
    private func handlePing(with message: String) {
 | 
			
		||||
        pingsMissed = 0
 | 
			
		||||
 | 
			
		||||
        write("", withType: .pong, withData: [])
 | 
			
		||||
 | 
			
		||||
        client?.engineDidReceivePing()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func checkPings() {
 | 
			
		||||
        let pingInterval = self.pingInterval ?? 25_000
 | 
			
		||||
 | 
			
		||||
        engineQueue.asyncAfter(deadline: .now() + .milliseconds(pingInterval)) {[weak self, id = self.sid] in
 | 
			
		||||
            // Make sure not to ping old connections
 | 
			
		||||
            guard let this = self, this.sid == id else { return }
 | 
			
		||||
 | 
			
		||||
            if this.pingsMissed > this.pingsMissedMax {
 | 
			
		||||
                this.closeOutEngine(reason: "Ping timeout")
 | 
			
		||||
            } else {
 | 
			
		||||
                this.pingsMissed += 1
 | 
			
		||||
 | 
			
		||||
                this.checkPings()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Parses raw binary received from engine.io.
 | 
			
		||||
@ -491,7 +484,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
    open func parseEngineData(_ data: Data) {
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Got binary data: \(data)", type: SocketEngine.logType)
 | 
			
		||||
 | 
			
		||||
        client?.parseEngineBinaryData(data.subdata(in: 1..<data.endIndex))
 | 
			
		||||
        client?.parseEngineBinaryData(data)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Parses a raw engine.io packet.
 | 
			
		||||
@ -502,7 +495,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
 | 
			
		||||
        let reader = SocketStringReader(message: message)
 | 
			
		||||
 | 
			
		||||
        if message.hasPrefix("b4") {
 | 
			
		||||
        if message.hasPrefix("b") {
 | 
			
		||||
            return handleBase64(message: message)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -517,6 +510,8 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
            handleMessage(String(message.dropFirst()))
 | 
			
		||||
        case .noop:
 | 
			
		||||
            handleNOOP()
 | 
			
		||||
        case .ping:
 | 
			
		||||
            handlePing(with: message)
 | 
			
		||||
        case .pong:
 | 
			
		||||
            handlePong(with: message)
 | 
			
		||||
        case .open:
 | 
			
		||||
@ -549,12 +544,12 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
        guard connected, let pingInterval = pingInterval else { return }
 | 
			
		||||
 | 
			
		||||
        // Server is not responding
 | 
			
		||||
        if pongsMissed > pongsMissedMax {
 | 
			
		||||
        if pingsMissed > pingsMissedMax {
 | 
			
		||||
            closeOutEngine(reason: "Ping timeout")
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pongsMissed += 1
 | 
			
		||||
        pingsMissed += 1
 | 
			
		||||
        write("", withType: .ping, withData: [], completion: nil)
 | 
			
		||||
 | 
			
		||||
        engineQueue.asyncAfter(deadline: .now() + .milliseconds(pingInterval)) {[weak self, id = self.sid] in
 | 
			
		||||
@ -564,7 +559,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
            this.sendPing()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        client?.engineDidSendPing()
 | 
			
		||||
        client?.engineDidSendPong()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Called when the engine should set/update its configs from a given configuration.
 | 
			
		||||
@ -595,8 +590,8 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
                self.secure = secure
 | 
			
		||||
            case let .selfSigned(selfSigned):
 | 
			
		||||
                self.selfSigned = selfSigned
 | 
			
		||||
            case let .security(security):
 | 
			
		||||
                self.security = security
 | 
			
		||||
            case let .security(pinner):
 | 
			
		||||
                self.certPinner = pinner
 | 
			
		||||
            case .compress:
 | 
			
		||||
                self.compress = true
 | 
			
		||||
            case .enableSOCKSProxy:
 | 
			
		||||
@ -609,7 +604,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
 | 
			
		||||
    // Moves from long-polling to websockets
 | 
			
		||||
    private func upgradeTransport() {
 | 
			
		||||
        if ws?.isConnected ?? false {
 | 
			
		||||
        if wsConnected {
 | 
			
		||||
            DefaultSocketLogger.Logger.log("Upgrading transport to WebSockets", type: SocketEngine.logType)
 | 
			
		||||
 | 
			
		||||
            fastUpgrade = true
 | 
			
		||||
@ -630,6 +625,7 @@ open class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, So
 | 
			
		||||
                completion?()
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            guard !self.probing else {
 | 
			
		||||
                self.probeWait.append((msg, type, data, completion))
 | 
			
		||||
 | 
			
		||||
@ -705,3 +701,32 @@ extension SocketEngine {
 | 
			
		||||
        didError(reason: "Engine URLSession became invalid")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum EngineError: Error {
 | 
			
		||||
    case canceled
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extension SocketEngine {
 | 
			
		||||
    public func didReceive(event: WebSocketEvent, client _: WebSocket) {
 | 
			
		||||
        switch event {
 | 
			
		||||
        case let .connected(headers):
 | 
			
		||||
            wsConnected = true
 | 
			
		||||
            client?.engineDidWebsocketUpgrade(headers: headers)
 | 
			
		||||
            websocketDidConnect()
 | 
			
		||||
        case let .error(err):
 | 
			
		||||
            print(err)
 | 
			
		||||
        case .cancelled:
 | 
			
		||||
            wsConnected = false
 | 
			
		||||
            websocketDidDisconnect(error: EngineError.canceled)
 | 
			
		||||
        case let .disconnected(reason, code):
 | 
			
		||||
            wsConnected = false
 | 
			
		||||
            websocketDidDisconnect(error: nil)
 | 
			
		||||
        case let .text(msg):
 | 
			
		||||
            parseEngineMessage(msg)
 | 
			
		||||
        case let .binary(data):
 | 
			
		||||
            parseEngineData(data)
 | 
			
		||||
        case _:
 | 
			
		||||
            break
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -44,11 +44,11 @@ import Foundation
 | 
			
		||||
    /// - parameter reason: The reason the engine opened.
 | 
			
		||||
    func engineDidOpen(reason: String)
 | 
			
		||||
 | 
			
		||||
    /// Called when the engine receives a pong message.
 | 
			
		||||
    func engineDidReceivePong()
 | 
			
		||||
    /// Called when the engine receives a ping message.
 | 
			
		||||
    func engineDidReceivePing()
 | 
			
		||||
 | 
			
		||||
    /// Called when the engine sends a ping to the server.
 | 
			
		||||
    func engineDidSendPing()
 | 
			
		||||
    /// Called when the engine sends a pong to the server.
 | 
			
		||||
    func engineDidSendPong()
 | 
			
		||||
 | 
			
		||||
    /// Called when the engine has a message that must be parsed.
 | 
			
		||||
    ///
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
import Foundation
 | 
			
		||||
 | 
			
		||||
/// Represents the type of engine.io packet types.
 | 
			
		||||
@objc public enum SocketEnginePacketType : Int {
 | 
			
		||||
@objc public enum SocketEnginePacketType: Int {
 | 
			
		||||
    /// Open message.
 | 
			
		||||
    case open
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@
 | 
			
		||||
import Foundation
 | 
			
		||||
 | 
			
		||||
/// Protocol that is used to implement socket.io polling support
 | 
			
		||||
public protocol SocketEnginePollable : SocketEngineSpec {
 | 
			
		||||
public protocol SocketEnginePollable: SocketEngineSpec {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
    /// `true` If engine's session has been invalidated.
 | 
			
		||||
@ -79,11 +79,7 @@ extension SocketEnginePollable {
 | 
			
		||||
            postWait.removeAll(keepingCapacity: true)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var postStr = ""
 | 
			
		||||
 | 
			
		||||
        for packet in postWait {
 | 
			
		||||
            postStr += "\(packet.msg.utf16.count):\(packet.msg)"
 | 
			
		||||
        }
 | 
			
		||||
        let postStr = postWait.lazy.map({ $0.msg }).joined(separator: "\u{1e}")
 | 
			
		||||
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Created POST string: \(postStr)", type: "SocketEnginePolling")
 | 
			
		||||
 | 
			
		||||
@ -195,19 +191,14 @@ extension SocketEnginePollable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func parsePollingMessage(_ str: String) {
 | 
			
		||||
        guard str.count != 1 else { return }
 | 
			
		||||
        guard !str.isEmpty else { return }
 | 
			
		||||
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Got poll message: \(str)", type: "SocketEnginePolling")
 | 
			
		||||
 | 
			
		||||
        var reader = SocketStringReader(message: str)
 | 
			
		||||
        let records = str.components(separatedBy: "\u{1e}")
 | 
			
		||||
 | 
			
		||||
        while reader.hasNext {
 | 
			
		||||
            if let n = Int(reader.readUntilOccurence(of: ":")) {
 | 
			
		||||
                parseEngineMessage(reader.read(count: n))
 | 
			
		||||
            } else {
 | 
			
		||||
                parseEngineMessage(str)
 | 
			
		||||
                break
 | 
			
		||||
            }
 | 
			
		||||
        for record in records {
 | 
			
		||||
            parseEngineMessage(record)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ import Foundation
 | 
			
		||||
import Starscream
 | 
			
		||||
 | 
			
		||||
/// Specifies a SocketEngine.
 | 
			
		||||
@objc public protocol SocketEngineSpec {
 | 
			
		||||
public protocol SocketEngineSpec: class {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
    /// The client for this engine.
 | 
			
		||||
@ -173,9 +173,9 @@ extension SocketEngineSpec {
 | 
			
		||||
 | 
			
		||||
    func createBinaryDataForSend(using data: Data) -> Either<Data, String> {
 | 
			
		||||
        if polling {
 | 
			
		||||
            return .right("b4" + data.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)))
 | 
			
		||||
            return .right("b" + data.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)))
 | 
			
		||||
        } else {
 | 
			
		||||
            return .left(Data([0x4]) + data)
 | 
			
		||||
            return .left(data)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,12 @@ import Foundation
 | 
			
		||||
import Starscream
 | 
			
		||||
 | 
			
		||||
/// Protocol that is used to implement socket.io WebSocket support
 | 
			
		||||
public protocol SocketEngineWebsocket : SocketEngineSpec {
 | 
			
		||||
public protocol SocketEngineWebsocket: SocketEngineSpec {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
    /// Whether or not the ws is connected
 | 
			
		||||
    var wsConnected: Bool { get }
 | 
			
		||||
 | 
			
		||||
    // MARK: Methods
 | 
			
		||||
 | 
			
		||||
    /// Sends an engine.io message through the WebSocket transport.
 | 
			
		||||
@ -47,7 +52,7 @@ public protocol SocketEngineWebsocket : SocketEngineSpec {
 | 
			
		||||
// WebSocket methods
 | 
			
		||||
extension SocketEngineWebsocket {
 | 
			
		||||
    func probeWebSocket() {
 | 
			
		||||
        if ws?.isConnected ?? false {
 | 
			
		||||
        if wsConnected  {
 | 
			
		||||
            sendWebSocketMessage("probe", withType: .ping, withData: [], completion: nil)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -69,14 +74,14 @@ extension SocketEngineWebsocket {
 | 
			
		||||
 | 
			
		||||
        ws?.write(string: "\(type.rawValue)\(str)")
 | 
			
		||||
 | 
			
		||||
        if data.count == 0 {
 | 
			
		||||
            completion?()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for item in data {
 | 
			
		||||
            if case let .left(bin) = createBinaryDataForSend(using: item) {
 | 
			
		||||
                ws?.write(data: bin, completion: completion)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if data.count == 0 {
 | 
			
		||||
            completion?()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ import Foundation
 | 
			
		||||
///
 | 
			
		||||
/// **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"
 | 
			
		||||
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
@ -282,18 +282,8 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emitAll(event, withItems: emitData)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Sends an event to the server on all namespaces in this manager.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Same as `emitAll(_:_:)`, but meant for Objective-C.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter event: The event to send.
 | 
			
		||||
    /// - parameter items: The data to send with this event.
 | 
			
		||||
    open func emitAll(_ event: String, withItems items: [Any]) {
 | 
			
		||||
        forAll {socket in
 | 
			
		||||
            socket.emit(event, with: items, completion: nil)
 | 
			
		||||
            socket.emit([event] + emitData, completion: nil)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -349,33 +339,32 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Engine opened \(reason)", type: SocketManager.logType)
 | 
			
		||||
 | 
			
		||||
        status = .connected
 | 
			
		||||
        nsps["/"]?.didConnect(toNamespace: "/")
 | 
			
		||||
 | 
			
		||||
        for (nsp, socket) in nsps where nsp != "/" && socket.status == .connecting {
 | 
			
		||||
        for (_, socket) in nsps where socket.status == .connecting {
 | 
			
		||||
            connectSocket(socket)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Called when the engine receives a pong message.
 | 
			
		||||
    open func engineDidReceivePong() {
 | 
			
		||||
    open func engineDidReceivePing() {
 | 
			
		||||
        handleQueue.async {
 | 
			
		||||
            self._engineDidReceivePong()
 | 
			
		||||
            self._engineDidReceivePing()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func _engineDidReceivePong() {
 | 
			
		||||
        emitAll(clientEvent: .pong, data: [])
 | 
			
		||||
    private func _engineDidReceivePing() {
 | 
			
		||||
        emitAll(clientEvent: .ping, data: [])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Called when the sends a ping to the server.
 | 
			
		||||
    open func engineDidSendPing() {
 | 
			
		||||
    open func engineDidSendPong() {
 | 
			
		||||
        handleQueue.async {
 | 
			
		||||
            self._engineDidSendPing()
 | 
			
		||||
            self._engineDidSendPong()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func _engineDidSendPing() {
 | 
			
		||||
        emitAll(clientEvent: .ping, data: [])
 | 
			
		||||
    private func _engineDidSendPong() {
 | 
			
		||||
        emitAll(clientEvent: .pong, data: [])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func forAll(do: (SocketIOClient) throws -> ()) rethrows {
 | 
			
		||||
@ -476,14 +465,19 @@ open class SocketManager : NSObject, SocketManagerSpec, SocketParsable, SocketDa
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Trying to reconnect", type: SocketManager.logType)
 | 
			
		||||
        emitAll(clientEvent: .reconnectAttempt, data: [(reconnectAttempts - currentReconnectAttempt)])
 | 
			
		||||
 | 
			
		||||
        forAll {socket in
 | 
			
		||||
            guard socket.status == .connecting else { return }
 | 
			
		||||
 | 
			
		||||
            socket.handleClientEvent(.reconnectAttempt, data: [(reconnectAttempts - currentReconnectAttempt)])
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        currentReconnectAttempt += 1
 | 
			
		||||
        connect()
 | 
			
		||||
 | 
			
		||||
        let interval = reconnectInterval(attempts: currentReconnectAttempt)
 | 
			
		||||
        DefaultSocketLogger.Logger.log("Scheduling reconnect in \(interval)s", type: SocketManager.logType)
 | 
			
		||||
        handleQueue.asyncAfter(deadline: DispatchTime.now() + interval, execute: _tryReconnect)
 | 
			
		||||
        handleQueue.asyncAfter(deadline: .now() + interval, execute: _tryReconnect)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func reconnectInterval(attempts: Int) -> Double {
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,6 @@ import Foundation
 | 
			
		||||
/// 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.
 | 
			
		||||
///
 | 
			
		||||
@objc
 | 
			
		||||
public protocol SocketManagerSpec : AnyObject, SocketEngineClient {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
@ -71,7 +70,7 @@ public protocol SocketManagerSpec : AnyObject, SocketEngineClient {
 | 
			
		||||
 | 
			
		||||
    /// The minimum number of seconds to wait before attempting to reconnect.
 | 
			
		||||
    var reconnectWait: Int { get set }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /// The maximum number of seconds to wait before attempting to reconnect.
 | 
			
		||||
    var reconnectWaitMax: Int { get set }
 | 
			
		||||
 | 
			
		||||
@ -116,7 +115,7 @@ public protocol SocketManagerSpec : AnyObject, SocketEngineClient {
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter event: The event to send.
 | 
			
		||||
    /// - parameter items: The data to send with this event.
 | 
			
		||||
    func emitAll(_ event: String, withItems items: [Any])
 | 
			
		||||
    func emitAll(_ event: String, _ items: SocketData...)
 | 
			
		||||
 | 
			
		||||
    /// Tries to reconnect to the server.
 | 
			
		||||
    ///
 | 
			
		||||
 | 
			
		||||
@ -118,7 +118,7 @@ public extension SocketParsable where Self: SocketManagerSpec & SocketDataBuffer
 | 
			
		||||
 | 
			
		||||
        var dataArray = String(message.utf16[message.utf16.index(reader.currentIndex, offsetBy: 1)...])!
 | 
			
		||||
 | 
			
		||||
        if type == .error && !dataArray.hasPrefix("[") && !dataArray.hasSuffix("]") {
 | 
			
		||||
        if (type == .error || type == .connect) && !dataArray.hasPrefix("[") && !dataArray.hasSuffix("]") {
 | 
			
		||||
            dataArray = "[" + dataArray + "]"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,72 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  SSLSecurity.swift
 | 
			
		||||
//  SocketIO-iOS
 | 
			
		||||
//
 | 
			
		||||
//  Created by Lukas Schmidt on 24.09.17.
 | 
			
		||||
//
 | 
			
		||||
//  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
 | 
			
		||||
import Starscream
 | 
			
		||||
 | 
			
		||||
/// A wrapper around Starscream's SSLSecurity that provides a minimal Objective-C interface.
 | 
			
		||||
open class SSLSecurity : NSObject {
 | 
			
		||||
    // MARK: Properties
 | 
			
		||||
 | 
			
		||||
    /// The internal Starscream SSLSecurity.
 | 
			
		||||
    public let security: Starscream.SSLSecurity
 | 
			
		||||
 | 
			
		||||
    init(security: Starscream.SSLSecurity) {
 | 
			
		||||
        self.security = security
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // MARK: Methods
 | 
			
		||||
 | 
			
		||||
    /// Creates a new SSLSecurity that specifies whether to use publicKeys or certificates should be used for SSL
 | 
			
		||||
    /// pinning validation
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning
 | 
			
		||||
    /// validation
 | 
			
		||||
    @objc
 | 
			
		||||
    public convenience init(usePublicKeys: Bool = true) {
 | 
			
		||||
        let security = Starscream.SSLSecurity(usePublicKeys: usePublicKeys)
 | 
			
		||||
        self.init(security: security)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// Designated init
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter certs: is the certificates or public keys to use
 | 
			
		||||
    /// - parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning
 | 
			
		||||
    /// validation
 | 
			
		||||
    /// - returns: a representation security object to be used with
 | 
			
		||||
    public convenience init(certs: [SSLCert], usePublicKeys: Bool) {
 | 
			
		||||
        let security = Starscream.SSLSecurity(certs: certs, usePublicKeys: usePublicKeys)
 | 
			
		||||
        self.init(security: security)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns whether or not the given trust is valid.
 | 
			
		||||
    ///
 | 
			
		||||
    /// - parameter trust: The trust to validate.
 | 
			
		||||
    /// - parameter domain: The CN domain to validate.
 | 
			
		||||
    /// - returns: Whether or not this is valid.
 | 
			
		||||
    public func isValid(_ trust: SecTrust, domain: String?) -> Bool {
 | 
			
		||||
        return security.isValid(trust, domain: domain)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -77,7 +77,7 @@ extension Dictionary where Key == String, Value == Any {
 | 
			
		||||
            return .randomizationFactor(factor)
 | 
			
		||||
        case let ("secure", secure as Bool):
 | 
			
		||||
            return .secure(secure)
 | 
			
		||||
        case let ("security", security as SSLSecurity):
 | 
			
		||||
        case let ("security", security as CertificatePinning):
 | 
			
		||||
            return .security(security)
 | 
			
		||||
        case let ("selfSigned", selfSigned as Bool):
 | 
			
		||||
            return .selfSigned(selfSigned)
 | 
			
		||||
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by Erik Little on 10/21/17.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "SocketIO_Tests-Swift.h"
 | 
			
		||||
 | 
			
		||||
@import XCTest;
 | 
			
		||||
@import SocketIO;
 | 
			
		||||
 | 
			
		||||
@interface ManagerObjectiveCTest : XCTestCase
 | 
			
		||||
 | 
			
		||||
@property TestSocket* socket;
 | 
			
		||||
@property TestSocket* socket2;
 | 
			
		||||
@property TestManager* manager;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@ -1,141 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by Erik Little on 10/21/17.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "ManagerObjectiveCTest.h"
 | 
			
		||||
 | 
			
		||||
@import Dispatch;
 | 
			
		||||
@import Foundation;
 | 
			
		||||
@import XCTest;
 | 
			
		||||
@import SocketIO;
 | 
			
		||||
 | 
			
		||||
@implementation ManagerObjectiveCTest
 | 
			
		||||
 | 
			
		||||
- (void)testSettingConfig {
 | 
			
		||||
    NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"];
 | 
			
		||||
    NSDictionary* headers = @{@"My Header": @"Some Value"};
 | 
			
		||||
 | 
			
		||||
    self.manager = [[TestManager alloc] initWithSocketURL:url config:@{
 | 
			
		||||
            @"forceNew": @YES,
 | 
			
		||||
            @"extraHeaders": headers
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    [self.manager connect];
 | 
			
		||||
 | 
			
		||||
    XCTAssertTrue(self.manager.forceNew);
 | 
			
		||||
    XCTAssertTrue([self.manager.engine.extraHeaders isEqualToDictionary:headers]);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testManagerProperties {
 | 
			
		||||
    XCTAssertNotNil(self.manager.defaultSocket);
 | 
			
		||||
    XCTAssertNil(self.manager.engine);
 | 
			
		||||
    XCTAssertFalse(self.manager.forceNew);
 | 
			
		||||
    XCTAssertEqual(self.manager.handleQueue, dispatch_get_main_queue());
 | 
			
		||||
    XCTAssertTrue(self.manager.reconnects);
 | 
			
		||||
    XCTAssertEqual(self.manager.reconnectWait, 10);
 | 
			
		||||
    XCTAssertEqual(self.manager.reconnectWaitMax, 30);
 | 
			
		||||
    XCTAssertEqual(self.manager.randomizationFactor, 0.5);
 | 
			
		||||
    XCTAssertEqual(self.manager.status, SocketIOStatusNotConnected);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testConnectSocketSyntax {
 | 
			
		||||
    [self setUpSockets];
 | 
			
		||||
    [self.manager connectSocket:self.socket];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testDisconnectSocketSyntax {
 | 
			
		||||
    [self setUpSockets];
 | 
			
		||||
    [self.manager disconnectSocket:self.socket];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testSocketForNamespaceSyntax {
 | 
			
		||||
    SocketIOClient* client = [self.manager socketForNamespace:@"/swift"];
 | 
			
		||||
    client = nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testManagerCallsConnect {
 | 
			
		||||
    [self setUpSockets];
 | 
			
		||||
 | 
			
		||||
    XCTestExpectation* expect = [self expectationWithDescription:@"The manager should call connect on the default socket"];
 | 
			
		||||
    XCTestExpectation* expect2 = [self expectationWithDescription:@"The manager should call connect on the socket"];
 | 
			
		||||
 | 
			
		||||
    self.socket.expects[@"didConnectCalled"] = expect;
 | 
			
		||||
    self.socket2.expects[@"didConnectCalled"] = expect2;
 | 
			
		||||
 | 
			
		||||
    [self.socket connect];
 | 
			
		||||
    [self.socket2 connect];
 | 
			
		||||
 | 
			
		||||
    [self.manager fakeConnecting];
 | 
			
		||||
    [self.manager fakeConnectingToNamespace:@"/swift"];
 | 
			
		||||
 | 
			
		||||
    [self waitForExpectationsWithTimeout:0.3 handler:nil];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testManagerCallsDisconnect {
 | 
			
		||||
    [self setUpSockets];
 | 
			
		||||
 | 
			
		||||
    XCTestExpectation* expect = [self expectationWithDescription:@"The manager should call disconnect on the default socket"];
 | 
			
		||||
    XCTestExpectation* expect2 = [self expectationWithDescription:@"The manager should call disconnect on the socket"];
 | 
			
		||||
 | 
			
		||||
    self.socket.expects[@"didDisconnectCalled"] = expect;
 | 
			
		||||
    self.socket2.expects[@"didDisconnectCalled"] = expect2;
 | 
			
		||||
 | 
			
		||||
    [self.socket2 on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
 | 
			
		||||
        [self.manager disconnect];
 | 
			
		||||
        [self.manager fakeDisconnecting];
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    [self.socket connect];
 | 
			
		||||
    [self.socket2 connect];
 | 
			
		||||
 | 
			
		||||
    [self.manager fakeConnecting];
 | 
			
		||||
    [self.manager fakeConnectingToNamespace:@"/swift"];
 | 
			
		||||
 | 
			
		||||
    [self waitForExpectationsWithTimeout:0.3 handler:nil];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testManagerEmitAll {
 | 
			
		||||
    [self setUpSockets];
 | 
			
		||||
 | 
			
		||||
    XCTestExpectation* expect = [self expectationWithDescription:@"The manager should emit an event to the default socket"];
 | 
			
		||||
    XCTestExpectation* expect2 = [self expectationWithDescription:@"The manager should emit an event to the socket"];
 | 
			
		||||
 | 
			
		||||
    self.socket.expects[@"emitAllEventCalled"] = expect;
 | 
			
		||||
    self.socket2.expects[@"emitAllEventCalled"] = expect2;
 | 
			
		||||
 | 
			
		||||
    [self.socket2 on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
 | 
			
		||||
        [self.manager emitAll:@"event" withItems:@[@"testing"]];
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    [self.socket connect];
 | 
			
		||||
    [self.socket2 connect];
 | 
			
		||||
 | 
			
		||||
    [self.manager fakeConnecting];
 | 
			
		||||
    [self.manager fakeConnectingToNamespace:@"/swift"];
 | 
			
		||||
 | 
			
		||||
    [self waitForExpectationsWithTimeout:0.3 handler:nil];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testMangerRemoveSocket {
 | 
			
		||||
    [self setUpSockets];
 | 
			
		||||
 | 
			
		||||
    [self.manager removeSocket:self.socket];
 | 
			
		||||
 | 
			
		||||
    XCTAssertNil(self.manager.nsps[self.socket.nsp]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setUpSockets {
 | 
			
		||||
    self.socket = [self.manager testSocketForNamespace:@"/"];
 | 
			
		||||
    self.socket2 = [self.manager testSocketForNamespace:@"/swift"];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setUp {
 | 
			
		||||
    [super setUp];
 | 
			
		||||
    NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"];
 | 
			
		||||
    self.manager = [[TestManager alloc] initWithSocketURL:url config:@{@"log": @NO}];
 | 
			
		||||
    self.socket = nil;
 | 
			
		||||
    self.socket2 = nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by Erik Little on 10/21/17.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@import Dispatch;
 | 
			
		||||
@import Foundation;
 | 
			
		||||
@import XCTest;
 | 
			
		||||
@import SocketIO;
 | 
			
		||||
 | 
			
		||||
@interface SocketObjectiveCTest : XCTestCase
 | 
			
		||||
 | 
			
		||||
@property SocketIOClient* socket;
 | 
			
		||||
@property SocketManager* manager;
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
@ -1,122 +0,0 @@
 | 
			
		||||
//
 | 
			
		||||
//  SocketObjectiveCTest.m
 | 
			
		||||
//  Socket.IO-Client-Swift
 | 
			
		||||
//
 | 
			
		||||
//  Created by Erik Little on 3/25/16.
 | 
			
		||||
//
 | 
			
		||||
//  Merely tests whether the Objective-C api breaks
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#import "SocketIO_Tests-Swift.h"
 | 
			
		||||
#import "SocketObjectiveCTest.h"
 | 
			
		||||
 | 
			
		||||
@import Dispatch;
 | 
			
		||||
@import Foundation;
 | 
			
		||||
@import XCTest;
 | 
			
		||||
@import SocketIO;
 | 
			
		||||
 | 
			
		||||
// TODO Manager interface tests
 | 
			
		||||
 | 
			
		||||
@implementation SocketObjectiveCTest
 | 
			
		||||
 | 
			
		||||
- (void)testProperties {
 | 
			
		||||
    XCTAssertTrue([self.socket.nsp isEqualToString:@"/"]);
 | 
			
		||||
    XCTAssertEqual(self.socket.status, SocketIOStatusNotConnected);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testOnSyntax {
 | 
			
		||||
    [self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) {
 | 
			
		||||
        [ack with:@[@1]];
 | 
			
		||||
        [[ack rawEmitView] with:@[@"hello"]];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testConnectSyntax {
 | 
			
		||||
    [self.socket connect];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testConnectTimeoutAfterSyntax {
 | 
			
		||||
    [self.socket connectWithTimeoutAfter:1 withHandler: ^() { }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testDisconnectSyntax {
 | 
			
		||||
    [self.socket disconnect];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testLeaveNamespaceSyntax {
 | 
			
		||||
    [self.socket leaveNamespace];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testJoinNamespaceSyntax {
 | 
			
		||||
    [self.socket joinNamespace];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testOnAnySyntax {
 | 
			
		||||
    [self.socket onAny:^(SocketAnyEvent* any) {
 | 
			
		||||
        NSString* event = any.event;
 | 
			
		||||
        NSArray* data = any.items;
 | 
			
		||||
 | 
			
		||||
        [self.socket emit:event with:data];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testRemoveAllHandlersSyntax {
 | 
			
		||||
    [self.socket removeAllHandlers];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testEmitSyntax {
 | 
			
		||||
    [self.socket emit:@"testEmit" with:@[@YES]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testEmitWriteCompletionSyntax {
 | 
			
		||||
    [self.socket emit:@"testEmit" with:@[@YES] completion:^{}];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testEmitWriteCompletion {
 | 
			
		||||
    XCTestExpectation* expect = [self expectationWithDescription:@"Write completion should be called"];
 | 
			
		||||
 | 
			
		||||
    [self.socket emit:@"testEmit" with:@[@YES] completion:^{
 | 
			
		||||
        [expect fulfill];
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    [self waitForExpectationsWithTimeout:0.3 handler:nil];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testRawEmitSyntax {
 | 
			
		||||
    [[self.socket rawEmitView] emit:@"myEvent" with:@[@1]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testEmitWithAckSyntax {
 | 
			
		||||
    [[self.socket emitWithAck:@"testAckEmit" with:@[@YES]] timingOutAfter:0 callback:^(NSArray* data) { }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testOffSyntax {
 | 
			
		||||
    [self.socket off:@"test"];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testSSLSecurity {
 | 
			
		||||
    SSLSecurity* sec = [[SSLSecurity alloc] initWithUsePublicKeys:0];
 | 
			
		||||
    sec = nil;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)testStatusChangeHandler {
 | 
			
		||||
    XCTestExpectation* expect = [self expectationWithDescription:@"statusChange should be correctly called"];
 | 
			
		||||
 | 
			
		||||
    [self.socket on:@"statusChange" callback:^(NSArray* data, SocketAckEmitter* ack) {
 | 
			
		||||
        XCTAssertTrue([data[1] integerValue] == SocketIOStatusConnecting);
 | 
			
		||||
        [expect fulfill];
 | 
			
		||||
    }];
 | 
			
		||||
 | 
			
		||||
    [OBjcUtils setTestStatusWithSocket:self.socket status:SocketIOStatusConnecting];
 | 
			
		||||
 | 
			
		||||
    [self waitForExpectationsWithTimeout:0.3 handler:nil];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (void)setUp {
 | 
			
		||||
    [super setUp];
 | 
			
		||||
    NSURL* url = [[NSURL alloc] initWithString:@"http://localhost"];
 | 
			
		||||
    self.manager = [[SocketManager alloc] initWithSocketURL:url config:@{@"log": @NO}];
 | 
			
		||||
    self.socket = [self.manager defaultSocket];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@end
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user