commit
4ae6489230
@ -68,7 +68,12 @@ class SocketParserTest: XCTestCase {
|
|||||||
|
|
||||||
func testInvalidInput() {
|
func testInvalidInput() {
|
||||||
let message = "8"
|
let message = "8"
|
||||||
XCTAssertNil(SocketParser.parseString(message))
|
switch SocketParser.parseString(message) {
|
||||||
|
case .Left(_):
|
||||||
|
return
|
||||||
|
case .Right(_):
|
||||||
|
XCTFail("Created packet when shouldn't have")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGenericParser() {
|
func testGenericParser() {
|
||||||
@ -83,7 +88,7 @@ class SocketParserTest: XCTestCase {
|
|||||||
let validValues = SocketParserTest.packetTypes[message]!
|
let validValues = SocketParserTest.packetTypes[message]!
|
||||||
let packet = SocketParser.parseString(message)
|
let packet = SocketParser.parseString(message)
|
||||||
let type = message.substringWithRange(Range<String.Index>(start: message.startIndex, end: message.startIndex.advancedBy(1)))
|
let type = message.substringWithRange(Range<String.Index>(start: message.startIndex, end: message.startIndex.advancedBy(1)))
|
||||||
if let packet = packet {
|
if case let .Right(packet) = packet {
|
||||||
XCTAssertEqual(packet.type, SocketPacket.PacketType(str:type)!)
|
XCTAssertEqual(packet.type, SocketPacket.PacketType(str:type)!)
|
||||||
XCTAssertEqual(packet.nsp, validValues.0)
|
XCTAssertEqual(packet.nsp, validValues.0)
|
||||||
XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1))
|
XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1))
|
||||||
|
|||||||
@ -65,8 +65,9 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
var cookies: [NSHTTPCookie]?
|
var cookies: [NSHTTPCookie]?
|
||||||
var sid = ""
|
var sid = ""
|
||||||
var socketPath = ""
|
var socketPath = ""
|
||||||
var urlPolling: String?
|
var urlPolling = ""
|
||||||
var urlWebSocket: String?
|
var urlWebSocket = ""
|
||||||
|
|
||||||
var ws: WebSocket?
|
var ws: WebSocket?
|
||||||
|
|
||||||
@objc public enum PacketType: Int {
|
@objc public enum PacketType: Int {
|
||||||
@ -129,7 +130,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
stopPolling()
|
stopPolling()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createBinaryDataForSend(data: NSData) -> (NSData?, String?) {
|
private func createBinaryDataForSend(data: NSData) -> Either<NSData, String> {
|
||||||
if websocket {
|
if websocket {
|
||||||
var byteArray = [UInt8](count: 1, repeatedValue: 0x0)
|
var byteArray = [UInt8](count: 1, repeatedValue: 0x0)
|
||||||
byteArray[0] = 4
|
byteArray[0] = 4
|
||||||
@ -137,23 +138,22 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
|
|
||||||
mutData.appendData(data)
|
mutData.appendData(data)
|
||||||
|
|
||||||
return (mutData, nil)
|
return .Left(mutData)
|
||||||
} else {
|
} else {
|
||||||
var str = "b4"
|
var str = "b4"
|
||||||
str += data.base64EncodedStringWithOptions(
|
str += data.base64EncodedStringWithOptions(
|
||||||
NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
|
NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
|
||||||
|
|
||||||
return (nil, str)
|
return .Right(str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createURLs(params: [String: AnyObject]?) -> (String?, String?) {
|
private func createURLs(params: [String: AnyObject]?) -> (String, String) {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return (nil, nil)
|
return ("", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = socketPath == "" ? "/socket.io" : socketPath
|
let path = socketPath == "" ? "/socket.io" : socketPath
|
||||||
|
|
||||||
let url = "\(client!.socketURL)\(path)/?transport="
|
let url = "\(client!.socketURL)\(path)/?transport="
|
||||||
var urlPolling: String
|
var urlPolling: String
|
||||||
var urlWebSocket: String
|
var urlWebSocket: String
|
||||||
@ -189,7 +189,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func createWebsocket(andConnect connect: Bool) {
|
private func createWebsocket(andConnect connect: Bool) {
|
||||||
let wsUrl = urlWebSocket! + (sid == "" ? "" : "&sid=\(sid)")
|
let wsUrl = urlWebSocket + (sid == "" ? "" : "&sid=\(sid)")
|
||||||
|
|
||||||
ws = WebSocket(url: NSURL(string: wsUrl)!,
|
ws = WebSocket(url: NSURL(string: wsUrl)!,
|
||||||
cookies: cookies)
|
cookies: cookies)
|
||||||
@ -228,7 +228,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
waitingForPoll = true
|
waitingForPoll = true
|
||||||
let req = NSMutableURLRequest(URL: NSURL(string: urlPolling! + "&sid=\(sid)&b64=1")!)
|
let req = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&sid=\(sid)&b64=1")!)
|
||||||
|
|
||||||
if cookies != nil {
|
if cookies != nil {
|
||||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
||||||
@ -318,7 +318,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
|
|
||||||
postWait.removeAll(keepCapacity: false)
|
postWait.removeAll(keepCapacity: false)
|
||||||
|
|
||||||
let req = NSMutableURLRequest(URL: NSURL(string: urlPolling! + "&sid=\(sid)")!)
|
let req = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&sid=\(sid)")!)
|
||||||
|
|
||||||
if let cookies = cookies {
|
if let cookies = cookies {
|
||||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies)
|
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies)
|
||||||
@ -468,7 +468,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling! + "&b64=1")!)
|
let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&b64=1")!)
|
||||||
|
|
||||||
if cookies != nil {
|
if cookies != nil {
|
||||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
||||||
@ -581,9 +581,9 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
postWait.append(strMsg)
|
postWait.append(strMsg)
|
||||||
|
|
||||||
for data in datas ?? [] {
|
for data in datas ?? [] {
|
||||||
let (_, b64Data) = createBinaryDataForSend(data)
|
if case let .Right(bin) = createBinaryDataForSend(data) {
|
||||||
|
postWait.append(bin)
|
||||||
postWait.append(b64Data!)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !waitingForPost {
|
if !waitingForPost {
|
||||||
@ -600,9 +600,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
|||||||
ws?.writeString("\(type.rawValue)\(str)")
|
ws?.writeString("\(type.rawValue)\(str)")
|
||||||
|
|
||||||
for data in datas ?? [] {
|
for data in datas ?? [] {
|
||||||
let (data, _) = createBinaryDataForSend(data)
|
if case let Either.Left(bin) = createBinaryDataForSend(data) {
|
||||||
if data != nil {
|
ws?.writeData(bin)
|
||||||
ws?.writeData(data!)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,26 +27,7 @@ class SocketParser {
|
|||||||
private static func isCorrectNamespace(nsp: String, _ socket: SocketIOClient) -> Bool {
|
private static func isCorrectNamespace(nsp: String, _ socket: SocketIOClient) -> Bool {
|
||||||
return nsp == socket.nsp
|
return nsp == socket.nsp
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func handleEvent(p: SocketPacket, socket: SocketIOClient) {
|
|
||||||
guard isCorrectNamespace(p.nsp, socket) else { return }
|
|
||||||
|
|
||||||
socket.handleEvent(p.event, data: p.args ?? [],
|
|
||||||
isInternalMessage: false, wantsAck: p.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func handleAck(p: SocketPacket, socket: SocketIOClient) {
|
|
||||||
guard isCorrectNamespace(p.nsp, socket) else { return }
|
|
||||||
|
|
||||||
socket.handleAck(p.id, data: p.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func handleBinary(p: SocketPacket, socket: SocketIOClient) {
|
|
||||||
guard isCorrectNamespace(p.nsp, socket) else { return }
|
|
||||||
|
|
||||||
socket.waitingData.append(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func handleConnect(p: SocketPacket, socket: SocketIOClient) {
|
private static func handleConnect(p: SocketPacket, socket: SocketIOClient) {
|
||||||
if p.nsp == "/" && socket.nsp != "/" {
|
if p.nsp == "/" && socket.nsp != "/" {
|
||||||
socket.joinNamespace()
|
socket.joinNamespace()
|
||||||
@ -57,14 +38,37 @@ class SocketParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func parseString(message: String) -> SocketPacket? {
|
private static func handlePacket(pack: SocketPacket, withSocket socket: SocketIOClient) {
|
||||||
|
guard isCorrectNamespace(pack.nsp, socket) else { return }
|
||||||
|
|
||||||
|
switch pack.type {
|
||||||
|
case .Event:
|
||||||
|
socket.handleEvent(pack.event, data: pack.args ?? [],
|
||||||
|
isInternalMessage: false, wantsAck: pack.id)
|
||||||
|
case .Ack:
|
||||||
|
socket.handleAck(pack.id, data: pack.data)
|
||||||
|
case .BinaryEvent:
|
||||||
|
socket.waitingData.append(pack)
|
||||||
|
case .BinaryAck:
|
||||||
|
socket.waitingData.append(pack)
|
||||||
|
case .Connect:
|
||||||
|
handleConnect(pack, socket: socket)
|
||||||
|
case .Disconnect:
|
||||||
|
socket.didDisconnect("Got Disconnect")
|
||||||
|
case .Error:
|
||||||
|
socket.didError("Error: \(pack.data)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func parseString(message: String) -> Either<String, SocketPacket> {
|
||||||
var parser = SocketStringReader(message: message)
|
var parser = SocketStringReader(message: message)
|
||||||
|
|
||||||
guard let type = SocketPacket.PacketType(str: parser.read(1))
|
guard let type = SocketPacket.PacketType(str: parser.read(1)) else {
|
||||||
else {return nil}
|
return .Left("Invalid packet type")
|
||||||
|
}
|
||||||
|
|
||||||
if !parser.hasNext {
|
if !parser.hasNext {
|
||||||
return SocketPacket(type: type, nsp: "/")
|
return .Right(SocketPacket(type: type, nsp: "/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var namespace: String?
|
var namespace: String?
|
||||||
@ -74,7 +78,7 @@ class SocketParser {
|
|||||||
if let holders = Int(parser.readUntilStringOccurence("-")) {
|
if let holders = Int(parser.readUntilStringOccurence("-")) {
|
||||||
placeholders = holders
|
placeholders = holders
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return .Left("Invalid packet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,8 +87,8 @@ class SocketParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parser.hasNext {
|
if !parser.hasNext {
|
||||||
return SocketPacket(type: type, id: -1,
|
return .Right(SocketPacket(type: type, id: -1,
|
||||||
nsp: namespace ?? "/", placeholders: placeholders)
|
nsp: namespace ?? "/", placeholders: placeholders))
|
||||||
}
|
}
|
||||||
|
|
||||||
var idString = ""
|
var idString = ""
|
||||||
@ -100,21 +104,28 @@ class SocketParser {
|
|||||||
|
|
||||||
let d = message[parser.currentIndex.advancedBy(1)..<message.endIndex]
|
let d = message[parser.currentIndex.advancedBy(1)..<message.endIndex]
|
||||||
let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
|
let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
|
||||||
let data = parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders]
|
|
||||||
|
|
||||||
return SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
switch parseData(noPlaceholders) {
|
||||||
nsp: namespace ?? "/", placeholders: placeholders)
|
case .Left(let err):
|
||||||
|
return .Left(err)
|
||||||
|
case .Right(let data):
|
||||||
|
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
||||||
|
nsp: namespace ?? "/", placeholders: placeholders))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses data for events
|
// Parses data for events
|
||||||
static func parseData(data: String) -> AnyObject? {
|
private static func parseData(data: String) -> Either<String, [AnyObject]> {
|
||||||
let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
|
let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
|
||||||
do {
|
do {
|
||||||
return try NSJSONSerialization.JSONObjectWithData(stringData!,
|
if let arr = try NSJSONSerialization.JSONObjectWithData(stringData!,
|
||||||
options: NSJSONReadingOptions.MutableContainers)
|
options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] {
|
||||||
|
return .Right(arr)
|
||||||
|
} else {
|
||||||
|
return .Left("Expected data array")
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Logger.error("Parsing JSON: %@", type: "SocketParser", args: data)
|
return .Left("Error parsing data for packet")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,30 +135,13 @@ class SocketParser {
|
|||||||
|
|
||||||
Logger.log("Parsing %@", type: "SocketParser", args: message)
|
Logger.log("Parsing %@", type: "SocketParser", args: message)
|
||||||
|
|
||||||
guard let pack = parseString(message) else {
|
switch parseString(message) {
|
||||||
Logger.error("Parsing message: %@", type: "SocketParser", args: message)
|
case .Left(let err):
|
||||||
return
|
Logger.error("\(err): %@", type: "SocketParser", args: message)
|
||||||
|
case .Right(let pack):
|
||||||
|
Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description)
|
||||||
|
handlePacket(pack, withSocket: socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description)
|
|
||||||
|
|
||||||
switch pack.type {
|
|
||||||
case .Event:
|
|
||||||
handleEvent(pack, socket: socket)
|
|
||||||
case .Ack:
|
|
||||||
handleAck(pack, socket: socket)
|
|
||||||
case .BinaryEvent:
|
|
||||||
handleBinary(pack, socket: socket)
|
|
||||||
case .BinaryAck:
|
|
||||||
handleBinary(pack, socket: socket)
|
|
||||||
case .Connect:
|
|
||||||
handleConnect(pack, socket: socket)
|
|
||||||
case .Disconnect:
|
|
||||||
socket.didDisconnect("Got Disconnect")
|
|
||||||
case .Error:
|
|
||||||
socket.didError("Error: \(pack.data)")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static func parseBinaryData(data: NSData, socket: SocketIOClient) {
|
static func parseBinaryData(data: NSData, socket: SocketIOClient) {
|
||||||
@ -156,9 +150,8 @@ class SocketParser {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let shouldExecute = socket.waitingData[socket.waitingData.count - 1].addData(data)
|
// Should execute event?
|
||||||
|
guard socket.waitingData[socket.waitingData.count - 1].addData(data) else {
|
||||||
guard shouldExecute else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,3 +28,7 @@ public typealias AckCallback = ([AnyObject]) -> Void
|
|||||||
public typealias NormalCallback = ([AnyObject], SocketAckEmitter?) -> Void
|
public typealias NormalCallback = ([AnyObject], SocketAckEmitter?) -> Void
|
||||||
public typealias OnAckCallback = (timeoutAfter: UInt64, callback: AckCallback) -> Void
|
public typealias OnAckCallback = (timeoutAfter: UInt64, callback: AckCallback) -> Void
|
||||||
|
|
||||||
|
enum Either<E, V> {
|
||||||
|
case Left(E)
|
||||||
|
case Right(V)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user