Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pixels to track VPN wake and stop attempts #797

Merged
merged 7 commits into from
Apr 26, 2024
Prev Previous commit
Next Next commit
Tentative fix for tunnel stop issues
  • Loading branch information
diegoreymendez committed Apr 23, 2024
commit 3aea1610bbe8701d6afa6551152278c502d1ce2e
7 changes: 2 additions & 5 deletions Sources/Common/Concurrency/TaskExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ import Foundation

public extension Task where Success == Never, Failure == Error {

static func periodic(priority: TaskPriority? = nil,
delay: TimeInterval? = nil,
static func periodic(delay: TimeInterval? = nil,
interval: TimeInterval,
operation: @escaping @Sendable () async -> Void,
cancellationHandler: (@Sendable () async -> Void)? = nil) -> Task {

Task.detached(priority: priority) {
diegoreymendez marked this conversation as resolved.
Show resolved Hide resolved
Task {
do {
if let delay {
try await Task<Never, Never>.sleep(interval: delay)
Expand All @@ -42,9 +41,7 @@ public extension Task where Success == Never, Failure == Error {
throw error
}
}

}

}

public extension Task where Success == Never, Failure == Never {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ final class NetworkProtectionConnectionTester {
static let monitorQueue = DispatchQueue(label: "com.duckduckgo.NetworkProtectionConnectionTester.monitorQueue")
static let endpoint = NWEndpoint.hostPort(host: .name("www.duckduckgo.com", nil), port: .https)

private var timer: DispatchSourceTimer?
private var task: Task<Never, Error>?
diegoreymendez marked this conversation as resolved.
Show resolved Hide resolved

// MARK: - Dispatch Queue

Expand Down Expand Up @@ -100,7 +100,7 @@ final class NetworkProtectionConnectionTester {

deinit {
os_log("[-] %{public}@", log: .networkProtectionMemoryLog, type: .debug, String(describing: self))
timer?.cancel()
task?.cancel()
}

// MARK: - Testing
Expand Down Expand Up @@ -131,9 +131,9 @@ final class NetworkProtectionConnectionTester {
}
}

func stop() async {
func stop() {
os_log("🔴 Stopping connection tester", log: log)
await stopScheduledTimer()
stopScheduledTimer()
isRunning = false
}

Expand Down Expand Up @@ -168,7 +168,7 @@ final class NetworkProtectionConnectionTester {
// MARK: - Timer scheduling

private func scheduleTimer(testImmediately: Bool) async throws {
await stopScheduledTimer()
stopScheduledTimer()

if testImmediately {
do {
Expand All @@ -179,50 +179,19 @@ final class NetworkProtectionConnectionTester {
}
}

let timer = DispatchSource.makeTimerSource(queue: timerQueue)
self.timer = timer

timer.schedule(deadline: .now() + self.intervalBetweenTests, repeating: self.intervalBetweenTests)
timer.setEventHandler { [weak self] in
Task { [self] in
// During regular connection tests we don't care about the error thrown
// by this method, as it'll be handled through the result handler callback.
// The error we're ignoring here is only used when this class is initialized
// with an immediate test, to know whether the connection is up while the user
// still sees "Connecting..."
try? await self?.testConnection()
}
task = Task.periodic(interval: intervalBetweenTests) { [weak self] in
// During regular connection tests we don't care about the error thrown
// by this method, as it'll be handled through the result handler callback.
// The error we're ignoring here is only used when this class is initialized
// with an immediate test, to know whether the connection is up while the user
// still sees "Connecting..."
try? await self?.testConnection()
}

// Enable back if needed. The only reason this commented code is left in is because it has
// documentation purposes, and while the timer should not be released here, it's ok to enable
// back the cancellation handler if it's needed for other purposes.
//
// timer.setCancelHandler { [weak self] in
// Do not re-enable this.
// Releasing the timer here is causing a crash. I'm leaving this here for documentation
// purposes, so that we're not tempted to add this back.
//
// self?.timer = nil
// }

timer.resume()
}

private func stopScheduledTimer() async {
cancelTimerImmediately()
}

private func cancelTimerImmediately() {
guard let timer = timer else {
return
}

if !timer.isCancelled {
timer.cancel()
}

self.timer = nil
private func stopScheduledTimer() {
task?.cancel()
task = nil
}

// MARK: - Testing the connection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public actor NetworkProtectionEntitlementMonitor {
public func stop() {
os_log("⚫️ Stopping entitlement monitor", log: .networkProtectionEntitlementMonitorLog)

task?.cancel() // Just making extra sure in case it's detached
task = nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public actor NetworkProtectionLatencyMonitor {
os_log("⚫️ Stopping latency monitor", log: .networkProtectionLatencyMonitorLog)

latencyCancellable = nil
task?.cancel() // Just making extra sure in case it's detached
task = nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ public actor NetworkProtectionTunnelFailureMonitor {
func stop() {
os_log("⚫️ Stopping tunnel failure monitor", log: .networkProtectionTunnelFailureMonitorLog)

networkMonitor.cancel()
networkMonitor.pathUpdateHandler = nil

task?.cancel() // Just making extra sure in case it's detached
task = nil
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/NetworkProtection/PacketTunnelProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ open class PacketTunnelProvider: NEPacketTunnelProvider {
open override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
diegoreymendez marked this conversation as resolved.
Show resolved Hide resolved

Task { @MainActor in
try await Task.sleep(interval: .seconds(3000))
await stopMonitors()

connectionStatus = .disconnecting
Expand Down Expand Up @@ -1302,7 +1303,7 @@ open class PacketTunnelProvider: NEPacketTunnelProvider {

@MainActor
public func stopMonitors() async {
await self.connectionTester.stop()
self.connectionTester.stop()
await self.tunnelFailureMonitor.stop()
await self.latencyMonitor.stop()
await self.entitlementMonitor.stop()
Expand Down