bump websocket version

This commit is contained in:
Erik 2016-04-10 13:59:21 -04:00
parent 4ee196c5fb
commit ed3d49001f
3 changed files with 53 additions and 29 deletions

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)

View File

@ -116,7 +116,7 @@ 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))

View File

@ -180,30 +180,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.dataUsingEncoding(NSUTF8StringEncoding)!, code: .TextFrame) dequeueWrite(str.dataUsingEncoding(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 {
@ -283,18 +295,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
} }
} }
} }
CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue) CFReadStreamSetDispatchQueue(inStream, WebSocket.sharedWorkQueue)
@ -428,7 +440,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)))
} }
@ -547,10 +559,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
@ -603,7 +615,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()
@ -739,7 +751,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.addOperationWithBlock { [weak self] in writeQueue.addOperationWithBlock { [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 }
@ -788,6 +800,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
} }
} }