Merge branch '1.2'

This commit is contained in:
Erik 2015-04-08 17:07:59 -04:00
commit a0dff2fea4
7 changed files with 247 additions and 247 deletions

View File

@ -26,7 +26,7 @@ import Foundation
extension String { extension String {
private var length:Int { private var length:Int {
return countElements(self) return count(self)
} }
} }
@ -69,7 +69,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
var connected:Bool { var connected:Bool {
return self._connected return self._connected
} }
weak var client:SocketEngineClient? weak var client:SocketEngineClient?
var cookies:[NSHTTPCookie]? var cookies:[NSHTTPCookie]?
var pingInterval:Int? var pingInterval:Int?
@ -83,7 +83,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
return self._websocket return self._websocket
} }
var ws:WebSocket? var ws:WebSocket?
public init(client:SocketEngineClient, forcePolling:Bool, public init(client:SocketEngineClient, forcePolling:Bool,
forceWebsockets:Bool, withCookies cookies:[NSHTTPCookie]?) { forceWebsockets:Bool, withCookies cookies:[NSHTTPCookie]?) {
self.client = client self.client = client
@ -93,19 +93,19 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration(), self.session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration(),
delegate: nil, delegateQueue: self.workQueue) delegate: nil, delegateQueue: self.workQueue)
} }
public func close(#fast:Bool) { public func close(#fast:Bool) {
self.pingTimer?.invalidate() self.pingTimer?.invalidate()
self.closed = true self.closed = true
self.write("", withType: PacketType.CLOSE, withData: nil) self.write("", withType: PacketType.CLOSE, withData: nil)
self.ws?.disconnect() self.ws?.disconnect()
if fast || self.polling { if fast || self.polling {
self.client?.didForceClose("Disconnect") self.client?.didForceClose("Disconnect")
} }
} }
private func createBinaryDataForSend(data:NSData) -> (NSData?, String?) { private func createBinaryDataForSend(data:NSData) -> (NSData?, String?) {
if self.websocket { if self.websocket {
var byteArray = [UInt8](count: 1, repeatedValue: 0x0) var byteArray = [UInt8](count: 1, repeatedValue: 0x0)
@ -117,20 +117,20 @@ public class SocketEngine: NSObject, WebSocketDelegate {
var str = "b4" var str = "b4"
str += data.base64EncodedStringWithOptions( str += data.base64EncodedStringWithOptions(
NSDataBase64EncodingOptions.Encoding64CharacterLineLength) NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
return (nil, str) return (nil, str)
} }
} }
private func createURLs(params:[String: AnyObject]?) -> (String, String) { private func createURLs(params:[String: AnyObject]?) -> (String, String) {
if self.client == nil { if self.client == nil {
return ("", "") return ("", "")
} }
var url = "\(self.client!.socketURL)/socket.io/?transport=" var url = "\(self.client!.socketURL)/socket.io/?transport="
var urlPolling:String var urlPolling:String
var urlWebSocket:String var urlWebSocket:String
if self.client!.secure { if self.client!.secure {
urlPolling = "https://" + url + "polling" urlPolling = "https://" + url + "polling"
urlWebSocket = "wss://" + url + "websocket" urlWebSocket = "wss://" + url + "websocket"
@ -138,16 +138,16 @@ public class SocketEngine: NSObject, WebSocketDelegate {
urlPolling = "http://" + url + "polling" urlPolling = "http://" + url + "polling"
urlWebSocket = "ws://" + url + "websocket" urlWebSocket = "ws://" + url + "websocket"
} }
if params != nil { if params != nil {
for (key, value) in params! { for (key, value) in params! {
let keyEsc = key.stringByAddingPercentEncodingWithAllowedCharacters( let keyEsc = key.stringByAddingPercentEncodingWithAllowedCharacters(
NSCharacterSet.URLHostAllowedCharacterSet())! NSCharacterSet.URLHostAllowedCharacterSet())!
urlPolling += "&\(keyEsc)=" urlPolling += "&\(keyEsc)="
urlWebSocket += "&\(keyEsc)=" urlWebSocket += "&\(keyEsc)="
if value is String { if value is String {
let valueEsc = (value as String).stringByAddingPercentEncodingWithAllowedCharacters( let valueEsc = (value as! String).stringByAddingPercentEncodingWithAllowedCharacters(
NSCharacterSet.URLHostAllowedCharacterSet())! NSCharacterSet.URLHostAllowedCharacterSet())!
urlPolling += "\(valueEsc)" urlPolling += "\(valueEsc)"
urlWebSocket += "\(valueEsc)" urlWebSocket += "\(valueEsc)"
@ -157,26 +157,26 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
} }
} }
return (urlPolling, urlWebSocket) return (urlPolling, urlWebSocket)
} }
private func createWebsocket(andConnect connect:Bool) { private func createWebsocket(andConnect connect:Bool) {
self.ws = WebSocket(url: NSURL(string: self.urlWebSocket! + "&sid=\(self.sid)")!) self.ws = WebSocket(url: NSURL(string: self.urlWebSocket! + "&sid=\(self.sid)")!)
self.ws?.queue = self.handleQueue self.ws?.queue = self.handleQueue
self.ws?.delegate = self self.ws?.delegate = self
if connect { if connect {
self.ws?.connect() self.ws?.connect()
} }
} }
private func doFastUpgrade() { private func doFastUpgrade() {
if self.waitingForPoll { if self.waitingForPoll {
NSLog("Outstanding poll when switched to websockets," + NSLog("Outstanding poll when switched to websockets," +
"we'll probably disconnect soon. You should report this.") "we'll probably disconnect soon. You should report this.")
} }
self.sendWebSocketMessage("", withType: PacketType.UPGRADE, datas: nil) self.sendWebSocketMessage("", withType: PacketType.UPGRADE, datas: nil)
self._websocket = true self._websocket = true
self._polling = false self._polling = false
@ -184,25 +184,25 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.probing = false self.probing = false
self.flushProbeWait() self.flushProbeWait()
} }
private func doPoll() { private func doPoll() {
if self.websocket || self.waitingForPoll || !self.connected { if self.websocket || self.waitingForPoll || !self.connected {
return return
} }
self.waitingForPoll = true self.waitingForPoll = true
let req = NSMutableURLRequest(URL: NSURL(string: self.urlPolling! + "&sid=\(self.sid)&b64=1")!) let req = NSMutableURLRequest(URL: NSURL(string: self.urlPolling! + "&sid=\(self.sid)&b64=1")!)
self.doRequest(req) self.doRequest(req)
} }
private func doRequest(req:NSMutableURLRequest) { private func doRequest(req:NSMutableURLRequest) {
if !self.polling { if !self.polling {
return return
} }
req.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData req.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
// NSLog("Doing request: \(req)") // NSLog("Doing request: \(req)")
self.session.dataTaskWithRequest(req) {[weak self] data, res, err in self.session.dataTaskWithRequest(req) {[weak self] data, res, err in
if self == nil { if self == nil {
@ -213,20 +213,21 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} else { } else {
NSLog(err.localizedDescription) NSLog(err.localizedDescription)
} }
return return
} }
// NSLog("Got response: \(res)") // NSLog("Got response: \(res)")
if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String { if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
dispatch_async(self!.parseQueue) { dispatch_async(self!.parseQueue) {
self?.parsePollingMessage(str) self?.parsePollingMessage(str)
return return
} }
} }
self?.waitingForPoll = false self?.waitingForPoll = false
if self!.fastUpgrade { if self!.fastUpgrade {
self?.doFastUpgrade() self?.doFastUpgrade()
return return
@ -235,26 +236,26 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
}.resume() }.resume()
} }
private func flushProbeWait() { private func flushProbeWait() {
// NSLog("flushing probe wait") // NSLog("flushing probe wait")
dispatch_async(self.emitQueue) {[weak self] in dispatch_async(self.emitQueue) {[weak self] in
if self == nil { if self == nil {
return return
} }
for waiter in self!.probeWait { for waiter in self!.probeWait {
self?.write(waiter.msg, withType: waiter.type, withData: waiter.data) self?.write(waiter.msg, withType: waiter.type, withData: waiter.data)
} }
self?.probeWait.removeAll(keepCapacity: false) self?.probeWait.removeAll(keepCapacity: false)
if self?.postWait.count != 0 { if self?.postWait.count != 0 {
self?.flushWaitingForPostToWebSocket() self?.flushWaitingForPostToWebSocket()
} }
} }
} }
private func flushWaitingForPost() { private func flushWaitingForPost() {
if self.postWait.count == 0 || !self.connected { if self.postWait.count == 0 || !self.connected {
return return
@ -262,33 +263,33 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.flushWaitingForPostToWebSocket() self.flushWaitingForPostToWebSocket()
return return
} }
var postStr = "" var postStr = ""
for packet in self.postWait { for packet in self.postWait {
let len = countElements(packet) let len = count(packet)
postStr += "\(len):\(packet)" postStr += "\(len):\(packet)"
} }
self.postWait.removeAll(keepCapacity: false) self.postWait.removeAll(keepCapacity: false)
let req = NSMutableURLRequest(URL: NSURL(string: self.urlPolling! + "&sid=\(self.sid)")!) let req = NSMutableURLRequest(URL: NSURL(string: self.urlPolling! + "&sid=\(self.sid)")!)
req.HTTPMethod = "POST" req.HTTPMethod = "POST"
req.setValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type") req.setValue("text/plain; charset=UTF-8", forHTTPHeaderField: "Content-Type")
let postData = postStr.dataUsingEncoding(NSUTF8StringEncoding, let postData = postStr.dataUsingEncoding(NSUTF8StringEncoding,
allowLossyConversion: false)! allowLossyConversion: false)!
req.HTTPBody = postData req.HTTPBody = postData
req.setValue(String(postData.length), forHTTPHeaderField: "Content-Length") req.setValue(String(postData.length), forHTTPHeaderField: "Content-Length")
self.waitingForPost = true self.waitingForPost = true
// NSLog("posting: \(postStr)") // NSLog("posting: \(postStr)")
// NSLog("Posting with WS status of: \(self.websocket)") // NSLog("Posting with WS status of: \(self.websocket)")
self.session.dataTaskWithRequest(req) {[weak self] data, res, err in self.session.dataTaskWithRequest(req) {[weak self] data, res, err in
if self == nil { if self == nil {
return return
@ -299,7 +300,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
NSLog(err.localizedDescription) NSLog(err.localizedDescription)
return return
} }
self?.waitingForPost = false self?.waitingForPost = false
dispatch_async(self!.emitQueue) { dispatch_async(self!.emitQueue) {
if !self!.fastUpgrade { if !self!.fastUpgrade {
@ -308,89 +309,90 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
}}.resume() }}.resume()
} }
// We had packets waiting for send when we upgraded // We had packets waiting for send when we upgraded
// Send them raw // Send them raw
private func flushWaitingForPostToWebSocket() { private func flushWaitingForPostToWebSocket() {
for msg in self.postWait { for msg in self.postWait {
self.ws?.writeString(msg) self.ws?.writeString(msg)
} }
self.postWait.removeAll(keepCapacity: true) self.postWait.removeAll(keepCapacity: true)
} }
// A poll failed, tell the client about it // A poll failed, tell the client about it
private func handlePollingFailed(reason:String) { private func handlePollingFailed(reason:String) {
self._connected = false self._connected = false
self.ws?.disconnect() self.ws?.disconnect()
self.pingTimer?.invalidate() self.pingTimer?.invalidate()
self.waitingForPoll = false self.waitingForPoll = false
self.waitingForPost = false self.waitingForPost = false
if self.client == nil { if self.client == nil {
return return
} }
if !self.closed && !self.client!.reconnecting { if !self.closed && !self.client!.reconnecting {
self.client?.pollingDidFail(reason) self.client?.pollingDidFail(reason)
} else if !self.client!.reconnecting { } else if !self.client!.reconnecting {
self.client?.didForceClose(reason) self.client?.didForceClose(reason)
} }
} }
public func open(opts:[String: AnyObject]? = nil) { public func open(opts:[String: AnyObject]? = nil) {
if self.connected { if self.connected {
fatalError("Engine tried to open while connected") fatalError("Engine tried to open while connected")
} }
self.closed = false self.closed = false
let (urlPolling, urlWebSocket) = self.createURLs(opts) let (urlPolling, urlWebSocket) = self.createURLs(opts)
self.urlPolling = urlPolling self.urlPolling = urlPolling
self.urlWebSocket = urlWebSocket self.urlWebSocket = urlWebSocket
if self.forceWebsockets { if self.forceWebsockets {
self._polling = false self._polling = false
self._websocket = true self._websocket = true
self.createWebsocket(andConnect: true) self.createWebsocket(andConnect: true)
return return
} }
let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&b64=1")!) let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&b64=1")!)
if self.cookies != nil { if self.cookies != nil {
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(self.cookies!) let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(self.cookies!)
reqPolling.allHTTPHeaderFields = headers reqPolling.allHTTPHeaderFields = headers
} }
self.doRequest(reqPolling) self.doRequest(reqPolling)
} }
// Translatation of engine.io-parser#decodePayload // Translatation of engine.io-parser#decodePayload
private func parsePollingMessage(str:String) { private func parsePollingMessage(str:String) {
if str.length == 1 { if str.length == 1 {
return return
} }
// println(str) // println(str)
let strArray = Array(str) let strArray = Array(str)
var length = "" var length = ""
var n = 0 var n = 0
var msg = "" var msg = ""
func testLength(length:String, inout n:Int) -> Bool { func testLength(length:String, inout n:Int) -> Bool {
if let num = length.toInt() { if let num = length.toInt() {
n = num n = num
} else { } else {
return true return true
} }
return false return false
} }
for var i = 0, l = str.length; i < l; i = i &+ 1 { for var i = 0, l = str.length; i < l; i = i &+ 1 {
let chr = String(strArray[i]) let chr = String(strArray[i])
if chr != ":" { if chr != ":" {
length += chr length += chr
} else { } else {
@ -399,16 +401,16 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.handlePollingFailed("Error parsing XHR message") self.handlePollingFailed("Error parsing XHR message")
return return
} }
msg = String(strArray[i&+1...i&+n]) msg = String(strArray[i&+1...i&+n])
if let lengthInt = length.toInt() { if let lengthInt = length.toInt() {
if lengthInt != msg.length { if lengthInt != msg.length {
NSLog("parsing error: \(str)") NSLog("parsing error: \(str)")
return return
} }
} }
if msg.length != 0 { if msg.length != 0 {
// Be sure to capture the value of the msg // Be sure to capture the value of the msg
dispatch_async(self.handleQueue) {[weak self, msg] in dispatch_async(self.handleQueue) {[weak self, msg] in
@ -416,54 +418,54 @@ public class SocketEngine: NSObject, WebSocketDelegate {
return return
} }
} }
i += n i += n
length = "" length = ""
} }
} }
} }
private func parseEngineData(data:NSData) { private func parseEngineData(data:NSData) {
if self.client == nil { if self.client == nil {
return return
} }
dispatch_async(self.client!.handleQueue) {[weak self] in dispatch_async(self.client!.handleQueue) {[weak self] in
self?.client?.parseBinaryData(data.subdataWithRange(NSMakeRange(1, data.length - 1))) self?.client?.parseBinaryData(data.subdataWithRange(NSMakeRange(1, data.length - 1)))
return return
} }
} }
private func parseEngineMessage(var message:String, fromPolling:Bool) { private func parseEngineMessage(var message:String, fromPolling:Bool) {
// NSLog("Engine got message: \(message)") // NSLog("Engine got message: \(message)")
if fromPolling { if fromPolling {
fixDoubleUTF8(&message) fixDoubleUTF8(&message)
} }
let type = message["^(\\d)"].groups()?[1] let type = message["^(\\d)"].groups()?[1]
if type != PacketType.MESSAGE.rawValue { if type != PacketType.MESSAGE.rawValue {
// TODO Handle other packets // TODO Handle other packets
if message.hasPrefix("b4") { if message.hasPrefix("b4") {
// binary in base64 string // binary in base64 string
message.removeRange(Range<String.Index>(start: message.startIndex, message.removeRange(Range<String.Index>(start: message.startIndex,
end: advance(message.startIndex, 2))) end: advance(message.startIndex, 2)))
if let data = NSData(base64EncodedString: message, if let data = NSData(base64EncodedString: message,
options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters) { options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters) {
// println("sending \(data)") // println("sending \(data)")
if self.client == nil { if self.client == nil {
return return
} }
dispatch_async(self.client!.handleQueue) {[weak self] in dispatch_async(self.client!.handleQueue) {[weak self] in
self?.client?.parseBinaryData(data) self?.client?.parseBinaryData(data)
return return
} }
} }
return return
} else if type == PacketType.NOOP.rawValue { } else if type == PacketType.NOOP.rawValue {
self.doPoll() self.doPoll()
@ -474,14 +476,14 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.upgradeTransport() self.upgradeTransport()
return return
} }
return return
} else if type == PacketType.OPEN.rawValue { } else if type == PacketType.OPEN.rawValue {
var err:NSError? var err:NSError?
message.removeAtIndex(message.startIndex) message.removeAtIndex(message.startIndex)
let mesData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! let mesData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
if let json = NSJSONSerialization.JSONObjectWithData(mesData, if let json = NSJSONSerialization.JSONObjectWithData(mesData,
options: NSJSONReadingOptions.AllowFragments, error: &err) as? NSDictionary { options: NSJSONReadingOptions.AllowFragments, error: &err) as? NSDictionary {
if let sid = json["sid"] as? String { if let sid = json["sid"] as? String {
@ -495,55 +497,55 @@ public class SocketEngine: NSObject, WebSocketDelegate {
NSLog("Error handshaking") NSLog("Error handshaking")
return return
} }
if let pingInterval = json["pingInterval"] as? Int { if let pingInterval = json["pingInterval"] as? Int {
self.pingInterval = pingInterval / 1000 self.pingInterval = pingInterval / 1000
} }
} else { } else {
fatalError("Error parsing engine connect") fatalError("Error parsing engine connect")
} }
self.startPingTimer() self.startPingTimer()
if !self.forceWebsockets { if !self.forceWebsockets {
self.doPoll() self.doPoll()
} }
return return
} else if type == PacketType.CLOSE.rawValue { } else if type == PacketType.CLOSE.rawValue {
if self.client == nil { if self.client == nil {
return return
} }
if self.polling { if self.polling {
self.client!.didForceClose("Disconnect") self.client!.didForceClose("Disconnect")
} }
return return
} }
// println("Got something idk what to do with") // println("Got something idk what to do with")
// println(messageString) // println(messageString)
} }
// Remove message type // Remove message type
message.removeAtIndex(message.startIndex) message.removeAtIndex(message.startIndex)
if self.client == nil { if self.client == nil {
return return
} }
dispatch_async(self.client!.handleQueue) {[weak self] in dispatch_async(self.client!.handleQueue) {[weak self] in
self?.client?.parseSocketMessage(message) self?.client?.parseSocketMessage(message)
return return
} }
} }
private func probeWebSocket() { private func probeWebSocket() {
if self.websocketConnected { if self.websocketConnected {
self.sendWebSocketMessage("probe", withType: PacketType.PING) self.sendWebSocketMessage("probe", withType: PacketType.PING)
} }
} }
/// Send an engine message (4) /// Send an engine message (4)
public func send(msg:String, withData datas:ContiguousArray<NSData>?) { public func send(msg:String, withData datas:ContiguousArray<NSData>?) {
if self.probing { if self.probing {
@ -552,11 +554,11 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.write(msg, withType: PacketType.MESSAGE, withData: datas) self.write(msg, withType: PacketType.MESSAGE, withData: datas)
} }
} }
func sendPing() { func sendPing() {
self.write("", withType: PacketType.PING, withData: nil) self.write("", withType: PacketType.PING, withData: nil)
} }
/// Send polling message. /// Send polling message.
/// Only call on emitQueue /// Only call on emitQueue
private func sendPollMessage(var msg:String, withType type:PacketType, private func sendPollMessage(var msg:String, withType type:PacketType,
@ -564,29 +566,29 @@ public class SocketEngine: NSObject, WebSocketDelegate {
// println("Sending poll: \(msg) as type: \(type.rawValue)") // println("Sending poll: \(msg) as type: \(type.rawValue)")
doubleEncodeUTF8(&msg) doubleEncodeUTF8(&msg)
let strMsg = "\(type.rawValue)\(msg)" let strMsg = "\(type.rawValue)\(msg)"
self.postWait.append(strMsg) self.postWait.append(strMsg)
if datas != nil { if datas != nil {
for data in datas! { for data in datas! {
let (nilData, b64Data) = self.createBinaryDataForSend(data) let (nilData, b64Data) = self.createBinaryDataForSend(data)
self.postWait.append(b64Data!) self.postWait.append(b64Data!)
} }
} }
if !self.waitingForPost { if !self.waitingForPost {
self.flushWaitingForPost() self.flushWaitingForPost()
} }
} }
/// Send message on WebSockets /// Send message on WebSockets
/// Only call on emitQueue /// Only call on emitQueue
private func sendWebSocketMessage(str:String, withType type:PacketType, private func sendWebSocketMessage(str:String, withType type:PacketType,
datas:ContiguousArray<NSData>? = nil) { datas:ContiguousArray<NSData>? = nil) {
// println("Sending ws: \(str) as type: \(type.rawValue)") // println("Sending ws: \(str) as type: \(type.rawValue)")
self.ws?.writeString("\(type.rawValue)\(str)") self.ws?.writeString("\(type.rawValue)\(str)")
if datas != nil { if datas != nil {
for data in datas! { for data in datas! {
let (data, nilString) = self.createBinaryDataForSend(data) let (data, nilString) = self.createBinaryDataForSend(data)
@ -596,13 +598,13 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
} }
} }
// Starts the ping timer // Starts the ping timer
private func startPingTimer() { private func startPingTimer() {
if self.pingInterval == nil { if self.pingInterval == nil {
return return
} }
self.pingTimer?.invalidate() self.pingTimer?.invalidate()
dispatch_async(dispatch_get_main_queue()) { dispatch_async(dispatch_get_main_queue()) {
self.pingTimer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(self.pingInterval!), self.pingTimer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(self.pingInterval!),
@ -610,7 +612,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
selector: Selector("sendPing"), userInfo: nil, repeats: true) selector: Selector("sendPing"), userInfo: nil, repeats: true)
} }
} }
private func upgradeTransport() { private func upgradeTransport() {
if self.websocketConnected { if self.websocketConnected {
// NSLog("Doing fast upgrade") // NSLog("Doing fast upgrade")
@ -620,13 +622,13 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.sendPollMessage("", withType: PacketType.NOOP) self.sendPollMessage("", withType: PacketType.NOOP)
} }
} }
public func write(msg:String, withType type:PacketType, withData data:ContiguousArray<NSData>?) { public func write(msg:String, withType type:PacketType, withData data:ContiguousArray<NSData>?) {
dispatch_async(self.emitQueue) {[weak self] in dispatch_async(self.emitQueue) {[weak self] in
if self == nil || !self!.connected { if self == nil || !self!.connected {
return return
} }
if self!.websocket { if self!.websocket {
// NSLog("writing ws: \(msg):\(data)") // NSLog("writing ws: \(msg):\(data)")
self?.sendWebSocketMessage(msg, withType: type, datas: data) self?.sendWebSocketMessage(msg, withType: type, datas: data)
@ -636,12 +638,12 @@ public class SocketEngine: NSObject, WebSocketDelegate {
} }
} }
} }
// Delagate methods // Delagate methods
public func websocketDidConnect(socket:WebSocket) { public func websocketDidConnect(socket:WebSocket) {
self.websocketConnected = true self.websocketConnected = true
if !self.forceWebsockets { if !self.forceWebsockets {
self.probing = true self.probing = true
self.probeWebSocket() self.probeWebSocket()
@ -651,21 +653,21 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self._polling = false self._polling = false
} }
} }
public func websocketDidDisconnect(socket:WebSocket, error:NSError?) { public func websocketDidDisconnect(socket:WebSocket, error:NSError?) {
self.websocketConnected = false self.websocketConnected = false
self.probing = false self.probing = false
if self.closed { if self.closed {
self.client?.didForceClose("Disconnect") self.client?.didForceClose("Disconnect")
return return
} }
if self.websocket { if self.websocket {
self.pingTimer?.invalidate() self.pingTimer?.invalidate()
self._connected = false self._connected = false
self._websocket = false self._websocket = false
let reason = error?.localizedDescription let reason = error?.localizedDescription
self.client?.webSocketDidCloseWithCode(1, self.client?.webSocketDidCloseWithCode(1,
reason: reason == nil ? "Socket Disconnected" : reason!) reason: reason == nil ? "Socket Disconnected" : reason!)
@ -673,11 +675,11 @@ public class SocketEngine: NSObject, WebSocketDelegate {
self.flushProbeWait() self.flushProbeWait()
} }
} }
public func websocketDidReceiveMessage(socket:WebSocket, text:String) { public func websocketDidReceiveMessage(socket:WebSocket, text:String) {
self.parseEngineMessage(text, fromPolling: false) self.parseEngineMessage(text, fromPolling: false)
} }
public func websocketDidReceiveData(socket:WebSocket, data:NSData) { public func websocketDidReceiveData(socket:WebSocket, data:NSData) {
self.parseEngineData(data) self.parseEngineData(data)
} }

View File

@ -34,4 +34,4 @@ func doubleEncodeUTF8(inout str:String) {
let latin1 = str.dataUsingEncoding(NSUTF8StringEncoding)! let latin1 = str.dataUsingEncoding(NSUTF8StringEncoding)!
let utf8 = NSString(data: latin1, encoding: NSISOLatin1StringEncoding)! let utf8 = NSString(data: latin1, encoding: NSISOLatin1StringEncoding)!
str = utf8 as String str = utf8 as String
} }

View File

@ -195,7 +195,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
return return
} }
self?.ackHandlers.addAck(ack, callback) self?.ackHandlers.addAck(ack, callback: callback)
dispatch_async(self!.emitQueue) { dispatch_async(self!.emitQueue) {
self?._emit(event, items, ack: ack) self?._emit(event, items, ack: ack)
@ -344,7 +344,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
var ackData:[AnyObject]? var ackData:[AnyObject]?
if data is NSArray { if data is NSArray {
ackData = data as? NSArray ackData = (data as? [AnyObject]?)!
} else if data != nil { } else if data != nil {
ackData = [data!] ackData = [data!]
} }

View File

@ -32,7 +32,7 @@ enum SocketPacketType:Int {
case ERROR = 4 case ERROR = 4
case BINARY_EVENT = 5 case BINARY_EVENT = 5
case BINARY_ACK = 6 case BINARY_ACK = 6
init(str:String) { init(str:String) {
if let int = str.toInt() { if let int = str.toInt() {
self = SocketPacketType(rawValue: int)! self = SocketPacketType(rawValue: int)!
@ -51,7 +51,7 @@ class SocketPacket {
var nsp = "" var nsp = ""
var placeholders:Int? var placeholders:Int?
var type:SocketPacketType? var type:SocketPacketType?
init(type:SocketPacketType?, data:[AnyObject]? = nil, nsp:String = "", init(type:SocketPacketType?, data:[AnyObject]? = nil, nsp:String = "",
placeholders:Int? = nil, id:Int? = nil) { placeholders:Int? = nil, id:Int? = nil) {
self.type = type self.type = type
@ -60,11 +60,11 @@ class SocketPacket {
self.placeholders = placeholders self.placeholders = placeholders
self.id = id self.id = id
} }
func getEvent() -> String { func getEvent() -> String {
return data?.removeAtIndex(0) as String return data?.removeAtIndex(0) as! String
} }
func addData(data:NSData) -> Bool { func addData(data:NSData) -> Bool {
func checkDoEvent() -> Bool { func checkDoEvent() -> Bool {
if self.placeholders == self.currentPlace { if self.placeholders == self.currentPlace {
@ -73,14 +73,14 @@ class SocketPacket {
return false return false
} }
} }
if checkDoEvent() { if checkDoEvent() {
return true return true
} }
self.binary.append(data) self.binary.append(data)
self.currentPlace++ self.currentPlace++
if checkDoEvent() { if checkDoEvent() {
self.currentPlace = 0 self.currentPlace = 0
return true return true
@ -88,14 +88,14 @@ class SocketPacket {
return false return false
} }
} }
func createMessageForEvent(event:String) -> String { func createMessageForEvent(event:String) -> String {
var message:String var message:String
var jsonSendError:NSError? var jsonSendError:NSError?
if self.binary.count == 0 { if self.binary.count == 0 {
self.type = SocketPacketType.EVENT self.type = SocketPacketType.EVENT
if self.nsp == "/" { if self.nsp == "/" {
if self.id == nil { if self.id == nil {
message = "2[\"\(event)\"" message = "2[\"\(event)\""
@ -111,7 +111,7 @@ class SocketPacket {
} }
} else { } else {
self.type = SocketPacketType.BINARY_EVENT self.type = SocketPacketType.BINARY_EVENT
if self.nsp == "/" { if self.nsp == "/" {
if self.id == nil { if self.id == nil {
message = "5\(self.binary.count)-[\"\(event)\"" message = "5\(self.binary.count)-[\"\(event)\""
@ -126,16 +126,16 @@ class SocketPacket {
} }
} }
} }
return self.completeMessage(message) return self.completeMessage(message)
} }
func createAck() -> String { func createAck() -> String {
var msg:String var msg:String
if self.binary.count == 0 { if self.binary.count == 0 {
self.type = SocketPacketType.ACK self.type = SocketPacketType.ACK
if nsp == "/" { if nsp == "/" {
msg = "3\(self.id!)[" msg = "3\(self.id!)["
} else { } else {
@ -143,58 +143,57 @@ class SocketPacket {
} }
} else { } else {
self.type = SocketPacketType.BINARY_ACK self.type = SocketPacketType.BINARY_ACK
if nsp == "/" { if nsp == "/" {
msg = "6\(self.binary.count)-\(self.id!)[" msg = "6\(self.binary.count)-\(self.id!)["
} else { } else {
msg = "6\(self.binary.count)-/\(self.nsp),\(self.id!)[" msg = "6\(self.binary.count)-/\(self.nsp),\(self.id!)["
} }
} }
return self.completeMessage(msg, ack: true) return self.completeMessage(msg, ack: true)
} }
func completeMessage(var message:String, ack:Bool = false) -> String { func completeMessage(var message:String, ack:Bool = false) -> String {
var err:NSError? var err:NSError?
if self.data == nil || self.data!.count == 0 { if self.data == nil || self.data!.count == 0 {
return message + "]" return message + "]"
} else if !ack { } else if !ack {
message += "," message += ","
} }
for arg in self.data! { for arg in self.data! {
if arg is NSDictionary || arg is [AnyObject] { if arg is NSDictionary || arg is [AnyObject] {
let jsonSend = NSJSONSerialization.dataWithJSONObject(arg, let jsonSend = NSJSONSerialization.dataWithJSONObject(arg,
options: NSJSONWritingOptions(0), error: &err) options: NSJSONWritingOptions(0), error: &err)
let jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding) let jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding)
message += jsonString! as String message += jsonString! as String
message += "," message += ","
continue continue
} }
if arg is String { if arg is String {
message += "\"\(arg)\"" message += "\"\(arg)\""
message += "," message += ","
continue continue
} }
message += "\(arg)" message += "\(arg)"
message += "," message += ","
} }
if message != "" { if message != "" {
message.removeAtIndex(message.endIndex.predecessor()) message.removeAtIndex(message.endIndex.predecessor())
} }
return message + "]" return message + "]"
} }
func fillInPlaceholders() { func fillInPlaceholders() {
var newArr = NSMutableArray(array: self.data!) var newArr = NSMutableArray(array: self.data!)
for i in 0..<self.data!.count { for i in 0..<self.data!.count {
if let str = self.data?[i] as? String { if let str = self.data?[i] as? String {
if let num = str["~~(\\d)"].groups() { if let num = str["~~(\\d)"].groups() {
@ -204,10 +203,10 @@ class SocketPacket {
newArr[i] = self._fillInPlaceholders(self.data![i]) newArr[i] = self._fillInPlaceholders(self.data![i])
} }
} }
self.data = newArr self.data = newArr as [AnyObject]
} }
private func _fillInPlaceholders(data:AnyObject) -> AnyObject { private func _fillInPlaceholders(data:AnyObject) -> AnyObject {
if let str = data as? String { if let str = data as? String {
if let num = str["~~(\\d)"].groups() { if let num = str["~~(\\d)"].groups() {
@ -217,19 +216,19 @@ class SocketPacket {
} }
} else if let dict = data as? NSDictionary { } else if let dict = data as? NSDictionary {
var newDict = NSMutableDictionary(dictionary: dict) var newDict = NSMutableDictionary(dictionary: dict)
for (key, value) in dict { for (key, value) in dict {
newDict[key as NSCopying] = _fillInPlaceholders(value) newDict[key as! NSCopying] = _fillInPlaceholders(value)
} }
return newDict return newDict
} else if let arr = data as? NSArray { } else if let arr = data as? NSArray {
var newArr = NSMutableArray(array: arr) var newArr = NSMutableArray(array: arr)
for i in 0..<arr.count { for i in 0..<arr.count {
newArr[i] = _fillInPlaceholders(arr[i]) newArr[i] = _fillInPlaceholders(arr[i])
} }
return newArr return newArr
} else { } else {
return data return data

View File

@ -22,48 +22,48 @@
import Foundation import Foundation
private let shredder = SocketParser.PacketShredder()
class SocketParser { class SocketParser {
private static let shredder = SocketParser.PacketShredder()
// Translation of socket.io-parser#deconstructPacket // Translation of socket.io-parser#deconstructPacket
private class PacketShredder { private class PacketShredder {
var buf = ContiguousArray<NSData>() var buf = ContiguousArray<NSData>()
func shred(data:AnyObject) -> AnyObject { func shred(data:AnyObject) -> AnyObject {
if let bin = data as? NSData { if let bin = data as? NSData {
let placeholder = ["_placeholder" :true, "num": buf.count] let placeholder = ["_placeholder" :true, "num": buf.count]
buf.append(bin) buf.append(bin)
return placeholder return placeholder
} else if let arr = data as? NSArray { } else if let arr = data as? NSArray {
var newArr = NSMutableArray(array: arr) var newArr = NSMutableArray(array: arr)
for i in 0..<arr.count { for i in 0..<arr.count {
newArr[i] = shred(arr[i]) newArr[i] = shred(arr[i])
} }
return newArr return newArr
} else if let dict = data as? NSDictionary { } else if let dict = data as? NSDictionary {
var newDict = NSMutableDictionary(dictionary: dict) var newDict = NSMutableDictionary(dictionary: dict)
for (key, value) in newDict { for (key, value) in newDict {
newDict[key as NSCopying] = shred(value) newDict[key as! NSCopying] = shred(value)
} }
return newDict return newDict
} else { } else {
return data return data
} }
} }
func deconstructPacket(packet:SocketPacket) { func deconstructPacket(packet:SocketPacket) {
if packet.data == nil { if packet.data == nil {
return return
} }
var data = packet.data! var data = packet.data!
for i in 0..<data.count { for i in 0..<data.count {
if data[i] is NSArray || data[i] is NSDictionary { if data[i] is NSArray || data[i] is NSDictionary {
data[i] = shred(data[i]) data[i] = shred(data[i])
@ -72,37 +72,37 @@ class SocketParser {
buf.append(bin) buf.append(bin)
} }
} }
packet.data = data packet.data = data
packet.binary = buf packet.binary = buf
buf.removeAll(keepCapacity: true) buf.removeAll(keepCapacity: true)
} }
} }
// Translation of socket.io-client#decodeString // Translation of socket.io-client#decodeString
class func parseString(str:String) -> SocketPacket? { class func parseString(str:String) -> SocketPacket? {
let arr = Array(str) let arr = Array(str)
let type = String(arr[0]) let type = String(arr[0])
if arr.count == 1 { if arr.count == 1 {
return SocketPacket(type: SocketPacketType(str: type)) return SocketPacket(type: SocketPacketType(str: type))
} }
var id = nil as Int? var id = nil as Int?
var nsp = "" var nsp = ""
var i = 0 var i = 0
var placeholders = -1 var placeholders = -1
if type == "5" || type == "6" { if type == "5" || type == "6" {
var buf = "" var buf = ""
while arr[++i] != "-" { while arr[++i] != "-" {
buf += String(arr[i]) buf += String(arr[i])
if i == arr.count { if i == arr.count {
break break
} }
} }
if buf.toInt() == nil || arr[i] != "-" { if buf.toInt() == nil || arr[i] != "-" {
NSLog("Error parsing \(str)") NSLog("Error parsing \(str)")
return nil return nil
@ -110,26 +110,26 @@ class SocketParser {
placeholders = buf.toInt()! placeholders = buf.toInt()!
} }
} }
if arr[i + 1] == "/" { if arr[i + 1] == "/" {
while ++i < arr.count { while ++i < arr.count {
let c = arr[i] let c = arr[i]
if c == "," { if c == "," {
break break
} }
nsp += String(c) nsp += String(c)
} }
} }
if i + 1 >= arr.count { if i + 1 >= arr.count {
return SocketPacket(type: SocketPacketType(str: type), return SocketPacket(type: SocketPacketType(str: type),
nsp: nsp, placeholders: placeholders, id: id) nsp: nsp, placeholders: placeholders, id: id)
} }
let next = String(arr[i + 1]) let next = String(arr[i + 1])
if next.toInt() != nil { if next.toInt() != nil {
var c = "" var c = ""
while ++i < arr.count { while ++i < arr.count {
@ -140,48 +140,48 @@ class SocketParser {
break break
} }
} }
id = c.toInt() id = c.toInt()
} }
if i + 1 < arr.count { if i + 1 < arr.count {
let d = String(arr[++i...arr.count-1]) let d = String(arr[++i...arr.count-1])
let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\"" let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
let data = SocketParser.parseData(noPlaceholders) as [AnyObject] let data = SocketParser.parseData(noPlaceholders) as! [AnyObject]
return SocketPacket(type: SocketPacketType(str: type), data: data, return SocketPacket(type: SocketPacketType(str: type), data: data,
nsp: nsp, placeholders: placeholders, id: id) nsp: nsp, placeholders: placeholders, id: id)
} }
return nil return nil
} }
// Parses data for events // Parses data for events
class func parseData(data:String) -> AnyObject? { class func parseData(data:String) -> AnyObject? {
var err:NSError? var err:NSError?
let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let parsed:AnyObject? = NSJSONSerialization.JSONObjectWithData(stringData!, let parsed:AnyObject? = NSJSONSerialization.JSONObjectWithData(stringData!,
options: NSJSONReadingOptions.AllowFragments, error: &err) options: NSJSONReadingOptions.AllowFragments, error: &err)
if err != nil { if err != nil {
// println(err) // println(err)
return nil return nil
} }
return parsed return parsed
} }
class func parseForEmit(packet:SocketPacket) { class func parseForEmit(packet:SocketPacket) {
shredder.deconstructPacket(packet) shredder.deconstructPacket(packet)
} }
// Parses messages recieved // Parses messages recieved
class func parseSocketMessage(stringMessage:String, socket:SocketIOClient) { class func parseSocketMessage(stringMessage:String, socket:SocketIOClient) {
if stringMessage == "" { if stringMessage == "" {
return return
} }
func checkNSP(nsp:String) -> Bool { func checkNSP(nsp:String) -> Bool {
if nsp == "" && socket.nsp != "/" { if nsp == "" && socket.nsp != "/" {
return true return true
@ -189,33 +189,33 @@ class SocketParser {
return false return false
} }
} }
let p = parseString(stringMessage) as SocketPacket! let p = parseString(stringMessage) as SocketPacket!
if p.type == SocketPacketType.EVENT { if p.type == SocketPacketType.EVENT {
if checkNSP(p.nsp) { if checkNSP(p.nsp) {
return return
} }
socket.handleEvent(p.getEvent(), data: p.data, socket.handleEvent(p.getEvent(), data: p.data,
isInternalMessage: false, wantsAck: p.id) isInternalMessage: false, wantsAck: p.id)
} else if p.type == SocketPacketType.ACK { } else if p.type == SocketPacketType.ACK {
if checkNSP(p.nsp) { if checkNSP(p.nsp) {
return return
} }
socket.handleAck(p.id!, data: p.data) socket.handleAck(p.id!, data: p.data)
} else if p.type == SocketPacketType.BINARY_EVENT { } else if p.type == SocketPacketType.BINARY_EVENT {
if checkNSP(p.nsp) { if checkNSP(p.nsp) {
return return
} }
socket.waitingData.append(p) socket.waitingData.append(p)
} else if p.type == SocketPacketType.BINARY_ACK { } else if p.type == SocketPacketType.BINARY_ACK {
if checkNSP(p.nsp) { if checkNSP(p.nsp) {
return return
} }
p.justAck = true p.justAck = true
socket.waitingData.append(p) socket.waitingData.append(p)
} else if p.type == SocketPacketType.CONNECT { } else if p.type == SocketPacketType.CONNECT {
@ -230,25 +230,25 @@ class SocketParser {
socket.didForceClose("Got Disconnect") socket.didForceClose("Got Disconnect")
} }
} }
// Handles binary data // Handles binary data
class func parseBinaryData(data:NSData, socket:SocketIOClient) { class func parseBinaryData(data:NSData, socket:SocketIOClient) {
// NSLog(data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros)) // NSLog(data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros))
if socket.waitingData.count == 0 { if socket.waitingData.count == 0 {
NSLog("Got data when not remaking packet") NSLog("Got data when not remaking packet")
return return
} }
let shouldExecute = socket.waitingData[0].addData(data) let shouldExecute = socket.waitingData[0].addData(data)
if !shouldExecute { if !shouldExecute {
return return
} }
let packet = socket.waitingData.removeAtIndex(0) let packet = socket.waitingData.removeAtIndex(0)
packet.fillInPlaceholders() packet.fillInPlaceholders()
if !packet.justAck { if !packet.justAck {
socket.handleEvent(packet.getEvent(), data: packet.data, socket.handleEvent(packet.getEvent(), data: packet.data,
wantsAck: packet.id) wantsAck: packet.id)

View File

@ -18,7 +18,7 @@ var swiftRegexCache = [String: NSRegularExpression]()
public class SwiftRegex: NSObject, BooleanType { public class SwiftRegex: NSObject, BooleanType {
var target:String var target:String
var regex: NSRegularExpression var regex: NSRegularExpression
init(target:String, pattern:String, options:NSRegularExpressionOptions = nil) { init(target:String, pattern:String, options:NSRegularExpressionOptions = nil) {
self.target = target self.target = target
if let regex = swiftRegexCache[pattern] { if let regex = swiftRegexCache[pattern] {
@ -36,16 +36,16 @@ public class SwiftRegex: NSObject, BooleanType {
} }
super.init() super.init()
} }
class func failure(message: String) { class func failure(message: String) {
println("SwiftRegex: "+message) println("SwiftRegex: "+message)
//assert(false,"SwiftRegex: failed") //assert(false,"SwiftRegex: failed")
} }
final var targetRange: NSRange { final var targetRange: NSRange {
return NSRange(location: 0,length: countElements(target.utf16)) return NSRange(location: 0,length: count(target.utf16))
} }
final func substring(range: NSRange) -> String? { final func substring(range: NSRange) -> String? {
if ( range.location != NSNotFound ) { if ( range.location != NSNotFound ) {
return (target as NSString).substringWithRange(range) return (target as NSString).substringWithRange(range)
@ -53,23 +53,23 @@ public class SwiftRegex: NSObject, BooleanType {
return nil return nil
} }
} }
public func doesMatch(options: NSMatchingOptions = nil) -> Bool { public func doesMatch(options: NSMatchingOptions = nil) -> Bool {
return range(options: options).location != NSNotFound return range(options: options).location != NSNotFound
} }
public func range(options: NSMatchingOptions = nil) -> NSRange { public func range(options: NSMatchingOptions = nil) -> NSRange {
return regex.rangeOfFirstMatchInString(target as String, options: nil, range: targetRange) return regex.rangeOfFirstMatchInString(target as String, options: nil, range: targetRange)
} }
public func match(options: NSMatchingOptions = nil) -> String? { public func match(options: NSMatchingOptions = nil) -> String? {
return substring(range(options: options)) return substring(range(options: options))
} }
public func groups(options: NSMatchingOptions = nil) -> [String]? { public func groups(options: NSMatchingOptions = nil) -> [String]? {
return groupsForMatch(regex.firstMatchInString(target as String, options: options, range: targetRange)) return groupsForMatch(regex.firstMatchInString(target as String, options: options, range: targetRange))
} }
func groupsForMatch(match: NSTextCheckingResult!) -> [String]? { func groupsForMatch(match: NSTextCheckingResult!) -> [String]? {
if match != nil { if match != nil {
var groups = [String]() var groups = [String]()
@ -85,51 +85,51 @@ public class SwiftRegex: NSObject, BooleanType {
return nil return nil
} }
} }
public subscript(groupno: Int) -> String? { public subscript(groupno: Int) -> String? {
get { get {
return groups()?[groupno] return groups()?[groupno]
} }
set(newValue) { set(newValue) {
if newValue == nil { if newValue == nil {
return return
} }
for match in matchResults()!.reverse() { for match in matchResults()!.reverse() {
let replacement = regex.replacementStringForResult(match, let replacement = regex.replacementStringForResult(match,
inString: target as String, offset: 0, template: newValue!) inString: target as String, offset: 0, template: newValue!)
let mut = NSMutableString(string: target) let mut = NSMutableString(string: target)
mut.replaceCharactersInRange(match.rangeAtIndex(groupno), withString: replacement) mut.replaceCharactersInRange(match.rangeAtIndex(groupno), withString: replacement)
target = mut as String target = mut as String
} }
} }
} }
func matchResults(options: NSMatchingOptions = nil) -> [NSTextCheckingResult]? { func matchResults(options: NSMatchingOptions = nil) -> [NSTextCheckingResult]? {
let matches = regex.matchesInString(target as String, options: options, range: targetRange) let matches = regex.matchesInString(target as String, options: options, range: targetRange)
as? [NSTextCheckingResult] as? [NSTextCheckingResult]
if matches != nil { if matches != nil {
return matches! return matches!
} else { } else {
return nil return nil
} }
} }
public func ranges(options: NSMatchingOptions = nil) -> [NSRange] { public func ranges(options: NSMatchingOptions = nil) -> [NSRange] {
return matchResults(options: options)!.map { $0.range } return matchResults(options: options)!.map { $0.range }
} }
public func matches(options: NSMatchingOptions = nil) -> [String] { public func matches(options: NSMatchingOptions = nil) -> [String] {
return matchResults(options: options)!.map( { self.substring($0.range)!}) return matchResults(options: options)!.map( { self.substring($0.range)!})
} }
public func allGroups(options: NSMatchingOptions = nil) -> [[String]?] { public func allGroups(options: NSMatchingOptions = nil) -> [[String]?] {
return matchResults(options: options)!.map {self.groupsForMatch($0)} return matchResults(options: options)!.map {self.groupsForMatch($0)}
} }
public func dictionary(options: NSMatchingOptions = nil) -> Dictionary<String,String> { public func dictionary(options: NSMatchingOptions = nil) -> Dictionary<String,String> {
var out = Dictionary<String,String>() var out = Dictionary<String,String>()
for match in matchResults(options: options)! { for match in matchResults(options: options)! {
@ -137,26 +137,26 @@ public class SwiftRegex: NSObject, BooleanType {
} }
return out return out
} }
func substituteMatches(substitution: (NSTextCheckingResult, UnsafeMutablePointer<ObjCBool>) -> String, func substituteMatches(substitution: (NSTextCheckingResult, UnsafeMutablePointer<ObjCBool>) -> String,
options:NSMatchingOptions = nil) -> String { options:NSMatchingOptions = nil) -> String {
let out = NSMutableString() let out = NSMutableString()
var pos = 0 var pos = 0
regex.enumerateMatchesInString(target as String, options: options, range: targetRange ) { regex.enumerateMatchesInString(target as String, options: options, range: targetRange ) {
(match: NSTextCheckingResult!, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) in (match: NSTextCheckingResult!, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) in
let matchRange = match.range let matchRange = match.range
out.appendString( self.substring(NSRange(location:pos, length:matchRange.location-pos))!) out.appendString( self.substring(NSRange(location:pos, length:matchRange.location-pos))!)
out.appendString( substitution(match, stop) ) out.appendString( substitution(match, stop) )
pos = matchRange.location + matchRange.length pos = matchRange.location + matchRange.length
} }
out.appendString(substring( NSRange(location:pos, length:targetRange.length-pos))!) out.appendString(substring( NSRange(location:pos, length:targetRange.length-pos))!)
return out as String return out as String
} }
public var boolValue: Bool { public var boolValue: Bool {
return doesMatch() return doesMatch()
} }
@ -184,11 +184,11 @@ public func ~= (left: SwiftRegex, right: String) -> String {
public func ~= (left: SwiftRegex, right: [String]) -> String { public func ~= (left: SwiftRegex, right: [String]) -> String {
var matchNumber = 0 var matchNumber = 0
return left.substituteMatches({match, stop -> String in return left.substituteMatches({match, stop -> String in
if ++matchNumber == right.count { if ++matchNumber == right.count {
stop.memory = true stop.memory = true
} }
return left.regex.replacementStringForResult( match, return left.regex.replacementStringForResult( match,
inString: left.target as String, offset: 0, template: right[matchNumber-1] ) inString: left.target as String, offset: 0, template: right[matchNumber-1] )
}, options: nil) }, options: nil)

View File

@ -7,7 +7,6 @@
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
import Foundation import Foundation
import CoreFoundation
public protocol WebSocketDelegate: class { public protocol WebSocketDelegate: class {
func websocketDidConnect(socket: WebSocket) func websocketDidConnect(socket: WebSocket)
@ -236,8 +235,8 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
if self.selfSignedSSL { if self.selfSignedSSL {
let settings: Dictionary<NSObject, NSObject> = [kCFStreamSSLValidatesCertificateChain: NSNumber(bool:false), kCFStreamSSLPeerName: kCFNull] let settings: Dictionary<NSObject, NSObject> = [kCFStreamSSLValidatesCertificateChain: NSNumber(bool:false), kCFStreamSSLPeerName: kCFNull]
inputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings) inputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String)
outputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings) outputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String)
} }
isRunLoop = true isRunLoop = true
inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
@ -247,18 +246,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
let bytes = UnsafePointer<UInt8>(data.bytes) let bytes = UnsafePointer<UInt8>(data.bytes)
outputStream!.write(bytes, maxLength: data.length) outputStream!.write(bytes, maxLength: data.length)
while(isRunLoop) { while(isRunLoop) {
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture() as NSDate) NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture() as! NSDate)
} }
} }
//delegate for the stream methods. Processes incoming bytes //delegate for the stream methods. Processes incoming bytes
func stream(aStream: NSStream!, handleEvent eventCode: NSStreamEvent) { public func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
if eventCode == .HasBytesAvailable { if eventCode == .HasBytesAvailable {
if(aStream == inputStream) { if(aStream == inputStream) {
processInputStream() processInputStream()
} }
} else if eventCode == .ErrorOccurred { } else if eventCode == .ErrorOccurred {
disconnectStream(aStream!.streamError) disconnectStream(aStream.streamError)
} else if eventCode == .EndEncountered { } else if eventCode == .EndEncountered {
disconnectStream(nil) disconnectStream(nil)
} }
@ -333,7 +332,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
///Finds the HTTP Packet in the TCP stream, by looking for the CRLF. ///Finds the HTTP Packet in the TCP stream, by looking for the CRLF.
private func processHTTP(buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Bool { private func processHTTP(buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Bool {
let CRLFBytes = [UInt8("\r"), UInt8("\n"), UInt8("\r"), UInt8("\n")] let CRLFBytes = [UInt8(ascii: "\r"), UInt8(ascii: "\n"), UInt8(ascii: "\r"), UInt8(ascii: "\n")]
var k = 0 var k = 0
var totalSize = 0 var totalSize = 0
for var i = 0; i < bufferLen; i++ { for var i = 0; i < bufferLen; i++ {
@ -376,7 +375,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response.takeUnretainedValue()) let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response.takeUnretainedValue())
let headers: NSDictionary = cfHeaders.takeUnretainedValue() let headers: NSDictionary = cfHeaders.takeUnretainedValue()
let acceptKey = headers[headerWSAcceptName] as NSString let acceptKey = headers[headerWSAcceptName] as! NSString
if acceptKey.length > 0 { if acceptKey.length > 0 {
return true return true
} }
@ -500,7 +499,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
data = NSData(bytes: UnsafePointer<UInt8>((buffer+offset)), length: Int(len)) data = NSData(bytes: UnsafePointer<UInt8>((buffer+offset)), length: Int(len))
} }
if receivedOpcode == OpCode.Pong.rawValue { if receivedOpcode == OpCode.Pong.rawValue {
let step = Int(offset+len) let step = offset + Int(len)
let extra = bufferLen-step let extra = bufferLen-step
if extra > 0 { if extra > 0 {
processRawMessage((buffer+step), bufferLen: extra) processRawMessage((buffer+step), bufferLen: extra)
@ -565,7 +564,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
processResponse(response!) processResponse(response!)
} }
let step = Int(offset+len) let step = offset + Int(len)
let extra = bufferLen-step let extra = bufferLen-step
if(extra > 0) { if(extra > 0) {
processExtra((buffer+step), bufferLen: extra) processExtra((buffer+step), bufferLen: extra)
@ -597,9 +596,9 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
dispatch_async(queue,{ dispatch_async(queue,{
if let textBlock = self.receivedTextBlock{ if let textBlock = self.receivedTextBlock{
textBlock(str!) textBlock(str! as String)
} }
self.delegate?.websocketDidReceiveMessage(self, text: str!) self.delegate?.websocketDidReceiveMessage(self, text: str! as String)
}) })
} else if response.code == .BinaryFrame { } else if response.code == .BinaryFrame {
let data = response.buffer! //local copy so it is perverse for writing let data = response.buffer! //local copy so it is perverse for writing
@ -673,7 +672,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
buffer[1] |= self.MaskMask buffer[1] |= self.MaskMask
var maskKey = UnsafeMutablePointer<UInt8>(buffer + offset) var maskKey = UnsafeMutablePointer<UInt8>(buffer + offset)
SecRandomCopyBytes(kSecRandomDefault, UInt(sizeof(UInt32)), maskKey) SecRandomCopyBytes(kSecRandomDefault, Int(sizeof(UInt32)), maskKey)
offset += sizeof(UInt32) offset += sizeof(UInt32)
for (var i = 0; i < dataLength; i++) { for (var i = 0; i < dataLength; i++) {
@ -711,4 +710,4 @@ public class WebSocket : NSObject, NSStreamDelegate {
} }
} }
} }