Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitaedbe8e

Browse files
committed
chore: handle waking from device sleep
1 parent250017b commitaedbe8e

File tree

5 files changed

+37
-31
lines changed

5 files changed

+37
-31
lines changed

‎Coder Desktop/Coder Desktop/Views/VPNMenu.swift

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@ struct VPNMenu<VPN: VPNService, S: Session>: View {
55
@EnvironmentObjectvarsession:S
66
@Environment(\.openSettings)privatevaropenSettings
77

8-
// There appears to be a race between the VPN service reporting itself as disconnected,
9-
// and the system extension process exiting. When the VPN is toggled off and on quickly,
10-
// an error is shown: "The VPN session failed because an internal error occurred".
11-
// This forces the user to wait a few seconds before they can toggle the VPN back on.
12-
@StateprivatevarwaitCleanup=false
13-
privatevarwaitCleanupDuration:Duration=.seconds(6)
14-
158
letinspection=Inspection<Self>()
169

1710
varbody:someView{
@@ -23,7 +16,7 @@ struct VPNMenu<VPN: VPNService, S: Session>: View {
2316
Toggle(isOn:Binding(
2417
get:{ vpn.state==.connected || vpn.state==.connecting},
2518
set:{ isOninTask{
26-
if isOn{await vpn.start()}else{awaitstop()}
19+
if isOn{await vpn.start()}else{awaitvpn.stop()}
2720
}
2821
}
2922
)){
@@ -93,21 +86,11 @@ struct VPNMenu<VPN: VPNService, S: Session>: View {
9386
}
9487

9588
privatevarvpnDisabled:Bool{
96-
waitCleanup ||
97-
!session.hasSession ||
89+
!session.hasSession ||
9890
vpn.state==.connecting ||
9991
vpn.state==.disconnecting ||
10092
vpn.state==.failed(.systemExtensionError(.needsUserApproval))
10193
}
102-
103-
privatefunc stop()async{
104-
await vpn.stop()
105-
waitCleanup=true
106-
Task{
107-
try?awaitTask.sleep(for: waitCleanupDuration)
108-
waitCleanup=false
109-
}
110-
}
11194
}
11295

11396
func openSystemExtensionSettings(){

‎Coder Desktop/VPN/Manager.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ actor Manager {
2727
fatalError("unknown architecture")
2828
#endif
2929
do{
30-
tryawaitdownload(src: dylibPath, dest: dest)
30+
letsessionConfig=URLSessionConfiguration.default
31+
// The tunnel might be asked to start before the network interfaces have woken up from sleep
32+
sessionConfig.waitsForConnectivity=true
33+
tryawaitdownload(src: dylibPath, dest: dest, urlSession:URLSession(configuration: sessionConfig))
3134
}catch{
3235
throw.download(error)
3336
}

‎Coder Desktop/VPN/PacketTunnelProvider.swift

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
4747
options _:[String:NSObject]?, completionHandler:@escaping(Error?)->Void
4848
){
4949
logger.info("startTunnel called")
50+
start(completionHandler)
51+
}
52+
53+
// called by `startTunnel` and on `wake`
54+
func start(_ completionHandler:@escaping(Error?)->Void){
5055
guard manager==nilelse{
5156
logger.error("startTunnel called with non-nil Manager")
5257
completionHandler(makeNSError(suffix:"PTP", desc:"Already running"))
@@ -95,8 +100,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
95100
with _:NEProviderStopReason, completionHandler:@escaping()->Void
96101
){
97102
logger.debug("stopTunnel called")
103+
teardown(completionHandler)
104+
}
105+
106+
// called by `stopTunnel` and `sleep`
107+
func teardown(_ completionHandler:@escaping()->Void){
98108
guardlet managerelse{
99-
logger.error("stopTunnel called with nil Manager")
109+
logger.error("teardown called with nil Manager")
100110
completionHandler()
101111
return
102112
}
@@ -121,15 +131,25 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
121131
}
122132
}
123133

134+
// sleep and wake reference: https://developer.apple.com/forums/thread/95988
124135
overridefunc sleep(completionHandler:@escaping()->Void){
125-
// Add code here to get ready to sleep.
126136
logger.debug("sleep called")
127-
completionHandler()
137+
teardown(completionHandler)
128138
}
129139

130140
overridefunc wake(){
131-
// Add code here to wake up.
132141
logger.debug("wake called")
142+
reasserting=true
143+
currentSettings=.init(tunnelRemoteAddress:"127.0.0.1")
144+
setTunnelNetworkSettings(nil)
145+
start{ errorin
146+
iflet error{
147+
self.logger.error("error starting tunnel after wake:\(error.localizedDescription)")
148+
self.cancelTunnelWithError(error)
149+
}else{
150+
self.reasserting=false
151+
}
152+
}
133153
}
134154

135155
// Wrapper around `setTunnelNetworkSettings` that supports merging updates

‎Coder Desktop/VPNLib/Download.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public class SignatureValidator {
101101
}
102102
}
103103

104-
publicfunc download(src:URL, dest:URL)asyncthrows(DownloadError){
104+
publicfunc download(src:URL, dest:URL, urlSession:URLSession)asyncthrows(DownloadError){
105105
varreq=URLRequest(url: src)
106106
ifFileManager.default.fileExists(atPath: dest.path){
107107
iflet existingFileData=try?Data(contentsOf: dest, options:.mappedIfSafe){
@@ -112,7 +112,7 @@ public func download(src: URL, dest: URL) async throws(DownloadError) {
112112
lettempURL:URL
113113
letresponse:URLResponse
114114
do{
115-
(tempURL, response)=tryawaitURLSession.shared.download(for: req)
115+
(tempURL, response)=tryawaiturlSession.download(for: req)
116116
}catch{
117117
throw.networkError(error)
118118
}

‎Coder Desktop/VPNLibTests/DownloadTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct DownloadTests {
1313
letfileURL=URL(string:"http://example.com/test1.txt")!
1414
Mock(url: fileURL, contentType:.html, statusCode:200, data:[.get: testData]).register()
1515

16-
tryawaitdownload(src: fileURL, dest: destinationURL)
16+
tryawaitdownload(src: fileURL, dest: destinationURL, urlSession:URLSession.shared)
1717

1818
try #require(FileManager.default.fileExists(atPath: destinationURL.path))
1919
defer{try?FileManager.default.removeItem(at: destinationURL)}
@@ -32,7 +32,7 @@ struct DownloadTests {
3232

3333
Mock(url: fileURL, contentType:.html, statusCode:200, data:[.get: testData]).register()
3434

35-
tryawaitdownload(src: fileURL, dest: destinationURL)
35+
tryawaitdownload(src: fileURL, dest: destinationURL, urlSession:URLSession.shared)
3636
try #require(FileManager.default.fileExists(atPath: destinationURL.path))
3737
letdownloadedData=tryData(contentsOf: destinationURL)
3838
#expect(downloadedData== testData)
@@ -44,7 +44,7 @@ struct DownloadTests {
4444
}
4545
mock.register()
4646

47-
tryawaitdownload(src: fileURL, dest: destinationURL)
47+
tryawaitdownload(src: fileURL, dest: destinationURL, urlSession:URLSession.shared)
4848
letunchangedData=tryData(contentsOf: destinationURL)
4949
#expect(unchangedData== testData)
5050
#expect(etagIncluded)
@@ -61,7 +61,7 @@ struct DownloadTests {
6161

6262
Mock(url: fileURL, contentType:.html, statusCode:200, data:[.get: ogData]).register()
6363

64-
tryawaitdownload(src: fileURL, dest: destinationURL)
64+
tryawaitdownload(src: fileURL, dest: destinationURL, urlSession:URLSession.shared)
6565
try #require(FileManager.default.fileExists(atPath: destinationURL.path))
6666
vardownloadedData=tryData(contentsOf: destinationURL)
6767
#expect(downloadedData== ogData)
@@ -73,7 +73,7 @@ struct DownloadTests {
7373
}
7474
mock.register()
7575

76-
tryawaitdownload(src: fileURL, dest: destinationURL)
76+
tryawaitdownload(src: fileURL, dest: destinationURL, urlSession:URLSession.shared)
7777
downloadedData=tryData(contentsOf: destinationURL)
7878
#expect(downloadedData== newData)
7979
#expect(etagIncluded)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp