This commit is contained in:
Erik 2016-06-14 20:41:59 -04:00
parent 7500ea83a0
commit 9a4ec5a82a
27 changed files with 552 additions and 545 deletions

View File

@ -536,9 +536,11 @@
}; };
572EF2371B51F18A00EEBB58 = { 572EF2371B51F18A00EEBB58 = {
CreatedOnToolsVersion = 6.4; CreatedOnToolsVersion = 6.4;
LastSwiftMigration = 0800;
}; };
572EF2411B51F18A00EEBB58 = { 572EF2411B51F18A00EEBB58 = {
CreatedOnToolsVersion = 6.4; CreatedOnToolsVersion = 6.4;
LastSwiftMigration = 0800;
}; };
}; };
}; };
@ -1081,6 +1083,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
}; };
@ -1132,6 +1135,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)";
SDKROOT = macosx; SDKROOT = macosx;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
}; };
@ -1188,6 +1192,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
}; };
name = Debug; name = Debug;
}; };
@ -1234,6 +1239,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_VERSION = 3.0;
}; };
name = Release; name = Release;
}; };

View File

@ -15,7 +15,7 @@ class SocketAckManagerTest: XCTestCase {
func testAddAcks() { func testAddAcks() {
let callbackExpection = self.expectation(withDescription: "callbackExpection") let callbackExpection = self.expectation(withDescription: "callbackExpection")
let itemsArray = ["Hi", "ho"] let itemsArray = ["Hi", "ho"]
func callback(items: [AnyObject]) { func callback(_ items: [AnyObject]) {
callbackExpection.fulfill() callbackExpection.fulfill()
} }
ackManager.addAck(1, callback: callback) ackManager.addAck(1, callback: callback)

View File

@ -10,13 +10,13 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketBasicPacketTest: XCTestCase { class SocketBasicPacketTest: XCTestCase {
let data = "test".data(using: NSUTF8StringEncoding)! let data = "test".data(using: String.Encoding.utf8)!
let data2 = "test2".data(using: NSUTF8StringEncoding)! let data2 = "test2".data(using: String.Encoding.utf8)!
func testEmpyEmit() { func testEmpyEmit() {
let expectedSendString = "2[\"test\"]" let expectedSendString = "2[\"test\"]"
let sendData = ["test"] let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -24,7 +24,7 @@ class SocketBasicPacketTest: XCTestCase {
func testNullEmit() { func testNullEmit() {
let expectedSendString = "2[\"test\",null]" let expectedSendString = "2[\"test\",null]"
let sendData = ["test", NSNull()] let sendData = ["test", NSNull()]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -32,7 +32,7 @@ class SocketBasicPacketTest: XCTestCase {
func testStringEmit() { func testStringEmit() {
let expectedSendString = "2[\"test\",\"foo bar\"]" let expectedSendString = "2[\"test\",\"foo bar\"]"
let sendData = ["test", "foo bar"] let sendData = ["test", "foo bar"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -40,7 +40,7 @@ class SocketBasicPacketTest: XCTestCase {
func testStringEmitWithQuotes() { func testStringEmitWithQuotes() {
let expectedSendString = "2[\"test\",\"\\\"he\\\"llo world\\\"\"]" let expectedSendString = "2[\"test\",\"\\\"he\\\"llo world\\\"\"]"
let sendData = ["test", "\"he\"llo world\""] let sendData = ["test", "\"he\"llo world\""]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -48,7 +48,7 @@ class SocketBasicPacketTest: XCTestCase {
func testJSONEmit() { func testJSONEmit() {
let expectedSendString = "2[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let expectedSendString = "2[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
let sendData = ["test", ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]] let sendData = ["test", ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -56,7 +56,7 @@ class SocketBasicPacketTest: XCTestCase {
func testArrayEmit() { func testArrayEmit() {
let expectedSendString = "2[\"test\",[\"hello\",1,{\"test\":\"test\"}]]" let expectedSendString = "2[\"test\",[\"hello\",1,{\"test\":\"test\"}]]"
let sendData = ["test", ["hello", 1, ["test": "test"]]] let sendData = ["test", ["hello", 1, ["test": "test"]]]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -64,7 +64,7 @@ class SocketBasicPacketTest: XCTestCase {
func testBinaryEmit() { func testBinaryEmit() {
let expectedSendString = "51-[\"test\",{\"_placeholder\":true,\"num\":0}]" 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(sendData as [AnyObject], id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data]) XCTAssertEqual(packet.binary, [data])
@ -73,7 +73,7 @@ class SocketBasicPacketTest: XCTestCase {
func testMultipleBinaryEmit() { func testMultipleBinaryEmit() {
let expectedSendString = "52-[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]" 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(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data, data2]) XCTAssertEqual(packet.binary, [data, data2])
@ -82,7 +82,7 @@ class SocketBasicPacketTest: XCTestCase {
func testEmitWithAck() { func testEmitWithAck() {
let expectedSendString = "20[\"test\"]" let expectedSendString = "20[\"test\"]"
let sendData = ["test"] let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -90,7 +90,7 @@ class SocketBasicPacketTest: XCTestCase {
func testEmitDataWithAck() { func testEmitDataWithAck() {
let expectedSendString = "51-0[\"test\",{\"_placeholder\":true,\"num\":0}]" 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(sendData as [AnyObject], id: 0, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data]) XCTAssertEqual(packet.binary, [data])
@ -99,7 +99,7 @@ class SocketBasicPacketTest: XCTestCase {
// Acks // Acks
func testEmptyAck() { func testEmptyAck() {
let expectedSendString = "30[]" let expectedSendString = "30[]"
let packet = SocketPacket.packetFromEmit(items: [], id: 0, nsp: "/", ack: true) let packet = SocketPacket.packetFromEmit([], id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -107,7 +107,7 @@ class SocketBasicPacketTest: XCTestCase {
func testNullAck() { func testNullAck() {
let expectedSendString = "30[null]" let expectedSendString = "30[null]"
let sendData = [NSNull()] let sendData = [NSNull()]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -115,7 +115,7 @@ class SocketBasicPacketTest: XCTestCase {
func testStringAck() { func testStringAck() {
let expectedSendString = "30[\"test\"]" let expectedSendString = "30[\"test\"]"
let sendData = ["test"] let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -123,7 +123,7 @@ class SocketBasicPacketTest: XCTestCase {
func testJSONAck() { func testJSONAck() {
let expectedSendString = "30[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let expectedSendString = "30[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
let sendData = [["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]] let sendData = [["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/", ack: true) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -131,7 +131,7 @@ class SocketBasicPacketTest: XCTestCase {
func testBinaryAck() { func testBinaryAck() {
let expectedSendString = "61-0[{\"_placeholder\":true,\"num\":0}]" 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(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data]) XCTAssertEqual(packet.binary, [data])
@ -140,7 +140,7 @@ class SocketBasicPacketTest: XCTestCase {
func testMultipleBinaryAck() { func testMultipleBinaryAck() {
let expectedSendString = "62-0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]" 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(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data2, data]) XCTAssertEqual(packet.binary, [data2, data])
@ -148,10 +148,10 @@ class SocketBasicPacketTest: XCTestCase {
func testBinaryStringPlaceholderInMessage() { func testBinaryStringPlaceholderInMessage() {
let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"_placeholder\":true,\"num\":1}]" let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"_placeholder\":true,\"num\":1}]"
let socket = SocketIOClient(socketURL: NSURL()) let socket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
socket.setTestable() socket.setTestable()
if case let .Right(packet) = socket.parseString(engineString) { if case let .right(packet) = socket.parseString(engineString) {
var packet = packet var packet = packet
XCTAssertEqual(packet.event, "test") XCTAssertEqual(packet.event, "test")
packet.addData(data) packet.addData(data)

View File

@ -15,8 +15,8 @@ class SocketEngineTest: XCTestCase {
override func setUp() { override func setUp() {
super.setUp() super.setUp()
client = SocketIOClient(socketURL: NSURL(string: "http://localhost")!) client = SocketIOClient(socketURL: URL(string: "http://localhost")!)
engine = SocketEngine(client: client, url: NSURL(string: "http://localhost")!, options: nil) engine = SocketEngine(client: client, url: URL(string: "http://localhost")!, options: nil)
client.setTestable() client.setTestable()
} }

View File

@ -10,13 +10,13 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketNamespacePacketTest: XCTestCase { class SocketNamespacePacketTest: XCTestCase {
let data = "test".data(using: NSUTF8StringEncoding)! let data = "test".data(using: String.Encoding.utf8)!
let data2 = "test2".data(using: NSUTF8StringEncoding)! let data2 = "test2".data(using: String.Encoding.utf8)!
func testEmpyEmit() { func testEmpyEmit() {
let expectedSendString = "2/swift,[\"test\"]" let expectedSendString = "2/swift,[\"test\"]"
let sendData = ["test"] let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -24,7 +24,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testNullEmit() { func testNullEmit() {
let expectedSendString = "2/swift,[\"test\",null]" let expectedSendString = "2/swift,[\"test\",null]"
let sendData = ["test", NSNull()] let sendData = ["test", NSNull()]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -32,7 +32,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testStringEmit() { func testStringEmit() {
let expectedSendString = "2/swift,[\"test\",\"foo bar\"]" let expectedSendString = "2/swift,[\"test\",\"foo bar\"]"
let sendData = ["test", "foo bar"] let sendData = ["test", "foo bar"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -40,7 +40,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testJSONEmit() { func testJSONEmit() {
let expectedSendString = "2/swift,[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let expectedSendString = "2/swift,[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
let sendData = ["test", ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]] let sendData = ["test", ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -48,7 +48,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testArrayEmit() { func testArrayEmit() {
let expectedSendString = "2/swift,[\"test\",[\"hello\",1,{\"test\":\"test\"}]]" let expectedSendString = "2/swift,[\"test\",[\"hello\",1,{\"test\":\"test\"}]]"
let sendData = ["test", ["hello", 1, ["test": "test"]]] let sendData = ["test", ["hello", 1, ["test": "test"]]]
let packet = SocketPacket.packetFromEmit(items: sendData, id: -1, nsp: "/swift", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -56,7 +56,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testBinaryEmit() { func testBinaryEmit() {
let expectedSendString = "51-/swift,[\"test\",{\"_placeholder\":true,\"num\":0}]" 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(sendData as [AnyObject], id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data]) XCTAssertEqual(packet.binary, [data])
@ -65,7 +65,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testMultipleBinaryEmit() { func testMultipleBinaryEmit() {
let expectedSendString = "52-/swift,[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]" 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(sendData, id: -1, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data, data2]) XCTAssertEqual(packet.binary, [data, data2])
@ -74,7 +74,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testEmitWithAck() { func testEmitWithAck() {
let expectedSendString = "2/swift,0[\"test\"]" let expectedSendString = "2/swift,0[\"test\"]"
let sendData = ["test"] let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: false) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -82,7 +82,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testEmitDataWithAck() { func testEmitDataWithAck() {
let expectedSendString = "51-/swift,0[\"test\",{\"_placeholder\":true,\"num\":0}]" 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(sendData as [AnyObject], id: 0, nsp: "/swift", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data]) XCTAssertEqual(packet.binary, [data])
@ -91,7 +91,7 @@ class SocketNamespacePacketTest: XCTestCase {
// Acks // Acks
func testEmptyAck() { func testEmptyAck() {
let expectedSendString = "3/swift,0[]" let expectedSendString = "3/swift,0[]"
let packet = SocketPacket.packetFromEmit(items: [], id: 0, nsp: "/swift", ack: true) let packet = SocketPacket.packetFromEmit([], id: 0, nsp: "/swift", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -99,7 +99,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testNullAck() { func testNullAck() {
let expectedSendString = "3/swift,0[null]" let expectedSendString = "3/swift,0[null]"
let sendData = [NSNull()] let sendData = [NSNull()]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/swift", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -107,7 +107,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testStringAck() { func testStringAck() {
let expectedSendString = "3/swift,0[\"test\"]" let expectedSendString = "3/swift,0[\"test\"]"
let sendData = ["test"] let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/swift", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -115,7 +115,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testJSONAck() { func testJSONAck() {
let expectedSendString = "3/swift,0[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let expectedSendString = "3/swift,0[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
let sendData = [["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]] let sendData = [["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]]
let packet = SocketPacket.packetFromEmit(items: sendData, id: 0, nsp: "/swift", ack: true) let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/swift", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
} }
@ -123,7 +123,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testBinaryAck() { func testBinaryAck() {
let expectedSendString = "61-/swift,0[{\"_placeholder\":true,\"num\":0}]" 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(sendData, id: 0, nsp: "/swift", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data]) XCTAssertEqual(packet.binary, [data])
@ -132,7 +132,7 @@ class SocketNamespacePacketTest: XCTestCase {
func testMultipleBinaryAck() { func testMultipleBinaryAck() {
let expectedSendString = "62-/swift,0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]" 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(sendData, id: 0, nsp: "/swift", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString) XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data2, data]) XCTAssertEqual(packet.binary, [data2, data])

View File

@ -46,7 +46,7 @@
- (void)testSocketManager { - (void)testSocketManager {
SocketClientManager* manager = [SocketClientManager sharedManager]; SocketClientManager* manager = [SocketClientManager sharedManager];
[manager addSocketWithSocket:self.socket labeledAs:@"test"]; [manager addSocket:self.socket labeledAs:@"test"];
[manager removeSocketWithLabel:@"test"]; [manager removeSocketWithLabel:@"test"];
} }

View File

@ -10,10 +10,10 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketParserTest: XCTestCase { class SocketParserTest: XCTestCase {
let testSocket = SocketIOClient(socketURL: NSURL()) let testSocket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
//Format key: message; namespace-data-binary-id //Format key: message; namespace-data-binary-id
static let packetTypes: [String: (String, [AnyObject], [NSData], Int)] = [ static let packetTypes: [String: (String, [AnyObject], [Data], Int)] = [
"0": ("/", [], [], -1), "1": ("/", [], [], -1), "0": ("/", [], [], -1), "1": ("/", [], [], -1),
"25[\"test\"]": ("/", ["test"], [], 5), "25[\"test\"]": ("/", ["test"], [], 5),
"2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1), "2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1),
@ -31,97 +31,97 @@ class SocketParserTest: XCTestCase {
func testDisconnect() { func testDisconnect() {
let message = "1" let message = "1"
validateParseResult(message: message) validateParseResult(message)
} }
func testConnect() { func testConnect() {
let message = "0" let message = "0"
validateParseResult(message: message) validateParseResult(message)
} }
func testDisconnectNameSpace() { func testDisconnectNameSpace() {
let message = "1/swift" let message = "1/swift"
validateParseResult(message: message) validateParseResult(message)
} }
func testConnecttNameSpace() { func testConnecttNameSpace() {
let message = "0/swift" let message = "0/swift"
validateParseResult(message: message) validateParseResult(message)
} }
func testIdEvent() { func testIdEvent() {
let message = "25[\"test\"]" let message = "25[\"test\"]"
validateParseResult(message: message) validateParseResult(message)
} }
func testBinaryPlaceholderAsString() { func testBinaryPlaceholderAsString() {
let message = "2[\"test\",\"~~0\"]" let message = "2[\"test\",\"~~0\"]"
validateParseResult(message: message) validateParseResult(message)
} }
func testNameSpaceArrayParse() { func testNameSpaceArrayParse() {
let message = "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]" let message = "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]"
validateParseResult(message: message) validateParseResult(message)
} }
func testNameSpaceArrayAckParse() { func testNameSpaceArrayAckParse() {
let message = "3/swift,0[[\"test3\",\"test4\"]]" let message = "3/swift,0[[\"test3\",\"test4\"]]"
validateParseResult(message: message) validateParseResult(message)
} }
func testNameSpaceBinaryEventParse() { func testNameSpaceBinaryEventParse() {
let message = "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]" let message = "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]"
validateParseResult(message: message) validateParseResult(message)
} }
func testNameSpaceBinaryAckParse() { func testNameSpaceBinaryAckParse() {
let message = "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]" let message = "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]"
validateParseResult(message: message) validateParseResult(message)
} }
func testNamespaceErrorParse() { func testNamespaceErrorParse() {
let message = "4/swift," let message = "4/swift,"
validateParseResult(message: message) validateParseResult(message)
} }
func testErrorTypeString() { func testErrorTypeString() {
let message = "4\"ERROR\"" let message = "4\"ERROR\""
validateParseResult(message: message) validateParseResult(message)
} }
func testErrorTypeDictionary() { func testErrorTypeDictionary() {
let message = "4{\"test\":2}" let message = "4{\"test\":2}"
validateParseResult(message: message) validateParseResult(message)
} }
func testErrorTypeInt() { func testErrorTypeInt() {
let message = "41" let message = "41"
validateParseResult(message: message) validateParseResult(message)
} }
func testInvalidInput() { func testInvalidInput() {
let message = "8" let message = "8"
switch testSocket.parseString(message) { switch testSocket.parseString(message) {
case .Left(_): case .left(_):
return return
case .Right(_): case .right(_):
XCTFail("Created packet when shouldn't have") XCTFail("Created packet when shouldn't have")
} }
} }
func testGenericParser() { func testGenericParser() {
var parser = SocketStringReader(message: "61-/swift,") var parser = SocketStringReader(message: "61-/swift,")
XCTAssertEqual(parser.read(length: 1), "6") XCTAssertEqual(parser.read(1), "6")
XCTAssertEqual(parser.currentCharacter, "1") XCTAssertEqual(parser.currentCharacter, "1")
XCTAssertEqual(parser.readUntilStringOccurence("-"), "1") XCTAssertEqual(parser.readUntilStringOccurence("-"), "1")
XCTAssertEqual(parser.currentCharacter, "/") XCTAssertEqual(parser.currentCharacter, "/")
} }
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.characters.index(message.startIndex, offsetBy: 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)
XCTAssertTrue((packet.data as NSArray).isEqual(to: validValues.1), "\(packet.data)") XCTAssertTrue((packet.data as NSArray).isEqual(to: validValues.1), "\(packet.data)")

View File

@ -10,13 +10,13 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketSideEffectTest: XCTestCase { class SocketSideEffectTest: XCTestCase {
let data = "test".data(using: NSUTF8StringEncoding)! let data = "test".data(using: String.Encoding.utf8)!
let data2 = "test2".data(using: NSUTF8StringEncoding)! let data2 = "test2".data(using: String.Encoding.utf8)!
private var socket: SocketIOClient! private var socket: SocketIOClient!
override func setUp() { override func setUp() {
super.setUp() super.setUp()
socket = SocketIOClient(socketURL: NSURL()) socket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
socket.setTestable() socket.setTestable()
} }
@ -55,7 +55,7 @@ class SocketSideEffectTest: XCTestCase {
} }
socket.parseSocketMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]") socket.parseSocketMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]")
socket.parseBinaryData(NSData()) socket.parseBinaryData(Data())
waitForExpectations(withTimeout: 3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
@ -83,7 +83,7 @@ class SocketSideEffectTest: XCTestCase {
func testHandleOnceEvent() { func testHandleOnceEvent() {
let expect = expectation(withDescription: "handled event") let expect = expectation(withDescription: "handled event")
socket.once(event: "test") {data, ack in socket.once("test") {data, ack in
XCTAssertEqual(data[0] as? String, "hello world") XCTAssertEqual(data[0] as? String, "hello world")
XCTAssertEqual(self.socket.testHandlers.count, 0) XCTAssertEqual(self.socket.testHandlers.count, 0)
expect.fulfill() expect.fulfill()
@ -140,7 +140,7 @@ class SocketSideEffectTest: XCTestCase {
func testSocketDataToAnyObject() { func testSocketDataToAnyObject() {
let data = ["test", 1, 2.2, ["Hello": 2, "bob": 2.2], true, [1, 2], [1.1, 2]] as [SocketData] let data = ["test", 1, 2.2, ["Hello": 2, "bob": 2.2], true, [1, 2], [1.1, 2]] as [SocketData]
XCTAssertEqual(data.count, socket.socketDataToAnyObject(data: data).count) XCTAssertEqual(data.count, socket.socketDataToAnyObject(data).count)
} }
func testHandleMultipleBinaryEvent() { func testHandleMultipleBinaryEvent() {

View File

@ -24,8 +24,8 @@
import Foundation import Foundation
extension NSCharacterSet { extension CharacterSet {
class var allowedURLCharacterSet: NSCharacterSet { static var allowedURLCharacterSet: CharacterSet {
return NSCharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]\" {}").inverted return CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]\" {}").inverted
} }
} }

View File

@ -36,7 +36,7 @@ public final class SocketAckEmitter : NSObject {
public func with(_ items: SocketData...) { public func with(_ items: SocketData...) {
guard ackNum != -1 else { return } guard ackNum != -1 else { return }
socket.emitAck(ackNum, with: socket.socketDataToAnyObject(data: items)) socket.emitAck(ackNum, with: socket.socketDataToAnyObject(items))
} }
public func with(_ items: [AnyObject]) { public func with(_ items: [AnyObject]) {

View File

@ -59,7 +59,7 @@ struct SocketAckManager {
mutating func executeAck(_ ack: Int, items: [AnyObject]) { mutating func executeAck(_ ack: Int, items: [AnyObject]) {
let callback = acks.remove(SocketAck(ack: ack)) let callback = acks.remove(SocketAck(ack: ack))
dispatch_async(dispatch_get_main_queue()) { DispatchQueue.main.async {
callback?.callback(items) callback?.callback(items)
} }
} }
@ -67,7 +67,7 @@ struct SocketAckManager {
mutating func timeoutAck(_ ack: Int) { mutating func timeoutAck(_ ack: Int) {
let callback = acks.remove(SocketAck(ack: ack)) let callback = acks.remove(SocketAck(ack: ack))
dispatch_async(dispatch_get_main_queue()) { DispatchQueue.main.async {
callback?.callback(["NO ACK"]) callback?.callback(["NO ACK"])
} }
} }

View File

@ -58,7 +58,7 @@ public final class SocketClientManager : NSObject {
} }
} }
public func addSocket(socket: SocketIOClient, labeledAs label: String) { public func addSocket(_ socket: SocketIOClient, labeledAs label: String) {
sockets[label] = socket sockets[label] = socket
} }
@ -66,7 +66,7 @@ public final class SocketClientManager : NSObject {
return sockets.removeValue(forKey: label) return sockets.removeValue(forKey: label)
} }
public func removeSocket(socket: SocketIOClient) -> SocketIOClient? { public func removeSocket(_ socket: SocketIOClient) -> SocketIOClient? {
var returnSocket: SocketIOClient? var returnSocket: SocketIOClient?
for (label, dictSocket) in sockets where dictSocket === socket { for (label, dictSocket) in sockets where dictSocket === socket {

View File

@ -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 = DispatchQueue(label: "com.socketio.engineEmitQueue", attributes: DispatchQueueAttributes.serial)
public let handleQueue = dispatch_queue_create("com.socketio.engineHandleQueue", DISPATCH_QUEUE_SERIAL)! public let handleQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: DispatchQueueAttributes.serial)
public let parseQueue = dispatch_queue_create("com.socketio.engineParseQueue", DISPATCH_QUEUE_SERIAL)! public let parseQueue = DispatchQueue(label: "com.socketio.engineParseQueue", attributes: DispatchQueueAttributes.serial)
public var connectParams: [String: AnyObject]? { public var connectParams: [String: AnyObject]? {
didSet { didSet {
@ -41,7 +41,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
public private(set) var closed = false public private(set) var closed = false
public private(set) var connected = false public private(set) var connected = false
public private(set) var cookies: [NSHTTPCookie]? public private(set) var cookies: [HTTPCookie]?
public private(set) var doubleEncodeUTF8 = true public private(set) var doubleEncodeUTF8 = true
public private(set) var extraHeaders: [String: String]? public private(set) var extraHeaders: [String: String]?
public private(set) var fastUpgrade = false public private(set) var fastUpgrade = false
@ -50,20 +50,20 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
public private(set) var invalidated = false public private(set) var invalidated = false
public private(set) var polling = true public private(set) var polling = true
public private(set) var probing = false public private(set) var probing = false
public private(set) var session: NSURLSession? public private(set) var session: URLSession?
public private(set) var sid = "" public private(set) var sid = ""
public private(set) var socketPath = "/engine.io/" public private(set) var socketPath = "/engine.io/"
public private(set) var urlPolling = NSURL() public private(set) var urlPolling = URL(string: "http://localhost/")!
public private(set) var urlWebSocket = NSURL() public private(set) var urlWebSocket = URL(string: "http://localhost/")!
public private(set) var websocket = false public private(set) var websocket = false
public private(set) var ws: WebSocket? public private(set) var ws: WebSocket?
public weak var client: SocketEngineClient? public weak var client: SocketEngineClient?
private weak var sessionDelegate: NSURLSessionDelegate? private weak var sessionDelegate: URLSessionDelegate?
private let logType = "SocketEngine" private let logType = "SocketEngine"
private let url: NSURL private let url: URL
private var pingInterval: Double? private var pingInterval: Double?
private var pingTimeout = 0.0 { private var pingTimeout = 0.0 {
@ -80,7 +80,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
private var selfSigned = false private var selfSigned = false
private var voipEnabled = false private var voipEnabled = false
public init(client: SocketEngineClient, url: NSURL, options: Set<SocketIOClientOption>) { public init(client: SocketEngineClient, url: URL, options: Set<SocketIOClientOption>) {
self.client = client self.client = client
self.url = url self.url = url
@ -120,7 +120,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
(urlPolling, urlWebSocket) = createURLs() (urlPolling, urlWebSocket) = createURLs()
} }
public convenience init(client: SocketEngineClient, url: NSURL, options: NSDictionary?) { public convenience init(client: SocketEngineClient, url: URL, options: NSDictionary?) {
self.init(client: client, url: url, options: options?.toSocketOptionsSet() ?? []) self.init(client: client, url: url, options: options?.toSocketOptionsSet() ?? [])
} }
@ -131,11 +131,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
private func checkAndHandleEngineError(_ msg: String) { private func checkAndHandleEngineError(_ msg: String) {
guard let stringData = msg.data(using: NSUTF8StringEncoding, guard let stringData = msg.data(using: String.Encoding.utf8,
allowLossyConversion: false) else { return } allowLossyConversion: false) else { return }
do { do {
if let dict = try NSJSONSerialization.jsonObject(with: stringData, options: .mutableContainers) as? NSDictionary { if let dict = try JSONSerialization.jsonObject(with: stringData, options: .mutableContainers) as? NSDictionary {
guard let error = dict["message"] as? String else { return } guard let error = dict["message"] as? String else { return }
/* /*
@ -144,10 +144,10 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
2: Bad handshake request 2: Bad handshake request
3: Bad request 3: Bad request
*/ */
didError(error: error) didError(error)
} }
} catch { } catch {
didError(error: "Got unknown error from server \(msg)") didError("Got unknown error from server \(msg)")
} }
} }
@ -156,7 +156,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
// binary in base64 string // binary in base64 string
let noPrefix = message[message.characters.index(message.startIndex, offsetBy: 2)..<message.endIndex] let noPrefix = message[message.characters.index(message.startIndex, offsetBy: 2)..<message.endIndex]
if let data = NSData(base64Encoded: noPrefix, options: .ignoreUnknownCharacters) { if let data = Data(base64Encoded: noPrefix, options: NSData.Base64EncodingOptions(rawValue: 0)) {
client?.parseEngineBinaryData(data) client?.parseEngineBinaryData(data)
} }
@ -180,7 +180,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
public func connect() { public func connect() {
if connected { 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: logType)
disconnect(reason: "reconnect") disconnect("reconnect")
} }
DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: logType, args: url) DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: logType, args: url)
@ -198,7 +198,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
let reqPolling = NSMutableURLRequest(url: urlPolling) let reqPolling = NSMutableURLRequest(url: urlPolling)
if cookies != nil { if cookies != nil {
let headers = NSHTTPCookie.requestHeaderFields(with: cookies!) let headers = HTTPCookie.requestHeaderFields(with: cookies!)
reqPolling.allHTTPHeaderFields = headers reqPolling.allHTTPHeaderFields = headers
} }
@ -208,18 +208,18 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
} }
dispatch_async(emitQueue) { (emitQueue).async {
self.doLongPoll(for: reqPolling) self.doLongPoll(for: reqPolling as URLRequest)
} }
} }
private func createURLs() -> (NSURL, NSURL) { private func createURLs() -> (URL, URL) {
if client == nil { if client == nil {
return (NSURL(), NSURL()) return (URL(string: "http://localhost/")!, URL(string: "http://localhost/")!)
} }
let urlPolling = NSURLComponents(string: url.absoluteString)! var urlPolling = URLComponents(string: url.absoluteString!)!
let urlWebSocket = NSURLComponents(string: url.absoluteString)! var urlWebSocket = URLComponents(string: url.absoluteString!)!
var queryString = "" var queryString = ""
urlWebSocket.path = socketPath urlWebSocket.path = socketPath
@ -252,7 +252,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
ws = WebSocket(url: urlWebSocketWithSid) ws = WebSocket(url: urlWebSocketWithSid)
if cookies != nil { if cookies != nil {
let headers = NSHTTPCookie.requestHeaderFields(with: cookies!) let headers = HTTPCookie.requestHeaderFields(with: cookies!)
for (key, value) in headers { for (key, value) in headers {
ws?.headers[key] = value ws?.headers[key] = value
} }
@ -273,20 +273,20 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
ws?.connect() ws?.connect()
} }
public func didError(error: String) { public func didError(_ error: String) {
DefaultSocketLogger.Logger.error("%@", type: logType, args: error) DefaultSocketLogger.Logger.error("%@", type: logType, args: error)
client?.engineDidError(reason: error) client?.engineDidError(error)
disconnect(reason: error) disconnect(error)
} }
public func disconnect(reason: String) { public func disconnect(_ reason: String) {
guard connected else { return closeOutEngine() } guard connected else { return closeOutEngine() }
DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType) DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType)
if closed { if closed {
closeOutEngine() closeOutEngine()
client?.engineDidClose(reason: reason) client?.engineDidClose(reason)
return return
} }
@ -301,7 +301,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
// We need to take special care when we're polling that we send it ASAP // We need to take special care when we're polling that we send it ASAP
// Also make sure we're on the emitQueue since we're touching postWait // Also make sure we're on the emitQueue since we're touching postWait
private func disconnectPolling() { private func disconnectPolling() {
dispatch_sync(emitQueue) { emitQueue.sync {
self.postWait.append(String(SocketEnginePacketType.close.rawValue)) self.postWait.append(String(SocketEnginePacketType.close.rawValue))
let req = self.createRequestForPostWithPostWait() let req = self.createRequestForPostWithPostWait()
self.doRequest(for: req) {_, _, _ in } self.doRequest(for: req) {_, _, _ in }
@ -326,7 +326,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
private func flushProbeWait() { private func flushProbeWait() {
DefaultSocketLogger.Logger.log("Flushing probe wait", type: logType) DefaultSocketLogger.Logger.log("Flushing probe wait", type: logType)
dispatch_async(emitQueue) { emitQueue.async {
for waiter in self.probeWait { for waiter in self.probeWait {
self.write(waiter.msg, withType: waiter.type, withData: waiter.data) self.write(waiter.msg, withType: waiter.type, withData: waiter.data)
} }
@ -345,14 +345,14 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
guard let ws = self.ws else { return } guard let ws = self.ws else { return }
for msg in postWait { for msg in postWait {
ws.writeString(str: msg) ws.writeString(msg)
} }
postWait.removeAll(keepingCapacity: true) postWait.removeAll(keepingCapacity: true)
} }
private func handleClose(reason: String) { private func handleClose(_ reason: String) {
client?.engineDidClose(reason: reason) client?.engineDidClose(reason)
} }
private func handleMessage(_ message: String) { private func handleMessage(_ message: String) {
@ -363,11 +363,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
doPoll() doPoll()
} }
private func handleOpen(openMessage: String) { private func handleOpen(_ openMessage: String) {
let mesData = openMessage.data(using: NSUTF8StringEncoding, allowLossyConversion: false)! let mesData = openMessage.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do { do {
let json = try NSJSONSerialization.jsonObject(with: mesData, let json = try JSONSerialization.jsonObject(with: mesData,
options: NSJSONReadingOptions.allowFragments) as? NSDictionary options: JSONSerialization.ReadingOptions.allowFragments) as? NSDictionary
if let sid = json?["sid"] as? String { if let sid = json?["sid"] as? String {
let upgradeWs: Bool let upgradeWs: Bool
@ -395,14 +395,14 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
doPoll() doPoll()
} }
client?.engineDidOpen(reason: "Connect") client?.engineDidOpen("Connect")
} }
} catch { } catch {
didError(error: "Error parsing open packet") didError("Error parsing open packet")
} }
} }
private func handlePong(pongMessage: String) { private func handlePong(_ pongMessage: String) {
pongsMissed = 0 pongsMissed = 0
// We should upgrade // We should upgrade
@ -411,9 +411,10 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
} }
public func parseEngineData(_ data: NSData) { public func parseEngineData(_ data: Data) {
DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data) DefaultSocketLogger.Logger.log("Got binary data: %@", type: "SocketEngine", args: data)
client?.parseEngineBinaryData(data.subdata(with: NSMakeRange(1, data.length - 1)))
client?.parseEngineBinaryData(data.subdata(in: Range<Int>(uncheckedBounds: (1, data.count - 1))))
} }
public func parseEngineMessage(_ message: String, fromPolling: Bool) { public func parseEngineMessage(_ message: String, fromPolling: Bool) {
@ -431,7 +432,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
if fromPolling && type != .noop && doubleEncodeUTF8 { if fromPolling && type != .noop && doubleEncodeUTF8 {
fixedString = fixDoubleUTF8(string: message) fixedString = fixDoubleUTF8(message)
} else { } else {
fixedString = message fixedString = message
} }
@ -443,12 +444,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
case .noop: case .noop:
handleNOOP() handleNOOP()
case .pong: case .pong:
handlePong(pongMessage: fixedString) handlePong(fixedString)
case .open: case .open:
handleOpen(openMessage: handleOpen(fixedString[fixedString.characters.index(after: fixedString.characters.startIndex)..<fixedString.endIndex])
fixedString[fixedString.characters.index(after: fixedString.characters.startIndex)..<fixedString.endIndex])
case .close: case .close:
handleClose(reason: fixedString) handleClose(fixedString)
default: default:
DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType) DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType)
} }
@ -462,9 +462,9 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
polling = true polling = true
probing = false probing = false
invalidated = false invalidated = false
session = NSURLSession(configuration: .default(), session = URLSession(configuration: .default(),
delegate: sessionDelegate, delegate: sessionDelegate,
delegateQueue: NSOperationQueue()) delegateQueue: OperationQueue())
sid = "" sid = ""
waitingForPoll = false waitingForPoll = false
waitingForPost = false waitingForPost = false
@ -478,7 +478,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
//Server is not responding //Server is not responding
if pongsMissed > pongsMissedMax { if pongsMissed > pongsMissedMax {
client?.engineDidClose(reason: "Ping timeout") client?.engineDidClose("Ping timeout")
return return
} }
@ -486,8 +486,8 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
pongsMissed += 1 pongsMissed += 1
write("", withType: .ping, withData: []) write("", withType: .ping, withData: [])
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(pingInterval * Double(NSEC_PER_SEC))) let time = DispatchTime.now() + Double(Int64(pingInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
dispatch_after(time, dispatch_get_main_queue()) {[weak self] in DispatchQueue.main.after(when: time) {[weak self] in
self?.sendPing() self?.sendPing()
} }
} }
@ -505,8 +505,8 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
/// Write a message, independent of transport. /// Write a message, independent of transport.
public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [NSData]) { public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) {
dispatch_async(emitQueue) { emitQueue.async {
guard self.connected else { return } guard self.connected else { return }
if self.websocket { if self.websocket {
@ -524,7 +524,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
// Delegate methods // Delegate methods
public func websocketDidConnect(socket: WebSocket) { public func websocketDidConnect(_ socket: WebSocket) {
if !forceWebsockets { if !forceWebsockets {
probing = true probing = true
probeWebSocket() probeWebSocket()
@ -535,11 +535,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
} }
} }
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) { public func websocketDidDisconnect(_ socket: WebSocket, error: NSError?) {
probing = false probing = false
if closed { if closed {
client?.engineDidClose(reason: "Disconnect") client?.engineDidClose("Disconnect")
return return
} }
@ -548,9 +548,9 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
websocket = false websocket = false
if let reason = error?.localizedDescription { if let reason = error?.localizedDescription {
didError(error: reason) didError(reason)
} else { } else {
client?.engineDidClose(reason: "Socket Disconnected") client?.engineDidClose("Socket Disconnected")
} }
} else { } else {
flushProbeWait() flushProbeWait()

View File

@ -26,9 +26,9 @@
import Foundation 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)
func engineDidOpen(reason: String) func engineDidOpen(_ reason: String)
func parseEngineMessage(_ msg: String) func parseEngineMessage(_ msg: String)
func parseEngineBinaryData(_ data: NSData) func parseEngineBinaryData(_ data: Data)
} }

View File

@ -30,7 +30,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
/// Holds strings waiting to be sent over polling. /// Holds strings waiting to be sent over polling.
/// You shouldn't need to mess with this. /// You shouldn't need to mess with this.
var postWait: [String] { get set } var postWait: [String] { get set }
var session: NSURLSession? { get } var session: URLSession? { get }
/// Because socket.io doesn't let you send two polling request at the same time /// Because socket.io doesn't let you send two polling request at the same time
/// we have to keep track if there's an outstanding poll /// we have to keep track if there's an outstanding poll
var waitingForPoll: Bool { get set } var waitingForPoll: Bool { get set }
@ -39,7 +39,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
var waitingForPost: Bool { get set } var waitingForPost: Bool { get set }
func doPoll() func doPoll()
func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [NSData]) func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data])
func stopPolling() func stopPolling()
} }
@ -47,7 +47,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
extension SocketEnginePollable { extension SocketEnginePollable {
private func addHeaders(for req: NSMutableURLRequest) { private func addHeaders(for req: NSMutableURLRequest) {
if cookies != nil { if cookies != nil {
let headers = NSHTTPCookie.requestHeaderFields(with: cookies!) let headers = HTTPCookie.requestHeaderFields(with: cookies!)
req.allHTTPHeaderFields = headers req.allHTTPHeaderFields = headers
} }
@ -58,7 +58,7 @@ extension SocketEnginePollable {
} }
} }
func createRequestForPostWithPostWait() -> NSURLRequest { func createRequestForPostWithPostWait() -> URLRequest {
var postStr = "" var postStr = ""
for packet in postWait { for packet in postWait {
@ -71,20 +71,20 @@ extension SocketEnginePollable {
postWait.removeAll(keepingCapacity: false) postWait.removeAll(keepingCapacity: false)
let req = NSMutableURLRequest(url: urlPollingWithSid) let req = NSMutableURLRequest(url: urlPollingWithSid as URL)
addHeaders(for: req) addHeaders(for: req)
req.httpMethod = "POST" req.httpMethod = "POST"
req.setValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type") req.setValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type")
let postData = postStr.data(using: NSUTF8StringEncoding, let postData = postStr.data(using: String.Encoding.utf8,
allowLossyConversion: false)! allowLossyConversion: false)!
req.httpBody = postData req.httpBody = postData
req.setValue(String(postData.length), forHTTPHeaderField: "Content-Length") req.setValue(String(postData.count), forHTTPHeaderField: "Content-Length")
return req return req as URLRequest
} }
public func doPoll() { public func doPoll() {
@ -93,13 +93,13 @@ extension SocketEnginePollable {
} }
waitingForPoll = true waitingForPoll = true
let req = NSMutableURLRequest(url: urlPollingWithSid) let req = NSMutableURLRequest(url: urlPollingWithSid as URL)
addHeaders(for: req) addHeaders(for: req)
doLongPoll(for: req) doLongPoll(for: req as URLRequest)
} }
func doRequest(for req: NSURLRequest, callbackWith callback: (NSData?, NSURLResponse?, NSError?) -> Void) { func doRequest(for req: URLRequest, callbackWith callback: (Data?, URLResponse?, NSError?) -> Void) {
if !polling || closed || invalidated || fastUpgrade { if !polling || closed || invalidated || fastUpgrade {
DefaultSocketLogger.Logger.error("Tried to do polling request when not supposed to", type: "SocketEnginePolling") DefaultSocketLogger.Logger.error("Tried to do polling request when not supposed to", type: "SocketEnginePolling")
return return
@ -110,7 +110,7 @@ extension SocketEnginePollable {
session?.dataTask(with: req, completionHandler: callback).resume() session?.dataTask(with: req, completionHandler: callback).resume()
} }
func doLongPoll(for req: NSURLRequest) { func doLongPoll(for req: URLRequest) {
doRequest(for: req) {[weak self] data, res, err in doRequest(for: req) {[weak self] data, res, err in
guard let this = self where this.polling else { return } guard let this = self where this.polling else { return }
@ -118,7 +118,7 @@ extension SocketEnginePollable {
DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling") DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling")
if this.polling { if this.polling {
this.didError(error: err?.localizedDescription ?? "Error") this.didError(err?.localizedDescription ?? "Error")
} }
return return
@ -126,8 +126,8 @@ extension SocketEnginePollable {
DefaultSocketLogger.Logger.log("Got polling response", type: "SocketEnginePolling") DefaultSocketLogger.Logger.log("Got polling response", type: "SocketEnginePolling")
if let str = String(data: data!, encoding: NSUTF8StringEncoding) { if let str = String(data: data!, encoding: String.Encoding.utf8) {
dispatch_async(this.parseQueue) { this.parseQueue.async {
this.parsePollingMessage(str) this.parsePollingMessage(str)
} }
} }
@ -163,7 +163,7 @@ extension SocketEnginePollable {
DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling") DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling")
if this.polling { if this.polling {
this.didError(error: err?.localizedDescription ?? "Error") this.didError(err?.localizedDescription ?? "Error")
} }
return return
@ -171,7 +171,7 @@ extension SocketEnginePollable {
this.waitingForPost = false this.waitingForPost = false
dispatch_async(this.emitQueue) { this.emitQueue.async {
if !this.fastUpgrade { if !this.fastUpgrade {
this.flushWaitingForPost() this.flushWaitingForPost()
this.doPoll() this.doPoll()
@ -187,13 +187,13 @@ extension SocketEnginePollable {
while reader.hasNext { while reader.hasNext {
if let n = Int(reader.readUntilStringOccurence(":")) { if let n = Int(reader.readUntilStringOccurence(":")) {
let str = reader.read(length: n) let str = reader.read(n)
dispatch_async(handleQueue) { (handleQueue).async {
self.parseEngineMessage(str, fromPolling: true) self.parseEngineMessage(str, fromPolling: true)
} }
} else { } else {
dispatch_async(handleQueue) { handleQueue.async {
self.parseEngineMessage(str, fromPolling: true) self.parseEngineMessage(str, fromPolling: true)
} }
break break
@ -203,12 +203,12 @@ extension SocketEnginePollable {
/// Send polling message. /// Send polling message.
/// Only call on emitQueue /// Only call on emitQueue
public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [NSData]) { public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) {
DefaultSocketLogger.Logger.log("Sending poll: %@ as type: %@", type: "SocketEnginePolling", args: message, type.rawValue) DefaultSocketLogger.Logger.log("Sending poll: %@ as type: %@", type: "SocketEnginePolling", args: message, type.rawValue)
let fixedMessage: String let fixedMessage: String
if doubleEncodeUTF8 { if doubleEncodeUTF8 {
fixedMessage = doubleEncodeUTF8(string: message) fixedMessage = doubleEncodeUTF8(message)
} else { } else {
fixedMessage = message fixedMessage = message
} }
@ -216,7 +216,7 @@ extension SocketEnginePollable {
postWait.append(String(type.rawValue) + fixedMessage) postWait.append(String(type.rawValue) + fixedMessage)
for data in datas { for data in datas {
if case let .Right(bin) = createBinaryDataForSend(using: data) { if case let .right(bin) = createBinaryDataForSend(using: data) {
postWait.append(bin) postWait.append(bin)
} }
} }

View File

@ -31,77 +31,77 @@ import Foundation
var connected: Bool { get } var connected: Bool { get }
var connectParams: [String: AnyObject]? { get set } var connectParams: [String: AnyObject]? { get set }
var doubleEncodeUTF8: Bool { get } var doubleEncodeUTF8: Bool { get }
var cookies: [NSHTTPCookie]? { get } var cookies: [HTTPCookie]? { get }
var extraHeaders: [String: String]? { get } var extraHeaders: [String: String]? { get }
var fastUpgrade: Bool { get } var fastUpgrade: Bool { get }
var forcePolling: Bool { get } var forcePolling: Bool { get }
var forceWebsockets: Bool { get } var forceWebsockets: Bool { get }
var parseQueue: dispatch_queue_t { get } var parseQueue: DispatchQueue { get }
var polling: Bool { get } var polling: Bool { get }
var probing: Bool { get } var probing: Bool { get }
var emitQueue: dispatch_queue_t { get } var emitQueue: DispatchQueue { get }
var handleQueue: dispatch_queue_t { get } var handleQueue: DispatchQueue { get }
var sid: String { get } var sid: String { get }
var socketPath: String { get } var socketPath: String { get }
var urlPolling: NSURL { get } var urlPolling: URL { get }
var urlWebSocket: NSURL { get } var urlWebSocket: URL { get }
var websocket: Bool { get } var websocket: Bool { get }
var ws: WebSocket? { get } var ws: WebSocket? { get }
init(client: SocketEngineClient, url: NSURL, options: NSDictionary?) init(client: SocketEngineClient, url: URL, options: NSDictionary?)
func connect() func connect()
func didError(error: String) func didError(_ error: String)
func disconnect(reason: String) func disconnect(_ reason: String)
func doFastUpgrade() func doFastUpgrade()
func flushWaitingForPostToWebSocket() func flushWaitingForPostToWebSocket()
func parseEngineData(_ data: NSData) func parseEngineData(_ data: Data)
func parseEngineMessage(_ message: String, fromPolling: Bool) func parseEngineMessage(_ message: String, fromPolling: Bool)
func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [NSData]) func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data])
} }
extension SocketEngineSpec { extension SocketEngineSpec {
var urlPollingWithSid: NSURL { var urlPollingWithSid: URL {
let com = NSURLComponents(url: urlPolling, resolvingAgainstBaseURL: false)! var com = URLComponents(url: urlPolling, resolvingAgainstBaseURL: false)!
com.percentEncodedQuery = com.percentEncodedQuery! + "&sid=\(sid.urlEncode()!)" com.percentEncodedQuery = com.percentEncodedQuery! + "&sid=\(sid.urlEncode()!)"
return com.url! return com.url!
} }
var urlWebSocketWithSid: NSURL { var urlWebSocketWithSid: URL {
let com = NSURLComponents(url: urlWebSocket, resolvingAgainstBaseURL: false)! var com = URLComponents(url: urlWebSocket, resolvingAgainstBaseURL: false)!
com.percentEncodedQuery = com.percentEncodedQuery! + (sid == "" ? "" : "&sid=\(sid.urlEncode()!)") com.percentEncodedQuery = com.percentEncodedQuery! + (sid == "" ? "" : "&sid=\(sid.urlEncode()!)")
return com.url! return com.url!
} }
func createBinaryDataForSend(using data: NSData) -> Either<NSData, String> { func createBinaryDataForSend(using data: Data) -> Either<Data, String> {
if websocket { if websocket {
var byteArray = [UInt8](repeating: 0x4, count: 1) var byteArray = [UInt8](repeating: 0x4, count: 1)
let mutData = NSMutableData(bytes: &byteArray, length: 1) let mutData = NSMutableData(bytes: &byteArray, length: 1)
mutData.append(data) mutData.append(data)
return .Left(mutData) return .left(mutData as Data)
} else { } else {
let str = "b4" + data.base64EncodedString(NSDataBase64EncodingOptions(rawValue: 0)) let str = "b4" + data.base64EncodedString(NSData.Base64EncodingOptions(rawValue: 0))
return .Right(str) return .right(str)
} }
} }
func doubleEncodeUTF8(string: String) -> String { func doubleEncodeUTF8(_ string: String) -> String {
if let latin1 = string.data(using: NSUTF8StringEncoding), if let latin1 = string.data(using: String.Encoding.utf8),
utf8 = NSString(data: latin1, encoding: NSISOLatin1StringEncoding) { utf8 = NSString(data: latin1, encoding: String.Encoding.isoLatin1.rawValue) {
return utf8 as String return utf8 as String
} else { } else {
return string return string
} }
} }
func fixDoubleUTF8(string: String) -> String { func fixDoubleUTF8(_ string: String) -> String {
if let utf8 = string.data(using: NSISOLatin1StringEncoding), if let utf8 = string.data(using: String.Encoding.isoLatin1),
latin1 = NSString(data: utf8, encoding: NSUTF8StringEncoding) { latin1 = NSString(data: utf8, encoding: String.Encoding.utf8.rawValue) {
return latin1 as String return latin1 as String
} else { } else {
return string return string
@ -109,7 +109,7 @@ extension SocketEngineSpec {
} }
/// Send an engine message (4) /// Send an engine message (4)
func send(_ msg: String, withData datas: [NSData]) { func send(_ msg: String, withData datas: [Data]) {
write(msg, withType: .message, withData: datas) write(msg, withType: .message, withData: datas)
} }
} }

View File

@ -27,7 +27,7 @@ import Foundation
/// Protocol that is used to implement socket.io WebSocket support /// Protocol that is used to implement socket.io WebSocket support
public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate { public protocol SocketEngineWebsocket : SocketEngineSpec, WebSocketDelegate {
func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [NSData]) func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data])
} }
// WebSocket methods // WebSocket methods
@ -40,23 +40,23 @@ extension SocketEngineWebsocket {
/// Send message on WebSockets /// Send message on WebSockets
/// Only call on emitQueue /// Only call on emitQueue
public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [NSData]) { public func sendWebSocketMessage(_ str: String, withType type: SocketEnginePacketType, withData datas: [Data]) {
DefaultSocketLogger.Logger.log("Sending ws: %@ as type: %@", type: "SocketEngine", args: str, type.rawValue) DefaultSocketLogger.Logger.log("Sending ws: %@ as type: %@", type: "SocketEngine", args: str, type.rawValue)
ws?.writeString(str: "\(type.rawValue)\(str)") ws?.writeString("\(type.rawValue)\(str)")
for data in datas { for data in datas {
if case let .Left(bin) = createBinaryDataForSend(using: data) { if case let .left(bin) = createBinaryDataForSend(using: data) {
ws?.writeData(data: bin) ws?.writeData(bin)
} }
} }
} }
public func websocketDidReceiveMessage(socket: WebSocket, text: String) { public func websocketDidReceiveMessage(_ socket: WebSocket, text: String) {
parseEngineMessage(text, fromPolling: false) parseEngineMessage(text, fromPolling: false)
} }
public func websocketDidReceiveData(socket: WebSocket, data: NSData) { public func websocketDidReceiveData(_ socket: WebSocket, data: Data) {
parseEngineData(data) parseEngineData(data)
} }
} }

View File

@ -26,10 +26,10 @@ import Foundation
struct SocketEventHandler { struct SocketEventHandler {
let event: String let event: String
let id: NSUUID let id: UUID
let callback: NormalCallback let callback: NormalCallback
func executeCallback(items: [AnyObject], withAck ack: Int, withSocket socket: SocketIOClient) { func executeCallback(_ items: [AnyObject], withAck ack: Int, withSocket socket: SocketIOClient) {
callback(items, SocketAckEmitter(socket: socket, ackNum: ack)) callback(items, SocketAckEmitter(socket: socket, ackNum: ack))
} }
} }

View File

@ -25,7 +25,7 @@
import Foundation import Foundation
public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable { public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable {
public let socketURL: NSURL public let socketURL: URL
public private(set) var engine: SocketEngineSpec? public private(set) var engine: SocketEngineSpec?
public private(set) var status = SocketIOClientStatus.notConnected { public private(set) var status = SocketIOClientStatus.notConnected {
@ -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 = DispatchQueue(label: "com.socketio.emitQueue", attributes: DispatchQueueAttributes.serial)
private let logType = "SocketIOClient" private let logType = "SocketIOClient"
private let parseQueue = dispatch_queue_create("com.socketio.parseQueue", DISPATCH_QUEUE_SERIAL)! private let parseQueue = DispatchQueue(label: "com.socketio.parseQueue", attributes: DispatchQueueAttributes.serial)
private var anyHandler: ((SocketAnyEvent) -> Void)? private var anyHandler: ((SocketAnyEvent) -> Void)?
private var currentReconnectAttempt = 0 private var currentReconnectAttempt = 0
@ -60,18 +60,18 @@ 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 = DispatchQueue.main
private(set) var reconnectAttempts = -1 private(set) var reconnectAttempts = -1
var waitingPackets = [SocketPacket]() var waitingPackets = [SocketPacket]()
/// Type safe way to create a new SocketIOClient. opts can be omitted /// Type safe way to create a new SocketIOClient. opts can be omitted
public init(socketURL: NSURL, options: Set<SocketIOClientOption> = []) { public init(socketURL: URL, options: Set<SocketIOClientOption> = []) {
self.options = options self.options = options
self.socketURL = socketURL self.socketURL = socketURL
if socketURL.absoluteString.hasPrefix("https://") { if ((socketURL.absoluteString?.hasPrefix("https://")) != nil) {
self.options.insertIgnore(element: .secure(true)) self.options.insertIgnore(.secure(true))
} }
for option in options { for option in options {
@ -97,20 +97,20 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
} }
} }
self.options.insertIgnore(element: .path("/socket.io/")) self.options.insertIgnore(.path("/socket.io/"))
super.init() super.init()
} }
/// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity. /// Not so type safe way to create a SocketIOClient, meant for Objective-C compatiblity.
/// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set<SocketIOClientOption>)` /// If using Swift it's recommended to use `init(socketURL: NSURL, options: Set<SocketIOClientOption>)`
public convenience init(socketURL: NSURL, options: NSDictionary?) { public convenience init(socketURL: URL, options: NSDictionary?) {
self.init(socketURL: socketURL, options: options?.toSocketOptionsSet() ?? []) self.init(socketURL: socketURL, options: options?.toSocketOptionsSet() ?? [])
} }
deinit { deinit {
DefaultSocketLogger.Logger.log("Client is being released", type: logType) DefaultSocketLogger.Logger.log("Client is being released", type: logType)
engine?.disconnect(reason: "Client Deinit") engine?.disconnect("Client Deinit")
} }
private func addEngine() -> SocketEngineSpec { private func addEngine() -> SocketEngineSpec {
@ -123,11 +123,11 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
/// Connect to the server. /// Connect to the server.
public func connect() { public func connect() {
connect(timeoutAfter: 0, handleWith: nil) connect(0, handleWith: nil)
} }
/// Connect to the server. If we aren't connected after timeoutAfter, call handler /// Connect to the server. If we aren't connected after timeoutAfter, call handler
public func connect(timeoutAfter: Int, handleWith handler: (() -> Void)?) { public func connect(_ timeoutAfter: Int, handleWith handler: (() -> Void)?) {
assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)") assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)")
guard status != .connected else { guard status != .connected else {
@ -145,30 +145,30 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
guard timeoutAfter != 0 else { return } guard timeoutAfter != 0 else { return }
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeoutAfter) * Int64(NSEC_PER_SEC)) let time = DispatchTime.now() + Double(Int64(timeoutAfter) * Int64(NSEC_PER_SEC)) / Double(NSEC_PER_SEC)
dispatch_after(time, handleQueue) {[weak self] in handleQueue.after(when: time) {[weak self] in
if let this = self where this.status != .connected && this.status != .disconnected { if let this = self where this.status != .connected && this.status != .disconnected {
this.status = .disconnected this.status = .disconnected
this.engine?.disconnect(reason: "Connect timeout") this.engine?.disconnect("Connect timeout")
handler?() handler?()
} }
} }
} }
private func createOnAck(items: [AnyObject]) -> OnAckCallback { private func createOnAck(_ items: [AnyObject]) -> OnAckCallback {
currentAck += 1 currentAck += 1
return {[weak self, ack = currentAck] timeout, callback in return {[weak self, ack = currentAck] timeout, callback in
if let this = self { if let this = self {
this.ackHandlers.addAck(ack, callback: callback) this.ackHandlers.addAck(ack, callback: callback)
this._emit(data: items, ack: ack) this._emit(items, ack: ack)
if timeout != 0 { if timeout != 0 {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * NSEC_PER_SEC)) let time = DispatchTime.now() + Double(Int64(timeout * NSEC_PER_SEC)) / Double(NSEC_PER_SEC)
dispatch_after(time, this.handleQueue) { this.handleQueue.after(when: time) {
this.ackHandlers.timeoutAck(ack) this.ackHandlers.timeoutAck(ack)
} }
} }
@ -185,7 +185,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
handleEvent("connect", data: [], isInternalMessage: false) handleEvent("connect", data: [], isInternalMessage: false)
} }
func didDisconnect(reason: String) { func didDisconnect(_ reason: String) {
guard status != .disconnected else { return } guard status != .disconnected else { return }
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason) DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
@ -193,7 +193,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
status = .disconnected status = .disconnected
// Make sure the engine is actually dead. // Make sure the engine is actually dead.
engine?.disconnect(reason: reason) engine?.disconnect(reason)
handleEvent("disconnect", data: [reason as AnyObject], isInternalMessage: true) handleEvent("disconnect", data: [reason as AnyObject], isInternalMessage: true)
} }
@ -203,12 +203,12 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
DefaultSocketLogger.Logger.log("Closing socket", type: logType) DefaultSocketLogger.Logger.log("Closing socket", type: logType)
didDisconnect(reason: "Disconnect") didDisconnect("Disconnect")
} }
/// Send a message to the server /// Send a message to the server
public func emit(_ event: String, _ items: SocketData...) { public func emit(_ event: String, _ items: SocketData...) {
emit(event, with: socketDataToAnyObject(data: items)) emit(event, with: socketDataToAnyObject(items))
} }
/// Same as emit, but meant for Objective-C /// Same as emit, but meant for Objective-C
@ -218,28 +218,28 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
return return
} }
_emit(data: [event as AnyObject] + items) _emit([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
/// an ack. /// an ack.
public func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback { public func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback {
return emitWithAck(event, with: socketDataToAnyObject(data: items)) return emitWithAck(event, with: socketDataToAnyObject(items))
} }
/// 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 as AnyObject] + items) return createOnAck([event as AnyObject] + items)
} }
private func _emit(data: [AnyObject], ack: Int? = nil) { private func _emit(_ data: [AnyObject], ack: Int? = nil) {
dispatch_async(emitQueue) { emitQueue.async {
guard self.status == .connected else { guard self.status == .connected else {
self.handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) self.handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true)
return return
} }
let packet = SocketPacket.packetFromEmit(items: data, id: ack ?? -1, nsp: self.nsp, ack: false) let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: self.nsp, ack: false)
let str = packet.packetString let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting: %@", type: self.logType, args: str) DefaultSocketLogger.Logger.log("Emitting: %@", type: self.logType, args: str)
@ -250,9 +250,9 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
// If the server wants to know that the client received data // If the server wants to know that the client received data
func emitAck(_ ack: Int, with items: [AnyObject]) { func emitAck(_ ack: Int, with items: [AnyObject]) {
dispatch_async(emitQueue) { emitQueue.async {
if self.status == .connected { if self.status == .connected {
let packet = SocketPacket.packetFromEmit(items: items, id: ack ?? -1, nsp: self.nsp, ack: true) let packet = SocketPacket.packetFromEmit(items, id: ack ?? -1, nsp: self.nsp, ack: true)
let str = packet.packetString let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: self.logType, args: str) DefaultSocketLogger.Logger.log("Emitting Ack: %@", type: self.logType, args: str)
@ -262,7 +262,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
} }
} }
public func engineDidClose(reason: String) { public func engineDidClose(_ reason: String) {
waitingPackets.removeAll() waitingPackets.removeAll()
if status != .disconnected { if status != .disconnected {
@ -270,21 +270,21 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
} }
if status == .disconnected || !reconnects { if status == .disconnected || !reconnects {
didDisconnect(reason: reason) didDisconnect(reason)
} else if !reconnecting { } else if !reconnecting {
reconnecting = true reconnecting = true
tryReconnect(reason: reason) tryReconnect(reason)
} }
} }
/// error /// error
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 as AnyObject], isInternalMessage: true) handleEvent("error", data: [reason as AnyObject], isInternalMessage: true)
} }
public func engineDidOpen(reason: String) { public func engineDidOpen(_ reason: String) {
DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient") DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient")
} }
@ -303,11 +303,11 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "") DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "")
dispatch_async(handleQueue) { handleQueue.async {
self.anyHandler?(SocketAnyEvent(event: event, items: data)) self.anyHandler?(SocketAnyEvent(event: event, items: data))
for handler in self.handlers where handler.event == event { for handler in self.handlers where handler.event == event {
handler.executeCallback(items: data, withAck: ack, withSocket: self) handler.executeCallback(data, withAck: ack, withSocket: self)
} }
} }
} }
@ -338,7 +338,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
} }
/// 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: UUID) {
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 })
@ -347,22 +347,22 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
/// Adds a handler for an event. /// Adds a handler for an event.
/// Returns: A unique id for the handler /// Returns: A unique id for the handler
@discardableResult @discardableResult
public func on(_ event: String, callback: NormalCallback) -> NSUUID { public func on(_ event: String, callback: NormalCallback) -> UUID {
DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event) DefaultSocketLogger.Logger.log("Adding handler for event: %@", type: logType, args: event)
let handler = SocketEventHandler(event: event, id: NSUUID(), callback: callback) let handler = SocketEventHandler(event: event, id: UUID(), callback: callback)
handlers.append(handler) handlers.append(handler)
return handler.id return handler.id as UUID
} }
/// Adds a single-use handler for an event. /// Adds a single-use handler for an event.
/// Returns: A unique id for the handler /// Returns: A unique id for the handler
@discardableResult @discardableResult
public func once(event: String, callback: NormalCallback) -> NSUUID { public func once(_ event: String, callback: NormalCallback) -> UUID {
DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event) DefaultSocketLogger.Logger.log("Adding once handler for event: %@", type: logType, args: event)
let id = NSUUID() let id = UUID()
let handler = SocketEventHandler(event: event, id: id) {[weak self] data, ack in let handler = SocketEventHandler(event: event, id: id) {[weak self] data, ack in
guard let this = self else { return } guard let this = self else { return }
@ -372,24 +372,24 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
handlers.append(handler) handlers.append(handler)
return handler.id return handler.id as UUID
} }
/// Adds a handler that will be called on every event. /// Adds a handler that will be called on every event.
public func onAny(handler: (SocketAnyEvent) -> Void) { public func onAny(_ handler: (SocketAnyEvent) -> Void) {
anyHandler = handler anyHandler = handler
} }
public func parseEngineMessage(_ msg: String) { public func parseEngineMessage(_ msg: String) {
DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg) DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg)
dispatch_async(parseQueue) { parseQueue.async {
self.parseSocketMessage(msg) self.parseSocketMessage(msg)
} }
} }
public func parseEngineBinaryData(_ data: NSData) { public func parseEngineBinaryData(_ data: Data) {
dispatch_async(parseQueue) { parseQueue.async {
self.parseBinaryData(data) self.parseBinaryData(data)
} }
} }
@ -398,7 +398,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
public func reconnect() { public func reconnect() {
guard !reconnecting else { return } guard !reconnecting else { return }
engine?.disconnect(reason: "manual reconnect") engine?.disconnect("manual reconnect")
} }
/// Removes all handlers. /// Removes all handlers.
@ -407,11 +407,11 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
handlers.removeAll(keepingCapacity: false) handlers.removeAll(keepingCapacity: false)
} }
func socketDataToAnyObject(data: [SocketData]) -> [AnyObject] { func socketDataToAnyObject(_ data: [SocketData]) -> [AnyObject] {
return data.flatMap({$0 as? AnyObject}) return data.flatMap({$0 as? AnyObject})
} }
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 as AnyObject], isInternalMessage: true) handleEvent("reconnect", data: [reason as AnyObject], isInternalMessage: true)
@ -426,7 +426,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
} }
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects { if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects {
return didDisconnect(reason: "Reconnect Failed") return didDisconnect("Reconnect Failed")
} }
DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType) DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType)
@ -436,9 +436,9 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
currentReconnectAttempt += 1 currentReconnectAttempt += 1
connect() connect()
let dispatchAfter = dispatch_time(DISPATCH_TIME_NOW, Int64(UInt64(reconnectWait) * NSEC_PER_SEC)) let dispatchAfter = DispatchTime.now() + Double(Int64(UInt64(reconnectWait) * NSEC_PER_SEC)) / Double(NSEC_PER_SEC)
dispatch_after(dispatchAfter, dispatch_get_main_queue(), _tryReconnect) DispatchQueue.main.after(when: dispatchAfter, execute: _tryReconnect)
} }
} }
@ -452,11 +452,11 @@ extension SocketIOClient {
status = .connected status = .connected
} }
func setTestEngine(engine: SocketEngineSpec?) { func setTestEngine(_ engine: SocketEngineSpec?) {
self.engine = engine self.engine = engine
} }
func emitTest(event: String, _ data: AnyObject...) { func emitTest(_ event: String, _ data: AnyObject...) {
self._emit(data: [event as AnyObject] + data) self._emit([event as AnyObject] + data)
} }
} }

View File

@ -30,13 +30,13 @@ protocol ClientOption : CustomStringConvertible, Hashable {
public enum SocketIOClientOption : ClientOption { public enum SocketIOClientOption : ClientOption {
case connectParams([String: AnyObject]) case connectParams([String: AnyObject])
case cookies([NSHTTPCookie]) case cookies([HTTPCookie])
case doubleEncodeUTF8(Bool) case doubleEncodeUTF8(Bool)
case extraHeaders([String: String]) case extraHeaders([String: String])
case forceNew(Bool) case forceNew(Bool)
case forcePolling(Bool) case forcePolling(Bool)
case forceWebsockets(Bool) case forceWebsockets(Bool)
case handleQueue(dispatch_queue_t) case handleQueue(DispatchQueue)
case log(Bool) case log(Bool)
case logger(SocketLogger) case logger(SocketLogger)
case nsp(String) case nsp(String)
@ -47,7 +47,7 @@ public enum SocketIOClientOption : ClientOption {
case secure(Bool) case secure(Bool)
case security(SSLSecurity) case security(SSLSecurity)
case selfSigned(Bool) case selfSigned(Bool)
case sessionDelegate(NSURLSessionDelegate) case sessionDelegate(URLSessionDelegate)
case voipEnabled(Bool) case voipEnabled(Bool)
public var description: String { public var description: String {
@ -158,7 +158,7 @@ public func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool {
} }
extension Set where Element : ClientOption { extension Set where Element : ClientOption {
mutating func insertIgnore(element: Element) { mutating func insertIgnore(_ element: Element) {
if !contains(element) { if !contains(element) {
insert(element) insert(element)
} }
@ -166,11 +166,11 @@ extension Set where Element : ClientOption {
} }
extension NSDictionary { extension NSDictionary {
private static func keyValueToSocketIOClientOption(key: String, value: AnyObject) -> SocketIOClientOption? { private static func keyValueToSocketIOClientOption(_ key: String, value: AnyObject) -> SocketIOClientOption? {
switch (key, value) { switch (key, value) {
case let ("connectParams", params as [String: AnyObject]): case let ("connectParams", params as [String: AnyObject]):
return .connectParams(params) return .connectParams(params)
case let ("cookies", cookies as [NSHTTPCookie]): case let ("cookies", cookies as [HTTPCookie]):
return .cookies(cookies) return .cookies(cookies)
case let ("doubleEncodeUTF8", encode as Bool): case let ("doubleEncodeUTF8", encode as Bool):
return .doubleEncodeUTF8(encode) return .doubleEncodeUTF8(encode)
@ -182,7 +182,7 @@ extension NSDictionary {
return .forcePolling(force) return .forcePolling(force)
case let ("forceWebsockets", force as Bool): case let ("forceWebsockets", force as Bool):
return .forceWebsockets(force) return .forceWebsockets(force)
case let ("handleQueue", queue as dispatch_queue_t): case let ("handleQueue", queue as DispatchQueue):
return .handleQueue(queue) return .handleQueue(queue)
case let ("log", log as Bool): case let ("log", log as Bool):
return .log(log) return .log(log)
@ -204,7 +204,7 @@ extension NSDictionary {
return .security(security) return .security(security)
case let ("selfSigned", selfSigned as Bool): case let ("selfSigned", selfSigned as Bool):
return .selfSigned(selfSigned) return .selfSigned(selfSigned)
case let ("sessionDelegate", delegate as NSURLSessionDelegate): case let ("sessionDelegate", delegate as URLSessionDelegate):
return .sessionDelegate(delegate) return .sessionDelegate(delegate)
case let ("voipEnabled", enable as Bool): case let ("voipEnabled", enable as Bool):
return .voipEnabled(enable) return .voipEnabled(enable)
@ -217,8 +217,8 @@ extension NSDictionary {
var options = Set<SocketIOClientOption>() var options = Set<SocketIOClientOption>()
for (rawKey, value) in self { for (rawKey, value) in self {
if let key = rawKey as? String, opt = NSDictionary.keyValueToSocketIOClientOption(key: key, value: value) { if let key = rawKey as? String, opt = NSDictionary.keyValueToSocketIOClientOption(key, value: value) {
options.insertIgnore(element: opt) options.insertIgnore(opt)
} }
} }

View File

@ -27,15 +27,15 @@ protocol SocketIOClientSpec : class {
var waitingPackets: [SocketPacket] { get set } var waitingPackets: [SocketPacket] { get set }
func didConnect() func didConnect()
func didDisconnect(reason: String) func didDisconnect(_ reason: String)
func didError(reason: String) func didError(_ reason: String)
func handleAck(_ ack: Int, data: [AnyObject]) func handleAck(_ ack: Int, data: [AnyObject])
func handleEvent(_ event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int) func handleEvent(_ event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int)
func joinNamespace(_ namespace: String) func joinNamespace(_ namespace: String)
} }
extension SocketIOClientSpec { 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 as AnyObject], isInternalMessage: true, withAck: -1) handleEvent("error", data: [reason as AnyObject], isInternalMessage: true, withAck: -1)

View File

@ -35,18 +35,18 @@ struct SocketPacket {
let type: PacketType let type: PacketType
enum PacketType: Int { enum PacketType: Int {
case Connect, Disconnect, Event, Ack, Error, BinaryEvent, BinaryAck case connect, disconnect, event, ack, error, binaryEvent, binaryAck
} }
var args: [AnyObject] { var args: [AnyObject] {
if type == .Event || type == .BinaryEvent && data.count != 0 { if type == .event || type == .binaryEvent && data.count != 0 {
return Array(data.dropFirst()) return Array(data.dropFirst())
} else { } else {
return data return data
} }
} }
var binary: [NSData] var binary: [Data]
var data: [AnyObject] var data: [AnyObject]
var description: String { var description: String {
return "SocketPacket {type: \(String(type.rawValue)); data: " + return "SocketPacket {type: \(String(type.rawValue)); data: " +
@ -62,7 +62,7 @@ struct SocketPacket {
} }
init(type: 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: [Data] = [Data]()) {
self.data = data self.data = data
self.id = id self.id = id
self.nsp = nsp self.nsp = nsp
@ -71,7 +71,7 @@ struct SocketPacket {
self.binary = binary self.binary = binary
} }
mutating func addData(_ data: NSData) -> Bool { mutating func addData(_ data: Data) -> Bool {
if placeholders == binary.count { if placeholders == binary.count {
return true return true
} }
@ -94,9 +94,9 @@ struct SocketPacket {
} }
do { do {
let jsonSend = try NSJSONSerialization.data(withJSONObject: data as AnyObject, let jsonSend = try JSONSerialization.data(withJSONObject: data as AnyObject,
options: NSJSONWritingOptions(rawValue: 0)) options: JSONSerialization.WritingOptions(rawValue: 0))
guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else { guard let jsonString = String(data: jsonSend, encoding: String.Encoding.utf8) else {
return message + "[]" return message + "[]"
} }
@ -117,7 +117,7 @@ struct SocketPacket {
let nspString: String let nspString: String
let idString: String let idString: String
if type == .BinaryEvent || type == .BinaryAck { if type == .binaryEvent || type == .binaryAck {
binaryCountString = typeString + String(binary.count) + "-" binaryCountString = typeString + String(binary.count) + "-"
} else { } else {
binaryCountString = typeString binaryCountString = typeString
@ -172,19 +172,19 @@ 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
case 0 where ack: case 0 where ack:
return .Ack return .ack
case _ where !ack: case _ where !ack:
return .BinaryEvent return .binaryEvent
case _ where ack: case _ where ack:
return .BinaryAck return .binaryAck
default: default:
return .Error return .error
} }
} }
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(binary.count, ack: ack), data: parsedData, let packet = SocketPacket(type: findType(binary.count, ack: ack), data: parsedData,
id: id, nsp: nsp, binary: binary) id: id, nsp: nsp, binary: binary)
@ -195,11 +195,11 @@ 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 [Data]) -> AnyObject {
let placeholder = ["_placeholder": true, "num": binary.count as AnyObject] let placeholder = ["_placeholder": true, "num": binary.count as AnyObject]
switch data { switch data {
case let bin as NSData: case let bin as Data:
binary.append(bin) binary.append(bin)
return placeholder as AnyObject return placeholder as AnyObject
case let arr as [AnyObject]: case let arr as [AnyObject]:
@ -216,8 +216,8 @@ private extension SocketPacket {
// Removes binary data from emit data // Removes binary data from emit data
// Returns a type containing the de-binaryed data and the binary // Returns a type containing the de-binaryed data and the binary
static func deconstructData(_ data: [AnyObject]) -> ([AnyObject], [NSData]) { static func deconstructData(_ data: [AnyObject]) -> ([AnyObject], [Data]) {
var binary = [NSData]() var binary = [Data]()
return (data.map({shred($0, binary: &binary)}), binary) return (data.map({shred($0, binary: &binary)}), binary)
} }

View File

@ -23,7 +23,7 @@
import Foundation import Foundation
protocol SocketParsable : SocketIOClientSpec { protocol SocketParsable : SocketIOClientSpec {
func parseBinaryData(_ data: NSData) func parseBinaryData(_ data: Data)
func parseSocketMessage(_ message: String) func parseSocketMessage(_ message: String)
} }
@ -42,19 +42,19 @@ extension SocketParsable {
private func handlePacket(_ pack: SocketPacket) { private func handlePacket(_ pack: SocketPacket) {
switch pack.type { switch pack.type {
case .Event where isCorrectNamespace(pack.nsp): case .event where isCorrectNamespace(pack.nsp):
handleEvent(pack.event, data: pack.args, isInternalMessage: false, withAck: pack.id) handleEvent(pack.event, data: pack.args, isInternalMessage: false, withAck: pack.id)
case .Ack where isCorrectNamespace(pack.nsp): case .ack where isCorrectNamespace(pack.nsp):
handleAck(pack.id, data: pack.data) handleAck(pack.id, data: pack.data)
case .BinaryEvent where isCorrectNamespace(pack.nsp): case .binaryEvent where isCorrectNamespace(pack.nsp):
waitingPackets.append(pack) waitingPackets.append(pack)
case .BinaryAck where isCorrectNamespace(pack.nsp): case .binaryAck where isCorrectNamespace(pack.nsp):
waitingPackets.append(pack) waitingPackets.append(pack)
case .Connect: case .connect:
handleConnect(pack) handleConnect(pack)
case .Disconnect: case .disconnect:
didDisconnect(reason: "Got Disconnect") didDisconnect("Got Disconnect")
case .Error: case .error:
handleEvent("error", data: pack.data, isInternalMessage: true, withAck: pack.id) handleEvent("error", data: pack.data, isInternalMessage: true, withAck: pack.id)
default: default:
DefaultSocketLogger.Logger.log("Got invalid packet: %@", type: "SocketParser", args: pack.description) DefaultSocketLogger.Logger.log("Got invalid packet: %@", type: "SocketParser", args: pack.description)
@ -65,22 +65,22 @@ extension SocketParsable {
func parseString(_ message: String) -> Either<String, SocketPacket> { func parseString(_ message: String) -> Either<String, SocketPacket> {
var parser = SocketStringReader(message: message) var parser = SocketStringReader(message: message)
guard let type = SocketPacket.PacketType(rawValue: Int(parser.read(length: 1)) ?? -1) else { guard let type = SocketPacket.PacketType(rawValue: Int(parser.read(1)) ?? -1) else {
return .Left("Invalid packet type") return .left("Invalid packet type")
} }
if !parser.hasNext { if !parser.hasNext {
return .Right(SocketPacket(type: type, nsp: "/")) return .right(SocketPacket(type: type, nsp: "/"))
} }
var namespace = "/" var namespace = "/"
var placeholders = -1 var placeholders = -1
if type == .BinaryEvent || type == .BinaryAck { if type == .binaryEvent || type == .binaryAck {
if let holders = Int(parser.readUntilStringOccurence("-")) { if let holders = Int(parser.readUntilStringOccurence("-")) {
placeholders = holders placeholders = holders
} else { } else {
return .Left("Invalid packet") return .left("Invalid packet")
} }
} }
@ -89,53 +89,53 @@ extension SocketParsable {
} }
if !parser.hasNext { if !parser.hasNext {
return .Right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders)) return .right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
} }
var idString = "" var idString = ""
if type == .Error { if type == .error {
parser.advance(by: -1) parser.advance(-1)
} else { } else {
while parser.hasNext { while parser.hasNext {
if let int = Int(parser.read(length: 1)) { if let int = Int(parser.read(1)) {
idString += String(int) idString += String(int)
} else { } else {
parser.advance(by: -2) parser.advance(-2)
break break
} }
} }
} }
let d = message[parser.advance(by: 1)..<message.endIndex] let d = message[parser.advance(1)..<message.endIndex]
switch parseData(d) { switch parseData(d) {
case let .Left(err): case let .left(err):
// Errors aren't always enclosed in an array // Errors aren't always enclosed in an array
if case let .Right(data) = parseData("\([d as AnyObject])") { if case let .right(data) = parseData("\([d as AnyObject])") {
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, return .right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: namespace, placeholders: placeholders)) nsp: namespace, placeholders: placeholders))
} else { } else {
return .Left(err) return .left(err)
} }
case let .Right(data): case let .right(data):
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, return .right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: namespace, placeholders: placeholders)) nsp: namespace, placeholders: placeholders))
} }
} }
// Parses data for events // Parses data for events
private func parseData(_ data: String) -> Either<String, [AnyObject]> { private func parseData(_ data: String) -> Either<String, [AnyObject]> {
let stringData = data.data(using: NSUTF8StringEncoding, allowLossyConversion: false) let stringData = data.data(using: String.Encoding.utf8, allowLossyConversion: false)
do { do {
if let arr = try NSJSONSerialization.jsonObject(with: stringData!, if let arr = try JSONSerialization.jsonObject(with: stringData!,
options: NSJSONReadingOptions.mutableContainers) as? [AnyObject] { options: JSONSerialization.ReadingOptions.mutableContainers) as? [AnyObject] {
return .Right(arr) return .right(arr)
} else { } else {
return .Left("Expected data array") return .left("Expected data array")
} }
} catch { } catch {
return .Left("Error parsing data for packet") return .left("Error parsing data for packet")
} }
} }
@ -146,15 +146,15 @@ extension SocketParsable {
DefaultSocketLogger.Logger.log("Parsing %@", type: "SocketParser", args: message) DefaultSocketLogger.Logger.log("Parsing %@", type: "SocketParser", args: message)
switch parseString(message) { switch parseString(message) {
case let .Left(err): case let .left(err):
DefaultSocketLogger.Logger.error("\(err): %@", type: "SocketParser", args: message) DefaultSocketLogger.Logger.error("\(err): %@", type: "SocketParser", args: message)
case let .Right(pack): case let .right(pack):
DefaultSocketLogger.Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description) DefaultSocketLogger.Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description)
handlePacket(pack) handlePacket(pack)
} }
} }
func parseBinaryData(_ data: NSData) { func parseBinaryData(_ data: Data) {
guard !waitingPackets.isEmpty else { guard !waitingPackets.isEmpty else {
DefaultSocketLogger.Logger.error("Got data when not remaking packet", type: "SocketParser") DefaultSocketLogger.Logger.error("Got data when not remaking packet", type: "SocketParser")
return return
@ -165,7 +165,7 @@ extension SocketParsable {
let packet = waitingPackets.removeLast() let packet = waitingPackets.removeLast()
if packet.type != .BinaryAck { if packet.type != .binaryAck {
handleEvent(packet.event, data: packet.args ?? [], handleEvent(packet.event, data: packet.args ?? [],
isInternalMessage: false, withAck: packet.id) isInternalMessage: false, withAck: packet.id)
} else { } else {

View File

@ -39,15 +39,15 @@ struct SocketStringReader {
} }
@discardableResult @discardableResult
mutating func advance(by: Int) -> String.Index { mutating func advance(_ by: Int) -> String.Index {
currentIndex = message.characters.index(currentIndex, offsetBy: by) currentIndex = message.characters.index(currentIndex, offsetBy: by)
return currentIndex return currentIndex
} }
mutating func read(length: Int) -> String { mutating func read(_ length: Int) -> String {
let readString = message[currentIndex..<message.characters.index(currentIndex, offsetBy: length)] let readString = message[currentIndex..<message.characters.index(currentIndex, offsetBy: length)]
advance(by: length) advance(length)
return readString return readString
} }
@ -60,12 +60,12 @@ struct SocketStringReader {
return substring return substring
} }
advance(by: message.characters.distance(from: message.characters.startIndex, to: foundRange.lowerBound) + 1) advance(message.characters.distance(from: message.characters.startIndex, to: foundRange.lowerBound) + 1)
return substring.substring(to: foundRange.lowerBound) return substring.substring(to: foundRange.lowerBound)
} }
mutating func readUntilEnd() -> String { mutating func readUntilEnd() -> String {
return read(length: message.characters.distance(from: currentIndex, to: message.endIndex)) return read(message.characters.distance(from: currentIndex, to: message.endIndex))
} }
} }

View File

@ -32,7 +32,7 @@ extension Dictionary : SocketData {}
extension Double : SocketData {} extension Double : SocketData {}
extension Int : SocketData {} extension Int : SocketData {}
extension NSArray : SocketData {} extension NSArray : SocketData {}
extension NSData : SocketData {} extension Data : SocketData {}
extension NSDictionary : SocketData {} extension NSDictionary : SocketData {}
extension NSString : SocketData {} extension NSString : SocketData {}
extension NSNull : SocketData {} extension NSNull : SocketData {}
@ -42,10 +42,10 @@ 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 Probe = (msg: String, type: SocketEnginePacketType, data: [Data])
typealias ProbeWaitQueue = [Probe] typealias ProbeWaitQueue = [Probe]
enum Either<E, V> { enum Either<E, V> {
case Left(E) case left(E)
case Right(V) case right(V)
} }

View File

@ -24,7 +24,7 @@ import Foundation
import Security import Security
public class SSLCert : NSObject { public class SSLCert : NSObject {
var certData: NSData? var certData: Data?
var key: SecKey? var key: SecKey?
/** /**
@ -34,7 +34,7 @@ public class SSLCert : NSObject {
- returns: a representation security object to be used with - returns: a representation security object to be used with
*/ */
public init(data: NSData) { public init(data: Data) {
self.certData = data self.certData = data
} }
@ -54,7 +54,7 @@ public class SSLSecurity : NSObject {
public var validatedDN = true //should the domain name be validated? public var validatedDN = true //should the domain name be validated?
var isReady = false //is the key processing done? var isReady = false //is the key processing done?
var certificates: [NSData]? //the certificates var certificates: [Data]? //the certificates
var pubKeys: [SecKey]? //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?
@ -66,12 +66,12 @@ public class SSLSecurity : NSObject {
- 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.main().pathsForResources(ofType: "cer", inDirectory: ".") let paths = Bundle.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
if let data = NSData(contentsOfFile: path) { if let data = NSData(contentsOfFile: path) {
certs.append(SSLCert(data: data)) certs.append(SSLCert(data: data as Data))
} }
return certs return certs
} }
@ -93,11 +93,11 @@ public class SSLSecurity : NSObject {
self.usePublicKeys = usePublicKeys self.usePublicKeys = usePublicKeys
if self.usePublicKeys { if self.usePublicKeys {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)) { DispatchQueue.global(attributes: DispatchQueue.GlobalAttributes.qosDefault).async {
let pubKeys = certs.reduce([SecKey]()) { (pubKeys: [SecKey], cert: SSLCert) -> [SecKey] 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: data) cert.key = self.extractPublicKey(data)
} }
if let key = cert.key { if let key = cert.key {
pubKeys.append(key) pubKeys.append(key)
@ -109,7 +109,7 @@ public class SSLSecurity : NSObject {
self.isReady = true self.isReady = true
} }
} else { } else {
let certificates = certs.reduce([NSData]()) { (certificates: [NSData], cert: SSLCert) -> [NSData] in let certificates = certs.reduce([Data]()) { (certificates: [Data], cert: SSLCert) -> [Data] in
var certificates = certificates var certificates = certificates
if let data = cert.certData { if let data = cert.certData {
certificates.append(data) certificates.append(data)
@ -129,7 +129,7 @@ public class SSLSecurity : NSObject {
- returns: if the key was successfully validated - returns: if the key was successfully validated
*/ */
public func isValid(trust: SecTrust, domain: String?) -> Bool { public func isValid(_ trust: SecTrust, domain: String?) -> Bool {
var tries = 0 var tries = 0
while(!self.isReady) { while(!self.isReady) {
@ -141,14 +141,14 @@ public class SSLSecurity : NSObject {
} }
var policy: SecPolicy var policy: SecPolicy
if self.validatedDN { if self.validatedDN {
policy = SecPolicyCreateSSL(true, domain) policy = SecPolicyCreateSSL(true, domain)!
} 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: trust) let serverPubKeys = publicKeyChainForTrust(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) {
@ -158,16 +158,16 @@ public class SSLSecurity : NSObject {
} }
} }
} else if let certs = self.certificates { } else if let certs = self.certificates {
let serverCerts = certificateChainForTrust(trust: trust) let serverCerts = certificateChainForTrust(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)
var result: SecTrustResultType = 0 var result = SecTrustResultType(rawValue: 0)!
SecTrustEvaluate(trust,&result) SecTrustEvaluate(trust,&result)
let r = Int(result) let r = Int(result.rawValue)
if r == kSecTrustResultUnspecified || r == kSecTrustResultProceed { if r == Int(SecTrustResultType.unspecified.rawValue) || r == Int(SecTrustResultType.proceed.rawValue) {
var trustedCount = 0 var trustedCount = 0
for serverCert in serverCerts { for serverCert in serverCerts {
for cert in certs { for cert in certs {
@ -192,10 +192,10 @@ public class SSLSecurity : NSObject {
- returns: a public key - returns: a public key
*/ */
func extractPublicKey(data: NSData) -> SecKey? { func extractPublicKey(_ data: Data) -> SecKey? {
guard let cert = SecCertificateCreateWithData(nil, data) else { return nil } guard let cert = SecCertificateCreateWithData(nil, data) else { return nil }
return extractPublicKeyFromCert(cert: cert, policy: SecPolicyCreateBasicX509()) return extractPublicKeyFromCert(cert, policy: SecPolicyCreateBasicX509()!)
} }
/** /**
@ -205,13 +205,13 @@ public class SSLSecurity : NSObject {
- returns: a public key - returns: a public key
*/ */
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKey? { func extractPublicKeyFromCert(_ cert: SecCertificate, policy: SecPolicy) -> SecKey? {
var possibleTrust: SecTrust? var possibleTrust: SecTrust?
SecTrustCreateWithCertificates(cert, policy, &possibleTrust) SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
guard let trust = possibleTrust else { return nil } guard let trust = possibleTrust else { return nil }
var result: SecTrustResultType = 0 var result = SecTrustResultType(rawValue: 0)!
SecTrustEvaluate(trust, &result) SecTrustEvaluate(trust, &result)
return SecTrustCopyPublicKey(trust) return SecTrustCopyPublicKey(trust)
} }
@ -223,11 +223,11 @@ public class SSLSecurity : NSObject {
- returns: the certificate chain for the trust - returns: the certificate chain for the trust
*/ */
func certificateChainForTrust(trust: SecTrust) -> [NSData] { func certificateChainForTrust(_ trust: SecTrust) -> [Data] {
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([NSData]()) { (certificates: [NSData], index: Int) -> [NSData] in let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([Data]()) { (certificates: [Data], index: Int) -> [Data] in
var certificates = certificates var certificates = certificates
let cert = SecTrustGetCertificateAtIndex(trust, index) let cert = SecTrustGetCertificateAtIndex(trust, index)
certificates.append(SecCertificateCopyData(cert!)) certificates.append(SecCertificateCopyData(cert!) as Data)
return certificates return certificates
} }
@ -241,12 +241,12 @@ public class SSLSecurity : NSObject {
- 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: SecTrust) -> [SecKey] { func publicKeyChainForTrust(_ trust: SecTrust) -> [SecKey] {
let policy = SecPolicyCreateBasicX509() let policy = SecPolicyCreateBasicX509()
let keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKey]()) { (keys: [SecKey], index: Int) -> [SecKey] 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: cert!, policy: policy) { if let key = extractPublicKeyFromCert(cert!, policy: policy!) {
keys.append(key) keys.append(key)
} }

View File

@ -28,40 +28,40 @@ public let WebsocketDidDisconnectNotification = "WebsocketDidDisconnectNotificat
public let WebsocketDisconnectionErrorKeyName = "WebsocketDisconnectionErrorKeyName" public let WebsocketDisconnectionErrorKeyName = "WebsocketDisconnectionErrorKeyName"
public protocol WebSocketDelegate: class { public protocol WebSocketDelegate: class {
func websocketDidConnect(socket: WebSocket) func websocketDidConnect(_ socket: WebSocket)
func websocketDidDisconnect(socket: WebSocket, error: NSError?) func websocketDidDisconnect(_ socket: WebSocket, error: NSError?)
func websocketDidReceiveMessage(socket: WebSocket, text: String) func websocketDidReceiveMessage(_ socket: WebSocket, text: String)
func websocketDidReceiveData(socket: WebSocket, data: NSData) func websocketDidReceiveData(_ socket: WebSocket, data: Data)
} }
public protocol WebSocketPongDelegate: class { public protocol WebSocketPongDelegate: class {
func websocketDidReceivePong(socket: WebSocket) func websocketDidReceivePong(_ socket: WebSocket)
} }
public class WebSocket : NSObject, NSStreamDelegate { public class WebSocket : NSObject, StreamDelegate {
enum OpCode : UInt8 { enum OpCode : UInt8 {
case ContinueFrame = 0x0 case continueFrame = 0x0
case TextFrame = 0x1 case textFrame = 0x1
case BinaryFrame = 0x2 case binaryFrame = 0x2
//3-7 are reserved. //3-7 are reserved.
case ConnectionClose = 0x8 case connectionClose = 0x8
case Ping = 0x9 case ping = 0x9
case Pong = 0xA case pong = 0xA
//B-F reserved. //B-F reserved.
} }
public enum CloseCode : UInt16 { public enum CloseCode : UInt16 {
case Normal = 1000 case normal = 1000
case GoingAway = 1001 case goingAway = 1001
case ProtocolError = 1002 case protocolError = 1002
case ProtocolUnhandledType = 1003 case protocolUnhandledType = 1003
// 1004 reserved. // 1004 reserved.
case NoStatusReceived = 1005 case noStatusReceived = 1005
//1006 reserved. //1006 reserved.
case Encoding = 1007 case encoding = 1007
case PolicyViolated = 1008 case policyViolated = 1008
case MessageTooBig = 1009 case messageTooBig = 1009
} }
#if swift(>=3) #if swift(>=3)
@ -71,11 +71,11 @@ public class WebSocket : NSObject, NSStreamDelegate {
enum InternalErrorCode : UInt16 { enum InternalErrorCode : UInt16 {
// 0-999 WebSocket status codes not used // 0-999 WebSocket status codes not used
case OutputStreamWriteError = 1 case outputStreamWriteError = 1
} }
//Where the callback is executed. It defaults to the main UI thread queue. //Where the callback is executed. It defaults to the main UI thread queue.
public var queue = dispatch_get_main_queue() public var queue = DispatchQueue.main
var optionalProtocols : [String]? var optionalProtocols : [String]?
//Constant Values. //Constant Values.
@ -100,7 +100,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
class WSResponse { class WSResponse {
var isFin = false var isFin = false
var code: OpCode = .ContinueFrame var code: OpCode = .continueFrame
var bytesLeft = 0 var bytesLeft = 0
var frameCount = 0 var frameCount = 0
var buffer: NSMutableData? var buffer: NSMutableData?
@ -111,7 +111,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
public var onConnect: ((Void) -> Void)? public var onConnect: ((Void) -> Void)?
public var onDisconnect: ((NSError?) -> Void)? public var onDisconnect: ((NSError?) -> Void)?
public var onText: ((String) -> Void)? public var onText: ((String) -> Void)?
public var onData: ((NSData) -> Void)? public var onData: ((Data) -> Void)?
public var onPong: ((Void) -> Void)? public var onPong: ((Void) -> Void)?
public var headers = [String: String]() public var headers = [String: String]()
public var voipEnabled = false public var voipEnabled = false
@ -123,21 +123,21 @@ public class WebSocket : NSObject, NSStreamDelegate {
public var isConnected :Bool { public var isConnected :Bool {
return connected return connected
} }
public var currentURL: NSURL {return url} public var currentURL: URL {return url}
private var url: NSURL private var url: URL
private var inputStream: NSInputStream? private var inputStream: InputStream?
private var outputStream: NSOutputStream? private var outputStream: NSOutputStream?
private var connected = false private var connected = false
private var isCreated = false private var isCreated = false
private var writeQueue = NSOperationQueue() private var writeQueue = OperationQueue()
private var readStack = [WSResponse]() private var readStack = [WSResponse]()
private var inputQueue = [NSData]() private var inputQueue = [Data]()
private var fragBuffer: NSData? private var fragBuffer: Data?
private var certValidated = false private var certValidated = false
private var didDisconnect = false private var didDisconnect = false
private var readyToWrite = false private var readyToWrite = false
private let mutex = NSLock() private let mutex = Lock()
private let notificationCenter = NSNotificationCenter.default() private let notificationCenter = NotificationCenter.default()
private var canDispatch: Bool { private var canDispatch: Bool {
mutex.lock() mutex.lock()
let canWork = readyToWrite let canWork = readyToWrite
@ -145,10 +145,10 @@ public class WebSocket : NSObject, NSStreamDelegate {
return canWork return canWork
} }
//the shared processing queue used for all websocket //the shared processing queue used for all websocket
private static let sharedWorkQueue = dispatch_queue_create("com.vluxe.starscream.websocket", DISPATCH_QUEUE_SERIAL) private static let sharedWorkQueue = DispatchQueue(label: "com.vluxe.starscream.websocket", attributes: DispatchQueueAttributes.serial)
//used for setting protocols. //used for setting protocols.
public init(url: NSURL, protocols: [String]? = nil) { public init(url: URL, protocols: [String]? = nil) {
self.url = url self.url = url
self.origin = url.absoluteString self.origin = url.absoluteString
writeQueue.maxConcurrentOperationCount = 1 writeQueue.maxConcurrentOperationCount = 1
@ -173,18 +173,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
- Parameter forceTimeout: Maximum time to wait for the server to close the socket. - Parameter forceTimeout: Maximum time to wait for the server to close the socket.
*/ */
public func disconnect(forceTimeout: NSTimeInterval? = nil) { public func disconnect(_ forceTimeout: TimeInterval? = 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 queue.after(when: DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { [weak self] in
self?.disconnectStream(error: nil) self?.disconnectStream(nil)
} }
fallthrough fallthrough
case .none: case .none:
writeError(code: CloseCode.Normal.rawValue) writeError(CloseCode.normal.rawValue)
default: default:
self.disconnectStream(error: nil) self.disconnectStream(nil)
break break
} }
} }
@ -197,9 +197,9 @@ public class WebSocket : NSObject, NSStreamDelegate {
- parameter str: The string to write. - parameter str: The string to write.
- parameter completion: The (optional) completion handler. - parameter completion: The (optional) completion handler.
*/ */
public func writeString(str: String, completion: (() -> ())? = nil) { public func writeString(_ str: String, completion: (() -> ())? = nil) {
guard isConnected else { return } guard isConnected else { return }
dequeueWrite(data: str.data(using: NSUTF8StringEncoding)!, code: .TextFrame, writeCompletion: completion) dequeueWrite(str.data(using: String.Encoding.utf8)!, code: .textFrame, writeCompletion: completion)
} }
/** /**
@ -210,16 +210,16 @@ public class WebSocket : NSObject, NSStreamDelegate {
- parameter data: The data to write. - parameter data: The data to write.
- parameter completion: The (optional) completion handler. - parameter completion: The (optional) completion handler.
*/ */
public func writeData(data: NSData, completion: (() -> ())? = nil) { public func writeData(_ data: Data, completion: (() -> ())? = nil) {
guard isConnected else { return } guard isConnected else { return }
dequeueWrite(data: data, code: .BinaryFrame, writeCompletion: completion) dequeueWrite(data, code: .binaryFrame, writeCompletion: completion)
} }
//write a ping to the websocket. This sends it as a control frame. //write a ping to the websocket. This sends it as a control frame.
//yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s //yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s
public func writePing(data: NSData, completion: (() -> ())? = nil) { public func writePing(_ data: Data, completion: (() -> ())? = nil) {
guard isConnected else { return } guard isConnected else { return }
dequeueWrite(data: data, code: .Ping, writeCompletion: completion) dequeueWrite(data, code: .ping, writeCompletion: completion)
} }
//private method that starts the connection //private method that starts the connection
@ -230,34 +230,34 @@ public class WebSocket : NSObject, NSStreamDelegate {
var port = url.port var port = url.port
if port == nil { if port == nil {
if ["wss", "https"].contains(url.scheme) { if ["wss", "https"].contains(url.scheme!) {
port = 443 port = 443
} else { } else {
port = 80 port = 80
} }
} }
addHeader(urlRequest: urlRequest, key: headerWSUpgradeName as NSString, val: headerWSUpgradeValue as NSString) addHeader(urlRequest, key: headerWSUpgradeName as NSString, val: headerWSUpgradeValue as NSString)
addHeader(urlRequest: urlRequest, key: headerWSConnectionName as NSString, val: headerWSConnectionValue as NSString) addHeader(urlRequest, key: headerWSConnectionName as NSString, val: headerWSConnectionValue as NSString)
if let protocols = optionalProtocols { if let protocols = optionalProtocols {
addHeader(urlRequest: urlRequest, key: headerWSProtocolName as NSString, val: protocols.joined(separator: ",") as NSString) addHeader(urlRequest, key: headerWSProtocolName as NSString, val: protocols.joined(separator: ",") as NSString)
} }
addHeader(urlRequest: urlRequest, key: headerWSVersionName as NSString, val: headerWSVersionValue as NSString) addHeader(urlRequest, key: headerWSVersionName as NSString, val: headerWSVersionValue as NSString)
addHeader(urlRequest: urlRequest, key: headerWSKeyName as NSString, val: generateWebSocketKey() as NSString) addHeader(urlRequest, key: headerWSKeyName as NSString, val: generateWebSocketKey() as NSString)
if let origin = origin { if let origin = origin {
addHeader(urlRequest: urlRequest, key: headerOriginName as NSString, val: origin as NSString) addHeader(urlRequest, key: headerOriginName as NSString, val: origin as NSString)
} }
addHeader(urlRequest: urlRequest, key: headerWSHostName as NSString, val: "\(url.host!):\(port!)" as NSString) addHeader(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 as NSString, val: value as NSString) addHeader(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()
initStreamsWithData(data: serializedRequest, Int(port!)) initStreamsWithData(serializedRequest as Data, Int(port!))
} }
} }
//Add a header to the CFHTTPMessage by using the NSString bridges to CFString //Add a header to the CFHTTPMessage by using the NSString bridges to CFString
private func addHeader(urlRequest: CFHTTPMessage, key: NSString, val: NSString) { private func addHeader(_ urlRequest: CFHTTPMessage, key: NSString, val: NSString) {
CFHTTPMessageSetHeaderFieldValue(urlRequest, key, val) CFHTTPMessageSetHeaderFieldValue(urlRequest, key, val)
} }
@ -269,13 +269,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
let uni = UnicodeScalar(UInt32(97 + arc4random_uniform(25))) let uni = UnicodeScalar(UInt32(97 + arc4random_uniform(25)))
key += "\(Character(uni))" key += "\(Character(uni))"
} }
let data = key.data(using: NSUTF8StringEncoding) let data = key.data(using: String.Encoding.utf8)
let baseKey = data?.base64EncodedString(NSDataBase64EncodingOptions(rawValue: 0)) let baseKey = data?.base64EncodedString(NSData.Base64EncodingOptions(rawValue: 0))
return baseKey! return baseKey!
} }
//Start the stream connection and write the data to the output stream //Start the stream connection and write the data to the output stream
private func initStreamsWithData(data: NSData, _ port: Int) { private func initStreamsWithData(_ data: Data, _ port: Int) {
//higher level API we will cut over to at some point //higher level API we will cut over to at some point
//NSStream.getStreamsToHostWithName(url.host, port: url.port.integerValue, inputStream: &inputStream, outputStream: &outputStream) //NSStream.getStreamsToHostWithName(url.host, port: url.port.integerValue, inputStream: &inputStream, outputStream: &outputStream)
@ -288,15 +288,15 @@ public class WebSocket : NSObject, NSStreamDelegate {
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 as NSString, forKey: NSStreamSocketSecurityLevelKey) inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as NSString, forKey: Stream.PropertyKey.socketSecurityLevelKey.rawValue)
outStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL as NSString, forKey: NSStreamSocketSecurityLevelKey) outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as NSString, forKey: Stream.PropertyKey.socketSecurityLevelKey.rawValue)
} 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 as NSString, forKey: NSStreamNetworkServiceType) inStream.setProperty(StreamNetworkServiceTypeValue.voip as NSString, forKey: Stream.PropertyKey.networkServiceType.rawValue)
outStream.setProperty(NSStreamNetworkServiceTypeVoIP as NSString, forKey: NSStreamNetworkServiceType) outStream.setProperty(StreamNetworkServiceTypeValue.voip as NSString, forKey: Stream.PropertyKey.networkServiceType.rawValue)
} }
if selfSignedSSL { if selfSignedSSL {
let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull] let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull]
@ -304,18 +304,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
outStream.setProperty(settings as AnyObject?, forKey: kCFStreamPropertySSLSettings as String) outStream.setProperty(settings as AnyObject?, forKey: kCFStreamPropertySSLSettings as String)
} }
if let cipherSuites = self.enabledSSLCipherSuites { if let cipherSuites = self.enabledSSLCipherSuites {
if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContext?, if let sslContextIn = CFReadStreamCopyProperty(inputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext?,
sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContext? { sslContextOut = CFWriteStreamCopyProperty(outputStream, CFStreamPropertyKey(rawValue: 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(detail: "Error setting ingoing cypher suites", code: UInt16(resIn)) let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn))
disconnectStream(error: error) disconnectStream(error)
return return
} }
if resOut != errSecSuccess { if resOut != errSecSuccess {
let error = self.errorWithDetail(detail: "Error setting outgoing cypher suites", code: UInt16(resOut)) let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut))
disconnectStream(error: error) disconnectStream(error)
return return
} }
} }
@ -329,7 +329,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
self.readyToWrite = true self.readyToWrite = true
self.mutex.unlock() self.mutex.unlock()
let bytes = UnsafePointer<UInt8>(data.bytes) let bytes = UnsafePointer<UInt8>((data as NSData).bytes)
var out = timeout * 1000000 //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 {
@ -337,27 +337,27 @@ public class WebSocket : NSObject, NSStreamDelegate {
out -= 100 out -= 100
if out < 0 { if out < 0 {
self?.cleanupStream() self?.cleanupStream()
self?.doDisconnect(error: self?.errorWithDetail(detail: "write wait timed out", code: 2)) self?.doDisconnect(self?.errorWithDetail("write wait timed out", code: 2))
return return
} else if outStream.streamError != nil { } else if outStream.streamError != nil {
return //disconnectStream will be called. return //disconnectStream will be called.
} }
} }
outStream.write(bytes, maxLength: data.length) outStream.write(bytes, maxLength: data.count)
} }
} }
//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: Stream, handle eventCode: Stream.Event) {
if let sec = security where !certValidated && [.hasBytesAvailable, .hasSpaceAvailable].contains(eventCode) { 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: trust as! SecTrust, domain: domain as! String?) { if sec.isValid(trust as! SecTrust, domain: domain as! String?) {
certValidated = true certValidated = true
} else { } else {
let error = errorWithDetail(detail: "Invalid SSL certificate", code: 1) let error = errorWithDetail("Invalid SSL certificate", code: 1)
disconnectStream(error: error) disconnectStream(error)
return return
} }
} }
@ -367,20 +367,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
processInputStream() processInputStream()
} }
} else if eventCode == .errorOccurred { } else if eventCode == .errorOccurred {
disconnectStream(error: aStream.streamError) disconnectStream(aStream.streamError)
} else if eventCode == .endEncountered { } else if eventCode == .endEncountered {
disconnectStream(error: nil) disconnectStream(nil)
} }
} }
//disconnect the stream object //disconnect the stream object
private func disconnectStream(error: NSError?) { private func disconnectStream(_ error: NSError?) {
if error == nil { if error == nil {
writeQueue.waitUntilAllOperationsAreFinished() writeQueue.waitUntilAllOperationsAreFinished()
} else { } else {
writeQueue.cancelAllOperations() writeQueue.cancelAllOperations()
} }
cleanupStream() cleanupStream()
doDisconnect(error: error) doDisconnect(error)
} }
private func cleanupStream() { private func cleanupStream() {
@ -409,7 +409,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
if inputQueue.count == 0 { if inputQueue.count == 0 {
process = true process = true
} }
inputQueue.append(NSData(bytes: buffer, length: length)) inputQueue.append(Data(bytes: UnsafePointer<UInt8>(buffer), count: length))
if process { if process {
dequeueInput() dequeueInput()
} }
@ -420,44 +420,44 @@ public class WebSocket : NSObject, NSStreamDelegate {
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) var combine = NSData(data: fragBuffer) as Data
combine.append(data) combine.append(data)
work = combine work = combine
self.fragBuffer = nil self.fragBuffer = nil
} }
let buffer = UnsafePointer<UInt8>(work.bytes) let buffer = UnsafePointer<UInt8>((work as NSData).bytes)
let length = work.length let length = work.count
if !connected { if !connected {
processTCPHandshake(buffer: buffer, bufferLen: length) processTCPHandshake(buffer, bufferLen: length)
} else { } else {
processRawMessagesInBuffer(pointer: buffer, bufferLen: length) processRawMessagesInBuffer(buffer, bufferLen: length)
} }
inputQueue = inputQueue.filter{$0 != data} inputQueue = inputQueue.filter{$0 != data}
} }
} }
//handle checking the inital connection status //handle checking the inital connection status
private func processTCPHandshake(buffer: UnsafePointer<UInt8>, bufferLen: Int) { private func processTCPHandshake(_ buffer: UnsafePointer<UInt8>, bufferLen: Int) {
let code = processHTTP(buffer: buffer, bufferLen: bufferLen) let code = processHTTP(buffer, bufferLen: bufferLen)
switch code { switch code {
case 0: case 0:
connected = true connected = true
guard canDispatch else {return} guard canDispatch else {return}
dispatch_async(queue!) { [weak self] in queue.async { [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(s)
s.notificationCenter.post(name: WebsocketDidConnectNotification, object: self) s.notificationCenter.post(name: NSNotification.Name(WebsocketDidConnectNotification), object: self)
} }
case -1: case -1:
fragBuffer = NSData(bytes: buffer, length: bufferLen) fragBuffer = Data(bytes: UnsafePointer<UInt8>(buffer), count: bufferLen)
break //do nothing, we are going to collect more data break //do nothing, we are going to collect more data
default: default:
doDisconnect(error: errorWithDetail(detail: "Invalid HTTP upgrade", code: UInt16(code))) doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: UInt16(code)))
} }
} }
///Finds the HTTP Packet in the TCP stream, by looking for the CRLF. ///Finds the HTTP Packet in the TCP stream, by looking for the CRLF.
private func processHTTP(buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Int { private func processHTTP(_ buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Int {
let CRLFBytes = [UInt8(ascii: "\r"), UInt8(ascii: "\n"), UInt8(ascii: "\r"), UInt8(ascii: "\n")] let CRLFBytes = [UInt8(ascii: "\r"), UInt8(ascii: "\n"), UInt8(ascii: "\r"), UInt8(ascii: "\n")]
var k = 0 var k = 0
var totalSize = 0 var totalSize = 0
@ -473,14 +473,14 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
} }
if totalSize > 0 { if totalSize > 0 {
let code = validateResponse(buffer: buffer, bufferLen: totalSize) let code = validateResponse(buffer, bufferLen: totalSize)
if code != 0 { if code != 0 {
return code return code
} }
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 {
processRawMessagesInBuffer(pointer: buffer + totalSize, bufferLen: restSize) processRawMessagesInBuffer(buffer + totalSize, bufferLen: restSize)
} }
return 0 //success return 0 //success
} }
@ -488,7 +488,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///validates the HTTP is a 101 as per the RFC spec ///validates the HTTP is a 101 as per the RFC spec
private func validateResponse(buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Int { private func validateResponse(_ buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Int {
let response = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, false).takeRetainedValue() let response = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, false).takeRetainedValue()
CFHTTPMessageAppendBytes(response, buffer, bufferLen) CFHTTPMessageAppendBytes(response, buffer, bufferLen)
let code = CFHTTPMessageGetResponseStatusCode(response) let code = CFHTTPMessageGetResponseStatusCode(response)
@ -507,12 +507,12 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///read a 16 bit big endian value from a buffer ///read a 16 bit big endian value from a buffer
private static func readUint16(buffer: UnsafePointer<UInt8>, offset: Int) -> UInt16 { private static func readUint16(_ buffer: UnsafePointer<UInt8>, offset: Int) -> UInt16 {
return (UInt16(buffer[offset + 0]) << 8) | UInt16(buffer[offset + 1]) return (UInt16(buffer[offset + 0]) << 8) | UInt16(buffer[offset + 1])
} }
///read a 64 bit big endian value from a buffer ///read a 64 bit big endian value from a buffer
private static func readUint64(buffer: UnsafePointer<UInt8>, offset: Int) -> UInt64 { private static func readUint64(_ buffer: UnsafePointer<UInt8>, offset: Int) -> UInt64 {
var value = UInt64(0) var value = UInt64(0)
for i in 0...7 { for i in 0...7 {
value = (value << 8) | UInt64(buffer[offset + i]) value = (value << 8) | UInt64(buffer[offset + i])
@ -521,13 +521,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///write a 16 bit big endian value to a buffer ///write a 16 bit big endian value to a buffer
private static func writeUint16(buffer: UnsafeMutablePointer<UInt8>, offset: Int, value: UInt16) { private static func writeUint16(_ buffer: UnsafeMutablePointer<UInt8>, offset: Int, value: UInt16) {
buffer[offset + 0] = UInt8(value >> 8) buffer[offset + 0] = UInt8(value >> 8)
buffer[offset + 1] = UInt8(value & 0xff) buffer[offset + 1] = UInt8(value & 0xff)
} }
///write a 64 bit big endian value to a buffer ///write a 64 bit big endian value to a buffer
private static func writeUint64(buffer: UnsafeMutablePointer<UInt8>, offset: Int, value: UInt64) { private static func writeUint64(_ buffer: UnsafeMutablePointer<UInt8>, offset: Int, value: UInt64) {
for i in 0...7 { for i in 0...7 {
buffer[offset + i] = UInt8((value >> (8*UInt64(7 - i))) & 0xff) buffer[offset + i] = UInt8((value >> (8*UInt64(7 - i))) & 0xff)
} }
@ -540,7 +540,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
guard let baseAddress = buffer.baseAddress else { fatalError("") } guard let baseAddress = buffer.baseAddress else { fatalError("") }
let bufferLen = buffer.count let bufferLen = buffer.count
if response != nil && bufferLen < 2 { if response != nil && bufferLen < 2 {
fragBuffer = NSData(buffer: buffer) fragBuffer = Data(buffer: buffer)
return emptyBuffer return emptyBuffer
} }
if let response = response where response.bytesLeft > 0 { if let response = response where response.bytesLeft > 0 {
@ -551,43 +551,43 @@ public class WebSocket : NSObject, NSStreamDelegate {
extra = 0 extra = 0
} }
response.bytesLeft -= len response.bytesLeft -= len
response.buffer?.append(NSData(bytes: baseAddress, length: len)) response.buffer?.append(Data(bytes: baseAddress, count: len))
processResponse(response: response) processResponse(response)
return buffer.fromOffset(offset: bufferLen - extra) return buffer.fromOffset(bufferLen - extra)
} else { } else {
let isFin = (FinMask & baseAddress[0]) let isFin = (FinMask & baseAddress[0])
let receivedOpcode = OpCode(rawValue: (OpCodeMask & baseAddress[0])) let receivedOpcode = OpCode(rawValue: (OpCodeMask & baseAddress[0]))
let isMasked = (MaskMask & baseAddress[1]) let isMasked = (MaskMask & baseAddress[1])
let payloadLen = (PayloadLenMask & baseAddress[1]) let payloadLen = (PayloadLenMask & baseAddress[1])
var offset = 2 var offset = 2
if (isMasked > 0 || (RSVMask & baseAddress[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(errorWithDetail("masked and rsv data is not currently supported", code: errCode))
writeError(code: errCode) writeError(errCode)
return emptyBuffer 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 &&
receivedOpcode != .TextFrame && receivedOpcode != .Pong) { receivedOpcode != .textFrame && receivedOpcode != .pong) {
let errCode = CloseCode.ProtocolError.rawValue let errCode = CloseCode.protocolError.rawValue
doDisconnect(error: errorWithDetail(detail: "unknown opcode: \(receivedOpcode)", code: errCode)) doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode))
writeError(code: errCode) writeError(errCode)
return emptyBuffer 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(errorWithDetail("control frames can't be fragmented", code: errCode))
writeError(code: errCode) writeError(errCode)
return emptyBuffer 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: baseAddress, offset: offset) code = WebSocket.readUint16(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
} }
offset += 2 offset += 2
} }
@ -595,70 +595,70 @@ public class WebSocket : NSObject, NSStreamDelegate {
let len = Int(payloadLen-2) let len = Int(payloadLen-2)
if len > 0 { if len > 0 {
let bytes = baseAddress + offset let bytes = baseAddress + offset
let str: NSString? = NSString(data: NSData(bytes: bytes, length: len), encoding: NSUTF8StringEncoding) let str: NSString? = NSString(data: Data(bytes: bytes, count: len), encoding: String.Encoding.utf8.rawValue)
if str == nil { if str == nil {
code = CloseCode.ProtocolError.rawValue code = CloseCode.protocolError.rawValue
} }
} }
} }
doDisconnect(error: errorWithDetail(detail: "connection closed by server", code: code)) doDisconnect(errorWithDetail("connection closed by server", code: code))
writeError(code: code) writeError(code)
return emptyBuffer return emptyBuffer
} }
if isControlFrame && payloadLen > 125 { if isControlFrame && payloadLen > 125 {
writeError(code: CloseCode.ProtocolError.rawValue) writeError(CloseCode.protocolError.rawValue)
return emptyBuffer return emptyBuffer
} }
var dataLength = UInt64(payloadLen) var dataLength = UInt64(payloadLen)
if dataLength == 127 { if dataLength == 127 {
dataLength = WebSocket.readUint64(buffer: baseAddress, offset: offset) dataLength = WebSocket.readUint64(baseAddress, offset: offset)
offset += sizeof(UInt64) offset += sizeof(UInt64)
} else if dataLength == 126 { } else if dataLength == 126 {
dataLength = UInt64(WebSocket.readUint16(buffer: baseAddress, offset: offset)) dataLength = UInt64(WebSocket.readUint16(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: baseAddress, length: bufferLen) fragBuffer = Data(bytes: baseAddress, count: bufferLen)
return emptyBuffer return emptyBuffer
} }
var len = dataLength var len = dataLength
if dataLength > UInt64(bufferLen) { if dataLength > UInt64(bufferLen) {
len = UInt64(bufferLen-offset) len = UInt64(bufferLen-offset)
} }
let data: NSData let data: Data
if len < 0 { if len < 0 {
len = 0 len = 0
data = NSData() data = Data()
} else { } else {
data = NSData(bytes: baseAddress+offset, length: Int(len)) data = Data(bytes: baseAddress+offset, count: Int(len))
} }
if receivedOpcode == .Pong { if receivedOpcode == .pong {
if canDispatch { if canDispatch {
dispatch_async(queue!) { [weak self] in queue.async { [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(s)
} }
} }
return buffer.fromOffset(offset: offset + Int(len)) return buffer.fromOffset(offset + Int(len))
} }
var response = readStack.last var response = readStack.last
if isControlFrame { if isControlFrame {
response = nil //don't append pings response = nil //don't append pings
} }
if isFin == 0 && receivedOpcode == .ContinueFrame && response == nil { if isFin == 0 && receivedOpcode == .continueFrame && response == nil {
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(errorWithDetail("continue frame before a binary or text frame", code: errCode))
writeError(code: errCode) writeError(errCode)
return emptyBuffer return emptyBuffer
} }
var isNew = false var isNew = false
if response == nil { if response == nil {
if receivedOpcode == .ContinueFrame { if receivedOpcode == .continueFrame {
let errCode = CloseCode.ProtocolError.rawValue let errCode = CloseCode.protocolError.rawValue
doDisconnect(error: errorWithDetail(detail: "first frame can't be a continue frame", doDisconnect(errorWithDetail("first frame can't be a continue frame",
code: errCode)) code: errCode))
writeError(code: errCode) writeError(errCode)
return emptyBuffer return emptyBuffer
} }
isNew = true isNew = true
@ -667,13 +667,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
response!.bytesLeft = Int(dataLength) response!.bytesLeft = Int(dataLength)
response!.buffer = NSMutableData(data: data) response!.buffer = NSMutableData(data: data)
} else { } else {
if receivedOpcode == .ContinueFrame { if receivedOpcode == .continueFrame {
response!.bytesLeft = Int(dataLength) response!.bytesLeft = Int(dataLength)
} else { } else {
let errCode = CloseCode.ProtocolError.rawValue let errCode = CloseCode.protocolError.rawValue
doDisconnect(error: errorWithDetail(detail: "second and beyond of fragment message must be a continue frame", doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame",
code: errCode)) code: errCode))
writeError(code: errCode) writeError(errCode)
return emptyBuffer return emptyBuffer
} }
response!.buffer!.append(data) response!.buffer!.append(data)
@ -685,51 +685,52 @@ public class WebSocket : NSObject, NSStreamDelegate {
if isNew { if isNew {
readStack.append(response) readStack.append(response)
} }
processResponse(response: response) processResponse(response)
} }
let step = Int(offset+numericCast(len)) let step = Int(offset+numericCast(len))
return buffer.fromOffset(offset: step) return buffer.fromOffset(step)
} }
} }
/// Process all messages in the buffer if possible. /// Process all messages in the buffer if possible.
private func processRawMessagesInBuffer(pointer: UnsafePointer<UInt8>, bufferLen: Int) { private func processRawMessagesInBuffer(_ pointer: UnsafePointer<UInt8>, bufferLen: Int) {
var buffer = UnsafeBufferPointer(start: pointer, count: bufferLen) var buffer = UnsafeBufferPointer(start: pointer, count: bufferLen)
repeat { repeat {
buffer = processOneRawMessage(inBuffer: buffer) buffer = processOneRawMessage(inBuffer: buffer)
} while buffer.count >= 2 } while buffer.count >= 2
if buffer.count > 0 { if buffer.count > 0 {
fragBuffer = NSData(buffer: buffer) fragBuffer = Data(buffer: buffer)
} }
} }
///process the finished response of a buffer ///process the finished response of a buffer
private func processResponse(response: WSResponse) -> Bool { @discardableResult
private func processResponse(_ response: WSResponse) -> Bool {
if response.isFin && response.bytesLeft <= 0 { if response.isFin && response.bytesLeft <= 0 {
if response.code == .Ping { if response.code == .ping {
let data = response.buffer! //local copy so it is perverse for writing let data = response.buffer! //local copy so it is perverse for writing
dequeueWrite(data: data, code: OpCode.Pong) dequeueWrite(data as Data, code: .pong)
} else if response.code == .TextFrame { } else if response.code == .textFrame {
let str: NSString? = NSString(data: response.buffer!, encoding: NSUTF8StringEncoding) let str: NSString? = NSString(data: response.buffer! as Data, encoding: String.Encoding.utf8.rawValue)
if str == nil { if str == nil {
writeError(code: CloseCode.Encoding.rawValue) writeError(CloseCode.encoding.rawValue)
return false return false
} }
if canDispatch { if canDispatch {
dispatch_async(queue!) { [weak self] in queue.async { [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(s, text: str! as String)
} }
} }
} 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 queue.async { [weak self] in
guard let s = self else { return } guard let s = self else { return }
s.onData?(data) s.onData?(data as Data)
s.delegate?.websocketDidReceiveData(socket: s, data: data) s.delegate?.websocketDidReceiveData(s, data: data as Data)
} }
} }
} }
@ -740,7 +741,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///Create an error ///Create an error
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
@ -752,20 +753,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///write a an error to the socket ///write a an error to the socket
private func writeError(code: UInt16) { private func writeError(_ code: UInt16) {
let buf = NSMutableData(capacity: sizeof(UInt16)) let buf = NSMutableData(capacity: sizeof(UInt16))
let buffer = UnsafeMutablePointer<UInt8>(buf!.bytes) let buffer = UnsafeMutablePointer<UInt8>(buf!.bytes)
WebSocket.writeUint16(buffer: buffer, offset: 0, value: code) WebSocket.writeUint16(buffer, offset: 0, value: code)
dequeueWrite(data: NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose) dequeueWrite(Data(bytes: buffer, count: sizeof(UInt16)), code: .connectionClose)
} }
///used to write things to the stream ///used to write things to the stream
private func dequeueWrite(data: NSData, code: OpCode, writeCompletion: (() -> ())? = nil) { private func dequeueWrite(_ data: Data, code: OpCode, writeCompletion: (() -> ())? = nil) {
writeQueue.addOperation { [weak self] in writeQueue.addOperation { [weak self] in
//stream isn't ready, let's wait //stream isn't ready, let's wait
guard let s = self else { return } guard let s = self else { return }
var offset = 2 var offset = 2
let bytes = UnsafeMutablePointer<UInt8>(data.bytes) let bytes = UnsafeMutablePointer<UInt8>((data as NSData).bytes)
let dataLength = data.length let dataLength = data.count
let frame = NSMutableData(capacity: dataLength + s.MaxFrameSize) let frame = NSMutableData(capacity: dataLength + s.MaxFrameSize)
let buffer = UnsafeMutablePointer<UInt8>(frame!.mutableBytes) let buffer = UnsafeMutablePointer<UInt8>(frame!.mutableBytes)
buffer[0] = s.FinMask | code.rawValue buffer[0] = s.FinMask | code.rawValue
@ -773,11 +774,11 @@ public class WebSocket : NSObject, NSStreamDelegate {
buffer[1] = CUnsignedChar(dataLength) buffer[1] = CUnsignedChar(dataLength)
} else if dataLength <= Int(UInt16.max) { } else if dataLength <= Int(UInt16.max) {
buffer[1] = 126 buffer[1] = 126
WebSocket.writeUint16(buffer: buffer, offset: offset, value: UInt16(dataLength)) WebSocket.writeUint16(buffer, offset: offset, value: UInt16(dataLength))
offset += sizeof(UInt16) offset += sizeof(UInt16)
} else { } else {
buffer[1] = 127 buffer[1] = 127
WebSocket.writeUint64(buffer: buffer, offset: offset, value: UInt64(dataLength)) WebSocket.writeUint64(buffer, offset: offset, value: UInt64(dataLength))
offset += sizeof(UInt64) offset += sizeof(UInt64)
} }
buffer[1] |= s.MaskMask buffer[1] |= s.MaskMask
@ -799,17 +800,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
if let streamError = outStream.streamError { if let streamError = outStream.streamError {
error = streamError error = streamError
} else { } else {
let errCode = InternalErrorCode.OutputStreamWriteError.rawValue let errCode = InternalErrorCode.outputStreamWriteError.rawValue
error = s.errorWithDetail(detail: "output stream error during write", code: errCode) error = s.errorWithDetail("output stream error during write", code: errCode)
} }
s.doDisconnect(error: error) s.doDisconnect(error)
break break
} else { } else {
total += len total += len
} }
if total >= offset { if total >= offset {
if let queue = self?.queue, callback = writeCompletion { if let queue = self?.queue, callback = writeCompletion {
dispatch_async(queue) { queue.asynchronously() {
callback() callback()
} }
} }
@ -822,17 +823,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///used to preform the disconnect delegate ///used to preform the disconnect delegate
private func doDisconnect(error: NSError?) { private func doDisconnect(_ error: NSError?) {
guard !didDisconnect else { return } guard !didDisconnect else { return }
didDisconnect = true didDisconnect = true
connected = false connected = false
guard canDispatch else {return} guard canDispatch else {return}
dispatch_async(queue!) { [weak self] in queue.async { [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(s, error: error)
let userInfo = error.map({ [WebsocketDisconnectionErrorKeyName: $0] }) let userInfo = error.map({ [WebsocketDisconnectionErrorKeyName: $0] })
s.notificationCenter.post(name: WebsocketDidDisconnectNotification, object: self, userInfo: userInfo) s.notificationCenter.post(name: NSNotification.Name(rawValue: WebsocketDidDisconnectNotification), object: self, userInfo: userInfo)
} }
} }
@ -855,7 +856,7 @@ private extension NSData {
private extension UnsafeBufferPointer { private extension UnsafeBufferPointer {
func fromOffset(offset: Int) -> UnsafeBufferPointer<Element> { func fromOffset(_ offset: Int) -> UnsafeBufferPointer<Element> {
return UnsafeBufferPointer<Element>(start: baseAddress!.advanced(by: offset), count: count - offset) return UnsafeBufferPointer<Element>(start: baseAddress!.advanced(by: offset), count: count - offset)
} }