summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift16
-rw-r--r--ios/MullvadRustRuntime/include/mullvad_rust_runtime.h11
-rw-r--r--mullvad-ios/src/api_client/address_cache_provider.rs26
3 files changed, 37 insertions, 16 deletions
diff --git a/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift b/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift
index 4c731eaf3a..5de81c733e 100644
--- a/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift
+++ b/ios/MullvadRustRuntime/MullvadAddressCacheProvider.swift
@@ -15,17 +15,13 @@ public func iniSwiftAddressCacheWrapper(provider: DefaultAddressCacheProvider) -
}
@_cdecl("swift_get_cached_endpoint")
-func getCacheEndpoint(rawAddressCacheProvider: UnsafeMutableRawPointer) -> UnsafePointer<CChar>! {
+func getCacheEndpoint(rawAddressCacheProvider: UnsafeMutableRawPointer) -> LateStringDeallocator {
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
+ return LateStringDeallocator(ptr: cStr, deallocate_ptr: deallocate_pointer(pointer:))
+}
+
+func deallocate_pointer(pointer: UnsafePointer<CChar>?) {
+ pointer?.deallocate()
}
diff --git a/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h b/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
index 70c1428098..08bb177116 100644
--- a/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
+++ b/ios/MullvadRustRuntime/include/mullvad_rust_runtime.h
@@ -77,6 +77,15 @@ typedef struct SwiftRetryStrategy {
struct RetryStrategy *_0;
} SwiftRetryStrategy;
+/**
+ * A struct used to deallocate a pointer to a C String later than when the pointer's control is relinquished from Swift.
+ * Use the `deallocate_ptr` function on `ptr` to call the custom deallocator provided by Swift.
+ */
+typedef struct LateStringDeallocator {
+ const char *ptr;
+ void (*deallocate_ptr)(const char*);
+} LateStringDeallocator;
+
typedef struct SwiftMullvadApiResponse {
uint8_t *body;
uintptr_t body_size;
@@ -316,7 +325,7 @@ struct SwiftCancelHandle mullvad_ios_delete_account(struct SwiftApiContext api_c
* `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);
+extern struct LateStringDeallocator 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
diff --git a/mullvad-ios/src/api_client/address_cache_provider.rs b/mullvad-ios/src/api_client/address_cache_provider.rs
index ff9f4a13e8..f813683445 100644
--- a/mullvad-ios/src/api_client/address_cache_provider.rs
+++ b/mullvad-ios/src/api_client/address_cache_provider.rs
@@ -8,7 +8,9 @@ extern "C" {
/// # 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;
+ pub fn swift_get_cached_endpoint(
+ rawAddressCacheProvider: *const c_void,
+ ) -> LateStringDeallocator;
}
#[derive(Debug)]
@@ -40,16 +42,30 @@ pub struct SwiftAddressCacheProviderContext {
address_cache: *const c_void,
}
+/// A struct used to deallocate a pointer to a C String later than when the pointer's control is relinquished from Swift.
+/// Use the `deallocate_ptr` function on `ptr` to call the custom deallocator provided by Swift.
+#[repr(C)]
+pub struct LateStringDeallocator {
+ ptr: *const c_char,
+ deallocate_ptr: unsafe extern "C" fn(*const c_char),
+}
+
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) };
+ let deallocator = 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
+ // SAFETY: The pointer contained in the late deallocator 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) }
+ let cached_address = unsafe { convert_c_string(deallocator.ptr) }
.parse()
- .expect("Invalid socket address in cache")
+ .expect("Invalid socket address in cache");
+
+ // SAFETY: The pointer in `deallocator.ptr` must not be used after `deallocate_ptr` has been called.
+ // `deallocate_ptr` must be called only once
+ unsafe { (deallocator.deallocate_ptr)(deallocator.ptr) };
+ cached_address
}
}