commit
31e4c60db8
@ -88,7 +88,7 @@ Carthage
|
|||||||
-----------------
|
-----------------
|
||||||
Add this line to your `Cartfile`:
|
Add this line to your `Cartfile`:
|
||||||
```
|
```
|
||||||
github "socketio/socket.io-client-swift" ~> 6.1.1 # Or latest version
|
github "socketio/socket.io-client-swift" ~> 6.1.2 # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `carthage update --platform ios,macosx`.
|
Run `carthage update --platform ios,macosx`.
|
||||||
@ -102,7 +102,7 @@ source 'https://github.com/CocoaPods/Specs.git'
|
|||||||
platform :ios, '8.0'
|
platform :ios, '8.0'
|
||||||
use_frameworks!
|
use_frameworks!
|
||||||
|
|
||||||
pod 'Socket.IO-Client-Swift', '~> 6.1.1' # Or latest version
|
pod 'Socket.IO-Client-Swift', '~> 6.1.2' # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Install pods:
|
Install pods:
|
||||||
@ -130,7 +130,7 @@ CocoaSeeds
|
|||||||
Add this line to your `Seedfile`:
|
Add this line to your `Seedfile`:
|
||||||
|
|
||||||
```
|
```
|
||||||
github "socketio/socket.io-client-swift", "v6.1.1", :files => "Source/*.swift" # Or latest version
|
github "socketio/socket.io-client-swift", "v6.1.2", :files => "Source/*.swift" # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `seed install`.
|
Run `seed install`.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "Socket.IO-Client-Swift"
|
s.name = "Socket.IO-Client-Swift"
|
||||||
s.module_name = "SocketIOClientSwift"
|
s.module_name = "SocketIOClientSwift"
|
||||||
s.version = "6.1.1"
|
s.version = "6.1.2"
|
||||||
s.summary = "Socket.IO-client for iOS and OS X"
|
s.summary = "Socket.IO-client for iOS and OS X"
|
||||||
s.description = <<-DESC
|
s.description = <<-DESC
|
||||||
Socket.IO-client for iOS and OS X.
|
Socket.IO-client for iOS and OS X.
|
||||||
@ -14,7 +14,7 @@ Pod::Spec.new do |s|
|
|||||||
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.tvos.deployment_target = '9.0'
|
s.tvos.deployment_target = '9.0'
|
||||||
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v6.1.1' }
|
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v6.1.2' }
|
||||||
s.source_files = "Source/**/*.swift"
|
s.source_files = "Source/**/*.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
|
||||||
|
|||||||
@ -101,11 +101,6 @@
|
|||||||
74171EC51C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
74171EC51C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
||||||
74171EC71C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
74171EC71C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
||||||
74171EC81C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
74171EC81C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
||||||
74171EC91C10CD240062D398 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E611C10CD240062D398 /* SwiftRegex.swift */; };
|
|
||||||
74171ECA1C10CD240062D398 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E611C10CD240062D398 /* SwiftRegex.swift */; };
|
|
||||||
74171ECB1C10CD240062D398 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E611C10CD240062D398 /* SwiftRegex.swift */; };
|
|
||||||
74171ECD1C10CD240062D398 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E611C10CD240062D398 /* SwiftRegex.swift */; };
|
|
||||||
74171ECE1C10CD240062D398 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E611C10CD240062D398 /* SwiftRegex.swift */; };
|
|
||||||
74171ECF1C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
74171ECF1C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
||||||
74171ED01C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
74171ED01C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
||||||
74171ED11C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
74171ED11C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
||||||
@ -190,7 +185,6 @@
|
|||||||
74171E5E1C10CD240062D398 /* SocketParsable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketParsable.swift; path = Source/SocketParsable.swift; sourceTree = "<group>"; };
|
74171E5E1C10CD240062D398 /* SocketParsable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketParsable.swift; path = Source/SocketParsable.swift; sourceTree = "<group>"; };
|
||||||
74171E5F1C10CD240062D398 /* SocketStringReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketStringReader.swift; path = Source/SocketStringReader.swift; sourceTree = "<group>"; };
|
74171E5F1C10CD240062D398 /* SocketStringReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketStringReader.swift; path = Source/SocketStringReader.swift; sourceTree = "<group>"; };
|
||||||
74171E601C10CD240062D398 /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketTypes.swift; path = Source/SocketTypes.swift; sourceTree = "<group>"; };
|
74171E601C10CD240062D398 /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketTypes.swift; path = Source/SocketTypes.swift; sourceTree = "<group>"; };
|
||||||
74171E611C10CD240062D398 /* SwiftRegex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftRegex.swift; path = Source/SwiftRegex.swift; sourceTree = "<group>"; };
|
|
||||||
74171E621C10CD240062D398 /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = Source/WebSocket.swift; sourceTree = "<group>"; };
|
74171E621C10CD240062D398 /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = Source/WebSocket.swift; sourceTree = "<group>"; };
|
||||||
741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = "<group>"; };
|
741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = "<group>"; };
|
||||||
7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketEnginePollable.swift; path = Source/SocketEnginePollable.swift; sourceTree = "<group>"; };
|
7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketEnginePollable.swift; path = Source/SocketEnginePollable.swift; sourceTree = "<group>"; };
|
||||||
@ -375,7 +369,6 @@
|
|||||||
74171E5E1C10CD240062D398 /* SocketParsable.swift */,
|
74171E5E1C10CD240062D398 /* SocketParsable.swift */,
|
||||||
74171E5F1C10CD240062D398 /* SocketStringReader.swift */,
|
74171E5F1C10CD240062D398 /* SocketStringReader.swift */,
|
||||||
74171E601C10CD240062D398 /* SocketTypes.swift */,
|
74171E601C10CD240062D398 /* SocketTypes.swift */,
|
||||||
74171E611C10CD240062D398 /* SwiftRegex.swift */,
|
|
||||||
74171E621C10CD240062D398 /* WebSocket.swift */,
|
74171E621C10CD240062D398 /* WebSocket.swift */,
|
||||||
);
|
);
|
||||||
name = Source;
|
name = Source;
|
||||||
@ -638,7 +631,6 @@
|
|||||||
74171EAB1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
74171EAB1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
||||||
74171E991C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
74171E991C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
||||||
74171E8D1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E8D1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171EC91C10CD240062D398 /* SwiftRegex.swift in Sources */,
|
|
||||||
74171E7B1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7B1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171ECF1C10CD240062D398 /* WebSocket.swift in Sources */,
|
74171ECF1C10CD240062D398 /* WebSocket.swift in Sources */,
|
||||||
74171EB11C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB11C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
@ -663,7 +655,6 @@
|
|||||||
74171E8E1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E8E1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171E7C1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7C1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171E821C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
74171E821C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
||||||
74171ECA1C10CD240062D398 /* SwiftRegex.swift in Sources */,
|
|
||||||
74171EB21C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB21C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
741F39EE1BD025D80026C9CC /* SocketEngineTest.swift in Sources */,
|
741F39EE1BD025D80026C9CC /* SocketEngineTest.swift in Sources */,
|
||||||
74171EBE1C10CD240062D398 /* SocketStringReader.swift in Sources */,
|
74171EBE1C10CD240062D398 /* SocketStringReader.swift in Sources */,
|
||||||
@ -697,7 +688,6 @@
|
|||||||
74171EAD1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
74171EAD1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
||||||
74171E9B1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
74171E9B1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
||||||
74171E8F1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E8F1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171ECB1C10CD240062D398 /* SwiftRegex.swift in Sources */,
|
|
||||||
74171E7D1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7D1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171ED11C10CD240062D398 /* WebSocket.swift in Sources */,
|
74171ED11C10CD240062D398 /* WebSocket.swift in Sources */,
|
||||||
74171EB31C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB31C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
@ -742,7 +732,6 @@
|
|||||||
74171EAF1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
74171EAF1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
||||||
74171E9D1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
74171E9D1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
||||||
74171E911C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E911C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171ECD1C10CD240062D398 /* SwiftRegex.swift in Sources */,
|
|
||||||
74171E7F1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7F1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171ED31C10CD240062D398 /* WebSocket.swift in Sources */,
|
74171ED31C10CD240062D398 /* WebSocket.swift in Sources */,
|
||||||
74171EB51C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB51C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
@ -767,7 +756,6 @@
|
|||||||
74171E921C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E921C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171E801C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E801C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171E861C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
74171E861C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
||||||
74171ECE1C10CD240062D398 /* SwiftRegex.swift in Sources */,
|
|
||||||
74171EB61C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB61C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
57634A2A1BD9B46D00E19CD7 /* SocketEngineTest.swift in Sources */,
|
57634A2A1BD9B46D00E19CD7 /* SocketEngineTest.swift in Sources */,
|
||||||
74171EC21C10CD240062D398 /* SocketStringReader.swift in Sources */,
|
74171EC21C10CD240062D398 /* SocketStringReader.swift in Sources */,
|
||||||
|
|||||||
@ -145,4 +145,20 @@ class SocketBasicPacketTest: XCTestCase {
|
|||||||
XCTAssertEqual(packet.packetString, expectedSendString)
|
XCTAssertEqual(packet.packetString, expectedSendString)
|
||||||
XCTAssertEqual(packet.binary, [data2, data])
|
XCTAssertEqual(packet.binary, [data2, data])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBinaryStringPlaceholderInMessage() {
|
||||||
|
let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"num\":1,\"_placeholder\":true}]"
|
||||||
|
let socket = SocketIOClient(socketURL: NSURL())
|
||||||
|
socket.setTestable()
|
||||||
|
|
||||||
|
if case let .Right(packet) = socket.parseString(engineString) {
|
||||||
|
var packet = packet
|
||||||
|
XCTAssertEqual(packet.event, "test")
|
||||||
|
packet.addData(data)
|
||||||
|
packet.addData(data2)
|
||||||
|
XCTAssertEqual(packet.args[0] as? String, "~~0")
|
||||||
|
} else {
|
||||||
|
XCTFail()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,10 @@ class SocketParserTest: XCTestCase {
|
|||||||
"25[\"test\"]": ("/", ["test"], [], 5),
|
"25[\"test\"]": ("/", ["test"], [], 5),
|
||||||
"2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1),
|
"2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1),
|
||||||
"2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]": ("/swift", ["testArrayEmitReturn", ["test3", "test4"]], [], -1),
|
"2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]": ("/swift", ["testArrayEmitReturn", ["test3", "test4"]], [], -1),
|
||||||
"51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", ["testMultipleItemsWithBufferEmitReturn", [1, 2], ["test": "bob"], 25, "polo", "~~0"], [], -1),
|
"51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", ["testMultipleItemsWithBufferEmitReturn", [1, 2], ["test": "bob"], 25, "polo", ["_placeholder": true, "num": 0]], [], -1),
|
||||||
"3/swift,0[[\"test3\",\"test4\"]]": ("/swift", [["test3", "test4"]], [], 0),
|
"3/swift,0[[\"test3\",\"test4\"]]": ("/swift", [["test3", "test4"]], [], 0),
|
||||||
"61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]": ("/swift", [ [1, 2], ["test": "bob"], 25, "polo", "~~0"], [], 19),
|
"61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]":
|
||||||
|
("/swift", [ [1, 2], ["test": "bob"], 25, "polo", ["_placeholder": true, "num": 0]], [], 19),
|
||||||
"4/swift,": ("/swift", [], [], -1),
|
"4/swift,": ("/swift", [], [], -1),
|
||||||
"0/swift": ("/swift", [], [], -1),
|
"0/swift": ("/swift", [], [], -1),
|
||||||
"1/swift": ("/swift", [], [], -1),
|
"1/swift": ("/swift", [], [], -1),
|
||||||
@ -123,8 +124,8 @@ class SocketParserTest: XCTestCase {
|
|||||||
if case let .Right(packet) = packet {
|
if case let .Right(packet) = packet {
|
||||||
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
|
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
|
||||||
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), "\(packet.data)")
|
||||||
XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2))
|
XCTAssertTrue((packet.binary as NSArray).isEqualToArray(validValues.2), "\(packet.binary)")
|
||||||
XCTAssertEqual(packet.id, validValues.3)
|
XCTAssertEqual(packet.id, validValues.3)
|
||||||
} else {
|
} else {
|
||||||
XCTFail()
|
XCTFail()
|
||||||
|
|||||||
@ -62,9 +62,6 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
|
|
||||||
private weak var sessionDelegate: NSURLSessionDelegate?
|
private weak var sessionDelegate: NSURLSessionDelegate?
|
||||||
|
|
||||||
private typealias Probe = (msg: String, type: SocketEnginePacketType, data: [NSData])
|
|
||||||
private typealias ProbeWaitQueue = [Probe]
|
|
||||||
|
|
||||||
private let logType = "SocketEngine"
|
private let logType = "SocketEngine"
|
||||||
private let url: NSURL
|
private let url: NSURL
|
||||||
|
|
||||||
@ -74,6 +71,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
|
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var pongsMissed = 0
|
private var pongsMissed = 0
|
||||||
private var pongsMissedMax = 0
|
private var pongsMissedMax = 0
|
||||||
private var probeWait = ProbeWaitQueue()
|
private var probeWait = ProbeWaitQueue()
|
||||||
@ -387,7 +385,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
doPoll()
|
doPoll()
|
||||||
}
|
}
|
||||||
|
|
||||||
client?.engineDidOpen?("Connect")
|
client?.engineDidOpen("Connect")
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
didError("Error parsing open packet")
|
didError("Error parsing open packet")
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import Foundation
|
|||||||
@objc public protocol SocketEngineClient {
|
@objc public protocol SocketEngineClient {
|
||||||
func engineDidError(reason: String)
|
func engineDidError(reason: String)
|
||||||
func engineDidClose(reason: String)
|
func engineDidClose(reason: String)
|
||||||
optional func engineDidOpen(reason: String)
|
func engineDidOpen(reason: String)
|
||||||
func parseEngineMessage(msg: String)
|
func parseEngineMessage(msg: String)
|
||||||
func parseEngineBinaryData(data: NSData)
|
func parseEngineBinaryData(data: NSData)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -191,7 +191,6 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
|
DefaultSocketLogger.Logger.log("Disconnected: %@", type: logType, args: reason)
|
||||||
|
|
||||||
status = .Disconnected
|
status = .Disconnected
|
||||||
reconnects = false
|
|
||||||
|
|
||||||
// Make sure the engine is actually dead.
|
// Make sure the engine is actually dead.
|
||||||
engine?.disconnect(reason)
|
engine?.disconnect(reason)
|
||||||
@ -205,7 +204,6 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
|
DefaultSocketLogger.Logger.log("Closing socket", type: logType)
|
||||||
|
|
||||||
reconnects = false
|
|
||||||
didDisconnect("Disconnect")
|
didDisconnect("Disconnect")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +285,10 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
handleEvent("error", data: [reason], isInternalMessage: true)
|
handleEvent("error", data: [reason], isInternalMessage: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func engineDidOpen(reason: String) {
|
||||||
|
DefaultSocketLogger.Logger.log(reason, type: "SocketEngineClient")
|
||||||
|
}
|
||||||
|
|
||||||
// Called when the socket gets an ack for something it sent
|
// Called when the socket gets an ack for something it sent
|
||||||
func handleAck(ack: Int, data: [AnyObject]) {
|
func handleAck(ack: Int, data: [AnyObject]) {
|
||||||
guard status == .Connected else { return }
|
guard status == .Connected else { return }
|
||||||
@ -298,9 +300,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
|
|
||||||
/// Causes an event to be handled. Only use if you know what you're doing.
|
/// Causes an event to be handled. Only use if you know what you're doing.
|
||||||
public func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int = -1) {
|
public func handleEvent(event: String, data: [AnyObject], isInternalMessage: Bool, withAck ack: Int = -1) {
|
||||||
guard status == .Connected || isInternalMessage else {
|
guard status == .Connected || isInternalMessage else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "")
|
DefaultSocketLogger.Logger.log("Handling event: %@ with data: %@", type: logType, args: event, data ?? "")
|
||||||
|
|
||||||
@ -335,14 +335,14 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
public func off(event: String) {
|
public func off(event: String) {
|
||||||
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event)
|
DefaultSocketLogger.Logger.log("Removing handler for event: %@", type: logType, args: event)
|
||||||
|
|
||||||
handlers = handlers.filter { $0.event != event }
|
handlers = handlers.filter({ $0.event != event })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a handler with the specified UUID gotten from an `on` or `once`
|
/// Removes a handler with the specified UUID gotten from an `on` or `once`
|
||||||
public func off(id id: NSUUID) {
|
public func off(id id: NSUUID) {
|
||||||
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
|
DefaultSocketLogger.Logger.log("Removing handler with id: %@", type: logType, args: id)
|
||||||
|
|
||||||
handlers = handlers.filter { $0.id != id }
|
handlers = handlers.filter({ $0.id != id })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a handler for an event.
|
/// Adds a handler for an event.
|
||||||
|
|||||||
@ -61,7 +61,7 @@ struct SocketPacket {
|
|||||||
return createPacketString()
|
return createPacketString()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(type: SocketPacket.PacketType, data: [AnyObject] = [AnyObject](), id: Int = -1,
|
init(type: PacketType, data: [AnyObject] = [AnyObject](), id: Int = -1,
|
||||||
nsp: String, placeholders: Int = 0, binary: [NSData] = [NSData]()) {
|
nsp: String, placeholders: Int = 0, binary: [NSData] = [NSData]()) {
|
||||||
self.data = data
|
self.data = data
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -97,7 +97,7 @@ struct SocketPacket {
|
|||||||
let jsonSend = try NSJSONSerialization.dataWithJSONObject(data,
|
let jsonSend = try NSJSONSerialization.dataWithJSONObject(data,
|
||||||
options: NSJSONWritingOptions(rawValue: 0))
|
options: NSJSONWritingOptions(rawValue: 0))
|
||||||
guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else {
|
guard let jsonString = String(data: jsonSend, encoding: NSUTF8StringEncoding) else {
|
||||||
return "[]"
|
return message + "[]"
|
||||||
}
|
}
|
||||||
|
|
||||||
restOfMessage = jsonString
|
restOfMessage = jsonString
|
||||||
@ -187,19 +187,21 @@ struct SocketPacket {
|
|||||||
data = data.map(_fillInPlaceholders)
|
data = data.map(_fillInPlaceholders)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method that looks for placeholder strings
|
// Helper method that looks for placeholders
|
||||||
// If object is a collection it will recurse
|
// If object is a collection it will recurse
|
||||||
// Returns the object if it is not a placeholder string or the corresponding
|
// Returns the object if it is not a placeholder or the corresponding
|
||||||
// binary data
|
// binary data
|
||||||
private func _fillInPlaceholders(object: AnyObject) -> AnyObject {
|
private func _fillInPlaceholders(object: AnyObject) -> AnyObject {
|
||||||
switch object {
|
switch object {
|
||||||
case let string as String where string["~~(\\d)"].groups() != nil:
|
|
||||||
return binary[Int(string["~~(\\d)"].groups()![1])!]
|
|
||||||
case let dict as NSDictionary:
|
case let dict as NSDictionary:
|
||||||
return dict.reduce(NSMutableDictionary(), combine: {cur, keyValue in
|
if dict["_placeholder"] as? Bool ?? false {
|
||||||
cur[keyValue.0 as! NSCopying] = _fillInPlaceholders(keyValue.1)
|
return binary[dict["num"] as! Int]
|
||||||
return cur
|
} else {
|
||||||
})
|
return dict.reduce(NSMutableDictionary(), combine: {cur, keyValue in
|
||||||
|
cur[keyValue.0 as! NSCopying] = _fillInPlaceholders(keyValue.1)
|
||||||
|
return cur
|
||||||
|
})
|
||||||
|
}
|
||||||
case let arr as [AnyObject]:
|
case let arr as [AnyObject]:
|
||||||
return arr.map(_fillInPlaceholders)
|
return arr.map(_fillInPlaceholders)
|
||||||
default:
|
default:
|
||||||
@ -227,7 +229,7 @@ extension SocketPacket {
|
|||||||
static func packetFromEmit(items: [AnyObject], id: Int, nsp: String, ack: Bool) -> SocketPacket {
|
static func packetFromEmit(items: [AnyObject], id: Int, nsp: String, ack: Bool) -> SocketPacket {
|
||||||
let (parsedData, binary) = deconstructData(items)
|
let (parsedData, binary) = deconstructData(items)
|
||||||
let packet = SocketPacket(type: findType(binary.count, ack: ack), data: parsedData,
|
let packet = SocketPacket(type: findType(binary.count, ack: ack), data: parsedData,
|
||||||
id: id, nsp: nsp, placeholders: -1, binary: binary)
|
id: id, nsp: nsp, binary: binary)
|
||||||
|
|
||||||
return packet
|
return packet
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,8 +35,6 @@ extension SocketParsable {
|
|||||||
private func handleConnect(p: SocketPacket) {
|
private func handleConnect(p: SocketPacket) {
|
||||||
if p.nsp == "/" && nsp != "/" {
|
if p.nsp == "/" && nsp != "/" {
|
||||||
joinNamespace(nsp)
|
joinNamespace(nsp)
|
||||||
} else if p.nsp != "/" && nsp == "/" {
|
|
||||||
didConnect()
|
|
||||||
} else {
|
} else {
|
||||||
didConnect()
|
didConnect()
|
||||||
}
|
}
|
||||||
@ -91,8 +89,7 @@ extension SocketParsable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parser.hasNext {
|
if !parser.hasNext {
|
||||||
return .Right(SocketPacket(type: type, id: -1,
|
return .Right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
|
||||||
nsp: namespace ?? "/", placeholders: placeholders))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var idString = ""
|
var idString = ""
|
||||||
@ -111,12 +108,11 @@ extension SocketParsable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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\""
|
|
||||||
|
|
||||||
switch parseData(noPlaceholders) {
|
switch parseData(d) {
|
||||||
case let .Left(err):
|
case let .Left(err):
|
||||||
// Errors aren't always enclosed in an array
|
// Errors aren't always enclosed in an array
|
||||||
if case let .Right(data) = parseData("\([noPlaceholders as AnyObject])") {
|
if case let .Right(data) = parseData("\([d as AnyObject])") {
|
||||||
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
return .Right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
|
||||||
nsp: namespace, placeholders: placeholders))
|
nsp: namespace, placeholders: placeholders))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -28,6 +28,9 @@ 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
|
||||||
|
|
||||||
|
typealias Probe = (msg: String, type: SocketEnginePacketType, data: [NSData])
|
||||||
|
typealias ProbeWaitQueue = [Probe]
|
||||||
|
|
||||||
enum Either<E, V> {
|
enum Either<E, V> {
|
||||||
case Left(E)
|
case Left(E)
|
||||||
case Right(V)
|
case Right(V)
|
||||||
|
|||||||
@ -1,195 +0,0 @@
|
|||||||
//
|
|
||||||
// SwiftRegex.swift
|
|
||||||
// SwiftRegex
|
|
||||||
//
|
|
||||||
// Created by John Holdsworth on 26/06/2014.
|
|
||||||
// Copyright (c) 2014 John Holdsworth.
|
|
||||||
//
|
|
||||||
// $Id: //depot/SwiftRegex/SwiftRegex.swift#37 $
|
|
||||||
//
|
|
||||||
// This code is in the public domain from:
|
|
||||||
// https://github.com/johnno1962/SwiftRegex
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
infix operator <~ { associativity none precedence 130 }
|
|
||||||
|
|
||||||
private let lock = dispatch_semaphore_create(1)
|
|
||||||
private var swiftRegexCache = [String: NSRegularExpression]()
|
|
||||||
|
|
||||||
internal final class SwiftRegex : NSObject, BooleanType {
|
|
||||||
var target: String
|
|
||||||
var regex: NSRegularExpression
|
|
||||||
|
|
||||||
init(target:String, pattern:String, options:NSRegularExpressionOptions?) {
|
|
||||||
self.target = target
|
|
||||||
|
|
||||||
if dispatch_semaphore_wait(lock, dispatch_time(DISPATCH_TIME_NOW, Int64(10 * NSEC_PER_MSEC))) != 0 {
|
|
||||||
do {
|
|
||||||
let regex = try NSRegularExpression(pattern: pattern, options:
|
|
||||||
NSRegularExpressionOptions.DotMatchesLineSeparators)
|
|
||||||
self.regex = regex
|
|
||||||
} catch let error as NSError {
|
|
||||||
SwiftRegex.failure("Error in pattern: \(pattern) - \(error)")
|
|
||||||
self.regex = NSRegularExpression()
|
|
||||||
}
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let regex = swiftRegexCache[pattern] {
|
|
||||||
self.regex = regex
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
let regex = try NSRegularExpression(pattern: pattern, options:
|
|
||||||
NSRegularExpressionOptions.DotMatchesLineSeparators)
|
|
||||||
swiftRegexCache[pattern] = regex
|
|
||||||
self.regex = regex
|
|
||||||
} catch let error as NSError {
|
|
||||||
SwiftRegex.failure("Error in pattern: \(pattern) - \(error)")
|
|
||||||
self.regex = NSRegularExpression()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dispatch_semaphore_signal(lock)
|
|
||||||
super.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func failure(message: String) {
|
|
||||||
fatalError("SwiftRegex: \(message)")
|
|
||||||
}
|
|
||||||
|
|
||||||
private var targetRange: NSRange {
|
|
||||||
return NSRange(location: 0,length: target.utf16.count)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func substring(range: NSRange) -> String? {
|
|
||||||
if range.location != NSNotFound {
|
|
||||||
return (target as NSString).substringWithRange(range)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doesMatch(options: NSMatchingOptions!) -> Bool {
|
|
||||||
return range(options).location != NSNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
func range(options: NSMatchingOptions) -> NSRange {
|
|
||||||
return regex.rangeOfFirstMatchInString(target as String, options: [], range: targetRange)
|
|
||||||
}
|
|
||||||
|
|
||||||
func match(options: NSMatchingOptions) -> String? {
|
|
||||||
return substring(range(options))
|
|
||||||
}
|
|
||||||
|
|
||||||
func groups() -> [String]? {
|
|
||||||
return groupsForMatch(regex.firstMatchInString(target as String, options:
|
|
||||||
NSMatchingOptions.WithoutAnchoringBounds, range: targetRange))
|
|
||||||
}
|
|
||||||
|
|
||||||
private func groupsForMatch(match: NSTextCheckingResult?) -> [String]? {
|
|
||||||
guard let match = match else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var groups = [String]()
|
|
||||||
for groupno in 0...regex.numberOfCaptureGroups {
|
|
||||||
if let group = substring(match.rangeAtIndex(groupno)) {
|
|
||||||
groups += [group]
|
|
||||||
} else {
|
|
||||||
groups += ["_"] // avoids bridging problems
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return groups
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript(groupno: Int) -> String? {
|
|
||||||
get {
|
|
||||||
return groups()?[groupno]
|
|
||||||
}
|
|
||||||
|
|
||||||
set(newValue) {
|
|
||||||
if newValue == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for match in Array(matchResults().reverse()) {
|
|
||||||
let replacement = regex.replacementStringForResult(match,
|
|
||||||
inString: target as String, offset: 0, template: newValue!)
|
|
||||||
let mut = NSMutableString(string: target)
|
|
||||||
mut.replaceCharactersInRange(match.rangeAtIndex(groupno), withString: replacement)
|
|
||||||
|
|
||||||
target = mut as String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func matchResults() -> [NSTextCheckingResult] {
|
|
||||||
let matches = regex.matchesInString(target as String, options:
|
|
||||||
NSMatchingOptions.WithoutAnchoringBounds, range: targetRange)
|
|
||||||
as [NSTextCheckingResult]
|
|
||||||
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
|
|
||||||
func ranges() -> [NSRange] {
|
|
||||||
return matchResults().map { $0.range }
|
|
||||||
}
|
|
||||||
|
|
||||||
func matches() -> [String] {
|
|
||||||
return matchResults().map( { self.substring($0.range)!})
|
|
||||||
}
|
|
||||||
|
|
||||||
func allGroups() -> [[String]?] {
|
|
||||||
return matchResults().map { self.groupsForMatch($0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
func dictionary(options: NSMatchingOptions!) -> Dictionary<String,String> {
|
|
||||||
var out = Dictionary<String,String>()
|
|
||||||
for match in matchResults() {
|
|
||||||
out[substring(match.rangeAtIndex(1))!] = substring(match.rangeAtIndex(2))!
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func substituteMatches(substitution: ((NSTextCheckingResult, UnsafeMutablePointer<ObjCBool>) -> String),
|
|
||||||
options:NSMatchingOptions) -> String {
|
|
||||||
let out = NSMutableString()
|
|
||||||
var pos = 0
|
|
||||||
|
|
||||||
regex.enumerateMatchesInString(target as String, options: options, range: targetRange ) {match, flags, stop in
|
|
||||||
let matchRange = match!.range
|
|
||||||
out.appendString( self.substring(NSRange(location:pos, length:matchRange.location-pos))!)
|
|
||||||
out.appendString( substitution(match!, stop) )
|
|
||||||
pos = matchRange.location + matchRange.length
|
|
||||||
}
|
|
||||||
|
|
||||||
out.appendString(substring(NSRange(location:pos, length:targetRange.length-pos))!)
|
|
||||||
|
|
||||||
return out as String
|
|
||||||
}
|
|
||||||
|
|
||||||
var boolValue: Bool {
|
|
||||||
return doesMatch(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
subscript(pattern: String, options: NSRegularExpressionOptions) -> SwiftRegex {
|
|
||||||
return SwiftRegex(target: self, pattern: pattern, options: options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
subscript(pattern: String) -> SwiftRegex {
|
|
||||||
return SwiftRegex(target: self, pattern: pattern, options: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func <~ (left: SwiftRegex, right: String) -> String {
|
|
||||||
return left.substituteMatches({match, stop in
|
|
||||||
return left.regex.replacementStringForResult( match,
|
|
||||||
inString: left.target as String, offset: 0, template: right )
|
|
||||||
}, options: [])
|
|
||||||
}
|
|
||||||
@ -112,6 +112,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
public var security: SSLSecurity?
|
public var security: SSLSecurity?
|
||||||
public var enabledSSLCipherSuites: [SSLCipherSuite]?
|
public var enabledSSLCipherSuites: [SSLCipherSuite]?
|
||||||
public var origin: String?
|
public var origin: String?
|
||||||
|
public var timeout = 5
|
||||||
public var isConnected :Bool {
|
public var isConnected :Bool {
|
||||||
return connected
|
return connected
|
||||||
}
|
}
|
||||||
@ -319,12 +320,12 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
self.mutex.unlock()
|
self.mutex.unlock()
|
||||||
|
|
||||||
let bytes = UnsafePointer<UInt8>(data.bytes)
|
let bytes = UnsafePointer<UInt8>(data.bytes)
|
||||||
var timeout = 5000000 //wait 5 seconds before giving up
|
var out = timeout * 1000000 //wait 5 seconds before giving up
|
||||||
writeQueue.addOperationWithBlock { [weak self] in
|
writeQueue.addOperationWithBlock { [weak self] in
|
||||||
while !outStream.hasSpaceAvailable {
|
while !outStream.hasSpaceAvailable {
|
||||||
usleep(100) //wait until the socket is ready
|
usleep(100) //wait until the socket is ready
|
||||||
timeout -= 100
|
out -= 100
|
||||||
if timeout < 0 {
|
if out < 0 {
|
||||||
self?.cleanupStream()
|
self?.cleanupStream()
|
||||||
self?.doDisconnect(self?.errorWithDetail("write wait timed out", code: 2))
|
self?.doDisconnect(self?.errorWithDetail("write wait timed out", code: 2))
|
||||||
return
|
return
|
||||||
@ -405,25 +406,24 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
///dequeue the incoming input so it is processed in order
|
///dequeue the incoming input so it is processed in order
|
||||||
private func dequeueInput() {
|
private func dequeueInput() {
|
||||||
guard !inputQueue.isEmpty else { return }
|
while !inputQueue.isEmpty {
|
||||||
|
let data = inputQueue[0]
|
||||||
let data = inputQueue[0]
|
var work = data
|
||||||
var work = data
|
if let fragBuffer = fragBuffer {
|
||||||
if let fragBuffer = fragBuffer {
|
let combine = NSMutableData(data: fragBuffer)
|
||||||
let combine = NSMutableData(data: fragBuffer)
|
combine.appendData(data)
|
||||||
combine.appendData(data)
|
work = combine
|
||||||
work = combine
|
self.fragBuffer = nil
|
||||||
self.fragBuffer = nil
|
}
|
||||||
|
let buffer = UnsafePointer<UInt8>(work.bytes)
|
||||||
|
let length = work.length
|
||||||
|
if !connected {
|
||||||
|
processTCPHandshake(buffer, bufferLen: length)
|
||||||
|
} else {
|
||||||
|
processRawMessagesInBuffer(buffer, bufferLen: length)
|
||||||
|
}
|
||||||
|
inputQueue = inputQueue.filter{$0 != data}
|
||||||
}
|
}
|
||||||
let buffer = UnsafePointer<UInt8>(work.bytes)
|
|
||||||
let length = work.length
|
|
||||||
if !connected {
|
|
||||||
processTCPHandshake(buffer, bufferLen: length)
|
|
||||||
} else {
|
|
||||||
processRawMessage(buffer, bufferLen: length)
|
|
||||||
}
|
|
||||||
inputQueue = inputQueue.filter{$0 != data}
|
|
||||||
dequeueInput()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle checking the inital connection status
|
//handle checking the inital connection status
|
||||||
@ -469,7 +469,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
totalSize += 1 //skip the last \n
|
totalSize += 1 //skip the last \n
|
||||||
let restSize = bufferLen - totalSize
|
let restSize = bufferLen - totalSize
|
||||||
if restSize > 0 {
|
if restSize > 0 {
|
||||||
processRawMessage((buffer+totalSize),bufferLen: restSize)
|
processRawMessagesInBuffer(buffer + totalSize, bufferLen: restSize)
|
||||||
}
|
}
|
||||||
return 0 //success
|
return 0 //success
|
||||||
}
|
}
|
||||||
@ -522,12 +522,15 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///process the websocket data
|
/// Process one message at the start of `buffer`. Return another buffer (sharing storage) that contains the leftover contents of `buffer` that I didn't process.
|
||||||
private func processRawMessage(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
@warn_unused_result
|
||||||
|
private func processOneRawMessage(inBuffer buffer: UnsafeBufferPointer<UInt8>) -> UnsafeBufferPointer<UInt8> {
|
||||||
let response = readStack.last
|
let response = readStack.last
|
||||||
|
let baseAddress = buffer.baseAddress
|
||||||
|
let bufferLen = buffer.count
|
||||||
if response != nil && bufferLen < 2 {
|
if response != nil && bufferLen < 2 {
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(buffer: buffer)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if let response = response where response.bytesLeft > 0 {
|
if let response = response where response.bytesLeft > 0 {
|
||||||
var len = response.bytesLeft
|
var len = response.bytesLeft
|
||||||
@ -537,24 +540,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
extra = 0
|
extra = 0
|
||||||
}
|
}
|
||||||
response.bytesLeft -= len
|
response.bytesLeft -= len
|
||||||
response.buffer?.appendData(NSData(bytes: buffer, length: len))
|
response.buffer?.appendData(NSData(bytes: baseAddress, length: len))
|
||||||
processResponse(response)
|
processResponse(response)
|
||||||
let offset = bufferLen - extra
|
return buffer.fromOffset(bufferLen - extra)
|
||||||
if extra > 0 {
|
|
||||||
processExtra((buffer+offset), bufferLen: extra)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else {
|
} else {
|
||||||
let isFin = (FinMask & buffer[0])
|
let isFin = (FinMask & baseAddress[0])
|
||||||
let receivedOpcode = OpCode(rawValue: (OpCodeMask & buffer[0]))
|
let receivedOpcode = OpCode(rawValue: (OpCodeMask & baseAddress[0]))
|
||||||
let isMasked = (MaskMask & buffer[1])
|
let isMasked = (MaskMask & baseAddress[1])
|
||||||
let payloadLen = (PayloadLenMask & buffer[1])
|
let payloadLen = (PayloadLenMask & baseAddress[1])
|
||||||
var offset = 2
|
var offset = 2
|
||||||
if (isMasked > 0 || (RSVMask & buffer[0]) > 0) && receivedOpcode != .Pong {
|
if (isMasked > 0 || (RSVMask & baseAddress[0]) > 0) && receivedOpcode != .Pong {
|
||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(errorWithDetail("masked and rsv data is not currently supported", code: errCode))
|
doDisconnect(errorWithDetail("masked and rsv data is not currently supported", code: errCode))
|
||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping)
|
let isControlFrame = (receivedOpcode == .ConnectionClose || receivedOpcode == .Ping)
|
||||||
if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame &&
|
if !isControlFrame && (receivedOpcode != .BinaryFrame && receivedOpcode != .ContinueFrame &&
|
||||||
@ -562,20 +561,20 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode))
|
doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode))
|
||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if isControlFrame && isFin == 0 {
|
if isControlFrame && isFin == 0 {
|
||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(errorWithDetail("control frames can't be fragmented", code: errCode))
|
doDisconnect(errorWithDetail("control frames can't be fragmented", code: errCode))
|
||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if receivedOpcode == .ConnectionClose {
|
if receivedOpcode == .ConnectionClose {
|
||||||
var code = CloseCode.Normal.rawValue
|
var code = CloseCode.Normal.rawValue
|
||||||
if payloadLen == 1 {
|
if payloadLen == 1 {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
} else if payloadLen > 1 {
|
} else if payloadLen > 1 {
|
||||||
code = WebSocket.readUint16(buffer, offset: offset)
|
code = WebSocket.readUint16(baseAddress, offset: offset)
|
||||||
if code < 1000 || (code > 1003 && code < 1007) || (code > 1011 && code < 3000) {
|
if code < 1000 || (code > 1003 && code < 1007) || (code > 1011 && code < 3000) {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
}
|
}
|
||||||
@ -584,7 +583,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
if payloadLen > 2 {
|
if payloadLen > 2 {
|
||||||
let len = Int(payloadLen-2)
|
let len = Int(payloadLen-2)
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let bytes = UnsafePointer<UInt8>((buffer+offset))
|
let bytes = baseAddress + offset
|
||||||
let str: NSString? = NSString(data: NSData(bytes: bytes, length: len), encoding: NSUTF8StringEncoding)
|
let str: NSString? = NSString(data: NSData(bytes: bytes, length: len), encoding: NSUTF8StringEncoding)
|
||||||
if str == nil {
|
if str == nil {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
@ -593,23 +592,23 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
doDisconnect(errorWithDetail("connection closed by server", code: code))
|
doDisconnect(errorWithDetail("connection closed by server", code: code))
|
||||||
writeError(code)
|
writeError(code)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
if isControlFrame && payloadLen > 125 {
|
if isControlFrame && payloadLen > 125 {
|
||||||
writeError(CloseCode.ProtocolError.rawValue)
|
writeError(CloseCode.ProtocolError.rawValue)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
var dataLength = UInt64(payloadLen)
|
var dataLength = UInt64(payloadLen)
|
||||||
if dataLength == 127 {
|
if dataLength == 127 {
|
||||||
dataLength = WebSocket.readUint64(buffer, offset: offset)
|
dataLength = WebSocket.readUint64(baseAddress, offset: offset)
|
||||||
offset += sizeof(UInt64)
|
offset += sizeof(UInt64)
|
||||||
} else if dataLength == 126 {
|
} else if dataLength == 126 {
|
||||||
dataLength = UInt64(WebSocket.readUint16(buffer, offset: offset))
|
dataLength = UInt64(WebSocket.readUint16(baseAddress, offset: offset))
|
||||||
offset += sizeof(UInt16)
|
offset += sizeof(UInt16)
|
||||||
}
|
}
|
||||||
if bufferLen < offset || UInt64(bufferLen - offset) < dataLength {
|
if bufferLen < offset || UInt64(bufferLen - offset) < dataLength {
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(bytes: baseAddress, length: bufferLen)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
var len = dataLength
|
var len = dataLength
|
||||||
if dataLength > UInt64(bufferLen) {
|
if dataLength > UInt64(bufferLen) {
|
||||||
@ -620,7 +619,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
len = 0
|
len = 0
|
||||||
data = NSData()
|
data = NSData()
|
||||||
} else {
|
} else {
|
||||||
data = NSData(bytes: UnsafePointer<UInt8>((buffer+offset)), length: Int(len))
|
data = NSData(bytes: baseAddress+offset, length: Int(len))
|
||||||
}
|
}
|
||||||
if receivedOpcode == .Pong {
|
if receivedOpcode == .Pong {
|
||||||
if canDispatch {
|
if canDispatch {
|
||||||
@ -630,12 +629,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
s.pongDelegate?.websocketDidReceivePong(s)
|
s.pongDelegate?.websocketDidReceivePong(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let step = Int(offset+numericCast(len))
|
return buffer.fromOffset(offset + Int(len))
|
||||||
let extra = bufferLen-step
|
|
||||||
if extra > 0 {
|
|
||||||
processRawMessage((buffer+step), bufferLen: extra)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
var response = readStack.last
|
var response = readStack.last
|
||||||
if isControlFrame {
|
if isControlFrame {
|
||||||
@ -645,7 +639,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let errCode = CloseCode.ProtocolError.rawValue
|
let errCode = CloseCode.ProtocolError.rawValue
|
||||||
doDisconnect(errorWithDetail("continue frame before a binary or text frame", code: errCode))
|
doDisconnect(errorWithDetail("continue frame before a binary or text frame", code: errCode))
|
||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
var isNew = false
|
var isNew = false
|
||||||
if response == nil {
|
if response == nil {
|
||||||
@ -654,7 +648,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
doDisconnect(errorWithDetail("first frame can't be a continue frame",
|
doDisconnect(errorWithDetail("first frame can't be a continue frame",
|
||||||
code: errCode))
|
code: errCode))
|
||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
isNew = true
|
isNew = true
|
||||||
response = WSResponse()
|
response = WSResponse()
|
||||||
@ -669,7 +663,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame",
|
doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame",
|
||||||
code: errCode))
|
code: errCode))
|
||||||
writeError(errCode)
|
writeError(errCode)
|
||||||
return
|
return emptyBuffer
|
||||||
}
|
}
|
||||||
response!.buffer!.appendData(data)
|
response!.buffer!.appendData(data)
|
||||||
}
|
}
|
||||||
@ -684,20 +678,18 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let step = Int(offset+numericCast(len))
|
let step = Int(offset+numericCast(len))
|
||||||
let extra = bufferLen-step
|
return buffer.fromOffset(step)
|
||||||
if extra > 0 {
|
|
||||||
processExtra((buffer+step), bufferLen: extra)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///process the extra of a buffer
|
/// Process all messages in the buffer if possible.
|
||||||
private func processExtra(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
private func processRawMessagesInBuffer(pointer: UnsafePointer<UInt8>, bufferLen: Int) {
|
||||||
if bufferLen < 2 {
|
var buffer = UnsafeBufferPointer(start: pointer, count: bufferLen)
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
repeat {
|
||||||
} else {
|
buffer = processOneRawMessage(inBuffer: buffer)
|
||||||
processRawMessage(buffer, bufferLen: bufferLen)
|
} while buffer.count >= 2
|
||||||
|
if buffer.count > 0 {
|
||||||
|
fragBuffer = NSData(buffer: buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,6 +827,25 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension NSData {
|
||||||
|
|
||||||
|
convenience init(buffer: UnsafeBufferPointer<UInt8>) {
|
||||||
|
self.init(bytes: buffer.baseAddress, length: buffer.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension UnsafeBufferPointer {
|
||||||
|
|
||||||
|
func fromOffset(offset: Int) -> UnsafeBufferPointer<Element> {
|
||||||
|
return UnsafeBufferPointer<Element>(start: baseAddress.advancedBy(offset), count: count - offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private let emptyBuffer = UnsafeBufferPointer<UInt8>(start: nil, count: 0)
|
||||||
|
|
||||||
|
|
||||||
public class SSLCert {
|
public class SSLCert {
|
||||||
var certData: NSData?
|
var certData: NSData?
|
||||||
var key: SecKeyRef?
|
var key: SecKeyRef?
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user