Merge branch 'development'

* development:
  bump websocket
  note that swift2.3 is a tag now
  Bump websocket version, fix some warnings
This commit is contained in:
Erik 2017-03-29 12:20:37 -04:00
commit fafd8b5f22
No known key found for this signature in database
GPG Key ID: 4930B7C5FBC1A69D
2 changed files with 96 additions and 95 deletions

View File

@ -28,7 +28,7 @@ public final class SocketAnyEvent : NSObject {
public let event: String public let event: String
public let items: [Any]? public let items: [Any]?
override public var description: String { override public var description: String {
return "SocketAnyEvent: Event: \(event) items: \(items ?? nil)" return "SocketAnyEvent: Event: \(event) items: \(String(describing: items))"
} }
init(event: String, items: [Any]?) { init(event: String, items: [Any]?) {

View File

@ -193,7 +193,7 @@ open class WebSocket : NSObject, StreamDelegate {
If you supply a zero (or negative) `forceTimeout`, I immediately close the socket (without sending a Close control frame) and notify my delegate. If you supply a zero (or negative) `forceTimeout`, I immediately close the socket (without sending a Close control frame) and notify my delegate.
- Parameter forceTimeout: Maximum time to wait for the server to close the socket. - Parameter forceTimeout: Maximum time to wait for the server to close the socket.
- Parameter closeCode: The code to send on disconnect. The default is the normal close code for cleanly disconnecting a webSocket. - Parameter closeCode: The code to send on disconnect. The default is the normal close code for cleanly disconnecting a webSocket.
*/ */
open func disconnect(forceTimeout: TimeInterval? = nil, closeCode: UInt16 = CloseCode.normal.rawValue) { open func disconnect(forceTimeout: TimeInterval? = nil, closeCode: UInt16 = CloseCode.normal.rawValue) {
guard isConnected else { return } guard isConnected else { return }
switch forceTimeout { switch forceTimeout {
@ -246,7 +246,6 @@ open class WebSocket : NSObject, StreamDelegate {
Private method that starts the connection. Private method that starts the connection.
*/ */
private func createHTTPRequest() { private func createHTTPRequest() {
let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET" as CFString, let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET" as CFString,
url as CFURL, kCFHTTPVersion1_1).takeRetainedValue() url as CFURL, kCFHTTPVersion1_1).takeRetainedValue()
@ -319,6 +318,7 @@ open class WebSocket : NSObject, StreamDelegate {
inStream.delegate = self inStream.delegate = self
outStream.delegate = self outStream.delegate = self
if supportedSSLSchemes.contains(url.scheme!) { if supportedSSLSchemes.contains(url.scheme!) {
certValidated = false
inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey) inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey) outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
if disableSSLCertValidation { if disableSSLCertValidation {
@ -370,14 +370,29 @@ open class WebSocket : NSObject, StreamDelegate {
guard !sOperation.isCancelled else { return } guard !sOperation.isCancelled else { return }
out -= 100 out -= 100
if out < 0 { if out < 0 {
self?.cleanupStream() WebSocket.sharedWorkQueue.async {
self?.cleanupStream()
}
self?.doDisconnect(self?.errorWithDetail("write wait timed out", code: 2)) self?.doDisconnect(self?.errorWithDetail("write wait timed out", code: 2))
return return
} else if outStream.streamError != nil { } else if outStream.streamError != nil {
return // disconnectStream will be called. return // disconnectStream will be called.
} }
} }
guard !sOperation.isCancelled else { return } guard !sOperation.isCancelled, let s = self else { return }
// Do the pinning now if needed
if let sec = s.security, !s.certValidated {
let trust = outStream.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust
let domain = outStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String
s.certValidated = sec.isValid(trust, domain: domain)
if !s.certValidated {
WebSocket.sharedWorkQueue.async {
let error = s.errorWithDetail("Invalid SSL certificate", code: 1)
s.disconnectStream(error)
}
return
}
}
outStream.write(bytes, maxLength: data.count) outStream.write(bytes, maxLength: data.count)
} }
writeQueue.addOperation(operation) writeQueue.addOperation(operation)
@ -387,17 +402,6 @@ open class WebSocket : NSObject, StreamDelegate {
Delegate for the stream methods. Processes incoming bytes Delegate for the stream methods. Processes incoming bytes
*/ */
open func stream(_ aStream: Stream, handle eventCode: Stream.Event) { open func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
if let sec = security, !certValidated && [.hasBytesAvailable, .hasSpaceAvailable].contains(eventCode) {
let trust = aStream.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust
let domain = aStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String
if sec.isValid(trust, domain: domain) {
certValidated = true
} else {
let error = errorWithDetail("Invalid SSL certificate", code: 1)
disconnectStream(error)
return
}
}
if eventCode == .hasBytesAvailable { if eventCode == .hasBytesAvailable {
if aStream == inputStream { if aStream == inputStream {
processInputStream() processInputStream()
@ -498,7 +502,7 @@ open class WebSocket : NSObject, StreamDelegate {
break break
case -1: case -1:
fragBuffer = Data(bytes: buffer, count: bufferLen) fragBuffer = Data(bytes: buffer, count: bufferLen)
break // do nothing, we are going to collect more data break // do nothing, we are going to collect more data
default: default:
doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: UInt16(code))) doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: UInt16(code)))
} }
@ -628,7 +632,8 @@ open class WebSocket : NSObject, StreamDelegate {
return buffer.fromOffset(bufferLen - extra) return buffer.fromOffset(bufferLen - extra)
} else { } else {
let isFin = (FinMask & baseAddress[0]) let isFin = (FinMask & baseAddress[0])
let receivedOpcode = OpCode(rawValue: (OpCodeMask & baseAddress[0])) let receivedOpcodeRawValue = (OpCodeMask & baseAddress[0])
let receivedOpcode = OpCode(rawValue: receivedOpcodeRawValue)
let isMasked = (MaskMask & baseAddress[1]) let isMasked = (MaskMask & baseAddress[1])
let payloadLen = (PayloadLenMask & baseAddress[1]) let payloadLen = (PayloadLenMask & baseAddress[1])
var offset = 2 var offset = 2
@ -641,10 +646,10 @@ open class WebSocket : NSObject, StreamDelegate {
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: \(receivedOpcodeRawValue)", code: errCode))
writeError(errCode) writeError(errCode)
return emptyBuffer return emptyBuffer
} }
if isControlFrame && isFin == 0 { if isControlFrame && isFin == 0 {
let errCode = CloseCode.protocolError.rawValue let errCode = CloseCode.protocolError.rawValue
@ -687,18 +692,13 @@ open class WebSocket : NSObject, StreamDelegate {
if dataLength > UInt64(bufferLen) { if dataLength > UInt64(bufferLen) {
len = UInt64(bufferLen-offset) len = UInt64(bufferLen-offset)
} }
let data: Data if receivedOpcode == .connectionClose && len > 0 {
if len < 0 { let size = MemoryLayout<UInt16>.size
len = 0 offset += size
data = Data() len -= UInt64(size)
} else {
if receivedOpcode == .connectionClose && len > 0 {
let size = MemoryLayout<UInt16>.size
offset += size
len -= UInt64(size)
}
data = Data(bytes: baseAddress+offset, count: Int(len))
} }
let data = Data(bytes: baseAddress+offset, count: Int(len))
if receivedOpcode == .connectionClose { if receivedOpcode == .connectionClose {
var closeReason = "connection closed by server" var closeReason = "connection closed by server"
if let customCloseReason = String(data: data, encoding: .utf8) { if let customCloseReason = String(data: data, encoding: .utf8) {
@ -736,7 +736,7 @@ open class WebSocket : NSObject, StreamDelegate {
if receivedOpcode == .continueFrame { if receivedOpcode == .continueFrame {
let errCode = CloseCode.protocolError.rawValue let errCode = CloseCode.protocolError.rawValue
doDisconnect(errorWithDetail("first frame can't be a continue frame", doDisconnect(errorWithDetail("first frame can't be a continue frame",
code: errCode)) code: errCode))
writeError(errCode) writeError(errCode)
return emptyBuffer return emptyBuffer
} }
@ -751,7 +751,7 @@ open class WebSocket : NSObject, StreamDelegate {
} else { } else {
let errCode = CloseCode.protocolError.rawValue let errCode = CloseCode.protocolError.rawValue
doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame", doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame",
code: errCode)) code: errCode))
writeError(errCode) writeError(errCode)
return emptyBuffer return emptyBuffer
} }
@ -931,6 +931,7 @@ open class WebSocket : NSObject, StreamDelegate {
readyToWrite = false readyToWrite = false
mutex.unlock() mutex.unlock()
cleanupStream() cleanupStream()
writeQueue.cancelAllOperations()
} }
} }