Skip to content

Commit 54d8f4c

Browse files
committed
Refactor WebSocket closure code logic.
1 parent 5607ed3 commit 54d8f4c

File tree

6 files changed

+119
-102
lines changed

6 files changed

+119
-102
lines changed

PusherSwift.xcodeproj/project.pbxproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
33BB997C1D21230100B25C2A /* PusherTopLevelAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33BB99661D21226C00B25C2A /* PusherTopLevelAPITests.swift */; };
3131
33C1FD6F1D81BFC300921AD7 /* ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C1FD6E1D81BFC300921AD7 /* ObjectiveC.swift */; };
3232
33C40CB91C1DFC9C008A54E3 /* PusherSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 33831CD61A9CFFF200B124F1 /* PusherSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
33+
53140355250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53140354250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift */; };
34+
53140356250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53140354250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift */; };
3335
539D9AFC2507F67300B5765A /* PusherLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9AFB2507F67300B5765A /* PusherLogger.swift */; };
3436
539D9AFE2507F68400B5765A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9AFD2507F68400B5765A /* Constants.swift */; };
3537
539D9AFF2507F69400B5765A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9AFD2507F68400B5765A /* Constants.swift */; };
@@ -38,8 +40,6 @@
3840
539D9B032509101E00B5765A /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9B012509101E00B5765A /* WebSocket.swift */; };
3941
539D9B05250913B300B5765A /* WebSocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9B04250913B300B5765A /* WebSocketConnection.swift */; };
4042
539D9B06250913B300B5765A /* WebSocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9B04250913B300B5765A /* WebSocketConnection.swift */; };
41-
539D9B082509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9B072509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift */; };
42-
539D9B092509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539D9B072509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift */; };
4343
736E53F5242A378B0052CC1B /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 736E53F3242A35D90052CC1B /* String+Extensions.swift */; };
4444
736E53F7242A45AC0052CC1B /* XCTest+Assertions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 736E53F6242A45AC0052CC1B /* XCTest+Assertions.swift */; };
4545
73D8A1E72435E5F3001FDE05 /* PusherDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33BA541F1D9035BD00CD853B /* PusherDelegate.swift */; };
@@ -145,11 +145,11 @@
145145
33BB99661D21226C00B25C2A /* PusherTopLevelAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PusherTopLevelAPITests.swift; sourceTree = "<group>"; };
146146
33BB99671D21226C00B25C2A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Tests/Info.plist; sourceTree = "<group>"; };
147147
33C1FD6E1D81BFC300921AD7 /* ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveC.swift; sourceTree = "<group>"; };
148+
53140354250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PusherChannelsProtocolCloseCode.swift; sourceTree = "<group>"; };
148149
539D9AFB2507F67300B5765A /* PusherLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PusherLogger.swift; sourceTree = "<group>"; };
149150
539D9AFD2507F68400B5765A /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
150151
539D9B012509101E00B5765A /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebSocket.swift; sourceTree = "<group>"; };
151152
539D9B04250913B300B5765A /* WebSocketConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketConnection.swift; sourceTree = "<group>"; };
152-
539D9B072509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSessionWebSocketTask.CloseCode+Extensions.swift"; sourceTree = "<group>"; };
153153
736E53F3242A35D90052CC1B /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
154154
736E53F6242A45AC0052CC1B /* XCTest+Assertions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTest+Assertions.swift"; sourceTree = "<group>"; };
155155
73D8A1FE2435E5F3001FDE05 /* PusherSwiftWithEncryption.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PusherSwiftWithEncryption.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -283,6 +283,7 @@
283283
539D9AFD2507F68400B5765A /* Constants.swift */,
284284
3384C1B81CAECD9C00F10796 /* PusherChannel.swift */,
285285
3389F5711CAEDDF300563F49 /* PusherChannels.swift */,
286+
53140354250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift */,
286287
3389F5791CAEDEC800563F49 /* PusherClientOptions.swift */,
287288
E2498292231E612700CFBBD6 /* PusherError.swift */,
288289
E2B21F06243F5B860049A35B /* PusherEvent.swift */,
@@ -308,7 +309,6 @@
308309
5333ACFC24F80F5C006E8DF0 /* Extensions */ = {
309310
isa = PBXGroup;
310311
children = (
311-
539D9B072509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift */,
312312
E2B21F0C243F5DC10049A35B /* PusherWebsocketDelegate.swift */,
313313
);
314314
path = Extensions;
@@ -750,6 +750,7 @@
750750
isa = PBXSourcesBuildPhase;
751751
buildActionMask = 2147483647;
752752
files = (
753+
53140355250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift in Sources */,
753754
E26B8606244A079E00735172 /* PusherEncryptionHelpers.swift in Sources */,
754755
539D9AFE2507F68400B5765A /* Constants.swift in Sources */,
755756
E2B21F0A243F5BB50049A35B /* PusherConnection.swift in Sources */,
@@ -772,7 +773,6 @@
772773
E2B21EFF243F5B1E0049A35B /* PusherEventQueue.swift in Sources */,
773774
3389F56E1CAEDDD800563F49 /* PusherPresenceChannel.swift in Sources */,
774775
33C1FD6F1D81BFC300921AD7 /* ObjectiveC.swift in Sources */,
775-
539D9B082509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift in Sources */,
776776
3390D1E61F054D0400E1944D /* AuthRequestBuilderProtocol.swift in Sources */,
777777
330D7A6A1CAEDA6C0032FF2C /* PusherSwift.swift in Sources */,
778778
);
@@ -807,6 +807,7 @@
807807
isa = PBXSourcesBuildPhase;
808808
buildActionMask = 2147483647;
809809
files = (
810+
53140356250A8F7600F3D7BF /* PusherChannelsProtocolCloseCode.swift in Sources */,
810811
E26B8607244A079E00735172 /* PusherEncryptionHelpers.swift in Sources */,
811812
E2B21F0B243F5BB50049A35B /* PusherConnection.swift in Sources */,
812813
73D8A1E72435E5F3001FDE05 /* PusherDelegate.swift in Sources */,
@@ -829,7 +830,6 @@
829830
E2B21F00243F5B1E0049A35B /* PusherEventQueue.swift in Sources */,
830831
73D8A1F22435E5F3001FDE05 /* PusherPresenceChannel.swift in Sources */,
831832
73D8A1F32435E5F3001FDE05 /* ObjectiveC.swift in Sources */,
832-
539D9B092509142200B5765A /* URLSessionWebSocketTask.CloseCode+Extensions.swift in Sources */,
833833
73D8A1F52435E5F3001FDE05 /* AuthRequestBuilderProtocol.swift in Sources */,
834834
73D8A1F62435E5F3001FDE05 /* PusherSwift.swift in Sources */,
835835
);

Sources/Extensions/PusherWebsocketDelegate.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Foundation
1+
import Network
22

33
extension PusherConnection: WebSocketConnectionDelegate {
44

@@ -45,7 +45,7 @@ extension PusherConnection: WebSocketConnectionDelegate {
4545
- parameter reason: Optional further information on the connection closure.
4646
*/
4747
func webSocketDidDisconnect(connection: WebSocketConnection,
48-
closeCode: Int,
48+
closeCode: NWProtocolWebSocket.CloseCode,
4949
reason: Data?) {
5050
// Handles setting channel subscriptions to unsubscribed wheter disconnection
5151
// is intentional or not

Sources/Extensions/URLSessionWebSocketTask.CloseCode+Extensions.swift

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import Foundation
2+
3+
// MARK: - Pusher Channels Protocol close codes
4+
5+
/// Describes closure codes as specified by the Pusher Channels Protocol.
6+
///
7+
/// These closure codes fall in the 4000 - 4999 range, i.e. the `privateCode` case of `NWProtocolWebSocket.CloseCode`.
8+
///
9+
/// Reference: https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol#error-codes
10+
internal enum PusherChannelsProtocolCloseCode: UInt16 {
11+
12+
// MARK: - Pusher Channels Protocol reconnection strategies
13+
14+
/// Describes the reconnection strategy for a given `PusherChannelsProtocolCloseCode`.
15+
///
16+
/// Reference: https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol#connection-closure
17+
internal enum ReconnectionStrategy: UInt16 {
18+
19+
/// Indicates an error resulting in the connection being closed by Pusher Channels,
20+
/// and that attempting to reconnect using the same parameters will not succeed.
21+
case doNotReconnectUnchanged
22+
23+
/// Indicates an error resulting in the connection being closed by Pusher Channels,
24+
/// and that the client may reconnect after 1s or more.
25+
case reconnectAfterBackingOff
26+
27+
/// Indicates an error resulting in the connection being closed by Pusher Channels,
28+
/// and that the client may reconnect immediately.
29+
case reconnectImmediately
30+
31+
/// Indicates any other type of error in the connection being closed by Pusher Channels,
32+
/// and the client may reconnect if appropriate.
33+
case reconnectIfAppropriate
34+
35+
/// Indicates that the reconnection strategy is unknown due to the closure code being
36+
/// outside of the expected range as specified by the Pusher Channels Protocol.
37+
case unknown
38+
39+
// MARK: - Initialization
40+
41+
init(rawValue: UInt16) {
42+
switch rawValue {
43+
case 4000...4099:
44+
self = .doNotReconnectUnchanged
45+
case 4100...4199:
46+
self = .reconnectAfterBackingOff
47+
case 4200...4299:
48+
self = .reconnectImmediately
49+
case 4300...4399:
50+
self = .reconnectIfAppropriate
51+
default:
52+
self = .unknown
53+
}
54+
}
55+
}
56+
57+
// 4000 - 4099
58+
case applicationOnlyAcceptsSSLConnections = 4000
59+
case applicationDoesNotExist = 4001
60+
case applicationDisabled = 4003
61+
case applicationIsOverConnectionQuota = 4004
62+
case pathNotFound = 4005
63+
case invalidVersionStringFormat = 4006
64+
case unsupportedProtocolVersion = 4007
65+
case noProtocolVersionSupplied = 4008
66+
case connectionIsUnauthorized = 4009
67+
68+
// 4100 - 4199
69+
case overCapacity = 4100
70+
71+
// 4200 - 4299
72+
case genericReconnectImmediately = 4200
73+
74+
/// Ping was sent to the client, but no reply was received
75+
case pongReplyNotReceived = 4201
76+
77+
/// Client has been inactive for a long time (currently 24 hours)
78+
/// and client does not support ping.
79+
case closedAfterInactivity = 4202
80+
81+
// 4300 - 4399
82+
case clientEventRejectedDueToRateLimit = 4300
83+
84+
// MARK: - Public properties
85+
86+
var reconnectionStrategy: ReconnectionStrategy {
87+
return ReconnectionStrategy(rawValue: self.rawValue)
88+
}
89+
}

Sources/Models/WebSocket.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Foundation
1+
import Network
22

33
/// Manages a websocket connection to a given server which can accept such connections.
44
open class WebSocket: NSObject, WebSocketConnection, URLSessionWebSocketDelegate {
@@ -41,8 +41,10 @@ open class WebSocket: NSObject, WebSocketConnection, URLSessionWebSocketDelegate
4141
webSocketTask: URLSessionWebSocketTask,
4242
didCloseWith closeCode: URLSessionWebSocketTask.CloseCode,
4343
reason: Data?) {
44+
// swiftlint:disable:next force_try
45+
let nwCloseCode = try! NWProtocolWebSocket.CloseCode(rawValue: UInt16(closeCode.rawValue))
4446
delegate?.webSocketDidDisconnect(connection: self,
45-
closeCode: closeCode.rawValue,
47+
closeCode: nwCloseCode,
4648
reason: reason)
4749
}
4850

@@ -110,9 +112,19 @@ open class WebSocket: NSObject, WebSocketConnection, URLSessionWebSocketDelegate
110112
}
111113
}
112114

113-
func disconnect(closeCode: Int = URLSessionWebSocketTask.CloseCode.normalClosure.rawValue) {
114-
let closeCode = URLSessionWebSocketTask.CloseCode(rawValue: closeCode) ?? .normalClosure
115-
webSocketTask?.cancel(with: closeCode, reason: nil)
115+
func disconnect(closeCode: NWProtocolWebSocket.CloseCode = .protocolCode(.normalClosure)) {
116+
117+
var webSocketTaskCloseCode: URLSessionWebSocketTask.CloseCode!
118+
switch closeCode {
119+
case .protocolCode(let definedCode):
120+
webSocketTaskCloseCode = URLSessionWebSocketTask.CloseCode(rawValue: Int(definedCode.rawValue))
121+
case .applicationCode, .privateCode:
122+
webSocketTaskCloseCode = .normalClosure
123+
@unknown default:
124+
fatalError()
125+
}
126+
127+
webSocketTask?.cancel(with: webSocketTaskCloseCode, reason: nil)
116128
webSocketTask = nil
117129
pingTimer?.invalidate()
118130
}

Sources/Protocols/WebSocketConnection.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Foundation
1+
import Network
22

33
/// Defines a websocket connection.
44
internal protocol WebSocketConnection {
@@ -25,15 +25,17 @@ internal protocol WebSocketConnection {
2525

2626
/// Disconnect from the websocket.
2727
/// - Parameter closeCode: The code to use when closing the websocket connection.
28-
func disconnect(closeCode: Int)
28+
func disconnect(closeCode: NWProtocolWebSocket.CloseCode)
2929

3030
var delegate: WebSocketConnectionDelegate? { get set }
3131
}
3232

3333
/// Defines a delegate for a websocket connection.
3434
internal protocol WebSocketConnectionDelegate: AnyObject {
3535
func webSocketDidConnect(connection: WebSocketConnection)
36-
func webSocketDidDisconnect(connection: WebSocketConnection, closeCode: Int, reason: Data?)
36+
func webSocketDidDisconnect(connection: WebSocketConnection,
37+
closeCode: NWProtocolWebSocket.CloseCode,
38+
reason: Data?)
3739
func webSocketDidReceiveError(connection: WebSocketConnection, error: Error)
3840
func webSocketDidReceivePong(connection: WebSocketConnection)
3941
func webSocketDidReceiveMessage(connection: WebSocketConnection, string: String)

0 commit comments

Comments
 (0)