Skip to content

Commit 36fa256

Browse files
committed
chore: reconfigure VPN on reinstall
1 parent 3a520d5 commit 36fa256

File tree

5 files changed

+20
-11
lines changed

5 files changed

+20
-11
lines changed

Coder Desktop/Coder Desktop/Coder_DesktopApp.swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
5050
object: nil
5151
)
5252
Task {
53-
// If there's no NE config, then the user needs to sign in.
54-
// However, they might have a session from a previous install, so we
55-
// need to clear it.
53+
// If there's no NE config, but the user is logged in, such as
54+
// from a previous install, then we need to reconfigure.
5655
if await !vpn.loadNetworkExtensionConfig() {
57-
state.clearSession()
56+
state.reconfigure()
5857
}
5958
}
6059
}

Coder Desktop/Coder Desktop/MenuBarIconController.swift

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class MenuBarController {
1313

1414
init(menuBarExtra: FluidMenuBarExtra) {
1515
self.menuBarExtra = menuBarExtra
16+
// Off by default, as `vpnDidUpdate` isn't called until the VPN is configured
17+
menuBarExtra.setOpacity(offOpacity)
1618
}
1719

1820
func vpnDidUpdate(_ connection: NETunnelProviderSession) {

Coder Desktop/Coder Desktop/State.swift

+9-5
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ class AppState: ObservableObject {
3232

3333
@Published var useLiteralHeaders: Bool = UserDefaults.standard.bool(forKey: Keys.useLiteralHeaders) {
3434
didSet {
35-
if let onChange { onChange(tunnelProviderProtocol()) }
35+
reconfigure()
3636
guard persistent else { return }
3737
UserDefaults.standard.set(useLiteralHeaders, forKey: Keys.useLiteralHeaders)
3838
}
3939
}
4040

4141
@Published var literalHeaders: [LiteralHeader] {
4242
didSet {
43-
if let onChange { onChange(tunnelProviderProtocol()) }
43+
reconfigure()
4444
guard persistent else { return }
4545
try? UserDefaults.standard.set(JSONEncoder().encode(literalHeaders), forKey: Keys.literalHeaders)
4646
}
@@ -70,9 +70,13 @@ class AppState: ObservableObject {
7070
private let keychain: Keychain
7171
private let persistent: Bool
7272

73-
// This closure must be called when any property used to configure the VPN changes
7473
let onChange: ((NETunnelProviderProtocol?) -> Void)?
7574

75+
// reconfigure must be called when any property used to configure the VPN changes
76+
public func reconfigure() {
77+
if let onChange { onChange(tunnelProviderProtocol()) }
78+
}
79+
7680
public init(onChange: ((NETunnelProviderProtocol?) -> Void)? = nil,
7781
persistent: Bool = true)
7882
{
@@ -97,13 +101,13 @@ class AppState: ObservableObject {
97101
hasSession = true
98102
self.baseAccessURL = baseAccessURL
99103
self.sessionToken = sessionToken
100-
if let onChange { onChange(tunnelProviderProtocol()) }
104+
reconfigure()
101105
}
102106

103107
public func clearSession() {
104108
hasSession = false
105109
sessionToken = nil
106-
if let onChange { onChange(tunnelProviderProtocol()) }
110+
reconfigure()
107111
}
108112

109113
private func keychainGet(for key: String) -> String? {

Coder Desktop/Coder Desktop/Views/LoginForm.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct LoginForm: View {
3838
.animation(.easeInOut, value: currentPage)
3939
.onAppear {
4040
baseAccessURL = state.baseAccessURL?.absoluteString ?? baseAccessURL
41-
sessionToken = ""
41+
sessionToken = state.sessionToken ?? sessionToken
4242
}
4343
.alert("Error", isPresented: Binding(
4444
get: { loginError != nil },
@@ -122,7 +122,7 @@ struct LoginForm: View {
122122
).disabled(true)
123123
}
124124
Section {
125-
SecureField("Session Token", text: $sessionToken, prompt: Text("●●●●●●●●"))
125+
SecureField("Session Token", text: $sessionToken)
126126
.autocorrectionDisabled()
127127
.privacySensitive()
128128
.focused($focusedField, equals: .sessionToken)

Coder Desktop/VPN/Manager.swift

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ actor Manager {
3030
let sessionConfig = URLSessionConfiguration.default
3131
// The tunnel might be asked to start before the network interfaces have woken up from sleep
3232
sessionConfig.waitsForConnectivity = true
33+
// URLSession's waiting for connectivity sometimes hangs even when
34+
// the network is up so this is deliberately short (15s) to avoid a
35+
// poor UX where it appears stuck.
36+
sessionConfig.timeoutIntervalForResource = 15
3337
try await download(src: dylibPath, dest: dest, urlSession: URLSession(configuration: sessionConfig))
3438
} catch {
3539
throw .download(error)

0 commit comments

Comments
 (0)