update for latest swift
This commit is contained in:
commit
f90ad8caeb
@ -62,7 +62,7 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBinaryEmit() {
|
func testBinaryEmit() {
|
||||||
let expectedSendString = "51-[\"test\",{\"num\":0,\"_placeholder\":true}]"
|
let expectedSendString = "51-[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||||
let sendData = ["test", data]
|
let sendData = ["test", data]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false)
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testMultipleBinaryEmit() {
|
func testMultipleBinaryEmit() {
|
||||||
let expectedSendString = "52-[\"test\",{\"data1\":{\"num\":0,\"_placeholder\":true},\"data2\":{\"num\":1,\"_placeholder\":true}}]"
|
let expectedSendString = "52-[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]"
|
||||||
let sendData = ["test", ["data1": data, "data2": data2]]
|
let sendData = ["test", ["data1": data, "data2": data2]]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false)
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testEmitDataWithAck() {
|
func testEmitDataWithAck() {
|
||||||
let expectedSendString = "51-0[\"test\",{\"num\":0,\"_placeholder\":true}]"
|
let expectedSendString = "51-0[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||||
let sendData = ["test", data]
|
let sendData = ["test", data]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: false)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: false)
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBinaryAck() {
|
func testBinaryAck() {
|
||||||
let expectedSendString = "61-0[{\"num\":0,\"_placeholder\":true}]"
|
let expectedSendString = "61-0[{\"_placeholder\":true,\"num\":0}]"
|
||||||
let sendData = [data]
|
let sendData = [data]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true)
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testMultipleBinaryAck() {
|
func testMultipleBinaryAck() {
|
||||||
let expectedSendString = "62-0[{\"data2\":{\"num\":0,\"_placeholder\":true},\"data1\":{\"num\":1,\"_placeholder\":true}}]"
|
let expectedSendString = "62-0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]"
|
||||||
let sendData = [["data1": data, "data2": data2]]
|
let sendData = [["data1": data, "data2": data2]]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true)
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBinaryStringPlaceholderInMessage() {
|
func testBinaryStringPlaceholderInMessage() {
|
||||||
let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"num\":1,\"_placeholder\":true}]"
|
let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"_placeholder\":true,\"num\":1}]"
|
||||||
let socket = SocketIOClient(socketURL: NSURL())
|
let socket = SocketIOClient(socketURL: NSURL())
|
||||||
socket.setTestable()
|
socket.setTestable()
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBinaryEmit() {
|
func testBinaryEmit() {
|
||||||
let expectedSendString = "51-/swift,[\"test\",{\"num\":0,\"_placeholder\":true}]"
|
let expectedSendString = "51-/swift,[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||||
let sendData = ["test", data]
|
let sendData = ["test", data]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false)
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testMultipleBinaryEmit() {
|
func testMultipleBinaryEmit() {
|
||||||
let expectedSendString = "52-/swift,[\"test\",{\"data1\":{\"num\":0,\"_placeholder\":true},\"data2\":{\"num\":1,\"_placeholder\":true}}]"
|
let expectedSendString = "52-/swift,[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]"
|
||||||
let sendData = ["test", ["data1": data, "data2": data2]]
|
let sendData = ["test", ["data1": data, "data2": data2]]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false)
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testEmitDataWithAck() {
|
func testEmitDataWithAck() {
|
||||||
let expectedSendString = "51-/swift,0[\"test\",{\"num\":0,\"_placeholder\":true}]"
|
let expectedSendString = "51-/swift,0[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||||
let sendData = ["test", data]
|
let sendData = ["test", data]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: false)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: false)
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBinaryAck() {
|
func testBinaryAck() {
|
||||||
let expectedSendString = "61-/swift,0[{\"num\":0,\"_placeholder\":true}]"
|
let expectedSendString = "61-/swift,0[{\"_placeholder\":true,\"num\":0}]"
|
||||||
let sendData = [data]
|
let sendData = [data]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true)
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testMultipleBinaryAck() {
|
func testMultipleBinaryAck() {
|
||||||
let expectedSendString = "62-/swift,0[{\"data2\":{\"num\":0,\"_placeholder\":true},\"data1\":{\"num\":1,\"_placeholder\":true}}]"
|
let expectedSendString = "62-/swift,0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]"
|
||||||
let sendData = [["data1": data, "data2": data2]]
|
let sendData = [["data1": data, "data2": data2]]
|
||||||
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true)
|
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true)
|
||||||
|
|
||||||
|
|||||||
@ -120,7 +120,7 @@ class SocketParserTest: XCTestCase {
|
|||||||
func validateParseResult(message: String) {
|
func validateParseResult(message: String) {
|
||||||
let validValues = SocketParserTest.packetTypes[message]!
|
let validValues = SocketParserTest.packetTypes[message]!
|
||||||
let packet = testSocket.parseString(message)
|
let packet = testSocket.parseString(message)
|
||||||
let type = message.substring(with: Range<String.Index>(message.startIndex..<message.startIndex.advanced(by: 1)))
|
let type = message.substring(with: Range<String.Index>(message.startIndex..<message.characters.index(message.startIndex, offsetBy: 1)))
|
||||||
if case let .Right(packet) = packet {
|
if case let .Right(packet) = packet {
|
||||||
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
|
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
|
||||||
XCTAssertEqual(packet.nsp, validValues.0)
|
XCTAssertEqual(packet.nsp, validValues.0)
|
||||||
|
|||||||
@ -26,12 +26,12 @@ import Foundation
|
|||||||
|
|
||||||
public final class SocketAnyEvent : NSObject {
|
public final class SocketAnyEvent : NSObject {
|
||||||
public let event: String
|
public let event: String
|
||||||
public let items: NSArray?
|
public let items: [AnyObject]?
|
||||||
override public var description: String {
|
override public var description: String {
|
||||||
return "SocketAnyEvent: Event: \(event) items: \(items ?? nil)"
|
return "SocketAnyEvent: Event: \(event) items: \(items ?? nil)"
|
||||||
}
|
}
|
||||||
|
|
||||||
init(event: String, items: NSArray?) {
|
init(event: String, items: [AnyObject]?) {
|
||||||
self.event = event
|
self.event = event
|
||||||
self.items = items
|
self.items = items
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,9 +25,9 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWebsocket {
|
public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWebsocket {
|
||||||
public let emitQueue = dispatch_queue_create("com.socketio.engineEmitQueue", DISPATCH_QUEUE_SERIAL)
|
public let emitQueue = dispatch_queue_create("com.socketio.engineEmitQueue", DISPATCH_QUEUE_SERIAL)!
|
||||||
public let handleQueue = dispatch_queue_create("com.socketio.engineHandleQueue", DISPATCH_QUEUE_SERIAL)
|
public let handleQueue = dispatch_queue_create("com.socketio.engineHandleQueue", DISPATCH_QUEUE_SERIAL)!
|
||||||
public let parseQueue = dispatch_queue_create("com.socketio.engineParseQueue", DISPATCH_QUEUE_SERIAL)
|
public let parseQueue = dispatch_queue_create("com.socketio.engineParseQueue", DISPATCH_QUEUE_SERIAL)!
|
||||||
|
|
||||||
public var connectParams: [String: AnyObject]? {
|
public var connectParams: [String: AnyObject]? {
|
||||||
didSet {
|
didSet {
|
||||||
@ -62,9 +62,6 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
|
|
||||||
private weak var sessionDelegate: NSURLSessionDelegate?
|
private weak var sessionDelegate: NSURLSessionDelegate?
|
||||||
|
|
||||||
private typealias Probe = (msg: String, type: SocketEnginePacketType, data: [NSData])
|
|
||||||
private typealias ProbeWaitQueue = [Probe]
|
|
||||||
|
|
||||||
private let logType = "SocketEngine"
|
private let logType = "SocketEngine"
|
||||||
private let url: NSURL
|
private let url: NSURL
|
||||||
|
|
||||||
@ -74,6 +71,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
|
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var pongsMissed = 0
|
private var pongsMissed = 0
|
||||||
private var pongsMissedMax = 0
|
private var pongsMissedMax = 0
|
||||||
private var probeWait = ProbeWaitQueue()
|
private var probeWait = ProbeWaitQueue()
|
||||||
@ -153,7 +151,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
private func checkIfMessageIsBase64Binary(_ message: String) -> Bool {
|
private func checkIfMessageIsBase64Binary(_ message: String) -> Bool {
|
||||||
if message.hasPrefix("b4") {
|
if message.hasPrefix("b4") {
|
||||||
// binary in base64 string
|
// binary in base64 string
|
||||||
let noPrefix = message[message.startIndex.advanced(by: 2)..<message.endIndex]
|
let noPrefix = message[message.characters.index(message.startIndex, offsetBy: 2)..<message.endIndex]
|
||||||
|
|
||||||
if let data = NSData(base64Encoded: noPrefix,
|
if let data = NSData(base64Encoded: noPrefix,
|
||||||
options: .ignoreUnknownCharacters) {
|
options: .ignoreUnknownCharacters) {
|
||||||
@ -387,7 +385,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
doPoll()
|
doPoll()
|
||||||
}
|
}
|
||||||
|
|
||||||
client?.engineDidOpen?(reason: "Connect")
|
client?.engineDidOpen(reason: "Connect")
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
didError(error: "Error parsing open packet")
|
didError(error: "Error parsing open packet")
|
||||||
@ -430,13 +428,15 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
case .message:
|
case .message:
|
||||||
handleMessage(fixedString[fixedString.startIndex.successor()..<fixedString.endIndex])
|
handleMessage(
|
||||||
|
fixedString[fixedString.characters.index(after: fixedString.characters.startIndex)..<fixedString.endIndex])
|
||||||
case .noop:
|
case .noop:
|
||||||
handleNOOP()
|
handleNOOP()
|
||||||
case .pong:
|
case .pong:
|
||||||
handlePong(pongMessage: fixedString)
|
handlePong(pongMessage: fixedString)
|
||||||
case .open:
|
case .open:
|
||||||
handleOpen(openMessage: fixedString[fixedString.startIndex.successor()..<fixedString.endIndex])
|
handleOpen(openMessage:
|
||||||
|
fixedString[fixedString.characters.index(after: fixedString.characters.startIndex)..<fixedString.endIndex])
|
||||||
case .close:
|
case .close:
|
||||||
handleClose(reason: fixedString)
|
handleClose(reason: fixedString)
|
||||||
default:
|
default:
|
||||||
@ -452,7 +452,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
polling = true
|
polling = true
|
||||||
probing = false
|
probing = false
|
||||||
invalidated = false
|
invalidated = false
|
||||||
session = NSURLSession(configuration: .defaultSessionConfiguration(),
|
session = NSURLSession(configuration: .default(),
|
||||||
delegate: sessionDelegate,
|
delegate: sessionDelegate,
|
||||||
delegateQueue: NSOperationQueue())
|
delegateQueue: NSOperationQueue())
|
||||||
sid = ""
|
sid = ""
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import Foundation
|
|||||||
@objc public protocol SocketEngineClient {
|
@objc public protocol SocketEngineClient {
|
||||||
func engineDidError(reason: String)
|
func engineDidError(reason: String)
|
||||||
func engineDidClose(reason: String)
|
func engineDidClose(reason: String)
|
||||||
optional func engineDidOpen(reason: String)
|
func engineDidOpen(reason: String)
|
||||||
func parseEngineMessage(_ msg: String)
|
func parseEngineMessage(_ msg: String)
|
||||||
func parseEngineBinaryData(_ data: NSData)
|
func parseEngineBinaryData(_ data: NSData)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,9 +49,9 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
return nsp + "#" + (engine?.sid ?? "")
|
return nsp + "#" + (engine?.sid ?? "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private let emitQueue = dispatch_queue_create("com.socketio.emitQueue", DISPATCH_QUEUE_SERIAL)
|
private let emitQueue = dispatch_queue_create("com.socketio.emitQueue", DISPATCH_QUEUE_SERIAL)!
|
||||||
private let logType = "SocketIOClient"
|
private let logType = "SocketIOClient"
|
||||||
private let parseQueue = dispatch_queue_create("com.socketio.parseQueue", DISPATCH_QUEUE_SERIAL)
|
private let parseQueue = dispatch_queue_create("com.socketio.parseQueue", DISPATCH_QUEUE_SERIAL)!
|
||||||
|
|
||||||
private var anyHandler: ((SocketAnyEvent) -> Void)?
|
private var anyHandler: ((SocketAnyEvent) -> Void)?
|
||||||
private var currentReconnectAttempt = 0
|
private var currentReconnectAttempt = 0
|
||||||
@ -60,7 +60,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
private var reconnecting = false
|
private var reconnecting = false
|
||||||
|
|
||||||
private(set) var currentAck = -1
|
private(set) var currentAck = -1
|
||||||
private(set) var handleQueue = dispatch_get_main_queue()
|
private(set) var handleQueue = dispatch_get_main_queue()!
|
||||||
private(set) var reconnectAttempts = -1
|
private(set) var reconnectAttempts = -1
|
||||||
|
|
||||||
var waitingPackets = [SocketPacket]()
|
var waitingPackets = [SocketPacket]()
|
||||||
@ -114,7 +114,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func addEngine() -> SocketEngineSpec {
|
private func addEngine() -> SocketEngineSpec {
|
||||||
DefaultSocketLogger.Logger.log("Adding engine", type: logType)
|
DefaultSocketLogger.Logger.log("Adding engine", type: logType, args: "")
|
||||||
|
|
||||||
engine = SocketEngine(client: self, url: socketURL, options: options)
|
engine = SocketEngine(client: self, url: socketURL, options: options)
|
||||||
|
|
||||||
@ -191,11 +191,10 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
|
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
|
||||||
|
|
||||||
status = .disconnected
|
status = .disconnected
|
||||||
reconnects = false
|
|
||||||
|
|
||||||
// Make sure the engine is actually dead.
|
// Make sure the engine is actually dead.
|
||||||
engine?.disconnect(reason: reason)
|
engine?.disconnect(reason: reason)
|
||||||
handleEvent("disconnect", data: [reason], isInternalMessage: true)
|
handleEvent("disconnect", data: [reason as AnyObject], isInternalMessage: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnects the socket. Only reconnect the same socket if you know what you're doing.
|
/// Disconnects the socket. Only reconnect the same socket if you know what you're doing.
|
||||||
@ -205,7 +204,6 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
|
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
|
||||||
|
|
||||||
reconnects = false
|
|
||||||
didDisconnect(reason: "Disconnect")
|
didDisconnect(reason: "Disconnect")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,11 +215,11 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
/// Same as emit, but meant for Objective-C
|
/// Same as emit, but meant for Objective-C
|
||||||
public func emit(_ event: String, with items: [AnyObject]) {
|
public func emit(_ event: String, with items: [AnyObject]) {
|
||||||
guard status == .connected else {
|
guard status == .connected else {
|
||||||
handleEvent("error", data: ["Tried emitting \(event) when not connected"], isInternalMessage: true)
|
handleEvent("error", data: ["Tried emitting \(event) when not connected" as AnyObject], isInternalMessage: true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_emit(data: [event] + items)
|
_emit(data: [event as AnyObject] + items)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add
|
/// Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add
|
||||||
@ -232,7 +230,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
|
|
||||||
/// Same as emitWithAck, but for Objective-C
|
/// Same as emitWithAck, but for Objective-C
|
||||||
public func emitWithAck(_ event: String, with items: [AnyObject]) -> OnAckCallback {
|
public func emitWithAck(_ event: String, with items: [AnyObject]) -> OnAckCallback {
|
||||||
return createOnAck(items: [event] + items)
|
return createOnAck(items: [event as AnyObject] + items)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func _emit(data: [AnyObject], ack: Int? = nil) {
|
private func _emit(data: [AnyObject], ack: Int? = nil) {
|
||||||
@ -284,23 +282,25 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
public func engineDidError(reason: String) {
|
public func engineDidError(reason: String) {
|
||||||
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
|
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
|
||||||
|
|
||||||
handleEvent("error", data: [reason], isInternalMessage: true)
|
handleEvent("error", data: [reason as AnyObject], isInternalMessage: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func engineDidOpen(reason: String) {
|
||||||
|
DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the socket gets an ack for something it sent
|
// Called when the socket gets an ack for something it sent
|
||||||
func handleAck(_ ack: Int, data: [AnyObject]) {
|
func handleAck(_ ack: Int, data: [AnyObject]) {
|
||||||
guard status == .connected else { return }
|
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: logType, args: ack, data)
|
||||||
|
|
||||||
ackHandlers.executeAck(ack, items: data)
|
ackHandlers.executeAck(ack, items: data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Causes an event to be handled. Only use if you know what you're doing.
|
/// Causes an event to be handled. Only use if you know what you're doing.
|
||||||
public func handleEvent(_ event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int = -1) {
|
public func handleEvent(_ event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int = -1) {
|
||||||
guard status == .connected || isInternalMessage else {
|
guard status == .connected || isInternalMessage else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "")
|
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "")
|
||||||
|
|
||||||
@ -335,14 +335,14 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
public func off(event: String) {
|
public func off(event: String) {
|
||||||
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event)
|
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event)
|
||||||
|
|
||||||
handlers = handlers.filter { $0.event != event }
|
handlers = handlers.filter({ $0.event != event })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a handler with the specified UUID gotten from an `on` or `once`
|
/// Removes a handler with the specified UUID gotten from an `on` or `once`
|
||||||
public func off(id: NSUUID) {
|
public func off(id: NSUUID) {
|
||||||
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
|
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
|
||||||
|
|
||||||
handlers = handlers.filter { $0.id != id }
|
handlers = handlers.filter({ $0.id != id })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a handler for an event.
|
/// Adds a handler for an event.
|
||||||
@ -409,7 +409,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
private func tryReconnect(reason: String) {
|
private func tryReconnect(reason: String) {
|
||||||
if reconnecting {
|
if reconnecting {
|
||||||
DefaultSocketLogger.Logger.log("Starting reconnect", type: logType)
|
DefaultSocketLogger.Logger.log("Starting reconnect", type: logType)
|
||||||
handleEvent("reconnect", data: [reason], isInternalMessage: true)
|
handleEvent("reconnect", data: [reason as AnyObject], isInternalMessage: true)
|
||||||
|
|
||||||
_tryReconnect()
|
_tryReconnect()
|
||||||
}
|
}
|
||||||
@ -425,7 +425,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
}
|
}
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType)
|
DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType)
|
||||||
handleEvent("reconnectAttempt", data: [reconnectAttempts - currentReconnectAttempt],
|
handleEvent("reconnectAttempt", data: [(reconnectAttempts - currentReconnectAttempt) as AnyObject],
|
||||||
isInternalMessage: true)
|
isInternalMessage: true)
|
||||||
|
|
||||||
currentReconnectAttempt += 1
|
currentReconnectAttempt += 1
|
||||||
@ -452,6 +452,6 @@ extension SocketIOClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func emitTest(event: String, _ data: AnyObject...) {
|
func emitTest(event: String, _ data: AnyObject...) {
|
||||||
self._emit(data: [event] + data)
|
self._emit(data: [event as AnyObject] + data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,43 +105,43 @@ public enum SocketIOClientOption : ClientOption {
|
|||||||
|
|
||||||
switch self {
|
switch self {
|
||||||
case let .connectParams(params):
|
case let .connectParams(params):
|
||||||
value = params
|
value = params as AnyObject
|
||||||
case let .cookies(cookies):
|
case let .cookies(cookies):
|
||||||
value = cookies
|
value = cookies as AnyObject
|
||||||
case let .doubleEncodeUTF8(encode):
|
case let .doubleEncodeUTF8(encode):
|
||||||
value = encode
|
value = encode as AnyObject
|
||||||
case let .extraHeaders(headers):
|
case let .extraHeaders(headers):
|
||||||
value = headers
|
value = headers as AnyObject
|
||||||
case let .forceNew(force):
|
case let .forceNew(force):
|
||||||
value = force
|
value = force as AnyObject
|
||||||
case let .forcePolling(force):
|
case let .forcePolling(force):
|
||||||
value = force
|
value = force as AnyObject
|
||||||
case let .forceWebsockets(force):
|
case let .forceWebsockets(force):
|
||||||
value = force
|
value = force as AnyObject
|
||||||
case let .handleQueue(queue):
|
case let .handleQueue(queue):
|
||||||
value = queue
|
value = queue as AnyObject
|
||||||
case let .log(log):
|
case let .log(log):
|
||||||
value = log
|
value = log as AnyObject
|
||||||
case let .logger(logger):
|
case let .logger(logger):
|
||||||
value = logger
|
value = logger as AnyObject
|
||||||
case let .nsp(nsp):
|
case let .nsp(nsp):
|
||||||
value = nsp
|
value = nsp as AnyObject
|
||||||
case let .path(path):
|
case let .path(path):
|
||||||
value = path
|
value = path as AnyObject
|
||||||
case let .reconnects(reconnects):
|
case let .reconnects(reconnects):
|
||||||
value = reconnects
|
value = reconnects as AnyObject
|
||||||
case let .reconnectAttempts(attempts):
|
case let .reconnectAttempts(attempts):
|
||||||
value = attempts
|
value = attempts as AnyObject
|
||||||
case let .reconnectWait(wait):
|
case let .reconnectWait(wait):
|
||||||
value = wait
|
value = wait as AnyObject
|
||||||
case let .secure(secure):
|
case let .secure(secure):
|
||||||
value = secure
|
value = secure as AnyObject
|
||||||
case let .selfSigned(signed):
|
case let .selfSigned(signed):
|
||||||
value = signed
|
value = signed as AnyObject
|
||||||
case let .sessionDelegate(delegate):
|
case let .sessionDelegate(delegate):
|
||||||
value = delegate
|
value = delegate as AnyObject
|
||||||
case let .voipEnabled(enabled):
|
case let .voipEnabled(enabled):
|
||||||
value = enabled
|
value = enabled as AnyObject
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|||||||
@ -38,6 +38,6 @@ extension SocketIOClientSpec {
|
|||||||
func didError(reason: String) {
|
func didError(reason: String) {
|
||||||
DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason)
|
DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason)
|
||||||
|
|
||||||
handleEvent("error", data: [reason], isInternalMessage: true, withAck: -1)
|
handleEvent("error", data: [reason as AnyObject], isInternalMessage: true, withAck: -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,28 +29,25 @@ public protocol SocketLogger : class {
|
|||||||
var log: Bool { get set }
|
var log: Bool { get set }
|
||||||
|
|
||||||
/// Normal log messages
|
/// Normal log messages
|
||||||
func log(_ message: String, type: String, args: AnyObject...)
|
func log(_ message: String, type: String, args: Any...)
|
||||||
|
|
||||||
/// Error Messages
|
/// Error Messages
|
||||||
func error(_ message: String, type: String, args: AnyObject...)
|
func error(_ message: String, type: String, args: Any...)
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension SocketLogger {
|
public extension SocketLogger {
|
||||||
func log(_ message: String, type: String, args: AnyObject...) {
|
func log(_ message: String, type: String, args: Any...) {
|
||||||
abstractLog("LOG", message: message, type: type, args: args)
|
abstractLog("LOG", message: message, type: type, args: args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func error(_ message: String, type: String, args: AnyObject...) {
|
func error(_ message: String, type: String, args: Any...) {
|
||||||
abstractLog("ERROR", message: message, type: type, args: args)
|
abstractLog("ERROR", message: message, type: type, args: args)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func abstractLog(_ logType: String, message: String, type: String, args: [AnyObject]) {
|
private func abstractLog(_ logType: String, message: String, type: String, args: [Any]) {
|
||||||
guard log else { return }
|
guard log else { return }
|
||||||
|
|
||||||
let newArgs = args.map({arg -> CVarArg in String(arg)})
|
NSLog("\(logType) \(type): \(args)")
|
||||||
let replaced = String(format: message, arguments: newArgs)
|
|
||||||
|
|
||||||
NSLog("%@ %@: %@", logType, type, replaced)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ struct SocketPacket {
|
|||||||
return createPacketString()
|
return createPacketString()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(type: SocketPacket.PacketType, data: [AnyObject] = [AnyObject](), id: Int = -1,
|
init(type: PacketType, data: [AnyObject] = [AnyObject](), id: Int = -1,
|
||||||
nsp: String, placeholders: Int = 0, binary: [NSData] = [NSData]()) {
|
nsp: String, placeholders: Int = 0, binary: [NSData] = [NSData]()) {
|
||||||
self.data = data
|
self.data = data
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -94,10 +94,10 @@ struct SocketPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let jsonSend = try NSJSONSerialization.data(withJSONObject: data,
|
let jsonSend = try NSJSONSerialization.data(withJSONObject: data as AnyObject,
|
||||||
options: NSJSONWritingOptions(rawValue: 0))
|
options: NSJSONWritingOptions(rawValue: 0))
|
||||||
guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else {
|
guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else {
|
||||||
return "[]"
|
return message + "[]"
|
||||||
}
|
}
|
||||||
|
|
||||||
restOfMessage = jsonString
|
restOfMessage = jsonString
|
||||||
@ -189,7 +189,7 @@ struct SocketPacket {
|
|||||||
|
|
||||||
// Helper method that looks for placeholders
|
// Helper method that looks for placeholders
|
||||||
// If object is a collection it will recurse
|
// If object is a collection it will recurse
|
||||||
// Returns the object if it is not a placeholder string or the corresponding
|
// Returns the object if it is not a placeholder or the corresponding
|
||||||
// binary data
|
// binary data
|
||||||
private func _fillInPlaceholders(_ object: AnyObject) -> AnyObject {
|
private func _fillInPlaceholders(_ object: AnyObject) -> AnyObject {
|
||||||
switch object {
|
switch object {
|
||||||
@ -203,7 +203,7 @@ struct SocketPacket {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
case let arr as [AnyObject]:
|
case let arr as [AnyObject]:
|
||||||
return arr.map(_fillInPlaceholders)
|
return arr.map(_fillInPlaceholders) as AnyObject
|
||||||
default:
|
default:
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ struct SocketPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension SocketPacket {
|
extension SocketPacket {
|
||||||
private static func findType(binCount: Int, ack: Bool) -> PacketType {
|
private static func findType(_ binCount: Int, ack: Bool) -> PacketType {
|
||||||
switch binCount {
|
switch binCount {
|
||||||
case 0 where !ack:
|
case 0 where !ack:
|
||||||
return .Event
|
return .Event
|
||||||
@ -228,8 +228,8 @@ extension SocketPacket {
|
|||||||
|
|
||||||
static func packetFromEmit(items: [AnyObject], id: Int, nsp: String, ack: Bool) -> SocketPacket {
|
static func packetFromEmit(items: [AnyObject], id: Int, nsp: String, ack: Bool) -> SocketPacket {
|
||||||
let (parsedData, binary) = deconstructData(items)
|
let (parsedData, binary) = deconstructData(items)
|
||||||
let packet = SocketPacket(type: findType(binCount: binary.count, ack: ack), data: parsedData,
|
let packet = SocketPacket(type: findType(binary.count, ack: ack), data: parsedData,
|
||||||
id: id, nsp: nsp, placeholders: -1, binary: binary)
|
id: id, nsp: nsp, binary: binary)
|
||||||
|
|
||||||
return packet
|
return packet
|
||||||
}
|
}
|
||||||
@ -238,14 +238,14 @@ extension SocketPacket {
|
|||||||
private extension SocketPacket {
|
private extension SocketPacket {
|
||||||
// Recursive function that looks for NSData in collections
|
// Recursive function that looks for NSData in collections
|
||||||
static func shred(_ data: AnyObject, binary: inout [NSData]) -> AnyObject {
|
static func shred(_ data: AnyObject, binary: inout [NSData]) -> AnyObject {
|
||||||
let placeholder = ["_placeholder": true, "num": binary.count]
|
let placeholder = ["_placeholder": true, "num": binary.count as AnyObject]
|
||||||
|
|
||||||
switch data {
|
switch data {
|
||||||
case let bin as NSData:
|
case let bin as NSData:
|
||||||
binary.append(bin)
|
binary.append(bin)
|
||||||
return placeholder
|
return placeholder as AnyObject
|
||||||
case let arr as [AnyObject]:
|
case let arr as [AnyObject]:
|
||||||
return arr.map({shred($0, binary: &binary)})
|
return arr.map({shred($0, binary: &binary)}) as AnyObject
|
||||||
case let dict as NSDictionary:
|
case let dict as NSDictionary:
|
||||||
return dict.reduce(NSMutableDictionary(), combine: {cur, keyValue in
|
return dict.reduce(NSMutableDictionary(), combine: {cur, keyValue in
|
||||||
cur[keyValue.0 as! NSCopying] = shred(keyValue.1, binary: &binary)
|
cur[keyValue.0 as! NSCopying] = shred(keyValue.1, binary: &binary)
|
||||||
|
|||||||
@ -35,8 +35,6 @@ extension SocketParsable {
|
|||||||
private func handleConnect(_ p: SocketPacket) {
|
private func handleConnect(_ p: SocketPacket) {
|
||||||
if p.nsp == "/" && nsp != "/" {
|
if p.nsp == "/" && nsp != "/" {
|
||||||
joinNamespace(nsp)
|
joinNamespace(nsp)
|
||||||
} else if p.nsp != "/" && nsp == "/" {
|
|
||||||
didConnect()
|
|
||||||
} else {
|
} else {
|
||||||
didConnect()
|
didConnect()
|
||||||
}
|
}
|
||||||
@ -91,8 +89,7 @@ extension SocketParsable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parser.hasNext {
|
if !parser.hasNext {
|
||||||
return .Right(SocketPacket(type: type, id: -1,
|
return .Right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
|
||||||
nsp: namespace ?? "/", placeholders: placeholders))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var idString = ""
|
var idString = ""
|
||||||
@ -110,7 +107,7 @@ extension SocketParsable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let d = message[parser.currentIndex.advanced(by: 1)..<message.endIndex]
|
let d = message[parser.advance(by: 1)..<message.endIndex]
|
||||||
|
|
||||||
switch parseData(d) {
|
switch parseData(d) {
|
||||||
case let .Left(err):
|
case let .Left(err):
|
||||||
|
|||||||
@ -38,12 +38,14 @@ struct SocketStringReader {
|
|||||||
currentIndex = message.startIndex
|
currentIndex = message.startIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func advance(by: Int) {
|
mutating func advance(by: Int) -> String.Index {
|
||||||
currentIndex = currentIndex.advanced(by: by)
|
currentIndex = message.characters.index(currentIndex, offsetBy: by)
|
||||||
|
|
||||||
|
return currentIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func read(length: Int) -> String {
|
mutating func read(length: Int) -> String {
|
||||||
let readString = message[currentIndex..<currentIndex.advanced(by: length)]
|
let readString = message[currentIndex..<message.characters.index(currentIndex, offsetBy: length)]
|
||||||
advance(by: length)
|
advance(by: length)
|
||||||
|
|
||||||
return readString
|
return readString
|
||||||
@ -57,12 +59,12 @@ struct SocketStringReader {
|
|||||||
return substring
|
return substring
|
||||||
}
|
}
|
||||||
|
|
||||||
advance(by: message.startIndex.distance(to: foundRange.startIndex) + 1)
|
advance(by: message.characters.distance(from: message.characters.startIndex, to: foundRange.lowerBound) + 1)
|
||||||
|
|
||||||
return substring.substring(to: foundRange.startIndex)
|
return substring.substring(to: foundRange.lowerBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func readUntilEnd() -> String {
|
mutating func readUntilEnd() -> String {
|
||||||
return read(length: currentIndex.distance(to: message.endIndex))
|
return read(length: message.characters.distance(from: currentIndex, to: message.endIndex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,9 @@ public typealias AckCallback = ([AnyObject]) -> Void
|
|||||||
public typealias NormalCallback = ([AnyObject], SocketAckEmitter) -> Void
|
public typealias NormalCallback = ([AnyObject], SocketAckEmitter) -> Void
|
||||||
public typealias OnAckCallback = (timeoutAfter: UInt64, callback: AckCallback) -> Void
|
public typealias OnAckCallback = (timeoutAfter: UInt64, callback: AckCallback) -> Void
|
||||||
|
|
||||||
|
typealias Probe = (msg: String, type: SocketEnginePacketType, data: [NSData])
|
||||||
|
typealias ProbeWaitQueue = [Probe]
|
||||||
|
|
||||||
enum Either<E, V> {
|
enum Either<E, V> {
|
||||||
case Left(E)
|
case Left(E)
|
||||||
case Right(V)
|
case Right(V)
|
||||||
|
|||||||
@ -112,12 +112,10 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
public var headers = [String: String]()
|
public var headers = [String: String]()
|
||||||
public var voipEnabled = false
|
public var voipEnabled = false
|
||||||
public var selfSignedSSL = false
|
public var selfSignedSSL = false
|
||||||
#if swift(>=3)
|
|
||||||
#else
|
|
||||||
public var security: SSLSecurity?
|
public var security: SSLSecurity?
|
||||||
#endif
|
|
||||||
public var enabledSSLCipherSuites: [SSLCipherSuite]?
|
public var enabledSSLCipherSuites: [SSLCipherSuite]?
|
||||||
public var origin: String?
|
public var origin: String?
|
||||||
|
public var timeout = 5
|
||||||
public var isConnected :Bool {
|
public var isConnected :Bool {
|
||||||
return connected
|
return connected
|
||||||
}
|
}
|
||||||
@ -173,7 +171,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
public func disconnect(forceTimeout: NSTimeInterval? = nil) {
|
public func disconnect(forceTimeout: NSTimeInterval? = nil) {
|
||||||
switch forceTimeout {
|
switch forceTimeout {
|
||||||
case .some(let seconds) where seconds > 0:
|
case .some(let seconds) where seconds > 0:
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC))), queue) { [weak self] in
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC))), queue!) { [weak self] in
|
||||||
self?.disconnectStream(error: nil)
|
self?.disconnectStream(error: nil)
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -231,19 +229,19 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
port = 80
|
port = 80
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addHeader(urlRequest: urlRequest, key: headerWSUpgradeName, val: headerWSUpgradeValue)
|
addHeader(urlRequest: urlRequest, key: headerWSUpgradeName as NSString, val: headerWSUpgradeValue as NSString)
|
||||||
addHeader(urlRequest: urlRequest, key: headerWSConnectionName, val: headerWSConnectionValue)
|
addHeader(urlRequest: urlRequest, key: headerWSConnectionName as NSString, val: headerWSConnectionValue as NSString)
|
||||||
if let protocols = optionalProtocols {
|
if let protocols = optionalProtocols {
|
||||||
addHeader(urlRequest: urlRequest, key: headerWSProtocolName, val: protocols.joined(separator: ","))
|
addHeader(urlRequest: urlRequest, key: headerWSProtocolName as NSString, val: protocols.joined(separator: ",") as NSString)
|
||||||
}
|
}
|
||||||
addHeader(urlRequest: urlRequest, key: headerWSVersionName, val: headerWSVersionValue)
|
addHeader(urlRequest: urlRequest, key: headerWSVersionName as NSString, val: headerWSVersionValue as NSString)
|
||||||
addHeader(urlRequest: urlRequest, key: headerWSKeyName, val: generateWebSocketKey())
|
addHeader(urlRequest: urlRequest, key: headerWSKeyName as NSString, val: generateWebSocketKey() as NSString)
|
||||||
if let origin = origin {
|
if let origin = origin {
|
||||||
addHeader(urlRequest: urlRequest, key: headerOriginName, val: origin)
|
addHeader(urlRequest: urlRequest, key: headerOriginName as NSString, val: origin as NSString)
|
||||||
}
|
}
|
||||||
addHeader(urlRequest: urlRequest, key: headerWSHostName, val: "\(url.host!):\(port!)")
|
addHeader(urlRequest: urlRequest, key: headerWSHostName as NSString, val: "\(url.host!):\(port!)" as NSString)
|
||||||
for (key,value) in headers {
|
for (key,value) in headers {
|
||||||
addHeader(urlRequest: urlRequest, key: key, val: value)
|
addHeader(urlRequest: urlRequest, key: key as NSString, val: value as NSString)
|
||||||
}
|
}
|
||||||
if let cfHTTPMessage = CFHTTPMessageCopySerializedMessage(urlRequest) {
|
if let cfHTTPMessage = CFHTTPMessageCopySerializedMessage(urlRequest) {
|
||||||
let serializedRequest = cfHTTPMessage.takeRetainedValue()
|
let serializedRequest = cfHTTPMessage.takeRetainedValue()
|
||||||
@ -276,48 +274,45 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
|
|
||||||
var readStream: Unmanaged<CFReadStream>?
|
var readStream: Unmanaged<CFReadStream>?
|
||||||
var writeStream: Unmanaged<CFWriteStream>?
|
var writeStream: Unmanaged<CFWriteStream>?
|
||||||
let h: NSString = url.host!
|
let h = url.host!
|
||||||
CFStreamCreatePairWithSocketToHost(nil, h, UInt32(port), &readStream, &writeStream)
|
CFStreamCreatePairWithSocketToHost(nil, h as NSString, UInt32(port), &readStream, &writeStream)
|
||||||
inputStream = readStream!.takeRetainedValue()
|
inputStream = readStream!.takeRetainedValue()
|
||||||
outputStream = writeStream!.takeRetainedValue()
|
outputStream = writeStream!.takeRetainedValue()
|
||||||
guard let inStream = inputStream, let outStream = outputStream else { return }
|
guard let inStream = inputStream, let outStream = outputStream else { return }
|
||||||
inStream.delegate = self
|
inStream.delegate = self
|
||||||
outStream.delegate = self
|
outStream.delegate = self
|
||||||
if ["wss", "https"].contains(url.scheme) {
|
if ["wss", "https"].contains(url.scheme) {
|
||||||
inStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, forKey: NSStreamSocketSecurityLevelKey)
|
inStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL as NSString, forKey: NSStreamSocketSecurityLevelKey)
|
||||||
outStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, forKey: NSStreamSocketSecurityLevelKey)
|
outStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL as NSString, forKey: NSStreamSocketSecurityLevelKey)
|
||||||
} else {
|
} else {
|
||||||
certValidated = true //not a https session, so no need to check SSL pinning
|
certValidated = true //not a https session, so no need to check SSL pinning
|
||||||
}
|
}
|
||||||
if voipEnabled {
|
if voipEnabled {
|
||||||
inStream.setProperty(NSStreamNetworkServiceTypeVoIP, forKey: NSStreamNetworkServiceType)
|
inStream.setProperty(NSStreamNetworkServiceTypeVoIP as NSString, forKey: NSStreamNetworkServiceType)
|
||||||
outStream.setProperty(NSStreamNetworkServiceTypeVoIP, forKey: NSStreamNetworkServiceType)
|
outStream.setProperty(NSStreamNetworkServiceTypeVoIP as NSString, forKey: NSStreamNetworkServiceType)
|
||||||
}
|
}
|
||||||
if selfSignedSSL {
|
if selfSignedSSL {
|
||||||
let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull]
|
let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull]
|
||||||
inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String)
|
inStream.setProperty(settings as AnyObject?, forKey: kCFStreamPropertySSLSettings as String)
|
||||||
outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String)
|
outStream.setProperty(settings as AnyObject?, forKey: kCFStreamPropertySSLSettings as String)
|
||||||
}
|
}
|
||||||
#if swift(>=3)
|
|
||||||
#else
|
|
||||||
if let cipherSuites = self.enabledSSLCipherSuites {
|
if let cipherSuites = self.enabledSSLCipherSuites {
|
||||||
if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContextRef?,
|
if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContext?,
|
||||||
sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContextRef? {
|
sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContext? {
|
||||||
let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count)
|
let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count)
|
||||||
let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count)
|
let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count)
|
||||||
if resIn != errSecSuccess {
|
if resIn != errSecSuccess {
|
||||||
let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn))
|
let error = self.errorWithDetail(detail: "Error setting ingoing cypher suites", code: UInt16(resIn))
|
||||||
disconnectStream(error)
|
disconnectStream(error: error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if resOut != errSecSuccess {
|
if resOut != errSecSuccess {
|
||||||
let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut))
|
let error = self.errorWithDetail(detail: "Error setting outgoing cypher suites", code: UInt16(resOut))
|
||||||
disconnectStream(error)
|
disconnectStream(error: error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue)
|
CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue)
|
||||||
CFWriteStreamSetDispatchQueue(outStream, WebSocket.sharedWorkQueue)
|
CFWriteStreamSetDispatchQueue(outStream, WebSocket.sharedWorkQueue)
|
||||||
inStream.open()
|
inStream.open()
|
||||||
@ -328,12 +323,12 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
self.mutex.unlock()
|
self.mutex.unlock()
|
||||||
|
|
||||||
let bytes = UnsafePointer<UInt8>(data.bytes)
|
let bytes = UnsafePointer<UInt8>(data.bytes)
|
||||||
var timeout = 5000000 //wait 5 seconds before giving up
|
var out = timeout * 1000000 //wait 5 seconds before giving up
|
||||||
writeQueue.addOperation { [weak self] in
|
writeQueue.addOperation { [weak self] in
|
||||||
while !outStream.hasSpaceAvailable {
|
while !outStream.hasSpaceAvailable {
|
||||||
usleep(100) //wait until the socket is ready
|
usleep(100) //wait until the socket is ready
|
||||||
timeout -= 100
|
out -= 100
|
||||||
if timeout < 0 {
|
if out < 0 {
|
||||||
self?.cleanupStream()
|
self?.cleanupStream()
|
||||||
self?.doDisconnect(error: self?.errorWithDetail(detail: "write wait timed out", code: 2))
|
self?.doDisconnect(error: self?.errorWithDetail(detail: "write wait timed out", code: 2))
|
||||||
return
|
return
|
||||||
@ -344,24 +339,22 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
outStream.write(bytes, maxLength: data.length)
|
outStream.write(bytes, maxLength: data.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//delegate for the stream methods. Processes incoming bytes
|
//delegate for the stream methods. Processes incoming bytes
|
||||||
public func stream(aStream: NSStream, handle eventCode: NSStreamEvent) {
|
public func stream(aStream: NSStream, handle eventCode: NSStreamEvent) {
|
||||||
#if swift(>=3)
|
if let sec = security where !certValidated && [.hasBytesAvailable, .hasSpaceAvailable].contains(eventCode) {
|
||||||
#else
|
|
||||||
if let sec = security where !certValidated && [.HasBytesAvailable, .HasSpaceAvailable].contains(eventCode) {
|
|
||||||
let possibleTrust: AnyObject? = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as String)
|
let possibleTrust: AnyObject? = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as String)
|
||||||
if let trust: AnyObject = possibleTrust {
|
if let trust: AnyObject = possibleTrust {
|
||||||
let domain: AnyObject? = aStream.property(forKey: kCFStreamSSLPeerName as String)
|
let domain: AnyObject? = aStream.property(forKey: kCFStreamSSLPeerName as String)
|
||||||
if sec.isValid(trust as! SecTrustRef, domain: domain as! String?) {
|
if sec.isValid(trust: trust as! SecTrust, domain: domain as! String?) {
|
||||||
certValidated = true
|
certValidated = true
|
||||||
} else {
|
} else {
|
||||||
let error = errorWithDetail("Invalid SSL certificate", code: 1)
|
let error = errorWithDetail(detail: "Invalid SSL certificate", code: 1)
|
||||||
disconnectStream(error)
|
disconnectStream(error: error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if eventCode == .hasBytesAvailable {
|
if eventCode == .hasBytesAvailable {
|
||||||
if aStream == inputStream {
|
if aStream == inputStream {
|
||||||
processInputStream()
|
processInputStream()
|
||||||
@ -416,25 +409,24 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
///dequeue the incoming input so it is processed in order
|
///dequeue the incoming input so it is processed in order
|
||||||
private func dequeueInput() {
|
private func dequeueInput() {
|
||||||
guard !inputQueue.isEmpty else { return }
|
while !inputQueue.isEmpty {
|
||||||
|
let data = inputQueue[0]
|
||||||
let data = inputQueue[0]
|
var work = data
|
||||||
var work = data
|
if let fragBuffer = fragBuffer {
|
||||||
if let fragBuffer = fragBuffer {
|
let combine = NSMutableData(data: fragBuffer)
|
||||||
let combine = NSMutableData(data: fragBuffer)
|
combine.append(data)
|
||||||
combine.append(data)
|
work = combine
|
||||||
work = combine
|
self.fragBuffer = nil
|
||||||
self.fragBuffer = nil
|
}
|
||||||
|
let buffer = UnsafePointer<UInt8>(work.bytes)
|
||||||
|
let length = work.length
|
||||||
|
if !connected {
|
||||||
|
processTCPHandshake(buffer: buffer, bufferLen: length)
|
||||||
|
} else {
|
||||||
|
processRawMessagesInBuffer(pointer: buffer, bufferLen: length)
|
||||||
|
}
|
||||||
|
inputQueue = inputQueue.filter{$0 != data}
|
||||||
}
|
}
|
||||||
let buffer = UnsafePointer<UInt8>(work.bytes)
|
|
||||||
let length = work.length
|
|
||||||
if !connected {
|
|
||||||
processTCPHandshake(buffer: buffer, bufferLen: length)
|
|
||||||
} else {
|
|
||||||
processRawMessage(buffer: buffer, bufferLen: length)
|
|
||||||
}
|
|
||||||
inputQueue = inputQueue.filter{$0 != data}
|
|
||||||
dequeueInput()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle checking the inital connection status
|
//handle checking the inital connection status
|
||||||
@ -444,7 +436,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
case 0:
|
case 0:
|
||||||
connected = true
|
connected = true
|
||||||
guard canDispatch else {return}
|
guard canDispatch else {return}
|
||||||
dispatch_async(queue) { [weak self] in
|
dispatch_async(queue!) { [weak self] in
|
||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onConnect?()
|
s.onConnect?()
|
||||||
s.delegate?.websocketDidConnect(socket: s)
|
s.delegate?.websocketDidConnect(socket: s)
|
||||||
@ -480,7 +472,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
totalSize += 1 //skip the last \n
|
totalSize += 1 //skip the last \n
|
||||||
let restSize = bufferLen - totalSize
|
let restSize = bufferLen - totalSize
|
||||||
if restSize > 0 {
|
if restSize > 0 {
|
||||||
processRawMessage(buffer: (buffer+totalSize),bufferLen: restSize)
|
processRawMessagesInBuffer(pointer: buffer + totalSize, bufferLen: restSize)
|
||||||
}
|
}
|
||||||
return 0 //success
|
return 0 //success
|
||||||
}
|
}
|
||||||
@ -497,7 +489,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
if let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response) {
|
if let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response) {
|
||||||
let headers = cfHeaders.takeRetainedValue() as NSDictionary
|
let headers = cfHeaders.takeRetainedValue() as NSDictionary
|
||||||
if let acceptKey = headers[headerWSAcceptName] as? NSString {
|
if let acceptKey = headers[headerWSAcceptName as NSString] as? NSString {
|
||||||
if acceptKey.length > 0 {
|
if acceptKey.length > 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -533,12 +525,15 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///process the websocket data
|
/// Process one message at the start of `buffer`. Return another buffer (sharing storage) that contains the leftover contents of `buffer` that I didn't process.
|
||||||
private func processRawMessage(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
@warn_unused_result
|
||||||
|
private func processOneRawMessage(inBuffer buffer: UnsafeBufferPointer<UInt8>) -> UnsafeBufferPointer<UInt8> {
|
||||||
let response = readStack.last
|
let response = readStack.last
|
||||||
|
guard let baseAddress = buffer.baseAddress else { fatalError("") }
|
||||||
|
let bufferLen = buffer.count
|
||||||
if response != nil && bufferLen < 2 {
|
if response != nil && bufferLen < 2 {
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(buffer: buffer)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if let response = response where response.bytesLeft > 0 {
|
if let response = response where response.bytesLeft > 0 {
|
||||||
var len = response.bytesLeft
|
var len = response.bytesLeft
|
||||||
@ -548,24 +543,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
extra = 0
|
extra = 0
|
||||||
}
|
}
|
||||||
response.bytesLeft -= len
|
response.bytesLeft -= len
|
||||||
response.buffer?.append(NSData(bytes: buffer, length: len))
|
response.buffer?.append(NSData(bytes: baseAddress, length: len))
|
||||||
processResponse(response: response)
|
processResponse(response: response)
|
||||||
let offset = bufferLen - extra
|
return buffer.fromOffset(offset: bufferLen - extra)
|
||||||
if extra > 0 {
|
|
||||||
processExtra(buffer: (buffer+offset), bufferLen: extra)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else {
|
} else {
|
||||||
let isFin = (FinMask & buffer[0])
|
let isFin = (FinMask & baseAddress[0])
|
||||||
let receivedOpcode = OpCode(rawValue: (OpCodeMask & buffer[0]))
|
let receivedOpcode = OpCode(rawValue: (OpCodeMask & baseAddress[0]))
|
||||||
let isMasked = (MaskMask & buffer[1])
|
let isMasked = (MaskMask & baseAddress[1])
|
||||||
let payloadLen = (PayloadLenMask & buffer[1])
|
let payloadLen = (PayloadLenMask & baseAddress[1])
|
||||||
var offset = 2
|
var offset = 2
|
||||||
if (isMasked > 0 || (RSVMask & buffer[0]) > 0) && receivedOpcode != .Pong {
|
if (isMasked > 0 || (RSVMask & baseAddress[0]) > 0) && receivedOpcode != .Pong {
|
||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(error: errorWithDetail(detail: "masked and rsv data is not currently supported", code: errCode))
|
doDisconnect(error: errorWithDetail(detail: "masked and rsv data is not currently supported", code: errCode))
|
||||||
writeError(code: errCode)
|
writeError(code: errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping)
|
let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping)
|
||||||
if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame &&
|
if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame &&
|
||||||
@ -573,20 +564,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(error: errorWithDetail(detail: "unknown opcode: \(receivedOpcode)", code: errCode))
|
doDisconnect(error: errorWithDetail(detail: "unknown opcode: \(receivedOpcode)", code: errCode))
|
||||||
writeError(code: errCode)
|
writeError(code: errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if isControlFrame && isFin == 0 {
|
if isControlFrame && isFin == 0 {
|
||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(error: errorWithDetail(detail: "control frames can't be fragmented", code: errCode))
|
doDisconnect(error: errorWithDetail(detail: "control frames can't be fragmented", code: errCode))
|
||||||
writeError(code: errCode)
|
writeError(code: errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if receivedOpcode == .ConnectionClose {
|
if receivedOpcode == .ConnectionClose {
|
||||||
var code = CloseCode.Normal.rawValue
|
var code = CloseCode.Normal.rawValue
|
||||||
if payloadLen == 1 {
|
if payloadLen == 1 {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
} else if payloadLen > 1 {
|
} else if payloadLen > 1 {
|
||||||
code = WebSocket.readUint16(buffer: buffer, offset: offset)
|
code = WebSocket.readUint16(buffer: baseAddress, offset: offset)
|
||||||
if code < 1000 || (code > 1003 && code < 1007) || (code > 1011 && code < 3000) {
|
if code < 1000 || (code > 1003 && code < 1007) || (code > 1011 && code < 3000) {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
}
|
}
|
||||||
@ -595,7 +586,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
if payloadLen > 2 {
|
if payloadLen > 2 {
|
||||||
let len = Int(payloadLen-2)
|
let len = Int(payloadLen-2)
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let bytes = UnsafePointer<UInt8>((buffer+offset))
|
let bytes = baseAddress + offset
|
||||||
let str: NSString? = NSString(data: NSData(bytes: bytes, length: len), encoding: NSUTF8StringEncoding)
|
let str: NSString? = NSString(data: NSData(bytes: bytes, length: len), encoding: NSUTF8StringEncoding)
|
||||||
if str == nil {
|
if str == nil {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
@ -604,23 +595,23 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
doDisconnect(error: errorWithDetail(detail: "connection closed by server", code: code))
|
doDisconnect(error: errorWithDetail(detail: "connection closed by server", code: code))
|
||||||
writeError(code: code)
|
writeError(code: code)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if isControlFrame && payloadLen > 125 {
|
if isControlFrame && payloadLen > 125 {
|
||||||
writeError(code: CloseCode.ProtocolError.rawValue)
|
writeError(code: CloseCode.ProtocolError.rawValue)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
var dataLength = UInt64(payloadLen)
|
var dataLength = UInt64(payloadLen)
|
||||||
if dataLength == 127 {
|
if dataLength == 127 {
|
||||||
dataLength = WebSocket.readUint64(buffer: buffer, offset: offset)
|
dataLength = WebSocket.readUint64(buffer: baseAddress, offset: offset)
|
||||||
offset += sizeof(UInt64)
|
offset += sizeof(UInt64)
|
||||||
} else if dataLength == 126 {
|
} else if dataLength == 126 {
|
||||||
dataLength = UInt64(WebSocket.readUint16(buffer: buffer, offset: offset))
|
dataLength = UInt64(WebSocket.readUint16(buffer: baseAddress, offset: offset))
|
||||||
offset += sizeof(UInt16)
|
offset += sizeof(UInt16)
|
||||||
}
|
}
|
||||||
if bufferLen < offset || UInt64(bufferLen - offset) < dataLength {
|
if bufferLen < offset || UInt64(bufferLen - offset) < dataLength {
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(bytes: baseAddress, length: bufferLen)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
var len = dataLength
|
var len = dataLength
|
||||||
if dataLength > UInt64(bufferLen) {
|
if dataLength > UInt64(bufferLen) {
|
||||||
@ -631,22 +622,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
len = 0
|
len = 0
|
||||||
data = NSData()
|
data = NSData()
|
||||||
} else {
|
} else {
|
||||||
data = NSData(bytes: UnsafePointer<UInt8>((buffer+offset)), length: Int(len))
|
data = NSData(bytes: baseAddress+offset, length: Int(len))
|
||||||
}
|
}
|
||||||
if receivedOpcode == .Pong {
|
if receivedOpcode == .Pong {
|
||||||
if canDispatch {
|
if canDispatch {
|
||||||
dispatch_async(queue) { [weak self] in
|
dispatch_async(queue!) { [weak self] in
|
||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onPong?()
|
s.onPong?()
|
||||||
s.pongDelegate?.websocketDidReceivePong(socket: s)
|
s.pongDelegate?.websocketDidReceivePong(socket: s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let step = Int(offset+numericCast(len))
|
return buffer.fromOffset(offset: offset + Int(len))
|
||||||
let extra = bufferLen-step
|
|
||||||
if extra > 0 {
|
|
||||||
processRawMessage(buffer: (buffer+step), bufferLen: extra)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
var response = readStack.last
|
var response = readStack.last
|
||||||
if isControlFrame {
|
if isControlFrame {
|
||||||
@ -656,7 +642,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(error: errorWithDetail(detail: "continue frame before a binary or text frame", code: errCode))
|
doDisconnect(error: errorWithDetail(detail: "continue frame before a binary or text frame", code: errCode))
|
||||||
writeError(code: errCode)
|
writeError(code: errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
var isNew = false
|
var isNew = false
|
||||||
if response == nil {
|
if response == nil {
|
||||||
@ -665,7 +651,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
doDisconnect(error: errorWithDetail(detail: "first frame can't be a continue frame",
|
doDisconnect(error: errorWithDetail(detail: "first frame can't be a continue frame",
|
||||||
code: errCode))
|
code: errCode))
|
||||||
writeError(code: errCode)
|
writeError(code: errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
isNew = true
|
isNew = true
|
||||||
response = WSResponse()
|
response = WSResponse()
|
||||||
@ -680,7 +666,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
doDisconnect(error: errorWithDetail(detail: "second and beyond of fragment message must be a continue frame",
|
doDisconnect(error: errorWithDetail(detail: "second and beyond of fragment message must be a continue frame",
|
||||||
code: errCode))
|
code: errCode))
|
||||||
writeError(code: errCode)
|
writeError(code: errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
response!.buffer!.append(data)
|
response!.buffer!.append(data)
|
||||||
}
|
}
|
||||||
@ -695,20 +681,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let step = Int(offset+numericCast(len))
|
let step = Int(offset+numericCast(len))
|
||||||
let extra = bufferLen-step
|
return buffer.fromOffset(offset: step)
|
||||||
if extra > 0 {
|
|
||||||
processExtra(buffer: (buffer+step), bufferLen: extra)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///process the extra of a buffer
|
/// Process all messages in the buffer if possible.
|
||||||
private func processExtra(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
private func processRawMessagesInBuffer(pointer: UnsafePointer<UInt8>, bufferLen: Int) {
|
||||||
if bufferLen < 2 {
|
var buffer = UnsafeBufferPointer(start: pointer, count: bufferLen)
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
repeat {
|
||||||
} else {
|
buffer = processOneRawMessage(inBuffer: buffer)
|
||||||
processRawMessage(buffer: buffer, bufferLen: bufferLen)
|
} while buffer.count >= 2
|
||||||
|
if buffer.count > 0 {
|
||||||
|
fragBuffer = NSData(buffer: buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,7 +709,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if canDispatch {
|
if canDispatch {
|
||||||
dispatch_async(queue) { [weak self] in
|
dispatch_async(queue!) { [weak self] in
|
||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onText?(str! as String)
|
s.onText?(str! as String)
|
||||||
s.delegate?.websocketDidReceiveMessage(socket: s, text: str! as String)
|
s.delegate?.websocketDidReceiveMessage(socket: s, text: str! as String)
|
||||||
@ -734,7 +718,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
} else if response.code == .BinaryFrame {
|
} else if response.code == .BinaryFrame {
|
||||||
if canDispatch {
|
if canDispatch {
|
||||||
let data = response.buffer! //local copy so it is perverse for writing
|
let data = response.buffer! //local copy so it is perverse for writing
|
||||||
dispatch_async(queue) { [weak self] in
|
dispatch_async(queue!) { [weak self] in
|
||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onData?(data)
|
s.onData?(data)
|
||||||
s.delegate?.websocketDidReceiveData(socket: s, data: data)
|
s.delegate?.websocketDidReceiveData(socket: s, data: data)
|
||||||
@ -751,8 +735,9 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
private func errorWithDetail(detail: String, code: UInt16) -> NSError {
|
private func errorWithDetail(detail: String, code: UInt16) -> NSError {
|
||||||
var details = [String: String]()
|
var details = [String: String]()
|
||||||
details[NSLocalizedDescriptionKey] = detail
|
details[NSLocalizedDescriptionKey] = detail
|
||||||
|
|
||||||
#if swift(>=3)
|
#if swift(>=3)
|
||||||
return NSError(domain: "April 12 build of Swift 3 broke this property", code: Int(code), userInfo: details)
|
return NSError(domain: "This is still broken", code: Int(code), userInfo: details)
|
||||||
#else
|
#else
|
||||||
return NSError(domain: WebSocket.ErrorDomain, code: Int(code), userInfo: details)
|
return NSError(domain: WebSocket.ErrorDomain, code: Int(code), userInfo: details)
|
||||||
#endif
|
#endif
|
||||||
@ -834,7 +819,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
didDisconnect = true
|
didDisconnect = true
|
||||||
connected = false
|
connected = false
|
||||||
guard canDispatch else {return}
|
guard canDispatch else {return}
|
||||||
dispatch_async(queue) { [weak self] in
|
dispatch_async(queue!) { [weak self] in
|
||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onDisconnect?(error)
|
s.onDisconnect?(error)
|
||||||
s.delegate?.websocketDidDisconnect(socket: s, error: error)
|
s.delegate?.websocketDidDisconnect(socket: s, error: error)
|
||||||
@ -850,11 +835,27 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if swift(>=3)
|
private extension NSData {
|
||||||
#else
|
|
||||||
|
convenience init(buffer: UnsafeBufferPointer<UInt8>) {
|
||||||
|
self.init(bytes: buffer.baseAddress, length: buffer.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension UnsafeBufferPointer {
|
||||||
|
|
||||||
|
func fromOffset(offset: Int) -> UnsafeBufferPointer<Element> {
|
||||||
|
return UnsafeBufferPointer<Element>(start: baseAddress!.advanced(by: offset), count: count - offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private let emptyBuffer = UnsafeBufferPointer<UInt8>(start: nil, count: 0)
|
||||||
|
|
||||||
public class SSLCert {
|
public class SSLCert {
|
||||||
var certData: NSData?
|
var certData: NSData?
|
||||||
var key: SecKeyRef?
|
var key: SecKey?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Designated init for certificates
|
Designated init for certificates
|
||||||
@ -874,7 +875,7 @@ public class SSLCert {
|
|||||||
|
|
||||||
- returns: a representation security object to be used with
|
- returns: a representation security object to be used with
|
||||||
*/
|
*/
|
||||||
public init(key: SecKeyRef) {
|
public init(key: SecKey) {
|
||||||
self.key = key
|
self.key = key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -884,7 +885,7 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
var isReady = false //is the key processing done?
|
var isReady = false //is the key processing done?
|
||||||
var certificates: [NSData]? //the certificates
|
var certificates: [NSData]? //the certificates
|
||||||
var pubKeys: [SecKeyRef]? //the public keys
|
var pubKeys: [SecKey]? //the public keys
|
||||||
var usePublicKeys = false //use public keys or certificate validation?
|
var usePublicKeys = false //use public keys or certificate validation?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -895,7 +896,7 @@ public class SSLSecurity {
|
|||||||
- returns: a representation security object to be used with
|
- returns: a representation security object to be used with
|
||||||
*/
|
*/
|
||||||
public convenience init(usePublicKeys: Bool = false) {
|
public convenience init(usePublicKeys: Bool = false) {
|
||||||
let paths = NSBundle.mainBundle().pathsForResourcesOfType("cer", inDirectory: ".")
|
let paths = NSBundle.main().pathsForResources(ofType: "cer", inDirectory: ".")
|
||||||
|
|
||||||
let certs = paths.reduce([SSLCert]()) { (certs: [SSLCert], path: String) -> [SSLCert] in
|
let certs = paths.reduce([SSLCert]()) { (certs: [SSLCert], path: String) -> [SSLCert] in
|
||||||
var certs = certs
|
var certs = certs
|
||||||
@ -921,10 +922,10 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
if self.usePublicKeys {
|
if self.usePublicKeys {
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)) {
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)) {
|
||||||
let pubKeys = certs.reduce([SecKeyRef]()) { (pubKeys: [SecKeyRef], cert: SSLCert) -> [SecKeyRef] in
|
let pubKeys = certs.reduce([SecKey]()) { (pubKeys: [SecKey], cert: SSLCert) -> [SecKey] in
|
||||||
var pubKeys = pubKeys
|
var pubKeys = pubKeys
|
||||||
if let data = cert.certData where cert.key == nil {
|
if let data = cert.certData where cert.key == nil {
|
||||||
cert.key = self.extractPublicKey(data)
|
cert.key = self.extractPublicKey(data: data)
|
||||||
}
|
}
|
||||||
if let key = cert.key {
|
if let key = cert.key {
|
||||||
pubKeys.append(key)
|
pubKeys.append(key)
|
||||||
@ -956,7 +957,7 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
- returns: if the key was successfully validated
|
- returns: if the key was successfully validated
|
||||||
*/
|
*/
|
||||||
public func isValid(trust: SecTrustRef, domain: String?) -> Bool {
|
public func isValid(trust: SecTrust, domain: String?) -> Bool {
|
||||||
|
|
||||||
var tries = 0
|
var tries = 0
|
||||||
while(!self.isReady) {
|
while(!self.isReady) {
|
||||||
@ -966,16 +967,16 @@ public class SSLSecurity {
|
|||||||
return false //doesn't appear it is going to ever be ready...
|
return false //doesn't appear it is going to ever be ready...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var policy: SecPolicyRef
|
var policy: SecPolicy
|
||||||
if self.validatedDN {
|
if self.validatedDN {
|
||||||
policy = SecPolicyCreateSSL(true, domain)
|
policy = SecPolicyCreateSSL(true, (domain as! CFString))
|
||||||
} else {
|
} else {
|
||||||
policy = SecPolicyCreateBasicX509()
|
policy = SecPolicyCreateBasicX509()
|
||||||
}
|
}
|
||||||
SecTrustSetPolicies(trust,policy)
|
SecTrustSetPolicies(trust,policy)
|
||||||
if self.usePublicKeys {
|
if self.usePublicKeys {
|
||||||
if let keys = self.pubKeys {
|
if let keys = self.pubKeys {
|
||||||
let serverPubKeys = publicKeyChainForTrust(trust)
|
let serverPubKeys = publicKeyChainForTrust(trust: trust)
|
||||||
for serverKey in serverPubKeys as [AnyObject] {
|
for serverKey in serverPubKeys as [AnyObject] {
|
||||||
for key in keys as [AnyObject] {
|
for key in keys as [AnyObject] {
|
||||||
if serverKey.isEqual(key) {
|
if serverKey.isEqual(key) {
|
||||||
@ -985,12 +986,12 @@ public class SSLSecurity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let certs = self.certificates {
|
} else if let certs = self.certificates {
|
||||||
let serverCerts = certificateChainForTrust(trust)
|
let serverCerts = certificateChainForTrust(trust: trust)
|
||||||
var collect = [SecCertificate]()
|
var collect = [SecCertificate]()
|
||||||
for cert in certs {
|
for cert in certs {
|
||||||
collect.append(SecCertificateCreateWithData(nil,cert)!)
|
collect.append(SecCertificateCreateWithData(nil,cert)!)
|
||||||
}
|
}
|
||||||
SecTrustSetAnchorCertificates(trust,collect)
|
SecTrustSetAnchorCertificates(trust,collect as CFArray)
|
||||||
var result: SecTrustResultType = 0
|
var result: SecTrustResultType = 0
|
||||||
SecTrustEvaluate(trust,&result)
|
SecTrustEvaluate(trust,&result)
|
||||||
let r = Int(result)
|
let r = Int(result)
|
||||||
@ -1019,10 +1020,10 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
- returns: a public key
|
- returns: a public key
|
||||||
*/
|
*/
|
||||||
func extractPublicKey(data: NSData) -> SecKeyRef? {
|
func extractPublicKey(data: NSData) -> SecKey? {
|
||||||
guard let cert = SecCertificateCreateWithData(nil, data) else { return nil }
|
guard let cert = SecCertificateCreateWithData(nil, data) else { return nil }
|
||||||
|
|
||||||
return extractPublicKeyFromCert(cert, policy: SecPolicyCreateBasicX509())
|
return extractPublicKeyFromCert(cert: cert, policy: SecPolicyCreateBasicX509())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1032,7 +1033,7 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
- returns: a public key
|
- returns: a public key
|
||||||
*/
|
*/
|
||||||
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKeyRef? {
|
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKey? {
|
||||||
var possibleTrust: SecTrust?
|
var possibleTrust: SecTrust?
|
||||||
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
|
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
|
||||||
|
|
||||||
@ -1050,7 +1051,7 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
- returns: the certificate chain for the trust
|
- returns: the certificate chain for the trust
|
||||||
*/
|
*/
|
||||||
func certificateChainForTrust(trust: SecTrustRef) -> [NSData] {
|
func certificateChainForTrust(trust: SecTrust) -> [NSData] {
|
||||||
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([NSData]()) { (certificates: [NSData], index: Int) -> [NSData] in
|
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([NSData]()) { (certificates: [NSData], index: Int) -> [NSData] in
|
||||||
var certificates = certificates
|
var certificates = certificates
|
||||||
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
||||||
@ -1068,12 +1069,12 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
- returns: the public keys from the certifcate chain for the trust
|
- returns: the public keys from the certifcate chain for the trust
|
||||||
*/
|
*/
|
||||||
func publicKeyChainForTrust(trust: SecTrustRef) -> [SecKeyRef] {
|
func publicKeyChainForTrust(trust: SecTrust) -> [SecKey] {
|
||||||
let policy = SecPolicyCreateBasicX509()
|
let policy = SecPolicyCreateBasicX509()
|
||||||
let keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKeyRef]()) { (keys: [SecKeyRef], index: Int) -> [SecKeyRef] in
|
let keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKey]()) { (keys: [SecKey], index: Int) -> [SecKey] in
|
||||||
var keys = keys
|
var keys = keys
|
||||||
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
||||||
if let key = extractPublicKeyFromCert(cert!, policy: policy) {
|
if let key = extractPublicKeyFromCert(cert: cert!, policy: policy) {
|
||||||
keys.append(key)
|
keys.append(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1085,4 +1086,3 @@ public class SSLSecurity {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
Loading…
x
Reference in New Issue
Block a user