merge master
This commit is contained in:
commit
01e5e22e0b
@ -35,6 +35,8 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:@"localhost:8
|
|||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
[socket connect];
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
##Features
|
##Features
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "Socket.IO-Client-Swift"
|
s.name = "Socket.IO-Client-Swift"
|
||||||
s.version = "1.5.1"
|
s.version = "2.0.0"
|
||||||
s.summary = "Socket.IO-client for Swift"
|
s.summary = "Socket.IO-client for Swift"
|
||||||
s.description = <<-DESC
|
s.description = <<-DESC
|
||||||
Socket.IO-client for Swift.
|
Socket.IO-client for Swift.
|
||||||
@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = { "Erik" => "nuclear.ace@gmail.com" }
|
s.author = { "Erik" => "nuclear.ace@gmail.com" }
|
||||||
s.ios.deployment_target = '8.0'
|
s.ios.deployment_target = '8.0'
|
||||||
s.osx.deployment_target = '10.10'
|
s.osx.deployment_target = '10.10'
|
||||||
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v1.5.1' }
|
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v2.0.0' }
|
||||||
s.source_files = "SwiftIO/**/*.swift"
|
s.source_files = "SwiftIO/**/*.swift"
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files
|
# s.dependency 'Starscream', '~> 0.9' # currently this repo includes Starscream swift files
|
||||||
|
|||||||
@ -24,9 +24,6 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public typealias AckCallback = @objc_block (NSArray?) -> Void
|
|
||||||
public typealias OnAckCallback = (timeout:UInt64, callback:AckCallback) -> Void
|
|
||||||
|
|
||||||
struct SocketAckMap {
|
struct SocketAckMap {
|
||||||
private var acks = [Int: AckCallback]()
|
private var acks = [Int: AckCallback]()
|
||||||
private var waiting = [Int: Bool]()
|
private var waiting = [Int: Bool]()
|
||||||
|
|||||||
@ -26,24 +26,14 @@ import Foundation
|
|||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
private var length:Int {
|
private var length:Int {
|
||||||
return countElements(self)
|
return count(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private typealias Probe = (msg:String, type:PacketType, data:ContiguousArray<NSData>?)
|
|
||||||
private typealias ProbeWaitQueue = [Probe]
|
|
||||||
|
|
||||||
public enum PacketType:String {
|
|
||||||
case OPEN = "0"
|
|
||||||
case CLOSE = "1"
|
|
||||||
case PING = "2"
|
|
||||||
case PONG = "3"
|
|
||||||
case MESSAGE = "4"
|
|
||||||
case UPGRADE = "5"
|
|
||||||
case NOOP = "6"
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SocketEngine: NSObject, WebSocketDelegate {
|
public class SocketEngine: NSObject, WebSocketDelegate {
|
||||||
|
private typealias Probe = (msg:String, type:PacketType, data:ContiguousArray<NSData>?)
|
||||||
|
private typealias ProbeWaitQueue = [Probe]
|
||||||
|
|
||||||
private let workQueue = NSOperationQueue()
|
private let workQueue = NSOperationQueue()
|
||||||
private let emitQueue = dispatch_queue_create(
|
private let emitQueue = dispatch_queue_create(
|
||||||
"engineEmitQueue".cStringUsingEncoding(NSUTF8StringEncoding), DISPATCH_QUEUE_SERIAL)
|
"engineEmitQueue".cStringUsingEncoding(NSUTF8StringEncoding), DISPATCH_QUEUE_SERIAL)
|
||||||
@ -84,6 +74,24 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
}
|
}
|
||||||
var ws:WebSocket?
|
var ws:WebSocket?
|
||||||
|
|
||||||
|
public enum PacketType:Int {
|
||||||
|
case OPEN = 0
|
||||||
|
case CLOSE = 1
|
||||||
|
case PING = 2
|
||||||
|
case PONG = 3
|
||||||
|
case MESSAGE = 4
|
||||||
|
case UPGRADE = 5
|
||||||
|
case NOOP = 6
|
||||||
|
|
||||||
|
init(str:String) {
|
||||||
|
if let value = str.toInt() {
|
||||||
|
self = PacketType(rawValue: value)!
|
||||||
|
} else {
|
||||||
|
self = PacketType.NOOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -147,7 +155,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
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)"
|
||||||
@ -227,6 +235,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self?.waitingForPoll = false
|
self?.waitingForPoll = false
|
||||||
|
|
||||||
if self!.fastUpgrade {
|
if self!.fastUpgrade {
|
||||||
self?.doFastUpgrade()
|
self?.doFastUpgrade()
|
||||||
return
|
return
|
||||||
@ -266,7 +275,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
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)"
|
||||||
}
|
}
|
||||||
@ -320,6 +329,7 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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()
|
||||||
@ -441,10 +451,76 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
fixDoubleUTF8(&message)
|
fixDoubleUTF8(&message)
|
||||||
}
|
}
|
||||||
|
|
||||||
let type = message["^(\\d)"].groups()?[1]
|
let type = PacketType(str: (message["^(\\d)"].groups()?[1])!)
|
||||||
|
|
||||||
if type != PacketType.MESSAGE.rawValue {
|
if type == PacketType.MESSAGE {
|
||||||
// TODO Handle other packets
|
// Remove message type
|
||||||
|
message.removeAtIndex(message.startIndex)
|
||||||
|
|
||||||
|
if self.client == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_async(self.client!.handleQueue) {[weak self] in
|
||||||
|
self?.client?.parseSocketMessage(message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if type == PacketType.NOOP {
|
||||||
|
self.doPoll()
|
||||||
|
return
|
||||||
|
} else if type == PacketType.PONG {
|
||||||
|
// We should upgrade
|
||||||
|
if message == "3probe" {
|
||||||
|
self.upgradeTransport()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
} else if type == PacketType.OPEN {
|
||||||
|
var err:NSError?
|
||||||
|
|
||||||
|
message.removeAtIndex(message.startIndex)
|
||||||
|
let mesData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
|
||||||
|
|
||||||
|
if let json = NSJSONSerialization.JSONObjectWithData(mesData,
|
||||||
|
options: NSJSONReadingOptions.AllowFragments, error: &err) as? NSDictionary {
|
||||||
|
if let sid = json["sid"] as? String {
|
||||||
|
// println(json)
|
||||||
|
self.sid = sid
|
||||||
|
self._connected = true
|
||||||
|
if !self.forcePolling && !self.forceWebsockets {
|
||||||
|
self.createWebsocket(andConnect: true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NSLog("Error handshaking")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let pingInterval = json["pingInterval"] as? Int {
|
||||||
|
self.pingInterval = pingInterval / 1000
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fatalError("Error parsing engine connect")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.startPingTimer()
|
||||||
|
|
||||||
|
if !self.forceWebsockets {
|
||||||
|
self.doPoll()
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
} else if type == PacketType.CLOSE {
|
||||||
|
if self.client == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.polling {
|
||||||
|
self.client!.engineDidForceClose("Disconnect")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
} else {
|
||||||
if message.hasPrefix("b4") {
|
if message.hasPrefix("b4") {
|
||||||
// binary in base64 string
|
// binary in base64 string
|
||||||
|
|
||||||
@ -452,91 +528,16 @@ public class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
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)
|
||||||
|
where self.client != nil {
|
||||||
// println("sending \(data)")
|
// println("sending \(data)")
|
||||||
|
|
||||||
if self.client == nil {
|
|
||||||
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
|
|
||||||
} else if type == PacketType.NOOP.rawValue {
|
|
||||||
self.doPoll()
|
|
||||||
return
|
|
||||||
} else if type == PacketType.PONG.rawValue {
|
|
||||||
// We should upgrade
|
|
||||||
if message == "3probe" {
|
|
||||||
self.upgradeTransport()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
} else if type == PacketType.OPEN.rawValue {
|
|
||||||
var err:NSError?
|
|
||||||
|
|
||||||
message.removeAtIndex(message.startIndex)
|
|
||||||
let mesData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
|
|
||||||
|
|
||||||
if let json = NSJSONSerialization.JSONObjectWithData(mesData,
|
|
||||||
options: NSJSONReadingOptions.AllowFragments, error: &err) as? NSDictionary {
|
|
||||||
if let sid = json["sid"] as? String {
|
|
||||||
// println(json)
|
|
||||||
self.sid = sid
|
|
||||||
self._connected = true
|
|
||||||
if !self.forcePolling && !self.forceWebsockets {
|
|
||||||
self.createWebsocket(andConnect: true)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.client?.engineDidError("Error parsing engine connect")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let pingInterval = json["pingInterval"] as? Int {
|
|
||||||
self.pingInterval = pingInterval / 1000
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.client?.engineDidError("Error parsing engine connect")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.startPingTimer()
|
|
||||||
|
|
||||||
if !self.forceWebsockets {
|
|
||||||
self.doPoll()
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
} else if type == PacketType.CLOSE.rawValue {
|
|
||||||
if self.client == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.polling {
|
|
||||||
self.client!.engineDidForceClose("Disconnect")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// println("Got something idk what to do with")
|
|
||||||
// println(messageString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove message type
|
|
||||||
message.removeAtIndex(message.startIndex)
|
|
||||||
|
|
||||||
if self.client == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch_async(self.client!.handleQueue) {[weak self] in
|
|
||||||
self?.client?.parseSocketMessage(message)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,9 +24,6 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public typealias NormalCallback = (NSArray?, AckEmitter?) -> Void
|
|
||||||
public typealias AckEmitter = (AnyObject...) -> Void
|
|
||||||
|
|
||||||
private func emitAckCallback(socket:SocketIOClient, num:Int)
|
private func emitAckCallback(socket:SocketIOClient, num:Int)
|
||||||
// Curried
|
// Curried
|
||||||
(items:AnyObject...) -> Void {
|
(items:AnyObject...) -> Void {
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
// Socket.IO-Swift
|
// Socket.IO-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 3/16/15.
|
// Created by Erik Little on 3/16/15.
|
||||||
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
// in the Software without restriction, including without limitation the rights
|
// in the Software without restriction, including without limitation the rights
|
||||||
@ -34,4 +35,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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
@ -292,7 +292,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let packet = SocketPacket(type: nil, data: args, nsp: self.nsp, id: ack)
|
let packet = SocketPacket(type: nil, data: args, nsp: self.nsp, id: ack)
|
||||||
var str:String
|
let str:String
|
||||||
|
|
||||||
SocketParser.parseForEmit(packet)
|
SocketParser.parseForEmit(packet)
|
||||||
str = packet.createMessageForEvent(event)
|
str = packet.createMessageForEvent(event)
|
||||||
@ -312,7 +312,7 @@ public class SocketIOClient: NSObject, SocketEngineClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let packet = SocketPacket(type: nil, data: args, nsp: self!.nsp, id: ack)
|
let packet = SocketPacket(type: nil, data: args, nsp: self!.nsp, id: ack)
|
||||||
var str:String
|
let str:String
|
||||||
|
|
||||||
SocketParser.parseForEmit(packet)
|
SocketParser.parseForEmit(packet)
|
||||||
str = packet.createAck()
|
str = packet.createAck()
|
||||||
@ -349,7 +349,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!]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,24 +24,6 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum SocketPacketType:Int {
|
|
||||||
case CONNECT = 0
|
|
||||||
case DISCONNECT = 1
|
|
||||||
case EVENT = 2
|
|
||||||
case ACK = 3
|
|
||||||
case ERROR = 4
|
|
||||||
case BINARY_EVENT = 5
|
|
||||||
case BINARY_ACK = 6
|
|
||||||
|
|
||||||
init(str:String) {
|
|
||||||
if let int = str.toInt() {
|
|
||||||
self = SocketPacketType(rawValue: int)!
|
|
||||||
} else {
|
|
||||||
self = SocketPacketType(rawValue: 4)!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SocketPacket {
|
class SocketPacket {
|
||||||
var binary = ContiguousArray<NSData>()
|
var binary = ContiguousArray<NSData>()
|
||||||
var currentPlace = 0
|
var currentPlace = 0
|
||||||
@ -51,7 +33,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 +42,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 +55,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 +70,14 @@ class SocketPacket {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMessageForEvent(event:String) -> String {
|
func createMessageForEvent(event:String) -> String {
|
||||||
var message:String
|
let 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 +93,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 +108,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 +125,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 +185,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 +198,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
|
||||||
|
|||||||
@ -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.engineDidForceClose("Got Disconnect")
|
socket.engineDidForceClose("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)
|
||||||
|
|||||||
52
SwiftIO/SocketTypes.swift
Normal file
52
SwiftIO/SocketTypes.swift
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// SocketTypes.swift
|
||||||
|
// SocketIO-Swift
|
||||||
|
//
|
||||||
|
// Created by Erik Little on 4/8/15.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// @objc_block is undocumented, but is used because Swift assumes that all
|
||||||
|
// Objective-C blocks are copied, but Objective-C assumes that Swift will copy it.
|
||||||
|
// And the way things are done here, the bridging fails to copy the block in
|
||||||
|
// SocketAckMap#addAck
|
||||||
|
public typealias AckCallback = @objc_block (NSArray?) -> Void
|
||||||
|
public typealias AckEmitter = (AnyObject...) -> Void
|
||||||
|
public typealias NormalCallback = (NSArray?, AckEmitter?) -> Void
|
||||||
|
public typealias OnAckCallback = (timeout:UInt64, callback:AckCallback) -> Void
|
||||||
|
|
||||||
|
enum SocketPacketType:Int {
|
||||||
|
case CONNECT = 0
|
||||||
|
case DISCONNECT = 1
|
||||||
|
case EVENT = 2
|
||||||
|
case ACK = 3
|
||||||
|
case ERROR = 4
|
||||||
|
case BINARY_EVENT = 5
|
||||||
|
case BINARY_ACK = 6
|
||||||
|
|
||||||
|
init(str:String) {
|
||||||
|
if let int = str.toInt() {
|
||||||
|
self = SocketPacketType(rawValue: int)!
|
||||||
|
} else {
|
||||||
|
self = SocketPacketType(rawValue: 4)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
|||||||
@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user