commit
4ae6489230
@ -68,7 +68,12 @@ class SocketParserTest: XCTestCase {
|
||||
|
||||
func testInvalidInput() {
|
||||
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() {
|
||||
@ -83,7 +88,7 @@ class SocketParserTest: XCTestCase {
|
||||
let validValues = SocketParserTest.packetTypes[message]!
|
||||
let packet = SocketParser.parseString(message)
|
||||
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.nsp, validValues.0)
|
||||
XCTAssertTrue((packet.data as NSArray).isEqualToArray(validValues.1))
|
||||
|
||||
@ -65,8 +65,9 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
var cookies: [NSHTTPCookie]?
|
||||
var sid = ""
|
||||
var socketPath = ""
|
||||
var urlPolling: String?
|
||||
var urlWebSocket: String?
|
||||
var urlPolling = ""
|
||||
var urlWebSocket = ""
|
||||
|
||||
var ws: WebSocket?
|
||||
|
||||
@objc public enum PacketType: Int {
|
||||
@ -129,7 +130,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
stopPolling()
|
||||
}
|
||||
|
||||
private func createBinaryDataForSend(data: NSData) -> (NSData?, String?) {
|
||||
private func createBinaryDataForSend(data: NSData) -> Either<NSData, String> {
|
||||
if websocket {
|
||||
var byteArray = [UInt8](count: 1, repeatedValue: 0x0)
|
||||
byteArray[0] = 4
|
||||
@ -137,23 +138,22 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
|
||||
mutData.appendData(data)
|
||||
|
||||
return (mutData, nil)
|
||||
return .Left(mutData)
|
||||
} else {
|
||||
var str = "b4"
|
||||
str += data.base64EncodedStringWithOptions(
|
||||
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 {
|
||||
return (nil, nil)
|
||||
return ("", "")
|
||||
}
|
||||
|
||||
let path = socketPath == "" ? "/socket.io" : socketPath
|
||||
|
||||
let url = "\(client!.socketURL)\(path)/?transport="
|
||||
var urlPolling: String
|
||||
var urlWebSocket: String
|
||||
@ -189,7 +189,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
}
|
||||
|
||||
private func createWebsocket(andConnect connect: Bool) {
|
||||
let wsUrl = urlWebSocket! + (sid == "" ? "" : "&sid=\(sid)")
|
||||
let wsUrl = urlWebSocket + (sid == "" ? "" : "&sid=\(sid)")
|
||||
|
||||
ws = WebSocket(url: NSURL(string: wsUrl)!,
|
||||
cookies: cookies)
|
||||
@ -228,7 +228,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
}
|
||||
|
||||
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 {
|
||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
||||
@ -318,7 +318,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
|
||||
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 {
|
||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies)
|
||||
@ -468,7 +468,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling! + "&b64=1")!)
|
||||
let reqPolling = NSMutableURLRequest(URL: NSURL(string: urlPolling + "&b64=1")!)
|
||||
|
||||
if cookies != nil {
|
||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
||||
@ -581,9 +581,9 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
postWait.append(strMsg)
|
||||
|
||||
for data in datas ?? [] {
|
||||
let (_, b64Data) = createBinaryDataForSend(data)
|
||||
|
||||
postWait.append(b64Data!)
|
||||
if case let .Right(bin) = createBinaryDataForSend(data) {
|
||||
postWait.append(bin)
|
||||
}
|
||||
}
|
||||
|
||||
if !waitingForPost {
|
||||
@ -600,9 +600,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate {
|
||||
ws?.writeString("\(type.rawValue)\(str)")
|
||||
|
||||
for data in datas ?? [] {
|
||||
let (data, _) = createBinaryDataForSend(data)
|
||||
if data != nil {
|
||||
ws?.writeData(data!)
|
||||
if case let Either.Left(bin) = createBinaryDataForSend(data) {
|
||||
ws?.writeData(bin)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,26 +27,7 @@ class SocketParser {
|
||||
private static func isCorrectNamespace(nsp: String, _ socket: SocketIOClient) -> Bool {
|
||||
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) {
|
||||
if p.nsp == "/" && socket.nsp != "/" {
|
||||
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)
|
||||
|
||||
guard let type = SocketPacket.PacketType(str: parser.read(1))
|
||||
else {return nil}
|
||||
guard let type = SocketPacket.PacketType(str: parser.read(1)) else {
|
||||
return .Left("Invalid packet type")
|
||||
}
|
||||
|
||||
if !parser.hasNext {
|
||||
return SocketPacket(type: type, nsp: "/")
|
||||
return .Right(SocketPacket(type: type, nsp: "/"))
|
||||
}
|
||||
|
||||
var namespace: String?
|
||||
@ -74,7 +78,7 @@ class SocketParser {
|
||||
if let holders = Int(parser.readUntilStringOccurence("-")) {
|
||||
placeholders = holders
|
||||
} else {
|
||||
return nil
|
||||
return .Left("Invalid packet")
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,8 +87,8 @@ class SocketParser {
|
||||
}
|
||||
|
||||
if !parser.hasNext {
|
||||
return SocketPacket(type: type, id: -1,
|
||||
nsp: namespace ?? "/", placeholders: placeholders)
|
||||
return .Right(SocketPacket(type: type, id: -1,
|
||||
nsp: namespace ?? "/", placeholders: placeholders))
|
||||
}
|
||||
|
||||
var idString = ""
|
||||
@ -100,21 +104,28 @@ class SocketParser {
|
||||
|
||||
let d = message[parser.currentIndex.advancedBy(1)..<message.endIndex]
|
||||
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,
|
||||
nsp: namespace ?? "/", placeholders: placeholders)
|
||||
switch parseData(noPlaceholders) {
|
||||
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
|
||||
static func parseData(data: String) -> AnyObject? {
|
||||
private static func parseData(data: String) -> Either<String, [AnyObject]> {
|
||||
let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
|
||||
do {
|
||||
return try NSJSONSerialization.JSONObjectWithData(stringData!,
|
||||
options: NSJSONReadingOptions.MutableContainers)
|
||||
if let arr = try NSJSONSerialization.JSONObjectWithData(stringData!,
|
||||
options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] {
|
||||
return .Right(arr)
|
||||
} else {
|
||||
return .Left("Expected data array")
|
||||
}
|
||||
} catch {
|
||||
Logger.error("Parsing JSON: %@", type: "SocketParser", args: data)
|
||||
return nil
|
||||
return .Left("Error parsing data for packet")
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,30 +135,13 @@ class SocketParser {
|
||||
|
||||
Logger.log("Parsing %@", type: "SocketParser", args: message)
|
||||
|
||||
guard let pack = parseString(message) else {
|
||||
Logger.error("Parsing message: %@", type: "SocketParser", args: message)
|
||||
return
|
||||
switch parseString(message) {
|
||||
case .Left(let err):
|
||||
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) {
|
||||
@ -156,9 +150,8 @@ class SocketParser {
|
||||
return
|
||||
}
|
||||
|
||||
let shouldExecute = socket.waitingData[socket.waitingData.count - 1].addData(data)
|
||||
|
||||
guard shouldExecute else {
|
||||
// Should execute event?
|
||||
guard socket.waitingData[socket.waitingData.count - 1].addData(data) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -28,3 +28,7 @@ public typealias AckCallback = ([AnyObject]) -> Void
|
||||
public typealias NormalCallback = ([AnyObject], SocketAckEmitter?) -> 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