blob: c89ab573f0b5421ace5f5a717b3df36a1d26dd69 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
//
// OutOfTimeInteractor.swift
// MullvadVPN
//
// Created by pronebird on 26/10/2022.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import Foundation
import MullvadLogging
import MullvadREST
import MullvadSettings
import MullvadTypes
import Operations
@preconcurrency import StoreKit
final class OutOfTimeInteractor: Sendable {
private let tunnelManager: TunnelManager
nonisolated(unsafe) private var tunnelObserver: TunnelObserver?
nonisolated(unsafe) private let logger = Logger(label: "OutOfTimeInteractor")
private let accountUpdateTimerInterval: Duration = .minutes(1)
nonisolated(unsafe) private var accountUpdateTimer: DispatchSourceTimer?
nonisolated(unsafe) var didReceiveTunnelStatus: (@Sendable (TunnelStatus) -> Void)?
nonisolated(unsafe) var didAddMoreCredit: (@Sendable () -> Void)?
init(tunnelManager: TunnelManager) {
self.tunnelManager = tunnelManager
let tunnelObserver = TunnelBlockObserver(
didUpdateTunnelStatus: { [weak self] _, tunnelStatus in
self?.didReceiveTunnelStatus?(tunnelStatus)
},
didUpdateDeviceState: { [weak self] _, deviceState, previousDeviceState in
let isInactive = previousDeviceState.accountData?.isExpired == true
let isActive = deviceState.accountData?.isExpired == false
if isInactive && isActive {
self?.didAddMoreCredit?()
}
}
)
tunnelManager.addObserver(tunnelObserver)
self.tunnelObserver = tunnelObserver
}
var tunnelStatus: TunnelStatus {
tunnelManager.tunnelStatus
}
var deviceState: DeviceState {
tunnelManager.deviceState
}
func stopTunnel() {
tunnelManager.stopTunnel()
}
func startAccountUpdateTimer() {
logger.debug(
"Start polling account updates every \(accountUpdateTimerInterval) second(s)."
)
let timer = DispatchSource.makeTimerSource(queue: .main)
timer.setEventHandler { [weak self] in
self?.tunnelManager.updateAccountData()
}
accountUpdateTimer?.cancel()
accountUpdateTimer = timer
timer.schedule(
wallDeadline: .now() + accountUpdateTimerInterval,
repeating: accountUpdateTimerInterval.timeInterval
)
timer.activate()
}
func stopAccountUpdateTimer() {
logger.debug(
"Stop polling account updates."
)
accountUpdateTimer?.cancel()
accountUpdateTimer = nil
}
}
|