Skip to content

Commit

Permalink
Document SocketIOClientSwift
Browse files Browse the repository at this point in the history
add docs

Start documenting engine

More engine documentation

Document engine

document SocketEngineClient

Document SocketEnginePollable and SocketEnginePacketType

Document SocketEngineWebsocket

Document SocketIOClient

Document SocketIOClientStatus

Document SocketLogger

Document some typealiases

Document SocketIOClientOption

Document SocketIOClientConfiguration
  • Loading branch information
nuclearace committed May 6, 2017
1 parent a8ee018 commit 1ff8e11
Show file tree
Hide file tree
Showing 58 changed files with 17,706 additions and 114 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ DerivedData
Socket.IO-Test-Server/node_modules/*

.idea/
docs/docsets/
docs/undocumented.json
3 changes: 3 additions & 0 deletions Source/SocketAckEmitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public final class SocketAckEmitter : NSObject {
let socket: SocketIOClient
let ackNum: Int

// MARK: Properties

/// If true, this handler is expecting to be acked. Call `with(_: SocketData...)` to ack.
public var expected: Bool {
return ackNum != -1
Expand Down Expand Up @@ -67,6 +69,7 @@ public final class SocketAckEmitter : NSObject {
/// A class that represents an emit that will request an ack that has not yet been sent.
/// Call `timingOut(after:callback:)` to complete the emit
/// Example:
///
/// ```swift
/// socket.emitWithAck("myEvent").timingOut(after: 1) {data in
/// ...
Expand Down
45 changes: 33 additions & 12 deletions Source/SocketClientManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import Foundation

/**
Experimental socket manager.
API subject to change.
Can be used to persist sockets across ViewControllers.
Sockets are strongly stored, so be sure to remove them once they are no
longer needed.
Example usage:
```
let manager = SocketClientManager.sharedManager
Expand All @@ -44,38 +44,59 @@ import Foundation
```
*/
open class SocketClientManager : NSObject {
// MARK: Properties.

/// The shared manager.
open static let sharedManager = SocketClientManager()

private var sockets = [String: SocketIOClient]()


/// Gets a socket by its name.
///
/// - returns: The socket, if one had the given name.
open subscript(string: String) -> SocketIOClient? {
get {
return sockets[string]
}

set(socket) {
sockets[string] = socket
}
}


// MARK: Methods.

/// Adds a socket.
///
/// - parameter socket: The socket to add.
/// - parameter labeledAs: The label for this socket.
open func addSocket(_ socket: SocketIOClient, labeledAs label: String) {
sockets[label] = socket
}


/// Removes a socket by a given name.
///
/// - parameter withLabel: The label of the socket to remove.
/// - returns: The socket for the given label, if one was present.
open func removeSocket(withLabel label: String) -> SocketIOClient? {
return sockets.removeValue(forKey: label)
}

/// Removes a socket.
///
/// - parameter socket: The socket to remove.
/// - returns: The socket if it was in the manager.
open func removeSocket(_ socket: SocketIOClient) -> SocketIOClient? {
var returnSocket: SocketIOClient?

for (label, dictSocket) in sockets where dictSocket === socket {
returnSocket = sockets.removeValue(forKey: label)
}

return returnSocket
}


/// Removes all the sockets in the manager.
open func removeSockets() {
sockets.removeAll()
}
Expand Down
112 changes: 106 additions & 6 deletions Source/SocketEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,96 @@
import Dispatch
import Foundation

/// The class that handles the engine.io protocol and transports.
/// See `SocketEnginePollable` and `SocketEngineWebsocket` for transport specific methods.
public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket {
public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: [])
// MARK: Properties

/// The queue that all engine actions take place on.
public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue")

/// The connect parameters sent during a connect.
public var connectParams: [String: Any]? {
didSet {
(urlPolling, urlWebSocket) = createURLs()
}
}

/// A queue of engine.io messages waiting for POSTing
///
/// **You should not touch this directly**
public var postWait = [String]()

/// `true` if there is an outstanding poll. Trying to poll before the first is done will cause socket.io to
/// disconnect us.
///
/// **Do not touch this directly**
public var waitingForPoll = false

/// `true` if there is an outstanding post. Trying to post before the first is done will cause socket.io to
/// disconnect us.
///
/// **Do not touch this directly**
public var waitingForPost = false

/// `true` if this engine is closed.
public private(set) var closed = false

/// `true` if this engine is connected. Connected means that the initial poll connect has succeeded.
public private(set) var connected = false

/// An array of HTTPCookies that are sent during the connection.
public private(set) var cookies: [HTTPCookie]?

/// Set to `true` if using the node.js version of socket.io. The node.js version of socket.io
/// handles utf8 incorrectly.
public private(set) var doubleEncodeUTF8 = true

/// A dictionary of extra http headers that will be set during connection.
public private(set) var extraHeaders: [String: String]?

/// When `true`, the engine is in the process of switching to WebSockets.
///
/// **Do not touch this directly**
public private(set) var fastUpgrade = false

/// When `true`, the engine will only use HTTP long-polling as a transport.
public private(set) var forcePolling = false

/// When `true`, the engine will only use WebSockets as a transport.
public private(set) var forceWebsockets = false

/// `true` If engine's session has been invalidated.
public private(set) var invalidated = false

/// If `true`, the engine is currently in HTTP long-polling mode.
public private(set) var polling = true

/// If `true`, the engine is currently seeing whether it can upgrade to WebSockets.
public private(set) var probing = false

/// The URLSession that will be used for polling.
public private(set) var session: URLSession?

/// The session id for this engine.
public private(set) var sid = ""

/// The path to engine.io.
public private(set) var socketPath = "/engine.io/"

/// The url for polling.
public private(set) var urlPolling = URL(string: "http://localhost/")!

/// The url for WebSockets.
public private(set) var urlWebSocket = URL(string: "http://localhost/")!

/// If `true`, then the engine is currently in WebSockets mode.
public private(set) var websocket = false

/// The WebSocket for this engine.
public private(set) var ws: WebSocket?

/// The client for this engine.
public weak var client: SocketEngineClient?

private weak var sessionDelegate: URLSessionDelegate?
Expand All @@ -79,6 +137,13 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
private var selfSigned = false
private var voipEnabled = false

// MARK: Initializers

/// Creates a new engine.
///
/// - parameter client: The client for this engine.
/// - parameter url: The url for this engine.
/// - parameter config: An array of configuration options for this engine.
public init(client: SocketEngineClient, url: URL, config: SocketIOClientConfiguration) {
self.client = client
self.url = url
Expand Down Expand Up @@ -124,6 +189,11 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
(urlPolling, urlWebSocket) = createURLs()
}

/// Creates a new engine.
///
/// - parameter client: The client for this engine.
/// - parameter url: The url for this engine.
/// - parameter options: The options for this engine.
public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) {
self.init(client: client, url: url, config: options?.toSocketConfiguration() ?? [])
}
Expand All @@ -134,6 +204,8 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
stopPolling()
}

// MARK: Methods

private func checkAndHandleEngineError(_ msg: String) {
do {
let dict = try msg.toNSDictionary()
Expand Down Expand Up @@ -171,7 +243,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
client?.engineDidClose(reason: reason)
}

/// Starts the connection to the server
/// Starts the connection to the server.
public func connect() {
engineQueue.async {
self._connect()
Expand Down Expand Up @@ -273,12 +345,16 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
ws?.connect()
}

/// Called when an error happens during execution. Causes a disconnection.
public func didError(reason: String) {
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
client?.engineDidError(reason: reason)
disconnect(reason: reason)
}

/// Disconnects from the server.
///
/// - parameter reason: The reason for the disconnection. This is communicated up to the client.
public func disconnect(reason: String) {
engineQueue.async {
self._disconnect(reason: reason)
Expand Down Expand Up @@ -311,6 +387,10 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
closeOutEngine(reason: reason)
}

/// Called to switch from HTTP long-polling to WebSockets. After calling this method the engine will be in
/// WebSocket mode.
///
/// **You shouldn't call this directly**
public func doFastUpgrade() {
if waitingForPoll {
DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," +
Expand Down Expand Up @@ -339,8 +419,10 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
}

// We had packets waiting for send when we upgraded
// Send them raw
/// Causes any packets that were waiting for POSTing to be sent through the WebSocket. This happens because when
/// the engine is attempting to upgrade to WebSocket it does not do any POSTing.
///
/// **You shouldn't call this directly**
public func flushWaitingForPostToWebSocket() {
guard let ws = self.ws else { return }

Expand Down Expand Up @@ -415,12 +497,20 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
}

/// Parses raw binary received from engine.io.
///
/// - parameter data: The data to parse.
public func parseEngineData(_ data: Data) {
DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data)

client?.parseEngineBinaryData(data.subdata(in: 1..<data.endIndex))
}

/// Parses a raw engine.io packet.
///
/// - parameter message: The message to parse.
/// - parameter fromPolling: Whether this message is from long-polling.
/// If `true` we might have to fix utf8 encoding.
public func parseEngineMessage(_ message: String, fromPolling: Bool) {
DefaultSocketLogger.Logger.log("Got message: %@", type: logType, args: message)

Expand Down Expand Up @@ -506,7 +596,11 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
}

/// Write a message, independent of transport.
/// Writes a message to engine.io, independent of transport.
///
/// - parameter msg: The message to send.
/// - parameter withType: The type of this message.
/// - parameter withData: Any data that this message has.
public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) {
engineQueue.async {
guard self.connected else { return }
Expand All @@ -525,7 +619,9 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
}

// Delegate methods
// MARK: Starscream delegate conformance

/// Delegate method for connection.
public func websocketDidConnect(socket: WebSocket) {
if !forceWebsockets {
probing = true
Expand All @@ -537,6 +633,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
}

/// Delegate method for disconnection.
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
probing = false

Expand All @@ -562,6 +659,9 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}

extension SocketEngine {
// MARK: URLSessionDelegate methods

/// Delegate called when the session becomes invalid.
public func URLSession(session: URLSession, didBecomeInvalidWithError error: NSError?) {
DefaultSocketLogger.Logger.error("Engine URLSession became invalid", type: "SocketEngine")

Expand Down
24 changes: 23 additions & 1 deletion Source/SocketEngineClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,32 @@

import Foundation

@objc public protocol SocketEngineClient {
/// Declares that a type will be a delegate to an engine.
@objc public protocol SocketEngineClient {
// MARK: Methods

/// Called when the engine errors.
///
/// - parameter reason: The reason the engine errored.
func engineDidError(reason: String)

/// Called when the engine closes.
///
/// - parameter reason: The reason that the engine closed.
func engineDidClose(reason: String)

/// Called when the engine opens.
///
/// - parameter reason: The reason the engine opened.
func engineDidOpen(reason: String)

/// Called when the engine has a message that must be parsed.
///
/// - parameter msg: The message that needs parsing.
func parseEngineMessage(_ msg: String)

/// Called when the engine receives binary data.
///
/// - parameter data: The data the engine received.
func parseEngineBinaryData(_ data: Data)
}
Loading

0 comments on commit 1ff8e11

Please sign in to comment.