xcode 8
This commit is contained in:
parent
7500ea83a0
commit
9a4ec5a82a
@ -536,9 +536,11 @@
|
||||
};
|
||||
572EF2371B51F18A00EEBB58 = {
|
||||
CreatedOnToolsVersion = 6.4;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
572EF2411B51F18A00EEBB58 = {
|
||||
CreatedOnToolsVersion = 6.4;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -1081,6 +1083,7 @@
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
@ -1132,6 +1135,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
@ -1188,6 +1192,7 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -1234,6 +1239,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "io.socket.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@ -15,7 +15,7 @@ class SocketAckManagerTest: XCTestCase {
|
||||
func testAddAcks() {
|
||||
let callbackExpection = self.expectation(withDescription: "callbackExpection")
|
||||
let itemsArray = ["Hi", "ho"]
|
||||
func callback(items: [AnyObject]) {
|
||||
func callback(_ items: [AnyObject]) {
|
||||
callbackExpection.fulfill()
|
||||
}
|
||||
ackManager.addAck(1, callback: callback)
|
||||
|
||||
@ -10,13 +10,13 @@ import XCTest
|
||||
@testable import SocketIOClientSwift
|
||||
|
||||
class SocketBasicPacketTest: XCTestCase {
|
||||
let data = "test".data(using: NSUTF8StringEncoding)!
|
||||
let data2 = "test2".data(using: NSUTF8StringEncoding)!
|
||||
let data = "test".data(using: String.Encoding.utf8)!
|
||||
let data2 = "test2".data(using: String.Encoding.utf8)!
|
||||
|
||||
func testEmpyEmit() {
|
||||
let expectedSendString = "2[\"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)
|
||||
}
|
||||
@ -24,7 +24,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testNullEmit() {
|
||||
let expectedSendString = "2[\"test\",null]"
|
||||
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)
|
||||
}
|
||||
@ -32,7 +32,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testStringEmit() {
|
||||
let expectedSendString = "2[\"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)
|
||||
}
|
||||
@ -40,7 +40,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testStringEmitWithQuotes() {
|
||||
let expectedSendString = "2[\"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)
|
||||
}
|
||||
@ -48,7 +48,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testJSONEmit() {
|
||||
let expectedSendString = "2[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
|
||||
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)
|
||||
}
|
||||
@ -56,7 +56,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testArrayEmit() {
|
||||
let expectedSendString = "2[\"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)
|
||||
}
|
||||
@ -64,7 +64,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testBinaryEmit() {
|
||||
let expectedSendString = "51-[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||
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.binary, [data])
|
||||
@ -73,7 +73,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testMultipleBinaryEmit() {
|
||||
let expectedSendString = "52-[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]"
|
||||
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.binary, [data, data2])
|
||||
@ -82,7 +82,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testEmitWithAck() {
|
||||
let expectedSendString = "20[\"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)
|
||||
}
|
||||
@ -90,7 +90,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testEmitDataWithAck() {
|
||||
let expectedSendString = "51-0[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||
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.binary, [data])
|
||||
@ -99,7 +99,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
// Acks
|
||||
func testEmptyAck() {
|
||||
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)
|
||||
}
|
||||
@ -107,7 +107,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testNullAck() {
|
||||
let expectedSendString = "30[null]"
|
||||
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)
|
||||
}
|
||||
@ -115,7 +115,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testStringAck() {
|
||||
let expectedSendString = "30[\"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)
|
||||
}
|
||||
@ -123,7 +123,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testJSONAck() {
|
||||
let expectedSendString = "30[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
|
||||
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)
|
||||
}
|
||||
@ -131,7 +131,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testBinaryAck() {
|
||||
let expectedSendString = "61-0[{\"_placeholder\":true,\"num\":0}]"
|
||||
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.binary, [data])
|
||||
@ -140,7 +140,7 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
func testMultipleBinaryAck() {
|
||||
let expectedSendString = "62-0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]"
|
||||
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.binary, [data2, data])
|
||||
@ -148,10 +148,10 @@ class SocketBasicPacketTest: XCTestCase {
|
||||
|
||||
func testBinaryStringPlaceholderInMessage() {
|
||||
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()
|
||||
|
||||
if case let .Right(packet) = socket.parseString(engineString) {
|
||||
if case let .right(packet) = socket.parseString(engineString) {
|
||||
var packet = packet
|
||||
XCTAssertEqual(packet.event, "test")
|
||||
packet.addData(data)
|
||||
|
||||
@ -15,8 +15,8 @@ class SocketEngineTest: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
client = SocketIOClient(socketURL: NSURL(string: "http://localhost")!)
|
||||
engine = SocketEngine(client: client, url: NSURL(string: "http://localhost")!, options: nil)
|
||||
client = SocketIOClient(socketURL: URL(string: "http://localhost")!)
|
||||
engine = SocketEngine(client: client, url: URL(string: "http://localhost")!, options: nil)
|
||||
|
||||
client.setTestable()
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@ import XCTest
|
||||
@testable import SocketIOClientSwift
|
||||
|
||||
class SocketNamespacePacketTest: XCTestCase {
|
||||
let data = "test".data(using: NSUTF8StringEncoding)!
|
||||
let data2 = "test2".data(using: NSUTF8StringEncoding)!
|
||||
let data = "test".data(using: String.Encoding.utf8)!
|
||||
let data2 = "test2".data(using: String.Encoding.utf8)!
|
||||
|
||||
func testEmpyEmit() {
|
||||
let expectedSendString = "2/swift,[\"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)
|
||||
}
|
||||
@ -24,7 +24,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testNullEmit() {
|
||||
let expectedSendString = "2/swift,[\"test\",null]"
|
||||
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)
|
||||
}
|
||||
@ -32,7 +32,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testStringEmit() {
|
||||
let expectedSendString = "2/swift,[\"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)
|
||||
}
|
||||
@ -40,7 +40,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testJSONEmit() {
|
||||
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 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)
|
||||
}
|
||||
@ -48,7 +48,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testArrayEmit() {
|
||||
let expectedSendString = "2/swift,[\"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)
|
||||
}
|
||||
@ -56,7 +56,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testBinaryEmit() {
|
||||
let expectedSendString = "51-/swift,[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||
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.binary, [data])
|
||||
@ -65,7 +65,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testMultipleBinaryEmit() {
|
||||
let expectedSendString = "52-/swift,[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]"
|
||||
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.binary, [data, data2])
|
||||
@ -74,7 +74,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testEmitWithAck() {
|
||||
let expectedSendString = "2/swift,0[\"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)
|
||||
}
|
||||
@ -82,7 +82,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testEmitDataWithAck() {
|
||||
let expectedSendString = "51-/swift,0[\"test\",{\"_placeholder\":true,\"num\":0}]"
|
||||
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.binary, [data])
|
||||
@ -91,7 +91,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
// Acks
|
||||
func testEmptyAck() {
|
||||
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)
|
||||
}
|
||||
@ -99,7 +99,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testNullAck() {
|
||||
let expectedSendString = "3/swift,0[null]"
|
||||
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)
|
||||
}
|
||||
@ -107,7 +107,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testStringAck() {
|
||||
let expectedSendString = "3/swift,0[\"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)
|
||||
}
|
||||
@ -115,7 +115,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testJSONAck() {
|
||||
let expectedSendString = "3/swift,0[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]"
|
||||
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)
|
||||
}
|
||||
@ -123,7 +123,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testBinaryAck() {
|
||||
let expectedSendString = "61-/swift,0[{\"_placeholder\":true,\"num\":0}]"
|
||||
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.binary, [data])
|
||||
@ -132,7 +132,7 @@ class SocketNamespacePacketTest: XCTestCase {
|
||||
func testMultipleBinaryAck() {
|
||||
let expectedSendString = "62-/swift,0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]"
|
||||
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.binary, [data2, data])
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
- (void)testSocketManager {
|
||||
SocketClientManager* manager = [SocketClientManager sharedManager];
|
||||
[manager addSocketWithSocket:self.socket labeledAs:@"test"];
|
||||
[manager addSocket:self.socket labeledAs:@"test"];
|
||||
[manager removeSocketWithLabel:@"test"];
|
||||
}
|
||||
|
||||
|
||||
@ -10,10 +10,10 @@ import XCTest
|
||||
@testable import SocketIOClientSwift
|
||||
|
||||
class SocketParserTest: XCTestCase {
|
||||
let testSocket = SocketIOClient(socketURL: NSURL())
|
||||
let testSocket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
|
||||
|
||||
//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),
|
||||
"25[\"test\"]": ("/", ["test"], [], 5),
|
||||
"2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1),
|
||||
@ -31,97 +31,97 @@ class SocketParserTest: XCTestCase {
|
||||
|
||||
func testDisconnect() {
|
||||
let message = "1"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testConnect() {
|
||||
let message = "0"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testDisconnectNameSpace() {
|
||||
let message = "1/swift"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testConnecttNameSpace() {
|
||||
let message = "0/swift"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testIdEvent() {
|
||||
let message = "25[\"test\"]"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testBinaryPlaceholderAsString() {
|
||||
let message = "2[\"test\",\"~~0\"]"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testNameSpaceArrayParse() {
|
||||
let message = "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testNameSpaceArrayAckParse() {
|
||||
let message = "3/swift,0[[\"test3\",\"test4\"]]"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testNameSpaceBinaryEventParse() {
|
||||
let message = "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testNameSpaceBinaryAckParse() {
|
||||
let message = "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testNamespaceErrorParse() {
|
||||
let message = "4/swift,"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testErrorTypeString() {
|
||||
let message = "4\"ERROR\""
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testErrorTypeDictionary() {
|
||||
let message = "4{\"test\":2}"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testErrorTypeInt() {
|
||||
let message = "41"
|
||||
validateParseResult(message: message)
|
||||
validateParseResult(message)
|
||||
}
|
||||
|
||||
func testInvalidInput() {
|
||||
let message = "8"
|
||||
switch testSocket.parseString(message) {
|
||||
case .Left(_):
|
||||
case .left(_):
|
||||
return
|
||||
case .Right(_):
|
||||
case .right(_):
|
||||
XCTFail("Created packet when shouldn't have")
|
||||
}
|
||||
}
|
||||
|
||||
func testGenericParser() {
|
||||
var parser = SocketStringReader(message: "61-/swift,")
|
||||
XCTAssertEqual(parser.read(length: 1), "6")
|
||||
XCTAssertEqual(parser.read(1), "6")
|
||||
XCTAssertEqual(parser.currentCharacter, "1")
|
||||
XCTAssertEqual(parser.readUntilStringOccurence("-"), "1")
|
||||
XCTAssertEqual(parser.currentCharacter, "/")
|
||||
}
|
||||
|
||||
func validateParseResult(message: String) {
|
||||
func validateParseResult(_ message: String) {
|
||||
let validValues = SocketParserTest.packetTypes[message]!
|
||||
let packet = testSocket.parseString(message)
|
||||
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.nsp, validValues.0)
|
||||
XCTAssertTrue((packet.data as NSArray).isEqual(to: validValues.1), "\(packet.data)")
|
||||
|
||||
@ -10,13 +10,13 @@ import XCTest
|
||||
@testable import SocketIOClientSwift
|
||||
|
||||
class SocketSideEffectTest: XCTestCase {
|
||||
let data = "test".data(using: NSUTF8StringEncoding)!
|
||||
let data2 = "test2".data(using: NSUTF8StringEncoding)!
|
||||
let data = "test".data(using: String.Encoding.utf8)!
|
||||
let data2 = "test2".data(using: String.Encoding.utf8)!
|
||||
private var socket: SocketIOClient!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
socket = SocketIOClient(socketURL: NSURL())
|
||||
socket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
|
||||
socket.setTestable()
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ class SocketSideEffectTest: XCTestCase {
|
||||
}
|
||||
|
||||
socket.parseSocketMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]")
|
||||
socket.parseBinaryData(NSData())
|
||||
socket.parseBinaryData(Data())
|
||||
waitForExpectations(withTimeout: 3, handler: nil)
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ class SocketSideEffectTest: XCTestCase {
|
||||
|
||||
func testHandleOnceEvent() {
|
||||
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(self.socket.testHandlers.count, 0)
|
||||
expect.fulfill()
|
||||
@ -140,7 +140,7 @@ class SocketSideEffectTest: XCTestCase {
|
||||
func testSocketDataToAnyObject() {
|
||||
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() {
|
||||
|
||||
@ -24,8 +24,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension NSCharacterSet {
|
||||
class var allowedURLCharacterSet: NSCharacterSet {
|
||||
return NSCharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]\" {}").inverted
|
||||
extension CharacterSet {
|
||||
static var allowedURLCharacterSet: CharacterSet {
|
||||
return CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]\" {}").inverted
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ public final class SocketAckEmitter : NSObject {
|
||||
public func with(_ items: SocketData...) {
|
||||
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]) {
|
||||
|
||||
@ -59,7 +59,7 @@ struct SocketAckManager {
|
||||
mutating func executeAck(_ ack: Int, items: [AnyObject]) {
|
||||
let callback = acks.remove(SocketAck(ack: ack))
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
DispatchQueue.main.async {
|
||||
callback?.callback(items)
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,7 @@ struct SocketAckManager {
|
||||
mutating func timeoutAck(_ ack: Int) {
|
||||
let callback = acks.remove(SocketAck(ack: ack))
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
DispatchQueue.main.async {
|
||||
callback?.callback(["NO ACK"])
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ public final class SocketClientManager : NSObject {
|
||||
return sockets.removeValue(forKey: label)
|
||||
}
|
||||
|
||||
public func removeSocket(socket: SocketIOClient) -> SocketIOClient? {
|
||||
public func removeSocket(_ socket: SocketIOClient) -> SocketIOClient? {
|
||||
var returnSocket: SocketIOClient?
|
||||
|
||||
for (label, dictSocket) in sockets where dictSocket === socket {
|
||||
|
||||
@ -25,9 +25,9 @@
|
||||
import Foundation
|
||||
|
||||
public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWebsocket {
|
||||
public let emitQueue = dispatch_queue_create("com.socketio.engineEmitQueue", DISPATCH_QUEUE_SERIAL)!
|
||||
public let handleQueue = dispatch_queue_create("com.socketio.engineHandleQueue", DISPATCH_QUEUE_SERIAL)!
|
||||
public let parseQueue = dispatch_queue_create("com.socketio.engineParseQueue", DISPATCH_QUEUE_SERIAL)!
|
||||
public let emitQueue = DispatchQueue(label: "com.socketio.engineEmitQueue", attributes: DispatchQueueAttributes.serial)
|
||||
public let handleQueue = DispatchQueue(label: "com.socketio.engineHandleQueue", attributes: DispatchQueueAttributes.serial)
|
||||
public let parseQueue = DispatchQueue(label: "com.socketio.engineParseQueue", attributes: DispatchQueueAttributes.serial)
|
||||
|
||||
public var connectParams: [String: AnyObject]? {
|
||||
didSet {
|
||||
@ -41,7 +41,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
|
||||
public private(set) var closed = 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 extraHeaders: [String: String]?
|
||||
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 polling = true
|
||||
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 socketPath = "/engine.io/"
|
||||
public private(set) var urlPolling = NSURL()
|
||||
public private(set) var urlWebSocket = NSURL()
|
||||
public private(set) var urlPolling = URL(string: "http://localhost/")!
|
||||
public private(set) var urlWebSocket = URL(string: "http://localhost/")!
|
||||
public private(set) var websocket = false
|
||||
public private(set) var ws: WebSocket?
|
||||
|
||||
public weak var client: SocketEngineClient?
|
||||
|
||||
private weak var sessionDelegate: NSURLSessionDelegate?
|
||||
private weak var sessionDelegate: URLSessionDelegate?
|
||||
|
||||
private let logType = "SocketEngine"
|
||||
private let url: NSURL
|
||||
private let url: URL
|
||||
|
||||
private var pingInterval: Double?
|
||||
private var pingTimeout = 0.0 {
|
||||
@ -80,7 +80,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
private var selfSigned = 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.url = url
|
||||
|
||||
@ -120,7 +120,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
(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() ?? [])
|
||||
}
|
||||
|
||||
@ -131,11 +131,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
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 }
|
||||
|
||||
/*
|
||||
@ -144,10 +144,10 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
2: Bad handshake request
|
||||
3: Bad request
|
||||
*/
|
||||
didError(error: error)
|
||||
didError(error)
|
||||
}
|
||||
} 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
|
||||
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)
|
||||
}
|
||||
|
||||
@ -180,7 +180,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
public func connect() {
|
||||
if connected {
|
||||
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)
|
||||
@ -198,7 +198,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
let reqPolling = NSMutableURLRequest(url: urlPolling)
|
||||
|
||||
if cookies != nil {
|
||||
let headers = NSHTTPCookie.requestHeaderFields(with: cookies!)
|
||||
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
||||
reqPolling.allHTTPHeaderFields = headers
|
||||
}
|
||||
|
||||
@ -208,18 +208,18 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_async(emitQueue) {
|
||||
self.doLongPoll(for: reqPolling)
|
||||
(emitQueue).async {
|
||||
self.doLongPoll(for: reqPolling as URLRequest)
|
||||
}
|
||||
}
|
||||
|
||||
private func createURLs() -> (NSURL, NSURL) {
|
||||
private func createURLs() -> (URL, URL) {
|
||||
if client == nil {
|
||||
return (NSURL(), NSURL())
|
||||
return (URL(string: "http://localhost/")!, URL(string: "http://localhost/")!)
|
||||
}
|
||||
|
||||
let urlPolling = NSURLComponents(string: url.absoluteString)!
|
||||
let urlWebSocket = NSURLComponents(string: url.absoluteString)!
|
||||
var urlPolling = URLComponents(string: url.absoluteString!)!
|
||||
var urlWebSocket = URLComponents(string: url.absoluteString!)!
|
||||
var queryString = ""
|
||||
|
||||
urlWebSocket.path = socketPath
|
||||
@ -252,7 +252,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
ws = WebSocket(url: urlWebSocketWithSid)
|
||||
|
||||
if cookies != nil {
|
||||
let headers = NSHTTPCookie.requestHeaderFields(with: cookies!)
|
||||
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
||||
for (key, value) in headers {
|
||||
ws?.headers[key] = value
|
||||
}
|
||||
@ -273,20 +273,20 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
ws?.connect()
|
||||
}
|
||||
|
||||
public func didError(error: String) {
|
||||
public func didError(_ error: String) {
|
||||
DefaultSocketLogger.Logger.error("%@", type: logType, args: error)
|
||||
client?.engineDidError(reason: error)
|
||||
disconnect(reason: error)
|
||||
client?.engineDidError(error)
|
||||
disconnect(error)
|
||||
}
|
||||
|
||||
public func disconnect(reason: String) {
|
||||
public func disconnect(_ reason: String) {
|
||||
guard connected else { return closeOutEngine() }
|
||||
|
||||
DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType)
|
||||
|
||||
if closed {
|
||||
closeOutEngine()
|
||||
client?.engineDidClose(reason: reason)
|
||||
client?.engineDidClose(reason)
|
||||
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
|
||||
// Also make sure we're on the emitQueue since we're touching postWait
|
||||
private func disconnectPolling() {
|
||||
dispatch_sync(emitQueue) {
|
||||
emitQueue.sync {
|
||||
self.postWait.append(String(SocketEnginePacketType.close.rawValue))
|
||||
let req = self.createRequestForPostWithPostWait()
|
||||
self.doRequest(for: req) {_, _, _ in }
|
||||
@ -326,7 +326,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
private func flushProbeWait() {
|
||||
DefaultSocketLogger.Logger.log("Flushing probe wait", type: logType)
|
||||
|
||||
dispatch_async(emitQueue) {
|
||||
emitQueue.async {
|
||||
for waiter in self.probeWait {
|
||||
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 }
|
||||
|
||||
for msg in postWait {
|
||||
ws.writeString(str: msg)
|
||||
ws.writeString(msg)
|
||||
}
|
||||
|
||||
postWait.removeAll(keepingCapacity: true)
|
||||
}
|
||||
|
||||
private func handleClose(reason: String) {
|
||||
client?.engineDidClose(reason: reason)
|
||||
private func handleClose(_ reason: String) {
|
||||
client?.engineDidClose(reason)
|
||||
}
|
||||
|
||||
private func handleMessage(_ message: String) {
|
||||
@ -363,11 +363,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
doPoll()
|
||||
}
|
||||
|
||||
private func handleOpen(openMessage: String) {
|
||||
let mesData = openMessage.data(using: NSUTF8StringEncoding, allowLossyConversion: false)!
|
||||
private func handleOpen(_ openMessage: String) {
|
||||
let mesData = openMessage.data(using: String.Encoding.utf8, allowLossyConversion: false)!
|
||||
do {
|
||||
let json = try NSJSONSerialization.jsonObject(with: mesData,
|
||||
options: NSJSONReadingOptions.allowFragments) as? NSDictionary
|
||||
let json = try JSONSerialization.jsonObject(with: mesData,
|
||||
options: JSONSerialization.ReadingOptions.allowFragments) as? NSDictionary
|
||||
if let sid = json?["sid"] as? String {
|
||||
let upgradeWs: Bool
|
||||
|
||||
@ -395,14 +395,14 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
doPoll()
|
||||
}
|
||||
|
||||
client?.engineDidOpen(reason: "Connect")
|
||||
client?.engineDidOpen("Connect")
|
||||
}
|
||||
} catch {
|
||||
didError(error: "Error parsing open packet")
|
||||
didError("Error parsing open packet")
|
||||
}
|
||||
}
|
||||
|
||||
private func handlePong(pongMessage: String) {
|
||||
private func handlePong(_ pongMessage: String) {
|
||||
pongsMissed = 0
|
||||
|
||||
// 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)
|
||||
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) {
|
||||
@ -431,7 +432,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
}
|
||||
|
||||
if fromPolling && type != .noop && doubleEncodeUTF8 {
|
||||
fixedString = fixDoubleUTF8(string: message)
|
||||
fixedString = fixDoubleUTF8(message)
|
||||
} else {
|
||||
fixedString = message
|
||||
}
|
||||
@ -443,12 +444,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
case .noop:
|
||||
handleNOOP()
|
||||
case .pong:
|
||||
handlePong(pongMessage: fixedString)
|
||||
handlePong(fixedString)
|
||||
case .open:
|
||||
handleOpen(openMessage:
|
||||
fixedString[fixedString.characters.index(after: fixedString.characters.startIndex)..<fixedString.endIndex])
|
||||
handleOpen(fixedString[fixedString.characters.index(after: fixedString.characters.startIndex)..<fixedString.endIndex])
|
||||
case .close:
|
||||
handleClose(reason: fixedString)
|
||||
handleClose(fixedString)
|
||||
default:
|
||||
DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType)
|
||||
}
|
||||
@ -462,9 +462,9 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
polling = true
|
||||
probing = false
|
||||
invalidated = false
|
||||
session = NSURLSession(configuration: .default(),
|
||||
session = URLSession(configuration: .default(),
|
||||
delegate: sessionDelegate,
|
||||
delegateQueue: NSOperationQueue())
|
||||
delegateQueue: OperationQueue())
|
||||
sid = ""
|
||||
waitingForPoll = false
|
||||
waitingForPost = false
|
||||
@ -478,7 +478,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
|
||||
//Server is not responding
|
||||
if pongsMissed > pongsMissedMax {
|
||||
client?.engineDidClose(reason: "Ping timeout")
|
||||
client?.engineDidClose("Ping timeout")
|
||||
return
|
||||
}
|
||||
|
||||
@ -486,8 +486,8 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
pongsMissed += 1
|
||||
write("", withType: .ping, withData: [])
|
||||
|
||||
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(pingInterval * Double(NSEC_PER_SEC)))
|
||||
dispatch_after(time, dispatch_get_main_queue()) {[weak self] in
|
||||
let time = DispatchTime.now() + Double(Int64(pingInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
|
||||
DispatchQueue.main.after(when: time) {[weak self] in
|
||||
self?.sendPing()
|
||||
}
|
||||
}
|
||||
@ -505,8 +505,8 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
}
|
||||
|
||||
/// Write a message, independent of transport.
|
||||
public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [NSData]) {
|
||||
dispatch_async(emitQueue) {
|
||||
public func write(_ msg: String, withType type: SocketEnginePacketType, withData data: [Data]) {
|
||||
emitQueue.async {
|
||||
guard self.connected else { return }
|
||||
|
||||
if self.websocket {
|
||||
@ -524,7 +524,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
}
|
||||
|
||||
// Delegate methods
|
||||
public func websocketDidConnect(socket: WebSocket) {
|
||||
public func websocketDidConnect(_ socket: WebSocket) {
|
||||
if !forceWebsockets {
|
||||
probing = true
|
||||
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
|
||||
|
||||
if closed {
|
||||
client?.engineDidClose(reason: "Disconnect")
|
||||
client?.engineDidClose("Disconnect")
|
||||
return
|
||||
}
|
||||
|
||||
@ -548,9 +548,9 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
||||
websocket = false
|
||||
|
||||
if let reason = error?.localizedDescription {
|
||||
didError(error: reason)
|
||||
didError(reason)
|
||||
} else {
|
||||
client?.engineDidClose(reason: "Socket Disconnected")
|
||||
client?.engineDidClose("Socket Disconnected")
|
||||
}
|
||||
} else {
|
||||
flushProbeWait()
|
||||
|
||||
@ -26,9 +26,9 @@
|
||||
import Foundation
|
||||
|
||||
@objc public protocol SocketEngineClient {
|
||||
func engineDidError(reason: String)
|
||||
func engineDidClose(reason: String)
|
||||
func engineDidOpen(reason: String)
|
||||
func engineDidError(_ reason: String)
|
||||
func engineDidClose(_ reason: String)
|
||||
func engineDidOpen(_ reason: String)
|
||||
func parseEngineMessage(_ msg: String)
|
||||
func parseEngineBinaryData(_ data: NSData)
|
||||
func parseEngineBinaryData(_ data: Data)
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
|
||||
/// Holds strings waiting to be sent over polling.
|
||||
/// You shouldn't need to mess with this.
|
||||
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
|
||||
/// we have to keep track if there's an outstanding poll
|
||||
var waitingForPoll: Bool { get set }
|
||||
@ -39,7 +39,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
|
||||
var waitingForPost: Bool { get set }
|
||||
|
||||
func doPoll()
|
||||
func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [NSData])
|
||||
func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data])
|
||||
func stopPolling()
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
|
||||
extension SocketEnginePollable {
|
||||
private func addHeaders(for req: NSMutableURLRequest) {
|
||||
if cookies != nil {
|
||||
let headers = NSHTTPCookie.requestHeaderFields(with: cookies!)
|
||||
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
||||
req.allHTTPHeaderFields = headers
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ extension SocketEnginePollable {
|
||||
}
|
||||
}
|
||||
|
||||
func createRequestForPostWithPostWait() -> NSURLRequest {
|
||||
func createRequestForPostWithPostWait() -> URLRequest {
|
||||
var postStr = ""
|
||||
|
||||
for packet in postWait {
|
||||
@ -71,20 +71,20 @@ extension SocketEnginePollable {
|
||||
|
||||
postWait.removeAll(keepingCapacity: false)
|
||||
|
||||
let req = NSMutableURLRequest(url: urlPollingWithSid)
|
||||
let req = NSMutableURLRequest(url: urlPollingWithSid as URL)
|
||||
|
||||
addHeaders(for: req)
|
||||
|
||||
req.httpMethod = "POST"
|
||||
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)!
|
||||
|
||||
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() {
|
||||
@ -93,13 +93,13 @@ extension SocketEnginePollable {
|
||||
}
|
||||
|
||||
waitingForPoll = true
|
||||
let req = NSMutableURLRequest(url: urlPollingWithSid)
|
||||
let req = NSMutableURLRequest(url: urlPollingWithSid as URL)
|
||||
|
||||
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 {
|
||||
DefaultSocketLogger.Logger.error("Tried to do polling request when not supposed to", type: "SocketEnginePolling")
|
||||
return
|
||||
@ -110,7 +110,7 @@ extension SocketEnginePollable {
|
||||
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
|
||||
guard let this = self where this.polling else { return }
|
||||
|
||||
@ -118,7 +118,7 @@ extension SocketEnginePollable {
|
||||
DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling")
|
||||
|
||||
if this.polling {
|
||||
this.didError(error: err?.localizedDescription ?? "Error")
|
||||
this.didError(err?.localizedDescription ?? "Error")
|
||||
}
|
||||
|
||||
return
|
||||
@ -126,8 +126,8 @@ extension SocketEnginePollable {
|
||||
|
||||
DefaultSocketLogger.Logger.log("Got polling response", type: "SocketEnginePolling")
|
||||
|
||||
if let str = String(data: data!, encoding: NSUTF8StringEncoding) {
|
||||
dispatch_async(this.parseQueue) {
|
||||
if let str = String(data: data!, encoding: String.Encoding.utf8) {
|
||||
this.parseQueue.async {
|
||||
this.parsePollingMessage(str)
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ extension SocketEnginePollable {
|
||||
DefaultSocketLogger.Logger.error(err?.localizedDescription ?? "Error", type: "SocketEnginePolling")
|
||||
|
||||
if this.polling {
|
||||
this.didError(error: err?.localizedDescription ?? "Error")
|
||||
this.didError(err?.localizedDescription ?? "Error")
|
||||
}
|
||||
|
||||
return
|
||||
@ -171,7 +171,7 @@ extension SocketEnginePollable {
|
||||
|
||||
this.waitingForPost = false
|
||||
|
||||
dispatch_async(this.emitQueue) {
|
||||
this.emitQueue.async {
|
||||
if !this.fastUpgrade {
|
||||
this.flushWaitingForPost()
|
||||
this.doPoll()
|
||||
@ -187,13 +187,13 @@ extension SocketEnginePollable {
|
||||
|
||||
while reader.hasNext {
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
dispatch_async(handleQueue) {
|
||||
handleQueue.async {
|
||||
self.parseEngineMessage(str, fromPolling: true)
|
||||
}
|
||||
break
|
||||
@ -203,12 +203,12 @@ extension SocketEnginePollable {
|
||||
|
||||
/// Send polling message.
|
||||
/// 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)
|
||||
let fixedMessage: String
|
||||
|
||||
if doubleEncodeUTF8 {
|
||||
fixedMessage = doubleEncodeUTF8(string: message)
|
||||
fixedMessage = doubleEncodeUTF8(message)
|
||||
} else {
|
||||
fixedMessage = message
|
||||
}
|
||||
@ -216,7 +216,7 @@ extension SocketEnginePollable {
|
||||
postWait.append(String(type.rawValue) + fixedMessage)
|
||||
|
||||
for data in datas {
|
||||
if case let .Right(bin) = createBinaryDataForSend(using: data) {
|
||||
if case let .right(bin) = createBinaryDataForSend(using: data) {
|
||||
postWait.append(bin)
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,77 +31,77 @@ import Foundation
|
||||
var connected: Bool { get }
|
||||
var connectParams: [String: AnyObject]? { get set }
|
||||
var doubleEncodeUTF8: Bool { get }
|
||||
var cookies: [NSHTTPCookie]? { get }
|
||||
var cookies: [HTTPCookie]? { get }
|
||||
var extraHeaders: [String: String]? { get }
|
||||
var fastUpgrade: Bool { get }
|
||||
var forcePolling: Bool { get }
|
||||
var forceWebsockets: Bool { get }
|
||||
var parseQueue: dispatch_queue_t { get }
|
||||
var parseQueue: DispatchQueue { get }
|
||||
var polling: Bool { get }
|
||||
var probing: Bool { get }
|
||||
var emitQueue: dispatch_queue_t { get }
|
||||
var handleQueue: dispatch_queue_t { get }
|
||||
var emitQueue: DispatchQueue { get }
|
||||
var handleQueue: DispatchQueue { get }
|
||||
var sid: String { get }
|
||||
var socketPath: String { get }
|
||||
var urlPolling: NSURL { get }
|
||||
var urlWebSocket: NSURL { get }
|
||||
var urlPolling: URL { get }
|
||||
var urlWebSocket: URL { get }
|
||||
var websocket: Bool { get }
|
||||
var ws: WebSocket? { get }
|
||||
|
||||
init(client: SocketEngineClient, url: NSURL, options: NSDictionary?)
|
||||
init(client: SocketEngineClient, url: URL, options: NSDictionary?)
|
||||
|
||||
func connect()
|
||||
func didError(error: String)
|
||||
func disconnect(reason: String)
|
||||
func didError(_ error: String)
|
||||
func disconnect(_ reason: String)
|
||||
func doFastUpgrade()
|
||||
func flushWaitingForPostToWebSocket()
|
||||
func parseEngineData(_ data: NSData)
|
||||
func parseEngineData(_ data: Data)
|
||||
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 {
|
||||
var urlPollingWithSid: NSURL {
|
||||
let com = NSURLComponents(url: urlPolling, resolvingAgainstBaseURL: false)!
|
||||
var urlPollingWithSid: URL {
|
||||
var com = URLComponents(url: urlPolling, resolvingAgainstBaseURL: false)!
|
||||
com.percentEncodedQuery = com.percentEncodedQuery! + "&sid=\(sid.urlEncode()!)"
|
||||
|
||||
return com.url!
|
||||
}
|
||||
|
||||
var urlWebSocketWithSid: NSURL {
|
||||
let com = NSURLComponents(url: urlWebSocket, resolvingAgainstBaseURL: false)!
|
||||
var urlWebSocketWithSid: URL {
|
||||
var com = URLComponents(url: urlWebSocket, resolvingAgainstBaseURL: false)!
|
||||
com.percentEncodedQuery = com.percentEncodedQuery! + (sid == "" ? "" : "&sid=\(sid.urlEncode()!)")
|
||||
|
||||
return com.url!
|
||||
}
|
||||
|
||||
func createBinaryDataForSend(using data: NSData) -> Either<NSData, String> {
|
||||
func createBinaryDataForSend(using data: Data) -> Either<Data, String> {
|
||||
if websocket {
|
||||
var byteArray = [UInt8](repeating: 0x4, count: 1)
|
||||
let mutData = NSMutableData(bytes: &byteArray, length: 1)
|
||||
|
||||
mutData.append(data)
|
||||
|
||||
return .Left(mutData)
|
||||
return .left(mutData as Data)
|
||||
} 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 {
|
||||
if let latin1 = string.data(using: NSUTF8StringEncoding),
|
||||
utf8 = NSString(data: latin1, encoding: NSISOLatin1StringEncoding) {
|
||||
func doubleEncodeUTF8(_ string: String) -> String {
|
||||
if let latin1 = string.data(using: String.Encoding.utf8),
|
||||
utf8 = NSString(data: latin1, encoding: String.Encoding.isoLatin1.rawValue) {
|
||||
return utf8 as String
|
||||
} else {
|
||||
return string
|
||||
}
|
||||
}
|
||||
|
||||
func fixDoubleUTF8(string: String) -> String {
|
||||
if let utf8 = string.data(using: NSISOLatin1StringEncoding),
|
||||
latin1 = NSString(data: utf8, encoding: NSUTF8StringEncoding) {
|
||||
func fixDoubleUTF8(_ string: String) -> String {
|
||||
if let utf8 = string.data(using: String.Encoding.isoLatin1),
|
||||
latin1 = NSString(data: utf8, encoding: String.Encoding.utf8.rawValue) {
|
||||
return latin1 as String
|
||||
} else {
|
||||
return string
|
||||
@ -109,7 +109,7 @@ extension SocketEngineSpec {
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ import Foundation
|
||||
|
||||
/// Protocol that is used to implement socket.io WebSocket support
|
||||
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
|
||||
@ -40,23 +40,23 @@ extension SocketEngineWebsocket {
|
||||
|
||||
/// Send message on WebSockets
|
||||
/// 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)
|
||||
|
||||
ws?.writeString(str: "\(type.rawValue)\(str)")
|
||||
ws?.writeString("\(type.rawValue)\(str)")
|
||||
|
||||
for data in datas {
|
||||
if case let .Left(bin) = createBinaryDataForSend(using: data) {
|
||||
ws?.writeData(data: bin)
|
||||
if case let .left(bin) = createBinaryDataForSend(using: data) {
|
||||
ws?.writeData(bin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
|
||||
public func websocketDidReceiveMessage(_ socket: WebSocket, text: String) {
|
||||
parseEngineMessage(text, fromPolling: false)
|
||||
}
|
||||
|
||||
public func websocketDidReceiveData(socket: WebSocket, data: NSData) {
|
||||
public func websocketDidReceiveData(_ socket: WebSocket, data: Data) {
|
||||
parseEngineData(data)
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,10 +26,10 @@ import Foundation
|
||||
|
||||
struct SocketEventHandler {
|
||||
let event: String
|
||||
let id: NSUUID
|
||||
let id: UUID
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
import Foundation
|
||||
|
||||
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 status = SocketIOClientStatus.notConnected {
|
||||
@ -49,9 +49,9 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
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 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 currentReconnectAttempt = 0
|
||||
@ -60,18 +60,18 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
private var reconnecting = false
|
||||
|
||||
private(set) var currentAck = -1
|
||||
private(set) var handleQueue = dispatch_get_main_queue()!
|
||||
private(set) var handleQueue = DispatchQueue.main
|
||||
private(set) var reconnectAttempts = -1
|
||||
|
||||
var waitingPackets = [SocketPacket]()
|
||||
|
||||
/// 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.socketURL = socketURL
|
||||
|
||||
if socketURL.absoluteString.hasPrefix("https://") {
|
||||
self.options.insertIgnore(element: .secure(true))
|
||||
if ((socketURL.absoluteString?.hasPrefix("https://")) != nil) {
|
||||
self.options.insertIgnore(.secure(true))
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
/// 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>)`
|
||||
public convenience init(socketURL: NSURL, options: NSDictionary?) {
|
||||
public convenience init(socketURL: URL, options: NSDictionary?) {
|
||||
self.init(socketURL: socketURL, options: options?.toSocketOptionsSet() ?? [])
|
||||
}
|
||||
|
||||
deinit {
|
||||
DefaultSocketLogger.Logger.log("Client is being released", type: logType)
|
||||
engine?.disconnect(reason: "Client Deinit")
|
||||
engine?.disconnect("Client Deinit")
|
||||
}
|
||||
|
||||
private func addEngine() -> SocketEngineSpec {
|
||||
@ -123,11 +123,11 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
|
||||
/// Connect to the server.
|
||||
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
|
||||
public func connect(timeoutAfter: Int, handleWith handler: (() -> Void)?) {
|
||||
public func connect(_ timeoutAfter: Int, handleWith handler: (() -> Void)?) {
|
||||
assert(timeoutAfter >= 0, "Invalid timeout: \(timeoutAfter)")
|
||||
|
||||
guard status != .connected else {
|
||||
@ -145,30 +145,30 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
|
||||
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 {
|
||||
this.status = .disconnected
|
||||
this.engine?.disconnect(reason: "Connect timeout")
|
||||
this.engine?.disconnect("Connect timeout")
|
||||
|
||||
handler?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func createOnAck(items: [AnyObject]) -> OnAckCallback {
|
||||
private func createOnAck(_ items: [AnyObject]) -> OnAckCallback {
|
||||
currentAck += 1
|
||||
|
||||
return {[weak self, ack = currentAck] timeout, callback in
|
||||
if let this = self {
|
||||
this.ackHandlers.addAck(ack, callback: callback)
|
||||
this._emit(data: items, ack: ack)
|
||||
this._emit(items, ack: ack)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -185,7 +185,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
handleEvent("connect", data: [], isInternalMessage: false)
|
||||
}
|
||||
|
||||
func didDisconnect(reason: String) {
|
||||
func didDisconnect(_ reason: String) {
|
||||
guard status != .disconnected else { return }
|
||||
|
||||
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
|
||||
@ -193,7 +193,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
status = .disconnected
|
||||
|
||||
// Make sure the engine is actually dead.
|
||||
engine?.disconnect(reason: reason)
|
||||
engine?.disconnect(reason)
|
||||
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)
|
||||
|
||||
didDisconnect(reason: "Disconnect")
|
||||
didDisconnect("Disconnect")
|
||||
}
|
||||
|
||||
/// Send a message to the server
|
||||
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
|
||||
@ -218,28 +218,28 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
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
|
||||
/// an ack.
|
||||
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
|
||||
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) {
|
||||
dispatch_async(emitQueue) {
|
||||
private func _emit(_ data: [AnyObject], ack: Int? = nil) {
|
||||
emitQueue.async {
|
||||
guard self.status == .connected else {
|
||||
self.handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true)
|
||||
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
|
||||
|
||||
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
|
||||
func emitAck(_ ack: Int, with items: [AnyObject]) {
|
||||
dispatch_async(emitQueue) {
|
||||
emitQueue.async {
|
||||
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
|
||||
|
||||
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()
|
||||
|
||||
if status != .disconnected {
|
||||
@ -270,21 +270,21 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
}
|
||||
|
||||
if status == .disconnected || !reconnects {
|
||||
didDisconnect(reason: reason)
|
||||
didDisconnect(reason)
|
||||
} else if !reconnecting {
|
||||
reconnecting = true
|
||||
tryReconnect(reason: reason)
|
||||
tryReconnect(reason)
|
||||
}
|
||||
}
|
||||
|
||||
/// error
|
||||
public func engineDidError(reason: String) {
|
||||
public func engineDidError(_ reason: String) {
|
||||
DefaultSocketLogger.Logger.error("%@", type: logType, args: reason)
|
||||
|
||||
handleEvent("error", data: [reason as AnyObject], isInternalMessage: true)
|
||||
}
|
||||
|
||||
public func engineDidOpen(reason: String) {
|
||||
public func engineDidOpen(_ reason: String) {
|
||||
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 ?? "")
|
||||
|
||||
dispatch_async(handleQueue) {
|
||||
handleQueue.async {
|
||||
self.anyHandler?(SocketAnyEvent(event: event, items: data))
|
||||
|
||||
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`
|
||||
public func off(id: NSUUID) {
|
||||
public func off(id: UUID) {
|
||||
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
|
||||
|
||||
handlers = handlers.filter({ $0.id != id })
|
||||
@ -347,22 +347,22 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
/// Adds a handler for an event.
|
||||
/// Returns: A unique id for the handler
|
||||
@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)
|
||||
|
||||
let handler = SocketEventHandler(event: event, id: NSUUID(), callback: callback)
|
||||
let handler = SocketEventHandler(event: event, id: UUID(), callback: callback)
|
||||
handlers.append(handler)
|
||||
|
||||
return handler.id
|
||||
return handler.id as UUID
|
||||
}
|
||||
|
||||
/// Adds a single-use handler for an event.
|
||||
/// Returns: A unique id for the handler
|
||||
@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)
|
||||
|
||||
let id = NSUUID()
|
||||
let id = UUID()
|
||||
|
||||
let handler = SocketEventHandler(event: event, id: id) {[weak self] data, ack in
|
||||
guard let this = self else { return }
|
||||
@ -372,24 +372,24 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
|
||||
handlers.append(handler)
|
||||
|
||||
return handler.id
|
||||
return handler.id as UUID
|
||||
}
|
||||
|
||||
/// Adds a handler that will be called on every event.
|
||||
public func onAny(handler: (SocketAnyEvent) -> Void) {
|
||||
public func onAny(_ handler: (SocketAnyEvent) -> Void) {
|
||||
anyHandler = handler
|
||||
}
|
||||
|
||||
public func parseEngineMessage(_ msg: String) {
|
||||
DefaultSocketLogger.Logger.log("Should parse message: %@", type: "SocketIOClient", args: msg)
|
||||
|
||||
dispatch_async(parseQueue) {
|
||||
parseQueue.async {
|
||||
self.parseSocketMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
public func parseEngineBinaryData(_ data: NSData) {
|
||||
dispatch_async(parseQueue) {
|
||||
public func parseEngineBinaryData(_ data: Data) {
|
||||
parseQueue.async {
|
||||
self.parseBinaryData(data)
|
||||
}
|
||||
}
|
||||
@ -398,7 +398,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
public func reconnect() {
|
||||
guard !reconnecting else { return }
|
||||
|
||||
engine?.disconnect(reason: "manual reconnect")
|
||||
engine?.disconnect("manual reconnect")
|
||||
}
|
||||
|
||||
/// Removes all handlers.
|
||||
@ -407,11 +407,11 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
handlers.removeAll(keepingCapacity: false)
|
||||
}
|
||||
|
||||
func socketDataToAnyObject(data: [SocketData]) -> [AnyObject] {
|
||||
func socketDataToAnyObject(_ data: [SocketData]) -> [AnyObject] {
|
||||
return data.flatMap({$0 as? AnyObject})
|
||||
}
|
||||
|
||||
private func tryReconnect(reason: String) {
|
||||
private func tryReconnect(_ reason: String) {
|
||||
if reconnecting {
|
||||
DefaultSocketLogger.Logger.log("Starting reconnect", type: logType)
|
||||
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 {
|
||||
return didDisconnect(reason: "Reconnect Failed")
|
||||
return didDisconnect("Reconnect Failed")
|
||||
}
|
||||
|
||||
DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType)
|
||||
@ -436,9 +436,9 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
||||
currentReconnectAttempt += 1
|
||||
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
|
||||
}
|
||||
|
||||
func setTestEngine(engine: SocketEngineSpec?) {
|
||||
func setTestEngine(_ engine: SocketEngineSpec?) {
|
||||
self.engine = engine
|
||||
}
|
||||
|
||||
func emitTest(event: String, _ data: AnyObject...) {
|
||||
self._emit(data: [event as AnyObject] + data)
|
||||
func emitTest(_ event: String, _ data: AnyObject...) {
|
||||
self._emit([event as AnyObject] + data)
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,13 +30,13 @@ protocol ClientOption : CustomStringConvertible, Hashable {
|
||||
|
||||
public enum SocketIOClientOption : ClientOption {
|
||||
case connectParams([String: AnyObject])
|
||||
case cookies([NSHTTPCookie])
|
||||
case cookies([HTTPCookie])
|
||||
case doubleEncodeUTF8(Bool)
|
||||
case extraHeaders([String: String])
|
||||
case forceNew(Bool)
|
||||
case forcePolling(Bool)
|
||||
case forceWebsockets(Bool)
|
||||
case handleQueue(dispatch_queue_t)
|
||||
case handleQueue(DispatchQueue)
|
||||
case log(Bool)
|
||||
case logger(SocketLogger)
|
||||
case nsp(String)
|
||||
@ -47,7 +47,7 @@ public enum SocketIOClientOption : ClientOption {
|
||||
case secure(Bool)
|
||||
case security(SSLSecurity)
|
||||
case selfSigned(Bool)
|
||||
case sessionDelegate(NSURLSessionDelegate)
|
||||
case sessionDelegate(URLSessionDelegate)
|
||||
case voipEnabled(Bool)
|
||||
|
||||
public var description: String {
|
||||
@ -158,7 +158,7 @@ public func ==(lhs: SocketIOClientOption, rhs: SocketIOClientOption) -> Bool {
|
||||
}
|
||||
|
||||
extension Set where Element : ClientOption {
|
||||
mutating func insertIgnore(element: Element) {
|
||||
mutating func insertIgnore(_ element: Element) {
|
||||
if !contains(element) {
|
||||
insert(element)
|
||||
}
|
||||
@ -166,11 +166,11 @@ extension Set where Element : ClientOption {
|
||||
}
|
||||
|
||||
extension NSDictionary {
|
||||
private static func keyValueToSocketIOClientOption(key: String, value: AnyObject) -> SocketIOClientOption? {
|
||||
private static func keyValueToSocketIOClientOption(_ key: String, value: AnyObject) -> SocketIOClientOption? {
|
||||
switch (key, value) {
|
||||
case let ("connectParams", params as [String: AnyObject]):
|
||||
return .connectParams(params)
|
||||
case let ("cookies", cookies as [NSHTTPCookie]):
|
||||
case let ("cookies", cookies as [HTTPCookie]):
|
||||
return .cookies(cookies)
|
||||
case let ("doubleEncodeUTF8", encode as Bool):
|
||||
return .doubleEncodeUTF8(encode)
|
||||
@ -182,7 +182,7 @@ extension NSDictionary {
|
||||
return .forcePolling(force)
|
||||
case let ("forceWebsockets", force as Bool):
|
||||
return .forceWebsockets(force)
|
||||
case let ("handleQueue", queue as dispatch_queue_t):
|
||||
case let ("handleQueue", queue as DispatchQueue):
|
||||
return .handleQueue(queue)
|
||||
case let ("log", log as Bool):
|
||||
return .log(log)
|
||||
@ -204,7 +204,7 @@ extension NSDictionary {
|
||||
return .security(security)
|
||||
case let ("selfSigned", selfSigned as Bool):
|
||||
return .selfSigned(selfSigned)
|
||||
case let ("sessionDelegate", delegate as NSURLSessionDelegate):
|
||||
case let ("sessionDelegate", delegate as URLSessionDelegate):
|
||||
return .sessionDelegate(delegate)
|
||||
case let ("voipEnabled", enable as Bool):
|
||||
return .voipEnabled(enable)
|
||||
@ -217,8 +217,8 @@ extension NSDictionary {
|
||||
var options = Set<SocketIOClientOption>()
|
||||
|
||||
for (rawKey, value) in self {
|
||||
if let key = rawKey as? String, opt = NSDictionary.keyValueToSocketIOClientOption(key: key, value: value) {
|
||||
options.insertIgnore(element: opt)
|
||||
if let key = rawKey as? String, opt = NSDictionary.keyValueToSocketIOClientOption(key, value: value) {
|
||||
options.insertIgnore(opt)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,15 +27,15 @@ protocol SocketIOClientSpec : class {
|
||||
var waitingPackets: [SocketPacket] { get set }
|
||||
|
||||
func didConnect()
|
||||
func didDisconnect(reason: String)
|
||||
func didError(reason: String)
|
||||
func didDisconnect(_ reason: String)
|
||||
func didError(_ reason: String)
|
||||
func handleAck(_ ack: Int, data: [AnyObject])
|
||||
func handleEvent(_ event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int)
|
||||
func joinNamespace(_ namespace: String)
|
||||
}
|
||||
|
||||
extension SocketIOClientSpec {
|
||||
func didError(reason: String) {
|
||||
func didError(_ reason: String) {
|
||||
DefaultSocketLogger.Logger.error("%@", type: "SocketIOClient", args: reason)
|
||||
|
||||
handleEvent("error", data: [reason as AnyObject], isInternalMessage: true, withAck: -1)
|
||||
|
||||
@ -35,18 +35,18 @@ struct SocketPacket {
|
||||
let type: PacketType
|
||||
|
||||
enum PacketType: Int {
|
||||
case Connect, Disconnect, Event, Ack, Error, BinaryEvent, BinaryAck
|
||||
case connect, disconnect, event, ack, error, binaryEvent, binaryAck
|
||||
}
|
||||
|
||||
var args: [AnyObject] {
|
||||
if type == .Event || type == .BinaryEvent && data.count != 0 {
|
||||
if type == .event || type == .binaryEvent && data.count != 0 {
|
||||
return Array(data.dropFirst())
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
var binary: [NSData]
|
||||
var binary: [Data]
|
||||
var data: [AnyObject]
|
||||
var description: String {
|
||||
return "SocketPacket {type: \(String(type.rawValue)); data: " +
|
||||
@ -62,7 +62,7 @@ struct SocketPacket {
|
||||
}
|
||||
|
||||
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.id = id
|
||||
self.nsp = nsp
|
||||
@ -71,7 +71,7 @@ struct SocketPacket {
|
||||
self.binary = binary
|
||||
}
|
||||
|
||||
mutating func addData(_ data: NSData) -> Bool {
|
||||
mutating func addData(_ data: Data) -> Bool {
|
||||
if placeholders == binary.count {
|
||||
return true
|
||||
}
|
||||
@ -94,9 +94,9 @@ struct SocketPacket {
|
||||
}
|
||||
|
||||
do {
|
||||
let jsonSend = try NSJSONSerialization.data(withJSONObject: data as AnyObject,
|
||||
options: NSJSONWritingOptions(rawValue: 0))
|
||||
guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else {
|
||||
let jsonSend = try JSONSerialization.data(withJSONObject: data as AnyObject,
|
||||
options: JSONSerialization.WritingOptions(rawValue: 0))
|
||||
guard let jsonString = String(data: jsonSend, encoding: String.Encoding.utf8) else {
|
||||
return message + "[]"
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ struct SocketPacket {
|
||||
let nspString: String
|
||||
let idString: String
|
||||
|
||||
if type == .BinaryEvent || type == .BinaryAck {
|
||||
if type == .binaryEvent || type == .binaryAck {
|
||||
binaryCountString = typeString + String(binary.count) + "-"
|
||||
} else {
|
||||
binaryCountString = typeString
|
||||
@ -172,19 +172,19 @@ extension SocketPacket {
|
||||
private static func findType(_ binCount: Int, ack: Bool) -> PacketType {
|
||||
switch binCount {
|
||||
case 0 where !ack:
|
||||
return .Event
|
||||
return .event
|
||||
case 0 where ack:
|
||||
return .Ack
|
||||
return .ack
|
||||
case _ where !ack:
|
||||
return .BinaryEvent
|
||||
return .binaryEvent
|
||||
case _ where ack:
|
||||
return .BinaryAck
|
||||
return .binaryAck
|
||||
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 packet = SocketPacket(type: findType(binary.count, ack: ack), data: parsedData,
|
||||
id: id, nsp: nsp, binary: binary)
|
||||
@ -195,11 +195,11 @@ extension SocketPacket {
|
||||
|
||||
private extension SocketPacket {
|
||||
// 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]
|
||||
|
||||
switch data {
|
||||
case let bin as NSData:
|
||||
case let bin as Data:
|
||||
binary.append(bin)
|
||||
return placeholder as AnyObject
|
||||
case let arr as [AnyObject]:
|
||||
@ -216,8 +216,8 @@ private extension SocketPacket {
|
||||
|
||||
// Removes binary data from emit data
|
||||
// Returns a type containing the de-binaryed data and the binary
|
||||
static func deconstructData(_ data: [AnyObject]) -> ([AnyObject], [NSData]) {
|
||||
var binary = [NSData]()
|
||||
static func deconstructData(_ data: [AnyObject]) -> ([AnyObject], [Data]) {
|
||||
var binary = [Data]()
|
||||
|
||||
return (data.map({shred($0, binary: &binary)}), binary)
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
import Foundation
|
||||
|
||||
protocol SocketParsable : SocketIOClientSpec {
|
||||
func parseBinaryData(_ data: NSData)
|
||||
func parseBinaryData(_ data: Data)
|
||||
func parseSocketMessage(_ message: String)
|
||||
}
|
||||
|
||||
@ -42,19 +42,19 @@ extension SocketParsable {
|
||||
|
||||
private func handlePacket(_ pack: SocketPacket) {
|
||||
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)
|
||||
case .Ack where isCorrectNamespace(pack.nsp):
|
||||
case .ack where isCorrectNamespace(pack.nsp):
|
||||
handleAck(pack.id, data: pack.data)
|
||||
case .BinaryEvent where isCorrectNamespace(pack.nsp):
|
||||
case .binaryEvent where isCorrectNamespace(pack.nsp):
|
||||
waitingPackets.append(pack)
|
||||
case .BinaryAck where isCorrectNamespace(pack.nsp):
|
||||
case .binaryAck where isCorrectNamespace(pack.nsp):
|
||||
waitingPackets.append(pack)
|
||||
case .Connect:
|
||||
case .connect:
|
||||
handleConnect(pack)
|
||||
case .Disconnect:
|
||||
didDisconnect(reason: "Got Disconnect")
|
||||
case .Error:
|
||||
case .disconnect:
|
||||
didDisconnect("Got Disconnect")
|
||||
case .error:
|
||||
handleEvent("error", data: pack.data, isInternalMessage: true, withAck: pack.id)
|
||||
default:
|
||||
DefaultSocketLogger.Logger.log("Got invalid packet: %@", type: "SocketParser", args: pack.description)
|
||||
@ -65,22 +65,22 @@ extension SocketParsable {
|
||||
func parseString(_ message: String) -> Either<String, SocketPacket> {
|
||||
var parser = SocketStringReader(message: message)
|
||||
|
||||
guard let type = SocketPacket.PacketType(rawValue: Int(parser.read(length: 1)) ?? -1) else {
|
||||
return .Left("Invalid packet type")
|
||||
guard let type = SocketPacket.PacketType(rawValue: Int(parser.read(1)) ?? -1) else {
|
||||
return .left("Invalid packet type")
|
||||
}
|
||||
|
||||
if !parser.hasNext {
|
||||
return .Right(SocketPacket(type: type, nsp: "/"))
|
||||
return .right(SocketPacket(type: type, nsp: "/"))
|
||||
}
|
||||
|
||||
var namespace = "/"
|
||||
var placeholders = -1
|
||||
|
||||
if type == .BinaryEvent || type == .BinaryAck {
|
||||
if type == .binaryEvent || type == .binaryAck {
|
||||
if let holders = Int(parser.readUntilStringOccurence("-")) {
|
||||
placeholders = holders
|
||||
} else {
|
||||
return .Left("Invalid packet")
|
||||
return .left("Invalid packet")
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,53 +89,53 @@ extension SocketParsable {
|
||||
}
|
||||
|
||||
if !parser.hasNext {
|
||||
return .Right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
|
||||
return .right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
|
||||
}
|
||||
|
||||
var idString = ""
|
||||
|
||||
if type == .Error {
|
||||
parser.advance(by: -1)
|
||||
if type == .error {
|
||||
parser.advance(-1)
|
||||
} else {
|
||||
while parser.hasNext {
|
||||
if let int = Int(parser.read(length: 1)) {
|
||||
if let int = Int(parser.read(1)) {
|
||||
idString += String(int)
|
||||
} else {
|
||||
parser.advance(by: -2)
|
||||
parser.advance(-2)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let d = message[parser.advance(by: 1)..<message.endIndex]
|
||||
let d = message[parser.advance(1)..<message.endIndex]
|
||||
|
||||
switch parseData(d) {
|
||||
case let .Left(err):
|
||||
case let .left(err):
|
||||
// Errors aren't always enclosed in an array
|
||||
if case let .Right(data) = parseData("\([d as AnyObject])") {
|
||||
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
||||
if case let .right(data) = parseData("\([d as AnyObject])") {
|
||||
return .right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
||||
nsp: namespace, placeholders: placeholders))
|
||||
} else {
|
||||
return .Left(err)
|
||||
return .left(err)
|
||||
}
|
||||
case let .Right(data):
|
||||
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
||||
case let .right(data):
|
||||
return .right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
||||
nsp: namespace, placeholders: placeholders))
|
||||
}
|
||||
}
|
||||
|
||||
// Parses data for events
|
||||
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 {
|
||||
if let arr = try NSJSONSerialization.jsonObject(with: stringData!,
|
||||
options: NSJSONReadingOptions.mutableContainers) as? [AnyObject] {
|
||||
return .Right(arr)
|
||||
if let arr = try JSONSerialization.jsonObject(with: stringData!,
|
||||
options: JSONSerialization.ReadingOptions.mutableContainers) as? [AnyObject] {
|
||||
return .right(arr)
|
||||
} else {
|
||||
return .Left("Expected data array")
|
||||
return .left("Expected data array")
|
||||
}
|
||||
} 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)
|
||||
|
||||
switch parseString(message) {
|
||||
case let .Left(err):
|
||||
case let .left(err):
|
||||
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)
|
||||
handlePacket(pack)
|
||||
}
|
||||
}
|
||||
|
||||
func parseBinaryData(_ data: NSData) {
|
||||
func parseBinaryData(_ data: Data) {
|
||||
guard !waitingPackets.isEmpty else {
|
||||
DefaultSocketLogger.Logger.error("Got data when not remaking packet", type: "SocketParser")
|
||||
return
|
||||
@ -165,7 +165,7 @@ extension SocketParsable {
|
||||
|
||||
let packet = waitingPackets.removeLast()
|
||||
|
||||
if packet.type != .BinaryAck {
|
||||
if packet.type != .binaryAck {
|
||||
handleEvent(packet.event, data: packet.args ?? [],
|
||||
isInternalMessage: false, withAck: packet.id)
|
||||
} else {
|
||||
|
||||
@ -39,15 +39,15 @@ struct SocketStringReader {
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
mutating func advance(by: Int) -> String.Index {
|
||||
mutating func advance(_ by: Int) -> String.Index {
|
||||
currentIndex = message.characters.index(currentIndex, offsetBy: by)
|
||||
|
||||
return currentIndex
|
||||
}
|
||||
|
||||
mutating func read(length: Int) -> String {
|
||||
mutating func read(_ length: Int) -> String {
|
||||
let readString = message[currentIndex..<message.characters.index(currentIndex, offsetBy: length)]
|
||||
advance(by: length)
|
||||
advance(length)
|
||||
|
||||
return readString
|
||||
}
|
||||
@ -60,12 +60,12 @@ struct SocketStringReader {
|
||||
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)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ extension Dictionary : SocketData {}
|
||||
extension Double : SocketData {}
|
||||
extension Int : SocketData {}
|
||||
extension NSArray : SocketData {}
|
||||
extension NSData : SocketData {}
|
||||
extension Data : SocketData {}
|
||||
extension NSDictionary : SocketData {}
|
||||
extension NSString : SocketData {}
|
||||
extension NSNull : SocketData {}
|
||||
@ -42,10 +42,10 @@ public typealias AckCallback = ([AnyObject]) -> Void
|
||||
public typealias NormalCallback = ([AnyObject], SocketAckEmitter) -> 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]
|
||||
|
||||
enum Either<E, V> {
|
||||
case Left(E)
|
||||
case Right(V)
|
||||
case left(E)
|
||||
case right(V)
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ import Foundation
|
||||
import Security
|
||||
|
||||
public class SSLCert : NSObject {
|
||||
var certData: NSData?
|
||||
var certData: Data?
|
||||
var key: SecKey?
|
||||
|
||||
/**
|
||||
@ -34,7 +34,7 @@ public class SSLCert : NSObject {
|
||||
|
||||
- returns: a representation security object to be used with
|
||||
*/
|
||||
public init(data: NSData) {
|
||||
public init(data: Data) {
|
||||
self.certData = data
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ public class SSLSecurity : NSObject {
|
||||
public var validatedDN = true //should the domain name be validated?
|
||||
|
||||
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 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
|
||||
*/
|
||||
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
|
||||
var certs = certs
|
||||
if let data = NSData(contentsOfFile: path) {
|
||||
certs.append(SSLCert(data: data))
|
||||
certs.append(SSLCert(data: data as Data))
|
||||
}
|
||||
return certs
|
||||
}
|
||||
@ -93,11 +93,11 @@ public class SSLSecurity : NSObject {
|
||||
self.usePublicKeys = 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
|
||||
var pubKeys = pubKeys
|
||||
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 {
|
||||
pubKeys.append(key)
|
||||
@ -109,7 +109,7 @@ public class SSLSecurity : NSObject {
|
||||
self.isReady = true
|
||||
}
|
||||
} 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
|
||||
if let data = cert.certData {
|
||||
certificates.append(data)
|
||||
@ -129,7 +129,7 @@ public class SSLSecurity : NSObject {
|
||||
|
||||
- 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
|
||||
while(!self.isReady) {
|
||||
@ -141,14 +141,14 @@ public class SSLSecurity : NSObject {
|
||||
}
|
||||
var policy: SecPolicy
|
||||
if self.validatedDN {
|
||||
policy = SecPolicyCreateSSL(true, domain)
|
||||
policy = SecPolicyCreateSSL(true, domain)!
|
||||
} else {
|
||||
policy = SecPolicyCreateBasicX509()
|
||||
policy = SecPolicyCreateBasicX509()!
|
||||
}
|
||||
SecTrustSetPolicies(trust,policy)
|
||||
if self.usePublicKeys {
|
||||
if let keys = self.pubKeys {
|
||||
let serverPubKeys = publicKeyChainForTrust(trust: trust)
|
||||
let serverPubKeys = publicKeyChainForTrust(trust)
|
||||
for serverKey in serverPubKeys as [AnyObject] {
|
||||
for key in keys as [AnyObject] {
|
||||
if serverKey.isEqual(key) {
|
||||
@ -158,16 +158,16 @@ public class SSLSecurity : NSObject {
|
||||
}
|
||||
}
|
||||
} else if let certs = self.certificates {
|
||||
let serverCerts = certificateChainForTrust(trust: trust)
|
||||
let serverCerts = certificateChainForTrust(trust)
|
||||
var collect = [SecCertificate]()
|
||||
for cert in certs {
|
||||
collect.append(SecCertificateCreateWithData(nil,cert)!)
|
||||
}
|
||||
SecTrustSetAnchorCertificates(trust,collect)
|
||||
var result: SecTrustResultType = 0
|
||||
var result = SecTrustResultType(rawValue: 0)!
|
||||
SecTrustEvaluate(trust,&result)
|
||||
let r = Int(result)
|
||||
if r == kSecTrustResultUnspecified || r == kSecTrustResultProceed {
|
||||
let r = Int(result.rawValue)
|
||||
if r == Int(SecTrustResultType.unspecified.rawValue) || r == Int(SecTrustResultType.proceed.rawValue) {
|
||||
var trustedCount = 0
|
||||
for serverCert in serverCerts {
|
||||
for cert in certs {
|
||||
@ -192,10 +192,10 @@ public class SSLSecurity : NSObject {
|
||||
|
||||
- returns: a public key
|
||||
*/
|
||||
func extractPublicKey(data: NSData) -> SecKey? {
|
||||
func extractPublicKey(_ data: Data) -> SecKey? {
|
||||
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
|
||||
*/
|
||||
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKey? {
|
||||
func extractPublicKeyFromCert(_ cert: SecCertificate, policy: SecPolicy) -> SecKey? {
|
||||
var possibleTrust: SecTrust?
|
||||
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
|
||||
|
||||
guard let trust = possibleTrust else { return nil }
|
||||
|
||||
var result: SecTrustResultType = 0
|
||||
var result = SecTrustResultType(rawValue: 0)!
|
||||
SecTrustEvaluate(trust, &result)
|
||||
return SecTrustCopyPublicKey(trust)
|
||||
}
|
||||
@ -223,11 +223,11 @@ public class SSLSecurity : NSObject {
|
||||
|
||||
- returns: the certificate chain for the trust
|
||||
*/
|
||||
func certificateChainForTrust(trust: SecTrust) -> [NSData] {
|
||||
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([NSData]()) { (certificates: [NSData], index: Int) -> [NSData] in
|
||||
func certificateChainForTrust(_ trust: SecTrust) -> [Data] {
|
||||
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([Data]()) { (certificates: [Data], index: Int) -> [Data] in
|
||||
var certificates = certificates
|
||||
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
||||
certificates.append(SecCertificateCopyData(cert!))
|
||||
certificates.append(SecCertificateCopyData(cert!) as Data)
|
||||
return certificates
|
||||
}
|
||||
|
||||
@ -241,12 +241,12 @@ public class SSLSecurity : NSObject {
|
||||
|
||||
- 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 keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKey]()) { (keys: [SecKey], index: Int) -> [SecKey] in
|
||||
var keys = keys
|
||||
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
||||
if let key = extractPublicKeyFromCert(cert: cert!, policy: policy) {
|
||||
if let key = extractPublicKeyFromCert(cert!, policy: policy!) {
|
||||
keys.append(key)
|
||||
}
|
||||
|
||||
@ -257,4 +257,4 @@ public class SSLSecurity : NSObject {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,40 +28,40 @@ public let WebsocketDidDisconnectNotification = "WebsocketDidDisconnectNotificat
|
||||
public let WebsocketDisconnectionErrorKeyName = "WebsocketDisconnectionErrorKeyName"
|
||||
|
||||
public protocol WebSocketDelegate: class {
|
||||
func websocketDidConnect(socket: WebSocket)
|
||||
func websocketDidDisconnect(socket: WebSocket, error: NSError?)
|
||||
func websocketDidReceiveMessage(socket: WebSocket, text: String)
|
||||
func websocketDidReceiveData(socket: WebSocket, data: NSData)
|
||||
func websocketDidConnect(_ socket: WebSocket)
|
||||
func websocketDidDisconnect(_ socket: WebSocket, error: NSError?)
|
||||
func websocketDidReceiveMessage(_ socket: WebSocket, text: String)
|
||||
func websocketDidReceiveData(_ socket: WebSocket, data: Data)
|
||||
}
|
||||
|
||||
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 {
|
||||
case ContinueFrame = 0x0
|
||||
case TextFrame = 0x1
|
||||
case BinaryFrame = 0x2
|
||||
case continueFrame = 0x0
|
||||
case textFrame = 0x1
|
||||
case binaryFrame = 0x2
|
||||
//3-7 are reserved.
|
||||
case ConnectionClose = 0x8
|
||||
case Ping = 0x9
|
||||
case Pong = 0xA
|
||||
case connectionClose = 0x8
|
||||
case ping = 0x9
|
||||
case pong = 0xA
|
||||
//B-F reserved.
|
||||
}
|
||||
|
||||
public enum CloseCode : UInt16 {
|
||||
case Normal = 1000
|
||||
case GoingAway = 1001
|
||||
case ProtocolError = 1002
|
||||
case ProtocolUnhandledType = 1003
|
||||
case normal = 1000
|
||||
case goingAway = 1001
|
||||
case protocolError = 1002
|
||||
case protocolUnhandledType = 1003
|
||||
// 1004 reserved.
|
||||
case NoStatusReceived = 1005
|
||||
case noStatusReceived = 1005
|
||||
//1006 reserved.
|
||||
case Encoding = 1007
|
||||
case PolicyViolated = 1008
|
||||
case MessageTooBig = 1009
|
||||
case encoding = 1007
|
||||
case policyViolated = 1008
|
||||
case messageTooBig = 1009
|
||||
}
|
||||
|
||||
#if swift(>=3)
|
||||
@ -71,11 +71,11 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
|
||||
enum InternalErrorCode : UInt16 {
|
||||
// 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.
|
||||
public var queue = dispatch_get_main_queue()
|
||||
public var queue = DispatchQueue.main
|
||||
|
||||
var optionalProtocols : [String]?
|
||||
//Constant Values.
|
||||
@ -100,7 +100,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
|
||||
class WSResponse {
|
||||
var isFin = false
|
||||
var code: OpCode = .ContinueFrame
|
||||
var code: OpCode = .continueFrame
|
||||
var bytesLeft = 0
|
||||
var frameCount = 0
|
||||
var buffer: NSMutableData?
|
||||
@ -111,7 +111,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
public var onConnect: ((Void) -> Void)?
|
||||
public var onDisconnect: ((NSError?) -> Void)?
|
||||
public var onText: ((String) -> Void)?
|
||||
public var onData: ((NSData) -> Void)?
|
||||
public var onData: ((Data) -> Void)?
|
||||
public var onPong: ((Void) -> Void)?
|
||||
public var headers = [String: String]()
|
||||
public var voipEnabled = false
|
||||
@ -123,21 +123,21 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
public var isConnected :Bool {
|
||||
return connected
|
||||
}
|
||||
public var currentURL: NSURL {return url}
|
||||
private var url: NSURL
|
||||
private var inputStream: NSInputStream?
|
||||
public var currentURL: URL {return url}
|
||||
private var url: URL
|
||||
private var inputStream: InputStream?
|
||||
private var outputStream: NSOutputStream?
|
||||
private var connected = false
|
||||
private var isCreated = false
|
||||
private var writeQueue = NSOperationQueue()
|
||||
private var writeQueue = OperationQueue()
|
||||
private var readStack = [WSResponse]()
|
||||
private var inputQueue = [NSData]()
|
||||
private var fragBuffer: NSData?
|
||||
private var inputQueue = [Data]()
|
||||
private var fragBuffer: Data?
|
||||
private var certValidated = false
|
||||
private var didDisconnect = false
|
||||
private var readyToWrite = false
|
||||
private let mutex = NSLock()
|
||||
private let notificationCenter = NSNotificationCenter.default()
|
||||
private let mutex = Lock()
|
||||
private let notificationCenter = NotificationCenter.default()
|
||||
private var canDispatch: Bool {
|
||||
mutex.lock()
|
||||
let canWork = readyToWrite
|
||||
@ -145,10 +145,10 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
return canWork
|
||||
}
|
||||
//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.
|
||||
public init(url: NSURL, protocols: [String]? = nil) {
|
||||
public init(url: URL, protocols: [String]? = nil) {
|
||||
self.url = url
|
||||
self.origin = url.absoluteString
|
||||
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.
|
||||
*/
|
||||
public func disconnect(forceTimeout: NSTimeInterval? = nil) {
|
||||
public func disconnect(_ forceTimeout: TimeInterval? = nil) {
|
||||
switch forceTimeout {
|
||||
case .some(let seconds) where seconds > 0:
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC))), queue!) { [weak self] in
|
||||
self?.disconnectStream(error: nil)
|
||||
queue.after(when: DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { [weak self] in
|
||||
self?.disconnectStream(nil)
|
||||
}
|
||||
fallthrough
|
||||
case .none:
|
||||
writeError(code: CloseCode.Normal.rawValue)
|
||||
writeError(CloseCode.normal.rawValue)
|
||||
|
||||
default:
|
||||
self.disconnectStream(error: nil)
|
||||
self.disconnectStream(nil)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -197,9 +197,9 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
- parameter str: The string to write.
|
||||
- parameter completion: The (optional) completion handler.
|
||||
*/
|
||||
public func writeString(str: String, completion: (() -> ())? = nil) {
|
||||
public func writeString(_ str: String, completion: (() -> ())? = nil) {
|
||||
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 completion: The (optional) completion handler.
|
||||
*/
|
||||
public func writeData(data: NSData, completion: (() -> ())? = nil) {
|
||||
public func writeData(_ data: Data, completion: (() -> ())? = nil) {
|
||||
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.
|
||||
//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 }
|
||||
dequeueWrite(data: data, code: .Ping, writeCompletion: completion)
|
||||
dequeueWrite(data, code: .ping, writeCompletion: completion)
|
||||
}
|
||||
|
||||
//private method that starts the connection
|
||||
@ -230,34 +230,34 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
|
||||
var port = url.port
|
||||
if port == nil {
|
||||
if ["wss", "https"].contains(url.scheme) {
|
||||
if ["wss", "https"].contains(url.scheme!) {
|
||||
port = 443
|
||||
} else {
|
||||
port = 80
|
||||
}
|
||||
}
|
||||
addHeader(urlRequest: urlRequest, key: headerWSUpgradeName as NSString, val: headerWSUpgradeValue as NSString)
|
||||
addHeader(urlRequest: urlRequest, key: headerWSConnectionName as NSString, val: headerWSConnectionValue as NSString)
|
||||
addHeader(urlRequest, key: headerWSUpgradeName as NSString, val: headerWSUpgradeValue as NSString)
|
||||
addHeader(urlRequest, key: headerWSConnectionName as NSString, val: headerWSConnectionValue as NSString)
|
||||
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: urlRequest, key: headerWSKeyName as NSString, val: generateWebSocketKey() as NSString)
|
||||
addHeader(urlRequest, key: headerWSVersionName as NSString, val: headerWSVersionValue as NSString)
|
||||
addHeader(urlRequest, key: headerWSKeyName as NSString, val: generateWebSocketKey() as NSString)
|
||||
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 {
|
||||
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) {
|
||||
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
|
||||
private func addHeader(urlRequest: CFHTTPMessage, key: NSString, val: NSString) {
|
||||
private func addHeader(_ urlRequest: CFHTTPMessage, key: NSString, val: NSString) {
|
||||
CFHTTPMessageSetHeaderFieldValue(urlRequest, key, val)
|
||||
}
|
||||
|
||||
@ -269,13 +269,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
let uni = UnicodeScalar(UInt32(97 + arc4random_uniform(25)))
|
||||
key += "\(Character(uni))"
|
||||
}
|
||||
let data = key.data(using: NSUTF8StringEncoding)
|
||||
let baseKey = data?.base64EncodedString(NSDataBase64EncodingOptions(rawValue: 0))
|
||||
let data = key.data(using: String.Encoding.utf8)
|
||||
let baseKey = data?.base64EncodedString(NSData.Base64EncodingOptions(rawValue: 0))
|
||||
return baseKey!
|
||||
}
|
||||
|
||||
//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
|
||||
//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 }
|
||||
inStream.delegate = self
|
||||
outStream.delegate = self
|
||||
if ["wss", "https"].contains(url.scheme) {
|
||||
inStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL as NSString, forKey: NSStreamSocketSecurityLevelKey)
|
||||
outStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL as NSString, forKey: NSStreamSocketSecurityLevelKey)
|
||||
if ["wss", "https"].contains(url.scheme!) {
|
||||
inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as NSString, forKey: Stream.PropertyKey.socketSecurityLevelKey.rawValue)
|
||||
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as NSString, forKey: Stream.PropertyKey.socketSecurityLevelKey.rawValue)
|
||||
} else {
|
||||
certValidated = true //not a https session, so no need to check SSL pinning
|
||||
}
|
||||
if voipEnabled {
|
||||
inStream.setProperty(NSStreamNetworkServiceTypeVoIP as NSString, forKey: NSStreamNetworkServiceType)
|
||||
outStream.setProperty(NSStreamNetworkServiceTypeVoIP as NSString, forKey: NSStreamNetworkServiceType)
|
||||
inStream.setProperty(StreamNetworkServiceTypeValue.voip as NSString, forKey: Stream.PropertyKey.networkServiceType.rawValue)
|
||||
outStream.setProperty(StreamNetworkServiceTypeValue.voip as NSString, forKey: Stream.PropertyKey.networkServiceType.rawValue)
|
||||
}
|
||||
if selfSignedSSL {
|
||||
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)
|
||||
}
|
||||
if let cipherSuites = self.enabledSSLCipherSuites {
|
||||
if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContext?,
|
||||
sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContext? {
|
||||
if let sslContextIn = CFReadStreamCopyProperty(inputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext?,
|
||||
sslContextOut = CFWriteStreamCopyProperty(outputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext? {
|
||||
let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count)
|
||||
let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count)
|
||||
if resIn != errSecSuccess {
|
||||
let error = self.errorWithDetail(detail: "Error setting ingoing cypher suites", code: UInt16(resIn))
|
||||
disconnectStream(error: error)
|
||||
let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn))
|
||||
disconnectStream(error)
|
||||
return
|
||||
}
|
||||
if resOut != errSecSuccess {
|
||||
let error = self.errorWithDetail(detail: "Error setting outgoing cypher suites", code: UInt16(resOut))
|
||||
disconnectStream(error: error)
|
||||
let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut))
|
||||
disconnectStream(error)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -329,7 +329,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
self.readyToWrite = true
|
||||
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
|
||||
writeQueue.addOperation { [weak self] in
|
||||
while !outStream.hasSpaceAvailable {
|
||||
@ -337,27 +337,27 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
out -= 100
|
||||
if out < 0 {
|
||||
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
|
||||
} else if outStream.streamError != nil {
|
||||
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
|
||||
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) {
|
||||
let possibleTrust: AnyObject? = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as String)
|
||||
if let trust: AnyObject = possibleTrust {
|
||||
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
|
||||
} else {
|
||||
let error = errorWithDetail(detail: "Invalid SSL certificate", code: 1)
|
||||
disconnectStream(error: error)
|
||||
let error = errorWithDetail("Invalid SSL certificate", code: 1)
|
||||
disconnectStream(error)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -367,20 +367,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
processInputStream()
|
||||
}
|
||||
} else if eventCode == .errorOccurred {
|
||||
disconnectStream(error: aStream.streamError)
|
||||
disconnectStream(aStream.streamError)
|
||||
} else if eventCode == .endEncountered {
|
||||
disconnectStream(error: nil)
|
||||
disconnectStream(nil)
|
||||
}
|
||||
}
|
||||
//disconnect the stream object
|
||||
private func disconnectStream(error: NSError?) {
|
||||
private func disconnectStream(_ error: NSError?) {
|
||||
if error == nil {
|
||||
writeQueue.waitUntilAllOperationsAreFinished()
|
||||
} else {
|
||||
writeQueue.cancelAllOperations()
|
||||
}
|
||||
cleanupStream()
|
||||
doDisconnect(error: error)
|
||||
doDisconnect(error)
|
||||
}
|
||||
|
||||
private func cleanupStream() {
|
||||
@ -409,7 +409,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
if inputQueue.count == 0 {
|
||||
process = true
|
||||
}
|
||||
inputQueue.append(NSData(bytes: buffer, length: length))
|
||||
inputQueue.append(Data(bytes: UnsafePointer<UInt8>(buffer), count: length))
|
||||
if process {
|
||||
dequeueInput()
|
||||
}
|
||||
@ -420,44 +420,44 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
let data = inputQueue[0]
|
||||
var work = data
|
||||
if let fragBuffer = fragBuffer {
|
||||
let combine = NSMutableData(data: fragBuffer)
|
||||
var combine = NSData(data: fragBuffer) as Data
|
||||
combine.append(data)
|
||||
work = combine
|
||||
self.fragBuffer = nil
|
||||
}
|
||||
let buffer = UnsafePointer<UInt8>(work.bytes)
|
||||
let length = work.length
|
||||
let buffer = UnsafePointer<UInt8>((work as NSData).bytes)
|
||||
let length = work.count
|
||||
if !connected {
|
||||
processTCPHandshake(buffer: buffer, bufferLen: length)
|
||||
processTCPHandshake(buffer, bufferLen: length)
|
||||
} else {
|
||||
processRawMessagesInBuffer(pointer: buffer, bufferLen: length)
|
||||
processRawMessagesInBuffer(buffer, bufferLen: length)
|
||||
}
|
||||
inputQueue = inputQueue.filter{$0 != data}
|
||||
}
|
||||
}
|
||||
|
||||
//handle checking the inital connection status
|
||||
private func processTCPHandshake(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
||||
let code = processHTTP(buffer: buffer, bufferLen: bufferLen)
|
||||
private func processTCPHandshake(_ buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
||||
let code = processHTTP(buffer, bufferLen: bufferLen)
|
||||
switch code {
|
||||
case 0:
|
||||
connected = true
|
||||
guard canDispatch else {return}
|
||||
dispatch_async(queue!) { [weak self] in
|
||||
queue.async { [weak self] in
|
||||
guard let s = self else { return }
|
||||
s.onConnect?()
|
||||
s.delegate?.websocketDidConnect(socket: s)
|
||||
s.notificationCenter.post(name: WebsocketDidConnectNotification, object: self)
|
||||
s.delegate?.websocketDidConnect(s)
|
||||
s.notificationCenter.post(name: NSNotification.Name(WebsocketDidConnectNotification), object: self)
|
||||
}
|
||||
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
|
||||
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.
|
||||
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")]
|
||||
var k = 0
|
||||
var totalSize = 0
|
||||
@ -473,14 +473,14 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
}
|
||||
}
|
||||
if totalSize > 0 {
|
||||
let code = validateResponse(buffer: buffer, bufferLen: totalSize)
|
||||
let code = validateResponse(buffer, bufferLen: totalSize)
|
||||
if code != 0 {
|
||||
return code
|
||||
}
|
||||
totalSize += 1 //skip the last \n
|
||||
let restSize = bufferLen - totalSize
|
||||
if restSize > 0 {
|
||||
processRawMessagesInBuffer(pointer: buffer + totalSize, bufferLen: restSize)
|
||||
processRawMessagesInBuffer(buffer + totalSize, bufferLen: restSize)
|
||||
}
|
||||
return 0 //success
|
||||
}
|
||||
@ -488,7 +488,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
}
|
||||
|
||||
///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()
|
||||
CFHTTPMessageAppendBytes(response, buffer, bufferLen)
|
||||
let code = CFHTTPMessageGetResponseStatusCode(response)
|
||||
@ -507,12 +507,12 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
}
|
||||
|
||||
///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])
|
||||
}
|
||||
|
||||
///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)
|
||||
for i in 0...7 {
|
||||
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
|
||||
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 + 1] = UInt8(value & 0xff)
|
||||
}
|
||||
|
||||
///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 {
|
||||
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("") }
|
||||
let bufferLen = buffer.count
|
||||
if response != nil && bufferLen < 2 {
|
||||
fragBuffer = NSData(buffer: buffer)
|
||||
fragBuffer = Data(buffer: buffer)
|
||||
return emptyBuffer
|
||||
}
|
||||
if let response = response where response.bytesLeft > 0 {
|
||||
@ -551,43 +551,43 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
extra = 0
|
||||
}
|
||||
response.bytesLeft -= len
|
||||
response.buffer?.append(NSData(bytes: baseAddress, length: len))
|
||||
processResponse(response: response)
|
||||
return buffer.fromOffset(offset: bufferLen - extra)
|
||||
response.buffer?.append(Data(bytes: baseAddress, count: len))
|
||||
processResponse(response)
|
||||
return buffer.fromOffset(bufferLen - extra)
|
||||
} else {
|
||||
let isFin = (FinMask & baseAddress[0])
|
||||
let receivedOpcode = OpCode(rawValue: (OpCodeMask & baseAddress[0]))
|
||||
let isMasked = (MaskMask & baseAddress[1])
|
||||
let payloadLen = (PayloadLenMask & baseAddress[1])
|
||||
var offset = 2
|
||||
if (isMasked > 0 || (RSVMask & baseAddress[0]) > 0) && receivedOpcode != .Pong {
|
||||
let errCode = CloseCode.ProtocolError.rawValue
|
||||
doDisconnect(error: errorWithDetail(detail: "masked and rsv data is not currently supported", code: errCode))
|
||||
writeError(code: errCode)
|
||||
if (isMasked > 0 || (RSVMask & baseAddress[0]) > 0) && receivedOpcode != .pong {
|
||||
let errCode = CloseCode.protocolError.rawValue
|
||||
doDisconnect(errorWithDetail("masked and rsv data is not currently supported", code: errCode))
|
||||
writeError(errCode)
|
||||
return emptyBuffer
|
||||
}
|
||||
let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping)
|
||||
if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame &&
|
||||
receivedOpcode != .TextFrame && receivedOpcode != .Pong) {
|
||||
let errCode = CloseCode.ProtocolError.rawValue
|
||||
doDisconnect(error: errorWithDetail(detail: "unknown opcode: \(receivedOpcode)", code: errCode))
|
||||
writeError(code: errCode)
|
||||
let isControlFrame = (receivedOpcode == .connectionClose || receivedOpcode == .ping)
|
||||
if !isControlFrame && (receivedOpcode != .binaryFrame && receivedOpcode != .continueFrame &&
|
||||
receivedOpcode != .textFrame && receivedOpcode != .pong) {
|
||||
let errCode = CloseCode.protocolError.rawValue
|
||||
doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode))
|
||||
writeError(errCode)
|
||||
return emptyBuffer
|
||||
}
|
||||
if isControlFrame && isFin == 0 {
|
||||
let errCode = CloseCode.ProtocolError.rawValue
|
||||
doDisconnect(error: errorWithDetail(detail: "control frames can't be fragmented", code: errCode))
|
||||
writeError(code: errCode)
|
||||
let errCode = CloseCode.protocolError.rawValue
|
||||
doDisconnect(errorWithDetail("control frames can't be fragmented", code: errCode))
|
||||
writeError(errCode)
|
||||
return emptyBuffer
|
||||
}
|
||||
if receivedOpcode == .ConnectionClose {
|
||||
var code = CloseCode.Normal.rawValue
|
||||
if receivedOpcode == .connectionClose {
|
||||
var code = CloseCode.normal.rawValue
|
||||
if payloadLen == 1 {
|
||||
code = CloseCode.ProtocolError.rawValue
|
||||
code = CloseCode.protocolError.rawValue
|
||||
} 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) {
|
||||
code = CloseCode.ProtocolError.rawValue
|
||||
code = CloseCode.protocolError.rawValue
|
||||
}
|
||||
offset += 2
|
||||
}
|
||||
@ -595,70 +595,70 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
let len = Int(payloadLen-2)
|
||||
if len > 0 {
|
||||
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 {
|
||||
code = CloseCode.ProtocolError.rawValue
|
||||
code = CloseCode.protocolError.rawValue
|
||||
}
|
||||
}
|
||||
}
|
||||
doDisconnect(error: errorWithDetail(detail: "connection closed by server", code: code))
|
||||
writeError(code: code)
|
||||
doDisconnect(errorWithDetail("connection closed by server", code: code))
|
||||
writeError(code)
|
||||
return emptyBuffer
|
||||
}
|
||||
if isControlFrame && payloadLen > 125 {
|
||||
writeError(code: CloseCode.ProtocolError.rawValue)
|
||||
writeError(CloseCode.protocolError.rawValue)
|
||||
return emptyBuffer
|
||||
}
|
||||
var dataLength = UInt64(payloadLen)
|
||||
if dataLength == 127 {
|
||||
dataLength = WebSocket.readUint64(buffer: baseAddress, offset: offset)
|
||||
dataLength = WebSocket.readUint64(baseAddress, offset: offset)
|
||||
offset += sizeof(UInt64)
|
||||
} else if dataLength == 126 {
|
||||
dataLength = UInt64(WebSocket.readUint16(buffer: baseAddress, offset: offset))
|
||||
dataLength = UInt64(WebSocket.readUint16(baseAddress, offset: offset))
|
||||
offset += sizeof(UInt16)
|
||||
}
|
||||
if bufferLen < offset || UInt64(bufferLen - offset) < dataLength {
|
||||
fragBuffer = NSData(bytes: baseAddress, length: bufferLen)
|
||||
fragBuffer = Data(bytes: baseAddress, count: bufferLen)
|
||||
return emptyBuffer
|
||||
}
|
||||
var len = dataLength
|
||||
if dataLength > UInt64(bufferLen) {
|
||||
len = UInt64(bufferLen-offset)
|
||||
}
|
||||
let data: NSData
|
||||
let data: Data
|
||||
if len < 0 {
|
||||
len = 0
|
||||
data = NSData()
|
||||
data = Data()
|
||||
} 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 {
|
||||
dispatch_async(queue!) { [weak self] in
|
||||
queue.async { [weak self] in
|
||||
guard let s = self else { return }
|
||||
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
|
||||
if isControlFrame {
|
||||
response = nil //don't append pings
|
||||
}
|
||||
if isFin == 0 && receivedOpcode == .ContinueFrame && response == nil {
|
||||
let errCode = CloseCode.ProtocolError.rawValue
|
||||
doDisconnect(error: errorWithDetail(detail: "continue frame before a binary or text frame", code: errCode))
|
||||
writeError(code: errCode)
|
||||
if isFin == 0 && receivedOpcode == .continueFrame && response == nil {
|
||||
let errCode = CloseCode.protocolError.rawValue
|
||||
doDisconnect(errorWithDetail("continue frame before a binary or text frame", code: errCode))
|
||||
writeError(errCode)
|
||||
return emptyBuffer
|
||||
}
|
||||
var isNew = false
|
||||
if response == nil {
|
||||
if receivedOpcode == .ContinueFrame {
|
||||
let errCode = CloseCode.ProtocolError.rawValue
|
||||
doDisconnect(error: errorWithDetail(detail: "first frame can't be a continue frame",
|
||||
if receivedOpcode == .continueFrame {
|
||||
let errCode = CloseCode.protocolError.rawValue
|
||||
doDisconnect(errorWithDetail("first frame can't be a continue frame",
|
||||
code: errCode))
|
||||
writeError(code: errCode)
|
||||
writeError(errCode)
|
||||
return emptyBuffer
|
||||
}
|
||||
isNew = true
|
||||
@ -667,13 +667,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
response!.bytesLeft = Int(dataLength)
|
||||
response!.buffer = NSMutableData(data: data)
|
||||
} else {
|
||||
if receivedOpcode == .ContinueFrame {
|
||||
if receivedOpcode == .continueFrame {
|
||||
response!.bytesLeft = Int(dataLength)
|
||||
} else {
|
||||
let errCode = CloseCode.ProtocolError.rawValue
|
||||
doDisconnect(error: errorWithDetail(detail: "second and beyond of fragment message must be a continue frame",
|
||||
let errCode = CloseCode.protocolError.rawValue
|
||||
doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame",
|
||||
code: errCode))
|
||||
writeError(code: errCode)
|
||||
writeError(errCode)
|
||||
return emptyBuffer
|
||||
}
|
||||
response!.buffer!.append(data)
|
||||
@ -685,51 +685,52 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
if isNew {
|
||||
readStack.append(response)
|
||||
}
|
||||
processResponse(response: response)
|
||||
processResponse(response)
|
||||
}
|
||||
|
||||
let step = Int(offset+numericCast(len))
|
||||
return buffer.fromOffset(offset: step)
|
||||
return buffer.fromOffset(step)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
repeat {
|
||||
buffer = processOneRawMessage(inBuffer: buffer)
|
||||
} while buffer.count >= 2
|
||||
if buffer.count > 0 {
|
||||
fragBuffer = NSData(buffer: buffer)
|
||||
fragBuffer = Data(buffer: 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.code == .Ping {
|
||||
if response.code == .ping {
|
||||
let data = response.buffer! //local copy so it is perverse for writing
|
||||
dequeueWrite(data: data, code: OpCode.Pong)
|
||||
} else if response.code == .TextFrame {
|
||||
let str: NSString? = NSString(data: response.buffer!, encoding: NSUTF8StringEncoding)
|
||||
dequeueWrite(data as Data, code: .pong)
|
||||
} else if response.code == .textFrame {
|
||||
let str: NSString? = NSString(data: response.buffer! as Data, encoding: String.Encoding.utf8.rawValue)
|
||||
if str == nil {
|
||||
writeError(code: CloseCode.Encoding.rawValue)
|
||||
writeError(CloseCode.encoding.rawValue)
|
||||
return false
|
||||
}
|
||||
if canDispatch {
|
||||
dispatch_async(queue!) { [weak self] in
|
||||
queue.async { [weak self] in
|
||||
guard let s = self else { return }
|
||||
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 {
|
||||
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 }
|
||||
s.onData?(data)
|
||||
s.delegate?.websocketDidReceiveData(socket: s, data: data)
|
||||
s.onData?(data as Data)
|
||||
s.delegate?.websocketDidReceiveData(s, data: data as Data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -740,7 +741,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
}
|
||||
|
||||
///Create an error
|
||||
private func errorWithDetail(detail: String, code: UInt16) -> NSError {
|
||||
private func errorWithDetail(_ detail: String, code: UInt16) -> NSError {
|
||||
var details = [String: String]()
|
||||
details[NSLocalizedDescriptionKey] = detail
|
||||
|
||||
@ -752,20 +753,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
}
|
||||
|
||||
///write a an error to the socket
|
||||
private func writeError(code: UInt16) {
|
||||
private func writeError(_ code: UInt16) {
|
||||
let buf = NSMutableData(capacity: sizeof(UInt16))
|
||||
let buffer = UnsafeMutablePointer<UInt8>(buf!.bytes)
|
||||
WebSocket.writeUint16(buffer: buffer, offset: 0, value: code)
|
||||
dequeueWrite(data: NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose)
|
||||
WebSocket.writeUint16(buffer, offset: 0, value: code)
|
||||
dequeueWrite(Data(bytes: buffer, count: sizeof(UInt16)), code: .connectionClose)
|
||||
}
|
||||
///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
|
||||
//stream isn't ready, let's wait
|
||||
guard let s = self else { return }
|
||||
var offset = 2
|
||||
let bytes = UnsafeMutablePointer<UInt8>(data.bytes)
|
||||
let dataLength = data.length
|
||||
let bytes = UnsafeMutablePointer<UInt8>((data as NSData).bytes)
|
||||
let dataLength = data.count
|
||||
let frame = NSMutableData(capacity: dataLength + s.MaxFrameSize)
|
||||
let buffer = UnsafeMutablePointer<UInt8>(frame!.mutableBytes)
|
||||
buffer[0] = s.FinMask | code.rawValue
|
||||
@ -773,11 +774,11 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
buffer[1] = CUnsignedChar(dataLength)
|
||||
} else if dataLength <= Int(UInt16.max) {
|
||||
buffer[1] = 126
|
||||
WebSocket.writeUint16(buffer: buffer, offset: offset, value: UInt16(dataLength))
|
||||
WebSocket.writeUint16(buffer, offset: offset, value: UInt16(dataLength))
|
||||
offset += sizeof(UInt16)
|
||||
} else {
|
||||
buffer[1] = 127
|
||||
WebSocket.writeUint64(buffer: buffer, offset: offset, value: UInt64(dataLength))
|
||||
WebSocket.writeUint64(buffer, offset: offset, value: UInt64(dataLength))
|
||||
offset += sizeof(UInt64)
|
||||
}
|
||||
buffer[1] |= s.MaskMask
|
||||
@ -799,17 +800,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
if let streamError = outStream.streamError {
|
||||
error = streamError
|
||||
} else {
|
||||
let errCode = InternalErrorCode.OutputStreamWriteError.rawValue
|
||||
error = s.errorWithDetail(detail: "output stream error during write", code: errCode)
|
||||
let errCode = InternalErrorCode.outputStreamWriteError.rawValue
|
||||
error = s.errorWithDetail("output stream error during write", code: errCode)
|
||||
}
|
||||
s.doDisconnect(error: error)
|
||||
s.doDisconnect(error)
|
||||
break
|
||||
} else {
|
||||
total += len
|
||||
}
|
||||
if total >= offset {
|
||||
if let queue = self?.queue, callback = writeCompletion {
|
||||
dispatch_async(queue) {
|
||||
queue.asynchronously() {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
@ -822,17 +823,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
||||
}
|
||||
|
||||
///used to preform the disconnect delegate
|
||||
private func doDisconnect(error: NSError?) {
|
||||
private func doDisconnect(_ error: NSError?) {
|
||||
guard !didDisconnect else { return }
|
||||
didDisconnect = true
|
||||
connected = false
|
||||
guard canDispatch else {return}
|
||||
dispatch_async(queue!) { [weak self] in
|
||||
queue.async { [weak self] in
|
||||
guard let s = self else { return }
|
||||
s.onDisconnect?(error)
|
||||
s.delegate?.websocketDidDisconnect(socket: s, error: error)
|
||||
s.delegate?.websocketDidDisconnect(s, error: error)
|
||||
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 {
|
||||
|
||||
func fromOffset(offset: Int) -> UnsafeBufferPointer<Element> {
|
||||
func fromOffset(_ offset: Int) -> UnsafeBufferPointer<Element> {
|
||||
return UnsafeBufferPointer<Element>(start: baseAddress!.advanced(by: offset), count: count - offset)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user