diff options
| -rw-r--r-- | ios/MullvadREST/ApiHandlers/AddressCache.swift | 2 | ||||
| -rw-r--r-- | ios/MullvadRESTTests/MullvadApiTests.swift | 4 | ||||
| -rw-r--r-- | ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift | 31 | ||||
| -rw-r--r-- | ios/MullvadRustRuntime/MullvadApiContext.swift | 15 | ||||
| -rw-r--r-- | ios/MullvadRustRuntime/include/mullvad_rust_runtime.h | 36 | ||||
| -rw-r--r-- | ios/MullvadTypes/AddressCacheProviding.swift | 25 | ||||
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 8 | ||||
| -rw-r--r-- | ios/MullvadVPN/AppDelegate.swift | 3 | ||||
| -rw-r--r-- | ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift | 3 | ||||
| -rw-r--r-- | ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift | 3 | ||||
| -rw-r--r-- | mullvad-ios/src/api_client/access_method_resolver.rs | 13 | ||||
| -rw-r--r-- | mullvad-ios/src/api_client/address_cache_provider.rs | 68 | ||||
| -rw-r--r-- | mullvad-ios/src/api_client/mod.rs | 17 |
13 files changed, 213 insertions, 15 deletions
diff --git a/ios/MullvadREST/ApiHandlers/AddressCache.swift b/ios/MullvadREST/ApiHandlers/AddressCache.swift index d098e91226..b75a515c01 100644 --- a/ios/MullvadREST/ApiHandlers/AddressCache.swift +++ b/ios/MullvadREST/ApiHandlers/AddressCache.swift @@ -11,7 +11,7 @@ import MullvadLogging import MullvadTypes extension REST { - public final class AddressCache: @unchecked Sendable { + public final class AddressCache: AddressCacheProviding, @unchecked Sendable { /// Logger. private let logger = Logger(label: "AddressCache") diff --git a/ios/MullvadRESTTests/MullvadApiTests.swift b/ios/MullvadRESTTests/MullvadApiTests.swift index 506c7240f8..64c0eb371b 100644 --- a/ios/MullvadRESTTests/MullvadApiTests.swift +++ b/ios/MullvadRESTTests/MullvadApiTests.swift @@ -18,6 +18,7 @@ import XCTest class MullvadApiTests: XCTestCase { let encoder = JSONEncoder() + let addressCache = REST.AddressCache(canWriteToCache: false, fileCache: MemoryCache()) func makeApiProxy(port: UInt16) throws -> APIQuerying { let shadowsocksLoader = ShadowsocksLoaderStub(configuration: ShadowsocksConfiguration( @@ -38,7 +39,8 @@ class MullvadApiTests: XCTestCase { accessMethodWrapper: initAccessMethodSettingsWrapper( methods: accessMethodsRepository .fetchAll() - ) + ), + addressCacheProvider: addressCache ) let proxy = REST.MullvadAPIProxy( diff --git a/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift b/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift new file mode 100644 index 0000000000..4c731eaf3a --- /dev/null +++ b/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift @@ -0,0 +1,31 @@ +// +// MullvadAddressCacheProvider.swift +// MullvadRustRuntime +// +// Created by Marco Nikic on 2025-05-15. +// Copyright © 2025 Mullvad VPN AB. All rights reserved. +// + +import Foundation +import MullvadTypes + +public func iniSwiftAddressCacheWrapper(provider: DefaultAddressCacheProvider) -> SwiftAddressCacheWrapper { + let rawProvider = Unmanaged.passUnretained(provider).toOpaque() + return init_swift_address_cache_wrapper(rawProvider) +} + +@_cdecl("swift_get_cached_endpoint") +func getCacheEndpoint(rawAddressCacheProvider: UnsafeMutableRawPointer) -> UnsafePointer<CChar>! { + let addressCacheProvider = Unmanaged<DefaultAddressCacheProvider>.fromOpaque(rawAddressCacheProvider) + .takeUnretainedValue() + let cStr = addressCacheProvider.getCurrentEndpoint().description.toCStringPointer() + /** + `cStr` needs to shortly outlive the return of this function in order to get transformed into a `SocketAddr` + This is the simplest way to guarantee that the pointer returned does not get deallocated immediately + Or that no memory is leaked every time this function gets called + **/ + DispatchQueue(label: "com.MullvadRustRuntime.DecallocateQueue").async { + cStr?.deallocate() + } + return cStr +} diff --git a/ios/MullvadRustRuntime/MullvadApiContext.swift b/ios/MullvadRustRuntime/MullvadApiContext.swift index 5517348cc1..bd89ab891f 100644 --- a/ios/MullvadRustRuntime/MullvadApiContext.swift +++ b/ios/MullvadRustRuntime/MullvadApiContext.swift @@ -16,6 +16,8 @@ public struct MullvadApiContext: @unchecked Sendable { public let context: SwiftApiContext private let shadowsocksBridgeProvider: SwiftShadowsocksBridgeProviding! private let shadowsocksBridgeProviderWrapper: SwiftShadowsocksLoaderWrapper! + private let addressCacheWrapper: SwiftAddressCacheWrapper! + private let addressCacheProvider: AddressCacheProviding! public init( host: String, @@ -23,12 +25,17 @@ public struct MullvadApiContext: @unchecked Sendable { domain: String, disableTls: Bool = false, shadowsocksProvider: SwiftShadowsocksBridgeProviding, - accessMethodWrapper: SwiftAccessMethodSettingsWrapper + accessMethodWrapper: SwiftAccessMethodSettingsWrapper, + addressCacheProvider: AddressCacheProviding ) throws { let bridgeProvider = SwiftShadowsocksBridgeProvider(provider: shadowsocksProvider) self.shadowsocksBridgeProvider = bridgeProvider self.shadowsocksBridgeProviderWrapper = initMullvadShadowsocksBridgeProvider(provider: bridgeProvider) + let defaultAddressCache = DefaultAddressCacheProvider(provider: addressCacheProvider) + self.addressCacheProvider = defaultAddressCache + self.addressCacheWrapper = iniSwiftAddressCacheWrapper(provider: defaultAddressCache) + context = switch disableTls { case true: mullvad_api_init_new_tls_disabled( @@ -36,7 +43,8 @@ public struct MullvadApiContext: @unchecked Sendable { address, domain, shadowsocksBridgeProviderWrapper, - accessMethodWrapper + accessMethodWrapper, + addressCacheWrapper ) case false: mullvad_api_init_new( @@ -44,7 +52,8 @@ public struct MullvadApiContext: @unchecked Sendable { address, domain, shadowsocksBridgeProviderWrapper, - accessMethodWrapper + accessMethodWrapper, + addressCacheWrapper ) } diff --git a/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h b/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h index accd302d53..70c1428098 100644 --- a/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h +++ b/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h @@ -61,6 +61,14 @@ typedef struct SwiftShadowsocksLoaderWrapper { struct SwiftShadowsocksLoaderWrapperContext _0; } SwiftShadowsocksLoaderWrapper; +typedef struct SwiftAddressCacheProviderContext { + const void *address_cache; +} SwiftAddressCacheProviderContext; + +typedef struct SwiftAddressCacheWrapper { + struct SwiftAddressCacheProviderContext _0; +} SwiftAddressCacheWrapper; + typedef struct SwiftCancelHandle { struct RequestCancelHandle *ptr; } SwiftCancelHandle; @@ -161,7 +169,8 @@ struct SwiftApiContext mullvad_api_init_new_tls_disabled(const char *host, const char *address, const char *domain, struct SwiftShadowsocksLoaderWrapper bridge_provider, - struct SwiftAccessMethodSettingsWrapper settings_provider); + struct SwiftAccessMethodSettingsWrapper settings_provider, + struct SwiftAddressCacheWrapper address_cache); /** * # Safety @@ -181,7 +190,8 @@ struct SwiftApiContext mullvad_api_init_new(const char *host, const char *address, const char *domain, struct SwiftShadowsocksLoaderWrapper bridge_provider, - struct SwiftAccessMethodSettingsWrapper settings_provider); + struct SwiftAccessMethodSettingsWrapper settings_provider, + struct SwiftAddressCacheWrapper address_cache); /** * # Safety @@ -202,7 +212,8 @@ struct SwiftApiContext mullvad_api_init_inner(const char *host, const char *domain, bool disable_tls, struct SwiftShadowsocksLoaderWrapper bridge_provider, - struct SwiftAccessMethodSettingsWrapper settings_provider); + struct SwiftAccessMethodSettingsWrapper settings_provider, + struct SwiftAddressCacheWrapper address_cache); /** * Converts parameters into a `Box<AccessMethodSetting>` raw representation that @@ -299,6 +310,25 @@ struct SwiftCancelHandle mullvad_ios_delete_account(struct SwiftApiContext api_c const char *account_number); /** + * Return the latest available endpoint, or a default one if none are cached + * + * # SAFETY + * `rawAddressCacheProvider` **must** be provided by a call to `init_swift_address_cache_wrapper` + * It is okay to persist it, and use it accross multiple threads. + */ +extern const char *swift_get_cached_endpoint(const void *rawAddressCacheProvider); + +/** + * Called by the Swift side in order to provide an object to rust that provides API addresses in a UTF-8 string form + * + * # SAFETY + * `address_cache` **must be** pointing to a valid instance of a `DefaultAddressCacheProvider` + * That instance's lifetime has to be equivalent to a `'static` lifetime in Rust + * This function does not take ownership of `address_cache` + */ +struct SwiftAddressCacheWrapper init_swift_address_cache_wrapper(const void *address_cache); + +/** * # Safety * * `api_context` must be pointing to a valid instance of `SwiftApiContext`. A `SwiftApiContext` is created diff --git a/ios/MullvadTypes/AddressCacheProviding.swift b/ios/MullvadTypes/AddressCacheProviding.swift new file mode 100644 index 0000000000..059409bbd5 --- /dev/null +++ b/ios/MullvadTypes/AddressCacheProviding.swift @@ -0,0 +1,25 @@ +// +// AddressCacheProviding.swift +// MullvadTypes +// +// Created by Marco Nikic on 2025-05-15. +// Copyright © 2025 Mullvad VPN AB. All rights reserved. +// + +import Foundation + +public protocol AddressCacheProviding: Sendable { + func getCurrentEndpoint() -> AnyIPEndpoint +} + +public final class DefaultAddressCacheProvider: AddressCacheProviding, Sendable { + let provider: AddressCacheProviding + + public init(provider: AddressCacheProviding) { + self.provider = provider + } + + public func getCurrentEndpoint() -> AnyIPEndpoint { + provider.getCurrentEndpoint() + } +} diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index fb003e53b1..de1e60d6b1 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -788,6 +788,8 @@ A970C89D2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = A970C89C2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift */; }; A9711B2B2D662AE3003DA71D /* SwiftConnectionModeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9711B2A2D662AE3003DA71D /* SwiftConnectionModeProvider.swift */; }; A97275562CE36CAE00029F15 /* DaitaV2Parameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97275552CE36CAE00029F15 /* DaitaV2Parameters.swift */; }; + A97687C82DD60D5D000D96E8 /* AddressCacheProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97687C72DD60D5D000D96E8 /* AddressCacheProviding.swift */; }; + A97687CA2DD60F36000D96E8 /* MullvadAddressCacheProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97687C92DD60F36000D96E8 /* MullvadAddressCacheProvider.swift */; }; A97D25AE2B0BB18100946B2D /* ProtocolObfuscator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25AD2B0BB18100946B2D /* ProtocolObfuscator.swift */; }; A97D25B02B0BB5C400946B2D /* ProtocolObfuscationStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25AF2B0BB5C400946B2D /* ProtocolObfuscationStub.swift */; }; A97D25B22B0CB02D00946B2D /* ProtocolObfuscatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97D25B12B0CB02D00946B2D /* ProtocolObfuscatorTests.swift */; }; @@ -2343,6 +2345,8 @@ A970C89C2B29E38C000A7684 /* Socks5UsernamePasswordCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Socks5UsernamePasswordCommand.swift; sourceTree = "<group>"; }; A9711B2A2D662AE3003DA71D /* SwiftConnectionModeProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftConnectionModeProvider.swift; sourceTree = "<group>"; }; A97275552CE36CAE00029F15 /* DaitaV2Parameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DaitaV2Parameters.swift; sourceTree = "<group>"; }; + A97687C72DD60D5D000D96E8 /* AddressCacheProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCacheProviding.swift; sourceTree = "<group>"; }; + A97687C92DD60F36000D96E8 /* MullvadAddressCacheProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MullvadAddressCacheProvider.swift; sourceTree = "<group>"; }; A97D25AD2B0BB18100946B2D /* ProtocolObfuscator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolObfuscator.swift; sourceTree = "<group>"; }; A97D25AF2B0BB5C400946B2D /* ProtocolObfuscationStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolObfuscationStub.swift; sourceTree = "<group>"; }; A97D25B12B0CB02D00946B2D /* ProtocolObfuscatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolObfuscatorTests.swift; sourceTree = "<group>"; }; @@ -3063,6 +3067,7 @@ 58E511E028DDB7F100B0BCDE /* WrappingError.swift */, A9711B2A2D662AE3003DA71D /* SwiftConnectionModeProvider.swift */, A98207EE2D9192A300654558 /* ShadowsocksBridgeProviding.swift */, + A97687C72DD60D5D000D96E8 /* AddressCacheProviding.swift */, ); path = MullvadTypes; sourceTree = "<group>"; @@ -4587,6 +4592,7 @@ A96D0B442D675F0400DD6C59 /* MullvadConnectionModeProvider.swift */, A98207F02D91A0AC00654558 /* MullvadShadowsocksBridgeProvider.swift */, A98207F22D9ACE4C00654558 /* MullvadAccessMethodReceiver.swift */, + A97687C92DD60F36000D96E8 /* MullvadAddressCacheProvider.swift */, ); path = MullvadRustRuntime; sourceTree = "<group>"; @@ -6755,6 +6761,7 @@ 7A7AD14F2BF21EF200B30B3C /* NameInputFormatter.swift in Sources */, 58D22413294C90210029F5F8 /* RelayConstraints.swift in Sources */, 7AB401852DA53D5300522E17 /* NewAccountData.swift in Sources */, + A97687C82DD60D5D000D96E8 /* AddressCacheProviding.swift in Sources */, A97275562CE36CAE00029F15 /* DaitaV2Parameters.swift in Sources */, 7AF9BE8C2A321D1F00DBFEDB /* RelayFilter.swift in Sources */, 58D22414294C90210029F5F8 /* RelayLocation.swift in Sources */, @@ -6904,6 +6911,7 @@ 7AB931242D43C2CA005FCEBA /* MullvadApiContext.swift in Sources */, A9D9A4BB2C36D397004088DD /* EphemeralPeerNegotiator.swift in Sources */, F0A89CB72D9D923300580C27 /* String+UnsafePointer.swift in Sources */, + A97687CA2DD60F36000D96E8 /* MullvadAddressCacheProvider.swift in Sources */, A9D9A4B22C36D12D004088DD /* TunnelObfuscator.swift in Sources */, A98207F12D91A0AC00654558 /* MullvadShadowsocksBridgeProvider.swift in Sources */, 7AB931262D43D22F005FCEBA /* MullvadApiResponse.swift in Sources */, diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift index 4664fa3b57..2590e2f1e7 100644 --- a/ios/MullvadVPN/AppDelegate.swift +++ b/ios/MullvadVPN/AppDelegate.swift @@ -109,7 +109,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD address: REST.defaultAPIEndpoint.description, domain: REST.encryptedDNSHostname, shadowsocksProvider: shadowsocksLoader, - accessMethodWrapper: transportStrategy.opaqueAccessMethodSettingsWrapper + accessMethodWrapper: transportStrategy.opaqueAccessMethodSettingsWrapper, + addressCacheProvider: addressCache ) accessMethodReceiver = MullvadAccessMethodReceiver( diff --git a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift index 2169d0100d..cc496bba63 100644 --- a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift +++ b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift @@ -75,7 +75,8 @@ class TunnelManagerTests: XCTestCase { address: REST.defaultAPIEndpoint.description, domain: REST.encryptedDNSHostname, shadowsocksProvider: shadowsocksLoader, - accessMethodWrapper: transportStrategy.opaqueAccessMethodSettingsWrapper + accessMethodWrapper: transportStrategy.opaqueAccessMethodSettingsWrapper, + addressCacheProvider: addressCache ) try SettingsManager.writeSettings(LatestTunnelSettings()) diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift index 3f2df2cbdb..8be5f883b9 100644 --- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift +++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift @@ -266,7 +266,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { address: REST.defaultAPIEndpoint.description, domain: REST.encryptedDNSHostname, shadowsocksProvider: shadowsocksLoader, - accessMethodWrapper: transportStrategy.opaqueAccessMethodSettingsWrapper + accessMethodWrapper: transportStrategy.opaqueAccessMethodSettingsWrapper, + addressCacheProvider: addressCache ) accessMethodReceiver = MullvadAccessMethodReceiver( diff --git a/mullvad-ios/src/api_client/access_method_resolver.rs b/mullvad-ios/src/api_client/access_method_resolver.rs index 5ce22cc5cc..df8910fcbb 100644 --- a/mullvad-ios/src/api_client/access_method_resolver.rs +++ b/mullvad-ios/src/api_client/access_method_resolver.rs @@ -10,7 +10,10 @@ use talpid_types::net::{ }; use tonic::async_trait; -use super::shadowsocks_loader::SwiftShadowsocksLoaderWrapper; +use super::{ + address_cache_provider::SwiftAddressCacheWrapper, + shadowsocks_loader::SwiftShadowsocksLoaderWrapper, +}; #[derive(Debug)] pub struct SwiftAccessMethodResolver { @@ -18,6 +21,7 @@ pub struct SwiftAccessMethodResolver { domain: String, state: EncryptedDnsProxyState, bridge_provider: SwiftShadowsocksLoaderWrapper, + address_cache: SwiftAddressCacheWrapper, } impl SwiftAccessMethodResolver { @@ -26,12 +30,14 @@ impl SwiftAccessMethodResolver { domain: String, state: EncryptedDnsProxyState, bridge_provider: SwiftShadowsocksLoaderWrapper, + address_cache: SwiftAddressCacheWrapper, ) -> Self { Self { endpoint, domain, state, bridge_provider, + address_cache, } } } @@ -79,8 +85,9 @@ impl AccessMethodResolver for SwiftAccessMethodResolver { } async fn default_connection_mode(&self) -> AllowedEndpoint { - // TODO: Call the iOS Address cache implementation instead of returning the default endpoint - let endpoint = ApiConnectionMode::Direct.get_endpoint().unwrap(); + let endpoint = + Endpoint::from_socket_address(self.address_cache.get_addrs(), TransportProtocol::Tcp); + AllowedEndpoint { endpoint, clients: AllowedClients::All, diff --git a/mullvad-ios/src/api_client/address_cache_provider.rs b/mullvad-ios/src/api_client/address_cache_provider.rs new file mode 100644 index 0000000000..ff9f4a13e8 --- /dev/null +++ b/mullvad-ios/src/api_client/address_cache_provider.rs @@ -0,0 +1,68 @@ +use super::helpers::convert_c_string; +use libc::c_char; +use std::{ffi::c_void, net::SocketAddr}; + +extern "C" { + /// Return the latest available endpoint, or a default one if none are cached + /// + /// # SAFETY + /// `rawAddressCacheProvider` **must** be provided by a call to `init_swift_address_cache_wrapper` + /// It is okay to persist it, and use it accross multiple threads. + pub fn swift_get_cached_endpoint(rawAddressCacheProvider: *const c_void) -> *const c_char; +} + +#[derive(Debug)] +#[repr(C)] +pub struct SwiftAddressCacheWrapper(SwiftAddressCacheProviderContext); + +impl SwiftAddressCacheWrapper { + pub fn new(context: SwiftAddressCacheProviderContext) -> SwiftAddressCacheWrapper { + SwiftAddressCacheWrapper(context) + } + + pub fn get_addrs(&self) -> SocketAddr { + self.context_ref().get_addrs() + } + + fn context_ref(&self) -> &SwiftAddressCacheProviderContext { + &self.0 + } +} + +// SAFETY: The `address_cache` inside the `SwiftAddressCacheProviderContext`'s context is guaranteed to be thread safe +unsafe impl Sync for SwiftAddressCacheProviderContext {} +// SAFETY: The `address_cache` inside the `SwiftAddressCacheProviderContext`'s context is guaranteed to be Sendable +unsafe impl Send for SwiftAddressCacheProviderContext {} + +#[derive(Debug)] +#[repr(C)] +pub struct SwiftAddressCacheProviderContext { + address_cache: *const c_void, +} + +impl SwiftAddressCacheProviderContext { + pub fn get_addrs(&self) -> SocketAddr { + // SAFETY: See notice for `swift_get_cached_endpoint` + let raw_address = unsafe { swift_get_cached_endpoint(self.address_cache) }; + + // SAFETY: The pointer returned by `swift_get_cached_endpoint` is guaranteed to point to a valid UTF-8 String + // It is also guaranteed to be a valid representation of either an IPv4 or IPv6 address + unsafe { convert_c_string(raw_address) } + .parse() + .expect("Invalid socket address in cache") + } +} + +/// Called by the Swift side in order to provide an object to rust that provides API addresses in a UTF-8 string form +/// +/// # SAFETY +/// `address_cache` **must be** pointing to a valid instance of a `DefaultAddressCacheProvider` +/// That instance's lifetime has to be equivalent to a `'static` lifetime in Rust +/// This function does not take ownership of `address_cache` +#[unsafe(no_mangle)] +pub unsafe extern "C" fn init_swift_address_cache_wrapper( + address_cache: *const c_void, +) -> SwiftAddressCacheWrapper { + let context = SwiftAddressCacheProviderContext { address_cache }; + SwiftAddressCacheWrapper::new(context) +} diff --git a/mullvad-ios/src/api_client/mod.rs b/mullvad-ios/src/api_client/mod.rs index c65fe524a0..4e875fe4c6 100644 --- a/mullvad-ios/src/api_client/mod.rs +++ b/mullvad-ios/src/api_client/mod.rs @@ -2,6 +2,7 @@ use std::{ffi::c_char, ffi::CStr, future::Future, sync::Arc}; use access_method_resolver::SwiftAccessMethodResolver; use access_method_settings::SwiftAccessMethodSettingsWrapper; +use address_cache_provider::SwiftAddressCacheWrapper; use helpers::convert_c_string; use mullvad_api::{ access_mode::{AccessModeSelector, AccessModeSelectorHandle}, @@ -18,6 +19,7 @@ use talpid_future::retry::retry_future; mod access_method_resolver; mod access_method_settings; mod account; +mod address_cache_provider; mod api; mod cancellation; mod completion; @@ -135,6 +137,7 @@ pub extern "C" fn mullvad_api_init_new_tls_disabled( domain: *const c_char, bridge_provider: SwiftShadowsocksLoaderWrapper, settings_provider: SwiftAccessMethodSettingsWrapper, + address_cache: SwiftAddressCacheWrapper, ) -> SwiftApiContext { mullvad_api_init_inner( host, @@ -143,6 +146,7 @@ pub extern "C" fn mullvad_api_init_new_tls_disabled( true, bridge_provider, settings_provider, + address_cache, ) } @@ -165,6 +169,7 @@ pub extern "C" fn mullvad_api_init_new( domain: *const c_char, bridge_provider: SwiftShadowsocksLoaderWrapper, settings_provider: SwiftAccessMethodSettingsWrapper, + address_cache: SwiftAddressCacheWrapper, ) -> SwiftApiContext { #[cfg(feature = "api-override")] return mullvad_api_init_inner( @@ -174,9 +179,17 @@ pub extern "C" fn mullvad_api_init_new( false, bridge_provider, settings_provider, + address_cache, ); #[cfg(not(feature = "api-override"))] - mullvad_api_init_inner(host, address, domain, bridge_provider, settings_provider) + mullvad_api_init_inner( + host, + address, + domain, + bridge_provider, + settings_provider, + address_cache, + ) } /// # Safety @@ -199,6 +212,7 @@ pub extern "C" fn mullvad_api_init_inner( #[cfg(feature = "api-override")] disable_tls: bool, bridge_provider: SwiftShadowsocksLoaderWrapper, settings_provider: SwiftAccessMethodSettingsWrapper, + address_cache: SwiftAddressCacheWrapper, ) -> SwiftApiContext { // Safety: See notes for `convert_c_string` let (host, address, domain) = unsafe { @@ -233,6 +247,7 @@ pub extern "C" fn mullvad_api_init_inner( domain, encrypted_dns_proxy_state, bridge_provider, + address_cache, ); let api_context = tokio_handle.clone().block_on(async move { |
