Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mullvad-api for iOS #7238

Merged
merged 3 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/ios-rust-ffi.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: iOS - Build and test Rust FFI (mullvad-ios)
name: iOS - Build and test Rust FFI (mullvad-ios and mullvad-api)
on:
pull_request:
paths:
Expand Down Expand Up @@ -40,8 +40,8 @@ jobs:
# handy.
run: |
source env.sh
time cargo build --locked --verbose --lib -p mullvad-ios --target ${{ matrix.target }}
time cargo test --locked --verbose --lib -p mullvad-ios
time cargo build --locked --verbose --lib -p mullvad-ios -p mullvad-api --target ${{ matrix.target }}
time cargo test --locked --verbose --lib -p mullvad-ios -p mullvad-api

clippy-check-ios:
runs-on: macos-latest
Expand Down Expand Up @@ -70,5 +70,7 @@ jobs:
RUSTFLAGS: --deny warnings
run: |
source env.sh
time cargo clippy --locked --all-targets --no-default-features -p mullvad-ios --target ${{ matrix.target }}
time cargo clippy --locked --all-targets --all-features -p mullvad-ios --target ${{ matrix.target }}
time cargo clippy --locked --all-targets --no-default-features -p mullvad-ios -p mullvad-api \
--target ${{ matrix.target }}
time cargo clippy --locked --all-targets --all-features -p mullvad-ios -p mullvad-api \
--target ${{ matrix.target }}
53 changes: 31 additions & 22 deletions mullvad-api/include/mullvad-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@ typedef struct MullvadApiDevice {
/**
* Initializes a Mullvad API client.
*
* #Arguments
* # Safety
*
* * `client_ptr`: Must be a pointer to that is valid for the length of a `MullvadApiClient`
* struct.
* struct.
*
* * `api_address`: pointer to nul-terminated UTF-8 string containing a socket address
* representation
* ("143.32.4.32:9090"), the port is mandatory.
* ("143.32.4.32:9090"), the port is mandatory.
*
* * `hostname`: pointer to a null-terminated UTF-8 string representing the hostname that will be
* used for TLS validation.
* used for TLS validation.
*/
struct MullvadApiError mullvad_api_client_initialize(struct MullvadApiClient *client_ptr,
const char *api_address_ptr,
Expand All @@ -61,26 +62,27 @@ struct MullvadApiError mullvad_api_client_initialize(struct MullvadApiClient *cl
/**
* Removes all devices from a given account
*
* #Arguments
* # Safety
*
* * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
*
* * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
* account that will have all of it's devices removed.
* account that will have all of it's devices removed.
*/
struct MullvadApiError mullvad_api_remove_all_devices(struct MullvadApiClient client_ptr,
const char *account_ptr);

/**
* Removes all devices from a given account
*
* #Arguments
* # Safety
* * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
*
* * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
* account that will have all of it's devices removed.
* account that will have all of it's devices removed.
*
* * `expiry_unix_timestamp`: a pointer to a signed 64 bit integer. If this function returns no
* error, the expiry timestamp will be written to this pointer.
* error, the expiry timestamp will be written to this pointer.
*/
struct MullvadApiError mullvad_api_get_expiry(struct MullvadApiClient client_ptr,
const char *account_str_ptr,
Expand All @@ -89,15 +91,16 @@ struct MullvadApiError mullvad_api_get_expiry(struct MullvadApiClient client_ptr
/**
* Gets a list of all devices associated with the specified account from the API.
*
* #Arguments
* # Safety
*
* * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
*
* * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
* account that will have all of it's devices removed.
* account that will have all of it's devices removed.
*
* * `device_iter_ptr`: a pointer to a `device::MullvadApiDeviceIterator`. If this function
* doesn't return an error, the pointer will be initialized with a valid instance of
* `device::MullvadApiDeviceIterator`, which can be used to iterate through the devices.
* doesn't return an error, the pointer will be initialized with a valid instance of
* `device::MullvadApiDeviceIterator`, which can be used to iterate through the devices.
*/
struct MullvadApiError mullvad_api_list_devices(struct MullvadApiClient client_ptr,
const char *account_str_ptr,
Expand All @@ -107,16 +110,17 @@ struct MullvadApiError mullvad_api_list_devices(struct MullvadApiClient client_p
* Adds a device to the specified account with the specified public key. Note that the device
* name, associated addresess and UUID are not returned.
*
* #Arguments
* # Safety
*
* * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
*
* * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
* account that will have a device added to ita device added to it.
* account that will have a device added to ita device added to it.
*
* * `public_key_ptr`: a pointer to 32 bytes of a WireGuard public key that will be uploaded.
*
* * `new_device_ptr`: a pointer to enough memory to allocate a `MullvadApiDevice`. If this
* function doesn't return an error, it will be initialized.
* function doesn't return an error, it will be initialized.
*/
struct MullvadApiError mullvad_api_add_device(struct MullvadApiClient client_ptr,
const char *account_str_ptr,
Expand All @@ -126,24 +130,25 @@ struct MullvadApiError mullvad_api_add_device(struct MullvadApiClient client_ptr
/**
* Creates a new account.
*
* #Arguments
* # Safety
*
* * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
*
* * `account_str_ptr`: If a new account is created successfully, a pointer to an allocated C
* string containing the new
* account number will be written to this pointer. It must be freed via
* `mullvad_api_cstring_drop`.
* string containing the new account number will be written to this pointer. It must be freed via
* `mullvad_api_cstring_drop`.
*/
struct MullvadApiError mullvad_api_create_account(struct MullvadApiClient client_ptr,
const char **account_str_ptr);

/**
* Deletes the specified account.
*
* #Arguments
* # Safety
*
* * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
*
* * `account_str_ptr`: A null-terminated string representing the account to be deleted.
* * `account_str_ptr`: Must be a null-terminated string representing the account to be deleted.
*/
struct MullvadApiError mullvad_api_delete_account(struct MullvadApiClient client_ptr,
const char *account_str_ptr);
Expand All @@ -152,6 +157,10 @@ void mullvad_api_client_drop(struct MullvadApiClient client);

/**
* Deallocates a CString returned by the Mullvad API client.
*
* # Safety
*
* `cstr_ptr` must be a pointer to a string allocated by another `mullvad_api` function.
*/
void mullvad_api_cstring_drop(char *cstr_ptr);

Expand Down
2 changes: 1 addition & 1 deletion mullvad-api/src/ffi/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub extern "C" fn mullvad_api_device_iter_next(
// SAFETY: Assuming device pointer is valid
unsafe { ptr::write(device_ptr, device.into()) }

return true;
true
}

#[no_mangle]
Expand Down
73 changes: 42 additions & 31 deletions mullvad-api/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,19 @@ impl FfiClient {

/// Initializes a Mullvad API client.
///
/// #Arguments
/// # Safety
///
/// * `client_ptr`: Must be a pointer to that is valid for the length of a `MullvadApiClient`
/// struct.
/// struct.
///
/// * `api_address`: pointer to nul-terminated UTF-8 string containing a socket address
/// representation
/// ("143.32.4.32:9090"), the port is mandatory.
/// ("143.32.4.32:9090"), the port is mandatory.
///
/// * `hostname`: pointer to a null-terminated UTF-8 string representing the hostname that will be
/// used for TLS validation.
/// used for TLS validation.
#[no_mangle]
pub extern "C" fn mullvad_api_client_initialize(
pub unsafe extern "C" fn mullvad_api_client_initialize(
client_ptr: *mut MullvadApiClient,
api_address_ptr: *const libc::c_char,
hostname: *const libc::c_char,
Expand All @@ -252,13 +253,14 @@ pub extern "C" fn mullvad_api_client_initialize(

/// Removes all devices from a given account
///
/// #Arguments
/// # Safety
///
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
/// account that will have all of it's devices removed.
/// account that will have all of it's devices removed.
#[no_mangle]
pub extern "C" fn mullvad_api_remove_all_devices(
pub unsafe extern "C" fn mullvad_api_remove_all_devices(
client_ptr: MullvadApiClient,
account_ptr: *const libc::c_char,
) -> MullvadApiError {
Expand All @@ -271,16 +273,16 @@ pub extern "C" fn mullvad_api_remove_all_devices(

/// Removes all devices from a given account
///
/// #Arguments
/// # Safety
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
/// account that will have all of it's devices removed.
/// account that will have all of it's devices removed.
///
/// * `expiry_unix_timestamp`: a pointer to a signed 64 bit integer. If this function returns no
/// error, the expiry timestamp will be written to this pointer.
/// error, the expiry timestamp will be written to this pointer.
#[no_mangle]
pub extern "C" fn mullvad_api_get_expiry(
pub unsafe extern "C" fn mullvad_api_get_expiry(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
expiry_unix_timestamp: *mut i64,
Expand All @@ -297,17 +299,18 @@ pub extern "C" fn mullvad_api_get_expiry(

/// Gets a list of all devices associated with the specified account from the API.
///
/// #Arguments
/// # Safety
///
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
/// account that will have all of it's devices removed.
/// account that will have all of it's devices removed.
///
/// * `device_iter_ptr`: a pointer to a `device::MullvadApiDeviceIterator`. If this function
/// doesn't return an error, the pointer will be initialized with a valid instance of
/// `device::MullvadApiDeviceIterator`, which can be used to iterate through the devices.
/// doesn't return an error, the pointer will be initialized with a valid instance of
/// `device::MullvadApiDeviceIterator`, which can be used to iterate through the devices.
#[no_mangle]
pub extern "C" fn mullvad_api_list_devices(
pub unsafe extern "C" fn mullvad_api_list_devices(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
device_iter_ptr: *mut device::MullvadApiDeviceIterator,
Expand All @@ -325,18 +328,19 @@ pub extern "C" fn mullvad_api_list_devices(
/// Adds a device to the specified account with the specified public key. Note that the device
/// name, associated addresess and UUID are not returned.
///
/// #Arguments
/// # Safety
///
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: pointer to nul-terminated UTF-8 string containing the account number of the
/// account that will have a device added to ita device added to it.
/// account that will have a device added to ita device added to it.
///
/// * `public_key_ptr`: a pointer to 32 bytes of a WireGuard public key that will be uploaded.
///
/// * `new_device_ptr`: a pointer to enough memory to allocate a `MullvadApiDevice`. If this
/// function doesn't return an error, it will be initialized.
/// function doesn't return an error, it will be initialized.
#[no_mangle]
pub extern "C" fn mullvad_api_add_device(
pub unsafe extern "C" fn mullvad_api_add_device(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
public_key_ptr: *const u8,
Expand All @@ -358,15 +362,15 @@ pub extern "C" fn mullvad_api_add_device(

/// Creates a new account.
///
/// #Arguments
/// # Safety
///
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: If a new account is created successfully, a pointer to an allocated C
/// string containing the new
/// account number will be written to this pointer. It must be freed via
/// `mullvad_api_cstring_drop`.
/// string containing the new account number will be written to this pointer. It must be freed via
/// `mullvad_api_cstring_drop`.
#[no_mangle]
pub extern "C" fn mullvad_api_create_account(
pub unsafe extern "C" fn mullvad_api_create_account(
client_ptr: MullvadApiClient,
account_str_ptr: *mut *const libc::c_char,
) -> MullvadApiError {
Expand All @@ -389,12 +393,13 @@ pub extern "C" fn mullvad_api_create_account(

/// Deletes the specified account.
///
/// #Arguments
/// # Safety
///
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: A null-terminated string representing the account to be deleted.
/// * `account_str_ptr`: Must be a null-terminated string representing the account to be deleted.
#[no_mangle]
pub extern "C" fn mullvad_api_delete_account(
pub unsafe extern "C" fn mullvad_api_delete_account(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
) -> MullvadApiError {
Expand All @@ -411,14 +416,20 @@ pub extern "C" fn mullvad_api_client_drop(client: MullvadApiClient) {
}

/// Deallocates a CString returned by the Mullvad API client.
///
/// # Safety
///
/// `cstr_ptr` must be a pointer to a string allocated by another `mullvad_api` function.
#[no_mangle]
pub extern "C" fn mullvad_api_cstring_drop(cstr_ptr: *mut libc::c_char) {
pub unsafe extern "C" fn mullvad_api_cstring_drop(cstr_ptr: *mut libc::c_char) {
let _ = unsafe { CString::from_raw(cstr_ptr) };
}

/// The return value is only valid for the lifetime of the `ptr` that's passed in
///
/// SAFETY: `ptr` must be valid for `size` bytes
/// # Safety
///
/// `ptr` must be valid for `size` bytes
unsafe fn string_from_raw_ptr(ptr: *const libc::c_char) -> Result<String, MullvadApiError> {
let cstr = unsafe { CStr::from_ptr(ptr) };

Expand Down
1 change: 1 addition & 0 deletions mullvad-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ impl Runtime {
Runtime {
handle,
address_cache: AddressCache::with_static_addr(address),
dns_resolver: Arc::new(NullDnsResolver),
api_availability: ApiAvailability::default(),
}
}
Expand Down
Loading