Merge branch 'socketio/swift-2'
This commit is contained in:
commit
80d7622095
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.AppleDouble
|
.AppleDouble
|
||||||
.LSOverride
|
.LSOverride
|
||||||
|
*.xcodeproj
|
||||||
|
|
||||||
# Icon must end with two \r
|
# Icon must end with two \r
|
||||||
Icon
|
Icon
|
||||||
@ -41,3 +42,5 @@ DerivedData
|
|||||||
*.hmap
|
*.hmap
|
||||||
*.ipa
|
*.ipa
|
||||||
*.xcuserstate
|
*.xcuserstate
|
||||||
|
|
||||||
|
Socket.IO-Test-Server/node_modules/*
|
||||||
|
|||||||
37
README.md
37
README.md
@ -11,7 +11,7 @@ socket.on("connect") {data, ack in
|
|||||||
|
|
||||||
socket.on("currentAmount") {data, ack in
|
socket.on("currentAmount") {data, ack in
|
||||||
if let cur = data?[0] as? Double {
|
if let cur = data?[0] as? Double {
|
||||||
socket.emitWithAck("canUpdate", cur)(timeout: 0) {data in
|
socket.emitWithAck("canUpdate", cur)(timeoutAfter: 0) {data in
|
||||||
socket.emit("update", ["amount": cur + 2.50])
|
socket.emit("update", ["amount": cur + 2.50])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,11 +26,11 @@ socket.connect()
|
|||||||
```objective-c
|
```objective-c
|
||||||
SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:@"localhost:8080" options:nil];
|
SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:@"localhost:8080" options:nil];
|
||||||
|
|
||||||
[socket on:@"connect" callback:^(NSArray* data, void (^ack)(NSArray*)) {
|
[socket onObjectiveC:@"connect" callback:^(NSArray* data, void (^ack)(NSArray*)) {
|
||||||
NSLog(@"socket connected");
|
NSLog(@"socket connected");
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[socket on:@"currentAmount" callback:^(NSArray* data, void (^ack)(NSArray*)) {
|
[socket onObjectiveC:@"currentAmount" callback:^(NSArray* data, void (^ack)(NSArray*)) {
|
||||||
double cur = [[data objectAtIndex:0] floatValue];
|
double cur = [[data objectAtIndex:0] floatValue];
|
||||||
|
|
||||||
[socket emitWithAck:@"canUpdate" withItems:@[@(cur)]](0, ^(NSArray* data) {
|
[socket emitWithAck:@"canUpdate" withItems:@[@(cur)]](0, ^(NSArray* data) {
|
||||||
@ -52,15 +52,16 @@ SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:@"localhost:8
|
|||||||
- Can be used from Objective-C
|
- Can be used from Objective-C
|
||||||
|
|
||||||
##Installation
|
##Installation
|
||||||
Requires Swift 1.2/Xcode 6.3
|
Requires Swift 2/Xcode 7
|
||||||
|
|
||||||
|
If you need Swift 1.2/Xcode 6.3/4 use v2 (Pre-Swift 2 support is no longer maintained)
|
||||||
If you need Swift 1.1/Xcode 6.2 use v1.5.2. (Pre-Swift 1.2 support is no longer maintained)
|
If you need Swift 1.1/Xcode 6.2 use v1.5.2. (Pre-Swift 1.2 support is no longer maintained)
|
||||||
|
|
||||||
Carthage
|
Carthage
|
||||||
-----------------
|
-----------------
|
||||||
Add this line to your `Cartfile`:
|
Add this line to your `Cartfile`:
|
||||||
```
|
```
|
||||||
github "socketio/socket.io-client-swift" ~> 2.3.10 # Or latest version
|
github "socketio/socket.io-client-swift" ~> 2.4.3 # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `carthage update`.
|
Run `carthage update`.
|
||||||
@ -79,7 +80,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', '~> 2.3.10' # Or latest version
|
pod 'Socket.IO-Client-Swift', '~> 2.4.3' # Or latest version
|
||||||
```
|
```
|
||||||
|
|
||||||
Install pods:
|
Install pods:
|
||||||
@ -121,21 +122,23 @@ Options
|
|||||||
- `sessionDelegate: NSURLSessionDelegate` Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. Default is nil.
|
- `sessionDelegate: NSURLSessionDelegate` Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. Default is nil.
|
||||||
- `path: String` - If the server uses a custom path. ex: `"/swift"`. Default is `""`
|
- `path: String` - If the server uses a custom path. ex: `"/swift"`. Default is `""`
|
||||||
- `extraHeaders: [String: String]?` - Adds custom headers to the initial request. Default is nil.
|
- `extraHeaders: [String: String]?` - Adds custom headers to the initial request. Default is nil.
|
||||||
|
- `handleQueue: dispatch_queue_t` - The dispatch queue that handlers are run on. Default is the main queue.
|
||||||
|
|
||||||
Methods
|
Methods
|
||||||
-------
|
-------
|
||||||
1. `on(name:String, callback:((data:NSArray?, ack:AckEmitter?) -> Void))` - Adds a handler for an event. Items are passed by an array. `ack` can be used to send an ack when one is requested. See example.
|
1. `on(name:String, callback:((data:NSArray?, ack:AckEmitter?) -> Void))` - Adds a handler for an event. Items are passed by an array. `ack` can be used to send an ack when one is requested. See example.
|
||||||
2. `onAny(callback:((event:String, items:AnyObject?)) -> Void)` - Adds a handler for all events. It will be called on any received event.
|
2. `onObjectiveC(name:String, callback:((data:NSArray?, ack:AckEmitter?) -> Void))` - Adds a handler for an event. Items are passed by an array. `ack` can be used to send an ack when one is requested. See example.
|
||||||
3. `emit(event:String, _ items:AnyObject...)` - Sends a message. Can send multiple items.
|
3. `onAny(callback:((event:String, items:AnyObject?)) -> Void)` - Adds a handler for all events. It will be called on any received event.
|
||||||
4. `emit(event:String, withItems items:[AnyObject])` - `emit` for Objective-C
|
4. `emit(event:String, _ items:AnyObject...)` - Sends a message. Can send multiple items.
|
||||||
5. `emitWithAck(event:String, _ items:AnyObject...) -> (timeout:UInt64, callback:(NSArray?) -> Void) -> Void` - Sends a message that requests an acknowledgement from the server. Returns a function which you can use to add a handler. See example. Note: The message is not sent until you call the returned function.
|
5. `emit(event:String, withItems items:[AnyObject])` - `emit` for Objective-C
|
||||||
6. `emitWithAck(event:String, withItems items:[AnyObject]) -> (UInt64, (NSArray?) -> Void) -> Void` - `emitWithAck` for Objective-C. Note: The message is not sent until you call the returned function.
|
6. `emitWithAck(event:String, _ items:AnyObject...) -> (timeoutAfter:UInt64, callback:(NSArray?) -> Void) -> Void` - Sends a message that requests an acknowledgement from the server. Returns a function which you can use to add a handler. See example. Note: The message is not sent until you call the returned function.
|
||||||
7. `connect()` - Establishes a connection to the server. A "connect" event is fired upon successful connection.
|
7. `emitWithAck(event:String, withItems items:[AnyObject]) -> (UInt64, (NSArray?) -> Void) -> Void` - `emitWithAck` for Objective-C. Note: The message is not sent until you call the returned function.
|
||||||
8. `connect(#timeoutAfter:Int, withTimeoutHandler handler:(() -> Void)?)` - Connect to the server. If it isn't connected after timeoutAfter seconds, the handler is called.
|
8. `connect()` - Establishes a connection to the server. A "connect" event is fired upon successful connection.
|
||||||
9. `close(#fast:Bool)` - Closes the socket. Once a socket is closed it should not be reopened. Pass true to fast if you're closing from a background task.
|
9. `connect(#timeoutAfter:Int, withTimeoutHandler handler:(() -> Void)?)` - Connect to the server. If it isn't connected after timeoutAfter seconds, the handler is called.
|
||||||
10. `reconnect()` - Causes the client to reconnect to the server.
|
10. `close(#fast:Bool)` - Closes the socket. Once a socket is closed it should not be reopened. Pass true to fast if you're closing from a background task.
|
||||||
11. `joinNamespace()` - Causes the client to join nsp. Shouldn't need to be called unless you change nsp manually.
|
11. `reconnect()` - Causes the client to reconnect to the server.
|
||||||
12. `leaveNamespace()` - Causes the client to leave the nsp and go back to /
|
12. `joinNamespace()` - Causes the client to join nsp. Shouldn't need to be called unless you change nsp manually.
|
||||||
|
13. `leaveNamespace()` - Causes the client to leave the nsp and go back to /
|
||||||
|
|
||||||
Client Events
|
Client Events
|
||||||
------
|
------
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "Socket.IO-Client-Swift"
|
s.name = "Socket.IO-Client-Swift"
|
||||||
s.version = "2.3.10"
|
s.version = "2.4.3"
|
||||||
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.
|
||||||
@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = { "Erik" => "nuclear.ace@gmail.com" }
|
s.author = { "Erik" => "nuclear.ace@gmail.com" }
|
||||||
s.ios.deployment_target = '8.0'
|
s.ios.deployment_target = '8.0'
|
||||||
s.osx.deployment_target = '10.10'
|
s.osx.deployment_target = '10.10'
|
||||||
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v2.3.10' }
|
s.source = { :git => "https://github.com/socketio/socket.io-client-swift.git", :tag => 'v2.4.3' }
|
||||||
s.source_files = "SocketIOClientSwift/**/*.swift"
|
s.source_files = "SocketIOClientSwift/**/*.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
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
572EF21F1B51F16C00EEBB58 /* SocketIO-iOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF21E1B51F16C00EEBB58 /* SocketIO-iOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
572EF21F1B51F16C00EEBB58 /* SocketIO-iOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF21E1B51F16C00EEBB58 /* SocketIO-iOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
572EF2251B51F16C00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2191B51F16C00EEBB58 /* SocketIO.framework */; };
|
572EF2251B51F16C00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2191B51F16C00EEBB58 /* SocketIO.framework */; };
|
||||||
572EF22C1B51F16C00EEBB58 /* SocketIO_iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572EF22B1B51F16C00EEBB58 /* SocketIO_iOSTests.swift */; };
|
|
||||||
572EF23D1B51F18A00EEBB58 /* SocketIO-Mac.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
572EF23D1B51F18A00EEBB58 /* SocketIO-Mac.h in Headers */ = {isa = PBXBuildFile; fileRef = 572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
572EF2431B51F18A00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2381B51F18A00EEBB58 /* SocketIO.framework */; };
|
572EF2431B51F18A00EEBB58 /* SocketIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 572EF2381B51F18A00EEBB58 /* SocketIO.framework */; };
|
||||||
572EF24A1B51F18A00EEBB58 /* SocketIO_MacTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572EF2491B51F18A00EEBB58 /* SocketIO_MacTests.swift */; };
|
572EF24A1B51F18A00EEBB58 /* SocketIO_MacTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572EF2491B51F18A00EEBB58 /* SocketIO_MacTests.swift */; };
|
||||||
@ -39,6 +38,30 @@
|
|||||||
5764DFA01B51F254004FF46E /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF871B51F254004FF46E /* SwiftRegex.swift */; };
|
5764DFA01B51F254004FF46E /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF871B51F254004FF46E /* SwiftRegex.swift */; };
|
||||||
5764DFA11B51F254004FF46E /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF881B51F254004FF46E /* WebSocket.swift */; };
|
5764DFA11B51F254004FF46E /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF881B51F254004FF46E /* WebSocket.swift */; };
|
||||||
5764DFA21B51F254004FF46E /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF881B51F254004FF46E /* WebSocket.swift */; };
|
5764DFA21B51F254004FF46E /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF881B51F254004FF46E /* WebSocket.swift */; };
|
||||||
|
74781D5A1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; };
|
||||||
|
74781D5B1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; };
|
||||||
|
74781D5C1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; };
|
||||||
|
74781D5D1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74781D591B7E83930042CACA /* SocketIOClientStatus.swift */; };
|
||||||
|
941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941A4AB91B67A56C00C42318 /* TestKind.swift */; };
|
||||||
|
94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */; };
|
||||||
|
945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7C1B51F254004FF46E /* SocketAckManager.swift */; };
|
||||||
|
945B65361B5FCEEA0081E995 /* SocketAnyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7D1B51F254004FF46E /* SocketAnyEvent.swift */; };
|
||||||
|
945B65371B5FCEEA0081E995 /* SocketEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7E1B51F254004FF46E /* SocketEngine.swift */; };
|
||||||
|
945B65381B5FCEEA0081E995 /* SocketEngineClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF7F1B51F254004FF46E /* SocketEngineClient.swift */; };
|
||||||
|
945B65391B5FCEEA0081E995 /* SocketEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF801B51F254004FF46E /* SocketEventHandler.swift */; };
|
||||||
|
945B653A1B5FCEEA0081E995 /* SocketFixUTF8.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF811B51F254004FF46E /* SocketFixUTF8.swift */; };
|
||||||
|
945B653B1B5FCEEA0081E995 /* SocketIOClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF821B51F254004FF46E /* SocketIOClient.swift */; };
|
||||||
|
945B653C1B5FCEEA0081E995 /* SocketLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF831B51F254004FF46E /* SocketLogger.swift */; };
|
||||||
|
945B653D1B5FCEEA0081E995 /* SocketPacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF841B51F254004FF46E /* SocketPacket.swift */; };
|
||||||
|
945B653E1B5FCEEA0081E995 /* SocketParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF851B51F254004FF46E /* SocketParser.swift */; };
|
||||||
|
945B653F1B5FCEEA0081E995 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF861B51F254004FF46E /* SocketTypes.swift */; };
|
||||||
|
945B65401B5FCEEA0081E995 /* SwiftRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF871B51F254004FF46E /* SwiftRegex.swift */; };
|
||||||
|
945B65411B5FCEEA0081E995 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5764DF881B51F254004FF46E /* WebSocket.swift */; };
|
||||||
|
945B65431B63D9DB0081E995 /* SocketEmitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 945B65421B63D9DB0081E995 /* SocketEmitTest.swift */; };
|
||||||
|
94ADAC491B652D3300FD79AE /* SocketNamespaceEmitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94ADAC481B652D3300FD79AE /* SocketNamespaceEmitTest.swift */; };
|
||||||
|
94ADAC4B1B6632DD00FD79AE /* SocketAcknowledgementTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94ADAC4A1B6632DD00FD79AE /* SocketAcknowledgementTest.swift */; };
|
||||||
|
94CB8F0B1B6E48B90019ED53 /* SocketTestCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94CB8F0A1B6E48B90019ED53 /* SocketTestCases.swift */; };
|
||||||
|
94CB8F0D1B6E66E60019ED53 /* AbstractSocketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94CB8F0C1B6E66E60019ED53 /* AbstractSocketTest.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -64,7 +87,6 @@
|
|||||||
572EF21E1B51F16C00EEBB58 /* SocketIO-iOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketIO-iOS.h"; sourceTree = "<group>"; };
|
572EF21E1B51F16C00EEBB58 /* SocketIO-iOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketIO-iOS.h"; sourceTree = "<group>"; };
|
||||||
572EF2241B51F16C00EEBB58 /* SocketIO-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SocketIO-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
572EF2241B51F16C00EEBB58 /* SocketIO-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SocketIO-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
572EF22A1B51F16C00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
572EF22A1B51F16C00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
572EF22B1B51F16C00EEBB58 /* SocketIO_iOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketIO_iOSTests.swift; sourceTree = "<group>"; };
|
|
||||||
572EF2381B51F18A00EEBB58 /* SocketIO.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIO.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
572EF2381B51F18A00EEBB58 /* SocketIO.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIO.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
572EF23B1B51F18A00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
572EF23B1B51F18A00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketIO-Mac.h"; sourceTree = "<group>"; };
|
572EF23C1B51F18A00EEBB58 /* SocketIO-Mac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SocketIO-Mac.h"; sourceTree = "<group>"; };
|
||||||
@ -84,6 +106,14 @@
|
|||||||
5764DF861B51F254004FF46E /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketTypes.swift; path = SocketIOClientSwift/SocketTypes.swift; sourceTree = "<group>"; };
|
5764DF861B51F254004FF46E /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketTypes.swift; path = SocketIOClientSwift/SocketTypes.swift; sourceTree = "<group>"; };
|
||||||
5764DF871B51F254004FF46E /* SwiftRegex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftRegex.swift; path = SocketIOClientSwift/SwiftRegex.swift; sourceTree = "<group>"; };
|
5764DF871B51F254004FF46E /* SwiftRegex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftRegex.swift; path = SocketIOClientSwift/SwiftRegex.swift; sourceTree = "<group>"; };
|
||||||
5764DF881B51F254004FF46E /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = SocketIOClientSwift/WebSocket.swift; sourceTree = "<group>"; };
|
5764DF881B51F254004FF46E /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = SocketIOClientSwift/WebSocket.swift; sourceTree = "<group>"; };
|
||||||
|
74781D591B7E83930042CACA /* SocketIOClientStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientStatus.swift; path = SocketIOClientSwift/SocketIOClientStatus.swift; sourceTree = "<group>"; };
|
||||||
|
941A4AB91B67A56C00C42318 /* TestKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestKind.swift; sourceTree = "<group>"; };
|
||||||
|
94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceAcknowledgementTest.swift; sourceTree = "<group>"; };
|
||||||
|
945B65421B63D9DB0081E995 /* SocketEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEmitTest.swift; sourceTree = "<group>"; };
|
||||||
|
94ADAC481B652D3300FD79AE /* SocketNamespaceEmitTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespaceEmitTest.swift; sourceTree = "<group>"; };
|
||||||
|
94ADAC4A1B6632DD00FD79AE /* SocketAcknowledgementTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketAcknowledgementTest.swift; sourceTree = "<group>"; };
|
||||||
|
94CB8F0A1B6E48B90019ED53 /* SocketTestCases.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketTestCases.swift; sourceTree = "<group>"; };
|
||||||
|
94CB8F0C1B6E66E60019ED53 /* AbstractSocketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AbstractSocketTest.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -163,7 +193,13 @@
|
|||||||
572EF2281B51F16C00EEBB58 /* SocketIO-iOSTests */ = {
|
572EF2281B51F16C00EEBB58 /* SocketIO-iOSTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
572EF22B1B51F16C00EEBB58 /* SocketIO_iOSTests.swift */,
|
945B65421B63D9DB0081E995 /* SocketEmitTest.swift */,
|
||||||
|
94ADAC4A1B6632DD00FD79AE /* SocketAcknowledgementTest.swift */,
|
||||||
|
94ADAC481B652D3300FD79AE /* SocketNamespaceEmitTest.swift */,
|
||||||
|
94242BB71B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift */,
|
||||||
|
941A4AB91B67A56C00C42318 /* TestKind.swift */,
|
||||||
|
94CB8F0A1B6E48B90019ED53 /* SocketTestCases.swift */,
|
||||||
|
94CB8F0C1B6E66E60019ED53 /* AbstractSocketTest.swift */,
|
||||||
572EF2291B51F16C00EEBB58 /* Supporting Files */,
|
572EF2291B51F16C00EEBB58 /* Supporting Files */,
|
||||||
);
|
);
|
||||||
path = "SocketIO-iOSTests";
|
path = "SocketIO-iOSTests";
|
||||||
@ -221,6 +257,7 @@
|
|||||||
5764DF801B51F254004FF46E /* SocketEventHandler.swift */,
|
5764DF801B51F254004FF46E /* SocketEventHandler.swift */,
|
||||||
5764DF811B51F254004FF46E /* SocketFixUTF8.swift */,
|
5764DF811B51F254004FF46E /* SocketFixUTF8.swift */,
|
||||||
5764DF821B51F254004FF46E /* SocketIOClient.swift */,
|
5764DF821B51F254004FF46E /* SocketIOClient.swift */,
|
||||||
|
74781D591B7E83930042CACA /* SocketIOClientStatus.swift */,
|
||||||
5764DF831B51F254004FF46E /* SocketLogger.swift */,
|
5764DF831B51F254004FF46E /* SocketLogger.swift */,
|
||||||
5764DF841B51F254004FF46E /* SocketPacket.swift */,
|
5764DF841B51F254004FF46E /* SocketPacket.swift */,
|
||||||
5764DF851B51F254004FF46E /* SocketParser.swift */,
|
5764DF851B51F254004FF46E /* SocketParser.swift */,
|
||||||
@ -413,6 +450,7 @@
|
|||||||
5764DF951B51F254004FF46E /* SocketIOClient.swift in Sources */,
|
5764DF951B51F254004FF46E /* SocketIOClient.swift in Sources */,
|
||||||
5764DF8B1B51F254004FF46E /* SocketAnyEvent.swift in Sources */,
|
5764DF8B1B51F254004FF46E /* SocketAnyEvent.swift in Sources */,
|
||||||
5764DF971B51F254004FF46E /* SocketLogger.swift in Sources */,
|
5764DF971B51F254004FF46E /* SocketLogger.swift in Sources */,
|
||||||
|
74781D5A1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */,
|
||||||
5764DFA11B51F254004FF46E /* WebSocket.swift in Sources */,
|
5764DFA11B51F254004FF46E /* WebSocket.swift in Sources */,
|
||||||
5764DF991B51F254004FF46E /* SocketPacket.swift in Sources */,
|
5764DF991B51F254004FF46E /* SocketPacket.swift in Sources */,
|
||||||
5764DF891B51F254004FF46E /* SocketAckManager.swift in Sources */,
|
5764DF891B51F254004FF46E /* SocketAckManager.swift in Sources */,
|
||||||
@ -424,7 +462,27 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
572EF22C1B51F16C00EEBB58 /* SocketIO_iOSTests.swift in Sources */,
|
945B653E1B5FCEEA0081E995 /* SocketParser.swift in Sources */,
|
||||||
|
945B653D1B5FCEEA0081E995 /* SocketPacket.swift in Sources */,
|
||||||
|
945B653A1B5FCEEA0081E995 /* SocketFixUTF8.swift in Sources */,
|
||||||
|
945B65391B5FCEEA0081E995 /* SocketEventHandler.swift in Sources */,
|
||||||
|
94CB8F0B1B6E48B90019ED53 /* SocketTestCases.swift in Sources */,
|
||||||
|
945B65371B5FCEEA0081E995 /* SocketEngine.swift in Sources */,
|
||||||
|
945B65351B5FCEEA0081E995 /* SocketAckManager.swift in Sources */,
|
||||||
|
941A4ABA1B67A56C00C42318 /* TestKind.swift in Sources */,
|
||||||
|
94CB8F0D1B6E66E60019ED53 /* AbstractSocketTest.swift in Sources */,
|
||||||
|
945B65431B63D9DB0081E995 /* SocketEmitTest.swift in Sources */,
|
||||||
|
945B65401B5FCEEA0081E995 /* SwiftRegex.swift in Sources */,
|
||||||
|
945B653C1B5FCEEA0081E995 /* SocketLogger.swift in Sources */,
|
||||||
|
945B65381B5FCEEA0081E995 /* SocketEngineClient.swift in Sources */,
|
||||||
|
945B65361B5FCEEA0081E995 /* SocketAnyEvent.swift in Sources */,
|
||||||
|
94ADAC4B1B6632DD00FD79AE /* SocketAcknowledgementTest.swift in Sources */,
|
||||||
|
945B653F1B5FCEEA0081E995 /* SocketTypes.swift in Sources */,
|
||||||
|
74781D5B1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */,
|
||||||
|
945B653B1B5FCEEA0081E995 /* SocketIOClient.swift in Sources */,
|
||||||
|
94ADAC491B652D3300FD79AE /* SocketNamespaceEmitTest.swift in Sources */,
|
||||||
|
945B65411B5FCEEA0081E995 /* WebSocket.swift in Sources */,
|
||||||
|
94242BB81B67B0E500AAAC9D /* SocketNamespaceAcknowledgementTest.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -441,6 +499,7 @@
|
|||||||
5764DF961B51F254004FF46E /* SocketIOClient.swift in Sources */,
|
5764DF961B51F254004FF46E /* SocketIOClient.swift in Sources */,
|
||||||
5764DF8C1B51F254004FF46E /* SocketAnyEvent.swift in Sources */,
|
5764DF8C1B51F254004FF46E /* SocketAnyEvent.swift in Sources */,
|
||||||
5764DF981B51F254004FF46E /* SocketLogger.swift in Sources */,
|
5764DF981B51F254004FF46E /* SocketLogger.swift in Sources */,
|
||||||
|
74781D5C1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */,
|
||||||
5764DFA21B51F254004FF46E /* WebSocket.swift in Sources */,
|
5764DFA21B51F254004FF46E /* WebSocket.swift in Sources */,
|
||||||
5764DF9A1B51F254004FF46E /* SocketPacket.swift in Sources */,
|
5764DF9A1B51F254004FF46E /* SocketPacket.swift in Sources */,
|
||||||
5764DF8A1B51F254004FF46E /* SocketAckManager.swift in Sources */,
|
5764DF8A1B51F254004FF46E /* SocketAckManager.swift in Sources */,
|
||||||
@ -453,6 +512,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
572EF24A1B51F18A00EEBB58 /* SocketIO_MacTests.swift in Sources */,
|
572EF24A1B51F18A00EEBB58 /* SocketIO_MacTests.swift in Sources */,
|
||||||
|
74781D5D1B7E83930042CACA /* SocketIOClientStatus.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -485,7 +545,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
PRODUCT_NAME = SocketIO;
|
PRODUCT_NAME = SocketIO;
|
||||||
SWIFT_WHOLE_MODULE_OPTIMIZATION = YES;
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,10 +37,11 @@
|
|||||||
</BuildActionEntries>
|
</BuildActionEntries>
|
||||||
</BuildAction>
|
</BuildAction>
|
||||||
<TestAction
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
buildConfiguration = "Debug">
|
codeCoverageEnabled = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
@ -62,15 +63,18 @@
|
|||||||
ReferencedContainer = "container:Socket.IO-Client-Swift.xcodeproj">
|
ReferencedContainer = "container:Socket.IO-Client-Swift.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
buildConfiguration = "Debug"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
allowLocationSimulation = "YES">
|
allowLocationSimulation = "YES">
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
@ -85,10 +89,10 @@
|
|||||||
</AdditionalOptions>
|
</AdditionalOptions>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
savedToolIdentifier = ""
|
savedToolIdentifier = ""
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
buildConfiguration = "Release"
|
|
||||||
debugDocumentVersioning = "YES">
|
debugDocumentVersioning = "YES">
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
|
|||||||
95
Socket.IO-Test-Server/TestCases.js
Normal file
95
Socket.IO-Test-Server/TestCases.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
var assert = require("assert")
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
basicTest: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
|
||||||
|
},
|
||||||
|
returnData: []
|
||||||
|
},
|
||||||
|
testNull: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert(!inputData)
|
||||||
|
},
|
||||||
|
returnData: [null]
|
||||||
|
},
|
||||||
|
testBinary: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData.toString(), "gakgakgak2")
|
||||||
|
},
|
||||||
|
returnData: [new Buffer("gakgakgak2", "utf-8")]
|
||||||
|
},
|
||||||
|
testArray: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData.length, 2)
|
||||||
|
assert.equal(inputData[0], "test1")
|
||||||
|
assert.equal(inputData[1], "test2")
|
||||||
|
},
|
||||||
|
returnData: [["test3", "test4"]]
|
||||||
|
},
|
||||||
|
testString: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData, "marco")
|
||||||
|
},
|
||||||
|
returnData: ["polo"]
|
||||||
|
},
|
||||||
|
testBool: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert(!inputData)
|
||||||
|
},
|
||||||
|
returnData: [true]
|
||||||
|
},
|
||||||
|
testInteger: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData, 10)
|
||||||
|
},
|
||||||
|
returnData: [20]
|
||||||
|
},
|
||||||
|
testDouble: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData, 1.1)
|
||||||
|
},
|
||||||
|
returnData: [1.2]
|
||||||
|
},
|
||||||
|
testJSON: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData.name, "test")
|
||||||
|
assert.equal(inputData.nestedTest.test, "test")
|
||||||
|
assert.equal(inputData.testArray.length, 1)
|
||||||
|
},
|
||||||
|
returnData: [{testString: "test", testNumber: 15, nestedTest: {test: "test"}, testArray: [1, 1]}]
|
||||||
|
},
|
||||||
|
testJSONWithBuffer: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData.name, "test")
|
||||||
|
assert.equal(inputData.nestedTest.test, "test")
|
||||||
|
assert.equal(inputData.testArray.length, 1)
|
||||||
|
},
|
||||||
|
returnData: [{testString: "test", testNumber: 15, nestedTest: {test: "test"}, testArray: [new Buffer("gakgakgak2", "utf-8"), 1]}]
|
||||||
|
},testUnicode: {
|
||||||
|
assert: function(inputData) {
|
||||||
|
assert.equal(inputData, "🚀")
|
||||||
|
},
|
||||||
|
returnData: ["🚄"]
|
||||||
|
},testMultipleItems: {
|
||||||
|
assert: function(array, object, number, string, bool) {
|
||||||
|
assert.equal(array.length, 2)
|
||||||
|
assert.equal(array[0], "test1")
|
||||||
|
assert.equal(array[1], "test2")
|
||||||
|
assert.equal(number, 15)
|
||||||
|
assert.equal(string, "marco")
|
||||||
|
assert.equal(bool, false)
|
||||||
|
},
|
||||||
|
returnData: [[1, 2], {test: "bob"}, 25, "polo", false]
|
||||||
|
},testMultipleItemsWithBuffer: {
|
||||||
|
assert: function(array, object, number, string, binary) {
|
||||||
|
assert.equal(array.length, 2)
|
||||||
|
assert.equal(array[0], "test1")
|
||||||
|
assert.equal(array[1], "test2")
|
||||||
|
assert.equal(number, 15)
|
||||||
|
assert.equal(string, "marco")
|
||||||
|
assert.equal(binary.toString(), "gakgakgak2")
|
||||||
|
},
|
||||||
|
returnData: [[1, 2], {test: "bob"}, 25, "polo", new Buffer("gakgakgak2")]
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Socket.IO-Test-Server/acknowledgementEvents.js
Normal file
10
Socket.IO-Test-Server/acknowledgementEvents.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
function socketCallback(testKey, socket, testCase) {
|
||||||
|
return function() {
|
||||||
|
testCase.assert.apply(undefined , arguments)
|
||||||
|
var emitArguments = testCase.returnData;
|
||||||
|
var ack = arguments[arguments.length - 1]
|
||||||
|
ack.apply(socket, emitArguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.socketCallback = socketCallback
|
||||||
20
Socket.IO-Test-Server/emitEvents.js
Normal file
20
Socket.IO-Test-Server/emitEvents.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
function socketCallback(testKey, socket, testCase) {
|
||||||
|
return function() {
|
||||||
|
testCase.assert.apply(undefined , arguments)
|
||||||
|
|
||||||
|
var emitArguments = addArrays([testKey + "EmitReturn"], testCase.returnData)
|
||||||
|
socket.emit.apply(socket, emitArguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addArrays(firstArray, secondArray) {
|
||||||
|
var length = secondArray.length
|
||||||
|
var i;
|
||||||
|
for(i = 0; i < length; i++) {
|
||||||
|
firstArray.push(secondArray[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.socketCallback = socketCallback
|
||||||
13
Socket.IO-Test-Server/main.js
Normal file
13
Socket.IO-Test-Server/main.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var app = require('express')()
|
||||||
|
var server = app.listen(8080)
|
||||||
|
var io = require('socket.io')(server)
|
||||||
|
var acknowledgementsEvents = require("./acknowledgementEvents.js")
|
||||||
|
var emitEvents = require("./emitEvents.js")
|
||||||
|
var socketEventRegister = require("./socketEventRegister.js")
|
||||||
|
|
||||||
|
socketEventRegister.register(io, emitEvents.socketCallback, "Emit")
|
||||||
|
socketEventRegister.register(io, acknowledgementsEvents.socketCallback, "Acknowledgement")
|
||||||
|
|
||||||
|
var nsp = io.of("/swift")
|
||||||
|
socketEventRegister.register(nsp, emitEvents.socketCallback, "Emit")
|
||||||
|
socketEventRegister.register(nsp, acknowledgementsEvents.socketCallback, "Acknowledgement")
|
||||||
15
Socket.IO-Test-Server/package.json
Normal file
15
Socket.IO-Test-Server/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "socket.io-client-swift-test-server",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "A simple server to test aginst",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Lukas Schmidt",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.13.1",
|
||||||
|
"socket.io": "^1.3.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Socket.IO-Test-Server/socketEventRegister.js
Normal file
13
Socket.IO-Test-Server/socketEventRegister.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var testCases = require("./TestCases.js")
|
||||||
|
|
||||||
|
function registerSocketForEvents(ioSocket, socketCallback, testKind) {
|
||||||
|
ioSocket.on('connection', function(socket) {
|
||||||
|
var testCase;
|
||||||
|
for(testKey in testCases) {
|
||||||
|
testCase = testCases[testKey]
|
||||||
|
socket.on((testKey + testKind), socketCallback(testKey, socket, testCase))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.register = registerSocketForEvents
|
||||||
111
SocketIO-iOSTests/AbstractSocketTest.swift
Normal file
111
SocketIO-iOSTests/AbstractSocketTest.swift
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// AbstractSocketTest.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 02.08.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class AbstractSocketTest: XCTestCase {
|
||||||
|
static let TEST_TIMEOUT = 8.0
|
||||||
|
var socket:SocketIOClient!
|
||||||
|
var testKind:TestKind?
|
||||||
|
|
||||||
|
override func tearDown() {
|
||||||
|
super.tearDown()
|
||||||
|
socket.close(fast: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openConnection() {
|
||||||
|
let expection = self.expectationWithDescription("connect")
|
||||||
|
XCTAssertTrue(socket.status == SocketIOClientStatus.NotConnected)
|
||||||
|
socket.on("connect") {data, ack in
|
||||||
|
expection.fulfill()
|
||||||
|
}
|
||||||
|
socket.connect()
|
||||||
|
XCTAssertEqual(socket.status, SocketIOClientStatus.Connecting)
|
||||||
|
waitForExpectationsWithTimeout(AbstractSocketTest.TEST_TIMEOUT, handler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateTestName(rawTestName:String) ->String {
|
||||||
|
return rawTestName + testKind!.rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkConnectionStatus() {
|
||||||
|
XCTAssertEqual(socket.status, SocketIOClientStatus.Connected)
|
||||||
|
XCTAssertFalse(socket.secure)
|
||||||
|
}
|
||||||
|
|
||||||
|
func socketMultipleEmit(testName:String, emitData:Array<AnyObject>, callback:NormalCallback){
|
||||||
|
let finalTestname = generateTestName(testName)
|
||||||
|
weak var expection = self.expectationWithDescription(finalTestname)
|
||||||
|
func didGetEmit(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
callback(result, ack)
|
||||||
|
if let expection = expection {
|
||||||
|
expection.fulfill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit(finalTestname, withItems: emitData)
|
||||||
|
socket.on(finalTestname + "Return", callback: didGetEmit)
|
||||||
|
waitForExpectationsWithTimeout(SocketEmitTest.TEST_TIMEOUT, handler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func socketEmit(testName:String, emitData:AnyObject?, callback:NormalCallback){
|
||||||
|
let finalTestname = generateTestName(testName)
|
||||||
|
weak var expection = self.expectationWithDescription(finalTestname)
|
||||||
|
func didGetEmit(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
callback(result, ack)
|
||||||
|
if let expection = expection {
|
||||||
|
expection.fulfill()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on(finalTestname + "Return", callback: didGetEmit)
|
||||||
|
if let emitData = emitData {
|
||||||
|
socket.emit(finalTestname, emitData)
|
||||||
|
} else {
|
||||||
|
socket.emit(finalTestname)
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForExpectationsWithTimeout(SocketEmitTest.TEST_TIMEOUT, handler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func socketAcknwoledgeMultiple(testName:String, Data:Array<AnyObject>, callback:NormalCallback){
|
||||||
|
let finalTestname = generateTestName(testName)
|
||||||
|
weak var expection = self.expectationWithDescription(finalTestname)
|
||||||
|
func didGetResult(result:NSArray?) {
|
||||||
|
callback(result, nil)
|
||||||
|
if let expection = expection {
|
||||||
|
expection.fulfill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emitWithAck(finalTestname, withItems: Data)(timeoutAfter: 5, callback: didGetResult)
|
||||||
|
waitForExpectationsWithTimeout(SocketEmitTest.TEST_TIMEOUT, handler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func socketAcknwoledge(testName:String, Data:AnyObject?, callback:NormalCallback){
|
||||||
|
let finalTestname = generateTestName(testName)
|
||||||
|
weak var expection = self.expectationWithDescription(finalTestname)
|
||||||
|
func didGet(result:NSArray?) {
|
||||||
|
callback(result, nil)
|
||||||
|
if let expection = expection {
|
||||||
|
expection.fulfill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ack:OnAckCallback!
|
||||||
|
if let Data = Data {
|
||||||
|
ack = socket.emitWithAck(finalTestname, Data)
|
||||||
|
} else {
|
||||||
|
ack = socket.emitWithAck(finalTestname)
|
||||||
|
}
|
||||||
|
ack(timeoutAfter: 20, callback: didGet)
|
||||||
|
|
||||||
|
waitForExpectationsWithTimeout(SocketEmitTest.TEST_TIMEOUT, handler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
82
SocketIO-iOSTests/SocketAcknowledgementTest.swift
Normal file
82
SocketIO-iOSTests/SocketAcknowledgementTest.swift
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// SocketAcknowledgementTest.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 27.07.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class SocketAcknowledgementTest: AbstractSocketTest {
|
||||||
|
|
||||||
|
override func setUp() {
|
||||||
|
super.setUp()
|
||||||
|
testKind = TestKind.Acknowledgement
|
||||||
|
socket = SocketIOClient(socketURL: "127.0.0.1:8080", opts: [
|
||||||
|
"reconnects": true, // default true
|
||||||
|
"reconnectAttempts": -1, // default -1
|
||||||
|
"reconnectWait": 5, // default 10
|
||||||
|
"forcePolling": false,
|
||||||
|
"forceWebsockets": false,// default false
|
||||||
|
"path": ""])
|
||||||
|
openConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConnectionStatus() {
|
||||||
|
super.checkConnectionStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBasic() {
|
||||||
|
SocketTestCases.testBasic(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNull() {
|
||||||
|
SocketTestCases.testNull(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBinary() {
|
||||||
|
SocketTestCases.testBinary(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArray() {
|
||||||
|
SocketTestCases.testArray(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testString() {
|
||||||
|
SocketTestCases.testString(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBool() {
|
||||||
|
SocketTestCases.testBool(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInteger() {
|
||||||
|
SocketTestCases.testInteger(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDouble() {
|
||||||
|
SocketTestCases.testDouble(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSON() {
|
||||||
|
SocketTestCases.testJSON(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSONWithBuffer() {
|
||||||
|
SocketTestCases.testJSONWithBuffer(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnicode() {
|
||||||
|
SocketTestCases.testUnicode(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleItems() {
|
||||||
|
SocketTestCases.testMultipleItems(socketAcknwoledgeMultiple)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleWithBuffer() {
|
||||||
|
SocketTestCases.testMultipleItemsWithBuffer(socketAcknwoledgeMultiple)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
88
SocketIO-iOSTests/SocketEmitTest.swift
Normal file
88
SocketIO-iOSTests/SocketEmitTest.swift
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// ConvertedSocketTest.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 25.07.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class SocketEmitTest: AbstractSocketTest {
|
||||||
|
override func setUp() {
|
||||||
|
super.setUp()
|
||||||
|
testKind = TestKind.Emit
|
||||||
|
socket = SocketIOClient(socketURL: "127.0.0.1:8080", opts: [
|
||||||
|
"reconnects": true, // default true
|
||||||
|
"reconnectAttempts": -1, // default -1
|
||||||
|
"reconnectWait": 5, // default 10
|
||||||
|
"forcePolling": false,
|
||||||
|
"forceWebsockets": false,// default false
|
||||||
|
"path": ""]
|
||||||
|
)
|
||||||
|
openConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDown() {
|
||||||
|
socket.close(fast: false)
|
||||||
|
super.tearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConnectionStatus() {
|
||||||
|
super.checkConnectionStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBasic() {
|
||||||
|
SocketTestCases.testBasic(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNull() {
|
||||||
|
SocketTestCases.testNull(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBinary() {
|
||||||
|
SocketTestCases.testBinary(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArray() {
|
||||||
|
SocketTestCases.testArray(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testString() {
|
||||||
|
SocketTestCases.testString(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBool() {
|
||||||
|
SocketTestCases.testBool(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInteger() {
|
||||||
|
SocketTestCases.testInteger(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDouble() {
|
||||||
|
SocketTestCases.testDouble(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSON() {
|
||||||
|
SocketTestCases.testJSON(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSONWithBuffer() {
|
||||||
|
SocketTestCases.testJSONWithBuffer(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnicode() {
|
||||||
|
SocketTestCases.testUnicode(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleItems() {
|
||||||
|
SocketTestCases.testMultipleItems(socketMultipleEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleWithBuffer() {
|
||||||
|
SocketTestCases.testMultipleItemsWithBuffer(socketMultipleEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,36 +0,0 @@
|
|||||||
//
|
|
||||||
// SocketIO_iOSTests.swift
|
|
||||||
// SocketIO-iOSTests
|
|
||||||
//
|
|
||||||
// Created by Nacho Soto on 7/11/15.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import XCTest
|
|
||||||
|
|
||||||
class SocketIO_iOSTests: XCTestCase {
|
|
||||||
|
|
||||||
override func setUp() {
|
|
||||||
super.setUp()
|
|
||||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tearDown() {
|
|
||||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
|
||||||
super.tearDown()
|
|
||||||
}
|
|
||||||
|
|
||||||
func testExample() {
|
|
||||||
// This is an example of a functional test case.
|
|
||||||
XCTAssert(true, "Pass")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testPerformanceExample() {
|
|
||||||
// This is an example of a performance test case.
|
|
||||||
self.measureBlock() {
|
|
||||||
// Put the code you want to measure the time of here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
82
SocketIO-iOSTests/SocketNamespaceAcknowledgementTest.swift
Normal file
82
SocketIO-iOSTests/SocketNamespaceAcknowledgementTest.swift
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// SocketNamespaceAcknowledgementTest.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 28.07.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class SocketNamespaceAcknowledgementTest: AbstractSocketTest {
|
||||||
|
|
||||||
|
override func setUp() {
|
||||||
|
super.setUp()
|
||||||
|
testKind = TestKind.Acknowledgement
|
||||||
|
socket = SocketIOClient(socketURL: "127.0.0.1:8080", opts: [
|
||||||
|
"reconnects": true, // default true
|
||||||
|
"reconnectAttempts": -1, // default -1
|
||||||
|
"reconnectWait": 5, // default 10
|
||||||
|
"forcePolling": false,
|
||||||
|
"forceWebsockets": false,// default false
|
||||||
|
"path": "",
|
||||||
|
"nsp": "/swift"])
|
||||||
|
openConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConnectionStatus() {
|
||||||
|
super.checkConnectionStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBasic() {
|
||||||
|
SocketTestCases.testBasic(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNull() {
|
||||||
|
SocketTestCases.testNull(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBinary() {
|
||||||
|
SocketTestCases.testBinary(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArray() {
|
||||||
|
SocketTestCases.testArray(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testString() {
|
||||||
|
SocketTestCases.testString(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBool() {
|
||||||
|
SocketTestCases.testBool(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInteger() {
|
||||||
|
SocketTestCases.testInteger(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDouble() {
|
||||||
|
SocketTestCases.testDouble(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSON() {
|
||||||
|
SocketTestCases.testJSON(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSONWithBuffer() {
|
||||||
|
SocketTestCases.testJSONWithBuffer(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnicode() {
|
||||||
|
SocketTestCases.testUnicode(socketAcknwoledge)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleItems() {
|
||||||
|
SocketTestCases.testMultipleItems(socketAcknwoledgeMultiple)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleWithBuffer() {
|
||||||
|
SocketTestCases.testMultipleItemsWithBuffer(socketAcknwoledgeMultiple)
|
||||||
|
}
|
||||||
|
}
|
||||||
83
SocketIO-iOSTests/SocketNamespaceEmitTest.swift
Normal file
83
SocketIO-iOSTests/SocketNamespaceEmitTest.swift
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// SocketNamespaceEmitTest.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 26.07.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class SocketNamespaceEmitTest: AbstractSocketTest {
|
||||||
|
|
||||||
|
override func setUp() {
|
||||||
|
super.setUp()
|
||||||
|
testKind = TestKind.Emit
|
||||||
|
socket = SocketIOClient(socketURL: "127.0.0.1:8080", opts: [
|
||||||
|
"reconnects": true, // default true
|
||||||
|
"reconnectAttempts": -1, // default -1
|
||||||
|
"reconnectWait": 5, // default 10
|
||||||
|
"forcePolling": false,
|
||||||
|
"forceWebsockets": false,// default false
|
||||||
|
"path": "",
|
||||||
|
"nsp": "/swift"])
|
||||||
|
openConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConnectionStatus() {
|
||||||
|
super.checkConnectionStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBasic() {
|
||||||
|
SocketTestCases.testBasic(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNull() {
|
||||||
|
SocketTestCases.testNull(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBinary() {
|
||||||
|
SocketTestCases.testBinary(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArray() {
|
||||||
|
SocketTestCases.testArray(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testString() {
|
||||||
|
SocketTestCases.testString(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBool() {
|
||||||
|
SocketTestCases.testBool(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInteger() {
|
||||||
|
SocketTestCases.testInteger(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDouble() {
|
||||||
|
SocketTestCases.testDouble(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSON() {
|
||||||
|
SocketTestCases.testJSON(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testJSONWithBuffer() {
|
||||||
|
SocketTestCases.testJSONWithBuffer(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUnicode() {
|
||||||
|
SocketTestCases.testUnicode(socketEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleItems() {
|
||||||
|
SocketTestCases.testMultipleItems(socketMultipleEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMultipleWithBuffer() {
|
||||||
|
SocketTestCases.testMultipleItemsWithBuffer(socketMultipleEmit)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
246
SocketIO-iOSTests/SocketTestCases.swift
Normal file
246
SocketIO-iOSTests/SocketTestCases.swift
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
//
|
||||||
|
// SocketTestCases.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 02.08.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class SocketTestCases: NSObject {
|
||||||
|
typealias SocketSendFunction = (testName:String, emitData:AnyObject?, callback:NormalCallback)->()
|
||||||
|
|
||||||
|
static func testBasic(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "basicTest"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: nil, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testNull(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testNull"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let _ = result?.firstObject as? NSNull {
|
||||||
|
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
XCTFail("Should have NSNull as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: NSNull(), callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testBinary(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testBinary"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let data = result?.firstObject as? NSData {
|
||||||
|
let string = NSString(data: data, encoding: NSUTF8StringEncoding)!
|
||||||
|
XCTAssertEqual(string, "gakgakgak2")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSData as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = NSString(string: "gakgakgak2").dataUsingEncoding(NSUTF8StringEncoding)!
|
||||||
|
abstractSocketSend(testName: testName, emitData: data, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testArray(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testArray"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let array = result?.firstObject as? NSArray {
|
||||||
|
XCTAssertEqual(array.count, 2)
|
||||||
|
XCTAssertEqual((array.firstObject! as! String), "test3")
|
||||||
|
XCTAssertEqual((array.lastObject! as! String), "test4")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSArray as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: ["test1", "test2"], callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testString(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testString"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let string = result?.firstObject as? String {
|
||||||
|
XCTAssertEqual(string, "polo")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have String as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: "marco", callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testBool(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testBool"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let bool = result?.firstObject as? NSNumber {
|
||||||
|
XCTAssertTrue(bool.boolValue)
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Boolean as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: false, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testInteger(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testInteger"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let integer = result?.firstObject as? Int {
|
||||||
|
XCTAssertEqual(integer, 20)
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Integer as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: 10, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testDouble(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testDouble"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let double = result?.firstObject as? NSNumber {
|
||||||
|
XCTAssertEqual(double.floatValue, 1.2)
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Double as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: 1.1, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testJSONWithBuffer(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testJSONWithBuffer"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let json = result?.firstObject as? NSDictionary {
|
||||||
|
XCTAssertEqual((json.valueForKey("testString")! as! String), "test")
|
||||||
|
XCTAssertEqual((json.valueForKey("testNumber")! as! Int), 15)
|
||||||
|
XCTAssertEqual((json.valueForKey("testArray")! as! Array<AnyObject>).count, 2)
|
||||||
|
XCTAssertEqual(((json.valueForKey("testArray")! as! Array<AnyObject>).last! as! Int), 1)
|
||||||
|
let string = NSString(data: (json.valueForKey("testArray")! as! Array<AnyObject>).first! as! NSData, encoding: NSUTF8StringEncoding)!
|
||||||
|
XCTAssertEqual(string, "gakgakgak2")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSDictionary as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let json = ["name": "test", "testArray": ["hallo"], "nestedTest": ["test": "test"], "number": 15]
|
||||||
|
|
||||||
|
abstractSocketSend(testName: testName, emitData: json, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testJSON(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testJSON"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let json = result?.firstObject as? NSDictionary {
|
||||||
|
XCTAssertEqual((json.valueForKey("testString")! as! String), "test")
|
||||||
|
XCTAssertEqual(json.valueForKey("testNumber")! as? Int, 15)
|
||||||
|
XCTAssertEqual((json.valueForKey("testArray")! as! Array<AnyObject>).count, 2)
|
||||||
|
XCTAssertEqual((json.valueForKey("testArray")! as! Array<AnyObject>).first! as? Int, 1)
|
||||||
|
XCTAssertEqual((json.valueForKey("testArray")! as! Array<AnyObject>).last! as? Int, 1)
|
||||||
|
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSDictionary as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let json = ["name": "test", "testArray": ["hallo"], "nestedTest": ["test": "test"], "number": 15]
|
||||||
|
|
||||||
|
abstractSocketSend(testName: testName, emitData: json, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testUnicode(abstractSocketSend:SocketSendFunction) {
|
||||||
|
let testName = "testUnicode"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
if let unicode = result?.firstObject as? String {
|
||||||
|
XCTAssertEqual(unicode, "🚄")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have String as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstractSocketSend(testName: testName, emitData: "🚀", callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testMultipleItemsWithBuffer(abstractSocketMultipleSend:(testName:String, emitData:Array<AnyObject>, callback:NormalCallback)->()) {
|
||||||
|
let testName = "testMultipleItemsWithBuffer"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
XCTAssertEqual(result!.count, 5)
|
||||||
|
if result!.count != 5 {
|
||||||
|
XCTFail("Fatal Fail. Lost some Data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let array = result?.firstObject as? Array<AnyObject> {
|
||||||
|
XCTAssertEqual((array.last! as! Int), 2)
|
||||||
|
XCTAssertEqual((array.first! as! Int), 1)
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Array as result")
|
||||||
|
}
|
||||||
|
if let dict = result?[1] as? NSDictionary {
|
||||||
|
XCTAssertEqual((dict.valueForKey("test") as! String), "bob")
|
||||||
|
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSDictionary as result")
|
||||||
|
}
|
||||||
|
if let number = result?[2] as? Int {
|
||||||
|
XCTAssertEqual(number, 25)
|
||||||
|
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Integer as result")
|
||||||
|
}
|
||||||
|
if let string = result?[3] as? String {
|
||||||
|
XCTAssertEqual(string, "polo")
|
||||||
|
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Integer as result")
|
||||||
|
}
|
||||||
|
if let data = result?[4] as? NSData {
|
||||||
|
let string = NSString(data: data, encoding: NSUTF8StringEncoding)!
|
||||||
|
XCTAssertEqual(string, "gakgakgak2")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSData as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = NSString(string: "gakgakgak2").dataUsingEncoding(NSUTF8StringEncoding)!
|
||||||
|
let emitArray = [["test1", "test2"], ["test": "test"], 15, "marco", data]
|
||||||
|
abstractSocketMultipleSend(testName: testName, emitData: emitArray, callback: didGetResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func testMultipleItems(abstractSocketMultipleSend:(testName:String, emitData:Array<AnyObject>, callback:NormalCallback)->()) {
|
||||||
|
let testName = "testMultipleItems"
|
||||||
|
func didGetResult(result:NSArray?, ack:AckEmitter?) {
|
||||||
|
XCTAssertEqual(result!.count, 5)
|
||||||
|
if result!.count != 5 {
|
||||||
|
XCTFail("Fatal Fail. Lost some Data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let array = result?.firstObject as? Array<AnyObject> {
|
||||||
|
XCTAssertEqual((array.last! as! Int), 2)
|
||||||
|
XCTAssertEqual((array.first! as! Int), 1)
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Array as result")
|
||||||
|
}
|
||||||
|
if let dict = result?[1] as? NSDictionary {
|
||||||
|
XCTAssertEqual((dict.valueForKey("test") as! String), "bob")
|
||||||
|
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSDictionary as result")
|
||||||
|
}
|
||||||
|
if let number = result?[2] as? Int {
|
||||||
|
XCTAssertEqual(number, 25)
|
||||||
|
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Integer as result")
|
||||||
|
}
|
||||||
|
if let string = result?[3] as? String {
|
||||||
|
XCTAssertEqual(string, "polo")
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have Integer as result")
|
||||||
|
}
|
||||||
|
if let bool = result?[4] as? NSNumber {
|
||||||
|
XCTAssertFalse(bool.boolValue)
|
||||||
|
}else {
|
||||||
|
XCTFail("Should have NSNumber as result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let emitArray = [["test1", "test2"], ["test": "test"], 15, "marco", false]
|
||||||
|
abstractSocketMultipleSend(testName: testName, emitData: emitArray, callback: didGetResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
SocketIO-iOSTests/TestKind.swift
Normal file
13
SocketIO-iOSTests/TestKind.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// TestKind.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Lukas Schmidt on 28.07.15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum TestKind: String {
|
||||||
|
case Emit, Acknowledgement
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketAckManager.swift
|
// SocketAckManager.swift
|
||||||
// SocketIO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 4/3/15.
|
// Created by Erik Little on 4/3/15.
|
||||||
//
|
//
|
||||||
@ -25,38 +25,38 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
private struct SocketAck: Hashable, Equatable {
|
private struct SocketAck: Hashable, Equatable {
|
||||||
let ack:Int
|
let ack: Int
|
||||||
var callback:AckCallback!
|
var callback: AckCallback!
|
||||||
var hashValue:Int {
|
var hashValue: Int {
|
||||||
return ack.hashValue
|
return ack.hashValue
|
||||||
}
|
}
|
||||||
|
|
||||||
init(ack:Int) {
|
init(ack: Int) {
|
||||||
self.ack = ack
|
self.ack = ack
|
||||||
}
|
}
|
||||||
|
|
||||||
init(ack:Int, callback:AckCallback) {
|
init(ack: Int, callback: AckCallback) {
|
||||||
self.ack = ack
|
self.ack = ack
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func <(lhs:SocketAck, rhs:SocketAck) -> Bool {
|
private func <(lhs: SocketAck, rhs: SocketAck) -> Bool {
|
||||||
return lhs.ack < rhs.ack
|
return lhs.ack < rhs.ack
|
||||||
}
|
}
|
||||||
|
|
||||||
private func ==(lhs:SocketAck, rhs:SocketAck) -> Bool {
|
private func ==(lhs: SocketAck, rhs: SocketAck) -> Bool {
|
||||||
return lhs.ack == rhs.ack
|
return lhs.ack == rhs.ack
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SocketAckManager {
|
struct SocketAckManager {
|
||||||
private var acks = Set<SocketAck>(minimumCapacity: 1)
|
private var acks = Set<SocketAck>(minimumCapacity: 1)
|
||||||
|
|
||||||
mutating func addAck(ack:Int, callback:AckCallback) {
|
mutating func addAck(ack: Int, callback: AckCallback) {
|
||||||
acks.insert(SocketAck(ack: ack, callback: callback))
|
acks.insert(SocketAck(ack: ack, callback: callback))
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func executeAck(ack:Int, items:[AnyObject]?) {
|
mutating func executeAck(ack: Int, items: [AnyObject]?) {
|
||||||
let callback = acks.remove(SocketAck(ack: ack))
|
let callback = acks.remove(SocketAck(ack: ack))
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue()) {
|
dispatch_async(dispatch_get_main_queue()) {
|
||||||
@ -64,7 +64,7 @@ struct SocketAckManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func timeoutAck(ack:Int) {
|
mutating func timeoutAck(ack: Int) {
|
||||||
let callback = acks.remove(SocketAck(ack: ack))
|
let callback = acks.remove(SocketAck(ack: ack))
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue()) {
|
dispatch_async(dispatch_get_main_queue()) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketAnyEvent.swift
|
// SocketAnyEvent.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 3/28/15.
|
// Created by Erik Little on 3/28/15.
|
||||||
//
|
//
|
||||||
@ -24,11 +24,14 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objc public final class SocketAnyEvent {
|
@objc public final class SocketAnyEvent: NSObject {
|
||||||
public let event:String!
|
public let event: String!
|
||||||
public let items:NSArray?
|
public let items: NSArray?
|
||||||
|
override public var description: String {
|
||||||
|
return "SocketAnyEvent: Event: \(event) items: \(items ?? nil)"
|
||||||
|
}
|
||||||
|
|
||||||
init(event:String, items:NSArray?) {
|
init(event: String, items: NSArray?) {
|
||||||
self.event = event
|
self.event = event
|
||||||
self.items = items
|
self.items = items
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketEngine.swift
|
// SocketEngine.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 3/3/15.
|
// Created by Erik Little on 3/3/15.
|
||||||
//
|
//
|
||||||
@ -25,7 +25,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
||||||
private typealias Probe = (msg:String, type:PacketType, data:ContiguousArray<NSData>?)
|
private typealias Probe = (msg: String, type: PacketType, data: [NSData]?)
|
||||||
private typealias ProbeWaitQueue = [Probe]
|
private typealias ProbeWaitQueue = [Probe]
|
||||||
|
|
||||||
private let allowedCharacterSet = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?%#[]\" {}").invertedSet
|
private let allowedCharacterSet = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?%#[]\" {}").invertedSet
|
||||||
@ -33,16 +33,15 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
private let emitQueue = dispatch_queue_create("engineEmitQueue", DISPATCH_QUEUE_SERIAL)
|
private let emitQueue = dispatch_queue_create("engineEmitQueue", DISPATCH_QUEUE_SERIAL)
|
||||||
private let parseQueue = dispatch_queue_create("engineParseQueue", DISPATCH_QUEUE_SERIAL)
|
private let parseQueue = dispatch_queue_create("engineParseQueue", DISPATCH_QUEUE_SERIAL)
|
||||||
private let handleQueue = dispatch_queue_create("engineHandleQueue", DISPATCH_QUEUE_SERIAL)
|
private let handleQueue = dispatch_queue_create("engineHandleQueue", DISPATCH_QUEUE_SERIAL)
|
||||||
private let session:NSURLSession!
|
private let session: NSURLSession!
|
||||||
|
|
||||||
private var closed = false
|
private var closed = false
|
||||||
private var _connected = false
|
private var extraHeaders: [String: String]?
|
||||||
private var extraHeaders:[String: String]?
|
|
||||||
private var fastUpgrade = false
|
private var fastUpgrade = false
|
||||||
private var forcePolling = false
|
private var forcePolling = false
|
||||||
private var forceWebsockets = false
|
private var forceWebsockets = false
|
||||||
private var pingInterval:Double?
|
private var pingInterval: Double?
|
||||||
private var pingTimer:NSTimer?
|
private var pingTimer: NSTimer?
|
||||||
private var pingTimeout = 0.0 {
|
private var pingTimeout = 0.0 {
|
||||||
didSet {
|
didSet {
|
||||||
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
|
pongsMissedMax = Int(pingTimeout / (pingInterval ?? 25))
|
||||||
@ -51,45 +50,31 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
private var pongsMissed = 0
|
private var pongsMissed = 0
|
||||||
private var pongsMissedMax = 0
|
private var pongsMissedMax = 0
|
||||||
private var postWait = [String]()
|
private var postWait = [String]()
|
||||||
private var _polling = true
|
|
||||||
private var probing = false
|
private var probing = false
|
||||||
private var probeWait = ProbeWaitQueue()
|
private var probeWait = ProbeWaitQueue()
|
||||||
private var waitingForPoll = false
|
private var waitingForPoll = false
|
||||||
private var waitingForPost = false
|
private var waitingForPost = false
|
||||||
private var _websocket = false
|
|
||||||
private var websocketConnected = false
|
private var websocketConnected = false
|
||||||
|
|
||||||
let logType = "SocketEngine"
|
let logType = "SocketEngine"
|
||||||
|
|
||||||
var connected:Bool {
|
private(set) var connected = false
|
||||||
return _connected
|
private(set) var polling = true
|
||||||
}
|
private(set) var websocket = false
|
||||||
weak var client:SocketEngineClient?
|
|
||||||
var cookies:[NSHTTPCookie]?
|
weak var client: SocketEngineClient?
|
||||||
var log = false
|
var cookies: [NSHTTPCookie]?
|
||||||
var polling:Bool {
|
|
||||||
return _polling
|
|
||||||
}
|
|
||||||
var sid = ""
|
var sid = ""
|
||||||
var socketPath = ""
|
var socketPath = ""
|
||||||
var urlPolling:String?
|
var urlPolling: String?
|
||||||
var urlWebSocket:String?
|
var urlWebSocket: String?
|
||||||
var websocket:Bool {
|
|
||||||
return _websocket
|
|
||||||
}
|
|
||||||
var ws:WebSocket?
|
var ws:WebSocket?
|
||||||
|
|
||||||
public enum PacketType:Int {
|
public enum PacketType: Int {
|
||||||
case OPEN = 0
|
case Open, Close, Ping, Pong, Message, Upgrade, Noop
|
||||||
case CLOSE = 1
|
|
||||||
case PING = 2
|
|
||||||
case PONG = 3
|
|
||||||
case MESSAGE = 4
|
|
||||||
case UPGRADE = 5
|
|
||||||
case NOOP = 6
|
|
||||||
|
|
||||||
init?(str:String?) {
|
init?(str: String?) {
|
||||||
if let value = str?.toInt(), raw = PacketType(rawValue: value) {
|
if let value = Int(str ?? ""), raw = PacketType(rawValue: value) {
|
||||||
self = raw
|
self = raw
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
@ -97,18 +82,17 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(client:SocketEngineClient, sessionDelegate:NSURLSessionDelegate?) {
|
public init(client: SocketEngineClient, sessionDelegate: NSURLSessionDelegate?) {
|
||||||
self.client = client
|
self.client = client
|
||||||
self.session = NSURLSession(configuration: NSURLSessionConfiguration.ephemeralSessionConfiguration(),
|
self.session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
|
||||||
delegate: sessionDelegate, delegateQueue: workQueue)
|
delegate: sessionDelegate, delegateQueue: workQueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(client:SocketEngineClient, opts:NSDictionary?) {
|
public convenience init(client: SocketEngineClient, opts: NSDictionary?) {
|
||||||
self.init(client: client, sessionDelegate: opts?["sessionDelegate"] as? NSURLSessionDelegate)
|
self.init(client: client, sessionDelegate: opts?["sessionDelegate"] as? NSURLSessionDelegate)
|
||||||
forceWebsockets = opts?["forceWebsockets"] as? Bool ?? false
|
forceWebsockets = opts?["forceWebsockets"] as? Bool ?? false
|
||||||
forcePolling = opts?["forcePolling"] as? Bool ?? false
|
forcePolling = opts?["forcePolling"] as? Bool ?? false
|
||||||
cookies = opts?["cookies"] as? [NSHTTPCookie]
|
cookies = opts?["cookies"] as? [NSHTTPCookie]
|
||||||
log = opts?["log"] as? Bool ?? false
|
|
||||||
socketPath = opts?["path"] as? String ?? ""
|
socketPath = opts?["path"] as? String ?? ""
|
||||||
extraHeaders = opts?["extraHeaders"] as? [String: String]
|
extraHeaders = opts?["extraHeaders"] as? [String: String]
|
||||||
}
|
}
|
||||||
@ -117,7 +101,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
SocketLogger.log("Engine is being deinit", client: self)
|
SocketLogger.log("Engine is being deinit", client: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func close(#fast:Bool) {
|
public func close(fast fast: Bool) {
|
||||||
SocketLogger.log("Engine is being closed. Fast: %@", client: self, args: fast)
|
SocketLogger.log("Engine is being closed. Fast: %@", client: self, args: fast)
|
||||||
|
|
||||||
pingTimer?.invalidate()
|
pingTimer?.invalidate()
|
||||||
@ -126,18 +110,18 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
ws?.disconnect()
|
ws?.disconnect()
|
||||||
|
|
||||||
if fast || polling {
|
if fast || polling {
|
||||||
write("", withType: PacketType.CLOSE, withData: nil)
|
write("", withType: PacketType.Close, withData: nil)
|
||||||
client?.engineDidClose("Disconnect")
|
client?.engineDidClose("Disconnect")
|
||||||
}
|
}
|
||||||
|
|
||||||
stopPolling()
|
stopPolling()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createBinaryDataForSend(data:NSData) -> (NSData?, String?) {
|
private func createBinaryDataForSend(data: NSData) -> (NSData?, String?) {
|
||||||
if websocket {
|
if websocket {
|
||||||
var byteArray = [UInt8](count: 1, repeatedValue: 0x0)
|
var byteArray = [UInt8](count: 1, repeatedValue: 0x0)
|
||||||
byteArray[0] = 4
|
byteArray[0] = 4
|
||||||
var mutData = NSMutableData(bytes: &byteArray, length: 1)
|
let mutData = NSMutableData(bytes: &byteArray, length: 1)
|
||||||
|
|
||||||
mutData.appendData(data)
|
mutData.appendData(data)
|
||||||
|
|
||||||
@ -151,16 +135,16 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createURLs(params:[String: AnyObject]?) -> (String?, String?) {
|
private func createURLs(params: [String: AnyObject]?) -> (String?, String?) {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return (nil, nil)
|
return (nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = socketPath == "" ? "/socket.io" : socketPath
|
let path = socketPath == "" ? "/socket.io" : socketPath
|
||||||
|
|
||||||
var url = "\(client!.socketURL)\(path)/?transport="
|
let url = "\(client!.socketURL)\(path)/?transport="
|
||||||
var urlPolling:String
|
var urlPolling: String
|
||||||
var urlWebSocket:String
|
var urlWebSocket: String
|
||||||
|
|
||||||
if client!.secure {
|
if client!.secure {
|
||||||
urlPolling = "https://" + url + "polling"
|
urlPolling = "https://" + url + "polling"
|
||||||
@ -193,7 +177,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
return (urlPolling, urlWebSocket)
|
return (urlPolling, urlWebSocket)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createWebsocket(andConnect connect:Bool) {
|
private func createWebsocket(andConnect connect: Bool) {
|
||||||
let wsUrl = urlWebSocket! + (sid == "" ? "" : "&sid=\(sid)")
|
let wsUrl = urlWebSocket! + (sid == "" ? "" : "&sid=\(sid)")
|
||||||
|
|
||||||
ws = WebSocket(url: NSURL(string: wsUrl)!,
|
ws = WebSocket(url: NSURL(string: wsUrl)!,
|
||||||
@ -219,9 +203,9 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
"we'll probably disconnect soon. You should report this.", client: self)
|
"we'll probably disconnect soon. You should report this.", client: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWebSocketMessage("", withType: PacketType.UPGRADE, datas: nil)
|
sendWebSocketMessage("", withType: PacketType.Upgrade, datas: nil)
|
||||||
_websocket = true
|
websocket = true
|
||||||
_polling = false
|
polling = false
|
||||||
fastUpgrade = false
|
fastUpgrade = false
|
||||||
probing = false
|
probing = false
|
||||||
flushProbeWait()
|
flushProbeWait()
|
||||||
@ -249,7 +233,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
doRequest(req)
|
doRequest(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func doRequest(req:NSMutableURLRequest) {
|
private func doRequest(req: NSMutableURLRequest) {
|
||||||
if !polling {
|
if !polling {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -260,18 +244,18 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
session.dataTaskWithRequest(req) {[weak self] data, res, err in
|
session.dataTaskWithRequest(req) {[weak self] data, res, err in
|
||||||
if let this = self {
|
if let this = self {
|
||||||
if err != nil {
|
if err != nil || data == nil {
|
||||||
if this.polling {
|
if this.polling {
|
||||||
this.handlePollingFailed(err.localizedDescription)
|
this.handlePollingFailed(err?.localizedDescription ?? "Error")
|
||||||
} else {
|
} else {
|
||||||
SocketLogger.err(err.localizedDescription, client: this)
|
SocketLogger.err(err?.localizedDescription ?? "Error", client: this)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketLogger.log("Got polling response", client: this)
|
SocketLogger.log("Got polling response", client: this)
|
||||||
|
|
||||||
if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
|
if let str = NSString(data: data!, encoding: NSUTF8StringEncoding) as? String {
|
||||||
dispatch_async(this.parseQueue) {[weak this] in
|
dispatch_async(this.parseQueue) {[weak this] in
|
||||||
this?.parsePollingMessage(str)
|
this?.parsePollingMessage(str)
|
||||||
}
|
}
|
||||||
@ -316,7 +300,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
var postStr = ""
|
var postStr = ""
|
||||||
|
|
||||||
for packet in postWait {
|
for packet in postWait {
|
||||||
let len = count(packet)
|
let len = packet.characters.count
|
||||||
|
|
||||||
postStr += "\(len):\(packet)"
|
postStr += "\(len):\(packet)"
|
||||||
}
|
}
|
||||||
@ -325,8 +309,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
let req = NSMutableURLRequest(URL: NSURL(string: urlPolling! + "&sid=\(sid)")!)
|
let req = NSMutableURLRequest(URL: NSURL(string: urlPolling! + "&sid=\(sid)")!)
|
||||||
|
|
||||||
if cookies != nil {
|
if let cookies = cookies {
|
||||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
|
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies)
|
||||||
req.allHTTPHeaderFields = headers
|
req.allHTTPHeaderFields = headers
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,10 +330,10 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
session.dataTaskWithRequest(req) {[weak self] data, res, err in
|
session.dataTaskWithRequest(req) {[weak self] data, res, err in
|
||||||
if let this = self {
|
if let this = self {
|
||||||
if err != nil && this.polling {
|
if err != nil && this.polling {
|
||||||
this.handlePollingFailed(err.localizedDescription)
|
this.handlePollingFailed(err?.localizedDescription ?? "Error")
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
NSLog(err.localizedDescription)
|
NSLog(err?.localizedDescription ?? "Error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,58 +359,60 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handleClose() {
|
private func handleClose() {
|
||||||
if polling {
|
if let client = client where polling == true {
|
||||||
client?.engineDidClose("Disconnect")
|
client.engineDidClose("Disconnect")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func checkIfMessageIsBase64Binary(var message:String) {
|
private func checkIfMessageIsBase64Binary(var message: String) {
|
||||||
if message.hasPrefix("b4") {
|
if message.hasPrefix("b4") {
|
||||||
// binary in base64 string
|
// binary in base64 string
|
||||||
message.removeRange(Range<String.Index>(start: message.startIndex,
|
message.removeRange(Range<String.Index>(start: message.startIndex,
|
||||||
end: advance(message.startIndex, 2)))
|
end: message.startIndex.advancedBy(2)))
|
||||||
|
|
||||||
if let data = NSData(base64EncodedString: message,
|
if let data = NSData(base64EncodedString: message,
|
||||||
options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters), client = client {
|
options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters) {
|
||||||
dispatch_async(client.handleQueue) {[weak self] in
|
client?.parseBinaryData(data)
|
||||||
self?.client?.parseBinaryData(data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleMessage(message:String) {
|
private func handleMessage(message: String) {
|
||||||
if let client = client {
|
|
||||||
dispatch_async(client.handleQueue) {[weak client] in
|
|
||||||
client?.parseSocketMessage(message)
|
client?.parseSocketMessage(message)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleNOOP() {
|
private func handleNOOP() {
|
||||||
doPoll()
|
doPoll()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleOpen(openData:String) {
|
private func handleOpen(openData: String) {
|
||||||
var err:NSError?
|
|
||||||
let mesData = openData.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
|
let mesData = openData.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
|
||||||
|
do {
|
||||||
|
let json = try NSJSONSerialization.JSONObjectWithData(mesData,
|
||||||
|
options: NSJSONReadingOptions.AllowFragments) as? NSDictionary
|
||||||
|
if let sid = json?["sid"] as? String {
|
||||||
|
let upgradeWs: Bool
|
||||||
|
|
||||||
if let json = NSJSONSerialization.JSONObjectWithData(mesData,
|
|
||||||
options: NSJSONReadingOptions.AllowFragments,
|
|
||||||
error: &err) as? NSDictionary, sid = json["sid"] as? String {
|
|
||||||
self.sid = sid
|
self.sid = sid
|
||||||
_connected = true
|
connected = true
|
||||||
|
|
||||||
if !forcePolling && !forceWebsockets {
|
if let upgrades = json?["upgrades"] as? [String] {
|
||||||
createWebsocket(andConnect: true)
|
upgradeWs = upgrades.filter {$0 == "websocket"}.count != 0
|
||||||
|
} else {
|
||||||
|
upgradeWs = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if let pingInterval = json["pingInterval"] as? Double, pingTimeout = json["pingTimeout"] as? Double {
|
if let pingInterval = json?["pingInterval"] as? Double, pingTimeout = json?["pingTimeout"] as? Double {
|
||||||
self.pingInterval = pingInterval / 1000.0
|
self.pingInterval = pingInterval / 1000.0
|
||||||
self.pingTimeout = pingTimeout / 1000.0
|
self.pingTimeout = pingTimeout / 1000.0
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
client?.didError("Engine failed to handshake")
|
if !forcePolling && !forceWebsockets && upgradeWs {
|
||||||
|
createWebsocket(andConnect: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
SocketLogger.err("Error parsing open packet", client: self)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +423,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handlePong(pongMessage:String) {
|
private func handlePong(pongMessage: String) {
|
||||||
pongsMissed = 0
|
pongsMissed = 0
|
||||||
|
|
||||||
// We should upgrade
|
// We should upgrade
|
||||||
@ -447,8 +433,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A poll failed, tell the client about it
|
// A poll failed, tell the client about it
|
||||||
private func handlePollingFailed(reason:String) {
|
private func handlePollingFailed(reason: String) {
|
||||||
_connected = false
|
connected = false
|
||||||
ws?.disconnect()
|
ws?.disconnect()
|
||||||
pingTimer?.invalidate()
|
pingTimer?.invalidate()
|
||||||
waitingForPoll = false
|
waitingForPoll = false
|
||||||
@ -465,11 +451,11 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func open(opts:[String: AnyObject]? = nil) {
|
public func open(opts: [String: AnyObject]? = nil) {
|
||||||
if connected {
|
if connected {
|
||||||
SocketLogger.err("Tried to open while connected", client: self)
|
SocketLogger.err("Tried to open while connected", client: self)
|
||||||
|
|
||||||
client?.didError("Tried to open while connected")
|
client?.didError("Tried to open while connected")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,8 +467,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
(urlPolling, urlWebSocket) = createURLs(opts)
|
(urlPolling, urlWebSocket) = createURLs(opts)
|
||||||
|
|
||||||
if forceWebsockets {
|
if forceWebsockets {
|
||||||
_polling = false
|
polling = false
|
||||||
_websocket = true
|
websocket = true
|
||||||
createWebsocket(andConnect: true)
|
createWebsocket(andConnect: true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -494,8 +480,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
reqPolling.allHTTPHeaderFields = headers
|
reqPolling.allHTTPHeaderFields = headers
|
||||||
}
|
}
|
||||||
|
|
||||||
if extraHeaders != nil {
|
if let extraHeaders = extraHeaders {
|
||||||
for (headerName, value) in extraHeaders! {
|
for (headerName, value) in extraHeaders {
|
||||||
reqPolling.setValue(value, forHTTPHeaderField: headerName)
|
reqPolling.setValue(value, forHTTPHeaderField: headerName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,19 +491,18 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
// Translatation of engine.io-parser#decodePayload
|
// Translatation of engine.io-parser#decodePayload
|
||||||
private func parsePollingMessage(str:String) {
|
private func parsePollingMessage(str:String) {
|
||||||
if count(str) == 1 {
|
guard str.characters.count != 1 else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// println(str)
|
// println(str)
|
||||||
|
|
||||||
let strArray = Array(str)
|
let strArray = Array(str.characters)
|
||||||
var length = ""
|
var length = ""
|
||||||
var n = 0
|
var n = 0
|
||||||
var msg = ""
|
var msg = ""
|
||||||
|
|
||||||
func testLength(length:String, inout n:Int) -> Bool {
|
func testLength(length:String, inout n:Int) -> Bool {
|
||||||
if let num = length.toInt() {
|
if let num = Int(length) {
|
||||||
n = num
|
n = num
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
@ -525,13 +510,13 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for var i = 0, l = count(str); i < l; i++ {
|
for var i = 0, l = str.characters.count; i < l; i++ {
|
||||||
let chr = String(strArray[i])
|
let chr = String(strArray[i])
|
||||||
|
|
||||||
if chr != ":" {
|
if chr != ":" {
|
||||||
length += chr
|
length += chr
|
||||||
} else {
|
} else {
|
||||||
if length == "" || testLength(length, &n) {
|
if length == "" || testLength(length, n: &n) {
|
||||||
SocketLogger.err("Parsing error: %@", client: self, args: str)
|
SocketLogger.err("Parsing error: %@", client: self, args: str)
|
||||||
handlePollingFailed("Error parsing XHR message")
|
handlePollingFailed("Error parsing XHR message")
|
||||||
return
|
return
|
||||||
@ -539,12 +524,12 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
msg = String(strArray[i+1...i+n])
|
msg = String(strArray[i+1...i+n])
|
||||||
|
|
||||||
if let lengthInt = length.toInt() where lengthInt != count(msg) {
|
if let lengthInt = Int(length) where lengthInt != msg.characters.count {
|
||||||
SocketLogger.err("Parsing error: %@", client: self, args: str)
|
SocketLogger.err("Parsing error: %@", client: self, args: str)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if count(msg) != 0 {
|
if msg.characters.count != 0 {
|
||||||
// Be sure to capture the value of the msg
|
// Be sure to capture the value of the msg
|
||||||
dispatch_async(handleQueue) {[weak self, msg] in
|
dispatch_async(handleQueue) {[weak self, msg] in
|
||||||
self?.parseEngineMessage(msg, fromPolling: true)
|
self?.parseEngineMessage(msg, fromPolling: true)
|
||||||
@ -557,15 +542,11 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func parseEngineData(data:NSData) {
|
private func parseEngineData(data: NSData) {
|
||||||
if let client = client {
|
client?.parseBinaryData(data.subdataWithRange(NSMakeRange(1, data.length - 1)))
|
||||||
dispatch_async(client.handleQueue) {[weak self] in
|
|
||||||
self?.client?.parseBinaryData(data.subdataWithRange(NSMakeRange(1, data.length - 1)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func parseEngineMessage(var message:String, fromPolling:Bool) {
|
private func parseEngineMessage(var message: String, fromPolling: Bool) {
|
||||||
SocketLogger.log("Got message: %@", client: self, args: message)
|
SocketLogger.log("Got message: %@", client: self, args: message)
|
||||||
|
|
||||||
if fromPolling {
|
if fromPolling {
|
||||||
@ -574,21 +555,21 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
let type = PacketType(str: (message["^(\\d)"].groups()?[1])) ?? {
|
let type = PacketType(str: (message["^(\\d)"].groups()?[1])) ?? {
|
||||||
self.checkIfMessageIsBase64Binary(message)
|
self.checkIfMessageIsBase64Binary(message)
|
||||||
return PacketType.NOOP
|
return PacketType.Noop
|
||||||
}()
|
}()
|
||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
case PacketType.MESSAGE:
|
case PacketType.Message:
|
||||||
message.removeAtIndex(message.startIndex)
|
message.removeAtIndex(message.startIndex)
|
||||||
handleMessage(message)
|
handleMessage(message)
|
||||||
case PacketType.NOOP:
|
case PacketType.Noop:
|
||||||
handleNOOP()
|
handleNOOP()
|
||||||
case PacketType.PONG:
|
case PacketType.Pong:
|
||||||
handlePong(message)
|
handlePong(message)
|
||||||
case PacketType.OPEN:
|
case PacketType.Open:
|
||||||
message.removeAtIndex(message.startIndex)
|
message.removeAtIndex(message.startIndex)
|
||||||
handleOpen(message)
|
handleOpen(message)
|
||||||
case PacketType.CLOSE:
|
case PacketType.Close:
|
||||||
handleClose()
|
handleClose()
|
||||||
default:
|
default:
|
||||||
SocketLogger.log("Got unknown packet type", client: self)
|
SocketLogger.log("Got unknown packet type", client: self)
|
||||||
@ -597,16 +578,16 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
private func probeWebSocket() {
|
private func probeWebSocket() {
|
||||||
if websocketConnected {
|
if websocketConnected {
|
||||||
sendWebSocketMessage("probe", withType: PacketType.PING)
|
sendWebSocketMessage("probe", withType: PacketType.Ping)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send an engine message (4)
|
/// Send an engine message (4)
|
||||||
public func send(msg:String, withData datas:ContiguousArray<NSData>?) {
|
public func send(msg: String, withData datas: [NSData]?) {
|
||||||
if probing {
|
if probing {
|
||||||
probeWait.append((msg, PacketType.MESSAGE, datas))
|
probeWait.append((msg, PacketType.Message, datas))
|
||||||
} else {
|
} else {
|
||||||
write(msg, withType: PacketType.MESSAGE, withData: datas)
|
write(msg, withType: PacketType.Message, withData: datas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,13 +600,13 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
++pongsMissed
|
++pongsMissed
|
||||||
write("", withType: PacketType.PING, withData: nil)
|
write("", withType: PacketType.Ping, withData: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send polling message.
|
/// Send polling message.
|
||||||
/// Only call on emitQueue
|
/// Only call on emitQueue
|
||||||
private func sendPollMessage(var msg:String, withType type:PacketType,
|
private func sendPollMessage(var msg: String, withType type: PacketType,
|
||||||
datas:ContiguousArray<NSData>? = nil) {
|
datas:[NSData]? = nil) {
|
||||||
SocketLogger.log("Sending poll: %@ as type: %@", client: self, args: msg, type.rawValue)
|
SocketLogger.log("Sending poll: %@ as type: %@", client: self, args: msg, type.rawValue)
|
||||||
|
|
||||||
doubleEncodeUTF8(&msg)
|
doubleEncodeUTF8(&msg)
|
||||||
@ -633,9 +614,9 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
postWait.append(strMsg)
|
postWait.append(strMsg)
|
||||||
|
|
||||||
if datas != nil {
|
if let datas = datas {
|
||||||
for data in datas! {
|
for data in datas {
|
||||||
let (nilData, b64Data) = createBinaryDataForSend(data)
|
let (_, b64Data) = createBinaryDataForSend(data)
|
||||||
|
|
||||||
postWait.append(b64Data!)
|
postWait.append(b64Data!)
|
||||||
}
|
}
|
||||||
@ -648,15 +629,15 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
/// Send message on WebSockets
|
/// Send message on WebSockets
|
||||||
/// Only call on emitQueue
|
/// Only call on emitQueue
|
||||||
private func sendWebSocketMessage(str:String, withType type:PacketType,
|
private func sendWebSocketMessage(str: String, withType type: PacketType,
|
||||||
datas:ContiguousArray<NSData>? = nil) {
|
datas:[NSData]? = nil) {
|
||||||
SocketLogger.log("Sending ws: %@ as type: %@", client: self, args: str, type.rawValue)
|
SocketLogger.log("Sending ws: %@ as type: %@", client: self, args: str, type.rawValue)
|
||||||
|
|
||||||
ws?.writeString("\(type.rawValue)\(str)")
|
ws?.writeString("\(type.rawValue)\(str)")
|
||||||
|
|
||||||
if datas != nil {
|
if let datas = datas {
|
||||||
for data in datas! {
|
for data in datas {
|
||||||
let (data, nilString) = createBinaryDataForSend(data)
|
let (data, _) = createBinaryDataForSend(data)
|
||||||
if data != nil {
|
if data != nil {
|
||||||
ws?.writeData(data!)
|
ws?.writeData(data!)
|
||||||
}
|
}
|
||||||
@ -666,7 +647,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
// Starts the ping timer
|
// Starts the ping timer
|
||||||
private func startPingTimer() {
|
private func startPingTimer() {
|
||||||
if pingInterval == nil {
|
guard pingInterval != nil else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,7 +669,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
SocketLogger.log("Upgrading transport to WebSockets", client: self)
|
SocketLogger.log("Upgrading transport to WebSockets", client: self)
|
||||||
|
|
||||||
fastUpgrade = true
|
fastUpgrade = true
|
||||||
sendPollMessage("", withType: PacketType.NOOP)
|
sendPollMessage("", withType: PacketType.Noop)
|
||||||
// After this point, we should not send anymore polling messages
|
// After this point, we should not send anymore polling messages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -696,7 +677,7 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
/**
|
/**
|
||||||
Write a message, independent of transport.
|
Write a message, independent of transport.
|
||||||
*/
|
*/
|
||||||
public func write(msg:String, withType type:PacketType, withData data:ContiguousArray<NSData>?) {
|
public func write(msg: String, withType type: PacketType, withData data: [NSData]?) {
|
||||||
dispatch_async(emitQueue) {[weak self] in
|
dispatch_async(emitQueue) {[weak self] in
|
||||||
if let this = self where this.connected {
|
if let this = self where this.connected {
|
||||||
if this.websocket {
|
if this.websocket {
|
||||||
@ -715,12 +696,12 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
/**
|
/**
|
||||||
Write a message, independent of transport. For Objective-C. withData should be an NSArray of NSData
|
Write a message, independent of transport. For Objective-C. withData should be an NSArray of NSData
|
||||||
*/
|
*/
|
||||||
public func writeObjc(msg:String, withType type:Int, withData data:NSArray?) {
|
public func writeObjc(msg: String, withType type: Int, withData data: NSArray?) {
|
||||||
if let pType = PacketType(rawValue: type) {
|
if let pType = PacketType(rawValue: type) {
|
||||||
var arr = ContiguousArray<NSData>()
|
var arr = [NSData]()
|
||||||
|
|
||||||
if data != nil {
|
if let data = data {
|
||||||
for d in data! {
|
for d in data {
|
||||||
arr.append(d as! NSData)
|
arr.append(d as! NSData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -738,13 +719,13 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
probing = true
|
probing = true
|
||||||
probeWebSocket()
|
probeWebSocket()
|
||||||
} else {
|
} else {
|
||||||
_connected = true
|
connected = true
|
||||||
probing = false
|
probing = false
|
||||||
_polling = false
|
polling = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func websocketDidDisconnect(socket:WebSocket, error:NSError?) {
|
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
|
||||||
websocketConnected = false
|
websocketConnected = false
|
||||||
probing = false
|
probing = false
|
||||||
|
|
||||||
@ -755,8 +736,8 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
|
|
||||||
if websocket {
|
if websocket {
|
||||||
pingTimer?.invalidate()
|
pingTimer?.invalidate()
|
||||||
_connected = false
|
connected = false
|
||||||
_websocket = false
|
websocket = false
|
||||||
|
|
||||||
let reason = error?.localizedDescription ?? "Socket Disconnected"
|
let reason = error?.localizedDescription ?? "Socket Disconnected"
|
||||||
|
|
||||||
@ -770,11 +751,11 @@ public final class SocketEngine: NSObject, WebSocketDelegate, SocketLogClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func websocketDidReceiveMessage(socket:WebSocket, text:String) {
|
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
|
||||||
parseEngineMessage(text, fromPolling: false)
|
parseEngineMessage(text, fromPolling: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func websocketDidReceiveData(socket:WebSocket, data:NSData) {
|
public func websocketDidReceiveData(socket: WebSocket, data: NSData) {
|
||||||
parseEngineData(data)
|
parseEngineData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketEngineClient.swift
|
// SocketEngineClient.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 3/19/15.
|
// Created by Erik Little on 3/19/15.
|
||||||
//
|
//
|
||||||
@ -26,12 +26,11 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objc public protocol SocketEngineClient {
|
@objc public protocol SocketEngineClient {
|
||||||
var handleQueue:dispatch_queue_attr_t! {get}
|
var socketURL: String {get}
|
||||||
var socketURL:String {get}
|
var secure: Bool {get}
|
||||||
var secure:Bool {get}
|
|
||||||
|
|
||||||
func didError(reason:AnyObject)
|
func didError(reason: AnyObject)
|
||||||
func engineDidClose(reason:String)
|
func engineDidClose(reason: String)
|
||||||
func parseSocketMessage(msg:String)
|
func parseSocketMessage(msg: String)
|
||||||
func parseBinaryData(data:NSData)
|
func parseBinaryData(data: NSData)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// EventHandler.swift
|
// EventHandler.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 1/18/15.
|
// Created by Erik Little on 1/18/15.
|
||||||
//
|
//
|
||||||
@ -24,24 +24,37 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
private func emitAckCallback(socket:SocketIOClient, num:Int)
|
private func emitAckCallback(socket: SocketIOClient?, num: Int?)
|
||||||
(items:AnyObject...) -> Void {
|
(items: AnyObject...) -> Void {
|
||||||
socket.emitAck(num, withData: items)
|
socket?.emitAck(num ?? -1, withItems: items)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class SocketEventHandler {
|
private func emitAckCallbackObjectiveC(socket: SocketIOClient?, num: Int?)
|
||||||
let event:String!
|
(items: NSArray) -> Void {
|
||||||
let callback:NormalCallback?
|
socket?.emitAck(num ?? -1, withItems: items as [AnyObject])
|
||||||
|
}
|
||||||
|
|
||||||
init(event:String, callback:NormalCallback) {
|
struct SocketEventHandler {
|
||||||
|
let event: String
|
||||||
|
let callback: NormalCallback?
|
||||||
|
let callBackObjectiveC: NormalCallbackObjectiveC?
|
||||||
|
|
||||||
|
init(event: String, callback: NormalCallback) {
|
||||||
self.event = event
|
self.event = event
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
|
self.callBackObjectiveC = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeCallback(_ items:NSArray? = nil, withAck ack:Int? = nil, withAckType type:Int? = nil,
|
init(event: String, callback: NormalCallbackObjectiveC) {
|
||||||
withSocket socket:SocketIOClient? = nil) {
|
self.event = event
|
||||||
dispatch_async(dispatch_get_main_queue()) {[weak self] in
|
self.callback = nil
|
||||||
self?.callback?(items, ack != nil ? emitAckCallback(socket!, ack!) : nil)
|
self.callBackObjectiveC = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func executeCallback(items:NSArray? = nil, withAck ack:Int? = nil, withAckType type:Int? = nil,
|
||||||
|
withSocket socket:SocketIOClient? = nil) {
|
||||||
|
self.callback != nil ?
|
||||||
|
self.callback?(items, emitAckCallback(socket, num: ack))
|
||||||
|
: self.callBackObjectiveC?(items, emitAckCallbackObjectiveC(socket, num: ack))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketFixUTF8.swift
|
// SocketFixUTF8.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 3/16/15.
|
// Created by Erik Little on 3/16/15.
|
||||||
//
|
//
|
||||||
@ -25,13 +25,13 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
func fixDoubleUTF8(inout name:String) {
|
func fixDoubleUTF8(inout name: String) {
|
||||||
let utf8 = name.dataUsingEncoding(NSISOLatin1StringEncoding)!
|
let utf8 = name.dataUsingEncoding(NSISOLatin1StringEncoding)!
|
||||||
let latin1 = NSString(data: utf8, encoding: NSUTF8StringEncoding)!
|
let latin1 = NSString(data: utf8, encoding: NSUTF8StringEncoding)!
|
||||||
name = latin1 as String
|
name = latin1 as String
|
||||||
}
|
}
|
||||||
|
|
||||||
func doubleEncodeUTF8(inout str:String) {
|
func doubleEncodeUTF8(inout str: String) {
|
||||||
let latin1 = str.dataUsingEncoding(NSUTF8StringEncoding)!
|
let latin1 = str.dataUsingEncoding(NSUTF8StringEncoding)!
|
||||||
let utf8 = NSString(data: latin1, encoding: NSISOLatin1StringEncoding)!
|
let utf8 = NSString(data: latin1, encoding: NSISOLatin1StringEncoding)!
|
||||||
str = utf8 as String
|
str = utf8 as String
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketIOClient.swift
|
// SocketIOClient.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 11/23/14.
|
// Created by Erik Little on 11/23/14.
|
||||||
//
|
//
|
||||||
@ -25,59 +25,40 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient {
|
public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient {
|
||||||
private var anyHandler:((SocketAnyEvent) -> Void)?
|
private var anyHandler: ((SocketAnyEvent) -> Void)?
|
||||||
private var _closed = false
|
|
||||||
private var _connected = false
|
|
||||||
private var _connecting = false
|
|
||||||
private var currentReconnectAttempt = 0
|
private var currentReconnectAttempt = 0
|
||||||
private var handlers = ContiguousArray<SocketEventHandler>()
|
private var handlers = ContiguousArray<SocketEventHandler>()
|
||||||
private var connectParams:[String: AnyObject]?
|
private var connectParams: [String: AnyObject]?
|
||||||
private var _secure = false
|
private var reconnectTimer: NSTimer?
|
||||||
private var _reconnecting = false
|
|
||||||
private var reconnectTimer:NSTimer?
|
|
||||||
|
|
||||||
let reconnectAttempts:Int!
|
let reconnectAttempts: Int!
|
||||||
let logType = "SocketClient"
|
let logType = "SocketClient"
|
||||||
var ackHandlers = SocketAckManager()
|
var ackHandlers = SocketAckManager()
|
||||||
var currentAck = -1
|
var currentAck = -1
|
||||||
var log = false
|
var waitingData = [SocketPacket]()
|
||||||
var waitingData = ContiguousArray<SocketPacket>()
|
|
||||||
var sessionDelegate:NSURLSessionDelegate?
|
|
||||||
|
|
||||||
public let socketURL:String
|
|
||||||
public let handleAckQueue = dispatch_queue_create("handleAckQueue", DISPATCH_QUEUE_SERIAL)
|
|
||||||
public let handleQueue = dispatch_queue_create("handleQueue", DISPATCH_QUEUE_SERIAL)
|
|
||||||
public let emitQueue = dispatch_queue_create("emitQueue", DISPATCH_QUEUE_SERIAL)
|
public let emitQueue = dispatch_queue_create("emitQueue", DISPATCH_QUEUE_SERIAL)
|
||||||
public var closed:Bool {
|
public let handleQueue: dispatch_queue_t!
|
||||||
return _closed
|
public let socketURL: String
|
||||||
}
|
|
||||||
public var connected:Bool {
|
public private(set) var engine: SocketEngine?
|
||||||
return _connected
|
public private(set) var secure = false
|
||||||
}
|
public private(set) var status = SocketIOClientStatus.NotConnected
|
||||||
public var connecting:Bool {
|
|
||||||
return _connecting
|
|
||||||
}
|
|
||||||
public var engine:SocketEngine?
|
|
||||||
public var nsp = "/"
|
public var nsp = "/"
|
||||||
public var opts:[String: AnyObject]?
|
public var opts: [String: AnyObject]?
|
||||||
public var reconnects = true
|
public var reconnects = true
|
||||||
public var reconnecting:Bool {
|
|
||||||
return _reconnecting
|
|
||||||
}
|
|
||||||
public var reconnectWait = 10
|
public var reconnectWait = 10
|
||||||
public var secure:Bool {
|
public var sid: String? {
|
||||||
return _secure
|
|
||||||
}
|
|
||||||
public var sid:String? {
|
|
||||||
return engine?.sid
|
return engine?.sid
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a new SocketIOClient. opts can be omitted
|
Create a new SocketIOClient. opts can be omitted
|
||||||
*/
|
*/
|
||||||
public init(var socketURL:String, opts:[String: AnyObject]? = nil) {
|
public init(var socketURL: String, opts: [String: AnyObject]? = nil) {
|
||||||
if socketURL["https://"].matches().count != 0 {
|
if socketURL["https://"].matches().count != 0 {
|
||||||
self._secure = true
|
self.secure = true
|
||||||
}
|
}
|
||||||
|
|
||||||
socketURL = socketURL["http://"] ~= ""
|
socketURL = socketURL["http://"] ~= ""
|
||||||
@ -86,24 +67,15 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
self.socketURL = socketURL
|
self.socketURL = socketURL
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
|
|
||||||
// Set options
|
|
||||||
if let sessionDelegate = opts?["sessionDelegate"] as? NSURLSessionDelegate {
|
|
||||||
self.sessionDelegate = sessionDelegate
|
|
||||||
}
|
|
||||||
|
|
||||||
if let connectParams = opts?["connectParams"] as? [String: AnyObject] {
|
if let connectParams = opts?["connectParams"] as? [String: AnyObject] {
|
||||||
self.connectParams = connectParams
|
self.connectParams = connectParams
|
||||||
}
|
}
|
||||||
|
|
||||||
if let log = opts?["log"] as? Bool {
|
if let log = opts?["log"] as? Bool {
|
||||||
self.log = log
|
SocketLogger.log = log
|
||||||
}
|
|
||||||
|
|
||||||
if var nsp = opts?["nsp"] as? String {
|
|
||||||
if nsp != "/" && nsp.hasPrefix("/") {
|
|
||||||
nsp.removeAtIndex(nsp.startIndex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let nsp = opts?["nsp"] as? String {
|
||||||
self.nsp = nsp
|
self.nsp = nsp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,11 +93,13 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
self.reconnectWait = abs(reconnectWait)
|
self.reconnectWait = abs(reconnectWait)
|
||||||
}
|
}
|
||||||
|
|
||||||
super.init()
|
if let handleQueue = opts?["handleQueue"] as? dispatch_queue_t {
|
||||||
|
self.handleQueue = handleQueue
|
||||||
|
} else {
|
||||||
|
self.handleQueue = dispatch_get_main_queue()
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(socketURL:String, options:[String: AnyObject]?) {
|
super.init()
|
||||||
self.init(socketURL: socketURL, opts: options)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -149,15 +123,12 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
Will turn off automatic reconnects.
|
Will turn off automatic reconnects.
|
||||||
Pass true to fast if you're closing from a background task
|
Pass true to fast if you're closing from a background task
|
||||||
*/
|
*/
|
||||||
public func close(#fast:Bool) {
|
public func close(fast fast: Bool) {
|
||||||
SocketLogger.log("Closing socket", client: self)
|
SocketLogger.log("Closing socket", client: self)
|
||||||
|
|
||||||
reconnects = false
|
reconnects = false
|
||||||
_connecting = false
|
status = SocketIOClientStatus.Closed
|
||||||
_connected = false
|
|
||||||
_reconnecting = false
|
|
||||||
engine?.close(fast: fast)
|
engine?.close(fast: fast)
|
||||||
engine = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,28 +141,28 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
/**
|
/**
|
||||||
Connect to the server. If we aren't connected after timeoutAfter, call handler
|
Connect to the server. If we aren't connected after timeoutAfter, call handler
|
||||||
*/
|
*/
|
||||||
public func connect(#timeoutAfter:Int, withTimeoutHandler handler:(() -> Void)?) {
|
public func connect(timeoutAfter timeoutAfter:Int,
|
||||||
if closed {
|
withTimeoutHandler handler:(() -> Void)?) {
|
||||||
SocketLogger.log("Warning! This socket was previously closed. This might be dangerous!", client: self)
|
guard status != SocketIOClientStatus.Connected else {
|
||||||
_closed = false
|
|
||||||
} else if connected {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if status == SocketIOClientStatus.Closed {
|
||||||
|
SocketLogger.log("Warning! This socket was previously closed. This might be dangerous!", client: self)
|
||||||
|
}
|
||||||
|
|
||||||
_connecting = true
|
status = SocketIOClientStatus.Connecting
|
||||||
addEngine()
|
addEngine()
|
||||||
engine?.open(opts: connectParams)
|
engine?.open(connectParams)
|
||||||
|
|
||||||
if timeoutAfter == 0 {
|
guard timeoutAfter != 0 else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeoutAfter) * Int64(NSEC_PER_SEC))
|
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(timeoutAfter) * Int64(NSEC_PER_SEC))
|
||||||
|
|
||||||
dispatch_after(time, dispatch_get_main_queue()) {[weak self] in
|
dispatch_after(time, dispatch_get_main_queue()) {[weak self] in
|
||||||
if let this = self where !this.connected {
|
if let this = self where this.status != SocketIOClientStatus.Connected {
|
||||||
this._closed = true
|
this.status = SocketIOClientStatus.Closed
|
||||||
this._connecting = false
|
|
||||||
this.engine?.close(fast: true)
|
this.engine?.close(fast: true)
|
||||||
|
|
||||||
handler?()
|
handler?()
|
||||||
@ -199,13 +170,13 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createOnAck(event:String, items:[AnyObject]) -> OnAckCallback {
|
private func createOnAck(items: [AnyObject]) -> OnAckCallback {
|
||||||
return {[weak self, ack = ++currentAck] timeout, callback in
|
return {[weak self, ack = ++currentAck] timeout, callback in
|
||||||
if let this = self {
|
if let this = self {
|
||||||
this.ackHandlers.addAck(ack, callback: callback)
|
this.ackHandlers.addAck(ack, callback: callback)
|
||||||
|
|
||||||
dispatch_async(this.emitQueue) {[weak this] in
|
dispatch_async(this.emitQueue) {[weak this] in
|
||||||
this?._emit(event, items, ack: ack)
|
this?._emit(items, ack: ack)
|
||||||
}
|
}
|
||||||
|
|
||||||
if timeout != 0 {
|
if timeout != 0 {
|
||||||
@ -221,11 +192,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
|
|
||||||
func didConnect() {
|
func didConnect() {
|
||||||
SocketLogger.log("Socket connected", client: self)
|
SocketLogger.log("Socket connected", client: self)
|
||||||
|
status = SocketIOClientStatus.Connected
|
||||||
_closed = false
|
|
||||||
_connected = true
|
|
||||||
_connecting = false
|
|
||||||
_reconnecting = false
|
|
||||||
currentReconnectAttempt = 0
|
currentReconnectAttempt = 0
|
||||||
clearReconnectTimer()
|
clearReconnectTimer()
|
||||||
|
|
||||||
@ -234,18 +201,16 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
handleEvent("connect", data: nil, isInternalMessage: false)
|
handleEvent("connect", data: nil, isInternalMessage: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func didDisconnect(reason:String) {
|
func didDisconnect(reason: String) {
|
||||||
if closed {
|
guard status != SocketIOClientStatus.Closed else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketLogger.log("Disconnected: %@", client: self, args: reason)
|
SocketLogger.log("Disconnected: %@", client: self, args: reason)
|
||||||
|
|
||||||
_closed = true
|
status = SocketIOClientStatus.Closed
|
||||||
_connected = false
|
|
||||||
reconnects = false
|
reconnects = false
|
||||||
_connecting = false
|
|
||||||
_reconnecting = false
|
|
||||||
|
|
||||||
// Make sure the engine is actually dead.
|
// Make sure the engine is actually dead.
|
||||||
engine?.close(fast: true)
|
engine?.close(fast: true)
|
||||||
@ -253,7 +218,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// error
|
/// error
|
||||||
public func didError(reason:AnyObject) {
|
public func didError(reason: AnyObject) {
|
||||||
SocketLogger.err("%@", client: self, args: reason)
|
SocketLogger.err("%@", client: self, args: reason)
|
||||||
|
|
||||||
handleEvent("error", data: reason as? [AnyObject] ?? [reason],
|
handleEvent("error", data: reason as? [AnyObject] ?? [reason],
|
||||||
@ -263,33 +228,27 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
/**
|
/**
|
||||||
Same as close
|
Same as close
|
||||||
*/
|
*/
|
||||||
public func disconnect(#fast:Bool) {
|
public func disconnect(fast fast: Bool) {
|
||||||
close(fast: fast)
|
close(fast: fast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Send a message to the server
|
Send a message to the server
|
||||||
*/
|
*/
|
||||||
public func emit(event:String, _ items:AnyObject...) {
|
public func emit(event: String, _ items: AnyObject...) {
|
||||||
if !connected {
|
emit(event, withItems: items)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch_async(emitQueue) {[weak self] in
|
|
||||||
self?._emit(event, items)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Same as emit, but meant for Objective-C
|
Same as emit, but meant for Objective-C
|
||||||
*/
|
*/
|
||||||
public func emit(event:String, withItems items:[AnyObject]) {
|
public func emit(event: String, withItems items: [AnyObject]) {
|
||||||
if !connected {
|
guard status == SocketIOClientStatus.Connected else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async(emitQueue) {[weak self] in
|
dispatch_async(emitQueue) {[weak self] in
|
||||||
self?._emit(event, items)
|
self?._emit([event] + items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,39 +256,28 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add
|
Sends a message to the server, requesting an ack. Use the onAck method of SocketAckHandler to add
|
||||||
an ack.
|
an ack.
|
||||||
*/
|
*/
|
||||||
public func emitWithAck(event:String, _ items:AnyObject...) -> OnAckCallback {
|
public func emitWithAck(event: String, _ items: AnyObject...) -> OnAckCallback {
|
||||||
if !connected {
|
return emitWithAck(event, withItems: items)
|
||||||
return createOnAck(event, items: items)
|
|
||||||
}
|
|
||||||
|
|
||||||
return createOnAck(event, items: items)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Same as emitWithAck, but for Objective-C
|
Same as emitWithAck, but for Objective-C
|
||||||
*/
|
*/
|
||||||
public func emitWithAck(event:String, withItems items:[AnyObject]) -> OnAckCallback {
|
public func emitWithAck(event: String, withItems items: [AnyObject]) -> OnAckCallback {
|
||||||
if !connected {
|
return createOnAck([event] + items)
|
||||||
return createOnAck(event, items: items)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return createOnAck(event, items: items)
|
private func _emit(data: [AnyObject], ack: Int? = nil) {
|
||||||
}
|
guard status == SocketIOClientStatus.Connected else {
|
||||||
|
|
||||||
private func _emit(event:String, _ args:[AnyObject], ack:Int? = nil) {
|
|
||||||
if !connected {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let packet = SocketPacket(type: nil, data: args, nsp: nsp, id: ack)
|
let packet = SocketPacket.packetFromEmit(data, id: ack ?? -1, nsp: nsp, ack: false)
|
||||||
let str:String
|
let str = packet.packetString
|
||||||
|
|
||||||
SocketParser.parseForEmit(packet)
|
|
||||||
str = packet.createMessageForEvent(event)
|
|
||||||
|
|
||||||
SocketLogger.log("Emitting: %@", client: self, args: str)
|
SocketLogger.log("Emitting: %@", client: self, args: str)
|
||||||
|
|
||||||
if packet.type == SocketPacket.PacketType.BINARY_EVENT {
|
if packet.type == SocketPacket.PacketType.BinaryEvent {
|
||||||
engine?.send(str, withData: packet.binary)
|
engine?.send(str, withData: packet.binary)
|
||||||
} else {
|
} else {
|
||||||
engine?.send(str, withData: nil)
|
engine?.send(str, withData: nil)
|
||||||
@ -337,18 +285,15 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the server wants to know that the client received data
|
// If the server wants to know that the client received data
|
||||||
func emitAck(ack:Int, withData args:[AnyObject]) {
|
func emitAck(ack: Int, withItems items: [AnyObject]) {
|
||||||
dispatch_async(emitQueue) {[weak self] in
|
dispatch_async(emitQueue) {[weak self] in
|
||||||
if let this = self where this.connected {
|
if let this = self where this.status == SocketIOClientStatus.Connected {
|
||||||
let packet = SocketPacket(type: nil, data: args, nsp: this.nsp, id: ack)
|
let packet = SocketPacket.packetFromEmit(items, id: ack ?? -1, nsp: this.nsp, ack: true)
|
||||||
let str:String
|
let str = packet.packetString
|
||||||
|
|
||||||
SocketParser.parseForEmit(packet)
|
|
||||||
str = packet.createAck()
|
|
||||||
|
|
||||||
SocketLogger.log("Emitting Ack: %@", client: this, args: str)
|
SocketLogger.log("Emitting Ack: %@", client: this, args: str)
|
||||||
|
|
||||||
if packet.type == SocketPacket.PacketType.BINARY_ACK {
|
if packet.type == SocketPacket.PacketType.BinaryAck {
|
||||||
this.engine?.send(str, withData: packet.binary)
|
this.engine?.send(str, withData: packet.binary)
|
||||||
} else {
|
} else {
|
||||||
this.engine?.send(str, withData: nil)
|
this.engine?.send(str, withData: nil)
|
||||||
@ -358,20 +303,20 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func engineDidClose(reason:String) {
|
public func engineDidClose(reason: String) {
|
||||||
_connected = false
|
waitingData.removeAll()
|
||||||
_connecting = false
|
|
||||||
|
|
||||||
if closed || !reconnects {
|
if status == SocketIOClientStatus.Closed || !reconnects {
|
||||||
didDisconnect(reason)
|
didDisconnect(reason)
|
||||||
} else if !reconnecting {
|
} else if status != SocketIOClientStatus.Reconnecting {
|
||||||
|
status = SocketIOClientStatus.Reconnecting
|
||||||
handleEvent("reconnect", data: [reason], isInternalMessage: true)
|
handleEvent("reconnect", data: [reason], isInternalMessage: true)
|
||||||
tryReconnect()
|
tryReconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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?) {
|
||||||
SocketLogger.log("Handling ack: %@ with data: %@", client: self,
|
SocketLogger.log("Handling ack: %@ with data: %@", client: self,
|
||||||
args: ack, data ?? "")
|
args: ack, data ?? "")
|
||||||
|
|
||||||
@ -382,27 +327,29 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
/**
|
/**
|
||||||
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 = false,
|
public func handleEvent(event: String, data: [AnyObject]?, isInternalMessage: Bool,
|
||||||
wantsAck ack:Int? = nil) {
|
wantsAck ack: Int? = nil) {
|
||||||
// println("Should do event: \(event) with data: \(data)")
|
guard status == SocketIOClientStatus.Connected || isInternalMessage else {
|
||||||
if !connected && !isInternalMessage {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// println("Should do event: \(event) with data: \(data)")
|
||||||
|
|
||||||
SocketLogger.log("Handling event: %@ with data: %@", client: self,
|
SocketLogger.log("Handling event: %@ with data: %@", client: self,
|
||||||
args: event, data ?? "")
|
args: event, data ?? "")
|
||||||
|
|
||||||
if anyHandler != nil {
|
if anyHandler != nil {
|
||||||
dispatch_async(dispatch_get_main_queue()) {[weak self] in
|
dispatch_async(handleQueue) {[weak self] in
|
||||||
self?.anyHandler?(SocketAnyEvent(event: event, items: data))
|
self?.anyHandler?(SocketAnyEvent(event: event, items: data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for handler in handlers {
|
for handler in handlers where handler.event == event {
|
||||||
if handler.event == event {
|
if let ack = ack {
|
||||||
if ack != nil {
|
dispatch_async(handleQueue) {[weak self] in
|
||||||
handler.executeCallback(data, withAck: ack!, withSocket: self)
|
handler.executeCallback(data, withAck: ack, withSocket: self)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
dispatch_async(handleQueue) {
|
||||||
handler.executeCallback(data)
|
handler.executeCallback(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,7 +361,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
*/
|
*/
|
||||||
public func leaveNamespace() {
|
public func leaveNamespace() {
|
||||||
if nsp != "/" {
|
if nsp != "/" {
|
||||||
engine?.send("1/\(nsp)", withData: nil)
|
engine?.send("1\(nsp)", withData: nil)
|
||||||
nsp = "/"
|
nsp = "/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,23 +373,41 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
SocketLogger.log("Joining namespace", client: self)
|
SocketLogger.log("Joining namespace", client: self)
|
||||||
|
|
||||||
if nsp != "/" {
|
if nsp != "/" {
|
||||||
engine?.send("0/\(nsp)", withData: nil)
|
engine?.send("0\(nsp)", withData: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Joins namespace /
|
||||||
|
*/
|
||||||
|
public func joinNamespace(namespace: String) {
|
||||||
|
self.nsp = namespace
|
||||||
|
joinNamespace()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Removes handler(s)
|
Removes handler(s)
|
||||||
*/
|
*/
|
||||||
public func off(event:String) {
|
public func off(event: String) {
|
||||||
SocketLogger.log("Removing handler for event: %@", client: self, args: event)
|
SocketLogger.log("Removing handler for event: %@", client: self, args: event)
|
||||||
|
|
||||||
handlers = handlers.filter {$0.event == event ? false : true}
|
handlers = ContiguousArray(handlers.filter {!($0.event == event)})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Adds a handler for an event.
|
Adds a handler for an event.
|
||||||
*/
|
*/
|
||||||
public func on(event:String, callback:NormalCallback) {
|
public func on(event: String, callback: NormalCallback) {
|
||||||
|
SocketLogger.log("Adding handler for event: %@", client: self, args: event)
|
||||||
|
|
||||||
|
let handler = SocketEventHandler(event: event, callback: callback)
|
||||||
|
handlers.append(handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adds a handler for an event.
|
||||||
|
*/
|
||||||
|
public func onObjectiveC(event: String, callback: NormalCallbackObjectiveC) {
|
||||||
SocketLogger.log("Adding handler for event: %@", client: self, args: event)
|
SocketLogger.log("Adding handler for event: %@", client: self, args: event)
|
||||||
|
|
||||||
let handler = SocketEventHandler(event: event, callback: callback)
|
let handler = SocketEventHandler(event: event, callback: callback)
|
||||||
@ -460,7 +425,7 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
/**
|
/**
|
||||||
Adds a handler that will be called on every event.
|
Adds a handler that will be called on every event.
|
||||||
*/
|
*/
|
||||||
public func onAny(handler:(SocketAnyEvent) -> Void) {
|
public func onAny(handler: (SocketAnyEvent) -> Void) {
|
||||||
anyHandler = handler
|
anyHandler = handler
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,50 +436,58 @@ public final class SocketIOClient: NSObject, SocketEngineClient, SocketLogClient
|
|||||||
connect()
|
connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseSocketMessage(msg:String) {
|
public func parseSocketMessage(msg: String) {
|
||||||
SocketParser.parseSocketMessage(msg, socket: self)
|
dispatch_async(handleQueue) {[weak self] in
|
||||||
|
if let this = self {
|
||||||
|
SocketParser.parseSocketMessage(msg, socket: this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseBinaryData(data:NSData) {
|
public func parseBinaryData(data: NSData) {
|
||||||
SocketParser.parseBinaryData(data, socket: self)
|
dispatch_async(handleQueue) {[weak self] in
|
||||||
|
if let this = self {
|
||||||
|
SocketParser.parseBinaryData(data, socket: this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Trieds to reconnect to the server.
|
Tries to reconnect to the server.
|
||||||
*/
|
*/
|
||||||
public func reconnect() {
|
public func reconnect() {
|
||||||
_connected = false
|
|
||||||
_connecting = false
|
|
||||||
_reconnecting = false
|
|
||||||
|
|
||||||
engine?.stopPolling()
|
engine?.stopPolling()
|
||||||
tryReconnect()
|
tryReconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We lost connection and should attempt to reestablish
|
private func tryReconnect() {
|
||||||
@objc private func tryReconnect() {
|
if reconnectTimer == nil {
|
||||||
|
SocketLogger.log("Starting reconnect", client: self)
|
||||||
|
|
||||||
|
status = SocketIOClientStatus.Reconnecting
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue()) {[weak self] in
|
||||||
|
if let this = self {
|
||||||
|
this.reconnectTimer = NSTimer.scheduledTimerWithTimeInterval(Double(this.reconnectWait),
|
||||||
|
target: this, selector: "_tryReconnect", userInfo: nil, repeats: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func _tryReconnect() {
|
||||||
|
if status == SocketIOClientStatus.Connected {
|
||||||
|
clearReconnectTimer()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects {
|
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects {
|
||||||
clearReconnectTimer()
|
clearReconnectTimer()
|
||||||
didDisconnect("Reconnect Failed")
|
didDisconnect("Reconnect Failed")
|
||||||
|
|
||||||
return
|
return
|
||||||
} else if connected {
|
|
||||||
_connecting = false
|
|
||||||
_reconnecting = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if reconnectTimer == nil {
|
|
||||||
SocketLogger.log("Starting reconnect", client: self)
|
|
||||||
|
|
||||||
_reconnecting = true
|
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue()) {[weak self] in
|
|
||||||
if let this = self {
|
|
||||||
this.reconnectTimer = NSTimer.scheduledTimerWithTimeInterval(Double(this.reconnectWait),
|
|
||||||
target: this, selector: "tryReconnect", userInfo: nil, repeats: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketLogger.log("Trying to reconnect", client: self)
|
SocketLogger.log("Trying to reconnect", client: self)
|
||||||
|
|||||||
51
SocketIOClientSwift/SocketIOClientStatus.swift
Normal file
51
SocketIOClientSwift/SocketIOClientStatus.swift
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// SocketIOClientStatus.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Erik Little on 8/14/15.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objc public enum SocketIOClientStatus: Int, CustomStringConvertible {
|
||||||
|
public var description: String {
|
||||||
|
let des: String
|
||||||
|
|
||||||
|
switch rawValue {
|
||||||
|
case 0:
|
||||||
|
des = "Not Connected"
|
||||||
|
case 1:
|
||||||
|
des = "Closed"
|
||||||
|
case 2:
|
||||||
|
des = "Connecting"
|
||||||
|
case 3:
|
||||||
|
des = "Connected"
|
||||||
|
case 4:
|
||||||
|
des = "Reconnecting"
|
||||||
|
default:
|
||||||
|
des = "Unknown State"
|
||||||
|
}
|
||||||
|
|
||||||
|
return des
|
||||||
|
}
|
||||||
|
|
||||||
|
case NotConnected, Closed, Connecting, Connected, Reconnecting
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketLogger.swift
|
// SocketLogger.swift
|
||||||
// SocketIO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 4/11/15.
|
// Created by Erik Little on 4/11/15.
|
||||||
//
|
//
|
||||||
@ -24,48 +24,38 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
private let MESSAGE_LENGTH_MAX = 10000
|
|
||||||
|
|
||||||
protocol SocketLogClient {
|
protocol SocketLogClient {
|
||||||
var log:Bool {get set}
|
var logType: String {get}
|
||||||
var logType:String {get}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class SocketLogger {
|
final class SocketLogger {
|
||||||
private static let printQueue = dispatch_queue_create("printQueue", DISPATCH_QUEUE_SERIAL)
|
private static let printQueue = dispatch_queue_create("printQueue", DISPATCH_QUEUE_SERIAL)
|
||||||
|
static var log = false
|
||||||
|
|
||||||
private static func shorten(item:AnyObject) -> CVarArgType {
|
private static func toCVArgType(item: AnyObject) -> CVarArgType {
|
||||||
var str = toString(item)
|
return String(item)
|
||||||
|
|
||||||
if count(str) > MESSAGE_LENGTH_MAX {
|
|
||||||
let endIndex = advance(str.startIndex, MESSAGE_LENGTH_MAX)
|
|
||||||
|
|
||||||
str = str.substringToIndex(endIndex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return str
|
static func log(message: String, client: SocketLogClient, altType: String? = nil, args: AnyObject...) {
|
||||||
}
|
if !log {
|
||||||
|
|
||||||
static func log(message:String, client:SocketLogClient, altType:String? = nil, args:AnyObject...) {
|
|
||||||
if !client.log {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async(printQueue) {[type = client.logType] in
|
dispatch_async(printQueue) {[type = client.logType] in
|
||||||
let newArgs = args.map(SocketLogger.shorten)
|
let newArgs = args.map(SocketLogger.toCVArgType)
|
||||||
let replaced = String(format: message, arguments: newArgs)
|
let replaced = String(format: message, arguments: newArgs)
|
||||||
|
|
||||||
NSLog("%@: %@", altType ?? type, replaced)
|
NSLog("%@: %@", altType ?? type, replaced)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func err(message:String, client:SocketLogClient, altType:String? = nil, args:AnyObject...) {
|
static func err(message: String, client: SocketLogClient, altType: String? = nil, args: AnyObject...) {
|
||||||
if !client.log {
|
if !log {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async(printQueue) {[type = client.logType] in
|
dispatch_async(printQueue) {[type = client.logType] in
|
||||||
let newArgs = args.map(SocketLogger.shorten)
|
let newArgs = args.map(SocketLogger.toCVArgType)
|
||||||
let replaced = String(format: message, arguments: newArgs)
|
let replaced = String(format: message, arguments: newArgs)
|
||||||
|
|
||||||
NSLog("ERROR %@: %@", altType ?? type, replaced)
|
NSLog("ERROR %@: %@", altType ?? type, replaced)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketPacket.swift
|
// SocketPacket.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 1/18/15.
|
// Created by Erik Little on 1/18/15.
|
||||||
//
|
//
|
||||||
@ -24,38 +24,19 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class SocketPacket: Printable {
|
struct SocketPacket {
|
||||||
var binary = ContiguousArray<NSData>()
|
private var currentPlace = 0
|
||||||
var currentPlace = 0
|
private let placeholders: Int
|
||||||
var data:[AnyObject]?
|
|
||||||
var description:String {
|
|
||||||
var better = "SocketPacket {type: ~~0; data: ~~1; " +
|
|
||||||
"id: ~~2; placeholders: ~~3;}"
|
|
||||||
|
|
||||||
better = better["~~0"] ~= (type != nil ? String(type!.rawValue) : "nil")
|
let nsp: String
|
||||||
better = better["~~1"] ~= (data != nil ? "\(data!)" : "nil")
|
let id: Int
|
||||||
better = better["~~2"] ~= (id != nil ? String(id!) : "nil")
|
let type: PacketType
|
||||||
better = better["~~3"] ~= (placeholders != nil ? String(placeholders!) : "nil")
|
|
||||||
|
|
||||||
return better
|
enum PacketType: Int {
|
||||||
}
|
case Connect, Disconnect, Event, Ack, Error, BinaryEvent, BinaryAck
|
||||||
var id:Int?
|
|
||||||
var justAck = false
|
|
||||||
var nsp = ""
|
|
||||||
var placeholders:Int?
|
|
||||||
var type:PacketType?
|
|
||||||
|
|
||||||
enum PacketType:Int {
|
init?(str: String) {
|
||||||
case CONNECT = 0
|
if let int = Int(str), raw = PacketType(rawValue: int) {
|
||||||
case DISCONNECT = 1
|
|
||||||
case EVENT = 2
|
|
||||||
case ACK = 3
|
|
||||||
case ERROR = 4
|
|
||||||
case BINARY_EVENT = 5
|
|
||||||
case BINARY_ACK = 6
|
|
||||||
|
|
||||||
init?(str:String) {
|
|
||||||
if let int = str.toInt(), raw = PacketType(rawValue: int) {
|
|
||||||
self = raw
|
self = raw
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
@ -63,20 +44,54 @@ final class SocketPacket: Printable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(type:PacketType?, data:[AnyObject]? = nil, nsp:String = "",
|
var args: [AnyObject]? {
|
||||||
placeholders:Int? = nil, id:Int? = nil) {
|
var arr = data
|
||||||
self.type = type
|
|
||||||
|
if data.count == 0 {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
if type == PacketType.Event || type == PacketType.BinaryEvent {
|
||||||
|
arr.removeAtIndex(0)
|
||||||
|
return arr
|
||||||
|
} else {
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var binary: [NSData]
|
||||||
|
var data: [AnyObject]
|
||||||
|
var description: String {
|
||||||
|
var better = "SocketPacket {type: ~~0; data: ~~1; " +
|
||||||
|
"id: ~~2; placeholders: ~~3;}"
|
||||||
|
|
||||||
|
better = better["~~0"] ~= String(type.rawValue)
|
||||||
|
better = better["~~1"] ~= String(data)
|
||||||
|
better = better["~~2"] ~= String(id)
|
||||||
|
better = better["~~3"] ~= String(placeholders)
|
||||||
|
|
||||||
|
return better
|
||||||
|
}
|
||||||
|
|
||||||
|
var event: String {
|
||||||
|
return data[0] as! String
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetString: String {
|
||||||
|
return createPacketString()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(type: SocketPacket.PacketType, data: [AnyObject] = [AnyObject](), id: Int = -1,
|
||||||
|
nsp: String, placeholders: Int = 0, binary: [NSData] = [NSData]()) {
|
||||||
self.data = data
|
self.data = data
|
||||||
self.nsp = nsp
|
|
||||||
self.placeholders = placeholders
|
|
||||||
self.id = id
|
self.id = id
|
||||||
|
self.nsp = nsp
|
||||||
|
self.type = type
|
||||||
|
self.placeholders = placeholders
|
||||||
|
self.binary = binary
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEvent() -> String {
|
mutating func addData(data: NSData) -> Bool {
|
||||||
return data?.removeAtIndex(0) as! String
|
|
||||||
}
|
|
||||||
|
|
||||||
func addData(data:NSData) -> Bool {
|
|
||||||
if placeholders == currentPlace {
|
if placeholders == currentPlace {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -92,86 +107,22 @@ final class SocketPacket: Printable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMessageForEvent(event:String) -> String {
|
private func completeMessage(var message: String, ack: Bool) -> String {
|
||||||
let message:String
|
if data.count == 0 {
|
||||||
|
|
||||||
if binary.count == 0 {
|
|
||||||
type = PacketType.EVENT
|
|
||||||
|
|
||||||
if nsp == "/" {
|
|
||||||
if id == nil {
|
|
||||||
message = "2[\"\(event)\""
|
|
||||||
} else {
|
|
||||||
message = "2\(id!)[\"\(event)\""
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if id == nil {
|
|
||||||
message = "2/\(nsp),[\"\(event)\""
|
|
||||||
} else {
|
|
||||||
message = "2/\(nsp),\(id!)[\"\(event)\""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type = PacketType.BINARY_EVENT
|
|
||||||
|
|
||||||
if nsp == "/" {
|
|
||||||
if id == nil {
|
|
||||||
message = "5\(binary.count)-[\"\(event)\""
|
|
||||||
} else {
|
|
||||||
message = "5\(binary.count)-\(id!)[\"\(event)\""
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if id == nil {
|
|
||||||
message = "5\(binary.count)-/\(nsp),[\"\(event)\""
|
|
||||||
} else {
|
|
||||||
message = "5\(binary.count)-/\(nsp),\(id!)[\"\(event)\""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return completeMessage(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createAck() -> String {
|
|
||||||
var msg:String
|
|
||||||
|
|
||||||
if binary.count == 0 {
|
|
||||||
type = PacketType.ACK
|
|
||||||
|
|
||||||
if nsp == "/" {
|
|
||||||
msg = "3\(id!)["
|
|
||||||
} else {
|
|
||||||
msg = "3/\(nsp),\(id!)["
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type = PacketType.BINARY_ACK
|
|
||||||
|
|
||||||
if nsp == "/" {
|
|
||||||
msg = "6\(binary.count)-\(id!)["
|
|
||||||
} else {
|
|
||||||
msg = "6\(binary.count)-/\(nsp),\(id!)["
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return completeMessage(msg, ack: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func completeMessage(var message:String, ack:Bool = false) -> String {
|
|
||||||
var err:NSError?
|
|
||||||
|
|
||||||
if data == nil || data!.count == 0 {
|
|
||||||
return message + "]"
|
return message + "]"
|
||||||
} else if !ack {
|
|
||||||
message += ","
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for arg in data! {
|
for arg in data {
|
||||||
if arg is NSDictionary || arg is [AnyObject] {
|
if arg is NSDictionary || arg is [AnyObject] {
|
||||||
let jsonSend = NSJSONSerialization.dataWithJSONObject(arg,
|
do {
|
||||||
options: NSJSONWritingOptions(0), error: &err)
|
let jsonSend = try NSJSONSerialization.dataWithJSONObject(arg,
|
||||||
let jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding)
|
options: NSJSONWritingOptions(rawValue: 0))
|
||||||
|
let jsonString = NSString(data: jsonSend, encoding: NSUTF8StringEncoding)
|
||||||
|
|
||||||
message += jsonString! as String + ","
|
message += jsonString! as String + ","
|
||||||
|
} catch {
|
||||||
|
print("Error creating JSON object in SocketPacket.completeMessage")
|
||||||
|
}
|
||||||
} else if var str = arg as? String {
|
} else if var str = arg as? String {
|
||||||
str = str["\n"] ~= "\\\\n"
|
str = str["\n"] ~= "\\\\n"
|
||||||
str = str["\r"] ~= "\\\\r"
|
str = str["\r"] ~= "\\\\r"
|
||||||
@ -191,29 +142,98 @@ final class SocketPacket: Printable {
|
|||||||
return message + "]"
|
return message + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillInPlaceholders() {
|
private func createAck() -> String {
|
||||||
var newArr = NSMutableArray(array: data!)
|
let msg: String
|
||||||
|
|
||||||
for i in 0..<data!.count {
|
if type == PacketType.Ack {
|
||||||
if let str = data?[i] as? String, num = str["~~(\\d)"].groups() {
|
if nsp == "/" {
|
||||||
newArr[i] = binary[num[1].toInt()!]
|
msg = "3\(id)["
|
||||||
} else if data?[i] is NSDictionary || data?[i] is NSArray {
|
} else {
|
||||||
newArr[i] = _fillInPlaceholders(data![i])
|
msg = "3\(nsp),\(id)["
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if nsp == "/" {
|
||||||
|
msg = "6\(binary.count)-\(id)["
|
||||||
|
} else {
|
||||||
|
msg = "6\(binary.count)-/\(nsp),\(id)["
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completeMessage(msg, ack: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func createMessageForEvent() -> String {
|
||||||
|
let message: String
|
||||||
|
|
||||||
|
if type == PacketType.Event {
|
||||||
|
if nsp == "/" {
|
||||||
|
if id == -1 {
|
||||||
|
message = "2["
|
||||||
|
} else {
|
||||||
|
message = "2\(id)["
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if id == -1 {
|
||||||
|
message = "2\(nsp),["
|
||||||
|
} else {
|
||||||
|
message = "2\(nsp),\(id)["
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if nsp == "/" {
|
||||||
|
if id == -1 {
|
||||||
|
message = "5\(binary.count)-["
|
||||||
|
} else {
|
||||||
|
message = "5\(binary.count)-\(id)["
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if id == -1 {
|
||||||
|
message = "5\(binary.count)-\(nsp),["
|
||||||
|
} else {
|
||||||
|
message = "5\(binary.count)-\(nsp),\(id)["
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completeMessage(message, ack: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createPacketString() -> String {
|
||||||
|
let str: String
|
||||||
|
|
||||||
|
if type == PacketType.Event || type == PacketType.BinaryEvent {
|
||||||
|
str = createMessageForEvent()
|
||||||
|
} else {
|
||||||
|
str = createAck()
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func fillInPlaceholders() {
|
||||||
|
let newArr = NSMutableArray(array: data)
|
||||||
|
|
||||||
|
for i in 0..<data.count {
|
||||||
|
if let str = data[i] as? String, num = str["~~(\\d)"].groups() {
|
||||||
|
newArr[i] = binary[Int(num[1])!]
|
||||||
|
} else if data[i] is NSDictionary || data[i] is NSArray {
|
||||||
|
newArr[i] = _fillInPlaceholders(data[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data = newArr as [AnyObject]
|
data = newArr as [AnyObject]
|
||||||
}
|
}
|
||||||
|
|
||||||
private func _fillInPlaceholders(data:AnyObject) -> AnyObject {
|
private mutating func _fillInPlaceholders(data: AnyObject) -> AnyObject {
|
||||||
if let str = data as? String {
|
if let str = data as? String {
|
||||||
if let num = str["~~(\\d)"].groups() {
|
if let num = str["~~(\\d)"].groups() {
|
||||||
return binary[num[1].toInt()!]
|
return binary[Int(num[1])!]
|
||||||
} else {
|
} else {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
} else if let dict = data as? NSDictionary {
|
} else if let dict = data as? NSDictionary {
|
||||||
var newDict = NSMutableDictionary(dictionary: dict)
|
let newDict = NSMutableDictionary(dictionary: dict)
|
||||||
|
|
||||||
for (key, value) in dict {
|
for (key, value) in dict {
|
||||||
newDict[key as! NSCopying] = _fillInPlaceholders(value)
|
newDict[key as! NSCopying] = _fillInPlaceholders(value)
|
||||||
@ -221,7 +241,7 @@ final class SocketPacket: Printable {
|
|||||||
|
|
||||||
return newDict
|
return newDict
|
||||||
} else if let arr = data as? NSArray {
|
} else if let arr = data as? NSArray {
|
||||||
var newArr = NSMutableArray(array: arr)
|
let newArr = NSMutableArray(array: arr)
|
||||||
|
|
||||||
for i in 0..<arr.count {
|
for i in 0..<arr.count {
|
||||||
newArr[i] = _fillInPlaceholders(arr[i])
|
newArr[i] = _fillInPlaceholders(arr[i])
|
||||||
@ -233,3 +253,73 @@ final class SocketPacket: Printable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension SocketPacket {
|
||||||
|
private static func findType(binCount: Int, ack: Bool) -> PacketType {
|
||||||
|
switch binCount {
|
||||||
|
case 0 where !ack:
|
||||||
|
return PacketType.Event
|
||||||
|
case 0 where ack:
|
||||||
|
return PacketType.Ack
|
||||||
|
case _ where !ack:
|
||||||
|
return PacketType.BinaryEvent
|
||||||
|
case _ where ack:
|
||||||
|
return PacketType.BinaryAck
|
||||||
|
default:
|
||||||
|
return PacketType.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func packetFromEmit(items: [AnyObject], id: Int, nsp: String, ack: Bool) -> SocketPacket {
|
||||||
|
let (parsedData, binary) = deconstructData(items)
|
||||||
|
let packet = SocketPacket(type: findType(binary.count, ack: ack), data: parsedData,
|
||||||
|
id: id, nsp: nsp, placeholders: -1, binary: binary)
|
||||||
|
|
||||||
|
return packet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SocketPacket {
|
||||||
|
static func shred(data: AnyObject, inout binary: [NSData]) -> AnyObject {
|
||||||
|
if let bin = data as? NSData {
|
||||||
|
let placeholder = ["_placeholder" :true, "num": binary.count]
|
||||||
|
|
||||||
|
binary.append(bin)
|
||||||
|
|
||||||
|
return placeholder
|
||||||
|
} else if let arr = data as? NSArray {
|
||||||
|
let newArr = NSMutableArray(array: arr)
|
||||||
|
|
||||||
|
for i in 0..<arr.count {
|
||||||
|
newArr[i] = shred(arr[i], binary: &binary)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newArr
|
||||||
|
} else if let dict = data as? NSDictionary {
|
||||||
|
let newDict = NSMutableDictionary(dictionary: dict)
|
||||||
|
|
||||||
|
for (key, value) in newDict {
|
||||||
|
newDict[key as! NSCopying] = shred(value, binary: &binary)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newDict
|
||||||
|
} else {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func deconstructData(var data: [AnyObject]) -> ([AnyObject], [NSData]) {
|
||||||
|
var binary = [NSData]()
|
||||||
|
|
||||||
|
for i in 0..<data.count {
|
||||||
|
if data[i] is NSArray || data[i] is NSDictionary {
|
||||||
|
data[i] = shred(data[i], binary: &binary)
|
||||||
|
} else if let bin = data[i] as? NSData {
|
||||||
|
data[i] = ["_placeholder" :true, "num": binary.count]
|
||||||
|
binary.append(bin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (data, binary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketParser.swift
|
// SocketParser.swift
|
||||||
// Socket.IO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,73 +23,64 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class SocketParser {
|
class SocketParser {
|
||||||
private static let shredder = SocketParser.PacketShredder()
|
private static func isCorrectNamespace(nsp: String, _ socket: SocketIOClient) -> Bool {
|
||||||
|
return nsp == socket.nsp
|
||||||
// Translation of socket.io-parser#deconstructPacket
|
|
||||||
private final class PacketShredder {
|
|
||||||
var buf = ContiguousArray<NSData>()
|
|
||||||
|
|
||||||
func shred(data:AnyObject) -> AnyObject {
|
|
||||||
if let bin = data as? NSData {
|
|
||||||
let placeholder = ["_placeholder" :true, "num": buf.count]
|
|
||||||
|
|
||||||
buf.append(bin)
|
|
||||||
|
|
||||||
return placeholder
|
|
||||||
} else if let arr = data as? NSArray {
|
|
||||||
var newArr = NSMutableArray(array: arr)
|
|
||||||
|
|
||||||
for i in 0..<arr.count {
|
|
||||||
newArr[i] = shred(arr[i])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newArr
|
private static func handleAck(p: SocketPacket, socket: SocketIOClient) {
|
||||||
} else if let dict = data as? NSDictionary {
|
if !isCorrectNamespace(p.nsp, socket) {
|
||||||
var newDict = NSMutableDictionary(dictionary: dict)
|
|
||||||
|
|
||||||
for (key, value) in newDict {
|
|
||||||
newDict[key as! NSCopying] = shred(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newDict
|
|
||||||
} else {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func deconstructPacket(packet:SocketPacket) {
|
|
||||||
if packet.data == nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = packet.data!
|
socket.handleAck(p.id, data: p.data)
|
||||||
|
}
|
||||||
|
|
||||||
for i in 0..<data.count {
|
private static func handleBinaryAck(p: SocketPacket, socket: SocketIOClient) {
|
||||||
if data[i] is NSArray || data[i] is NSDictionary {
|
if !isCorrectNamespace(p.nsp, socket) {
|
||||||
data[i] = shred(data[i])
|
return
|
||||||
} else if let bin = data[i] as? NSData {
|
}
|
||||||
data[i] = ["_placeholder" :true, "num": buf.count]
|
|
||||||
buf.append(bin)
|
socket.waitingData.append(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func handleBinaryEvent(p: SocketPacket, socket: SocketIOClient) {
|
||||||
|
if !isCorrectNamespace(p.nsp, socket) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.waitingData.append(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func handleConnect(p: SocketPacket, socket: SocketIOClient) {
|
||||||
|
if p.nsp == "/" && socket.nsp != "/" {
|
||||||
|
socket.joinNamespace()
|
||||||
|
} else if p.nsp != "/" && socket.nsp == "/" {
|
||||||
|
socket.didConnect()
|
||||||
|
} else {
|
||||||
|
socket.didConnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.data = data
|
private static func handleEvent(p: SocketPacket, socket: SocketIOClient) {
|
||||||
packet.binary = buf
|
if !isCorrectNamespace(p.nsp, socket) {
|
||||||
buf.removeAll(keepCapacity: true)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.handleEvent(p.event, data: p.args,
|
||||||
|
isInternalMessage: false, wantsAck: p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translation of socket.io-client#decodeString
|
// Translation of socket.io-client#decodeString
|
||||||
static func parseString(str:String) -> SocketPacket? {
|
static func parseString(str: String) -> SocketPacket? {
|
||||||
let arr = Array(str)
|
let arr = Array(str.characters)
|
||||||
let type = String(arr[0])
|
let type = String(arr[0])
|
||||||
|
|
||||||
if arr.count == 1 {
|
if arr.count == 1 {
|
||||||
return SocketPacket(type: SocketPacket.PacketType(str: type))
|
return SocketPacket(type: SocketPacket.PacketType(str: type)!, nsp: "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = nil as Int?
|
var id: Int?
|
||||||
var nsp = ""
|
var nsp:String?
|
||||||
var i = 0
|
var i = 0
|
||||||
var placeholders = -1
|
var placeholders = -1
|
||||||
|
|
||||||
@ -103,7 +94,7 @@ class SocketParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let holders = buf.toInt() where arr[i] == "-" {
|
if let holders = Int(buf) where arr[i] == "-" {
|
||||||
placeholders = holders
|
placeholders = holders
|
||||||
} else {
|
} else {
|
||||||
NSLog("Error parsing \(str)")
|
NSLog("Error parsing \(str)")
|
||||||
@ -112,6 +103,8 @@ class SocketParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if arr[i + 1] == "/" {
|
if arr[i + 1] == "/" {
|
||||||
|
nsp = ""
|
||||||
|
|
||||||
while ++i < arr.count {
|
while ++i < arr.count {
|
||||||
let c = arr[i]
|
let c = arr[i]
|
||||||
|
|
||||||
@ -119,49 +112,56 @@ class SocketParser {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
nsp += String(c)
|
nsp! += String(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i + 1 >= arr.count {
|
if i + 1 >= arr.count {
|
||||||
return SocketPacket(type: SocketPacket.PacketType(str: type),
|
return SocketPacket(type: SocketPacket.PacketType(str: type)!, id: id ?? -1,
|
||||||
nsp: nsp, placeholders: placeholders, id: id)
|
nsp: nsp ?? "/", placeholders: placeholders)
|
||||||
}
|
}
|
||||||
|
|
||||||
let next = String(arr[i + 1])
|
let next = String(arr[i + 1])
|
||||||
|
|
||||||
if next.toInt() != nil {
|
if Int(next) != nil {
|
||||||
var c = ""
|
var c = ""
|
||||||
while ++i < arr.count {
|
while ++i < arr.count {
|
||||||
if let int = String(arr[i]).toInt() {
|
if let int = Int(String(arr[i])) {
|
||||||
c += String(arr[i])
|
c += String(int)
|
||||||
} else {
|
} else {
|
||||||
--i
|
--i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id = c.toInt()
|
id = Int(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ++i < arr.count {
|
if ++i < arr.count {
|
||||||
let d = str[advance(str.startIndex, i)...advance(str.startIndex, count(str)-1)]
|
let d = str[str.startIndex.advancedBy(i)...str.startIndex.advancedBy(str.characters.count-1)]
|
||||||
let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
|
let noPlaceholders = d["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
|
||||||
let data = SocketParser.parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders]
|
let data = SocketParser.parseData(noPlaceholders) as? [AnyObject] ?? [noPlaceholders]
|
||||||
|
|
||||||
return SocketPacket(type: SocketPacket.PacketType(str: type), data: data,
|
return SocketPacket(type: SocketPacket.PacketType(str: type)!, data: data, id: id ?? -1,
|
||||||
nsp: nsp, placeholders: placeholders, id: id)
|
nsp: nsp ?? "/", placeholders: placeholders)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses data for events
|
// Parses data for events
|
||||||
static func parseData(data:String) -> AnyObject? {
|
static func parseData(data: String) -> AnyObject? {
|
||||||
var err:NSError?
|
var err: NSError?
|
||||||
let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
|
let stringData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
|
||||||
let parsed:AnyObject? = NSJSONSerialization.JSONObjectWithData(stringData!,
|
let parsed: AnyObject?
|
||||||
options: NSJSONReadingOptions.MutableContainers, error: &err)
|
|
||||||
|
do {
|
||||||
|
parsed = try NSJSONSerialization.JSONObjectWithData(stringData!,
|
||||||
|
options: NSJSONReadingOptions.MutableContainers)
|
||||||
|
} catch let error as NSError {
|
||||||
|
err = error
|
||||||
|
parsed = nil
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// println(err)
|
// println(err)
|
||||||
@ -171,23 +171,15 @@ class SocketParser {
|
|||||||
return parsed
|
return parsed
|
||||||
}
|
}
|
||||||
|
|
||||||
static func parseForEmit(packet:SocketPacket) {
|
|
||||||
shredder.deconstructPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parses messages recieved
|
// Parses messages recieved
|
||||||
static func parseSocketMessage(stringMessage:String, socket:SocketIOClient) {
|
static func parseSocketMessage(stringMessage: String, socket: SocketIOClient) {
|
||||||
if stringMessage == "" {
|
if stringMessage == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkNSP(nsp:String) -> Bool {
|
|
||||||
return nsp == "" && socket.nsp != "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketLogger.log("Parsing %@", client: socket, altType: "SocketParser", args: stringMessage)
|
SocketLogger.log("Parsing %@", client: socket, altType: "SocketParser", args: stringMessage)
|
||||||
|
|
||||||
let p:SocketPacket
|
let p: SocketPacket
|
||||||
|
|
||||||
if let pack = parseString(stringMessage) {
|
if let pack = parseString(stringMessage) {
|
||||||
p = pack
|
p = pack
|
||||||
@ -196,50 +188,27 @@ class SocketParser {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketLogger.log("Decoded packet as: %@", client: socket, altType: "SocketParser", args: p)
|
SocketLogger.log("Decoded packet as: %@", client: socket, altType: "SocketParser", args: p.description)
|
||||||
|
|
||||||
if p.type == SocketPacket.PacketType.EVENT {
|
switch p.type {
|
||||||
if checkNSP(p.nsp) {
|
case SocketPacket.PacketType.Event:
|
||||||
return
|
handleEvent(p, socket: socket)
|
||||||
}
|
case SocketPacket.PacketType.Ack:
|
||||||
|
handleAck(p, socket: socket)
|
||||||
socket.handleEvent(p.getEvent(), data: p.data,
|
case SocketPacket.PacketType.BinaryEvent:
|
||||||
isInternalMessage: false, wantsAck: p.id)
|
handleBinaryEvent(p, socket: socket)
|
||||||
} else if p.type == SocketPacket.PacketType.ACK {
|
case SocketPacket.PacketType.BinaryAck:
|
||||||
if checkNSP(p.nsp) {
|
handleBinaryAck(p, socket: socket)
|
||||||
return
|
case SocketPacket.PacketType.Connect:
|
||||||
}
|
handleConnect(p, socket: socket)
|
||||||
|
case SocketPacket.PacketType.Disconnect:
|
||||||
socket.handleAck(p.id!, data: p.data)
|
|
||||||
} else if p.type == SocketPacket.PacketType.BINARY_EVENT {
|
|
||||||
if checkNSP(p.nsp) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.waitingData.append(p)
|
|
||||||
} else if p.type == SocketPacket.PacketType.BINARY_ACK {
|
|
||||||
if checkNSP(p.nsp) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.justAck = true
|
|
||||||
socket.waitingData.append(p)
|
|
||||||
} else if p.type == SocketPacket.PacketType.CONNECT {
|
|
||||||
if p.nsp == "" && socket.nsp != "/" {
|
|
||||||
socket.joinNamespace()
|
|
||||||
} else if p.nsp != "" && socket.nsp == "/" {
|
|
||||||
socket.didConnect()
|
|
||||||
} else {
|
|
||||||
socket.didConnect()
|
|
||||||
}
|
|
||||||
} else if p.type == SocketPacket.PacketType.DISCONNECT {
|
|
||||||
socket.didDisconnect("Got Disconnect")
|
socket.didDisconnect("Got Disconnect")
|
||||||
} else if p.type == SocketPacket.PacketType.ERROR {
|
case SocketPacket.PacketType.Error:
|
||||||
socket.didError(p.data == nil ? "Error" : p.data!)
|
socket.didError("Error: \(p.data)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func parseBinaryData(data:NSData, socket:SocketIOClient) {
|
static func parseBinaryData(data: NSData, socket: SocketIOClient) {
|
||||||
if socket.waitingData.count == 0 {
|
if socket.waitingData.count == 0 {
|
||||||
SocketLogger.err("Got data when not remaking packet", client: socket, altType: "SocketParser")
|
SocketLogger.err("Got data when not remaking packet", client: socket, altType: "SocketParser")
|
||||||
return
|
return
|
||||||
@ -251,14 +220,14 @@ class SocketParser {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let packet = socket.waitingData.removeAtIndex(0)
|
var packet = socket.waitingData.removeAtIndex(0)
|
||||||
packet.fillInPlaceholders()
|
packet.fillInPlaceholders()
|
||||||
|
|
||||||
if !packet.justAck {
|
if packet.type != SocketPacket.PacketType.BinaryAck {
|
||||||
socket.handleEvent(packet.getEvent(), data: packet.data,
|
socket.handleEvent(packet.event, data: packet.args,
|
||||||
wantsAck: packet.id)
|
isInternalMessage: false, wantsAck: packet.id)
|
||||||
} else {
|
} else {
|
||||||
socket.handleAck(packet.id!, data: packet.data)
|
socket.handleAck(packet.id, data: packet.args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SocketTypes.swift
|
// SocketTypes.swift
|
||||||
// SocketIO-Swift
|
// Socket.IO-Client-Swift
|
||||||
//
|
//
|
||||||
// Created by Erik Little on 4/8/15.
|
// Created by Erik Little on 4/8/15.
|
||||||
//
|
//
|
||||||
@ -24,11 +24,10 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
// @objc_block is undocumented, but is used because Swift assumes that all
|
public typealias AckCallback = (NSArray?) -> Void
|
||||||
// Objective-C blocks are copied, but Objective-C assumes that Swift will copy it.
|
|
||||||
// And the way things are done here, the bridging fails to copy the block in
|
|
||||||
// SocketAckMap#addAck
|
|
||||||
public typealias AckCallback = @objc_block (NSArray?) -> Void
|
|
||||||
public typealias AckEmitter = (AnyObject...) -> Void
|
public typealias AckEmitter = (AnyObject...) -> Void
|
||||||
|
public typealias AckEmitterObjectiveC = (NSArray) -> Void
|
||||||
public typealias NormalCallback = (NSArray?, AckEmitter?) -> Void
|
public typealias NormalCallback = (NSArray?, AckEmitter?) -> Void
|
||||||
public typealias OnAckCallback = (timeout:UInt64, callback:AckCallback) -> Void
|
public typealias NormalCallbackObjectiveC = (NSArray?, AckEmitterObjectiveC?) -> Void
|
||||||
|
public typealias OnAckCallback = (timeoutAfter:UInt64, callback:AckCallback) -> Void
|
||||||
|
|
||||||
|
|||||||
@ -19,18 +19,18 @@ public class SwiftRegex: NSObject, BooleanType {
|
|||||||
var target:String
|
var target:String
|
||||||
var regex: NSRegularExpression
|
var regex: NSRegularExpression
|
||||||
|
|
||||||
init(target:String, pattern:String, options:NSRegularExpressionOptions = nil) {
|
init(target:String, pattern:String, options:NSRegularExpressionOptions?) {
|
||||||
self.target = target
|
self.target = target
|
||||||
if let regex = swiftRegexCache[pattern] {
|
if let regex = swiftRegexCache[pattern] {
|
||||||
self.regex = regex
|
self.regex = regex
|
||||||
} else {
|
} else {
|
||||||
var error: NSError?
|
do {
|
||||||
if let regex = NSRegularExpression(pattern: pattern, options:options, error:&error) {
|
let regex = try NSRegularExpression(pattern: pattern, options:
|
||||||
|
NSRegularExpressionOptions.DotMatchesLineSeparators)
|
||||||
swiftRegexCache[pattern] = regex
|
swiftRegexCache[pattern] = regex
|
||||||
self.regex = regex
|
self.regex = regex
|
||||||
}
|
} catch let error1 as NSError {
|
||||||
else {
|
SwiftRegex.failure("Error in pattern: \(pattern) - \(error1)")
|
||||||
SwiftRegex.failure("Error in pattern: \(pattern) - \(error)")
|
|
||||||
self.regex = NSRegularExpression()
|
self.regex = NSRegularExpression()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,12 +38,12 @@ public class SwiftRegex: NSObject, BooleanType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class func failure(message: String) {
|
class func failure(message: String) {
|
||||||
println("SwiftRegex: "+message)
|
print("SwiftRegex: "+message)
|
||||||
//assert(false,"SwiftRegex: failed")
|
//assert(false,"SwiftRegex: failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
final var targetRange: NSRange {
|
final var targetRange: NSRange {
|
||||||
return NSRange(location: 0,length: count(target.utf16))
|
return NSRange(location: 0,length: target.utf16.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
final func substring(range: NSRange) -> String? {
|
final func substring(range: NSRange) -> String? {
|
||||||
@ -54,20 +54,21 @@ public class SwiftRegex: NSObject, BooleanType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func doesMatch(options: NSMatchingOptions = nil) -> Bool {
|
public func doesMatch(options: NSMatchingOptions!) -> Bool {
|
||||||
return range(options: options).location != NSNotFound
|
return range(options).location != NSNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
public func range(options: NSMatchingOptions = nil) -> NSRange {
|
public func range(options: NSMatchingOptions) -> NSRange {
|
||||||
return regex.rangeOfFirstMatchInString(target as String, options: nil, range: targetRange)
|
return regex.rangeOfFirstMatchInString(target as String, options: [], range: targetRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func match(options: NSMatchingOptions = nil) -> String? {
|
public func match(options: NSMatchingOptions) -> String? {
|
||||||
return substring(range(options: options))
|
return substring(range(options))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func groups(options: NSMatchingOptions = nil) -> [String]? {
|
public func groups() -> [String]? {
|
||||||
return groupsForMatch(regex.firstMatchInString(target as String, options: options, range: targetRange))
|
return groupsForMatch(regex.firstMatchInString(target as String, options:
|
||||||
|
NSMatchingOptions.WithoutAnchoringBounds, range: targetRange))
|
||||||
}
|
}
|
||||||
|
|
||||||
func groupsForMatch(match: NSTextCheckingResult!) -> [String]? {
|
func groupsForMatch(match: NSTextCheckingResult!) -> [String]? {
|
||||||
@ -96,7 +97,7 @@ public class SwiftRegex: NSObject, BooleanType {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for match in matchResults()!.reverse() {
|
for match in Array(matchResults().reverse()) {
|
||||||
let replacement = regex.replacementStringForResult(match,
|
let replacement = regex.replacementStringForResult(match,
|
||||||
inString: target as String, offset: 0, template: newValue!)
|
inString: target as String, offset: 0, template: newValue!)
|
||||||
let mut = NSMutableString(string: target)
|
let mut = NSMutableString(string: target)
|
||||||
@ -107,48 +108,43 @@ public class SwiftRegex: NSObject, BooleanType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchResults(options: NSMatchingOptions = nil) -> [NSTextCheckingResult]? {
|
func matchResults() -> [NSTextCheckingResult] {
|
||||||
let matches = regex.matchesInString(target as String, options: options, range: targetRange)
|
let matches = regex.matchesInString(target as String, options:
|
||||||
as? [NSTextCheckingResult]
|
NSMatchingOptions.WithoutAnchoringBounds, range: targetRange)
|
||||||
|
as [NSTextCheckingResult]
|
||||||
|
|
||||||
if matches != nil {
|
return matches
|
||||||
return matches!
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ranges(options: NSMatchingOptions = nil) -> [NSRange] {
|
public func ranges() -> [NSRange] {
|
||||||
return matchResults(options: options)!.map { $0.range }
|
return matchResults().map { $0.range }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func matches(options: NSMatchingOptions = nil) -> [String] {
|
public func matches() -> [String] {
|
||||||
return matchResults(options: options)!.map( { self.substring($0.range)!})
|
return matchResults().map( { self.substring($0.range)!})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func allGroups(options: NSMatchingOptions = nil) -> [[String]?] {
|
public func allGroups() -> [[String]?] {
|
||||||
return matchResults(options: options)!.map {self.groupsForMatch($0)}
|
return matchResults().map {self.groupsForMatch($0)}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dictionary(options: NSMatchingOptions = nil) -> Dictionary<String,String> {
|
public func dictionary(options: NSMatchingOptions!) -> Dictionary<String,String> {
|
||||||
var out = Dictionary<String,String>()
|
var out = Dictionary<String,String>()
|
||||||
for match in matchResults(options: options)! {
|
for match in matchResults() {
|
||||||
out[substring(match.rangeAtIndex(1))!] = substring(match.rangeAtIndex(2))!
|
out[substring(match.rangeAtIndex(1))!] = substring(match.rangeAtIndex(2))!
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func substituteMatches(substitution: ((NSTextCheckingResult, UnsafeMutablePointer<ObjCBool>) -> String),
|
func substituteMatches(substitution: ((NSTextCheckingResult, UnsafeMutablePointer<ObjCBool>) -> String),
|
||||||
options:NSMatchingOptions = nil) -> String {
|
options:NSMatchingOptions) -> String {
|
||||||
let out = NSMutableString()
|
let out = NSMutableString()
|
||||||
var pos = 0
|
var pos = 0
|
||||||
|
|
||||||
regex.enumerateMatchesInString(target as String, options: options, range: targetRange ) {
|
regex.enumerateMatchesInString(target as String, options: options, range: targetRange ) {match, flags, stop in
|
||||||
(match: NSTextCheckingResult!, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) in
|
let matchRange = match!.range
|
||||||
|
|
||||||
let matchRange = match.range
|
|
||||||
out.appendString( self.substring(NSRange(location:pos, length:matchRange.location-pos))!)
|
out.appendString( self.substring(NSRange(location:pos, length:matchRange.location-pos))!)
|
||||||
out.appendString( substitution(match, stop) )
|
out.appendString( substitution(match!, stop) )
|
||||||
pos = matchRange.location + matchRange.length
|
pos = matchRange.location + matchRange.length
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +154,7 @@ public class SwiftRegex: NSObject, BooleanType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var boolValue: Bool {
|
public var boolValue: Bool {
|
||||||
return doesMatch()
|
return doesMatch(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +166,7 @@ extension String {
|
|||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
public subscript(pattern: String) -> SwiftRegex {
|
public subscript(pattern: String) -> SwiftRegex {
|
||||||
return SwiftRegex(target: self, pattern: pattern)
|
return SwiftRegex(target: self, pattern: pattern, options: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +174,7 @@ public func ~= (left: SwiftRegex, right: String) -> String {
|
|||||||
return left.substituteMatches({match, stop in
|
return left.substituteMatches({match, stop in
|
||||||
return left.regex.replacementStringForResult( match,
|
return left.regex.replacementStringForResult( match,
|
||||||
inString: left.target as String, offset: 0, template: right )
|
inString: left.target as String, offset: 0, template: right )
|
||||||
}, options: nil)
|
}, options: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ~= (left: SwiftRegex, right: [String]) -> String {
|
public func ~= (left: SwiftRegex, right: [String]) -> String {
|
||||||
@ -191,7 +187,7 @@ public func ~= (left: SwiftRegex, right: [String]) -> String {
|
|||||||
|
|
||||||
return left.regex.replacementStringForResult( match,
|
return left.regex.replacementStringForResult( match,
|
||||||
inString: left.target as String, offset: 0, template: right[matchNumber-1] )
|
inString: left.target as String, offset: 0, template: right[matchNumber-1] )
|
||||||
}, options: nil)
|
}, options: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ~= (left: SwiftRegex, right: (String) -> String) -> String {
|
public func ~= (left: SwiftRegex, right: (String) -> String) -> String {
|
||||||
@ -199,11 +195,11 @@ public func ~= (left: SwiftRegex, right: (String) -> String) -> String {
|
|||||||
return left.substituteMatches(
|
return left.substituteMatches(
|
||||||
{match, stop -> String in
|
{match, stop -> String in
|
||||||
right(left.substring(match.range)!)
|
right(left.substring(match.range)!)
|
||||||
}, options: nil)
|
}, options: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ~= (left: SwiftRegex, right: ([String]?) -> String) -> String {
|
public func ~= (left: SwiftRegex, right: ([String]?) -> String) -> String {
|
||||||
return left.substituteMatches({match, stop -> String in
|
return left.substituteMatches({match, stop -> String in
|
||||||
return right(left.groupsForMatch(match))
|
return right(left.groupsForMatch(match))
|
||||||
}, options: nil)
|
}, options: [])
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
public var headers = Dictionary<String,String>()
|
public var headers = Dictionary<String,String>()
|
||||||
public var voipEnabled = false
|
public var voipEnabled = false
|
||||||
public var selfSignedSSL = false
|
public var selfSignedSSL = false
|
||||||
public var security: Security?
|
private var security: Security?
|
||||||
public var isConnected :Bool {
|
public var isConnected :Bool {
|
||||||
return connected
|
return connected
|
||||||
}
|
}
|
||||||
@ -168,7 +168,6 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
//private method that starts the connection
|
//private method that starts the connection
|
||||||
private func createHTTPRequest() {
|
private func createHTTPRequest() {
|
||||||
|
|
||||||
let str: NSString = url.absoluteString!
|
|
||||||
let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET",
|
let urlRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, "GET",
|
||||||
url, kCFHTTPVersion1_1).takeRetainedValue()
|
url, kCFHTTPVersion1_1).takeRetainedValue()
|
||||||
|
|
||||||
@ -184,24 +183,25 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
if self.cookies != nil {
|
if self.cookies != nil {
|
||||||
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(self.cookies!)
|
let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(self.cookies!)
|
||||||
for (key, value) in headers {
|
for (key, value) in headers {
|
||||||
self.addHeader(urlRequest, key: key as! String, val: value as! String)
|
self.addHeader(urlRequest, key: key as String, val: value as String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addHeader(urlRequest, key: headerWSUpgradeName, val: headerWSUpgradeValue)
|
self.addHeader(urlRequest, key: headerWSUpgradeName, val: headerWSUpgradeValue)
|
||||||
self.addHeader(urlRequest, key: headerWSConnectionName, val: headerWSConnectionValue)
|
self.addHeader(urlRequest, key: headerWSConnectionName, val: headerWSConnectionValue)
|
||||||
if let protocols = optionalProtocols {
|
if let protocols = optionalProtocols {
|
||||||
self.addHeader(urlRequest, key: headerWSProtocolName, val: ",".join(protocols))
|
self.addHeader(urlRequest, key: headerWSProtocolName, val: protocols.joinWithSeparator(","))
|
||||||
}
|
}
|
||||||
self.addHeader(urlRequest, key: headerWSVersionName, val: headerWSVersionValue)
|
self.addHeader(urlRequest, key: headerWSVersionName, val: headerWSVersionValue)
|
||||||
self.addHeader(urlRequest, key: headerWSKeyName, val: self.generateWebSocketKey())
|
self.addHeader(urlRequest, key: headerWSKeyName, val: self.generateWebSocketKey())
|
||||||
self.addHeader(urlRequest, key: headerOriginName, val: url.absoluteString!)
|
self.addHeader(urlRequest, key: headerOriginName, val: url.absoluteString)
|
||||||
self.addHeader(urlRequest, key: headerWSHostName, val: "\(url.host!):\(port!)")
|
self.addHeader(urlRequest, key: headerWSHostName, val: "\(url.host!):\(port!)")
|
||||||
for (key,value) in headers {
|
for (key,value) in headers {
|
||||||
self.addHeader(urlRequest, key: key, val: value)
|
self.addHeader(urlRequest, key: key, val: value)
|
||||||
}
|
}
|
||||||
|
|
||||||
let serializedRequest: NSData = CFHTTPMessageCopySerializedMessage(urlRequest).takeRetainedValue()
|
|
||||||
|
let serializedRequest: NSData = CFHTTPMessageCopySerializedMessage(urlRequest)!.takeRetainedValue()
|
||||||
self.initStreamsWithData(serializedRequest, Int(port!))
|
self.initStreamsWithData(serializedRequest, Int(port!))
|
||||||
}
|
}
|
||||||
//Add a header to the CFHTTPMessage by using the NSString bridges to CFString
|
//Add a header to the CFHTTPMessage by using the NSString bridges to CFString
|
||||||
@ -220,8 +220,8 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let uni = UnicodeScalar(UInt32(97 + arc4random_uniform(25)))
|
let uni = UnicodeScalar(UInt32(97 + arc4random_uniform(25)))
|
||||||
key += "\(Character(uni))"
|
key += "\(Character(uni))"
|
||||||
}
|
}
|
||||||
var data = key.dataUsingEncoding(NSUTF8StringEncoding)
|
let data = key.dataUsingEncoding(NSUTF8StringEncoding)
|
||||||
var baseKey = data?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(0))
|
let baseKey = data?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
|
||||||
return baseKey!
|
return baseKey!
|
||||||
}
|
}
|
||||||
//Start the stream connection and write the data to the output stream
|
//Start the stream connection and write the data to the output stream
|
||||||
@ -250,8 +250,8 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
}
|
}
|
||||||
if self.selfSignedSSL {
|
if self.selfSignedSSL {
|
||||||
let settings: Dictionary<NSObject, NSObject> = [kCFStreamSSLValidatesCertificateChain: NSNumber(bool:false), kCFStreamSSLPeerName: kCFNull]
|
let settings: Dictionary<NSObject, NSObject> = [kCFStreamSSLValidatesCertificateChain: NSNumber(bool:false), kCFStreamSSLPeerName: kCFNull]
|
||||||
inputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as! String)
|
inputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String)
|
||||||
outputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as! String)
|
outputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String)
|
||||||
}
|
}
|
||||||
isRunLoop = true
|
isRunLoop = true
|
||||||
inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
|
inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
|
||||||
@ -261,16 +261,16 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let bytes = UnsafePointer<UInt8>(data.bytes)
|
let bytes = UnsafePointer<UInt8>(data.bytes)
|
||||||
outputStream!.write(bytes, maxLength: data.length)
|
outputStream!.write(bytes, maxLength: data.length)
|
||||||
while(isRunLoop) {
|
while(isRunLoop) {
|
||||||
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture() as! NSDate)
|
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture() as NSDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//delegate for the stream methods. Processes incoming bytes
|
//delegate for the stream methods. Processes incoming bytes
|
||||||
public func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
|
public func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
|
||||||
|
|
||||||
if let sec = security where !certValidated && (eventCode == .HasBytesAvailable || eventCode == .HasSpaceAvailable) {
|
if let sec = security where !certValidated && (eventCode == .HasBytesAvailable || eventCode == .HasSpaceAvailable) {
|
||||||
var possibleTrust: AnyObject? = aStream.propertyForKey(kCFStreamPropertySSLPeerTrust as! String)
|
let possibleTrust: AnyObject? = aStream.propertyForKey(kCFStreamPropertySSLPeerTrust as String)
|
||||||
if let trust: AnyObject = possibleTrust {
|
if let trust: AnyObject = possibleTrust {
|
||||||
var domain: AnyObject? = aStream.propertyForKey(kCFStreamSSLPeerName as! String)
|
let domain: AnyObject? = aStream.propertyForKey(kCFStreamSSLPeerName as String)
|
||||||
if sec.isValid(trust as! SecTrustRef, domain: domain as! String?) {
|
if sec.isValid(trust as! SecTrustRef, domain: domain as! String?) {
|
||||||
certValidated = true
|
certValidated = true
|
||||||
} else {
|
} else {
|
||||||
@ -314,7 +314,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
///handles the incoming bytes and sending them to the proper processing method
|
///handles the incoming bytes and sending them to the proper processing method
|
||||||
private func processInputStream() {
|
private func processInputStream() {
|
||||||
let buf = NSMutableData(capacity: BUFFER_MAX)
|
let buf = NSMutableData(capacity: BUFFER_MAX)
|
||||||
var buffer = UnsafeMutablePointer<UInt8>(buf!.bytes)
|
let buffer = UnsafeMutablePointer<UInt8>(buf!.bytes)
|
||||||
let length = inputStream!.read(buffer, maxLength: BUFFER_MAX)
|
let length = inputStream!.read(buffer, maxLength: BUFFER_MAX)
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
if !connected {
|
if !connected {
|
||||||
@ -340,7 +340,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let data = inputQueue[0]
|
let data = inputQueue[0]
|
||||||
var work = data
|
var work = data
|
||||||
if (fragBuffer != nil) {
|
if (fragBuffer != nil) {
|
||||||
var combine = NSMutableData(data: fragBuffer!)
|
let combine = NSMutableData(data: fragBuffer!)
|
||||||
combine.appendData(data)
|
combine.appendData(data)
|
||||||
work = combine
|
work = combine
|
||||||
fragBuffer = nil
|
fragBuffer = nil
|
||||||
@ -388,14 +388,14 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
|
|
||||||
///validates the HTTP is a 101 as per the RFC spec
|
///validates the HTTP is a 101 as per the RFC spec
|
||||||
private func validateResponse(buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Bool {
|
private func validateResponse(buffer: UnsafePointer<UInt8>, bufferLen: Int) -> Bool {
|
||||||
let response = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, 0).takeRetainedValue()
|
let response = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, false).takeRetainedValue()
|
||||||
CFHTTPMessageAppendBytes(response, buffer, bufferLen)
|
CFHTTPMessageAppendBytes(response, buffer, bufferLen)
|
||||||
if CFHTTPMessageGetResponseStatusCode(response) != 101 {
|
if CFHTTPMessageGetResponseStatusCode(response) != 101 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response)
|
let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response)
|
||||||
let headers: NSDictionary = cfHeaders.takeRetainedValue()
|
let headers:NSDictionary? = cfHeaders?.takeRetainedValue()
|
||||||
let acceptKey = headers[headerWSAcceptName] as! NSString
|
let acceptKey = headers?[headerWSAcceptName] as! NSString
|
||||||
if acceptKey.length > 0 {
|
if acceptKey.length > 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -404,7 +404,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
|
|
||||||
///process the websocket data
|
///process the websocket data
|
||||||
private func processRawMessage(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
private func processRawMessage(buffer: UnsafePointer<UInt8>, bufferLen: Int) {
|
||||||
var response = readStack.last
|
let response = readStack.last
|
||||||
if response != nil && bufferLen < 2 {
|
if response != nil && bufferLen < 2 {
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
||||||
return
|
return
|
||||||
@ -420,7 +420,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
resp.bytesLeft -= len
|
resp.bytesLeft -= len
|
||||||
resp.buffer?.appendData(NSData(bytes: buffer, length: len))
|
resp.buffer?.appendData(NSData(bytes: buffer, length: len))
|
||||||
processResponse(resp)
|
processResponse(resp)
|
||||||
var offset = bufferLen - extra
|
let offset = bufferLen - extra
|
||||||
if extra > 0 {
|
if extra > 0 {
|
||||||
processExtra((buffer+offset), bufferLen: extra)
|
processExtra((buffer+offset), bufferLen: extra)
|
||||||
}
|
}
|
||||||
@ -459,7 +459,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
if payloadLen == 1 {
|
if payloadLen == 1 {
|
||||||
code = CloseCode.ProtocolError.rawValue
|
code = CloseCode.ProtocolError.rawValue
|
||||||
} else if payloadLen > 1 {
|
} else if payloadLen > 1 {
|
||||||
var codeBuffer = UnsafePointer<UInt16>((buffer+offset))
|
let codeBuffer = UnsafePointer<UInt16>((buffer+offset))
|
||||||
code = codeBuffer[0].bigEndian
|
code = codeBuffer[0].bigEndian
|
||||||
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
|
||||||
@ -470,7 +470,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let len = Int(payloadLen-2)
|
let len = Int(payloadLen-2)
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let bytes = UnsafePointer<UInt8>((buffer+offset))
|
let bytes = UnsafePointer<UInt8>((buffer+offset))
|
||||||
var 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
|
||||||
}
|
}
|
||||||
@ -495,7 +495,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
dataLength = UInt64(bytes[0].bigEndian)
|
dataLength = UInt64(bytes[0].bigEndian)
|
||||||
offset += sizeof(UInt16)
|
offset += sizeof(UInt16)
|
||||||
}
|
}
|
||||||
if bufferLen < offset {
|
if bufferLen < offset || UInt64(bufferLen - offset) < dataLength {
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -599,16 +599,16 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
let data = response.buffer! //local copy so it is perverse for writing
|
let data = response.buffer! //local copy so it is perverse for writing
|
||||||
dequeueWrite(data, code: OpCode.Pong)
|
dequeueWrite(data, code: OpCode.Pong)
|
||||||
} else if response.code == .TextFrame {
|
} else if response.code == .TextFrame {
|
||||||
var str: NSString? = NSString(data: response.buffer!, encoding: NSUTF8StringEncoding)
|
let str: NSString? = NSString(data: response.buffer!, encoding: NSUTF8StringEncoding)
|
||||||
if str == nil {
|
if str == nil {
|
||||||
writeError(CloseCode.Encoding.rawValue)
|
writeError(CloseCode.Encoding.rawValue)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
dispatch_async(queue,{
|
dispatch_async(queue,{
|
||||||
if let textBlock = self.onText {
|
if let textBlock = self.onText {
|
||||||
textBlock(str! as! String)
|
textBlock(str! as String)
|
||||||
}
|
}
|
||||||
self.delegate?.websocketDidReceiveMessage(self, text: str! as! String)
|
self.delegate?.websocketDidReceiveMessage(self, text: str! as String)
|
||||||
})
|
})
|
||||||
} else if response.code == .BinaryFrame {
|
} else if response.code == .BinaryFrame {
|
||||||
let data = response.buffer! //local copy so it is perverse for writing
|
let data = response.buffer! //local copy so it is perverse for writing
|
||||||
@ -635,7 +635,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
///write a an error to the socket
|
///write a an error to the socket
|
||||||
private func writeError(code: UInt16) {
|
private func writeError(code: UInt16) {
|
||||||
let buf = NSMutableData(capacity: sizeof(UInt16))
|
let buf = NSMutableData(capacity: sizeof(UInt16))
|
||||||
var buffer = UnsafeMutablePointer<UInt16>(buf!.bytes)
|
let buffer = UnsafeMutablePointer<UInt16>(buf!.bytes)
|
||||||
buffer[0] = code.bigEndian
|
buffer[0] = code.bigEndian
|
||||||
dequeueWrite(NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose)
|
dequeueWrite(NSData(bytes: buffer, length: sizeof(UInt16)), code: .ConnectionClose)
|
||||||
}
|
}
|
||||||
@ -670,17 +670,17 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
buffer[1] = CUnsignedChar(dataLength)
|
buffer[1] = CUnsignedChar(dataLength)
|
||||||
} else if dataLength <= Int(UInt16.max) {
|
} else if dataLength <= Int(UInt16.max) {
|
||||||
buffer[1] = 126
|
buffer[1] = 126
|
||||||
var sizeBuffer = UnsafeMutablePointer<UInt16>((buffer+offset))
|
let sizeBuffer = UnsafeMutablePointer<UInt16>((buffer+offset))
|
||||||
sizeBuffer[0] = UInt16(dataLength).bigEndian
|
sizeBuffer[0] = UInt16(dataLength).bigEndian
|
||||||
offset += sizeof(UInt16)
|
offset += sizeof(UInt16)
|
||||||
} else {
|
} else {
|
||||||
buffer[1] = 127
|
buffer[1] = 127
|
||||||
var sizeBuffer = UnsafeMutablePointer<UInt64>((buffer+offset))
|
let sizeBuffer = UnsafeMutablePointer<UInt64>((buffer+offset))
|
||||||
sizeBuffer[0] = UInt64(dataLength).bigEndian
|
sizeBuffer[0] = UInt64(dataLength).bigEndian
|
||||||
offset += sizeof(UInt64)
|
offset += sizeof(UInt64)
|
||||||
}
|
}
|
||||||
buffer[1] |= self.MaskMask
|
buffer[1] |= self.MaskMask
|
||||||
var maskKey = UnsafeMutablePointer<UInt8>(buffer + offset)
|
let maskKey = UnsafeMutablePointer<UInt8>(buffer + offset)
|
||||||
SecRandomCopyBytes(kSecRandomDefault, Int(sizeof(UInt32)), maskKey)
|
SecRandomCopyBytes(kSecRandomDefault, Int(sizeof(UInt32)), maskKey)
|
||||||
offset += sizeof(UInt32)
|
offset += sizeof(UInt32)
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
let writeBuffer = UnsafePointer<UInt8>(frame!.bytes+total)
|
let writeBuffer = UnsafePointer<UInt8>(frame!.bytes+total)
|
||||||
var len = self.outputStream?.write(writeBuffer, maxLength: offset-total)
|
let len = self.outputStream?.write(writeBuffer, maxLength: offset-total)
|
||||||
if len == nil || len! < 0 {
|
if len == nil || len! < 0 {
|
||||||
var error: NSError?
|
var error: NSError?
|
||||||
if let streamError = self.outputStream?.streamError {
|
if let streamError = self.outputStream?.streamError {
|
||||||
@ -771,8 +771,8 @@ public class SSLCert {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Security {
|
private class Security {
|
||||||
public var validatedDN = true //should the domain name be validated?
|
private var validatedDN = true //should the domain name be validated?
|
||||||
|
|
||||||
var isReady = false //is the key processing done?
|
var isReady = false //is the key processing done?
|
||||||
var certificates: [NSData]? //the certificates
|
var certificates: [NSData]? //the certificates
|
||||||
@ -786,11 +786,11 @@ public class Security {
|
|||||||
|
|
||||||
:returns: a representation security object to be used with
|
:returns: a representation security object to be used with
|
||||||
*/
|
*/
|
||||||
public convenience init(usePublicKeys: Bool = false) {
|
private convenience init(usePublicKeys: Bool = false) {
|
||||||
let paths = NSBundle.mainBundle().pathsForResourcesOfType("cer", inDirectory: ".")
|
let paths = NSBundle.mainBundle().pathsForResourcesOfType("cer", inDirectory: ".")
|
||||||
var collect = Array<SSLCert>()
|
var collect = Array<SSLCert>()
|
||||||
for path in paths {
|
for path in paths {
|
||||||
if let d = NSData(contentsOfFile: path as! String) {
|
if let d = NSData(contentsOfFile: path as String) {
|
||||||
collect.append(SSLCert(data: d))
|
collect.append(SSLCert(data: d))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -805,7 +805,7 @@ public class Security {
|
|||||||
|
|
||||||
:returns: a representation security object to be used with
|
:returns: a representation security object to be used with
|
||||||
*/
|
*/
|
||||||
public init(certs: [SSLCert], usePublicKeys: Bool) {
|
private init(certs: [SSLCert], usePublicKeys: Bool) {
|
||||||
self.usePublicKeys = usePublicKeys
|
self.usePublicKeys = usePublicKeys
|
||||||
|
|
||||||
if self.usePublicKeys {
|
if self.usePublicKeys {
|
||||||
@ -842,7 +842,7 @@ public class Security {
|
|||||||
|
|
||||||
:returns: if the key was successfully validated
|
:returns: if the key was successfully validated
|
||||||
*/
|
*/
|
||||||
public func isValid(trust: SecTrustRef, domain: String?) -> Bool {
|
private func isValid(trust: SecTrustRef, domain: String?) -> Bool {
|
||||||
|
|
||||||
var tries = 0
|
var tries = 0
|
||||||
while(!self.isReady) {
|
while(!self.isReady) {
|
||||||
@ -854,9 +854,9 @@ public class Security {
|
|||||||
}
|
}
|
||||||
var policy: SecPolicyRef
|
var policy: SecPolicyRef
|
||||||
if self.validatedDN {
|
if self.validatedDN {
|
||||||
policy = SecPolicyCreateSSL(1, domain).takeRetainedValue()
|
policy = SecPolicyCreateSSL(true, domain)
|
||||||
} else {
|
} else {
|
||||||
policy = SecPolicyCreateBasicX509().takeRetainedValue()
|
policy = SecPolicyCreateBasicX509()
|
||||||
}
|
}
|
||||||
SecTrustSetPolicies(trust,policy)
|
SecTrustSetPolicies(trust,policy)
|
||||||
if self.usePublicKeys {
|
if self.usePublicKeys {
|
||||||
@ -879,7 +879,7 @@ public class Security {
|
|||||||
let serverCerts = certificateChainForTrust(trust)
|
let serverCerts = certificateChainForTrust(trust)
|
||||||
var collect = Array<SecCertificate>()
|
var collect = Array<SecCertificate>()
|
||||||
for cert in certs {
|
for cert in certs {
|
||||||
collect.append(SecCertificateCreateWithData(nil,cert).takeRetainedValue())
|
collect.append(SecCertificateCreateWithData(nil,cert)!)
|
||||||
}
|
}
|
||||||
SecTrustSetAnchorCertificates(trust,collect)
|
SecTrustSetAnchorCertificates(trust,collect)
|
||||||
var result: SecTrustResultType = 0
|
var result: SecTrustResultType = 0
|
||||||
@ -911,10 +911,9 @@ public class Security {
|
|||||||
:returns: a public key
|
:returns: a public key
|
||||||
*/
|
*/
|
||||||
func extractPublicKey(data: NSData) -> SecKeyRef? {
|
func extractPublicKey(data: NSData) -> SecKeyRef? {
|
||||||
var publicKey: NSData?
|
|
||||||
let possibleCert = SecCertificateCreateWithData(nil,data)
|
let possibleCert = SecCertificateCreateWithData(nil,data)
|
||||||
if let cert = possibleCert {
|
if let cert = possibleCert {
|
||||||
return extractPublicKeyFromCert(cert.takeRetainedValue(),policy: SecPolicyCreateBasicX509().takeRetainedValue())
|
return extractPublicKeyFromCert(cert,policy: SecPolicyCreateBasicX509())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -927,13 +926,12 @@ public class Security {
|
|||||||
:returns: a public key
|
:returns: a public key
|
||||||
*/
|
*/
|
||||||
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKeyRef? {
|
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKeyRef? {
|
||||||
var possibleTrust: Unmanaged<SecTrust>?
|
let possibleTrust = UnsafeMutablePointer<SecTrust?>.alloc(1)
|
||||||
SecTrustCreateWithCertificates(cert,policy, &possibleTrust)
|
SecTrustCreateWithCertificates( cert, policy, possibleTrust)
|
||||||
if let trust = possibleTrust {
|
if let trust = possibleTrust.memory {
|
||||||
let t = trust.takeRetainedValue()
|
|
||||||
var result: SecTrustResultType = 0
|
var result: SecTrustResultType = 0
|
||||||
SecTrustEvaluate(t,&result)
|
SecTrustEvaluate(trust,&result)
|
||||||
return SecTrustCopyPublicKey(t).takeRetainedValue()
|
return SecTrustCopyPublicKey(trust)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -949,7 +947,7 @@ public class Security {
|
|||||||
var collect = Array<NSData>()
|
var collect = Array<NSData>()
|
||||||
for var i = 0; i < SecTrustGetCertificateCount(trust); i++ {
|
for var i = 0; i < SecTrustGetCertificateCount(trust); i++ {
|
||||||
let cert = SecTrustGetCertificateAtIndex(trust,i)
|
let cert = SecTrustGetCertificateAtIndex(trust,i)
|
||||||
collect.append(SecCertificateCopyData(cert.takeRetainedValue()).takeRetainedValue())
|
collect.append(SecCertificateCopyData(cert!))
|
||||||
}
|
}
|
||||||
return collect
|
return collect
|
||||||
}
|
}
|
||||||
@ -963,10 +961,10 @@ public class Security {
|
|||||||
*/
|
*/
|
||||||
func publicKeyChainForTrust(trust: SecTrustRef) -> Array<SecKeyRef> {
|
func publicKeyChainForTrust(trust: SecTrustRef) -> Array<SecKeyRef> {
|
||||||
var collect = Array<SecKeyRef>()
|
var collect = Array<SecKeyRef>()
|
||||||
let policy = SecPolicyCreateBasicX509().takeRetainedValue()
|
let policy = SecPolicyCreateBasicX509()
|
||||||
for var i = 0; i < SecTrustGetCertificateCount(trust); i++ {
|
for var i = 0; i < SecTrustGetCertificateCount(trust); i++ {
|
||||||
let cert = SecTrustGetCertificateAtIndex(trust,i)
|
let cert = SecTrustGetCertificateAtIndex(trust,i)
|
||||||
if let key = extractPublicKeyFromCert(cert.takeRetainedValue(), policy: policy) {
|
if let key = extractPublicKeyFromCert(cert!, policy: policy) {
|
||||||
collect.append(key)
|
collect.append(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user