Merge branch 'development'

* development:
  don't lose ping precision
  weak in protocols do nothing
  Fix url in faq
  Extract addHeaders to enginespec
  Add faq for namespace usage
  Remove redundant as, change method name
  Make log types static
  Removed Test Coverage from iOS scheme
  Fix queue violation. #792
This commit is contained in:
Erik Little 2017-09-17 10:21:32 -04:00
commit 21ea0aff42
No known key found for this signature in database
GPG Key ID: 4930B7C5FBC1A69D
6 changed files with 93 additions and 86 deletions

View File

@ -40,8 +40,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
@ -70,6 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@ -33,6 +33,8 @@ import Foundation
open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, SocketParsable {
// MARK: Properties
private static let logType = "SocketIOClient"
/// The engine for this client.
public private(set) var engine: SocketEngineSpec?
@ -87,8 +89,6 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
private(set) var currentAck = -1
private(set) var reconnectAttempts = -1
private let logType = "SocketIOClient"
private var anyHandler: ((SocketAnyEvent) -> ())?
private var currentReconnectAttempt = 0
private var handlers = [SocketEventHandler]()
@ -146,16 +146,19 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
}
deinit {
DefaultSocketLogger.Logger.log("Client is being released", type: logType)
DefaultSocketLogger.Logger.log("Client is being released", type: SocketIOClient.logType)
engine?.disconnect(reason: "Client Deinit")
}
// MARK: Methods
private func addEngine() {
DefaultSocketLogger.Logger.log("Adding engine", type: logType, args: "")
DefaultSocketLogger.Logger.log("Adding engine", type: SocketIOClient.logType, args: "")
engine?.engineQueue.sync {
self.engine?.client = nil
}
engine?.client = nil
engine = SocketEngine(client: self, url: socketURL, config: config)
}
@ -173,7 +176,8 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)")
guard status != .connected else {
DefaultSocketLogger.Logger.log("Tried connecting on an already connected socket", type: logType)
DefaultSocketLogger.Logger.log("Tried connecting on an already connected socket",
type: SocketIOClient.logType)
return
}
@ -204,7 +208,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
}
func didConnect(toNamespace namespace: String) {
DefaultSocketLogger.Logger.log("Socket connected", type: logType)
DefaultSocketLogger.Logger.log("Socket connected", type: SocketIOClient.logType)
status = .connected
@ -214,7 +218,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
func didDisconnect(reason: String) {
guard status != .disconnected else { return }
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
DefaultSocketLogger.Logger.log("Disconnected: %@", type: SocketIOClient.logType, args: reason)
reconnecting = false
status = .disconnected
@ -226,7 +230,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
/// Disconnects the socket.
open func disconnect() {
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
DefaultSocketLogger.Logger.log("Closing socket", type: SocketIOClient.logType)
didDisconnect(reason: "Disconnect")
}
@ -243,7 +247,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
try emit(event, with: items.map({ try $0.socketRepresentation() }))
} catch let err {
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
type: logType)
type: SocketIOClient.logType)
handleClientEvent(.error, data: [event, items, err])
}
@ -286,7 +290,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() }))
} catch let err {
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
type: logType)
type: SocketIOClient.logType)
handleClientEvent(.error, data: [event, items, err])
@ -323,7 +327,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false)
let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting: %@", type: logType, args: str)
DefaultSocketLogger.Logger.log("Emitting: %@", type: SocketIOClient.logType, args: str)
engine?.send(str, withData: packet.binary)
}
@ -335,7 +339,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
let packet = SocketPacket.packetFromEmit(items, id: ack, nsp: nsp, ack: true)
let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: logType, args: str)
DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: SocketIOClient.logType, args: str)
engine?.send(str, withData: packet.binary)
}
@ -374,7 +378,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
}
private func _engineDidError(reason: String) {
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
DefaultSocketLogger.Logger.error("%@", type: SocketIOClient.logType, args: reason)
handleClientEvent(.error, data: [reason])
}
@ -383,14 +387,14 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
///
/// - parameter reason: The reason the engine opened.
open func engineDidOpen(reason: String) {
DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient")
DefaultSocketLogger.Logger.log(reason, type: SocketIOClient.logType)
}
// Called when the socket gets an ack for something it sent
func handleAck(_ ack: Int, data: [Any]) {
guard status == .connected else { return }
DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: logType, args: ack, data)
DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: SocketIOClient.logType, args: ack, data)
ackHandlers.executeAck(ack, with: data, onQueue: handleQueue)
}
@ -404,7 +408,8 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
open func handleEvent(_ event: String, data: [Any], isInternalMessage: Bool, withAck ack: Int = -1) {
guard status == .connected || isInternalMessage else { return }
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data)
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: SocketIOClient.logType,
args: event, data)
anyHandler?(SocketAnyEvent(event: event, items: data))
@ -434,7 +439,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
nsp = namespace
if nsp != "/" {
DefaultSocketLogger.Logger.log("Joining namespace", type: logType)
DefaultSocketLogger.Logger.log("Joining namespace", type: SocketIOClient.logType)
engine?.send("0\(nsp)", withData: [])
}
}
@ -454,7 +459,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
///
/// - parameter event: The event to remove handlers for.
open func off(_ event: String) {
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event)
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: SocketIOClient.logType, args: event)
handlers = handlers.filter({ $0.event != event })
}
@ -465,7 +470,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
///
/// - parameter id: The UUID of the handler you wish to remove.
open func off(id: UUID) {
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: SocketIOClient.logType, args: id)
handlers = handlers.filter({ $0.id != id })
}
@ -477,7 +482,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
/// - returns: A unique id for the handler that can be used to remove it.
@discardableResult
open func on(_ event: String, callback: @escaping NormalCallback) -> UUID {
DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event)
DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: SocketIOClient.logType, args: event)
let handler = SocketEventHandler(event: event, id: UUID(), callback: callback)
handlers.append(handler)
@ -500,7 +505,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
/// - returns: A unique id for the handler that can be used to remove it.
@discardableResult
open func on(clientEvent event: SocketClientEvent, callback: @escaping NormalCallback) -> UUID {
DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event)
DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: SocketIOClient.logType, args: event)
let handler = SocketEventHandler(event: event.rawValue, id: UUID(), callback: callback)
handlers.append(handler)
@ -525,7 +530,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
/// - returns: A unique id for the handler that can be used to remove it.
@discardableResult
open func once(_ event: String, callback: @escaping NormalCallback) -> UUID {
DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event)
DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: SocketIOClient.logType, args: event)
let id = UUID()
@ -551,7 +556,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
///
/// - parameter msg: The message that needs parsing.
public func parseEngineMessage(_ msg: String) {
DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg)
DefaultSocketLogger.Logger.log("Should parse message: %@", type: SocketIOClient.logType, args: msg)
handleQueue.async { self.parseSocketMessage(msg) }
}
@ -581,7 +586,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
private func tryReconnect(reason: String) {
guard reconnecting else { return }
DefaultSocketLogger.Logger.log("Starting reconnect", type: logType)
DefaultSocketLogger.Logger.log("Starting reconnect", type: SocketIOClient.logType)
handleClientEvent(.reconnect, data: [reason])
_tryReconnect()
@ -594,7 +599,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
return didDisconnect(reason: "Reconnect Failed")
}
DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType)
DefaultSocketLogger.Logger.log("Trying to reconnect", type: SocketIOClient.logType)
handleClientEvent(.reconnectAttempt, data: [(reconnectAttempts - currentReconnectAttempt)])
currentReconnectAttempt += 1

View File

@ -31,6 +31,8 @@ import StarscreamSocketIO
public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePollable, SocketEngineWebsocket {
// MARK: Properties
private static let logType = "SocketEngine"
/// The queue that all engine actions take place on.
public let engineQueue = DispatchQueue(label: "com.socketio.engineHandleQueue")
@ -119,13 +121,12 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
private weak var sessionDelegate: URLSessionDelegate?
private let logType = "SocketEngine"
private let url: URL
private var pingInterval: Double?
private var pingTimeout = 0.0 {
private var pingInterval: Int?
private var pingTimeout = 0 {
didSet {
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25000))
}
}
@ -196,7 +197,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
deinit {
DefaultSocketLogger.Logger.log("Engine is being released", type: logType)
DefaultSocketLogger.Logger.log("Engine is being released", type: SocketEngine.logType)
closed = true
stopPolling()
}
@ -249,35 +250,26 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
private func _connect() {
if connected {
DefaultSocketLogger.Logger.error("Engine tried opening while connected. Assuming this was a reconnect", type: logType)
DefaultSocketLogger.Logger.error("Engine tried opening while connected. Assuming this was a reconnect",
type: SocketEngine.logType)
disconnect(reason: "reconnect")
}
DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: logType, args: url)
DefaultSocketLogger.Logger.log("Handshaking", type: logType)
DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: SocketEngine.logType, args: url)
DefaultSocketLogger.Logger.log("Handshaking", type: SocketEngine.logType)
resetEngine()
if forceWebsockets {
polling = false
websocket = true
createWebsocketAndConnect()
createWebSocketAndConnect()
return
}
var reqPolling = URLRequest(url: urlPolling, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
if cookies != nil {
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
reqPolling.allHTTPHeaderFields = headers
}
if let extraHeaders = extraHeaders {
for (headerName, value) in extraHeaders {
reqPolling.setValue(value, forHTTPHeaderField: headerName)
}
}
addHeaders(to: &reqPolling)
doLongPoll(for: reqPolling)
}
@ -301,8 +293,8 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
urlWebSocket.scheme = "ws"
}
if connectParams != nil {
for (key, value) in connectParams! {
if let connectParams = self.connectParams {
for (key, value) in connectParams {
let keyEsc = key.urlEncode()!
let valueEsc = "\(value)".urlEncode()!
@ -316,9 +308,9 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
return (urlPolling.url!, urlWebSocket.url!)
}
private func createWebsocketAndConnect() {
ws?.delegate = nil
ws = WebSocket(url: urlWebSocketWithSid as URL)
private func createWebSocketAndConnect() {
ws?.delegate = nil // TODO this seems a bit defensive, is this really needed?
ws = WebSocket(url: urlWebSocketWithSid)
if cookies != nil {
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
@ -344,7 +336,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// Called when an error happens during execution. Causes a disconnection.
public func didError(reason: String) {
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
DefaultSocketLogger.Logger.error("%@", type: SocketEngine.logType, args: reason)
client?.engineDidError(reason: reason)
disconnect(reason: reason)
}
@ -361,7 +353,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
private func _disconnect(reason: String) {
guard connected else { return closeOutEngine(reason: reason) }
DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType)
DefaultSocketLogger.Logger.log("Engine is being closed.", type: SocketEngine.logType)
if closed {
return closeOutEngine(reason: reason)
@ -391,7 +383,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
public func doFastUpgrade() {
if waitingForPoll {
DefaultSocketLogger.Logger.error("Outstanding poll when switched to WebSockets," +
"we'll probably disconnect soon. You should report this.", type: logType)
"we'll probably disconnect soon. You should report this.", type: SocketEngine.logType)
}
sendWebSocketMessage("", withType: .upgrade, withData: [])
@ -403,7 +395,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
private func flushProbeWait() {
DefaultSocketLogger.Logger.log("Flushing probe wait", type: logType)
DefaultSocketLogger.Logger.log("Flushing probe wait", type: SocketEngine.logType)
for waiter in probeWait {
write(waiter.msg, withType: waiter.type, withData: waiter.data)
@ -467,13 +459,13 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
upgradeWs = false
}
if let pingInterval = json["pingInterval"] as? Double, let pingTimeout = json["pingTimeout"] as? Double {
self.pingInterval = pingInterval / 1000.0
self.pingTimeout = pingTimeout / 1000.0
if let pingInterval = json["pingInterval"] as? Int, let pingTimeout = json["pingTimeout"] as? Int {
self.pingInterval = pingInterval
self.pingTimeout = pingTimeout
}
if !forcePolling && !forceWebsockets && upgradeWs {
createWebsocketAndConnect()
createWebSocketAndConnect()
}
sendPing()
@ -498,7 +490,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
///
/// - parameter data: The data to parse.
public func parseEngineData(_ data: Data) {
DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data)
DefaultSocketLogger.Logger.log("Got binary data: %@", type: SocketEngine.logType, args: data)
client?.parseEngineBinaryData(data.subdata(in: 1..<data.endIndex))
}
@ -509,7 +501,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
/// - parameter fromPolling: Whether this message is from long-polling.
/// If `true` we might have to fix utf8 encoding.
public func parseEngineMessage(_ message: String) {
DefaultSocketLogger.Logger.log("Got message: %@", type: logType, args: message)
DefaultSocketLogger.Logger.log("Got message: %@", type: SocketEngine.logType, args: message)
let reader = SocketStringReader(message: message)
@ -535,7 +527,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
case .close:
handleClose(message)
default:
DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType)
DefaultSocketLogger.Logger.log("Got unknown packet type", type: SocketEngine.logType)
}
}
@ -558,7 +550,7 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
}
private func sendPing() {
guard connected else { return }
guard connected, let pingInterval = pingInterval else { return }
// Server is not responding
if pongsMissed > pongsMissedMax {
@ -567,18 +559,18 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
return
}
guard let pingInterval = pingInterval else { return }
pongsMissed += 1
write("", withType: .ping, withData: [])
engineQueue.asyncAfter(deadline: DispatchTime.now() + Double(pingInterval)) {[weak self] in self?.sendPing() }
engineQueue.asyncAfter(deadline: DispatchTime.now() + .milliseconds(pingInterval)) {[weak self] in
self?.sendPing()
}
}
// Moves from long-polling to websockets
private func upgradeTransport() {
if ws?.isConnected ?? false {
DefaultSocketLogger.Logger.log("Upgrading transport to WebSockets", type: logType)
DefaultSocketLogger.Logger.log("Upgrading transport to WebSockets", type: SocketEngine.logType)
fastUpgrade = true
sendPollMessage("", withType: .noop, withData: [])
@ -597,11 +589,11 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
if self.websocket {
DefaultSocketLogger.Logger.log("Writing ws: %@ has data: %@",
type: self.logType, args: msg, data.count != 0)
type: SocketEngine.logType, args: msg, data.count != 0)
self.sendWebSocketMessage(msg, withType: type, withData: data)
} else if !self.probing {
DefaultSocketLogger.Logger.log("Writing poll: %@ has data: %@",
type: self.logType, args: msg, data.count != 0)
type: SocketEngine.logType, args: msg, data.count != 0)
self.sendPollMessage(msg, withType: type, withData: data)
} else {
self.probeWait.append((msg, type, data))

View File

@ -71,19 +71,6 @@ public protocol SocketEnginePollable : SocketEngineSpec {
// Default polling methods
extension SocketEnginePollable {
private func addHeaders(to req: inout URLRequest) {
if cookies != nil {
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
req.allHTTPHeaderFields = headers
}
if extraHeaders != nil {
for (headerName, value) in extraHeaders! {
req.setValue(value, forHTTPHeaderField: headerName)
}
}
}
func createRequestForPostWithPostWait() -> URLRequest {
defer { postWait.removeAll(keepingCapacity: true) }

View File

@ -29,7 +29,7 @@ import StarscreamSocketIO
/// Specifies a SocketEngine.
@objc public protocol SocketEngineSpec {
/// The client for this engine.
weak var client: SocketEngineClient? { get set }
var client: SocketEngineClient? { get set }
/// `true` if this engine is closed.
var closed: Bool { get }
@ -147,6 +147,18 @@ extension SocketEngineSpec {
return com.url!
}
func addHeaders(to req: inout URLRequest) {
if let cookies = cookies {
req.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: cookies)
}
if let extraHeaders = extraHeaders {
for (headerName, value) in extraHeaders {
req.setValue(value, forHTTPHeaderField: headerName)
}
}
}
func createBinaryDataForSend(using data: Data) -> Either<Data, String> {
if websocket {
var byteArray = [UInt8](repeating: 0x4, count: 1)

View File

@ -42,3 +42,13 @@ class SocketManager {
}
```
------
Another case where this might happen is if you use namespaces in your socket.io application.
In the JavaScript client a url that looks like `http://somesocketioserver.com/client` would be done with the `nsp` config.
```swift
let socket = SocketIOClient(socketURL: URL(string: "http://somesocketioserver.com")!, config: [.nsp("/client")])
```