Merge branch 'development'
* development: Update readme to reflect that 10.0+ only support socket.io 2.0+ Remove more doubleEncode stuff Remove doubleEncodeUTF8 from NSDictionary translation Fix unicode for socket.io 2.0 Use guard statements in polling More Objective-c tests Use Data instead of NSData code style Make addHeaders inout
This commit is contained in:
commit
033a509541
@ -51,7 +51,7 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Supports socket.io 1.0+
|
- Supports socket.io 2.0+ (For socket.io 1.0 use v9.x)
|
||||||
- Supports binary
|
- Supports binary
|
||||||
- Supports Polling and WebSockets
|
- Supports Polling and WebSockets
|
||||||
- Supports TLS/SSL
|
- Supports TLS/SSL
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class SocketEngineTest: XCTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.parseEngineMessage("{\"code\": 0, \"message\": \"Unknown transport\"}", fromPolling: false)
|
engine.parseEngineMessage("{\"code\": 0, \"message\": \"Unknown transport\"}")
|
||||||
waitForExpectations(timeout: 3, handler: nil)
|
waitForExpectations(timeout: 3, handler: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class SocketEngineTest: XCTestCase {
|
|||||||
finalExpectation.fulfill()
|
finalExpectation.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.parseEngineMessage("afafafda", fromPolling: false)
|
engine.parseEngineMessage("afafafda")
|
||||||
waitForExpectations(timeout: 3, handler: nil)
|
waitForExpectations(timeout: 3, handler: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,11 +79,13 @@ class SocketEngineTest: XCTestCase {
|
|||||||
let expect = expectation(description: "Engine Decodes utf8")
|
let expect = expectation(description: "Engine Decodes utf8")
|
||||||
|
|
||||||
client.on("stringTest") {data, ack in
|
client.on("stringTest") {data, ack in
|
||||||
XCTAssertEqual(data[0] as? String, "lïne one\nlīne \rtwo", "Failed string test")
|
XCTAssertEqual(data[0] as? String, "lïne one\nlīne \rtwo𦅙𦅛", "Failed string test")
|
||||||
expect.fulfill()
|
expect.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.parsePollingMessage("41:42[\"stringTest\",\"lïne one\\nlīne \\rtwo\"]")
|
let stringMessage = "42[\"stringTest\",\"lïne one\\nlīne \\rtwo𦅙𦅛\"]"
|
||||||
|
|
||||||
|
engine.parsePollingMessage("\(stringMessage.utf16.count):\(stringMessage)")
|
||||||
waitForExpectations(timeout: 3, handler: nil)
|
waitForExpectations(timeout: 3, handler: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +118,8 @@ class SocketEngineTest: XCTestCase {
|
|||||||
expect.fulfill()
|
expect.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.parseEngineMessage(packetString, fromPolling: false)
|
engine.parseEngineMessage(packetString)
|
||||||
engine.parseEngineMessage(b64String, fromPolling: false)
|
engine.parseEngineMessage(b64String)
|
||||||
|
|
||||||
waitForExpectations(timeout: 3, handler: nil)
|
waitForExpectations(timeout: 3, handler: nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,9 @@
|
|||||||
// Merely tests whether the Objective-C api breaks
|
// Merely tests whether the Objective-C api breaks
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <XCTest/XCTest.h>
|
@import Dispatch;
|
||||||
|
@import Foundation;
|
||||||
|
@import XCTest;
|
||||||
@import SocketIO;
|
@import SocketIO;
|
||||||
|
|
||||||
@interface SocketObjectiveCTest : XCTestCase
|
@interface SocketObjectiveCTest : XCTestCase
|
||||||
@ -24,20 +26,66 @@
|
|||||||
self.socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @NO, @"forcePolling": @YES}];
|
self.socket = [[SocketIOClient alloc] initWithSocketURL:url config:@{@"log": @NO, @"forcePolling": @YES}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testProperties {
|
||||||
|
NSURL* url = nil;
|
||||||
|
|
||||||
|
url = self.socket.socketURL;
|
||||||
|
self.socket.forceNew = false;
|
||||||
|
self.socket.handleQueue = dispatch_get_main_queue();
|
||||||
|
self.socket.nsp = @"/objective-c";
|
||||||
|
self.socket.reconnects = false;
|
||||||
|
self.socket.reconnectWait = 1;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testOnSyntax {
|
- (void)testOnSyntax {
|
||||||
[self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) {
|
[self.socket on:@"someCallback" callback:^(NSArray* data, SocketAckEmitter* ack) {
|
||||||
[ack with:@[@1]];
|
[ack with:@[@1]];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testConnectSyntax {
|
||||||
|
[self.socket connect];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testConnectTimeoutAfterSyntax {
|
||||||
|
[self.socket connectWithTimeoutAfter:1 withHandler: ^() { }];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testDisconnectSyntax {
|
||||||
|
[self.socket disconnect];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testLeaveNamespaceSyntax {
|
||||||
|
[self.socket leaveNamespace];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testJoinNamespaceSyntax {
|
||||||
|
[self.socket joinNamespace:@"/objective-c"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testOnAnySyntax {
|
||||||
|
[self.socket onAny:^(SocketAnyEvent* any) {
|
||||||
|
NSString* event = any.event;
|
||||||
|
NSArray* data = any.items;
|
||||||
|
|
||||||
|
[self.socket emit:event with:data];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testReconnectSyntax {
|
||||||
|
[self.socket reconnect];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testRemoveAllHandlersSyntax {
|
||||||
|
[self.socket removeAllHandlers];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testEmitSyntax {
|
- (void)testEmitSyntax {
|
||||||
[self.socket emit:@"testEmit" with:@[@YES]];
|
[self.socket emit:@"testEmit" with:@[@YES]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testEmitWithAckSyntax {
|
- (void)testEmitWithAckSyntax {
|
||||||
[[self.socket emitWithAck:@"testAckEmit" with:@[@YES]] timingOutAfter:0 callback:^(NSArray* data) {
|
[[self.socket emitWithAck:@"testAckEmit" with:@[@YES]] timingOutAfter:0 callback:^(NSArray* data) { }];
|
||||||
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testOffSyntax {
|
- (void)testOffSyntax {
|
||||||
|
|||||||
@ -66,10 +66,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
/// An array of HTTPCookies that are sent during the connection.
|
/// An array of HTTPCookies that are sent during the connection.
|
||||||
public private(set) var cookies: [HTTPCookie]?
|
public private(set) var cookies: [HTTPCookie]?
|
||||||
|
|
||||||
/// Set to `true` if using the node.js version of socket.io. The node.js version of socket.io
|
|
||||||
/// handles utf8 incorrectly.
|
|
||||||
public private(set) var doubleEncodeUTF8 = true
|
|
||||||
|
|
||||||
/// A dictionary of extra http headers that will be set during connection.
|
/// A dictionary of extra http headers that will be set during connection.
|
||||||
public private(set) var extraHeaders: [String: String]?
|
public private(set) var extraHeaders: [String: String]?
|
||||||
|
|
||||||
@ -153,8 +149,6 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
connectParams = params
|
connectParams = params
|
||||||
case let .cookies(cookies):
|
case let .cookies(cookies):
|
||||||
self.cookies = cookies
|
self.cookies = cookies
|
||||||
case let .doubleEncodeUTF8(encode):
|
|
||||||
doubleEncodeUTF8 = encode
|
|
||||||
case let .extraHeaders(headers):
|
case let .extraHeaders(headers):
|
||||||
extraHeaders = headers
|
extraHeaders = headers
|
||||||
case let .sessionDelegate(delegate):
|
case let .sessionDelegate(delegate):
|
||||||
@ -227,8 +221,8 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
// binary in base64 string
|
// binary in base64 string
|
||||||
let noPrefix = message[message.index(message.startIndex, offsetBy: 2)..<message.endIndex]
|
let noPrefix = message[message.index(message.startIndex, offsetBy: 2)..<message.endIndex]
|
||||||
|
|
||||||
if let data = NSData(base64Encoded: noPrefix, options: .ignoreUnknownCharacters) {
|
if let data = Data(base64Encoded: noPrefix, options: .ignoreUnknownCharacters) {
|
||||||
client?.parseEngineBinaryData(data as Data)
|
client?.parseEngineBinaryData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,11 +505,10 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
/// - parameter message: The message to parse.
|
/// - parameter message: The message to parse.
|
||||||
/// - parameter fromPolling: Whether this message is from long-polling.
|
/// - parameter fromPolling: Whether this message is from long-polling.
|
||||||
/// If `true` we might have to fix utf8 encoding.
|
/// If `true` we might have to fix utf8 encoding.
|
||||||
public func parseEngineMessage(_ message: String, fromPolling: Bool) {
|
public func parseEngineMessage(_ message: String) {
|
||||||
DefaultSocketLogger.Logger.log("Got message: %@", type: logType, args: message)
|
DefaultSocketLogger.Logger.log("Got message: %@", type: logType, args: message)
|
||||||
|
|
||||||
let reader = SocketStringReader(message: message)
|
let reader = SocketStringReader(message: message)
|
||||||
let fixedString: String
|
|
||||||
|
|
||||||
if message.hasPrefix("b4") {
|
if message.hasPrefix("b4") {
|
||||||
return handleBase64(message: message)
|
return handleBase64(message: message)
|
||||||
@ -527,23 +520,17 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if fromPolling && type != .noop && doubleEncodeUTF8 {
|
|
||||||
fixedString = fixDoubleUTF8(message)
|
|
||||||
} else {
|
|
||||||
fixedString = message
|
|
||||||
}
|
|
||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
case .message:
|
case .message:
|
||||||
handleMessage(String(fixedString.characters.dropFirst()))
|
handleMessage(String(message.characters.dropFirst()))
|
||||||
case .noop:
|
case .noop:
|
||||||
handleNOOP()
|
handleNOOP()
|
||||||
case .pong:
|
case .pong:
|
||||||
handlePong(with: fixedString)
|
handlePong(with: message)
|
||||||
case .open:
|
case .open:
|
||||||
handleOpen(openData: String(fixedString.characters.dropFirst()))
|
handleOpen(openData: String(message.characters.dropFirst()))
|
||||||
case .close:
|
case .close:
|
||||||
handleClose(fixedString)
|
handleClose(message)
|
||||||
default:
|
default:
|
||||||
DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType)
|
DefaultSocketLogger.Logger.log("Got unknown packet type", type: logType)
|
||||||
}
|
}
|
||||||
@ -643,17 +630,19 @@ public final class SocketEngine : NSObject, URLSessionDelegate, SocketEnginePoll
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if websocket {
|
guard websocket else {
|
||||||
connected = false
|
|
||||||
websocket = false
|
|
||||||
|
|
||||||
if let reason = error?.localizedDescription {
|
|
||||||
didError(reason: reason)
|
|
||||||
} else {
|
|
||||||
client?.engineDidClose(reason: "Socket Disconnected")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
flushProbeWait()
|
flushProbeWait()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = false
|
||||||
|
websocket = false
|
||||||
|
|
||||||
|
if let reason = error?.localizedDescription {
|
||||||
|
didError(reason: reason)
|
||||||
|
} else {
|
||||||
|
client?.engineDidClose(reason: "Socket Disconnected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,9 +71,7 @@ public protocol SocketEnginePollable : SocketEngineSpec {
|
|||||||
|
|
||||||
// Default polling methods
|
// Default polling methods
|
||||||
extension SocketEnginePollable {
|
extension SocketEnginePollable {
|
||||||
private func addHeaders(for req: URLRequest) -> URLRequest {
|
private func addHeaders(to req: inout URLRequest) {
|
||||||
var req = req
|
|
||||||
|
|
||||||
if cookies != nil {
|
if cookies != nil {
|
||||||
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
let headers = HTTPCookie.requestHeaderFields(with: cookies!)
|
||||||
req.allHTTPHeaderFields = headers
|
req.allHTTPHeaderFields = headers
|
||||||
@ -84,8 +82,6 @@ extension SocketEnginePollable {
|
|||||||
req.setValue(value, forHTTPHeaderField: headerName)
|
req.setValue(value, forHTTPHeaderField: headerName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return req
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRequestForPostWithPostWait() -> URLRequest {
|
func createRequestForPostWithPostWait() -> URLRequest {
|
||||||
@ -94,9 +90,7 @@ extension SocketEnginePollable {
|
|||||||
var postStr = ""
|
var postStr = ""
|
||||||
|
|
||||||
for packet in postWait {
|
for packet in postWait {
|
||||||
let len = packet.characters.count
|
postStr += "\(packet.utf16.count):\(packet)"
|
||||||
|
|
||||||
postStr += "\(len):\(packet)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Created POST string: %@", type: "SocketEnginePolling", args: postStr)
|
DefaultSocketLogger.Logger.log("Created POST string: %@", type: "SocketEnginePolling", args: postStr)
|
||||||
@ -104,11 +98,10 @@ extension SocketEnginePollable {
|
|||||||
var req = URLRequest(url: urlPollingWithSid)
|
var req = URLRequest(url: urlPollingWithSid)
|
||||||
let postData = postStr.data(using: .utf8, allowLossyConversion: false)!
|
let postData = postStr.data(using: .utf8, allowLossyConversion: false)!
|
||||||
|
|
||||||
req = addHeaders(for: req)
|
addHeaders(to: &req)
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
req.httpBody = postData
|
req.httpBody = postData
|
||||||
req.setValue(String(postData.count), forHTTPHeaderField: "Content-Length")
|
req.setValue(String(postData.count), forHTTPHeaderField: "Content-Length")
|
||||||
|
|
||||||
@ -119,20 +112,16 @@ extension SocketEnginePollable {
|
|||||||
///
|
///
|
||||||
/// You shouldn't need to call this directly, the engine should automatically maintain a long-poll request.
|
/// You shouldn't need to call this directly, the engine should automatically maintain a long-poll request.
|
||||||
public func doPoll() {
|
public func doPoll() {
|
||||||
if websocket || waitingForPoll || !connected || closed {
|
guard !websocket && !waitingForPoll && connected && !closed else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var req = URLRequest(url: urlPollingWithSid)
|
var req = URLRequest(url: urlPollingWithSid)
|
||||||
req = addHeaders(for: req)
|
addHeaders(to: &req)
|
||||||
|
|
||||||
doLongPoll(for: req )
|
doLongPoll(for: req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func doRequest(for req: URLRequest, callbackWith callback: @escaping (Data?, URLResponse?, Error?) -> Void) {
|
func doRequest(for req: URLRequest, callbackWith callback: @escaping (Data?, URLResponse?, Error?) -> Void) {
|
||||||
if !polling || closed || invalidated || fastUpgrade {
|
guard polling && !closed && !invalidated && !fastUpgrade else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Doing polling %@ %@", type: "SocketEnginePolling",
|
DefaultSocketLogger.Logger.log("Doing polling %@ %@", type: "SocketEnginePolling",
|
||||||
args: req.httpMethod ?? "", req)
|
args: req.httpMethod ?? "", req)
|
||||||
@ -173,10 +162,10 @@ extension SocketEnginePollable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func flushWaitingForPost() {
|
private func flushWaitingForPost() {
|
||||||
if postWait.count == 0 || !connected {
|
guard postWait.count != 0 && connected else { return }
|
||||||
return
|
guard !websocket else {
|
||||||
} else if websocket {
|
|
||||||
flushWaitingForPostToWebSocket()
|
flushWaitingForPostToWebSocket()
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,13 +200,15 @@ extension SocketEnginePollable {
|
|||||||
func parsePollingMessage(_ str: String) {
|
func parsePollingMessage(_ str: String) {
|
||||||
guard str.characters.count != 1 else { return }
|
guard str.characters.count != 1 else { return }
|
||||||
|
|
||||||
|
DefaultSocketLogger.Logger.log("Got poll message: %@", type: "SocketEnginePolling", args: str)
|
||||||
|
|
||||||
var reader = SocketStringReader(message: str)
|
var reader = SocketStringReader(message: str)
|
||||||
|
|
||||||
while reader.hasNext {
|
while reader.hasNext {
|
||||||
if let n = Int(reader.readUntilOccurence(of: ":")) {
|
if let n = Int(reader.readUntilOccurence(of: ":")) {
|
||||||
parseEngineMessage(reader.read(count: n), fromPolling: true)
|
parseEngineMessage(reader.read(count: n))
|
||||||
} else {
|
} else {
|
||||||
parseEngineMessage(str, fromPolling: true)
|
parseEngineMessage(str)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,15 +223,8 @@ extension SocketEnginePollable {
|
|||||||
/// - parameter withData: The data associated with this message.
|
/// - parameter withData: The data associated with this message.
|
||||||
public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) {
|
public func sendPollMessage(_ message: String, withType type: SocketEnginePacketType, withData datas: [Data]) {
|
||||||
DefaultSocketLogger.Logger.log("Sending poll: %@ as type: %@", type: "SocketEnginePolling", args: message, type.rawValue)
|
DefaultSocketLogger.Logger.log("Sending poll: %@ as type: %@", type: "SocketEnginePolling", args: message, type.rawValue)
|
||||||
let fixedMessage: String
|
|
||||||
|
|
||||||
if doubleEncodeUTF8 {
|
postWait.append(String(type.rawValue) + message)
|
||||||
fixedMessage = doubleEncodeUTF8(message)
|
|
||||||
} else {
|
|
||||||
fixedMessage = message
|
|
||||||
}
|
|
||||||
|
|
||||||
postWait.append(String(type.rawValue) + fixedMessage)
|
|
||||||
|
|
||||||
for data in datas {
|
for data in datas {
|
||||||
if case let .right(bin) = createBinaryDataForSend(using: data) {
|
if case let .right(bin) = createBinaryDataForSend(using: data) {
|
||||||
|
|||||||
@ -39,10 +39,6 @@ import Foundation
|
|||||||
/// The connect parameters sent during a connect.
|
/// The connect parameters sent during a connect.
|
||||||
var connectParams: [String: Any]? { get set }
|
var connectParams: [String: Any]? { get set }
|
||||||
|
|
||||||
/// Set to `true` if using the node.js version of socket.io. The node.js version of socket.io
|
|
||||||
/// handles utf8 incorrectly.
|
|
||||||
var doubleEncodeUTF8: Bool { get }
|
|
||||||
|
|
||||||
/// An array of HTTPCookies that are sent during the connection.
|
/// An array of HTTPCookies that are sent during the connection.
|
||||||
var cookies: [HTTPCookie]? { get }
|
var cookies: [HTTPCookie]? { get }
|
||||||
|
|
||||||
@ -125,7 +121,7 @@ import Foundation
|
|||||||
/// - parameter message: The message to parse.
|
/// - parameter message: The message to parse.
|
||||||
/// - parameter fromPolling: Whether this message is from long-polling.
|
/// - parameter fromPolling: Whether this message is from long-polling.
|
||||||
/// If `true` we might have to fix utf8 encoding.
|
/// If `true` we might have to fix utf8 encoding.
|
||||||
func parseEngineMessage(_ message: String, fromPolling: Bool)
|
func parseEngineMessage(_ message: String)
|
||||||
|
|
||||||
/// Writes a message to engine.io, independent of transport.
|
/// Writes a message to engine.io, independent of transport.
|
||||||
///
|
///
|
||||||
@ -165,24 +161,6 @@ extension SocketEngineSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doubleEncodeUTF8(_ string: String) -> String {
|
|
||||||
if let latin1 = string.data(using: String.Encoding.utf8),
|
|
||||||
let utf8 = NSString(data: latin1, encoding: String.Encoding.isoLatin1.rawValue) {
|
|
||||||
return utf8 as String
|
|
||||||
} else {
|
|
||||||
return string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fixDoubleUTF8(_ string: String) -> String {
|
|
||||||
if let utf8 = string.data(using: String.Encoding.isoLatin1),
|
|
||||||
let latin1 = NSString(data: utf8, encoding: String.Encoding.utf8.rawValue) {
|
|
||||||
return latin1 as String
|
|
||||||
} else {
|
|
||||||
return string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Send an engine message (4)
|
/// Send an engine message (4)
|
||||||
func send(_ msg: String, withData datas: [Data]) {
|
func send(_ msg: String, withData datas: [Data]) {
|
||||||
write(msg, withType: .message, withData: datas)
|
write(msg, withType: .message, withData: datas)
|
||||||
|
|||||||
@ -68,7 +68,7 @@ extension SocketEngineWebsocket {
|
|||||||
|
|
||||||
/// Delegate method for when a message is received.
|
/// Delegate method for when a message is received.
|
||||||
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
|
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
|
||||||
parseEngineMessage(text, fromPolling: false)
|
parseEngineMessage(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delegate method for when binary is received.
|
/// Delegate method for when binary is received.
|
||||||
|
|||||||
@ -48,8 +48,6 @@ extension NSDictionary {
|
|||||||
return .connectParams(params)
|
return .connectParams(params)
|
||||||
case let ("cookies", cookies as [HTTPCookie]):
|
case let ("cookies", cookies as [HTTPCookie]):
|
||||||
return .cookies(cookies)
|
return .cookies(cookies)
|
||||||
case let ("doubleEncodeUTF8", encode as Bool):
|
|
||||||
return .doubleEncodeUTF8(encode)
|
|
||||||
case let ("extraHeaders", headers as [String: String]):
|
case let ("extraHeaders", headers as [String: String]):
|
||||||
return .extraHeaders(headers)
|
return .extraHeaders(headers)
|
||||||
case let ("forceNew", force as Bool):
|
case let ("forceNew", force as Bool):
|
||||||
@ -104,7 +102,7 @@ extension NSDictionary {
|
|||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
func toArray() throws -> [Any] {
|
func toArray() throws -> [Any] {
|
||||||
guard let stringData = data(using: .utf8, allowLossyConversion: false) else { return [] }
|
guard let stringData = data(using: .utf16, allowLossyConversion: false) else { return [] }
|
||||||
guard let array = try JSONSerialization.jsonObject(with: stringData, options: .mutableContainers) as? [Any] else {
|
guard let array = try JSONSerialization.jsonObject(with: stringData, options: .mutableContainers) as? [Any] else {
|
||||||
throw JSONError.notArray
|
throw JSONError.notArray
|
||||||
}
|
}
|
||||||
@ -113,7 +111,7 @@ extension String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toNSDictionary() throws -> NSDictionary {
|
func toNSDictionary() throws -> NSDictionary {
|
||||||
guard let binData = data(using: .utf8, allowLossyConversion: false) else { return [:] }
|
guard let binData = data(using: .utf16, allowLossyConversion: false) else { return [:] }
|
||||||
guard let json = try JSONSerialization.jsonObject(with: binData, options: .allowFragments) as? NSDictionary else {
|
guard let json = try JSONSerialization.jsonObject(with: binData, options: .allowFragments) as? NSDictionary else {
|
||||||
throw JSONError.notNSDictionary
|
throw JSONError.notNSDictionary
|
||||||
}
|
}
|
||||||
|
|||||||
@ -237,7 +237,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
|
|||||||
/// - parameter items: The items to send with this event. May be left out.
|
/// - parameter items: The items to send with this event. May be left out.
|
||||||
open func emit(_ event: String, _ items: SocketData...) {
|
open func emit(_ event: String, _ items: SocketData...) {
|
||||||
do {
|
do {
|
||||||
emit(event, with: try items.map({ try $0.socketRepresentation() }))
|
try emit(event, with: items.map({ try $0.socketRepresentation() }))
|
||||||
} catch let err {
|
} catch let err {
|
||||||
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
|
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
|
||||||
type: logType)
|
type: logType)
|
||||||
|
|||||||
@ -36,8 +36,8 @@ public enum SocketIOClientOption : ClientOption {
|
|||||||
/// An array of cookies that will be sent during the initial connection.
|
/// An array of cookies that will be sent during the initial connection.
|
||||||
case cookies([HTTPCookie])
|
case cookies([HTTPCookie])
|
||||||
|
|
||||||
/// The node.js socket.io currently does funky things to unicode when doing HTTP long-polling. Passing `true` in
|
/// Deprecated
|
||||||
/// this option causes the client to try and fix any bad unicode that might be sent.
|
@available(*, deprecated, message: "No longer needed in socket.io 2.0+")
|
||||||
case doubleEncodeUTF8(Bool)
|
case doubleEncodeUTF8(Bool)
|
||||||
|
|
||||||
/// Any extra HTTP headers that should be sent during the initial connection.
|
/// Any extra HTTP headers that should be sent during the initial connection.
|
||||||
|
|||||||
@ -107,7 +107,7 @@ extension SocketParsable where Self: SocketIOClientSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataArray = message[message.characters.index(reader.currentIndex, offsetBy: 1)..<message.endIndex]
|
var dataArray = String(message.utf16[message.utf16.index(reader.currentIndex, offsetBy: 1)..<message.utf16.endIndex])!
|
||||||
|
|
||||||
if type == .error && !dataArray.hasPrefix("[") && !dataArray.hasSuffix("]") {
|
if type == .error && !dataArray.hasPrefix("[") && !dataArray.hasSuffix("]") {
|
||||||
dataArray = "[" + dataArray + "]"
|
dataArray = "[" + dataArray + "]"
|
||||||
|
|||||||
@ -24,29 +24,29 @@
|
|||||||
|
|
||||||
struct SocketStringReader {
|
struct SocketStringReader {
|
||||||
let message: String
|
let message: String
|
||||||
var currentIndex: String.Index
|
var currentIndex: String.UTF16View.Index
|
||||||
var hasNext: Bool {
|
var hasNext: Bool {
|
||||||
return currentIndex != message.endIndex
|
return currentIndex != message.utf16.endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentCharacter: String {
|
var currentCharacter: String {
|
||||||
return String(message[currentIndex])
|
return String(UnicodeScalar(message.utf16[currentIndex])!)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(message: String) {
|
init(message: String) {
|
||||||
self.message = message
|
self.message = message
|
||||||
currentIndex = message.startIndex
|
currentIndex = message.utf16.startIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
mutating func advance(by: Int) -> String.Index {
|
mutating func advance(by: Int) -> String.UTF16View.Index {
|
||||||
currentIndex = message.characters.index(currentIndex, offsetBy: by)
|
currentIndex = message.utf16.index(currentIndex, offsetBy: by)
|
||||||
|
|
||||||
return currentIndex
|
return currentIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func read(count: Int) -> String {
|
mutating func read(count: Int) -> String {
|
||||||
let readString = message[currentIndex..<message.characters.index(currentIndex, offsetBy: count)]
|
let readString = String(message.utf16[currentIndex..<message.utf16.index(currentIndex, offsetBy: count)])!
|
||||||
|
|
||||||
advance(by: count)
|
advance(by: count)
|
||||||
|
|
||||||
@ -54,20 +54,20 @@ struct SocketStringReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutating func readUntilOccurence(of string: String) -> String {
|
mutating func readUntilOccurence(of string: String) -> String {
|
||||||
let substring = message[currentIndex..<message.endIndex]
|
let substring = message.utf16[currentIndex..<message.utf16.endIndex]
|
||||||
|
|
||||||
guard let foundRange = substring.range(of: string) else {
|
guard let foundIndex = substring.index(of: string.utf16.first!) else {
|
||||||
currentIndex = message.endIndex
|
currentIndex = message.utf16.endIndex
|
||||||
|
|
||||||
return substring
|
return String(substring)!
|
||||||
}
|
}
|
||||||
|
|
||||||
advance(by: message.characters.distance(from: message.characters.startIndex, to: foundRange.lowerBound) + 1)
|
advance(by: substring.distance(from: substring.startIndex, to: foundIndex) + 1)
|
||||||
|
|
||||||
return substring.substring(to: foundRange.lowerBound)
|
return String(substring[substring.startIndex..<foundIndex])!
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func readUntilEnd() -> String {
|
mutating func readUntilEnd() -> String {
|
||||||
return read(count: message.characters.distance(from: currentIndex, to: message.endIndex))
|
return read(count: message.utf16.distance(from: currentIndex, to: message.utf16.endIndex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user