From b1a79d6451b688c3be33e8dbf1785831afb0e893 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Wed, 24 Oct 2018 11:02:08 +0200 Subject: [PATCH] Shut down on server-initiated HARD_RESET Session is stale and not recoverable (lame duck). --- .../Sources/AppExtension/TunnelKitProvider.swift | 2 +- TunnelKit/Sources/Core/SessionError.swift | 3 +++ TunnelKit/Sources/Core/SessionProxy.swift | 15 ++++++++------- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift index 47b87d4..35e7373 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift @@ -652,7 +652,7 @@ extension TunnelKitProvider { } } else if let se = error as? SessionError { switch se { - case .negotiationTimeout, .pingTimeout: + case .negotiationTimeout, .pingTimeout, .staleSession: return .timeout case .badCredentials: diff --git a/TunnelKit/Sources/Core/SessionError.swift b/TunnelKit/Sources/Core/SessionError.swift index 632fe28..2198138 100644 --- a/TunnelKit/Sources/Core/SessionError.swift +++ b/TunnelKit/Sources/Core/SessionError.swift @@ -67,6 +67,9 @@ public enum SessionError: String, Error { /// The server couldn't ping back before timeout. case pingTimeout + + /// The session reached a stale state and can't be recovered. + case staleSession } extension Error { diff --git a/TunnelKit/Sources/Core/SessionProxy.swift b/TunnelKit/Sources/Core/SessionProxy.swift index 3e62a4e..e554ff8 100644 --- a/TunnelKit/Sources/Core/SessionProxy.swift +++ b/TunnelKit/Sources/Core/SessionProxy.swift @@ -326,12 +326,6 @@ public class SessionProxy { private func start() { loopLink() hardReset() - - guard !keys.isEmpty else { - fatalError("Main loop must follow hard reset, keys are empty!") - } - - loopNegotiation() } private func loopNegotiation() { @@ -466,7 +460,10 @@ public class SessionProxy { // deferStop(.shutdown, e) // return } - if (code == .softResetV1) && (negotiationKey.state != .softReset) { + if (code == .hardResetServerV2) && (negotiationKey.state != .hardReset) { + deferStop(.shutdown, SessionError.staleSession) + return + } else if (code == .softResetV1) && (negotiationKey.state != .softReset) { softReset(isServerInitiated: true) } @@ -560,6 +557,10 @@ public class SessionProxy { let payload = hardResetPayload() ?? Data() negotiationKey.state = .hardReset + guard !keys.isEmpty else { + fatalError("Main loop must follow hard reset, keys are empty!") + } + loopNegotiation() enqueueControlPackets(code: .hardResetClientV2, key: UInt8(negotiationKeyIdx), payload: payload) }