commit
5ced8a5a9e
@ -165,6 +165,7 @@ case ReconnectAttempts(Int) // How many times to reconnect. Default is `-1` (inf
|
|||||||
case ReconnectWait(Int) // Amount of time to wait between reconnects. Default is `10`
|
case ReconnectWait(Int) // Amount of time to wait between reconnects. Default is `10`
|
||||||
case SessionDelegate(NSURLSessionDelegate) // Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. Default is nil.
|
case SessionDelegate(NSURLSessionDelegate) // Sets an NSURLSessionDelegate for the underlying engine. Useful if you need to handle self-signed certs. Default is nil.
|
||||||
case Secure(Bool) // If the connection should use TLS. Default is false.
|
case Secure(Bool) // If the connection should use TLS. Default is false.
|
||||||
|
case Security(SSLSecurity) // Allows you to set which certs are valid. Useful for SSL pinning.
|
||||||
case SelfSigned(Bool) // Sets WebSocket.selfSignedSSL (Don't do this, iOS will yell at you)
|
case SelfSigned(Bool) // Sets WebSocket.selfSignedSSL (Don't do this, iOS will yell at you)
|
||||||
case VoipEnabled(Bool) // Only use this option if you're using the client with VoIP services. Changes the way the WebSocket is created. Default is false
|
case VoipEnabled(Bool) // Only use this option if you're using the client with VoIP services. Changes the way the WebSocket is created. Default is false
|
||||||
```
|
```
|
||||||
|
|||||||
@ -101,11 +101,6 @@
|
|||||||
74171EC51C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
74171EC51C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
||||||
74171EC71C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
74171EC71C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
||||||
74171EC81C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
74171EC81C10CD240062D398 /* SocketTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E601C10CD240062D398 /* SocketTypes.swift */; };
|
||||||
74171ECF1C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
|
||||||
74171ED01C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
|
||||||
74171ED11C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
|
||||||
74171ED31C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
|
||||||
74171ED41C10CD240062D398 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74171E621C10CD240062D398 /* WebSocket.swift */; };
|
|
||||||
741F39EE1BD025D80026C9CC /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */; };
|
741F39EE1BD025D80026C9CC /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */; };
|
||||||
741F39EF1BD025D80026C9CC /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */; };
|
741F39EF1BD025D80026C9CC /* SocketEngineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */; };
|
||||||
7420CB791C49629E00956AA4 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */; };
|
7420CB791C49629E00956AA4 /* SocketEnginePollable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */; };
|
||||||
@ -121,6 +116,15 @@
|
|||||||
7472C65F1BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */; };
|
7472C65F1BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */; };
|
||||||
7472C6601BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */; };
|
7472C6601BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */; };
|
||||||
74ABF7771C3991C10078C657 /* SocketIOClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74ABF7761C3991C10078C657 /* SocketIOClientSpec.swift */; };
|
74ABF7771C3991C10078C657 /* SocketIOClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74ABF7761C3991C10078C657 /* SocketIOClientSpec.swift */; };
|
||||||
|
74B4AD1D1D09A5D80062A523 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4AD1C1D09A5D80062A523 /* WebSocket.swift */; };
|
||||||
|
74B4AD211D09A6190062A523 /* SSLSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4AD201D09A6190062A523 /* SSLSecurity.swift */; };
|
||||||
|
74B4AD221D09A6190062A523 /* SSLSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4AD201D09A6190062A523 /* SSLSecurity.swift */; };
|
||||||
|
74B4AD231D09A6190062A523 /* SSLSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4AD201D09A6190062A523 /* SSLSecurity.swift */; };
|
||||||
|
74B4AD241D09A6450062A523 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4AD1C1D09A5D80062A523 /* WebSocket.swift */; };
|
||||||
|
74B4AD251D09A6490062A523 /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B4AD1C1D09A5D80062A523 /* WebSocket.swift */; };
|
||||||
|
74BC45AB1D0C6675008CC431 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */; };
|
||||||
|
74BC45AC1D0C6675008CC431 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */; };
|
||||||
|
74BC45AD1D0C6675008CC431 /* SocketClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */; };
|
||||||
74F124F01BC574CF002966F4 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */; };
|
74F124F01BC574CF002966F4 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */; };
|
||||||
74F124F11BC574CF002966F4 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */; };
|
74F124F11BC574CF002966F4 /* SocketBasicPacketTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */; };
|
||||||
CEBA56961CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */; };
|
CEBA56961CDA0B7700BA0389 /* NSCharacterSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */; };
|
||||||
@ -160,7 +164,6 @@
|
|||||||
572EF21D1B51F16C00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
572EF21D1B51F16C00EEBB58 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
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>"; };
|
|
||||||
572EF2381B51F18A00EEBB58 /* SocketIOClientSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIOClientSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
572EF2381B51F18A00EEBB58 /* SocketIOClientSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SocketIOClientSwift.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>"; };
|
||||||
@ -185,7 +188,6 @@
|
|||||||
74171E5E1C10CD240062D398 /* SocketParsable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketParsable.swift; path = Source/SocketParsable.swift; sourceTree = "<group>"; };
|
74171E5E1C10CD240062D398 /* SocketParsable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketParsable.swift; path = Source/SocketParsable.swift; sourceTree = "<group>"; };
|
||||||
74171E5F1C10CD240062D398 /* SocketStringReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketStringReader.swift; path = Source/SocketStringReader.swift; sourceTree = "<group>"; };
|
74171E5F1C10CD240062D398 /* SocketStringReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketStringReader.swift; path = Source/SocketStringReader.swift; sourceTree = "<group>"; };
|
||||||
74171E601C10CD240062D398 /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketTypes.swift; path = Source/SocketTypes.swift; sourceTree = "<group>"; };
|
74171E601C10CD240062D398 /* SocketTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketTypes.swift; path = Source/SocketTypes.swift; sourceTree = "<group>"; };
|
||||||
74171E621C10CD240062D398 /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = Source/WebSocket.swift; sourceTree = "<group>"; };
|
|
||||||
741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = "<group>"; };
|
741F39ED1BD025D80026C9CC /* SocketEngineTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketEngineTest.swift; sourceTree = "<group>"; };
|
||||||
7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketEnginePollable.swift; path = Source/SocketEnginePollable.swift; sourceTree = "<group>"; };
|
7420CB781C49629E00956AA4 /* SocketEnginePollable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketEnginePollable.swift; path = Source/SocketEnginePollable.swift; sourceTree = "<group>"; };
|
||||||
742D150B1CA5794B00BD987D /* SocketObjectiveCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SocketObjectiveCTest.m; sourceTree = "<group>"; };
|
742D150B1CA5794B00BD987D /* SocketObjectiveCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SocketObjectiveCTest.m; sourceTree = "<group>"; };
|
||||||
@ -194,6 +196,9 @@
|
|||||||
7472C65B1BCAB53E003CA70D /* SocketNamespacePacketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespacePacketTest.swift; sourceTree = "<group>"; };
|
7472C65B1BCAB53E003CA70D /* SocketNamespacePacketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketNamespacePacketTest.swift; sourceTree = "<group>"; };
|
||||||
7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketSideEffectTest.swift; sourceTree = "<group>"; };
|
7472C65E1BCAC46E003CA70D /* SocketSideEffectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketSideEffectTest.swift; sourceTree = "<group>"; };
|
||||||
74ABF7761C3991C10078C657 /* SocketIOClientSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientSpec.swift; path = Source/SocketIOClientSpec.swift; sourceTree = "<group>"; };
|
74ABF7761C3991C10078C657 /* SocketIOClientSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketIOClientSpec.swift; path = Source/SocketIOClientSpec.swift; sourceTree = "<group>"; };
|
||||||
|
74B4AD1C1D09A5D80062A523 /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebSocket.swift; path = Source/WebSocket/WebSocket.swift; sourceTree = "<group>"; };
|
||||||
|
74B4AD201D09A6190062A523 /* SSLSecurity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SSLSecurity.swift; path = Source/WebSocket/SSLSecurity.swift; sourceTree = "<group>"; };
|
||||||
|
74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SocketClientManager.swift; path = Source/SocketClientManager.swift; sourceTree = "<group>"; };
|
||||||
74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketBasicPacketTest.swift; sourceTree = "<group>"; };
|
74F124EF1BC574CF002966F4 /* SocketBasicPacketTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketBasicPacketTest.swift; sourceTree = "<group>"; };
|
||||||
CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSCharacterSet.swift; path = Source/NSCharacterSet.swift; sourceTree = "<group>"; };
|
CEBA56951CDA0B7700BA0389 /* NSCharacterSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSCharacterSet.swift; path = Source/NSCharacterSet.swift; sourceTree = "<group>"; };
|
||||||
CEBA56991CDA0B8200BA0389 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = String.swift; path = Source/String.swift; sourceTree = "<group>"; };
|
CEBA56991CDA0B8200BA0389 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = String.swift; path = Source/String.swift; sourceTree = "<group>"; };
|
||||||
@ -253,7 +258,6 @@
|
|||||||
children = (
|
children = (
|
||||||
5764DF7B1B51F24A004FF46E /* Source */,
|
5764DF7B1B51F24A004FF46E /* Source */,
|
||||||
572EF21B1B51F16C00EEBB58 /* SocketIO-iOS */,
|
572EF21B1B51F16C00EEBB58 /* SocketIO-iOS */,
|
||||||
572EF2281B51F16C00EEBB58 /* SocketIO-iOSTests */,
|
|
||||||
572EF2391B51F18A00EEBB58 /* SocketIO-Mac */,
|
572EF2391B51F18A00EEBB58 /* SocketIO-Mac */,
|
||||||
572EF2461B51F18A00EEBB58 /* SocketIO-MacTests */,
|
572EF2461B51F18A00EEBB58 /* SocketIO-MacTests */,
|
||||||
572EF21A1B51F16C00EEBB58 /* Products */,
|
572EF21A1B51F16C00EEBB58 /* Products */,
|
||||||
@ -290,22 +294,6 @@
|
|||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
572EF2281B51F16C00EEBB58 /* SocketIO-iOSTests */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
572EF2291B51F16C00EEBB58 /* Supporting Files */,
|
|
||||||
);
|
|
||||||
path = "SocketIO-iOSTests";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
572EF2291B51F16C00EEBB58 /* Supporting Files */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
572EF22A1B51F16C00EEBB58 /* Info.plist */,
|
|
||||||
);
|
|
||||||
name = "Supporting Files";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
572EF2391B51F18A00EEBB58 /* SocketIO-Mac */ = {
|
572EF2391B51F18A00EEBB58 /* SocketIO-Mac */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -349,10 +337,10 @@
|
|||||||
5764DF7B1B51F24A004FF46E /* Source */ = {
|
5764DF7B1B51F24A004FF46E /* Source */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CEBA569E1CDA0C0C00BA0389 /* utils */,
|
|
||||||
74171E501C10CD240062D398 /* SocketAckEmitter.swift */,
|
74171E501C10CD240062D398 /* SocketAckEmitter.swift */,
|
||||||
74171E511C10CD240062D398 /* SocketAckManager.swift */,
|
74171E511C10CD240062D398 /* SocketAckManager.swift */,
|
||||||
74171E521C10CD240062D398 /* SocketAnyEvent.swift */,
|
74171E521C10CD240062D398 /* SocketAnyEvent.swift */,
|
||||||
|
74BC45AA1D0C6675008CC431 /* SocketClientManager.swift */,
|
||||||
74171E531C10CD240062D398 /* SocketEngine.swift */,
|
74171E531C10CD240062D398 /* SocketEngine.swift */,
|
||||||
74171E541C10CD240062D398 /* SocketEngineClient.swift */,
|
74171E541C10CD240062D398 /* SocketEngineClient.swift */,
|
||||||
74171E551C10CD240062D398 /* SocketEnginePacketType.swift */,
|
74171E551C10CD240062D398 /* SocketEnginePacketType.swift */,
|
||||||
@ -369,11 +357,21 @@
|
|||||||
74171E5E1C10CD240062D398 /* SocketParsable.swift */,
|
74171E5E1C10CD240062D398 /* SocketParsable.swift */,
|
||||||
74171E5F1C10CD240062D398 /* SocketStringReader.swift */,
|
74171E5F1C10CD240062D398 /* SocketStringReader.swift */,
|
||||||
74171E601C10CD240062D398 /* SocketTypes.swift */,
|
74171E601C10CD240062D398 /* SocketTypes.swift */,
|
||||||
74171E621C10CD240062D398 /* WebSocket.swift */,
|
CEBA569E1CDA0C0C00BA0389 /* utils */,
|
||||||
|
74B4AD1B1D09A5C30062A523 /* Websocket */,
|
||||||
);
|
);
|
||||||
name = Source;
|
name = Source;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
74B4AD1B1D09A5C30062A523 /* Websocket */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
74B4AD1C1D09A5D80062A523 /* WebSocket.swift */,
|
||||||
|
74B4AD201D09A6190062A523 /* SSLSecurity.swift */,
|
||||||
|
);
|
||||||
|
name = Websocket;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
CEBA569E1CDA0C0C00BA0389 /* utils */ = {
|
CEBA569E1CDA0C0C00BA0389 /* utils */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -619,6 +617,7 @@
|
|||||||
740CA1221C496EF700CB98F4 /* SocketEngineWebsocket.swift in Sources */,
|
740CA1221C496EF700CB98F4 /* SocketEngineWebsocket.swift in Sources */,
|
||||||
74171EA51C10CD240062D398 /* SocketIOClientStatus.swift in Sources */,
|
74171EA51C10CD240062D398 /* SocketIOClientStatus.swift in Sources */,
|
||||||
CEBA569A1CDA0B8200BA0389 /* String.swift in Sources */,
|
CEBA569A1CDA0B8200BA0389 /* String.swift in Sources */,
|
||||||
|
74B4AD1D1D09A5D80062A523 /* WebSocket.swift in Sources */,
|
||||||
74171E751C10CD240062D398 /* SocketEngine.swift in Sources */,
|
74171E751C10CD240062D398 /* SocketEngine.swift in Sources */,
|
||||||
74171E691C10CD240062D398 /* SocketAckManager.swift in Sources */,
|
74171E691C10CD240062D398 /* SocketAckManager.swift in Sources */,
|
||||||
7420CB791C49629E00956AA4 /* SocketEnginePollable.swift in Sources */,
|
7420CB791C49629E00956AA4 /* SocketEnginePollable.swift in Sources */,
|
||||||
@ -626,18 +625,19 @@
|
|||||||
74ABF7771C3991C10078C657 /* SocketIOClientSpec.swift in Sources */,
|
74ABF7771C3991C10078C657 /* SocketIOClientSpec.swift in Sources */,
|
||||||
74171E871C10CD240062D398 /* SocketEngineSpec.swift in Sources */,
|
74171E871C10CD240062D398 /* SocketEngineSpec.swift in Sources */,
|
||||||
74171E631C10CD240062D398 /* SocketAckEmitter.swift in Sources */,
|
74171E631C10CD240062D398 /* SocketAckEmitter.swift in Sources */,
|
||||||
|
74B4AD211D09A6190062A523 /* SSLSecurity.swift in Sources */,
|
||||||
74171EBD1C10CD240062D398 /* SocketStringReader.swift in Sources */,
|
74171EBD1C10CD240062D398 /* SocketStringReader.swift in Sources */,
|
||||||
74171EC31C10CD240062D398 /* SocketTypes.swift in Sources */,
|
74171EC31C10CD240062D398 /* SocketTypes.swift in Sources */,
|
||||||
74171EAB1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
74171EAB1C10CD240062D398 /* SocketLogger.swift in Sources */,
|
||||||
74171E991C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
74171E991C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
||||||
74171E8D1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E8D1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171E7B1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7B1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171ECF1C10CD240062D398 /* WebSocket.swift in Sources */,
|
|
||||||
74171EB11C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB11C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
74171EB71C10CD240062D398 /* SocketParsable.swift in Sources */,
|
74171EB71C10CD240062D398 /* SocketParsable.swift in Sources */,
|
||||||
74171E811C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
74171E811C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
||||||
74171E6F1C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
74171E6F1C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
||||||
74171E9F1C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
74171E9F1C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
||||||
|
74BC45AB1D0C6675008CC431 /* SocketClientManager.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -648,7 +648,6 @@
|
|||||||
7472C65F1BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */,
|
7472C65F1BCAC46E003CA70D /* SocketSideEffectTest.swift in Sources */,
|
||||||
74171EA61C10CD240062D398 /* SocketIOClientStatus.swift in Sources */,
|
74171EA61C10CD240062D398 /* SocketIOClientStatus.swift in Sources */,
|
||||||
74171E881C10CD240062D398 /* SocketEngineSpec.swift in Sources */,
|
74171E881C10CD240062D398 /* SocketEngineSpec.swift in Sources */,
|
||||||
74171ED01C10CD240062D398 /* WebSocket.swift in Sources */,
|
|
||||||
74171EA01C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
74171EA01C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
||||||
74171E701C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
74171E701C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
||||||
74171EC41C10CD240062D398 /* SocketTypes.swift in Sources */,
|
74171EC41C10CD240062D398 /* SocketTypes.swift in Sources */,
|
||||||
@ -673,6 +672,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
74B4AD241D09A6450062A523 /* WebSocket.swift in Sources */,
|
||||||
740CA1211C496EF200CB98F4 /* SocketEngineWebsocket.swift in Sources */,
|
740CA1211C496EF200CB98F4 /* SocketEngineWebsocket.swift in Sources */,
|
||||||
7471CCEA1C39926300364B59 /* SocketIOClientSpec.swift in Sources */,
|
7471CCEA1C39926300364B59 /* SocketIOClientSpec.swift in Sources */,
|
||||||
CEBA569B1CDA0B8200BA0389 /* String.swift in Sources */,
|
CEBA569B1CDA0B8200BA0389 /* String.swift in Sources */,
|
||||||
@ -689,12 +689,13 @@
|
|||||||
74171E9B1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
74171E9B1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
||||||
74171E8F1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E8F1C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171E7D1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7D1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171ED11C10CD240062D398 /* WebSocket.swift in Sources */,
|
74B4AD221D09A6190062A523 /* SSLSecurity.swift in Sources */,
|
||||||
74171EB31C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB31C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
74171EB91C10CD240062D398 /* SocketParsable.swift in Sources */,
|
74171EB91C10CD240062D398 /* SocketParsable.swift in Sources */,
|
||||||
74171E831C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
74171E831C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
||||||
74171E711C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
74171E711C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
||||||
74171EA11C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
74171EA11C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
||||||
|
74BC45AC1D0C6675008CC431 /* SocketClientManager.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -717,6 +718,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
74B4AD251D09A6490062A523 /* WebSocket.swift in Sources */,
|
||||||
740CA1201C496EEB00CB98F4 /* SocketEngineWebsocket.swift in Sources */,
|
740CA1201C496EEB00CB98F4 /* SocketEngineWebsocket.swift in Sources */,
|
||||||
7471CCEB1C39926C00364B59 /* SocketIOClientSpec.swift in Sources */,
|
7471CCEB1C39926C00364B59 /* SocketIOClientSpec.swift in Sources */,
|
||||||
CEBA569C1CDA0B8200BA0389 /* String.swift in Sources */,
|
CEBA569C1CDA0B8200BA0389 /* String.swift in Sources */,
|
||||||
@ -733,12 +735,13 @@
|
|||||||
74171E9D1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
74171E9D1C10CD240062D398 /* SocketIOClient.swift in Sources */,
|
||||||
74171E911C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
74171E911C10CD240062D398 /* SocketEventHandler.swift in Sources */,
|
||||||
74171E7F1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
74171E7F1C10CD240062D398 /* SocketEngineClient.swift in Sources */,
|
||||||
74171ED31C10CD240062D398 /* WebSocket.swift in Sources */,
|
74B4AD231D09A6190062A523 /* SSLSecurity.swift in Sources */,
|
||||||
74171EB51C10CD240062D398 /* SocketPacket.swift in Sources */,
|
74171EB51C10CD240062D398 /* SocketPacket.swift in Sources */,
|
||||||
74171EBB1C10CD240062D398 /* SocketParsable.swift in Sources */,
|
74171EBB1C10CD240062D398 /* SocketParsable.swift in Sources */,
|
||||||
74171E851C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
74171E851C10CD240062D398 /* SocketEnginePacketType.swift in Sources */,
|
||||||
74171E731C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
74171E731C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
||||||
74171EA31C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
74171EA31C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
||||||
|
74BC45AD1D0C6675008CC431 /* SocketClientManager.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -749,7 +752,6 @@
|
|||||||
57634A231BD9B46D00E19CD7 /* SocketSideEffectTest.swift in Sources */,
|
57634A231BD9B46D00E19CD7 /* SocketSideEffectTest.swift in Sources */,
|
||||||
74171EAA1C10CD240062D398 /* SocketIOClientStatus.swift in Sources */,
|
74171EAA1C10CD240062D398 /* SocketIOClientStatus.swift in Sources */,
|
||||||
74171E8C1C10CD240062D398 /* SocketEngineSpec.swift in Sources */,
|
74171E8C1C10CD240062D398 /* SocketEngineSpec.swift in Sources */,
|
||||||
74171ED41C10CD240062D398 /* WebSocket.swift in Sources */,
|
|
||||||
74171EA41C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
74171EA41C10CD240062D398 /* SocketIOClientOption.swift in Sources */,
|
||||||
74171E741C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
74171E741C10CD240062D398 /* SocketAnyEvent.swift in Sources */,
|
||||||
74171EC81C10CD240062D398 /* SocketTypes.swift in Sources */,
|
74171EC81C10CD240062D398 /* SocketTypes.swift in Sources */,
|
||||||
|
|||||||
@ -44,4 +44,10 @@
|
|||||||
[self.socket off:@"test"];
|
[self.socket off:@"test"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testSocketManager {
|
||||||
|
SocketClientManager* manager = [SocketClientManager sharedManager];
|
||||||
|
[manager addSocket:self.socket labeledAs:@"test"];
|
||||||
|
[manager removeSocketWithLabel:@"test"];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class SocketParserTest: XCTestCase {
|
|||||||
let testSocket = SocketIOClient(socketURL: NSURL())
|
let testSocket = SocketIOClient(socketURL: NSURL())
|
||||||
|
|
||||||
//Format key: message; namespace-data-binary-id
|
//Format key: message; namespace-data-binary-id
|
||||||
static let packetTypes: Dictionary<String, (String, [AnyObject], [NSData], Int)> = [
|
static let packetTypes: [String: (String, [AnyObject], [NSData], Int)] = [
|
||||||
"0": ("/", [], [], -1), "1": ("/", [], [], -1),
|
"0": ("/", [], [], -1), "1": ("/", [], [], -1),
|
||||||
"25[\"test\"]": ("/", ["test"], [], 5),
|
"25[\"test\"]": ("/", ["test"], [], 5),
|
||||||
"2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1),
|
"2[\"test\",\"~~0\"]": ("/", ["test", "~~0"], [], -1),
|
||||||
|
|||||||
@ -153,4 +153,16 @@ class SocketSideEffectTest: XCTestCase {
|
|||||||
socket.parseBinaryData(data2)
|
socket.parseBinaryData(data2)
|
||||||
waitForExpectationsWithTimeout(3, handler: nil)
|
waitForExpectationsWithTimeout(3, handler: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSocketManager() {
|
||||||
|
let manager = SocketClientManager.sharedManager
|
||||||
|
manager["test"] = socket
|
||||||
|
|
||||||
|
XCTAssert(manager["test"] === socket, "failed to get socket")
|
||||||
|
|
||||||
|
manager["test"] = nil
|
||||||
|
|
||||||
|
XCTAssert(manager["test"] == nil, "socket not removed")
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>en</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>$(PRODUCT_NAME)</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>BNDL</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
82
Source/SocketClientManager.swift
Normal file
82
Source/SocketClientManager.swift
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// SocketClientManager.swift
|
||||||
|
// Socket.IO-Client-Swift
|
||||||
|
//
|
||||||
|
// Created by Erik Little on 6/11/16.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
Experimental socket manager.
|
||||||
|
|
||||||
|
API subject to change.
|
||||||
|
|
||||||
|
Can be used to persist sockets across ViewControllers.
|
||||||
|
|
||||||
|
Sockets are strongly stored, so be sure to remove them once they are no
|
||||||
|
longer needed.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
```
|
||||||
|
let manager = SocketClientManager.sharedManager
|
||||||
|
manager["room1"] = socket1
|
||||||
|
manager["room2"] = socket2
|
||||||
|
manager.removeSocket(socket: socket2)
|
||||||
|
manager["room1"]?.emit("hello")
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
public final class SocketClientManager : NSObject {
|
||||||
|
public static let sharedManager = SocketClientManager()
|
||||||
|
|
||||||
|
private var sockets = [String: SocketIOClient]()
|
||||||
|
|
||||||
|
public subscript(string: String) -> SocketIOClient? {
|
||||||
|
get {
|
||||||
|
return sockets[string]
|
||||||
|
}
|
||||||
|
|
||||||
|
set(socket) {
|
||||||
|
sockets[string] = socket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func addSocket(socket: SocketIOClient, labeledAs label: String) {
|
||||||
|
sockets[label] = socket
|
||||||
|
}
|
||||||
|
|
||||||
|
public func removeSocket(withLabel label: String) -> SocketIOClient? {
|
||||||
|
return sockets.removeValueForKey(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func removeSocket(socket socket: SocketIOClient) -> SocketIOClient? {
|
||||||
|
var returnSocket: SocketIOClient?
|
||||||
|
|
||||||
|
for (label, dictSocket) in sockets where dictSocket === socket {
|
||||||
|
returnSocket = sockets.removeValueForKey(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnSocket
|
||||||
|
}
|
||||||
|
|
||||||
|
public func removeSockets() {
|
||||||
|
sockets.removeAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -76,6 +76,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
private var pongsMissedMax = 0
|
private var pongsMissedMax = 0
|
||||||
private var probeWait = ProbeWaitQueue()
|
private var probeWait = ProbeWaitQueue()
|
||||||
private var secure = false
|
private var secure = false
|
||||||
|
private var security: SSLSecurity?
|
||||||
private var selfSigned = false
|
private var selfSigned = false
|
||||||
private var voipEnabled = false
|
private var voipEnabled = false
|
||||||
|
|
||||||
@ -105,6 +106,8 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
voipEnabled = enable
|
voipEnabled = enable
|
||||||
case let .Secure(secure):
|
case let .Secure(secure):
|
||||||
self.secure = secure
|
self.secure = secure
|
||||||
|
case let .Security(security):
|
||||||
|
self.security = security
|
||||||
case let .SelfSigned(selfSigned):
|
case let .SelfSigned(selfSigned):
|
||||||
self.selfSigned = selfSigned
|
self.selfSigned = selfSigned
|
||||||
default:
|
default:
|
||||||
@ -153,8 +156,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
// binary in base64 string
|
// binary in base64 string
|
||||||
let noPrefix = message[message.startIndex.advancedBy(2)..<message.endIndex]
|
let noPrefix = message[message.startIndex.advancedBy(2)..<message.endIndex]
|
||||||
|
|
||||||
if let data = NSData(base64EncodedString: noPrefix,
|
if let data = NSData(base64EncodedString: noPrefix, options: .IgnoreUnknownCharacters) {
|
||||||
options: .IgnoreUnknownCharacters) {
|
|
||||||
client?.parseEngineBinaryData(data)
|
client?.parseEngineBinaryData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +166,16 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func closeOutEngine() {
|
||||||
|
sid = ""
|
||||||
|
closed = true
|
||||||
|
invalidated = true
|
||||||
|
connected = false
|
||||||
|
|
||||||
|
ws?.disconnect()
|
||||||
|
stopPolling()
|
||||||
|
}
|
||||||
|
|
||||||
/// Starts the connection to the server
|
/// Starts the connection to the server
|
||||||
public func connect() {
|
public func connect() {
|
||||||
if connected {
|
if connected {
|
||||||
@ -171,7 +183,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
disconnect("reconnect")
|
disconnect("reconnect")
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Starting engine", type: logType)
|
DefaultSocketLogger.Logger.log("Starting engine. Server: %@", type: logType, args: url)
|
||||||
DefaultSocketLogger.Logger.log("Handshaking", type: logType)
|
DefaultSocketLogger.Logger.log("Handshaking", type: logType)
|
||||||
|
|
||||||
resetEngine()
|
resetEngine()
|
||||||
@ -256,6 +268,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
ws?.voipEnabled = voipEnabled
|
ws?.voipEnabled = voipEnabled
|
||||||
ws?.delegate = self
|
ws?.delegate = self
|
||||||
ws?.selfSignedSSL = selfSigned
|
ws?.selfSignedSSL = selfSigned
|
||||||
|
ws?.security = security
|
||||||
|
|
||||||
ws?.connect()
|
ws?.connect()
|
||||||
}
|
}
|
||||||
@ -267,35 +280,32 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func disconnect(reason: String) {
|
public func disconnect(reason: String) {
|
||||||
func postSendClose(data: NSData?, _ res: NSURLResponse?, _ err: NSError?) {
|
guard connected else { return closeOutEngine() }
|
||||||
sid = ""
|
|
||||||
closed = true
|
|
||||||
invalidated = true
|
|
||||||
connected = false
|
|
||||||
|
|
||||||
ws?.disconnect()
|
|
||||||
stopPolling()
|
|
||||||
client?.engineDidClose(reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType)
|
DefaultSocketLogger.Logger.log("Engine is being closed.", type: logType)
|
||||||
|
|
||||||
if closed {
|
if closed {
|
||||||
|
closeOutEngine()
|
||||||
client?.engineDidClose(reason)
|
client?.engineDidClose(reason)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if websocket {
|
if websocket {
|
||||||
sendWebSocketMessage("", withType: .Close, withData: [])
|
sendWebSocketMessage("", withType: .Close, withData: [])
|
||||||
postSendClose(nil, nil, nil)
|
closeOutEngine()
|
||||||
} else {
|
} else {
|
||||||
|
disconnectPolling()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We need to take special care when we're polling that we send it ASAP
|
// We need to take special care when we're polling that we send it ASAP
|
||||||
// Also make sure we're on the emitQueue since we're touching postWait
|
// Also make sure we're on the emitQueue since we're touching postWait
|
||||||
|
private func disconnectPolling() {
|
||||||
dispatch_sync(emitQueue) {
|
dispatch_sync(emitQueue) {
|
||||||
self.postWait.append(String(SocketEnginePacketType.Close.rawValue))
|
self.postWait.append(String(SocketEnginePacketType.Close.rawValue))
|
||||||
let req = self.createRequestForPostWithPostWait()
|
let req = self.createRequestForPostWithPostWait()
|
||||||
self.doRequest(req, withCallback: postSendClose)
|
self.doRequest(req) {_, _, _ in }
|
||||||
}
|
self.closeOutEngine()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +345,7 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
guard let ws = self.ws else { return }
|
guard let ws = self.ws else { return }
|
||||||
|
|
||||||
for msg in postWait {
|
for msg in postWait {
|
||||||
ws.writeString(fixDoubleUTF8(msg))
|
ws.writeString(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
postWait.removeAll(keepCapacity: true)
|
postWait.removeAll(keepCapacity: true)
|
||||||
@ -535,13 +545,11 @@ public final class SocketEngine : NSObject, SocketEnginePollable, SocketEngineWe
|
|||||||
connected = false
|
connected = false
|
||||||
websocket = false
|
websocket = false
|
||||||
|
|
||||||
let reason = error?.localizedDescription ?? "Socket Disconnected"
|
if let reason = error?.localizedDescription {
|
||||||
|
|
||||||
if error != nil {
|
|
||||||
didError(reason)
|
didError(reason)
|
||||||
|
} else {
|
||||||
|
client?.engineDidClose("Socket Disconnected")
|
||||||
}
|
}
|
||||||
|
|
||||||
client?.engineDidClose(reason)
|
|
||||||
} else {
|
} else {
|
||||||
flushProbeWait()
|
flushProbeWait()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -213,9 +213,7 @@ extension SocketEnginePollable {
|
|||||||
fixedMessage = message
|
fixedMessage = message
|
||||||
}
|
}
|
||||||
|
|
||||||
let strMsg = "\(type.rawValue)\(fixedMessage)"
|
postWait.append(String(type.rawValue) + fixedMessage)
|
||||||
|
|
||||||
postWait.append(strMsg)
|
|
||||||
|
|
||||||
for data in datas {
|
for data in datas {
|
||||||
if case let .Right(bin) = createBinaryDataForSend(data) {
|
if case let .Right(bin) = createBinaryDataForSend(data) {
|
||||||
|
|||||||
@ -197,8 +197,7 @@ public final class SocketIOClient : NSObject, SocketEngineClient, SocketParsable
|
|||||||
handleEvent("disconnect", data: [reason], isInternalMessage: true)
|
handleEvent("disconnect", data: [reason], isInternalMessage: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnects the socket. Only reconnect the same socket if you know what you're doing.
|
/// Disconnects the socket.
|
||||||
/// Will turn off automatic reconnects.
|
|
||||||
public func disconnect() {
|
public func disconnect() {
|
||||||
assert(status != .NotConnected, "Tried closing a NotConnected client")
|
assert(status != .NotConnected, "Tried closing a NotConnected client")
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public enum SocketIOClientOption : ClientOption {
|
|||||||
case ReconnectAttempts(Int)
|
case ReconnectAttempts(Int)
|
||||||
case ReconnectWait(Int)
|
case ReconnectWait(Int)
|
||||||
case Secure(Bool)
|
case Secure(Bool)
|
||||||
|
case Security(SSLSecurity)
|
||||||
case SelfSigned(Bool)
|
case SelfSigned(Bool)
|
||||||
case SessionDelegate(NSURLSessionDelegate)
|
case SessionDelegate(NSURLSessionDelegate)
|
||||||
case VoipEnabled(Bool)
|
case VoipEnabled(Bool)
|
||||||
@ -85,6 +86,8 @@ public enum SocketIOClientOption : ClientOption {
|
|||||||
description = "reconnectWait"
|
description = "reconnectWait"
|
||||||
case .Secure:
|
case .Secure:
|
||||||
description = "secure"
|
description = "secure"
|
||||||
|
case .Security:
|
||||||
|
description = "security"
|
||||||
case .SelfSigned:
|
case .SelfSigned:
|
||||||
description = "selfSigned"
|
description = "selfSigned"
|
||||||
case .SessionDelegate:
|
case .SessionDelegate:
|
||||||
@ -136,6 +139,8 @@ public enum SocketIOClientOption : ClientOption {
|
|||||||
value = wait
|
value = wait
|
||||||
case let .Secure(secure):
|
case let .Secure(secure):
|
||||||
value = secure
|
value = secure
|
||||||
|
case let .Security(security):
|
||||||
|
value = security
|
||||||
case let .SelfSigned(signed):
|
case let .SelfSigned(signed):
|
||||||
value = signed
|
value = signed
|
||||||
case let .SessionDelegate(delegate):
|
case let .SessionDelegate(delegate):
|
||||||
@ -195,6 +200,8 @@ extension NSDictionary {
|
|||||||
return .ReconnectWait(wait)
|
return .ReconnectWait(wait)
|
||||||
case let ("secure", secure as Bool):
|
case let ("secure", secure as Bool):
|
||||||
return .Secure(secure)
|
return .Secure(secure)
|
||||||
|
case let ("security", security as SSLSecurity):
|
||||||
|
return .Security(security)
|
||||||
case let ("selfSigned", selfSigned as Bool):
|
case let ("selfSigned", selfSigned as Bool):
|
||||||
return .SelfSigned(selfSigned)
|
return .SelfSigned(selfSigned)
|
||||||
case let ("sessionDelegate", delegate as NSURLSessionDelegate):
|
case let ("sessionDelegate", delegate as NSURLSessionDelegate):
|
||||||
|
|||||||
@ -111,73 +111,31 @@ struct SocketPacket {
|
|||||||
return message + restOfMessage
|
return message + restOfMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createAck() -> String {
|
|
||||||
let message: String
|
|
||||||
|
|
||||||
if type == .Ack {
|
|
||||||
if nsp == "/" {
|
|
||||||
message = "3\(id)"
|
|
||||||
} else {
|
|
||||||
message = "3\(nsp),\(id)"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if nsp == "/" {
|
|
||||||
message = "6\(binary.count)-\(id)"
|
|
||||||
} else {
|
|
||||||
message = "6\(binary.count)-\(nsp),\(id)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return completeMessage(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private func createMessageForEvent() -> String {
|
|
||||||
let message: String
|
|
||||||
|
|
||||||
if type == .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)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createPacketString() -> String {
|
private func createPacketString() -> String {
|
||||||
let str: String
|
let typeString = String(type.rawValue)
|
||||||
|
let binaryCountString: String
|
||||||
|
let nspString: String
|
||||||
|
let idString: String
|
||||||
|
|
||||||
if type == .Event || type == .BinaryEvent {
|
if type == .BinaryEvent || type == .BinaryAck {
|
||||||
str = createMessageForEvent()
|
binaryCountString = typeString + String(binary.count) + "-"
|
||||||
} else {
|
} else {
|
||||||
str = createAck()
|
binaryCountString = typeString
|
||||||
}
|
}
|
||||||
|
|
||||||
return str
|
if nsp != "/" {
|
||||||
|
nspString = binaryCountString + nsp + ","
|
||||||
|
} else {
|
||||||
|
nspString = binaryCountString
|
||||||
|
}
|
||||||
|
|
||||||
|
if id != -1 {
|
||||||
|
idString = nspString + String(id)
|
||||||
|
} else {
|
||||||
|
idString = nspString
|
||||||
|
}
|
||||||
|
|
||||||
|
return completeMessage(idString)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when we have all the binary data for a packet
|
// Called when we have all the binary data for a packet
|
||||||
|
|||||||
@ -96,9 +96,8 @@ extension SocketParsable {
|
|||||||
|
|
||||||
if type == .Error {
|
if type == .Error {
|
||||||
parser.advanceIndexBy(-1)
|
parser.advanceIndexBy(-1)
|
||||||
}
|
} else {
|
||||||
|
while parser.hasNext {
|
||||||
while parser.hasNext && type != .Error {
|
|
||||||
if let int = Int(parser.read(1)) {
|
if let int = Int(parser.read(1)) {
|
||||||
idString += String(int)
|
idString += String(int)
|
||||||
} else {
|
} else {
|
||||||
@ -106,6 +105,7 @@ extension SocketParsable {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let d = message[parser.currentIndex.advancedBy(1)..<message.endIndex]
|
let d = message[parser.currentIndex.advancedBy(1)..<message.endIndex]
|
||||||
|
|
||||||
@ -162,9 +162,7 @@ extension SocketParsable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Should execute event?
|
// Should execute event?
|
||||||
guard waitingPackets[waitingPackets.count - 1].addData(data) else {
|
guard waitingPackets[waitingPackets.count - 1].addData(data) else { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let packet = waitingPackets.removeLast()
|
let packet = waitingPackets.removeLast()
|
||||||
|
|
||||||
|
|||||||
260
Source/WebSocket/SSLSecurity.swift
Normal file
260
Source/WebSocket/SSLSecurity.swift
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SSLSecurity.swift
|
||||||
|
// Starscream
|
||||||
|
//
|
||||||
|
// Created by Dalton Cherry on 5/16/15.
|
||||||
|
// Copyright (c) 2014-2015 Dalton Cherry.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Security
|
||||||
|
|
||||||
|
public class SSLCert : NSObject {
|
||||||
|
var certData: NSData?
|
||||||
|
var key: SecKeyRef?
|
||||||
|
|
||||||
|
/**
|
||||||
|
Designated init for certificates
|
||||||
|
|
||||||
|
- parameter data: is the binary data of the certificate
|
||||||
|
|
||||||
|
- returns: a representation security object to be used with
|
||||||
|
*/
|
||||||
|
public init(data: NSData) {
|
||||||
|
self.certData = data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Designated init for public keys
|
||||||
|
|
||||||
|
- parameter key: is the public key to be used
|
||||||
|
|
||||||
|
- returns: a representation security object to be used with
|
||||||
|
*/
|
||||||
|
public init(key: SecKeyRef) {
|
||||||
|
self.key = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SSLSecurity : NSObject {
|
||||||
|
public var validatedDN = true //should the domain name be validated?
|
||||||
|
|
||||||
|
var isReady = false //is the key processing done?
|
||||||
|
var certificates: [NSData]? //the certificates
|
||||||
|
var pubKeys: [SecKeyRef]? //the public keys
|
||||||
|
var usePublicKeys = false //use public keys or certificate validation?
|
||||||
|
|
||||||
|
/**
|
||||||
|
Use certs from main app bundle
|
||||||
|
|
||||||
|
- parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation
|
||||||
|
|
||||||
|
- returns: a representation security object to be used with
|
||||||
|
*/
|
||||||
|
public convenience init(usePublicKeys: Bool = false) {
|
||||||
|
let paths = NSBundle.mainBundle().pathsForResourcesOfType("cer", inDirectory: ".")
|
||||||
|
|
||||||
|
let certs = paths.reduce([SSLCert]()) { (certs: [SSLCert], path: String) -> [SSLCert] in
|
||||||
|
var certs = certs
|
||||||
|
if let data = NSData(contentsOfFile: path) {
|
||||||
|
certs.append(SSLCert(data: data))
|
||||||
|
}
|
||||||
|
return certs
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(certs: certs, usePublicKeys: usePublicKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Designated init
|
||||||
|
|
||||||
|
- parameter keys: is the certificates or public keys to use
|
||||||
|
- parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation
|
||||||
|
|
||||||
|
- returns: a representation security object to be used with
|
||||||
|
*/
|
||||||
|
public init(certs: [SSLCert], usePublicKeys: Bool) {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.usePublicKeys = usePublicKeys
|
||||||
|
|
||||||
|
if self.usePublicKeys {
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)) {
|
||||||
|
let pubKeys = certs.reduce([SecKeyRef]()) { (pubKeys: [SecKeyRef], cert: SSLCert) -> [SecKeyRef] in
|
||||||
|
var pubKeys = pubKeys
|
||||||
|
if let data = cert.certData where cert.key == nil {
|
||||||
|
cert.key = self.extractPublicKey(data)
|
||||||
|
}
|
||||||
|
if let key = cert.key {
|
||||||
|
pubKeys.append(key)
|
||||||
|
}
|
||||||
|
return pubKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pubKeys = pubKeys
|
||||||
|
self.isReady = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let certificates = certs.reduce([NSData]()) { (certificates: [NSData], cert: SSLCert) -> [NSData] in
|
||||||
|
var certificates = certificates
|
||||||
|
if let data = cert.certData {
|
||||||
|
certificates.append(data)
|
||||||
|
}
|
||||||
|
return certificates
|
||||||
|
}
|
||||||
|
self.certificates = certificates
|
||||||
|
self.isReady = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Valid the trust and domain name.
|
||||||
|
|
||||||
|
- parameter trust: is the serverTrust to validate
|
||||||
|
- parameter domain: is the CN domain to validate
|
||||||
|
|
||||||
|
- returns: if the key was successfully validated
|
||||||
|
*/
|
||||||
|
public func isValid(trust: SecTrustRef, domain: String?) -> Bool {
|
||||||
|
|
||||||
|
var tries = 0
|
||||||
|
while(!self.isReady) {
|
||||||
|
usleep(1000)
|
||||||
|
tries += 1
|
||||||
|
if tries > 5 {
|
||||||
|
return false //doesn't appear it is going to ever be ready...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var policy: SecPolicyRef
|
||||||
|
if self.validatedDN {
|
||||||
|
policy = SecPolicyCreateSSL(true, domain)
|
||||||
|
} else {
|
||||||
|
policy = SecPolicyCreateBasicX509()
|
||||||
|
}
|
||||||
|
SecTrustSetPolicies(trust,policy)
|
||||||
|
if self.usePublicKeys {
|
||||||
|
if let keys = self.pubKeys {
|
||||||
|
let serverPubKeys = publicKeyChainForTrust(trust)
|
||||||
|
for serverKey in serverPubKeys as [AnyObject] {
|
||||||
|
for key in keys as [AnyObject] {
|
||||||
|
if serverKey.isEqual(key) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let certs = self.certificates {
|
||||||
|
let serverCerts = certificateChainForTrust(trust)
|
||||||
|
var collect = [SecCertificate]()
|
||||||
|
for cert in certs {
|
||||||
|
collect.append(SecCertificateCreateWithData(nil,cert)!)
|
||||||
|
}
|
||||||
|
SecTrustSetAnchorCertificates(trust,collect)
|
||||||
|
var result: SecTrustResultType = 0
|
||||||
|
SecTrustEvaluate(trust,&result)
|
||||||
|
let r = Int(result)
|
||||||
|
if r == kSecTrustResultUnspecified || r == kSecTrustResultProceed {
|
||||||
|
var trustedCount = 0
|
||||||
|
for serverCert in serverCerts {
|
||||||
|
for cert in certs {
|
||||||
|
if cert == serverCert {
|
||||||
|
trustedCount += 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if trustedCount == serverCerts.count {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the public key from a certificate data
|
||||||
|
|
||||||
|
- parameter data: is the certificate to pull the public key from
|
||||||
|
|
||||||
|
- returns: a public key
|
||||||
|
*/
|
||||||
|
func extractPublicKey(data: NSData) -> SecKeyRef? {
|
||||||
|
guard let cert = SecCertificateCreateWithData(nil, data) else { return nil }
|
||||||
|
|
||||||
|
return extractPublicKeyFromCert(cert, policy: SecPolicyCreateBasicX509())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the public key from a certificate
|
||||||
|
|
||||||
|
- parameter data: is the certificate to pull the public key from
|
||||||
|
|
||||||
|
- returns: a public key
|
||||||
|
*/
|
||||||
|
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKeyRef? {
|
||||||
|
var possibleTrust: SecTrust?
|
||||||
|
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
|
||||||
|
|
||||||
|
guard let trust = possibleTrust else { return nil }
|
||||||
|
|
||||||
|
var result: SecTrustResultType = 0
|
||||||
|
SecTrustEvaluate(trust, &result)
|
||||||
|
return SecTrustCopyPublicKey(trust)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the certificate chain for the trust
|
||||||
|
|
||||||
|
- parameter trust: is the trust to lookup the certificate chain for
|
||||||
|
|
||||||
|
- returns: the certificate chain for the trust
|
||||||
|
*/
|
||||||
|
func certificateChainForTrust(trust: SecTrustRef) -> [NSData] {
|
||||||
|
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([NSData]()) { (certificates: [NSData], index: Int) -> [NSData] in
|
||||||
|
var certificates = certificates
|
||||||
|
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
||||||
|
certificates.append(SecCertificateCopyData(cert!))
|
||||||
|
return certificates
|
||||||
|
}
|
||||||
|
|
||||||
|
return certificates
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the public key chain for the trust
|
||||||
|
|
||||||
|
- parameter trust: is the trust to lookup the certificate chain and extract the public keys
|
||||||
|
|
||||||
|
- returns: the public keys from the certifcate chain for the trust
|
||||||
|
*/
|
||||||
|
func publicKeyChainForTrust(trust: SecTrustRef) -> [SecKeyRef] {
|
||||||
|
let policy = SecPolicyCreateBasicX509()
|
||||||
|
let keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKeyRef]()) { (keys: [SecKeyRef], index: Int) -> [SecKeyRef] in
|
||||||
|
var keys = keys
|
||||||
|
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
||||||
|
if let key = extractPublicKeyFromCert(cert!, policy: policy) {
|
||||||
|
keys.append(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -23,6 +23,10 @@ import Foundation
|
|||||||
import CoreFoundation
|
import CoreFoundation
|
||||||
import Security
|
import Security
|
||||||
|
|
||||||
|
public let WebsocketDidConnectNotification = "WebsocketDidConnectNotification"
|
||||||
|
public let WebsocketDidDisconnectNotification = "WebsocketDidDisconnectNotification"
|
||||||
|
public let WebsocketDisconnectionErrorKeyName = "WebsocketDisconnectionErrorKeyName"
|
||||||
|
|
||||||
public protocol WebSocketDelegate: class {
|
public protocol WebSocketDelegate: class {
|
||||||
func websocketDidConnect(socket: WebSocket)
|
func websocketDidConnect(socket: WebSocket)
|
||||||
func websocketDidDisconnect(socket: WebSocket, error: NSError?)
|
func websocketDidDisconnect(socket: WebSocket, error: NSError?)
|
||||||
@ -130,6 +134,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
private var didDisconnect = false
|
private var didDisconnect = false
|
||||||
private var readyToWrite = false
|
private var readyToWrite = false
|
||||||
private let mutex = NSLock()
|
private let mutex = NSLock()
|
||||||
|
private let notificationCenter = NSNotificationCenter.defaultCenter()
|
||||||
private var canDispatch: Bool {
|
private var canDispatch: Bool {
|
||||||
mutex.lock()
|
mutex.lock()
|
||||||
let canWork = readyToWrite
|
let canWork = readyToWrite
|
||||||
@ -185,6 +190,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
Write a string to the websocket. This sends it as a text frame.
|
Write a string to the websocket. This sends it as a text frame.
|
||||||
|
|
||||||
If you supply a non-nil completion block, I will perform it when the write completes.
|
If you supply a non-nil completion block, I will perform it when the write completes.
|
||||||
|
|
||||||
- parameter str: The string to write.
|
- parameter str: The string to write.
|
||||||
- parameter completion: The (optional) completion handler.
|
- parameter completion: The (optional) completion handler.
|
||||||
*/
|
*/
|
||||||
@ -197,6 +203,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
Write binary data to the websocket. This sends it as a binary frame.
|
Write binary data to the websocket. This sends it as a binary frame.
|
||||||
|
|
||||||
If you supply a non-nil completion block, I will perform it when the write completes.
|
If you supply a non-nil completion block, I will perform it when the write completes.
|
||||||
|
|
||||||
- parameter data: The data to write.
|
- parameter data: The data to write.
|
||||||
- parameter completion: The (optional) completion handler.
|
- parameter completion: The (optional) completion handler.
|
||||||
*/
|
*/
|
||||||
@ -437,6 +444,7 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onConnect?()
|
s.onConnect?()
|
||||||
s.delegate?.websocketDidConnect(s)
|
s.delegate?.websocketDidConnect(s)
|
||||||
|
s.notificationCenter.postNotificationName(WebsocketDidConnectNotification, object: self)
|
||||||
}
|
}
|
||||||
case -1:
|
case -1:
|
||||||
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
fragBuffer = NSData(bytes: buffer, length: bufferLen)
|
||||||
@ -815,6 +823,8 @@ public class WebSocket : NSObject, NSStreamDelegate {
|
|||||||
guard let s = self else { return }
|
guard let s = self else { return }
|
||||||
s.onDisconnect?(error)
|
s.onDisconnect?(error)
|
||||||
s.delegate?.websocketDidDisconnect(s, error: error)
|
s.delegate?.websocketDidDisconnect(s, error: error)
|
||||||
|
let userInfo = error.map({ [WebsocketDisconnectionErrorKeyName: $0] })
|
||||||
|
s.notificationCenter.postNotificationName(WebsocketDidDisconnectNotification, object: self, userInfo: userInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,238 +854,3 @@ private extension UnsafeBufferPointer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let emptyBuffer = UnsafeBufferPointer<UInt8>(start: nil, count: 0)
|
private let emptyBuffer = UnsafeBufferPointer<UInt8>(start: nil, count: 0)
|
||||||
|
|
||||||
|
|
||||||
public class SSLCert {
|
|
||||||
var certData: NSData?
|
|
||||||
var key: SecKeyRef?
|
|
||||||
|
|
||||||
/**
|
|
||||||
Designated init for certificates
|
|
||||||
|
|
||||||
- parameter data: is the binary data of the certificate
|
|
||||||
|
|
||||||
- returns: a representation security object to be used with
|
|
||||||
*/
|
|
||||||
public init(data: NSData) {
|
|
||||||
self.certData = data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Designated init for public keys
|
|
||||||
|
|
||||||
- parameter key: is the public key to be used
|
|
||||||
|
|
||||||
- returns: a representation security object to be used with
|
|
||||||
*/
|
|
||||||
public init(key: SecKeyRef) {
|
|
||||||
self.key = key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SSLSecurity {
|
|
||||||
public var validatedDN = true //should the domain name be validated?
|
|
||||||
|
|
||||||
var isReady = false //is the key processing done?
|
|
||||||
var certificates: [NSData]? //the certificates
|
|
||||||
var pubKeys: [SecKeyRef]? //the public keys
|
|
||||||
var usePublicKeys = false //use public keys or certificate validation?
|
|
||||||
|
|
||||||
/**
|
|
||||||
Use certs from main app bundle
|
|
||||||
|
|
||||||
- parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation
|
|
||||||
|
|
||||||
- returns: a representation security object to be used with
|
|
||||||
*/
|
|
||||||
public convenience init(usePublicKeys: Bool = false) {
|
|
||||||
let paths = NSBundle.mainBundle().pathsForResourcesOfType("cer", inDirectory: ".")
|
|
||||||
|
|
||||||
let certs = paths.reduce([SSLCert]()) { (certs: [SSLCert], path: String) -> [SSLCert] in
|
|
||||||
var certs = certs
|
|
||||||
if let data = NSData(contentsOfFile: path) {
|
|
||||||
certs.append(SSLCert(data: data))
|
|
||||||
}
|
|
||||||
return certs
|
|
||||||
}
|
|
||||||
|
|
||||||
self.init(certs: certs, usePublicKeys: usePublicKeys)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Designated init
|
|
||||||
|
|
||||||
- parameter keys: is the certificates or public keys to use
|
|
||||||
- parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation
|
|
||||||
|
|
||||||
- returns: a representation security object to be used with
|
|
||||||
*/
|
|
||||||
public init(certs: [SSLCert], usePublicKeys: Bool) {
|
|
||||||
self.usePublicKeys = usePublicKeys
|
|
||||||
|
|
||||||
if self.usePublicKeys {
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)) {
|
|
||||||
let pubKeys = certs.reduce([SecKeyRef]()) { (pubKeys: [SecKeyRef], cert: SSLCert) -> [SecKeyRef] in
|
|
||||||
var pubKeys = pubKeys
|
|
||||||
if let data = cert.certData where cert.key == nil {
|
|
||||||
cert.key = self.extractPublicKey(data)
|
|
||||||
}
|
|
||||||
if let key = cert.key {
|
|
||||||
pubKeys.append(key)
|
|
||||||
}
|
|
||||||
return pubKeys
|
|
||||||
}
|
|
||||||
|
|
||||||
self.pubKeys = pubKeys
|
|
||||||
self.isReady = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let certificates = certs.reduce([NSData]()) { (certificates: [NSData], cert: SSLCert) -> [NSData] in
|
|
||||||
var certificates = certificates
|
|
||||||
if let data = cert.certData {
|
|
||||||
certificates.append(data)
|
|
||||||
}
|
|
||||||
return certificates
|
|
||||||
}
|
|
||||||
self.certificates = certificates
|
|
||||||
self.isReady = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Valid the trust and domain name.
|
|
||||||
|
|
||||||
- parameter trust: is the serverTrust to validate
|
|
||||||
- parameter domain: is the CN domain to validate
|
|
||||||
|
|
||||||
- returns: if the key was successfully validated
|
|
||||||
*/
|
|
||||||
public func isValid(trust: SecTrustRef, domain: String?) -> Bool {
|
|
||||||
|
|
||||||
var tries = 0
|
|
||||||
while(!self.isReady) {
|
|
||||||
usleep(1000)
|
|
||||||
tries += 1
|
|
||||||
if tries > 5 {
|
|
||||||
return false //doesn't appear it is going to ever be ready...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var policy: SecPolicyRef
|
|
||||||
if self.validatedDN {
|
|
||||||
policy = SecPolicyCreateSSL(true, domain)
|
|
||||||
} else {
|
|
||||||
policy = SecPolicyCreateBasicX509()
|
|
||||||
}
|
|
||||||
SecTrustSetPolicies(trust,policy)
|
|
||||||
if self.usePublicKeys {
|
|
||||||
if let keys = self.pubKeys {
|
|
||||||
let serverPubKeys = publicKeyChainForTrust(trust)
|
|
||||||
for serverKey in serverPubKeys as [AnyObject] {
|
|
||||||
for key in keys as [AnyObject] {
|
|
||||||
if serverKey.isEqual(key) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if let certs = self.certificates {
|
|
||||||
let serverCerts = certificateChainForTrust(trust)
|
|
||||||
var collect = [SecCertificate]()
|
|
||||||
for cert in certs {
|
|
||||||
collect.append(SecCertificateCreateWithData(nil,cert)!)
|
|
||||||
}
|
|
||||||
SecTrustSetAnchorCertificates(trust,collect)
|
|
||||||
var result: SecTrustResultType = 0
|
|
||||||
SecTrustEvaluate(trust,&result)
|
|
||||||
let r = Int(result)
|
|
||||||
if r == kSecTrustResultUnspecified || r == kSecTrustResultProceed {
|
|
||||||
var trustedCount = 0
|
|
||||||
for serverCert in serverCerts {
|
|
||||||
for cert in certs {
|
|
||||||
if cert == serverCert {
|
|
||||||
trustedCount += 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if trustedCount == serverCerts.count {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the public key from a certificate data
|
|
||||||
|
|
||||||
- parameter data: is the certificate to pull the public key from
|
|
||||||
|
|
||||||
- returns: a public key
|
|
||||||
*/
|
|
||||||
func extractPublicKey(data: NSData) -> SecKeyRef? {
|
|
||||||
guard let cert = SecCertificateCreateWithData(nil, data) else { return nil }
|
|
||||||
|
|
||||||
return extractPublicKeyFromCert(cert, policy: SecPolicyCreateBasicX509())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the public key from a certificate
|
|
||||||
|
|
||||||
- parameter data: is the certificate to pull the public key from
|
|
||||||
|
|
||||||
- returns: a public key
|
|
||||||
*/
|
|
||||||
func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKeyRef? {
|
|
||||||
var possibleTrust: SecTrust?
|
|
||||||
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
|
|
||||||
|
|
||||||
guard let trust = possibleTrust else { return nil }
|
|
||||||
|
|
||||||
var result: SecTrustResultType = 0
|
|
||||||
SecTrustEvaluate(trust, &result)
|
|
||||||
return SecTrustCopyPublicKey(trust)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the certificate chain for the trust
|
|
||||||
|
|
||||||
- parameter trust: is the trust to lookup the certificate chain for
|
|
||||||
|
|
||||||
- returns: the certificate chain for the trust
|
|
||||||
*/
|
|
||||||
func certificateChainForTrust(trust: SecTrustRef) -> [NSData] {
|
|
||||||
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([NSData]()) { (certificates: [NSData], index: Int) -> [NSData] in
|
|
||||||
var certificates = certificates
|
|
||||||
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
|
||||||
certificates.append(SecCertificateCopyData(cert!))
|
|
||||||
return certificates
|
|
||||||
}
|
|
||||||
|
|
||||||
return certificates
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the public key chain for the trust
|
|
||||||
|
|
||||||
- parameter trust: is the trust to lookup the certificate chain and extract the public keys
|
|
||||||
|
|
||||||
- returns: the public keys from the certifcate chain for the trust
|
|
||||||
*/
|
|
||||||
func publicKeyChainForTrust(trust: SecTrustRef) -> [SecKeyRef] {
|
|
||||||
let policy = SecPolicyCreateBasicX509()
|
|
||||||
let keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKeyRef]()) { (keys: [SecKeyRef], index: Int) -> [SecKeyRef] in
|
|
||||||
var keys = keys
|
|
||||||
let cert = SecTrustGetCertificateAtIndex(trust, index)
|
|
||||||
if let key = extractPublicKeyFromCert(cert!, policy: policy) {
|
|
||||||
keys.append(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user