@@ -111,14 +111,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
111111 public var selfSignedSSL = false
112112 private var security : SSLSecurity ?
113113 public var enabledSSLCipherSuites : [ SSLCipherSuite ] ?
114- public var origin : String ?
115114 public var isConnected : Bool {
116115 return connected
117116 }
118- public var currentURL : NSURL { return url}
119117 private var url : NSURL
120118 private var inputStream : NSInputStream ?
121119 private var outputStream : NSOutputStream ?
120+ private var isRunLoop = false
122121 private var connected = false
123122 private var isCreated = false
124123 private var writeQueue = NSOperationQueue ( )
@@ -127,24 +126,26 @@ public class WebSocket : NSObject, NSStreamDelegate {
127126 private var fragBuffer : NSData ?
128127 private var certValidated = false
129128 private var didDisconnect = false
130- //the shared processing queue used for all websocket
131- private static let sharedWorkQueue = dispatch_queue_create ( " com.vluxe.starscream.websocket " , DISPATCH_QUEUE_SERIAL)
132129
133130 //used for setting protocols.
134131 public init ( url: NSURL , protocols: [ String ] ? = nil ) {
135132 self . url = url
136- self . origin = url. absoluteString
137133 writeQueue. maxConcurrentOperationCount = 1
138134 optionalProtocols = protocols
139135 }
140136
141137 ///Connect to the websocket server on a background thread
142138 public func connect( ) {
143139 guard !isCreated else { return }
144- didDisconnect = false
145- isCreated = true
146- createHTTPRequest ( )
147- isCreated = false
140+
141+ dispatch_async ( queue) { [ weak self] in
142+ self ? . didDisconnect = false
143+ }
144+ dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ) ) { [ weak self] in
145+ self ? . isCreated = true
146+ self ? . createHTTPRequest ( )
147+ self ? . isCreated = false
148+ }
148149 }
149150
150151 /**
@@ -174,22 +175,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
174175
175176 ///write a string to the websocket. This sends it as a text frame.
176177 public func writeString( str: String ) {
177- guard isConnected else { return }
178178 dequeueWrite ( str. dataUsingEncoding ( NSUTF8StringEncoding) !, code: . TextFrame)
179179 }
180180
181181 ///write binary data to the websocket. This sends it as a binary frame.
182182 public func writeData( data: NSData ) {
183- guard isConnected else { return }
184183 dequeueWrite ( data, code: . BinaryFrame)
185184 }
186185
187186 //write a ping to the websocket. This sends it as a control frame.
188187 //yodel a sound to the planet. This sends it as an astroid. http://youtu.be/Eu5ZJELRiJ8?t=42s
189188 public func writePing( data: NSData ) {
190- guard isConnected else { return }
191189 dequeueWrite ( data, code: . Ping)
192190 }
191+ //private methods below!
193192
194193 //private method that starts the connection
195194 private func createHTTPRequest( ) {
@@ -212,9 +211,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
212211 }
213212 addHeader ( urlRequest, key: headerWSVersionName, val: headerWSVersionValue)
214213 addHeader ( urlRequest, key: headerWSKeyName, val: generateWebSocketKey ( ) )
215- if let origin = origin {
216- addHeader ( urlRequest, key: headerOriginName, val: origin)
217- }
214+ addHeader ( urlRequest, key: headerOriginName, val: url. absoluteString)
218215 addHeader ( urlRequest, key: headerWSHostName, val: " \( url. host!) : \( port!) " )
219216 for (key, value) in headers {
220217 addHeader ( urlRequest, key: key, val: value)
@@ -224,12 +221,10 @@ public class WebSocket : NSObject, NSStreamDelegate {
224221 initStreamsWithData ( serializedRequest, Int ( port!) )
225222 }
226223 }
227-
228224 //Add a header to the CFHTTPMessage by using the NSString bridges to CFString
229225 private func addHeader( urlRequest: CFHTTPMessage , key: NSString , val: NSString ) {
230226 CFHTTPMessageSetHeaderFieldValue ( urlRequest, key, val)
231227 }
232-
233228 //generate a websocket key as needed in rfc
234229 private func generateWebSocketKey( ) -> String {
235230 var key = " "
@@ -242,7 +237,6 @@ public class WebSocket : NSObject, NSStreamDelegate {
242237 let baseKey = data? . base64EncodedStringWithOptions ( NSDataBase64EncodingOptions ( rawValue: 0 ) )
243238 return baseKey!
244239 }
245-
246240 //Start the stream connection and write the data to the output stream
247241 private func initStreamsWithData( data: NSData , _ port: Int ) {
248242 //higher level API we will cut over to at some point
@@ -289,16 +283,15 @@ public class WebSocket : NSObject, NSStreamDelegate {
289283 }
290284 }
291285 }
292- CFReadStreamSetDispatchQueue( inStream, WebSocket . sharedWorkQueue)
293- CFWriteStreamSetDispatchQueue ( outStream, WebSocket . sharedWorkQueue)
286+ isRunLoop = true
287+ inStream. scheduleInRunLoop ( NSRunLoop . currentRunLoop ( ) , forMode: NSDefaultRunLoopMode)
288+ outStream. scheduleInRunLoop ( NSRunLoop . currentRunLoop ( ) , forMode: NSDefaultRunLoopMode)
294289 inStream. open ( )
295290 outStream. open ( )
296291 let bytes = UnsafePointer < UInt8 > ( data. bytes)
297- writeQueue. addOperationWithBlock {
298- while !outStream. hasSpaceAvailable {
299- usleep ( 100 ) //wait until the socket is ready
300- }
301- outStream. write ( bytes, maxLength: data. length)
292+ outStream. write ( bytes, maxLength: data. length)
293+ while ( isRunLoop) {
294+ NSRunLoop . currentRunLoop ( ) . runMode ( NSDefaultRunLoopMode, beforeDate: NSDate . distantFuture ( ) as NSDate )
302295 }
303296 }
304297 //delegate for the stream methods. Processes incoming bytes
@@ -331,16 +324,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
331324 private func disconnectStream( error: NSError? ) {
332325 writeQueue. waitUntilAllOperationsAreFinished ( )
333326 if let stream = inputStream {
334- CFReadStreamSetDispatchQueue ( stream, nil )
327+ stream. removeFromRunLoop ( NSRunLoop . currentRunLoop ( ) , forMode : NSDefaultRunLoopMode )
335328 stream. close ( )
336329 }
337330 if let stream = outputStream {
338- CFWriteStreamSetDispatchQueue ( stream, nil )
331+ stream. removeFromRunLoop ( NSRunLoop . currentRunLoop ( ) , forMode : NSDefaultRunLoopMode )
339332 stream. close ( )
340333 }
341334 outputStream = nil
335+ isRunLoop = false
342336 certValidated = false
343337 doDisconnect ( error)
338+ connected = false
344339 }
345340
346341 ///handles the incoming bytes and sending them to the proper processing method
@@ -350,13 +345,24 @@ public class WebSocket : NSObject, NSStreamDelegate {
350345 let length = inputStream!. read ( buffer, maxLength: BUFFER_MAX)
351346
352347 guard length > 0 else { return }
353- var process = false
354- if inputQueue. count == 0 {
355- process = true
356- }
357- inputQueue. append ( NSData ( bytes: buffer, length: length) )
358- if process {
359- dequeueInput ( )
348+
349+ if !connected {
350+ connected = processHTTP ( buffer, bufferLen: length)
351+ if !connected {
352+ let response = CFHTTPMessageCreateEmpty ( kCFAllocatorDefault, false ) . takeRetainedValue ( )
353+ CFHTTPMessageAppendBytes ( response, buffer, length)
354+ let code = CFHTTPMessageGetResponseStatusCode ( response)
355+ doDisconnect ( errorWithDetail ( " Invalid HTTP upgrade " , code: UInt16 ( code) ) )
356+ }
357+ } else {
358+ var process = false
359+ if inputQueue. count == 0 {
360+ process = true
361+ }
362+ inputQueue. append ( NSData ( bytes: buffer, length: length) )
363+ if process {
364+ dequeueInput ( )
365+ }
360366 }
361367 }
362368 ///dequeue the incoming input so it is processed in order
@@ -372,36 +378,13 @@ public class WebSocket : NSObject, NSStreamDelegate {
372378 self . fragBuffer = nil
373379 }
374380 let buffer = UnsafePointer < UInt8 > ( work. bytes)
375- let length = work. length
376- if !connected {
377- processTCPHandshake ( buffer, bufferLen: length)
378- } else {
379- processRawMessage ( buffer, bufferLen: length)
380- }
381+ processRawMessage ( buffer, bufferLen: work. length)
381382 inputQueue = inputQueue. filter { $0 != data}
382383 dequeueInput ( )
383384 }
384385
385- //handle checking the inital connection status
386- private func processTCPHandshake( buffer: UnsafePointer < UInt8 > , bufferLen: Int) {
387- let code = processHTTP ( buffer, bufferLen: bufferLen)
388- switch code {
389- case 0 :
390- connected = true
391- dispatch_async ( queue) { [ weak self] in
392- guard let s = self else { return }
393- s. onConnect ? ( )
394- s. delegate? . websocketDidConnect ( s)
395- }
396- case - 1 :
397- fragBuffer = NSData ( bytes: buffer, length: bufferLen)
398- break //do nothing, we are going to collect more data
399- default :
400- doDisconnect ( errorWithDetail ( " Invalid HTTP upgrade " , code: UInt16 ( code) ) )
401- }
402- }
403386 ///Finds the HTTP Packet in the TCP stream, by looking for the CRLF.
404- private func processHTTP( buffer: UnsafePointer < UInt8 > , bufferLen: Int) - > Int {
387+ private func processHTTP( buffer: UnsafePointer < UInt8 > , bufferLen: Int) - > Bool {
405388 let CRLFBytes = [ UInt8 ( ascii: " \r " ) , UInt8 ( ascii: " \n " ) , UInt8 ( ascii: " \r " ) , UInt8 ( ascii: " \n " ) ]
406389 var k = 0
407390 var totalSize = 0
@@ -417,37 +400,39 @@ public class WebSocket : NSObject, NSStreamDelegate {
417400 }
418401 }
419402 if totalSize > 0 {
420- let code = validateResponse ( buffer, bufferLen: totalSize)
421- if code != 0 {
422- return code
423- }
424- totalSize += 1 //skip the last \n
425- let restSize = bufferLen - totalSize
426- if restSize > 0 {
427- processRawMessage ( ( buffer+ totalSize) , bufferLen: restSize)
403+ if validateResponse ( buffer, bufferLen: totalSize) {
404+ dispatch_async ( queue) { [ weak self] in
405+ guard let s = self else { return }
406+ s. onConnect ? ( )
407+ s. delegate? . websocketDidConnect ( s)
408+ }
409+ totalSize += 1 //skip the last \n
410+ let restSize = bufferLen - totalSize
411+ if restSize > 0 {
412+ processRawMessage ( ( buffer+ totalSize) , bufferLen: restSize)
413+ }
414+ return true
428415 }
429- return 0 //success
430416 }
431- return - 1 //was unable to find the full TCP header
417+ return false
432418 }
433419
434420 ///validates the HTTP is a 101 as per the RFC spec
435- private func validateResponse( buffer: UnsafePointer < UInt8 > , bufferLen: Int) - > Int {
421+ private func validateResponse( buffer: UnsafePointer < UInt8 > , bufferLen: Int) - > Bool {
436422 let response = CFHTTPMessageCreateEmpty ( kCFAllocatorDefault, false ) . takeRetainedValue ( )
437423 CFHTTPMessageAppendBytes ( response, buffer, bufferLen)
438- let code = CFHTTPMessageGetResponseStatusCode ( response)
439- if code != 101 {
440- return code
424+ if CFHTTPMessageGetResponseStatusCode ( response) != 101 {
425+ return false
441426 }
442427 if let cfHeaders = CFHTTPMessageCopyAllHeaderFields ( response) {
443428 let headers = cfHeaders. takeRetainedValue ( ) as NSDictionary
444429 if let acceptKey = headers [ headerWSAcceptName] as? NSString {
445430 if acceptKey. length > 0 {
446- return 0
431+ return true
447432 }
448433 }
449434 }
450- return - 1
435+ return false
451436 }
452437
453438 ///read a 16 bit big endian value from a buffer
@@ -703,6 +688,8 @@ public class WebSocket : NSObject, NSStreamDelegate {
703688 }
704689 ///used to write things to the stream
705690 private func dequeueWrite( data: NSData, code: OpCode) {
691+ guard isConnected else { return }
692+
706693 writeQueue. addOperationWithBlock { [ weak self] in
707694 //stream isn't ready, let's wait
708695 guard let s = self else { return }
@@ -734,6 +721,9 @@ public class WebSocket : NSObject, NSStreamDelegate {
734721 }
735722 var total = 0
736723 while true {
724+ if !s. isConnected {
725+ break
726+ }
737727 guard let outStream = s. outputStream else { break }
738728 let writeBuffer = UnsafePointer < UInt8 > ( frame!. bytes+ total)
739729 let len = outStream. write ( writeBuffer, maxLength: offset- total)
@@ -761,16 +751,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
761751 ///used to preform the disconnect delegate
762752 private func do Disconnect( error: NSError? ) {
763753 guard !didDisconnect else { return }
764- didDisconnect = true
765- connected = false
754+
766755 dispatch_async ( queue) { [ weak self] in
767756 guard let s = self else { return }
757+ s. didDisconnect = true
768758 s. onDisconnect ? ( error)
769759 s. delegate? . websocketDidDisconnect ( s, error: error)
770760 }
771761 }
772762
773763}
764+
774765private class SSLCert {
775766 var certData : NSData ?
776767 var key : SecKeyRef ?
0 commit comments