summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/SimulatorTunnelProviderHost.swift50
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider.swift57
-rw-r--r--ios/TunnelProviderMessaging/URLRequestProxy.swift72
4 files changed, 113 insertions, 70 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 44ab78144f..caab716d84 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -305,6 +305,7 @@
58D22422294C921B0029F5F8 /* MullvadLogging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58D223F3294C8FF00029F5F8 /* MullvadLogging.framework */; };
58D22426294C92750029F5F8 /* MullvadTypes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58D223D5294C8E5E0029F5F8 /* MullvadTypes.framework */; platformFilter = ios; };
58D22435294C975B0029F5F8 /* Operations.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58D223A5294C8A480029F5F8 /* Operations.framework */; platformFilter = ios; };
+ 58D229B8298D1FE200BB5A2D /* URLRequestProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D229B6298D1D5200BB5A2D /* URLRequestProxy.swift */; };
58DF28A52417CB4B00E836B0 /* StorePaymentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58DF28A42417CB4B00E836B0 /* StorePaymentManager.swift */; };
58E0729D28814AAE008902F8 /* PacketTunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0729C28814AAE008902F8 /* PacketTunnelConfiguration.swift */; };
58E0729F28814ACC008902F8 /* WireGuardLogLevel+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E0729E28814ACC008902F8 /* WireGuardLogLevel+Logging.swift */; };
@@ -854,6 +855,7 @@
58D223D7294C8E5E0029F5F8 /* MullvadTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MullvadTypes.h; sourceTree = "<group>"; };
58D223F3294C8FF00029F5F8 /* MullvadLogging.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MullvadLogging.framework; sourceTree = BUILT_PRODUCTS_DIR; };
58D223F5294C8FF00029F5F8 /* MullvadLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MullvadLogging.h; sourceTree = "<group>"; };
+ 58D229B6298D1D5200BB5A2D /* URLRequestProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestProxy.swift; sourceTree = "<group>"; };
58DF28A42417CB4B00E836B0 /* StorePaymentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorePaymentManager.swift; sourceTree = "<group>"; };
58DF5B732851FF3F00E92647 /* InputOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputOperation.swift; sourceTree = "<group>"; };
58DF5B752852108E00E92647 /* InputInjectionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputInjectionBuilder.swift; sourceTree = "<group>"; };
@@ -1244,6 +1246,7 @@
5898D2AD290185D200EB5EBA /* ProxyURLResponse.swift */,
585DA89226B0323E00B8C587 /* TunnelProviderMessage.swift */,
5898D2A7290182B000EB5EBA /* TunnelProviderReply.swift */,
+ 58D229B6298D1D5200BB5A2D /* URLRequestProxy.swift */,
);
path = TunnelProviderMessaging;
sourceTree = "<group>";
@@ -2228,6 +2231,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 58D229B8298D1FE200BB5A2D /* URLRequestProxy.swift in Sources */,
5898D29129017C3100EB5EBA /* TunnelProviderMessage.swift in Sources */,
5898D29029017BEE00EB5EBA /* PacketTunnelOptions.swift in Sources */,
5898D2AE290185D200EB5EBA /* ProxyURLResponse.swift in Sources */,
diff --git a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
index 1ddf7b295f..3841a3bd8b 100644
--- a/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
+++ b/ios/MullvadVPN/SimulatorTunnelProviderHost.swift
@@ -19,8 +19,7 @@ import TunnelProviderMessaging
final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
private var selectorResult: RelaySelectorResult?
- private let urlSession = REST.makeURLSession()
- private var proxiedRequests = [UUID: URLSessionDataTask]()
+ private let urlRequestProxy: URLRequestProxy
private let relayCacheTracker: RelayCacheTracker
private let providerLogger = Logger(label: "SimulatorTunnelProviderHost")
@@ -28,6 +27,10 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
init(relayCacheTracker: RelayCacheTracker) {
self.relayCacheTracker = relayCacheTracker
+ self.urlRequestProxy = URLRequestProxy(
+ urlSession: REST.makeURLSession(),
+ dispatchQueue: dispatchQueue
+ )
}
override func startTunnel(
@@ -123,40 +126,21 @@ final class SimulatorTunnelProviderHost: SimulatorTunnelProviderDelegate {
completionHandler?(nil)
case let .sendURLRequest(proxyRequest):
- let task = urlSession
- .dataTask(with: proxyRequest.urlRequest) { [weak self] data, response, error in
- guard let self = self else { return }
-
- self.dispatchQueue.async {
- self.proxiedRequests.removeValue(forKey: proxyRequest.id)
-
- var reply: Data?
- do {
- let proxyResponse = ProxyURLResponse(
- data: data,
- response: response,
- error: error
- )
- reply = try TunnelProviderReply(proxyResponse).encode()
- } catch {
- self.providerLogger.error(
- error: error,
- message: "Failed to encode ProxyURLResponse."
- )
- }
-
- completionHandler?(reply)
- }
+ urlRequestProxy.sendRequest(proxyRequest) { response in
+ var reply: Data?
+ do {
+ reply = try TunnelProviderReply(response).encode()
+ } catch {
+ self.providerLogger.error(
+ error: error,
+ message: "Failed to encode ProxyURLResponse."
+ )
}
-
- proxiedRequests[proxyRequest.id] = task
-
- task.resume()
+ completionHandler?(reply)
+ }
case let .cancelURLRequest(id):
- let task = proxiedRequests.removeValue(forKey: id)
-
- task?.cancel()
+ urlRequestProxy.cancelRequest(identifier: id)
completionHandler?(nil)
}
diff --git a/ios/PacketTunnel/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider.swift
index b8382e6f3f..9de2504487 100644
--- a/ios/PacketTunnel/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider.swift
@@ -64,12 +64,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
/// Current selector result.
private var selectorResult: RelaySelectorResult?
- /// URL session used for proxy requests.
- private let urlSession = REST.makeURLSession()
-
- /// List of all proxied network requests bypassing VPN.
- private var proxiedRequests: [UUID: URLSessionDataTask] = [:]
-
/// A system completion handler passed from startTunnel and saved for later use once the
/// connection is established.
private var startTunnelCompletionHandler: (() -> Void)?
@@ -77,6 +71,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
/// Tunnel monitor.
private var tunnelMonitor: TunnelMonitor!
+ /// Request proxy used to perform URLRequests bypassing VPN.
+ private let urlRequestProxy: URLRequestProxy
+
/// Account data request proxy
private let accountsProxy: REST.AccountsProxy
@@ -130,6 +127,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
securityGroupIdentifier: ApplicationConfiguration.securityGroupIdentifier,
isReadOnly: true
)!
+
+ let urlSession = REST.makeURLSession()
let urlSessionTransport = REST.URLSessionTransport(urlSession: urlSession)
let proxyFactory = REST.ProxyFactory.makeProxyFactory(
transportProvider: { () -> RESTTransport? in
@@ -137,6 +136,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
},
addressCache: addressCache
)
+
+ urlRequestProxy = URLRequestProxy(urlSession: urlSession, dispatchQueue: dispatchQueue)
accountsProxy = proxyFactory.createAccountsProxy()
devicesProxy = proxyFactory.createDevicesProxy()
@@ -314,40 +315,22 @@ class PacketTunnelProvider: NEPacketTunnelProvider, TunnelMonitorDelegate {
completionHandler?(response)
case let .sendURLRequest(proxyRequest):
- let task = self.urlSession
- .dataTask(with: proxyRequest.urlRequest) { [weak self] data, response, error in
- guard let self = self else { return }
-
- self.dispatchQueue.async {
- self.proxiedRequests.removeValue(forKey: proxyRequest.id)
-
- var reply: Data?
- do {
- let response = ProxyURLResponse(
- data: data,
- response: response,
- error: error
- )
- reply = try TunnelProviderReply(response).encode()
- } catch {
- self.providerLogger.error(
- error: error,
- message: "Failed to encode ProxyURLResponse."
- )
- }
-
- completionHandler?(reply)
- }
+ self.urlRequestProxy.sendRequest(proxyRequest) { response in
+ var reply: Data?
+ do {
+ reply = try TunnelProviderReply(response).encode()
+ } catch {
+ self.providerLogger.error(
+ error: error,
+ message: "Failed to encode ProxyURLResponse."
+ )
}
-
- self.proxiedRequests[proxyRequest.id] = task
-
- task.resume()
+ completionHandler?(reply)
+ }
case let .cancelURLRequest(id):
- let task = self.proxiedRequests.removeValue(forKey: id)
-
- task?.cancel()
+ self.urlRequestProxy.cancelRequest(identifier: id)
+ completionHandler?(nil)
}
}
}
diff --git a/ios/TunnelProviderMessaging/URLRequestProxy.swift b/ios/TunnelProviderMessaging/URLRequestProxy.swift
new file mode 100644
index 0000000000..8d66819ebb
--- /dev/null
+++ b/ios/TunnelProviderMessaging/URLRequestProxy.swift
@@ -0,0 +1,72 @@
+//
+// URLRequestProxy.swift
+// PacketTunnel
+//
+// Created by pronebird on 03/02/2023.
+// Copyright © 2023 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+public final class URLRequestProxy {
+ /// Serial queue used for synchronizing access to class members.
+ private let dispatchQueue: DispatchQueue
+
+ /// URL session used for proxy requests.
+ private let urlSession: URLSession
+
+ /// List of all proxied network requests bypassing VPN.
+ private var proxiedRequests: [UUID: URLSessionDataTask] = [:]
+
+ public init(urlSession: URLSession, dispatchQueue: DispatchQueue) {
+ self.urlSession = urlSession
+ self.dispatchQueue = dispatchQueue
+ }
+
+ public func sendRequest(
+ _ proxyRequest: ProxyURLRequest,
+ completionHandler: @escaping (ProxyURLResponse) -> Void
+ ) {
+ dispatchQueue.async {
+ let task = self.urlSession
+ .dataTask(with: proxyRequest.urlRequest) { [weak self] data, response, error in
+ guard let self = self else { return }
+
+ self.dispatchQueue.async {
+ let response = ProxyURLResponse(
+ data: data,
+ response: response,
+ error: error
+ )
+
+ _ = self.removeRequest(identifier: proxyRequest.id)
+
+ completionHandler(response)
+ }
+ }
+
+ // All tasks should have unique identifiers, but if not, cancel the task scheduled
+ // earlier.
+ let oldTask = self.addRequest(identifier: proxyRequest.id, task: task)
+ oldTask?.cancel()
+
+ task.resume()
+ }
+ }
+
+ public func cancelRequest(identifier: UUID) {
+ dispatchQueue.async {
+ let task = self.removeRequest(identifier: identifier)
+
+ task?.cancel()
+ }
+ }
+
+ private func addRequest(identifier: UUID, task: URLSessionDataTask) -> URLSessionDataTask? {
+ return proxiedRequests.updateValue(task, forKey: identifier)
+ }
+
+ private func removeRequest(identifier: UUID) -> URLSessionDataTask? {
+ return proxiedRequests.removeValue(forKey: identifier)
+ }
+}