merge development and fix tests

This commit is contained in:
Erik 2016-04-10 14:15:35 -04:00
commit 376e31bfca
10 changed files with 127 additions and 112 deletions

View File

@ -13,14 +13,14 @@ class SocketAckManagerTest: XCTestCase {
var ackManager = SocketAckManager() var ackManager = SocketAckManager()
func testAddAcks() { func testAddAcks() {
let callbackExpection = self.expectationWithDescription("callbackExpection") let callbackExpection = self.expectation(withDescription: "callbackExpection")
let itemsArray = ["Hi", "ho"] let itemsArray = ["Hi", "ho"]
func callback(items: [AnyObject]) { func callback(items: [AnyObject]) {
callbackExpection.fulfill() callbackExpection.fulfill()
} }
ackManager.addAck(1, callback: callback) ackManager.addAck(1, callback: callback)
ackManager.executeAck(1, items: itemsArray) ackManager.executeAck(1, items: itemsArray)
waitForExpectationsWithTimeout(3.0, handler: nil) waitForExpectations(withTimeout: 3.0, handler: nil)
} }
} }

View File

@ -10,8 +10,8 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketBasicPacketTest: XCTestCase { class SocketBasicPacketTest: XCTestCase {
let data = "test".dataUsingEncoding(NSUTF8StringEncoding)! let data = "test".data(usingEncoding: NSUTF8StringEncoding)!
let data2 = "test2".dataUsingEncoding(NSUTF8StringEncoding)! let data2 = "test2".data(usingEncoding: NSUTF8StringEncoding)!
func testEmpyEmit() { func testEmpyEmit() {
let expectedSendString = "2[\"test\"]" let expectedSendString = "2[\"test\"]"

View File

@ -22,17 +22,17 @@ class SocketEngineTest: XCTestCase {
} }
func testBasicPollingMessage() { func testBasicPollingMessage() {
let expectation = expectationWithDescription("Basic polling test") let expect = expectation(withDescription: "Basic polling test")
client.on("blankTest") {data, ack in client.on("blankTest") {data, ack in
expectation.fulfill() expect.fulfill()
} }
engine.parsePollingMessage("15:42[\"blankTest\"]") engine.parsePollingMessage("15:42[\"blankTest\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testTwoPacketsInOnePollTest() { func testTwoPacketsInOnePollTest() {
let finalExpectation = expectationWithDescription("Final packet in poll test") let finalExpectation = expectation(withDescription: "Final packet in poll test")
var gotBlank = false var gotBlank = false
client.on("blankTest") {data, ack in client.on("blankTest") {data, ack in
@ -48,11 +48,11 @@ class SocketEngineTest: XCTestCase {
} }
engine.parsePollingMessage("15:42[\"blankTest\"]24:42[\"stringTest\",\"hello\"]") engine.parsePollingMessage("15:42[\"blankTest\"]24:42[\"stringTest\",\"hello\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testEngineDoesErrorOnUnknownTransport() { func testEngineDoesErrorOnUnknownTransport() {
let finalExpectation = expectationWithDescription("Unknown Transport") let finalExpectation = expectation(withDescription: "Unknown Transport")
client.on("error") {data, ack in client.on("error") {data, ack in
if let error = data[0] as? String where error == "Unknown transport" { if let error = data[0] as? String where error == "Unknown transport" {
@ -61,29 +61,29 @@ class SocketEngineTest: XCTestCase {
} }
engine.parseEngineMessage("{\"code\": 0, \"message\": \"Unknown transport\"}", fromPolling: false) engine.parseEngineMessage("{\"code\": 0, \"message\": \"Unknown transport\"}", fromPolling: false)
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testEngineDoesErrorOnUnknownMessage() { func testEngineDoesErrorOnUnknownMessage() {
let finalExpectation = expectationWithDescription("Engine Errors") let finalExpectation = expectation(withDescription: "Engine Errors")
client.on("error") {data, ack in client.on("error") {data, ack in
finalExpectation.fulfill() finalExpectation.fulfill()
} }
engine.parseEngineMessage("afafafda", fromPolling: false) engine.parseEngineMessage("afafafda", fromPolling: false)
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testEngineDecodesUTF8Properly() { func testEngineDecodesUTF8Properly() {
let expectation = expectationWithDescription("Engine Decodes utf8") let expect = expectation(withDescription: "Engine Decodes utf8")
client.on("stringTest") {data, ack in client.on("stringTest") {data, ack in
XCTAssertEqual(data[0] as? String, "lïne one\nlīne \rtwo", "Failed string test") XCTAssertEqual(data[0] as? String, "lïne one\nlīne \rtwo", "Failed string test")
expectation.fulfill() expect.fulfill()
} }
engine.parsePollingMessage("41:42[\"stringTest\",\"lïne one\\nlīne \\rtwo\"]") engine.parsePollingMessage("41:42[\"stringTest\",\"lïne one\\nlīne \\rtwo\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
} }

View File

@ -10,8 +10,8 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketNamespacePacketTest: XCTestCase { class SocketNamespacePacketTest: XCTestCase {
let data = "test".dataUsingEncoding(NSUTF8StringEncoding)! let data = "test".data(usingEncoding: NSUTF8StringEncoding)!
let data2 = "test2".dataUsingEncoding(NSUTF8StringEncoding)! let data2 = "test2".data(usingEncoding: NSUTF8StringEncoding)!
func testEmpyEmit() { func testEmpyEmit() {
let expectedSendString = "2/swift,[\"test\"]" let expectedSendString = "2/swift,[\"test\"]"

View File

@ -31,11 +31,11 @@
} }
- (void)testEmitSyntax { - (void)testEmitSyntax {
[self.socket emit:@"testEmit" withItems:@[@YES]]; [self.socket emit:@"testEmit" with:@[@YES]];
} }
- (void)testEmitWithAckSyntax { - (void)testEmitWithAckSyntax {
[self.socket emitWithAck:@"testAckEmit" withItems:@[@YES]]; [self.socket emitWithAck:@"testAckEmit" with:@[@YES]];
} }
- (void)testOffSyntax { - (void)testOffSyntax {

View File

@ -25,6 +25,7 @@ class SocketParserTest: XCTestCase {
"0/swift": ("/swift", [], [], -1), "0/swift": ("/swift", [], [], -1),
"1/swift": ("/swift", [], [], -1), "1/swift": ("/swift", [], [], -1),
"4\"ERROR\"": ("/", ["ERROR"], [], -1), "4\"ERROR\"": ("/", ["ERROR"], [], -1),
"4{\"test\":2}": ("/", [["test": 2]], [], -1),
"41": ("/", [1], [], -1)] "41": ("/", [1], [], -1)]
func testDisconnect() { func testDisconnect() {
@ -87,6 +88,11 @@ class SocketParserTest: XCTestCase {
validateParseResult(message) validateParseResult(message)
} }
func testErrorTypeDictionary() {
let message = "4{\"test\":2}"
validateParseResult(message)
}
func testErrorTypeInt() { func testErrorTypeInt() {
let message = "41" let message = "41"
validateParseResult(message) validateParseResult(message)
@ -113,12 +119,12 @@ class SocketParserTest: XCTestCase {
func validateParseResult(message: String) { func validateParseResult(message: String) {
let validValues = SocketParserTest.packetTypes[message]! let validValues = SocketParserTest.packetTypes[message]!
let packet = testSocket.parseString(message) let packet = testSocket.parseString(message)
let type = message.substringWithRange(Range<String.Index>(message.startIndex..<message.startIndex.advancedBy(1))) let type = message.substring(with: Range<String.Index>(message.startIndex..<message.startIndex.advanced(by: 1)))
if case let .Right(packet) = packet { if case let .Right(packet) = packet {
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!) XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
XCTAssertEqual(packet.nsp, validValues.0) XCTAssertEqual(packet.nsp, validValues.0)
XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1)) XCTAssertTrue((packet.data as NSArray).isEqual(to: validValues.1))
XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2)) XCTAssertTrue((packet.binary as NSArray).isEqual(to: validValues.2))
XCTAssertEqual(packet.id, validValues.3) XCTAssertEqual(packet.id, validValues.3)
} else { } else {
XCTFail() XCTFail()
@ -127,10 +133,10 @@ class SocketParserTest: XCTestCase {
func testParsePerformance() { func testParsePerformance() {
let keys = Array(SocketParserTest.packetTypes.keys) let keys = Array(SocketParserTest.packetTypes.keys)
measureBlock({ measure {
for item in keys.enumerate() { for item in keys.enumerated() {
self.testSocket.parseString(item.element) self.testSocket.parseString(item.element)
} }
}) }
} }
} }

View File

@ -10,8 +10,8 @@ import XCTest
@testable import SocketIOClientSwift @testable import SocketIOClientSwift
class SocketSideEffectTest: XCTestCase { class SocketSideEffectTest: XCTestCase {
let data = "test".dataUsingEncoding(NSUTF8StringEncoding)! let data = "test".data(usingEncoding: NSUTF8StringEncoding)!
let data2 = "test2".dataUsingEncoding(NSUTF8StringEncoding)! let data2 = "test2".data(usingEncoding: NSUTF8StringEncoding)!
private var socket: SocketIOClient! private var socket: SocketIOClient!
override func setUp() { override func setUp() {
@ -37,60 +37,60 @@ class SocketSideEffectTest: XCTestCase {
} }
func testHandleAck() { func testHandleAck() {
let expectation = expectationWithDescription("handled ack") let expect = expectation(withDescription: "handled ack")
socket.emitWithAck("test")(timeoutAfter: 0) {data in socket.emitWithAck("test")(timeoutAfter: 0) {data in
XCTAssertEqual(data[0] as? String, "hello world") XCTAssertEqual(data[0] as? String, "hello world")
expectation.fulfill() expect.fulfill()
} }
socket.parseSocketMessage("30[\"hello world\"]") socket.parseSocketMessage("30[\"hello world\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testHandleAck2() { func testHandleAck2() {
let expectation = expectationWithDescription("handled ack2") let expect = expectation(withDescription: "handled ack2")
socket.emitWithAck("test")(timeoutAfter: 0) {data in socket.emitWithAck("test")(timeoutAfter: 0) {data in
XCTAssertTrue(data.count == 2, "Wrong number of ack items") XCTAssertTrue(data.count == 2, "Wrong number of ack items")
expectation.fulfill() expect.fulfill()
} }
socket.parseSocketMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]") socket.parseSocketMessage("61-0[{\"_placeholder\":true,\"num\":0},{\"test\":true}]")
socket.parseBinaryData(NSData()) socket.parseBinaryData(NSData())
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testHandleEvent() { func testHandleEvent() {
let expectation = expectationWithDescription("handled event") let expect = expectation(withDescription: "handled event")
socket.on("test") {data, ack in socket.on("test") {data, ack in
XCTAssertEqual(data[0] as? String, "hello world") XCTAssertEqual(data[0] as? String, "hello world")
expectation.fulfill() expect.fulfill()
} }
socket.parseSocketMessage("2[\"test\",\"hello world\"]") socket.parseSocketMessage("2[\"test\",\"hello world\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testHandleStringEventWithQuotes() { func testHandleStringEventWithQuotes() {
let expectation = expectationWithDescription("handled event") let expect = expectation(withDescription: "handled event")
socket.on("test") {data, ack in socket.on("test") {data, ack in
XCTAssertEqual(data[0] as? String, "\"hello world\"") XCTAssertEqual(data[0] as? String, "\"hello world\"")
expectation.fulfill() expect.fulfill()
} }
socket.parseSocketMessage("2[\"test\",\"\\\"hello world\\\"\"]") socket.parseSocketMessage("2[\"test\",\"\\\"hello world\\\"\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testHandleOnceEvent() { func testHandleOnceEvent() {
let expectation = expectationWithDescription("handled event") let expect = expectation(withDescription: "handled event")
socket.once("test") {data, ack in socket.once("test") {data, ack in
XCTAssertEqual(data[0] as? String, "hello world") XCTAssertEqual(data[0] as? String, "hello world")
XCTAssertEqual(self.socket.testHandlers.count, 0) XCTAssertEqual(self.socket.testHandlers.count, 0)
expectation.fulfill() expect.fulfill()
} }
socket.parseSocketMessage("2[\"test\",\"hello world\"]") socket.parseSocketMessage("2[\"test\",\"hello world\"]")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testOffWithEvent() { func testOffWithEvent() {
@ -112,45 +112,45 @@ class SocketSideEffectTest: XCTestCase {
} }
func testHandlesErrorPacket() { func testHandlesErrorPacket() {
let expectation = expectationWithDescription("Handled error") let expect = expectation(withDescription: "Handled error")
socket.on("error") {data, ack in socket.on("error") {data, ack in
if let error = data[0] as? String where error == "test error" { if let error = data[0] as? String where error == "test error" {
expectation.fulfill() expect.fulfill()
} }
} }
socket.parseSocketMessage("4\"test error\"") socket.parseSocketMessage("4\"test error\"")
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testHandleBinaryEvent() { func testHandleBinaryEvent() {
let expectation = expectationWithDescription("handled binary event") let expect = expectation(withDescription: "handled binary event")
socket.on("test") {data, ack in socket.on("test") {data, ack in
if let dict = data[0] as? NSDictionary, data = dict["test"] as? NSData { if let dict = data[0] as? NSDictionary, data = dict["test"] as? NSData {
XCTAssertEqual(data, self.data) XCTAssertEqual(data, self.data)
expectation.fulfill() expect.fulfill()
} }
} }
socket.parseSocketMessage("51-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0}}]") socket.parseSocketMessage("51-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0}}]")
socket.parseBinaryData(data) socket.parseBinaryData(data)
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
func testHandleMultipleBinaryEvent() { func testHandleMultipleBinaryEvent() {
let expectation = expectationWithDescription("handled multiple binary event") let expect = expectation(withDescription: "handled multiple binary event")
socket.on("test") {data, ack in socket.on("test") {data, ack in
if let dict = data[0] as? NSDictionary, data = dict["test"] as? NSData, if let dict = data[0] as? NSDictionary, data = dict["test"] as? NSData,
data2 = dict["test2"] as? NSData { data2 = dict["test2"] as? NSData {
XCTAssertEqual(data, self.data) XCTAssertEqual(data, self.data)
XCTAssertEqual(data2, self.data2) XCTAssertEqual(data2, self.data2)
expectation.fulfill() expect.fulfill()
} }
} }
socket.parseSocketMessage("52-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0},\"test2\":{\"_placeholder\":true,\"num\":1}}]") socket.parseSocketMessage("52-[\"test\",{\"test\":{\"_placeholder\":true,\"num\":0},\"test2\":{\"_placeholder\":true,\"num\":1}}]")
socket.parseBinaryData(data) socket.parseBinaryData(data)
socket.parseBinaryData(data2) socket.parseBinaryData(data2)
waitForExpectationsWithTimeout(3, handler: nil) waitForExpectations(withTimeout: 3, handler: nil)
} }
} }

View File

@ -164,10 +164,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
return {[weak self, ack = currentAck] timeout, callback in return {[weak self, ack = currentAck] timeout, callback in
if let this = self { if let this = self {
this.ackHandlers.addAck(ack, callback: callback) this.ackHandlers.addAck(ack, callback: callback)
this._emit(items, ack: ack)
dispatch_async(this.emitQueue) {
this._emit(items, ack: ack)
}
if timeout != 0 { if timeout != 0 {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * NSEC_PER_SEC)) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeout * NSEC_PER_SEC))
@ -223,38 +220,34 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
return return
} }
dispatch_async(emitQueue) {[emitData = [event] + items] in _emit([event] + items)
self._emit(emitData)
}
} }
/** /// Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add
Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add /// an ack.
an ack.
*/
public func emitWithAck(event: String, _ items: AnyObject...) -> OnAckCallback { public func emitWithAck(event: String, _ items: AnyObject...) -> OnAckCallback {
return emitWithAck(event, with: items) return emitWithAck(event, with: items)
} }
/** /// Same as emitWithAck, but for Objective-C
Same as emitWithAck, but for Objective-C
*/
public func emitWithAck(event: String, with items: [AnyObject]) -> OnAckCallback { public func emitWithAck(event: String, with items: [AnyObject]) -> OnAckCallback {
return createOnAck([event] + items) return createOnAck([event] + items)
} }
private func _emit(data: [AnyObject], ack: Int? = nil) { private func _emit(data: [AnyObject], ack: Int? = nil) {
guard status == .connected else { dispatch_async(emitQueue) {
handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true) guard self.status == .connected else {
return self.handleEvent("error", data: ["Tried emitting when not connected"], isInternalMessage: true)
return
}
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)
self.engine?.send(str, withData: packet.binary)
} }
let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false)
let str = packet.packetString
DefaultSocketLogger.Logger.log("Emitting: %@", type: logType, args: str)
engine?.send(str, withData: packet.binary)
} }
// If the server wants to know that the client received data // If the server wants to know that the client received data
@ -295,7 +288,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
// Called when the socket gets an ack for something it sent // Called when the socket gets an ack for something it sent
func handleAck(ack: Int, data: [AnyObject]) { func handleAck(ack: Int, data: [AnyObject]) {
guard status == .connected else {return} guard status == .connected else { return }
DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: logType, args: ack, data ?? "") DefaultSocketLogger.Logger.log("Handling ack: %@ with data: %@", type: logType, args: ack, data ?? "")
@ -427,9 +420,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
} }
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects { if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects {
didDisconnect("Reconnect Failed") return didDisconnect("Reconnect Failed")
return
} }
DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType) DefaultSocketLogger.Logger.log("Trying to reconnect", type: logType)

View File

@ -76,7 +76,7 @@ extension SocketParsable {
return .Right(SocketPacket(type: type, nsp: "/")) return .Right(SocketPacket(type: type, nsp: "/"))
} }
var namespace: String? var namespace = "/"
var placeholders = -1 var placeholders = -1
if type == .BinaryEvent || type == .BinaryAck { if type == .BinaryEvent || type == .BinaryAck {
@ -116,16 +116,16 @@ extension SocketParsable {
switch parseData(noPlaceholders) { switch parseData(noPlaceholders) {
case let .Left(err): case let .Left(err):
// If first you don't succeed, try again // Errors aren't always enclosed in an array
if case let .Right(data) = parseData("\([noPlaceholders as AnyObject])") { if case let .Right(data) = parseData("\([noPlaceholders as AnyObject])") {
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: namespace ?? "/", placeholders: placeholders)) nsp: namespace, placeholders: placeholders))
} else { } else {
return .Left(err) return .Left(err)
} }
case let .Right(data): case let .Right(data):
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1, return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: namespace ?? "/", placeholders: placeholders)) nsp: namespace, placeholders: placeholders))
} }
} }

View File

@ -183,30 +183,42 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
} }
///write a string to the websocket. This sends it as a text frame. /**
public func writeString(str: String) { Write a string to the websocket. This sends it as a text frame.
If you supply a non-nil completion block, I will perform it when the write completes.
- parameter str: The string to write.
- parameter completion: The (optional) completion handler.
*/
public func writeString(str: String, completion: (() -> ())? = nil) {
guard isConnected else { return } guard isConnected else { return }
dequeueWrite(str.data(usingEncoding: NSUTF8StringEncoding)!, code: .TextFrame) dequeueWrite(str.data(usingEncoding: NSUTF8StringEncoding)!, code: .TextFrame, writeCompletion: completion)
} }
///write binary data to the websocket. This sends it as a binary frame. /**
public func writeData(data: NSData) { Write binary data to the websocket. This sends it as a binary frame.
If you supply a non-nil completion block, I will perform it when the write completes.
- parameter data: The data to write.
- parameter completion: The (optional) completion handler.
*/
public func writeData(data: NSData, completion: (() -> ())? = nil) {
guard isConnected else { return } guard isConnected else { return }
dequeueWrite(data, code: .BinaryFrame) dequeueWrite(data, code: .BinaryFrame, writeCompletion: completion)
} }
//write a ping to the websocket. This sends it as a control frame. //write a ping to the websocket. This sends it as a control frame.
//yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s //yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s
public func writePing(data: NSData) { public func writePing(data: NSData, completion: (() -> ())? = nil) {
guard isConnected else { return } guard isConnected else { return }
dequeueWrite(data, code: .Ping) dequeueWrite(data, code: .Ping, writeCompletion: completion)
} }
//private method that starts the connection //private method that starts the connection
private func createHTTPRequest() { private func createHTTPRequest() {
let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET", let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET",
url, kCFHTTPVersion1_1).takeRetainedValue() url, kCFHTTPVersion1_1).takeRetainedValue()
var port = url.port var port = url.port
if port == nil { if port == nil {
@ -288,18 +300,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
if let cipherSuites = self.enabledSSLCipherSuites { if let cipherSuites = self.enabledSSLCipherSuites {
if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContextRef?, if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContextRef?,
sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContextRef? { sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContextRef? {
let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count) let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count)
let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count) let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count)
if resIn != errSecSuccess { if resIn != errSecSuccess {
let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn)) let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn))
disconnectStream(error) disconnectStream(error)
return return
} }
if resOut != errSecSuccess { if resOut != errSecSuccess {
let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut)) let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut))
disconnectStream(error) disconnectStream(error)
return return
} }
} }
} }
#endif #endif
@ -436,7 +448,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
case -1: case -1:
fragBuffer = NSData(bytes: buffer, length: bufferLen) fragBuffer = NSData(bytes: buffer, length: bufferLen)
break //do nothing, we are going to collect more data break //do nothing, we are going to collect more data
default: default:
doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: UInt16(code))) doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: UInt16(code)))
} }
@ -555,10 +567,10 @@ public class WebSocket : NSObject, NSStreamDelegate {
let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping) let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping)
if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame && if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame &&
receivedOpcode != .TextFrame && receivedOpcode != .Pong) { receivedOpcode != .TextFrame && receivedOpcode != .Pong) {
let errCode = CloseCode.ProtocolError.rawValue let errCode = CloseCode.ProtocolError.rawValue
doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode)) doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode))
writeError(errCode) writeError(errCode)
return return
} }
if isControlFrame && isFin == 0 { if isControlFrame && isFin == 0 {
let errCode = CloseCode.ProtocolError.rawValue let errCode = CloseCode.ProtocolError.rawValue
@ -611,7 +623,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
if dataLength > UInt64(bufferLen) { if dataLength > UInt64(bufferLen) {
len = UInt64(bufferLen-offset) len = UInt64(bufferLen-offset)
} }
var data: NSData! let data: NSData
if len < 0 { if len < 0 {
len = 0 len = 0
data = NSData() data = NSData()
@ -747,7 +759,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
dequeueWrite(NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose) dequeueWrite(NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose)
} }
///used to write things to the stream ///used to write things to the stream
private func dequeueWrite(data: NSData, code: OpCode) { private func dequeueWrite(data: NSData, code: OpCode, writeCompletion: (() -> ())? = nil) {
writeQueue.addOperation { [weak self] in writeQueue.addOperation { [weak self] in
//stream isn't ready, let's wait //stream isn't ready, let's wait
guard let s = self else { return } guard let s = self else { return }
@ -796,6 +808,12 @@ public class WebSocket : NSObject, NSStreamDelegate {
total += len total += len
} }
if total >= offset { if total >= offset {
if let queue = self?.queue, callback = writeCompletion {
dispatch_async(queue) {
callback()
}
}
break break
} }
} }