Skip to content

Commit

Permalink
PacketTunnelCore: Introduce SelectedRelay and remove dependency on Re…
Browse files Browse the repository at this point in the history
…laySelector module

Also:
- IPC: accept NextRelay in "reconnect" message
  • Loading branch information
Andrej Mihajlov committed Oct 10, 2023
1 parent 3bed86d commit 2e8a6f8
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 132 deletions.
19 changes: 0 additions & 19 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@
58C7AF112ABD8480007EDD7A /* TunnelProviderMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA89226B0323E00B8C587 /* TunnelProviderMessage.swift */; };
58C7AF122ABD8480007EDD7A /* TunnelProviderReply.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5898D2A7290182B000EB5EBA /* TunnelProviderReply.swift */; };
58C7AF132ABD8480007EDD7A /* PacketTunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA89826B0329200B8C587 /* PacketTunnelStatus.swift */; };
58C7AF142ABD8480007EDD7A /* RelaySelectorResult+PacketTunnelRelay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C9B8CC2ABB247700040B46 /* RelaySelectorResult+PacketTunnelRelay.swift */; };
58C7AF152ABD8480007EDD7A /* PacketTunnelRelay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5898D2B62902A9EA00EB5EBA /* PacketTunnelRelay.swift */; };
58C7AF162ABD84A8007EDD7A /* URLRequestProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D229B6298D1D5200BB5A2D /* URLRequestProxy.swift */; };
58C7AF172ABD84AA007EDD7A /* ProxyURLRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 063687AF28EB083800BE7161 /* ProxyURLRequest.swift */; };
Expand Down Expand Up @@ -414,7 +413,6 @@
58FE25BF2AA72311003D1918 /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D96B192A8247C100A5C673 /* MigrationManager.swift */; };
58FE25C22AA72729003D1918 /* MullvadREST.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06799ABC28F98E1D00ACD94E /* MullvadREST.framework */; };
58FE25C62AA72779003D1918 /* PacketTunnelCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C7A4362A863F440060C66F /* PacketTunnelCore.framework */; };
58FE25CB2AA727A9003D1918 /* libRelaySelector.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5898D29829017DAC00EB5EBA /* libRelaySelector.a */; };
58FE25CE2AA72802003D1918 /* MullvadSettings.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58B2FDD32AA71D2A003EB5C6 /* MullvadSettings.framework */; };
58FE25D42AA729B5003D1918 /* ActorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FE25D32AA729B5003D1918 /* ActorTests.swift */; };
58FE25D72AA72A8F003D1918 /* State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5824030C2A811B0000163DE8 /* State.swift */; };
Expand Down Expand Up @@ -820,13 +818,6 @@
remoteGlobalIDString = 58C7A4352A863F440060C66F;
remoteInfo = PacketTunnelCore;
};
58FE25CC2AA727A9003D1918 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 58CE5E58224146200008646E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5898D29729017DAC00EB5EBA;
remoteInfo = RelaySelector;
};
58FE25D02AA72802003D1918 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 58CE5E58224146200008646E /* Project object */;
Expand Down Expand Up @@ -1324,7 +1315,6 @@
58C7A43D2A863F460060C66F /* PacketTunnelCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PacketTunnelCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
58C7A46F2A8649ED0060C66F /* PingerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PingerTests.swift; sourceTree = "<group>"; };
58C8191729FAA2C400DEB1B4 /* NotificationConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConfiguration.swift; sourceTree = "<group>"; };
58C9B8CC2ABB247700040B46 /* RelaySelectorResult+PacketTunnelRelay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RelaySelectorResult+PacketTunnelRelay.swift"; sourceTree = "<group>"; };
58CAF9F72983D36800BE19F7 /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = "<group>"; };
58CAF9FF2983FF0200BE19F7 /* LoginInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInteractor.swift; sourceTree = "<group>"; };
58CAFA01298530DC00BE19F7 /* Promise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1593,7 +1583,6 @@
buildActionMask = 2147483647;
files = (
A94D691A2ABAD66700413DD4 /* WireGuardKitTypes in Frameworks */,
58FE25CB2AA727A9003D1918 /* libRelaySelector.a in Frameworks */,
58C9B8DA2ABB271D00040B46 /* MullvadTransport.framework in Frameworks */,
58FE65952AB1D90600E53CB5 /* MullvadTypes.framework in Frameworks */,
58C7A45C2A8640490060C66F /* MullvadLogging.framework in Frameworks */,
Expand Down Expand Up @@ -2454,7 +2443,6 @@
587C575226D2615F005EF767 /* PacketTunnelOptions.swift */,
5898D2B62902A9EA00EB5EBA /* PacketTunnelRelay.swift */,
585DA89826B0329200B8C587 /* PacketTunnelStatus.swift */,
58C9B8CC2ABB247700040B46 /* RelaySelectorResult+PacketTunnelRelay.swift */,
585DA89226B0323E00B8C587 /* TunnelProviderMessage.swift */,
5898D2A7290182B000EB5EBA /* TunnelProviderReply.swift */,
);
Expand Down Expand Up @@ -3160,7 +3148,6 @@
);
dependencies = (
58C7A45F2A8640490060C66F /* PBXTargetDependency */,
58FE25CD2AA727A9003D1918 /* PBXTargetDependency */,
58FE65982AB1D90600E53CB5 /* PBXTargetDependency */,
58C9B8DD2ABB271D00040B46 /* PBXTargetDependency */,
);
Expand Down Expand Up @@ -3934,7 +3921,6 @@
58C7A4522A863FB50060C66F /* Pinger.swift in Sources */,
580D6B8C2AB3369300B2D6E0 /* BlockedStateErrorMapperProtocol.swift in Sources */,
58C7AF172ABD84AA007EDD7A /* ProxyURLRequest.swift in Sources */,
58C7AF142ABD8480007EDD7A /* RelaySelectorResult+PacketTunnelRelay.swift in Sources */,
5838321F2AC3160A00EA2071 /* Actor+KeyPolicy.swift in Sources */,
58C7AF122ABD8480007EDD7A /* TunnelProviderReply.swift in Sources */,
58C7A4572A863FB90060C66F /* TunnelDeviceInfoProtocol.swift in Sources */,
Expand Down Expand Up @@ -4587,11 +4573,6 @@
target = 58C7A4352A863F440060C66F /* PacketTunnelCore */;
targetProxy = 58FE25C82AA72779003D1918 /* PBXContainerItemProxy */;
};
58FE25CD2AA727A9003D1918 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5898D29729017DAC00EB5EBA /* RelaySelector */;
targetProxy = 58FE25CC2AA727A9003D1918 /* PBXContainerItemProxy */;
};
58FE25D12AA72802003D1918 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 58B2FDD22AA71D2A003EB5C6 /* MullvadSettings */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import RelayCache
import RelaySelector

final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
private var selectorResult: RelaySelectorResult?
private var selectedRelay: SelectedRelay?
private let urlRequestProxy: URLRequestProxy
private let relayCacheTracker: RelayCacheTracker

Expand All @@ -40,24 +40,24 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
completionHandler: @escaping (Error?) -> Void
) {
dispatchQueue.async {
var selectorResult: RelaySelectorResult?
var selectedRelay: SelectedRelay?

do {
let tunnelOptions = PacketTunnelOptions(rawOptions: options ?? [:])

selectorResult = try tunnelOptions.getSelectorResult()
selectedRelay = try tunnelOptions.getSelectedRelay()
} catch {
self.providerLogger.error(
error: error,
message: """
Failed to decode relay selector result passed from the app. \
Failed to decode selected relay passed from the app. \
Will continue by picking new relay.
"""
)
}

do {
self.selectorResult = try selectorResult ?? self.pickRelay()
self.selectedRelay = try selectedRelay ?? self.pickRelay()

completionHandler(nil)
} catch {
Expand All @@ -72,7 +72,7 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {

override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
dispatchQueue.async {
self.selectorResult = nil
self.selectedRelay = nil

completionHandler()
}
Expand All @@ -99,7 +99,7 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
switch message {
case .getTunnelStatus:
var tunnelStatus = PacketTunnelStatus()
tunnelStatus.tunnelRelay = self.selectorResult?.packetTunnelRelay
tunnelStatus.tunnelRelay = self.selectedRelay?.packetTunnelRelay

var reply: Data?
do {
Expand All @@ -113,10 +113,17 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {

completionHandler?(reply)

case let .reconnectTunnel(aSelectorResult):
case let .reconnectTunnel(nextRelay):
reasserting = true
if let aSelectorResult {
selectorResult = aSelectorResult
switch nextRelay {
case let .preSelected(selectedRelay):
self.selectedRelay = selectedRelay
case .random:
if let nextRelay = try? pickRelay() {
self.selectedRelay = nextRelay
}
case .current:
break
}
reasserting = false
completionHandler?(nil)
Expand Down Expand Up @@ -145,15 +152,19 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
}
}

private func pickRelay() throws -> RelaySelectorResult {
private func pickRelay() throws -> SelectedRelay {
let cachedRelays = try relayCacheTracker.getCachedRelays()
let tunnelSettings = try SettingsManager.readSettings()

return try RelaySelector.evaluate(
let selectorResult = try RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: tunnelSettings.relayConstraints,
numberOfFailedAttempts: 0
)
return SelectedRelay(
endpoint: selectorResult.endpoint,
hostname: selectorResult.relay.hostname,
location: selectorResult.location
)
}
}

Expand Down
16 changes: 8 additions & 8 deletions ios/MullvadVPN/TunnelManager/StartTunnelOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class StartTunnelOperation: ResultOperation<Void> {

case .disconnected, .pendingReconnect:
do {
let selectorResult = try interactor.selectRelay()
let selectedRelay = try interactor.selectRelay()

makeTunnelProviderAndStartTunnel(selectorResult: selectorResult) { error in
makeTunnelProviderAndStartTunnel(selectedRelay: selectedRelay) { error in
self.finish(result: error.map { .failure($0) } ?? .success(()))
}
} catch {
Expand All @@ -66,15 +66,15 @@ class StartTunnelOperation: ResultOperation<Void> {
}

private func makeTunnelProviderAndStartTunnel(
selectorResult: RelaySelectorResult,
selectedRelay: SelectedRelay,
completionHandler: @escaping (Error?) -> Void
) {
makeTunnelProvider { result in
self.dispatchQueue.async {
do {
try self.startTunnel(
tunnel: try result.get(),
selectorResult: selectorResult
selectedRelay: selectedRelay
)

completionHandler(nil)
Expand All @@ -85,11 +85,11 @@ class StartTunnelOperation: ResultOperation<Void> {
}
}

private func startTunnel(tunnel: Tunnel, selectorResult: RelaySelectorResult) throws {
private func startTunnel(tunnel: Tunnel, selectedRelay: SelectedRelay) throws {
var tunnelOptions = PacketTunnelOptions()

do {
try tunnelOptions.setSelectorResult(selectorResult)
try tunnelOptions.setSelectedRelay(selectedRelay)
} catch {
logger.error(
error: error,
Expand All @@ -101,8 +101,8 @@ class StartTunnelOperation: ResultOperation<Void> {

interactor.updateTunnelStatus { tunnelStatus in
tunnelStatus = TunnelStatus()
tunnelStatus.packetTunnelStatus.tunnelRelay = selectorResult.packetTunnelRelay
tunnelStatus.state = .connecting(selectorResult.packetTunnelRelay)
tunnelStatus.packetTunnelStatus.tunnelRelay = selectedRelay.packetTunnelRelay
tunnelStatus.state = .connecting(selectedRelay.packetTunnelRelay)
}

try tunnel.start(options: tunnelOptions.rawOptions())
Expand Down
8 changes: 4 additions & 4 deletions ios/MullvadVPN/TunnelManager/Tunnel+Messaging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ private let dispatchQueue = DispatchQueue(label: "Tunnel.dispatchQueue")
private let proxyRequestTimeout = REST.defaultAPINetworkTimeout + 2

extension Tunnel {
/// Request packet tunnel process to reconnect the tunnel with the given relay selector result.
/// Packet tunnel will reconnect to the current relay if relay selector result is not provided.
/// Request packet tunnel process to reconnect the tunnel with the given relay.
/// Packet tunnel will reconnect to the current relay if relay is not provided.
func reconnectTunnel(
relaySelectorResult: RelaySelectorResult?,
to nextRelay: NextRelay,
completionHandler: @escaping (Result<Void, Error>) -> Void
) -> Cancellable {
let operation = SendTunnelProviderMessageOperation(
dispatchQueue: dispatchQueue,
application: .shared,
tunnel: self,
message: .reconnectTunnel(relaySelectorResult),
message: .reconnectTunnel(nextRelay),
completionHandler: completionHandler
)

Expand Down
5 changes: 2 additions & 3 deletions ios/MullvadVPN/TunnelManager/TunnelInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

import Foundation
import MullvadSettings
import RelayCache
import RelaySelector
import PacketTunnelCore

protocol TunnelInteractor {
// MARK: - Tunnel manipulation
Expand Down Expand Up @@ -38,5 +37,5 @@ protocol TunnelInteractor {

func startTunnel()
func prepareForVPNConfigurationDeletion()
func selectRelay() throws -> RelaySelectorResult
func selectRelay() throws -> SelectedRelay
}
17 changes: 11 additions & 6 deletions ios/MullvadVPN/TunnelManager/TunnelManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,9 @@ final class TunnelManager: StorePaymentObserver {
throw UnsetTunnelError()
}

let selectorResult = selectNewRelay ? try self.selectRelay() : nil
let nextRelay: NextRelay = selectNewRelay ? .preSelected(try self.selectRelay()) : .current

return tunnel.reconnectTunnel(relaySelectorResult: selectorResult) { result in
return tunnel.reconnectTunnel(to: nextRelay) { result in
finish(result.error)
}
} catch {
Expand Down Expand Up @@ -819,14 +819,19 @@ final class TunnelManager: StorePaymentObserver {
updateTunnelStatus(tunnel?.status ?? .disconnected)
}

fileprivate func selectRelay() throws -> RelaySelectorResult {
fileprivate func selectRelay() throws -> SelectedRelay {
let cachedRelays = try relayCacheTracker.getCachedRelays()

return try RelaySelector.evaluate(
let selectorResult = try RelaySelector.evaluate(
relays: cachedRelays.relays,
constraints: settings.relayConstraints,
numberOfFailedAttempts: tunnelStatus.packetTunnelStatus.numberOfFailedAttempts
)

return SelectedRelay(
endpoint: selectorResult.endpoint,
hostname: selectorResult.relay.hostname,
location: selectorResult.location
)
}

fileprivate func prepareForVPNConfigurationDeletion() {
Expand Down Expand Up @@ -1306,7 +1311,7 @@ private struct TunnelInteractorProxy: TunnelInteractor {
tunnelManager.prepareForVPNConfigurationDeletion()
}

func selectRelay() throws -> RelaySelectorResult {
func selectRelay() throws -> SelectedRelay {
try tunnelManager.selectRelay()
}

Expand Down
4 changes: 2 additions & 2 deletions ios/PacketTunnel/PacketTunnelProvider/AppMessageHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ struct AppMessageHandler {
packetTunnelActor.notifyKeyRotation(date: nil)
return nil

case let .reconnectTunnel(selectorResult):
packetTunnelActor.reconnect(to: selectorResult.map { .preSelected($0) } ?? .current)
case let .reconnectTunnel(nextRelay):
packetTunnelActor.reconnect(to: nextRelay)
return nil
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ extension PacketTunnelProvider {
var parsedOptions = StartOptions(launchSource: tunnelOptions.isOnDemand() ? .onDemand : .app)

do {
if let selectorResult = try tunnelOptions.getSelectorResult() {
if let selectedRelay = try tunnelOptions.getSelectedRelay() {
parsedOptions.launchSource = .app
parsedOptions.selectorResult = selectorResult
parsedOptions.selectedRelay = selectedRelay
} else if !tunnelOptions.isOnDemand() {
parsedOptions.launchSource = .system
}
Expand Down
10 changes: 8 additions & 2 deletions ios/PacketTunnel/PacketTunnelProvider/RelaySelectorWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ struct RelaySelectorWrapper: RelaySelectorProtocol {
func selectRelay(
with constraints: RelayConstraints,
connectionAttemptFailureCount: UInt
) throws -> RelaySelectorResult {
try RelaySelector.evaluate(
) throws -> SelectedRelay {
let selectorResult = try RelaySelector.evaluate(
relays: relayCache.read().relays,
constraints: constraints,
numberOfFailedAttempts: connectionAttemptFailureCount
)

return SelectedRelay(
endpoint: selectorResult.endpoint,
hostname: selectorResult.relay.hostname,
location: selectorResult.location
)
}
}
Loading

0 comments on commit 2e8a6f8

Please sign in to comment.