From 9acae3b15428ed4b2679a1a3cf170631720ce1c5 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 18 Aug 2016 19:09:26 -0400 Subject: [PATCH 1/5] I'm not convinced this is right --- SocketIO-MacTests/SocketBasicPacketTest.swift | 14 +++++++------- .../SocketNamespacePacketTest.swift | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/SocketIO-MacTests/SocketBasicPacketTest.swift b/SocketIO-MacTests/SocketBasicPacketTest.swift index d22116a..b533d6a 100644 --- a/SocketIO-MacTests/SocketBasicPacketTest.swift +++ b/SocketIO-MacTests/SocketBasicPacketTest.swift @@ -46,7 +46,7 @@ class SocketBasicPacketTest: XCTestCase { } func testJSONEmit() { - let expectedSendString = "2[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":1,\"null\":null}]" + let expectedSendString = "2[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let sendData = ["test" as AnyObject, ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()] as NSDictionary] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/", ack: false) @@ -62,7 +62,7 @@ class SocketBasicPacketTest: XCTestCase { } func testBinaryEmit() { - let expectedSendString = "51-[\"test\",{\"_placeholder\":1,\"num\":0}]" + let expectedSendString = "51-[\"test\",{\"_placeholder\":true,\"num\":0}]" let sendData = ["test", data] as [Any] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/", ack: false) @@ -71,7 +71,7 @@ class SocketBasicPacketTest: XCTestCase { } func testMultipleBinaryEmit() { - let expectedSendString = "52-[\"test\",{\"data1\":{\"_placeholder\":1,\"num\":0},\"data2\":{\"_placeholder\":1,\"num\":1}}]" + let expectedSendString = "52-[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]" let sendData = ["test" as AnyObject, ["data1": data, "data2": data2] as NSDictionary] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/", ack: false) @@ -90,7 +90,7 @@ class SocketBasicPacketTest: XCTestCase { } func testEmitDataWithAck() { - let expectedSendString = "51-0[\"test\",{\"_placeholder\":1,\"num\":0}]" + let expectedSendString = "51-0[\"test\",{\"_placeholder\":true,\"num\":0}]" let sendData = ["test" as AnyObject, data as AnyObject] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: 0, nsp: "/", ack: false) @@ -123,7 +123,7 @@ class SocketBasicPacketTest: XCTestCase { } func testJSONAck() { - let expectedSendString = "30[{\"test\":\"hello\",\"hello\":1,\"foobar\":1,\"null\":null}]" + 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(sendData as [AnyObject], id: 0, nsp: "/", ack: true) @@ -131,7 +131,7 @@ class SocketBasicPacketTest: XCTestCase { } func testBinaryAck() { - let expectedSendString = "61-0[{\"_placeholder\":1,\"num\":0}]" + let expectedSendString = "61-0[{\"_placeholder\":true,\"num\":0}]" let sendData = [data] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: 0, nsp: "/", ack: true) @@ -140,7 +140,7 @@ class SocketBasicPacketTest: XCTestCase { } func testMultipleBinaryAck() { - let expectedSendString = "62-0[{\"data2\":{\"_placeholder\":1,\"num\":0},\"data1\":{\"_placeholder\":1,\"num\":1}}]" + let expectedSendString = "62-0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]" let sendData = [["data1": data, "data2": data2]] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: 0, nsp: "/", ack: true) diff --git a/SocketIO-MacTests/SocketNamespacePacketTest.swift b/SocketIO-MacTests/SocketNamespacePacketTest.swift index e1144a1..435e9e3 100644 --- a/SocketIO-MacTests/SocketNamespacePacketTest.swift +++ b/SocketIO-MacTests/SocketNamespacePacketTest.swift @@ -38,7 +38,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testJSONEmit() { - let expectedSendString = "2/swift,[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":1,\"null\":null}]" + let expectedSendString = "2/swift,[\"test\",{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let sendData = ["test" as AnyObject, ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()] as NSDictionary] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/swift", ack: false) @@ -46,7 +46,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testArrayEmit() { - let expectedSendString = "2/swift,[\"test\",[\"hello\",1,{\"test\":\"test\"}]]" + let expectedSendString = "2/swift,[\"test\",[\"hello\",true,{\"test\":\"test\"}]]" let sendData = ["test", ["hello", 1, ["test": "test"]]] as [Any] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/swift", ack: false) @@ -55,7 +55,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testBinaryEmit() { - let expectedSendString = "51-/swift,[\"test\",{\"_placeholder\":1,\"num\":0}]" + let expectedSendString = "51-/swift,[\"test\",{\"_placeholder\":true,\"num\":0}]" let sendData = ["test" as AnyObject, data as AnyObject] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/swift", ack: false) @@ -64,7 +64,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testMultipleBinaryEmit() { - let expectedSendString = "52-/swift,[\"test\",{\"data1\":{\"_placeholder\":1,\"num\":0},\"data2\":{\"_placeholder\":1,\"num\":1}}]" + let expectedSendString = "52-/swift,[\"test\",{\"data1\":{\"_placeholder\":true,\"num\":0},\"data2\":{\"_placeholder\":true,\"num\":1}}]" let sendData = ["test" as AnyObject, ["data1": data, "data2": data2] as NSDictionary] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: -1, nsp: "/swift", ack: false) @@ -81,7 +81,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testEmitDataWithAck() { - let expectedSendString = "51-/swift,0[\"test\",{\"_placeholder\":1,\"num\":0}]" + let expectedSendString = "51-/swift,0[\"test\",{\"_placeholder\":true,\"num\":0}]" let sendData = ["test" as AnyObject, data as AnyObject] as [AnyObject] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: 0, nsp: "/swift", ack: false) @@ -114,7 +114,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testJSONAck() { - let expectedSendString = "3/swift,0[{\"test\":\"hello\",\"hello\":1,\"foobar\":1,\"null\":null}]" + let expectedSendString = "3/swift,0[{\"test\":\"hello\",\"hello\":1,\"foobar\":true,\"null\":null}]" let sendData = [["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: 0, nsp: "/swift", ack: true) @@ -122,7 +122,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testBinaryAck() { - let expectedSendString = "61-/swift,0[{\"_placeholder\":1,\"num\":0}]" + let expectedSendString = "61-/swift,0[{\"_placeholder\":true,\"num\":0}]" let sendData = [data] let packet = SocketPacket.packetFromEmit(sendData as [AnyObject], id: 0, nsp: "/swift", ack: true) @@ -131,7 +131,7 @@ class SocketNamespacePacketTest: XCTestCase { } func testMultipleBinaryAck() { - let expectedSendString = "62-/swift,0[{\"data2\":{\"_placeholder\":1,\"num\":0},\"data1\":{\"_placeholder\":1,\"num\":1}}]" + 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(sendData as [AnyObject], id: 0, nsp: "/swift", ack: true) From 1232c34817eb1eed0a94862bd0846ffa73bf8115 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 18 Aug 2016 19:22:19 -0400 Subject: [PATCH 2/5] narrow down what's causing compiler crashes --- Source/WebSocket.swift | 128 ++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/Source/WebSocket.swift b/Source/WebSocket.swift index 52ab6dc..a0181a6 100644 --- a/Source/WebSocket.swift +++ b/Source/WebSocket.swift @@ -296,72 +296,72 @@ public class WebSocket: NSObject, StreamDelegate { //higher level API we will cut over to at some point //NSStream.getStreamsToHostWithName(url.host, port: url.port.integerValue, inputStream: &inputStream, outputStream: &outputStream) -// var readStream: Unmanaged? -// var writeStream: Unmanaged? -// let h = url.host! -// CFStreamCreatePairWithSocketToHost(nil, h as NSString, UInt32(port), &readStream, &writeStream) -// inputStream = readStream!.takeRetainedValue() -// outputStream = writeStream!.takeRetainedValue() -// guard let inStream = inputStream, let outStream = outputStream else { return } -// inStream.delegate = self -// outStream.delegate = self -// if supportedSSLSchemes.contains(url.scheme!) { + var readStream: Unmanaged? + var writeStream: Unmanaged? + let h = url.host! + CFStreamCreatePairWithSocketToHost(nil, h as NSString, UInt32(port), &readStream, &writeStream) + inputStream = readStream!.takeRetainedValue() + outputStream = writeStream!.takeRetainedValue() + guard let inStream = inputStream, let outStream = outputStream else { return } + inStream.delegate = self + outStream.delegate = self + if supportedSSLSchemes.contains(url.scheme!) { // inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) // outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) -// } else { -// certValidated = true //not a https session, so no need to check SSL pinning -// } -// if voipEnabled { -// inStream.setProperty(StreamNetworkServiceTypeValue.voIP as NSString, forKey: Stream.PropertyKey(rawValue: Stream.PropertyKey.networkServiceType.rawValue)) -// outStream.setProperty(StreamNetworkServiceTypeValue.voIP as NSString, forKey: Stream.PropertyKey(rawValue: Stream.PropertyKey.networkServiceType.rawValue)) -// } -// if selfSignedSSL { -// let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull] -// inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey) -// outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey) -// } -// if let cipherSuites = self.enabledSSLCipherSuites { -// if let sslContextIn = CFReadStreamCopyProperty(inputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext?, -// let 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) -// return -// } -// if resOut != errSecSuccess { -// let error = self.errorWithDetail(detail: "Error setting outgoing cypher suites", code: UInt16(resOut)) -// disconnectStream(error: error) -// return -// } -// } -// } -// CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue) -// CFWriteStreamSetDispatchQueue(outStream, WebSocket.sharedWorkQueue) -// inStream.open() -// outStream.open() -// -// self.mutex.lock() -// self.readyToWrite = true -// self.mutex.unlock() -// -// let bytes = UnsafeRawPointer(data.bytes).assumingMemoryBound(to: UInt8.self) -// var out = timeout * 1000000 // wait 5 seconds before giving up -// writeQueue.addOperation { [weak self] in -// while !outStream.hasSpaceAvailable { -// usleep(100) // wait until the socket is ready -// out -= 100 -// if out < 0 { -// self?.cleanupStream() -// self?.doDisconnect(error: self?.errorWithDetail(detail: "write wait timed out", code: 2)) -// return -// } else if outStream.streamError != nil { -// return // disconnectStream will be called. -// } -// } -// outStream.write(bytes, maxLength: data.length) -// } + } else { + certValidated = true //not a https session, so no need to check SSL pinning + } + if voipEnabled { + inStream.setProperty(StreamNetworkServiceTypeValue.voIP as NSString, forKey: Stream.PropertyKey(rawValue: Stream.PropertyKey.networkServiceType.rawValue)) + outStream.setProperty(StreamNetworkServiceTypeValue.voIP as NSString, forKey: Stream.PropertyKey(rawValue: Stream.PropertyKey.networkServiceType.rawValue)) + } + if selfSignedSSL { + let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull] + inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey) + outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey) + } + if let cipherSuites = self.enabledSSLCipherSuites { + if let sslContextIn = CFReadStreamCopyProperty(inputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext?, + let 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) + return + } + if resOut != errSecSuccess { + let error = self.errorWithDetail(detail: "Error setting outgoing cypher suites", code: UInt16(resOut)) + disconnectStream(error: error) + return + } + } + } + CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue) + CFWriteStreamSetDispatchQueue(outStream, WebSocket.sharedWorkQueue) + inStream.open() + outStream.open() + + self.mutex.lock() + self.readyToWrite = true + self.mutex.unlock() + + let bytes = UnsafeRawPointer(data.bytes).assumingMemoryBound(to: UInt8.self) + var out = timeout * 1000000 // wait 5 seconds before giving up + writeQueue.addOperation { [weak self] in + while !outStream.hasSpaceAvailable { + usleep(100) // wait until the socket is ready + out -= 100 + if out < 0 { + self?.cleanupStream() + self?.doDisconnect(error: self?.errorWithDetail(detail: "write wait timed out", code: 2)) + return + } else if outStream.streamError != nil { + return // disconnectStream will be called. + } + } + outStream.write(bytes, maxLength: data.length) + } } // Delegate for the stream methods. Processes incoming bytes. From 70b870690efbe4d83c6862bee28db3b4c7f3dfe6 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 20 Aug 2016 15:30:07 -0400 Subject: [PATCH 3/5] Fix websocket --- Source/WebSocket.swift | 98 ++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/Source/WebSocket.swift b/Source/WebSocket.swift index a0181a6..c4d5315 100644 --- a/Source/WebSocket.swift +++ b/Source/WebSocket.swift @@ -38,9 +38,9 @@ public protocol WebSocketPongDelegate: class { func websocketDidReceivePong(_ socket: WebSocket) } -public class WebSocket: NSObject, StreamDelegate { +public class WebSocket : NSObject, StreamDelegate { - enum OpCode: UInt8 { + enum OpCode : UInt8 { case continueFrame = 0x0 case textFrame = 0x1 case binaryFrame = 0x2 @@ -51,7 +51,7 @@ public class WebSocket: NSObject, StreamDelegate { // B-F reserved. } - public enum CloseCode: UInt16 { + public enum CloseCode : UInt16 { case normal = 1000 case goingAway = 1001 case protocolError = 1002 @@ -66,7 +66,7 @@ public class WebSocket: NSObject, StreamDelegate { public static let ErrorDomain = "WebSocket" - enum InternalErrorCode: UInt16 { + enum InternalErrorCode : UInt16 { // 0-999 WebSocket status codes not used case outputStreamWriteError = 1 } @@ -135,7 +135,7 @@ public class WebSocket: NSObject, StreamDelegate { public var isConnected :Bool { return connected } - + public var currentURL: NSURL { return url } // MARK: - Private @@ -190,7 +190,7 @@ public class WebSocket: NSObject, StreamDelegate { - Parameter forceTimeout: Maximum time to wait for the server to close the socket. */ - public func disconnect(_ forceTimeout: TimeInterval? = nil) { + public func disconnect(forceTimeout: TimeInterval? = nil) { switch forceTimeout { case .some(let seconds) where seconds > 0: callbackQueue.asyncAfter(deadline: DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { [weak self] in @@ -253,19 +253,19 @@ public class WebSocket: NSObject, StreamDelegate { 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() @@ -274,7 +274,7 @@ public class WebSocket: NSObject, StreamDelegate { } /// 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) } @@ -306,8 +306,8 @@ public class WebSocket: NSObject, StreamDelegate { inStream.delegate = self outStream.delegate = self if supportedSSLSchemes.contains(url.scheme!) { -// inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) -// outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) + // inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) + // outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) } else { certValidated = true //not a https session, so no need to check SSL pinning } @@ -326,12 +326,12 @@ public class WebSocket: NSObject, StreamDelegate { 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)) + let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn)) disconnectStream(error: error) return } if resOut != errSecSuccess { - let error = self.errorWithDetail(detail: "Error setting outgoing cypher suites", code: UInt16(resOut)) + let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut)) disconnectStream(error: error) return } @@ -354,7 +354,7 @@ public class WebSocket: NSObject, StreamDelegate { out -= 100 if out < 0 { self?.cleanupStream() - self?.doDisconnect(error: self?.errorWithDetail(detail: "write wait timed out", code: 2)) + self?.doDisconnect(error: self?.errorWithDetail("write wait timed out", code: 2)) return } else if outStream.streamError != nil { return // disconnectStream will be called. @@ -365,18 +365,17 @@ public class WebSocket: NSObject, StreamDelegate { } // Delegate for the stream methods. Processes incoming bytes. - public func stream(aStream: Stream, handleEvent eventCode: Stream.Event) { - + public func stream(_ aStream: Stream, handle eventCode: Stream.Event) { if let sec = security , !certValidated && [.hasBytesAvailable, .hasSpaceAvailable].contains(eventCode) { let possibleTrust = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as AnyObject - let domain = aStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String - if sec.isValid(possibleTrust as! SecTrust, domain: domain) { - certValidated = true - } else { - let error = errorWithDetail(detail: "Invalid SSL certificate", code: 1) - disconnectStream(error: error) - return - } + let domain = aStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String + if sec.isValid(possibleTrust as! SecTrust, domain: domain) { + certValidated = true + } else { + let error = errorWithDetail("Invalid SSL certificate", code: 1) + disconnectStream(error: error) + return + } } if eventCode == .hasBytesAvailable { if aStream == inputStream { @@ -426,7 +425,7 @@ public class WebSocket: NSObject, StreamDelegate { if inputQueue.count == 0 { process = true } - inputQueue.append(Data(bytes: UnsafePointer(buffer), count: length)) + inputQueue.append(Data(bytes: UnsafeRawPointer(buffer).assumingMemoryBound(to: UInt8.self), count: length)) if process { dequeueInput() } @@ -471,7 +470,7 @@ public class WebSocket: NSObject, StreamDelegate { fragBuffer = NSData(bytes: buffer, length: bufferLen) as Data break // do nothing, we are going to collect more data default: - doDisconnect(error: errorWithDetail(detail: "Invalid HTTP upgrade", code: UInt16(code))) + doDisconnect(error: errorWithDetail("Invalid HTTP upgrade", code: UInt16(code))) } } @@ -544,7 +543,7 @@ public class WebSocket: NSObject, StreamDelegate { 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, offset: Int, value: UInt64) { for i in 0...7 { @@ -571,7 +570,7 @@ public class WebSocket: NSObject, StreamDelegate { } response.bytesLeft -= len response.buffer?.append(Data(bytes: baseAddress, count: len)) - processResponse(response: response) + _ = processResponse(response) return buffer.fromOffset(bufferLen - extra) } else { let isFin = (FinMask & baseAddress[0]) @@ -581,7 +580,7 @@ public class WebSocket: NSObject, StreamDelegate { 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)) + doDisconnect(error: errorWithDetail("masked and rsv data is not currently supported", code: errCode)) writeError(code: errCode) return emptyBuffer } @@ -589,13 +588,13 @@ public class WebSocket: NSObject, StreamDelegate { if !isControlFrame && (receivedOpcode != .binaryFrame && receivedOpcode != .continueFrame && receivedOpcode != .textFrame && receivedOpcode != .pong) { let errCode = CloseCode.protocolError.rawValue - doDisconnect(error: errorWithDetail(detail: "unknown opcode: \(receivedOpcode)", code: errCode)) + doDisconnect(error: errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode)) writeError(code: errCode) return emptyBuffer } if isControlFrame && isFin == 0 { let errCode = CloseCode.protocolError.rawValue - doDisconnect(error: errorWithDetail(detail: "control frames can't be fragmented", code: errCode)) + doDisconnect(error: errorWithDetail("control frames can't be fragmented", code: errCode)) writeError(code: errCode) return emptyBuffer } @@ -622,7 +621,7 @@ public class WebSocket: NSObject, StreamDelegate { } } } - doDisconnect(error: errorWithDetail(detail: closeReason, code: code)) + doDisconnect(error: errorWithDetail(closeReason, code: code)) writeError(code: code) return emptyBuffer } @@ -669,7 +668,7 @@ public class WebSocket: NSObject, StreamDelegate { } 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)) + doDisconnect(error: errorWithDetail("continue frame before a binary or text frame", code: errCode)) writeError(code: errCode) return emptyBuffer } @@ -677,8 +676,8 @@ public class WebSocket: NSObject, StreamDelegate { if response == nil { if receivedOpcode == .continueFrame { let errCode = CloseCode.protocolError.rawValue - doDisconnect(error: errorWithDetail(detail: "first frame can't be a continue frame", - code: errCode)) + doDisconnect(error: errorWithDetail("first frame can't be a continue frame", + code: errCode)) writeError(code: errCode) return emptyBuffer } @@ -692,8 +691,8 @@ public class WebSocket: NSObject, StreamDelegate { 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", - code: errCode)) + doDisconnect(error: errorWithDetail("second and beyond of fragment message must be a continue frame", + code: errCode)) writeError(code: errCode) return emptyBuffer } @@ -706,7 +705,7 @@ public class WebSocket: NSObject, StreamDelegate { if isNew { readStack.append(response) } - processResponse(response: response) + _ = processResponse(response) } let step = Int(offset + numericCast(len)) @@ -726,7 +725,7 @@ public class WebSocket: NSObject, StreamDelegate { } /// Process the finished response of a buffer. - private func processResponse(response: WSResponse) -> Bool { + private func processResponse(_ response: WSResponse) -> Bool { if response.isFin && response.bytesLeft <= 0 { if response.code == .ping { let data = response.buffer! // local copy so it's not perverse for writing @@ -761,15 +760,10 @@ public class WebSocket: NSObject, StreamDelegate { } /// 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 - - #if swift(>=3) - return NSError(domain: "This is still broken", code: Int(code), userInfo: details) - #else return NSError(domain: WebSocket.ErrorDomain, code: Int(code), userInfo: details) - #endif } /// Write a an error to the socket. @@ -822,7 +816,7 @@ public class WebSocket: NSObject, StreamDelegate { error = streamError as NSError } else { let errCode = InternalErrorCode.outputStreamWriteError.rawValue - error = s.errorWithDetail(detail: "output stream error during write", code: errCode) + error = s.errorWithDetail("output stream error during write", code: errCode) } s.doDisconnect(error: error) break From 29670af4d366289491e2312891bf31bec4eadc39 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 20 Aug 2016 16:16:57 -0400 Subject: [PATCH 4/5] fix crash --- Source/WebSocket.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/WebSocket.swift b/Source/WebSocket.swift index c4d5315..6fd2178 100644 --- a/Source/WebSocket.swift +++ b/Source/WebSocket.swift @@ -306,14 +306,14 @@ public class WebSocket : NSObject, StreamDelegate { inStream.delegate = self outStream.delegate = self if supportedSSLSchemes.contains(url.scheme!) { - // inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) - // outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL, forKey: Stream.PropertyKey.socketSecurityLevelKey) + inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey) + outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey) } else { certValidated = true //not a https session, so no need to check SSL pinning } if voipEnabled { - inStream.setProperty(StreamNetworkServiceTypeValue.voIP as NSString, forKey: Stream.PropertyKey(rawValue: Stream.PropertyKey.networkServiceType.rawValue)) - outStream.setProperty(StreamNetworkServiceTypeValue.voIP as NSString, forKey: Stream.PropertyKey(rawValue: Stream.PropertyKey.networkServiceType.rawValue)) + inStream.setProperty(StreamNetworkServiceTypeValue.voIP as AnyObject, forKey: Stream.PropertyKey.networkServiceType) + outStream.setProperty(StreamNetworkServiceTypeValue.voIP as AnyObject, forKey: Stream.PropertyKey.networkServiceType) } if selfSignedSSL { let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false), kCFStreamSSLPeerName: kCFNull] @@ -863,10 +863,10 @@ public class WebSocket : NSObject, StreamDelegate { } -private extension NSData { +private extension Data { - convenience init(buffer: UnsafeBufferPointer) { - self.init(bytes: buffer.baseAddress, length: buffer.count) + init(buffer: UnsafeBufferPointer) { + self.init(bytes: buffer.baseAddress!, count: buffer.count) } } From f982e756c238245712963b9fa67182b21e70f873 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 20 Aug 2016 17:58:52 -0400 Subject: [PATCH 5/5] varios tweaks --- Source/SocketExtensions.swift | 4 ++-- Source/SocketPacket.swift | 15 +++++++++------ Source/SocketStringReader.swift | 2 ++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Source/SocketExtensions.swift b/Source/SocketExtensions.swift index 4a47074..7280bba 100644 --- a/Source/SocketExtensions.swift +++ b/Source/SocketExtensions.swift @@ -30,9 +30,9 @@ enum JSONError : Error { } extension Array { - /// Because Swift 3 removes a lot of implicit briding so we have to perform more casts + /// Because Swift 3 removes a lot of implicit briding so we have to perform more explicit bridging func toAnyObjectArray() -> [AnyObject] { - return flatMap({$0 as? AnyObject}) + return flatMap({ $0 as AnyObject }) } } diff --git a/Source/SocketPacket.swift b/Source/SocketPacket.swift index aa333eb..71a79d8 100644 --- a/Source/SocketPacket.swift +++ b/Source/SocketPacket.swift @@ -134,7 +134,7 @@ struct SocketPacket { // binary data private func _fillInPlaceholders(_ object: AnyObject) -> AnyObject { switch object { - case let dict as NSDictionary: + case let dict as [AnyHashable: AnyObject]: if dict["_placeholder"] as? Bool ?? false { return binary[dict["num"] as! Int] as AnyObject } else { @@ -187,11 +187,14 @@ private extension SocketPacket { return placeholder as AnyObject case let arr as [AnyObject]: return arr.map({shred($0, binary: &binary)}) as AnyObject - case let dict as NSDictionary: - return dict.reduce(NSMutableDictionary(), {cur, keyValue in - cur[keyValue.0 as! NSCopying] = shred(keyValue.1 as AnyObject, binary: &binary) - return cur - }) + case let dict as [AnyHashable: AnyObject]: + return dict.reduce([AnyHashable: AnyObject](), {cur, keyValue in + var mutCur = cur + + mutCur[keyValue.0] = shred(keyValue.1 as AnyObject, binary: &binary) + + return mutCur + }) as AnyObject default: return data } diff --git a/Source/SocketStringReader.swift b/Source/SocketStringReader.swift index b0fbcd8..8bdb4d4 100644 --- a/Source/SocketStringReader.swift +++ b/Source/SocketStringReader.swift @@ -47,6 +47,7 @@ struct SocketStringReader { mutating func read(count: Int) -> String { let readString = message[currentIndex.. String { let substring = message[currentIndex..