Skip to content

Commit

Permalink
Throttle network path updates in packet tunnel
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson committed Nov 28, 2023
1 parent f976843 commit e6a35ed
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
// Copyright © 2023 Mullvad VPN AB. All rights reserved.
//

import Foundation
import Combine
import NetworkExtension
import PacketTunnelCore

final class PacketTunnelPathObserver: DefaultPathObserverProtocol {
private weak var packetTunnelProvider: NEPacketTunnelProvider?
private let stateLock = NSLock()
private var observationToken: NSKeyValueObservation?
private var pathUpdatePublisher: AnyCancellable?
private let eventQueue: DispatchQueue

init(packetTunnelProvider: NEPacketTunnelProvider) {
init(packetTunnelProvider: NEPacketTunnelProvider, eventQueue: DispatchQueue) {
self.packetTunnelProvider = packetTunnelProvider
self.eventQueue = eventQueue
}

var defaultPath: NetworkPath? {
Expand All @@ -25,22 +27,26 @@ final class PacketTunnelPathObserver: DefaultPathObserverProtocol {

func start(_ body: @escaping (NetworkPath) -> Void) {
stateLock.withLock {
observationToken?.invalidate()
pathUpdatePublisher?.cancel()

// Normally packet tunnel provider should exist throughout the network extension lifetime.
observationToken = packetTunnelProvider?.observe(\.defaultPath, options: [.new]) { _, change in
let nwPath = change.newValue.flatMap { $0 }
if let nwPath {
body(nwPath)
pathUpdatePublisher = packetTunnelProvider?.publisher(for: \.defaultPath)
.removeDuplicates(by: { oldPath, newPath in
oldPath?.status == newPath?.status
})
.throttle(for: .seconds(2), scheduler: eventQueue, latest: true)
.sink { change in
if let change {
body(change)
}
}
}
}
}

func stop() {
stateLock.withLock {
observationToken?.invalidate()
observationToken = nil
pathUpdatePublisher?.cancel()
pathUpdatePublisher = nil
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
eventQueue: internalQueue,
pinger: Pinger(replyQueue: internalQueue),
tunnelDeviceInfo: adapter,
defaultPathObserver: PacketTunnelPathObserver(packetTunnelProvider: self),
defaultPathObserver: PacketTunnelPathObserver(packetTunnelProvider: self, eventQueue: internalQueue),
timings: TunnelMonitorTimings()
)

Expand All @@ -78,7 +78,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
timings: PacketTunnelActorTimings(),
tunnelAdapter: adapter,
tunnelMonitor: tunnelMonitor,
defaultPathObserver: PacketTunnelPathObserver(packetTunnelProvider: self),
defaultPathObserver: PacketTunnelPathObserver(packetTunnelProvider: self, eventQueue: internalQueue),
blockedStateErrorMapper: BlockedStateErrorMapper(),
relaySelector: RelaySelectorWrapper(relayCache: relayCache),
settingsReader: SettingsReader()
Expand Down

0 comments on commit e6a35ed

Please sign in to comment.