summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSebastian Holmin <sebastian.holmin@mullvad.net>2025-02-12 10:20:17 +0100
committerSebastian Holmin <sebastian.holmin@mullvad.net>2025-02-12 10:20:17 +0100
commit218f495aa363771307cc8c752225c8f29b88abcf (patch)
treeb0d3d1bcfd250894bc748602ebf58eb4df8e1bde
parent92d61b5118be6fb5510f99393b38f40b25cc8abf (diff)
parent99b9393962c75291d7610757b39db4cc00a68e1d (diff)
downloadmullvadvpn-218f495aa363771307cc8c752225c8f29b88abcf.tar.xz
mullvadvpn-218f495aa363771307cc8c752225c8f29b88abcf.zip
Merge branch '2024-edition-beta'
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml91
-rw-r--r--mullvad-api/Cargo.toml24
-rw-r--r--mullvad-api/src/availability.rs20
-rw-r--r--mullvad-api/src/device.rs13
-rw-r--r--mullvad-api/src/ffi/device.rs6
-rw-r--r--mullvad-api/src/ffi/error.rs2
-rw-r--r--mullvad-api/src/ffi/mod.rs18
-rw-r--r--mullvad-api/src/lib.rs14
-rw-r--r--mullvad-api/src/relay_list.rs2
-rw-r--r--mullvad-cli/src/cmds/relay.rs45
-rw-r--r--mullvad-cli/src/format.rs6
-rw-r--r--mullvad-daemon/src/api.rs4
-rw-r--r--mullvad-daemon/src/device/api.rs25
-rw-r--r--mullvad-daemon/src/device/mod.rs41
-rw-r--r--mullvad-daemon/src/device/service.rs8
-rw-r--r--mullvad-daemon/src/exception_logging/win.rs9
-rw-r--r--mullvad-daemon/src/lib.rs78
-rw-r--r--mullvad-daemon/src/management_interface.rs10
-rw-r--r--mullvad-daemon/src/migrations/account_history.rs17
-rw-r--r--mullvad-daemon/src/relay_list/mod.rs2
-rw-r--r--mullvad-daemon/src/settings/mod.rs7
-rw-r--r--mullvad-daemon/src/settings/patch.rs8
-rw-r--r--mullvad-daemon/src/version_check.rs7
-rw-r--r--mullvad-ios/Cargo.toml2
-rw-r--r--mullvad-ios/src/encrypted_dns_proxy.rs8
-rw-r--r--mullvad-ios/src/ephemeral_peer_proxy/mod.rs6
-rw-r--r--mullvad-ios/src/lib.rs2
-rw-r--r--mullvad-ios/src/shadowsocks_proxy/ffi.rs4
-rw-r--r--mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs4
-rw-r--r--mullvad-jni/src/lib.rs4
-rw-r--r--mullvad-jni/src/problem_report.rs4
-rw-r--r--mullvad-management-interface/src/client.rs4
-rw-r--r--mullvad-nsis/src/lib.rs6
-rw-r--r--talpid-core/src/connectivity_listener.rs2
-rw-r--r--talpid-core/src/dns/windows/dnsapi.rs2
-rw-r--r--talpid-core/src/firewall/windows/mod.rs2
-rw-r--r--talpid-core/src/split_tunnel/windows/driver.rs86
-rw-r--r--talpid-core/src/split_tunnel/windows/volume_monitor.rs2
-rw-r--r--talpid-core/src/split_tunnel/windows/windows.rs19
-rw-r--r--talpid-core/src/tunnel/mod.rs2
-rw-r--r--talpid-core/src/window.rs8
-rw-r--r--talpid-openvpn/src/lib.rs2
-rw-r--r--talpid-openvpn/src/wintun.rs10
-rw-r--r--talpid-routing/src/unix/android.rs2
-rw-r--r--talpid-routing/src/unix/mod.rs4
-rw-r--r--talpid-routing/src/windows/default_route_monitor.rs15
-rw-r--r--talpid-routing/src/windows/route_manager.rs30
-rw-r--r--talpid-windows/src/net.rs12
-rw-r--r--talpid-wireguard/src/wireguard_go/mod.rs2
-rw-r--r--talpid-wireguard/src/wireguard_kernel/wg_message.rs2
-rw-r--r--talpid-wireguard/src/wireguard_nt/mod.rs39
-rw-r--r--test/Cargo.lock57
-rw-r--r--test/Cargo.toml18
-rw-r--r--test/test-manager/src/tests/helpers.rs2
-rw-r--r--test/test-manager/src/tests/mod.rs4
-rw-r--r--wireguard-go-rs/Cargo.toml9
-rw-r--r--wireguard-go-rs/src/lib.rs2
58 files changed, 493 insertions, 351 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a237ae236a..93a21312ff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "addr2line"
@@ -485,9 +485,9 @@ dependencies = [
[[package]]
name = "cbindgen"
-version = "0.27.0"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb"
+checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff"
dependencies = [
"heck 0.4.1",
"indexmap 2.2.6",
@@ -2478,7 +2478,7 @@ name = "mullvad-api"
version = "0.0.0"
dependencies = [
"async-trait",
- "cbindgen 0.24.5",
+ "cbindgen 0.28.0",
"chrono",
"futures",
"http 1.1.0",
@@ -2616,7 +2616,7 @@ dependencies = [
name = "mullvad-ios"
version = "0.0.0"
dependencies = [
- "cbindgen 0.27.0",
+ "cbindgen 0.28.0",
"hyper-util",
"libc",
"log",
diff --git a/Cargo.toml b/Cargo.toml
index b1c5ff8aa1..2555ad16d8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,59 +4,55 @@ repository = "https://github.com/mullvad/mullvadvpn-app/"
license = "GPL-3.0"
edition = "2021"
# Must be less than or equal to `channel` in `rust-toolchain.toml`
-rust-version = "1.80.0"
+rust-version = "1.83.0"
[workspace]
resolver = "2"
members = [
- "android/translations-converter",
- "desktop/packages/nseventforwarder",
- "desktop/packages/win-shortcuts",
- "mullvad-api",
- "mullvad-cli",
- "mullvad-daemon",
- "mullvad-encrypted-dns-proxy",
- "mullvad-exclude",
- "mullvad-fs",
- "mullvad-ios",
- "mullvad-jni",
- "mullvad-leak-checker",
- "mullvad-management-interface",
- "mullvad-nsis",
- "mullvad-paths",
- "mullvad-problem-report",
- "mullvad-relay-selector",
- "mullvad-setup",
- "mullvad-types",
- "mullvad-types/intersection-derive",
- "mullvad-version",
- "talpid-core",
- "talpid-dbus",
- "talpid-future",
- "talpid-macos",
- "talpid-net",
- "talpid-openvpn",
- "talpid-openvpn-plugin",
- "talpid-platform-metadata",
- "talpid-routing",
- "talpid-time",
- "talpid-tunnel",
- "talpid-tunnel-config-client",
- "talpid-windows",
- "talpid-wireguard",
- "tunnel-obfuscation",
- "wireguard-go-rs",
- "windows-installer",
+ "android/translations-converter",
+ "desktop/packages/nseventforwarder",
+ "desktop/packages/win-shortcuts",
+ "mullvad-api",
+ "mullvad-cli",
+ "mullvad-daemon",
+ "mullvad-encrypted-dns-proxy",
+ "mullvad-exclude",
+ "mullvad-fs",
+ "mullvad-ios",
+ "mullvad-jni",
+ "mullvad-leak-checker",
+ "mullvad-management-interface",
+ "mullvad-nsis",
+ "mullvad-paths",
+ "mullvad-problem-report",
+ "mullvad-relay-selector",
+ "mullvad-setup",
+ "mullvad-types",
+ "mullvad-types/intersection-derive",
+ "mullvad-version",
+ "talpid-core",
+ "talpid-dbus",
+ "talpid-future",
+ "talpid-macos",
+ "talpid-net",
+ "talpid-openvpn",
+ "talpid-openvpn-plugin",
+ "talpid-platform-metadata",
+ "talpid-routing",
+ "talpid-time",
+ "talpid-tunnel",
+ "talpid-tunnel-config-client",
+ "talpid-windows",
+ "talpid-wireguard",
+ "tunnel-obfuscation",
+ "wireguard-go-rs",
+ "windows-installer",
]
# Default members dictate what is built when running `cargo build` in the root directory.
# This is set to a minimal set of packages to speed up the build process and avoid building
# crates which might not compile without additional input, such as the `windows-installer` crate.
# To build or test everything, add `--workspace` to your cargo commands.
-default-members = [
- "mullvad-cli",
- "mullvad-daemon",
- "mullvad-version",
-]
+default-members = ["mullvad-cli", "mullvad-daemon", "mullvad-version"]
# Keep all lints in sync with `test/Cargo.toml`
[workspace.lints.rust]
@@ -93,7 +89,12 @@ tonic-build = { version = "0.10.0", default-features = false }
tower = { version = "0.5.1", features = ["util"] }
prost = "0.13.3"
prost-types = "0.13.3"
-hyper-util = {version = "0.1.8", features = ["client", "client-legacy", "http2", "http1"]}
+hyper-util = { version = "0.1.8", features = [
+ "client",
+ "client-legacy",
+ "http2",
+ "http1",
+] }
env_logger = "0.10.0"
thiserror = "2.0"
diff --git a/mullvad-api/Cargo.toml b/mullvad-api/Cargo.toml
index 005d1a9505..db248daf63 100644
--- a/mullvad-api/Cargo.toml
+++ b/mullvad-api/Cargo.toml
@@ -22,15 +22,27 @@ thiserror = { workspace = true }
futures = { workspace = true }
http = "1.1.0"
hyper = { version = "1.4.1", features = ["client", "http1"] }
-hyper-util = { workspace = true}
+hyper-util = { workspace = true }
http-body-util = "0.1.2"
tower = { workspace = true }
ipnetwork = { workspace = true }
log = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
-tokio = { workspace = true, features = ["macros", "time", "rt-multi-thread", "net", "io-std", "io-util", "fs"] }
-tokio-rustls = { version = "0.26.0", features = ["logging", "tls12", "ring"], default-features = false}
+tokio = { workspace = true, features = [
+ "macros",
+ "time",
+ "rt-multi-thread",
+ "net",
+ "io-std",
+ "io-util",
+ "fs",
+] }
+tokio-rustls = { version = "0.26.0", features = [
+ "logging",
+ "tls12",
+ "ring",
+], default-features = false }
tokio-socks = "0.5.1"
rustls-pemfile = "2.1.3"
uuid = { version = "1.4.1", features = ["v4"] }
@@ -41,7 +53,7 @@ mullvad-types = { path = "../mullvad-types" }
talpid-types = { path = "../talpid-types" }
talpid-time = { path = "../talpid-time" }
-shadowsocks = { workspace = true, features = [ "stream-cipher" ] }
+shadowsocks = { workspace = true, features = ["stream-cipher"] }
[dev-dependencies]
talpid-time = { path = "../talpid-time", features = ["test"] }
@@ -49,8 +61,8 @@ tokio = { workspace = true, features = ["test-util", "time"] }
mockito = "1.6.1"
[build-dependencies]
-cbindgen = { version = "0.24.3", default-features = false }
+cbindgen = { version = "0.28.0", default-features = false }
[lib]
-crate-type = [ "rlib", "staticlib" ]
+crate-type = ["rlib", "staticlib"]
bench = false
diff --git a/mullvad-api/src/availability.rs b/mullvad-api/src/availability.rs
index 9d5e135c15..a8ac3aa6cf 100644
--- a/mullvad-api/src/availability.rs
+++ b/mullvad-api/src/availability.rs
@@ -128,11 +128,14 @@ impl ApiAvailability {
self.acquire().state
}
- pub fn wait_for_unsuspend(&self) -> impl Future<Output = Result<(), Error>> {
+ pub fn wait_for_unsuspend(&self) -> impl Future<Output = Result<(), Error>> + use<> {
self.wait_for_state(|state| !state.is_suspended())
}
- pub fn when_bg_resumes<F: Future<Output = O>, O>(&self, task: F) -> impl Future<Output = O> {
+ pub fn when_bg_resumes<F: Future<Output = O>, O>(
+ &self,
+ task: F,
+ ) -> impl Future<Output = O> + use<F, O> {
let wait_task = self.wait_for_state(|state| !state.is_background_paused());
async move {
let _ = wait_task.await;
@@ -140,11 +143,14 @@ impl ApiAvailability {
}
}
- pub fn wait_background(&self) -> impl Future<Output = Result<(), Error>> {
+ pub fn wait_background(&self) -> impl Future<Output = Result<(), Error>> + use<> {
self.wait_for_state(|state| !state.is_background_paused())
}
- pub fn when_online<F: Future<Output = O>, O>(&self, task: F) -> impl Future<Output = O> {
+ pub fn when_online<F: Future<Output = O>, O>(
+ &self,
+ task: F,
+ ) -> impl Future<Output = O> + use<F, O> {
let wait_task = self.wait_for_state(|state| !state.is_offline());
async move {
let _ = wait_task.await;
@@ -156,10 +162,10 @@ impl ApiAvailability {
self.wait_for_state(|state| !state.is_offline())
}
- fn wait_for_state(
+ fn wait_for_state<F: Fn(State) -> bool>(
&self,
- state_ready: impl Fn(State) -> bool,
- ) -> impl Future<Output = Result<(), Error>> {
+ state_ready: F,
+ ) -> impl Future<Output = Result<(), Error>> + use<F> {
let mut rx = { self.acquire().tx.subscribe() };
let handle = self.clone();
diff --git a/mullvad-api/src/device.rs b/mullvad-api/src/device.rs
index 036beb731f..062c06f28b 100644
--- a/mullvad-api/src/device.rs
+++ b/mullvad-api/src/device.rs
@@ -36,8 +36,9 @@ impl DevicesProxy {
&self,
account: AccountNumber,
pubkey: wireguard::PublicKey,
- ) -> impl Future<Output = Result<(Device, mullvad_types::wireguard::AssociatedAddresses), rest::Error>>
- {
+ ) -> impl Future<
+ Output = Result<(Device, mullvad_types::wireguard::AssociatedAddresses), rest::Error>,
+ > + use<> {
#[derive(serde::Serialize)]
struct DeviceSubmission {
pubkey: wireguard::PublicKey,
@@ -89,7 +90,7 @@ impl DevicesProxy {
&self,
account: AccountNumber,
id: DeviceId,
- ) -> impl Future<Output = Result<Device, rest::Error>> {
+ ) -> impl Future<Output = Result<Device, rest::Error>> + use<> {
let service = self.handle.service.clone();
let factory = self.handle.factory.clone();
async move {
@@ -104,7 +105,7 @@ impl DevicesProxy {
pub fn list(
&self,
account: AccountNumber,
- ) -> impl Future<Output = Result<Vec<Device>, rest::Error>> {
+ ) -> impl Future<Output = Result<Vec<Device>, rest::Error>> + use<> {
let service = self.handle.service.clone();
let factory = self.handle.factory.clone();
async move {
@@ -120,7 +121,7 @@ impl DevicesProxy {
&self,
account: AccountNumber,
id: DeviceId,
- ) -> impl Future<Output = Result<(), rest::Error>> {
+ ) -> impl Future<Output = Result<(), rest::Error>> + use<> {
let service = self.handle.service.clone();
let factory = self.handle.factory.clone();
async move {
@@ -138,7 +139,7 @@ impl DevicesProxy {
account: AccountNumber,
id: DeviceId,
pubkey: wireguard::PublicKey,
- ) -> impl Future<Output = Result<mullvad_types::wireguard::AssociatedAddresses, rest::Error>>
+ ) -> impl Future<Output = Result<mullvad_types::wireguard::AssociatedAddresses, rest::Error>> + use<>
{
#[derive(serde::Serialize)]
struct RotateDevicePubkey {
diff --git a/mullvad-api/src/ffi/device.rs b/mullvad-api/src/ffi/device.rs
index 87fdfcf98b..9007d6d8df 100644
--- a/mullvad-api/src/ffi/device.rs
+++ b/mullvad-api/src/ffi/device.rs
@@ -72,7 +72,7 @@ where
}
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_device_iter_next(
mut iter: MullvadApiDeviceIterator,
device_ptr: *mut MullvadApiDevice,
@@ -93,12 +93,12 @@ pub extern "C" fn mullvad_api_device_iter_next(
true
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_device_iter_drop(iter: MullvadApiDeviceIterator) {
iter.drop()
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_device_drop(device: MullvadApiDevice) {
device.drop()
}
diff --git a/mullvad-api/src/ffi/error.rs b/mullvad-api/src/ffi/error.rs
index 66ffc01220..2468515c25 100644
--- a/mullvad-api/src/ffi/error.rs
+++ b/mullvad-api/src/ffi/error.rs
@@ -64,7 +64,7 @@ impl MullvadApiError {
}
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_error_drop(error: MullvadApiError) {
error.drop()
}
diff --git a/mullvad-api/src/ffi/mod.rs b/mullvad-api/src/ffi/mod.rs
index 9677488257..5eae180f01 100644
--- a/mullvad-api/src/ffi/mod.rs
+++ b/mullvad-api/src/ffi/mod.rs
@@ -237,7 +237,7 @@ impl FfiClient {
/// * `hostname`: pointer to a null-terminated UTF-8 string representing the hostname that will be
/// used for TLS validation.
/// * `disable_tls`: only valid when built for tests, can be ignored when consumed by Swift.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_client_initialize(
client_ptr: *mut MullvadApiClient,
api_address_ptr: *const libc::c_char,
@@ -275,7 +275,7 @@ pub unsafe extern "C" fn mullvad_api_client_initialize(
///
/// * `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.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_remove_all_devices(
client_ptr: MullvadApiClient,
account_ptr: *const libc::c_char,
@@ -297,7 +297,7 @@ pub unsafe extern "C" fn mullvad_api_remove_all_devices(
///
/// * `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.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_get_expiry(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
@@ -325,7 +325,7 @@ pub unsafe extern "C" fn mullvad_api_get_expiry(
/// * `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.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_list_devices(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
@@ -355,7 +355,7 @@ pub unsafe extern "C" fn mullvad_api_list_devices(
///
/// * `new_device_ptr`: a pointer to enough memory to allocate a `MullvadApiDevice`. If this
/// function doesn't return an error, it will be initialized.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_add_device(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
@@ -385,7 +385,7 @@ pub unsafe extern "C" fn mullvad_api_add_device(
/// * `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`.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_create_account(
client_ptr: MullvadApiClient,
account_str_ptr: *mut *const libc::c_char,
@@ -414,7 +414,7 @@ pub unsafe extern "C" fn mullvad_api_create_account(
/// * `client_ptr`: Must be a valid, initialized instance of `MullvadApiClient`
///
/// * `account_str_ptr`: Must be a null-terminated string representing the account to be deleted.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_delete_account(
client_ptr: MullvadApiClient,
account_str_ptr: *const libc::c_char,
@@ -426,7 +426,7 @@ pub unsafe extern "C" fn mullvad_api_delete_account(
}
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub extern "C" fn mullvad_api_client_drop(client: MullvadApiClient) {
client.drop()
}
@@ -436,7 +436,7 @@ pub extern "C" fn mullvad_api_client_drop(client: MullvadApiClient) {
/// # Safety
///
/// `cstr_ptr` must be a pointer to a string allocated by another `mullvad_api` function.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn mullvad_api_cstring_drop(cstr_ptr: *mut libc::c_char) {
let _ = unsafe { CString::from_raw(cstr_ptr) };
}
diff --git a/mullvad-api/src/lib.rs b/mullvad-api/src/lib.rs
index a47c708b2e..997a0635c7 100644
--- a/mullvad-api/src/lib.rs
+++ b/mullvad-api/src/lib.rs
@@ -504,7 +504,7 @@ impl AccountsProxy {
pub fn get_data(
&self,
account: AccountNumber,
- ) -> impl Future<Output = Result<AccountData, rest::Error>> {
+ ) -> impl Future<Output = Result<AccountData, rest::Error>> + use<> {
let service = self.handle.service.clone();
let factory = self.handle.factory.clone();
async move {
@@ -517,7 +517,9 @@ impl AccountsProxy {
}
}
- pub fn create_account(&self) -> impl Future<Output = Result<AccountNumber, rest::Error>> {
+ pub fn create_account(
+ &self,
+ ) -> impl Future<Output = Result<AccountNumber, rest::Error>> + use<> {
#[derive(serde::Deserialize)]
struct AccountCreationResponse {
number: AccountNumber,
@@ -540,7 +542,7 @@ impl AccountsProxy {
&self,
account: AccountNumber,
voucher_code: String,
- ) -> impl Future<Output = Result<VoucherSubmission, rest::Error>> {
+ ) -> impl Future<Output = Result<VoucherSubmission, rest::Error>> + use<> {
#[derive(serde::Serialize)]
struct VoucherSubmission {
voucher_code: String,
@@ -562,7 +564,7 @@ impl AccountsProxy {
pub fn delete_account(
&self,
account: AccountNumber,
- ) -> impl Future<Output = Result<(), rest::Error>> {
+ ) -> impl Future<Output = Result<(), rest::Error>> + use<> {
let service = self.handle.service.clone();
let factory = self.handle.factory.clone();
@@ -629,7 +631,7 @@ impl AccountsProxy {
pub fn get_www_auth_token(
&self,
account: AccountNumber,
- ) -> impl Future<Output = Result<String, rest::Error>> {
+ ) -> impl Future<Output = Result<String, rest::Error>> + use<> {
#[derive(serde::Deserialize)]
struct AuthTokenResponse {
auth_token: String,
@@ -717,7 +719,7 @@ impl AppVersionProxy {
app_version: AppVersion,
platform: &str,
platform_version: String,
- ) -> impl Future<Output = Result<AppVersionResponse, rest::Error>> {
+ ) -> impl Future<Output = Result<AppVersionResponse, rest::Error>> + use<> {
let service = self.handle.service.clone();
let path = format!("{APP_URL_PREFIX}/releases/{platform}/{app_version}");
diff --git a/mullvad-api/src/relay_list.rs b/mullvad-api/src/relay_list.rs
index f1375b5f6f..f19961bc8a 100644
--- a/mullvad-api/src/relay_list.rs
+++ b/mullvad-api/src/relay_list.rs
@@ -32,7 +32,7 @@ impl RelayListProxy {
pub fn relay_list(
&self,
etag: Option<String>,
- ) -> impl Future<Output = Result<Option<relay_list::RelayList>, rest::Error>> {
+ ) -> impl Future<Output = Result<Option<relay_list::RelayList>, rest::Error>> + use<> {
let service = self.handle.service.clone();
let request = self.handle.factory.get("app/v1/relays");
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index d0de98c27a..1f2d1f9192 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -941,35 +941,38 @@ pub async fn resolve_location_constraint(
relay_filter: impl FnOnce(&mullvad_types::relay_list::Relay) -> bool,
) -> Result<Constraint<GeographicLocationConstraint>> {
let relay_iter = rpc.get_relay_locations().await?.into_relays();
- if let Some(matching_relay) = relay_iter
+ match relay_iter
.clone()
.find(|relay| relay.hostname.to_lowercase() == location_constraint_args.country)
{
- if relay_filter(&matching_relay) {
- Ok(Constraint::Only(relay_to_geographical_constraint(
- matching_relay,
- )))
- } else {
- bail!(
- "The relay `{}` is not valid for this operation",
- location_constraint_args.country
- )
+ Some(matching_relay) => {
+ if relay_filter(&matching_relay) {
+ Ok(Constraint::Only(relay_to_geographical_constraint(
+ matching_relay,
+ )))
+ } else {
+ bail!(
+ "The relay `{}` is not valid for this operation",
+ location_constraint_args.country
+ )
+ }
}
- } else {
- // The Constraint was not a relay, assuming it to be a location
- let location_constraint: Constraint<GeographicLocationConstraint> =
- Constraint::from(location_constraint_args);
+ _ => {
+ // The Constraint was not a relay, assuming it to be a location
+ let location_constraint: Constraint<GeographicLocationConstraint> =
+ Constraint::from(location_constraint_args);
- // If the location constraint was not "any", then validate the country/city
- if let Constraint::Only(constraint) = &location_constraint {
- let found = relay_iter.clone().any(|relay| constraint.matches(&relay));
+ // If the location constraint was not "any", then validate the country/city
+ if let Constraint::Only(constraint) = &location_constraint {
+ let found = relay_iter.clone().any(|relay| constraint.matches(&relay));
- if !found {
- bail!("Invalid location argument");
+ if !found {
+ bail!("Invalid location argument");
+ }
}
- }
- Ok(location_constraint)
+ Ok(location_constraint)
+ }
}
}
diff --git a/mullvad-cli/src/format.rs b/mullvad-cli/src/format.rs
index fdf105e51f..3292f7eb71 100644
--- a/mullvad-cli/src/format.rs
+++ b/mullvad-cli/src/format.rs
@@ -12,13 +12,13 @@ use talpid_types::{
#[macro_export]
macro_rules! print_option {
- ($value:expr $(,)?) => {{
+ ($value:expr_2021 $(,)?) => {{
println!("{:<4}{:<24}{}", "", "", $value,)
}};
- ($option:literal, $value:expr $(,)?) => {{
+ ($option:literal, $value:expr_2021 $(,)?) => {{
println!("{:<4}{:<24}{}", "", concat!($option, ":"), $value,)
}};
- ($option:expr, $value:expr $(,)?) => {{
+ ($option:expr_2021, $value:expr_2021 $(,)?) => {{
println!("{:<4}{:<24}{}", "", format!("{}:", $option), $value,)
}};
}
diff --git a/mullvad-daemon/src/api.rs b/mullvad-daemon/src/api.rs
index 97799d244e..e07a5a7077 100644
--- a/mullvad-daemon/src/api.rs
+++ b/mullvad-daemon/src/api.rs
@@ -344,7 +344,9 @@ impl AccessModeSelector {
match execution {
Ok(_) => (),
Err(error) if error.is_critical_error() => {
- log::error!("AccessModeSelector failed due to an internal error and won't be able to recover without a restart. {error}");
+ log::error!(
+ "AccessModeSelector failed due to an internal error and won't be able to recover without a restart. {error}"
+ );
break;
}
Err(error) => {
diff --git a/mullvad-daemon/src/device/api.rs b/mullvad-daemon/src/device/api.rs
index d7b73d6e7b..714df2dfb3 100644
--- a/mullvad-daemon/src/device/api.rs
+++ b/mullvad-daemon/src/device/api.rs
@@ -151,27 +151,22 @@ impl futures::Future for Call {
) -> std::task::Poll<Self::Output> {
use Call::*;
match &mut *self {
- Login(call, tx) => {
- if let std::task::Poll::Ready(response) = Pin::new(call).poll(cx) {
+ Login(call, tx) => match Pin::new(call).poll(cx) {
+ std::task::Poll::Ready(response) => {
std::task::Poll::Ready(ApiResult::Login(response, tx.take().unwrap()))
- } else {
- std::task::Poll::Pending
}
- }
+ _ => std::task::Poll::Pending,
+ },
TimerKeyRotation(call) | OneshotKeyRotation(call) => {
Pin::new(call).poll(cx).map(ApiResult::Rotation)
}
Validation(call) => Pin::new(call).poll(cx).map(ApiResult::Validation),
- VoucherSubmission(call, tx) => {
- if let std::task::Poll::Ready(response) = Pin::new(call).poll(cx) {
- std::task::Poll::Ready(ApiResult::VoucherSubmission(
- response,
- tx.take().unwrap(),
- ))
- } else {
- std::task::Poll::Pending
- }
- }
+ VoucherSubmission(call, tx) => match Pin::new(call).poll(cx) {
+ std::task::Poll::Ready(response) => std::task::Poll::Ready(
+ ApiResult::VoucherSubmission(response, tx.take().unwrap()),
+ ),
+ _ => std::task::Poll::Pending,
+ },
#[cfg(target_os = "android")]
InitPlayPurchase(call, tx) => {
if let std::task::Poll::Ready(response) = Pin::new(call).poll(cx) {
diff --git a/mullvad-daemon/src/device/mod.rs b/mullvad-daemon/src/device/mod.rs
index 829b3f2060..e6e89d8b24 100644
--- a/mullvad-daemon/src/device/mod.rs
+++ b/mullvad-daemon/src/device/mod.rs
@@ -945,7 +945,7 @@ impl AccountManager {
fn spawn_timed_key_rotation(
&self,
- ) -> Option<impl Future<Output = Result<WireguardData, Error>> + Send + 'static> {
+ ) -> Option<impl Future<Output = Result<WireguardData, Error>> + Send + 'static + use<>> {
let config = self.data.device()?;
let key_rotation_timer = self.key_rotation_timer(config.device.wg_data.created);
@@ -1002,20 +1002,26 @@ impl AccountManager {
.is_ok()
});
- if let Some(old_config) = old_config {
- let logout_call = tokio::spawn(Box::pin(self.logout_api_call(old_config)));
+ match old_config {
+ Some(old_config) => {
+ let logout_call = tokio::spawn(Box::pin(self.logout_api_call(old_config)));
- tokio::spawn(async move {
- let _response = tokio::time::timeout(LOGOUT_TIMEOUT, logout_call).await;
+ tokio::spawn(async move {
+ let _response = tokio::time::timeout(LOGOUT_TIMEOUT, logout_call).await;
+ let _ = tx.send(Ok(()));
+ });
+ }
+ _ => {
+ // The state was `revoked`.
let _ = tx.send(Ok(()));
- });
- } else {
- // The state was `revoked`.
- let _ = tx.send(Ok(()));
+ }
}
}
- fn logout_api_call(&self, data: PrivateAccountAndDevice) -> impl Future<Output = ()> + 'static {
+ fn logout_api_call(
+ &self,
+ data: PrivateAccountAndDevice,
+ ) -> impl Future<Output = ()> + 'static + use<> {
let service = self.device_service.clone();
async move {
@@ -1057,7 +1063,7 @@ impl AccountManager {
fn initiate_key_rotation(
&self,
- ) -> Result<impl Future<Output = Result<WireguardData, Error>>, Error> {
+ ) -> Result<impl Future<Output = Result<WireguardData, Error>> + use<>, Error> {
let data = self.data.device().cloned().ok_or(Error::NoDevice)?;
let device_service = self.device_service.clone();
Ok(async move {
@@ -1067,7 +1073,10 @@ impl AccountManager {
})
}
- fn key_rotation_timer(&self, key_created: DateTime<Utc>) -> impl Future<Output = ()> + 'static {
+ fn key_rotation_timer(
+ &self,
+ key_created: DateTime<Utc>,
+ ) -> impl Future<Output = ()> + 'static + use<> {
let rotation_interval = self.rotation_interval;
async move {
@@ -1097,21 +1106,23 @@ impl AccountManager {
fn fetch_device_config(
&self,
old_config: &PrivateAccountAndDevice,
- ) -> impl Future<Output = Result<Device, Error>> {
+ ) -> impl Future<Output = Result<Device, Error>> + use<> {
let device_service = self.device_service.clone();
let account_number = old_config.account_number.clone();
let device_id = old_config.device.id.clone();
async move { device_service.get(account_number, device_id).await }
}
- fn validation_call(&self) -> Result<impl Future<Output = Result<Device, Error>>, Error> {
+ fn validation_call(
+ &self,
+ ) -> Result<impl Future<Output = Result<Device, Error>> + use<>, Error> {
let old_config = self.data.device().ok_or(Error::NoDevice)?;
Ok(self.fetch_device_config(old_config))
}
fn expiry_call(
&self,
- ) -> Result<impl Future<Output = Result<chrono::DateTime<Utc>, Error>>, Error> {
+ ) -> Result<impl Future<Output = Result<chrono::DateTime<Utc>, Error>> + use<>, Error> {
let old_config = self.data.device().ok_or(Error::NoDevice)?;
let account_number = old_config.account_number.clone();
let account_service = self.account_service.clone();
diff --git a/mullvad-daemon/src/device/service.rs b/mullvad-daemon/src/device/service.rs
index b5d8fcd3b3..3ebecf0483 100644
--- a/mullvad-daemon/src/device/service.rs
+++ b/mullvad-daemon/src/device/service.rs
@@ -44,7 +44,7 @@ impl DeviceService {
pub fn generate_for_account(
&self,
account_number: AccountNumber,
- ) -> impl Future<Output = Result<PrivateAccountAndDevice, Error>> + Send {
+ ) -> impl Future<Output = Result<PrivateAccountAndDevice, Error>> + Send + use<> {
let private_key = PrivateKey::new_from_random();
let pubkey = private_key.public_key();
@@ -261,7 +261,9 @@ pub struct AccountService {
}
impl AccountService {
- pub fn create_account(&self) -> impl Future<Output = Result<AccountNumber, rest::Error>> {
+ pub fn create_account(
+ &self,
+ ) -> impl Future<Output = Result<AccountNumber, rest::Error>> + use<> {
let proxy = self.proxy.clone();
let api_handle = self.api_availability.clone();
retry_future(
@@ -274,7 +276,7 @@ impl AccountService {
pub fn get_www_auth_token(
&self,
account: AccountNumber,
- ) -> impl Future<Output = Result<String, rest::Error>> {
+ ) -> impl Future<Output = Result<String, rest::Error>> + use<> {
let proxy = self.proxy.clone();
let api_handle = self.api_availability.clone();
retry_future(
diff --git a/mullvad-daemon/src/exception_logging/win.rs b/mullvad-daemon/src/exception_logging/win.rs
index 0a890a7e74..3fa50aa506 100644
--- a/mullvad-daemon/src/exception_logging/win.rs
+++ b/mullvad-daemon/src/exception_logging/win.rs
@@ -69,7 +69,8 @@ fn generate_minidump(
};
// SAFETY: MiniDumpWriteDump is not thread-safe, so for this to be safe all threads need to be
- // synchronized. logging_exception_filter takes precaution by adding a thread-safe reentrancy guard.
+ // synchronized. logging_exception_filter takes precaution by adding a thread-safe reentrancy
+ // guard.
if unsafe {
MiniDumpWriteDump(
process,
@@ -148,9 +149,9 @@ unsafe extern "system" fn logging_exception_filter(info_ptr: *const EXCEPTION_PO
}
// SAFETY: We've explicitly checked for null pointer and
// alignment. We assume that Windows gives us valid pointers, i.e. info points to valid data.
- let info: &EXCEPTION_POINTERS = &*info_ptr;
- let record: &EXCEPTION_RECORD = &*info.ExceptionRecord;
- let context: &CONTEXT = &*info.ContextRecord;
+ let info: &EXCEPTION_POINTERS = unsafe { &*info_ptr };
+ let record: &EXCEPTION_RECORD = unsafe { &*info.ExceptionRecord };
+ let context: &CONTEXT = unsafe { &*info.ContextRecord };
// Generate minidump
let dump_path = match log_dir() {
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 6e91e6efa1..1da90693fc 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -560,12 +560,11 @@ where
InternalDaemonEvent: From<E>,
{
fn send(&self, event: E) -> Result<(), talpid_core::mpsc::Error> {
- if let Some(sender) = self.sender.upgrade() {
- sender
+ match self.sender.upgrade() {
+ Some(sender) => sender
.unbounded_send(InternalDaemonEvent::from(event))
- .map_err(|_| talpid_core::mpsc::Error::ChannelClosed)
- } else {
- Err(talpid_core::mpsc::Error::ChannelClosed)
+ .map_err(|_| talpid_core::mpsc::Error::ChannelClosed),
+ _ => Err(talpid_core::mpsc::Error::ChannelClosed),
}
}
}
@@ -958,10 +957,13 @@ impl Daemon {
self.disconnect_tunnel();
while let Some(event) = self.rx.next().await {
- if let InternalDaemonEvent::TunnelStateTransition(transition) = event {
- self.handle_tunnel_state_transition(transition).await;
- } else {
- log::trace!("Ignoring event because the daemon is shutting down");
+ match event {
+ InternalDaemonEvent::TunnelStateTransition(transition) => {
+ self.handle_tunnel_state_transition(transition).await;
+ }
+ _ => {
+ log::trace!("Ignoring event because the daemon is shutting down");
+ }
}
if self.tunnel_state.is_disconnected() {
@@ -1162,14 +1164,15 @@ impl Daemon {
// If not connected, we have to guess whether the users local connection supports IPv6.
// The only thing we have to go on is the wireguard setting.
TunnelState::Disconnected { .. } => {
- if let RelaySettings::Normal(relay_constraints) = &self.settings.relay_settings {
- // Note that `Constraint::Any` corresponds to just IPv4
- matches!(
- relay_constraints.wireguard_constraints.ip_version,
- mullvad_types::constraints::Constraint::Only(IpVersion::V6)
- )
- } else {
- false
+ match &self.settings.relay_settings {
+ RelaySettings::Normal(relay_constraints) => {
+ // Note that `Constraint::Any` corresponds to just IPv4
+ matches!(
+ relay_constraints.wireguard_constraints.ip_version,
+ mullvad_types::constraints::Constraint::Only(IpVersion::V6)
+ )
+ }
+ _ => false,
}
}
// Fetching IP from am.i.mullvad.net should only be done from a tunnel state where a
@@ -1690,24 +1693,27 @@ impl Daemon {
}
async fn on_get_www_auth_token(&mut self, tx: ResponseTx<String, Error>) {
- if let Ok(Some(device)) = self.account_manager.data().await.map(|s| s.into_device()) {
- let future = self
- .account_manager
- .account_service
- .get_www_auth_token(device.account_number);
- tokio::spawn(async {
+ match self.account_manager.data().await.map(|s| s.into_device()) {
+ Ok(Some(device)) => {
+ let future = self
+ .account_manager
+ .account_service
+ .get_www_auth_token(device.account_number);
+ tokio::spawn(async {
+ Self::oneshot_send(
+ tx,
+ future.await.map_err(Error::RestError),
+ "get_www_auth_token response",
+ );
+ });
+ }
+ _ => {
Self::oneshot_send(
tx,
- future.await.map_err(Error::RestError),
+ Err(Error::NoAccountNumber),
"get_www_auth_token response",
);
- });
- } else {
- Self::oneshot_send(
- tx,
- Err(Error::NoAccountNumber),
- "get_www_auth_token response",
- );
+ }
}
}
@@ -2709,12 +2715,10 @@ impl Daemon {
}
async fn on_get_wireguard_key(&self, tx: ResponseTx<Option<PublicKey>, Error>) {
- let result =
- if let Ok(Some(config)) = self.account_manager.data().await.map(|s| s.into_device()) {
- Ok(Some(config.device.wg_data.get_public_key()))
- } else {
- Err(Error::NoAccountNumber)
- };
+ let result = match self.account_manager.data().await.map(|s| s.into_device()) {
+ Ok(Some(config)) => Ok(Some(config.device.wg_data.get_public_key())),
+ _ => Err(Error::NoAccountNumber),
+ };
Self::oneshot_send(tx, result, "get_wireguard_key response");
}
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 817dc85200..8249aea968 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -290,7 +290,9 @@ impl ManagementService for ManagementServiceImpl {
async fn set_block_when_disconnected(&self, request: Request<bool>) -> ServiceResult<()> {
let block_when_disconnected = request.into_inner();
log::debug!("set_block_when_disconnected({})", block_when_disconnected);
- Err(Status::unimplemented("Setting Lockdown mode on Android is not supported - this is handled by the OS, not the daemon"))
+ Err(Status::unimplemented(
+ "Setting Lockdown mode on Android is not supported - this is handled by the OS, not the daemon",
+ ))
}
async fn set_auto_connect(&self, request: Request<bool>) -> ServiceResult<()> {
@@ -1138,7 +1140,7 @@ impl ManagementInterfaceServer {
let rpc_server_join_handle = mullvad_management_interface::spawn_rpc_server(
server,
async move {
- server_abort_rx.into_future().await;
+ StreamExt::into_future(server_abort_rx).await;
},
&rpc_socket_path,
)
@@ -1353,9 +1355,7 @@ fn map_device_error(error: &device::Error) -> Status {
}
device::Error::InvalidVoucher => Status::new(Code::NotFound, INVALID_VOUCHER_MESSAGE),
device::Error::UsedVoucher => Status::new(Code::ResourceExhausted, USED_VOUCHER_MESSAGE),
- device::Error::DeviceIoError(ref _error) => {
- Status::new(Code::Unavailable, error.to_string())
- }
+ device::Error::DeviceIoError(_error) => Status::new(Code::Unavailable, error.to_string()),
device::Error::OtherRestError(error) => map_rest_error(error),
_ => Status::new(Code::Unknown, error.to_string()),
}
diff --git a/mullvad-daemon/src/migrations/account_history.rs b/mullvad-daemon/src/migrations/account_history.rs
index eeaf6e67d7..7f9579ce04 100644
--- a/mullvad-daemon/src/migrations/account_history.rs
+++ b/mullvad-daemon/src/migrations/account_history.rs
@@ -25,13 +25,16 @@ pub async fn migrate_location(old_dir: &Path, new_dir: &Path) {
return;
}
- if let Err(error) = fs::copy(&old_path, &new_path).await {
- log::error!(
- "{}",
- error.display_chain_with_msg("Failed to migrate account history file location")
- );
- } else {
- let _ = fs::remove_file(old_path).await;
+ match fs::copy(&old_path, &new_path).await {
+ Err(error) => {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to migrate account history file location")
+ );
+ }
+ _ => {
+ let _ = fs::remove_file(old_path).await;
+ }
}
}
diff --git a/mullvad-daemon/src/relay_list/mod.rs b/mullvad-daemon/src/relay_list/mod.rs
index 99fa60df57..ee5781aff0 100644
--- a/mullvad-daemon/src/relay_list/mod.rs
+++ b/mullvad-daemon/src/relay_list/mod.rs
@@ -166,7 +166,7 @@ impl RelayListUpdater {
api_handle: ApiAvailability,
proxy: RelayListProxy,
tag: Option<String>,
- ) -> impl Future<Output = Result<Option<RelayList>, mullvad_api::Error>> + 'static {
+ ) -> impl Future<Output = Result<Option<RelayList>, mullvad_api::Error>> + use<> {
let download_futures = move || {
let available = api_handle.wait_background();
let req = proxy.relay_list(tag.clone());
diff --git a/mullvad-daemon/src/settings/mod.rs b/mullvad-daemon/src/settings/mod.rs
index dcb7e56106..0b0d914569 100644
--- a/mullvad-daemon/src/settings/mod.rs
+++ b/mullvad-daemon/src/settings/mod.rs
@@ -504,10 +504,9 @@ impl Display for SettingsSummary<'_> {
impl SettingsSummary<'_> {
fn fmt_option<T: Display>(f: &mut fmt::Formatter<'_>, val: Option<T>) -> fmt::Result {
- if let Some(inner) = &val {
- inner.fmt(f)
- } else {
- f.write_str("unset")
+ match &val {
+ Some(inner) => inner.fmt(f),
+ _ => f.write_str("unset"),
}
}
}
diff --git a/mullvad-daemon/src/settings/patch.rs b/mullvad-daemon/src/settings/patch.rs
index 6e66fe6389..1025039cd8 100644
--- a/mullvad-daemon/src/settings/patch.rs
+++ b/mullvad-daemon/src/settings/patch.rs
@@ -238,7 +238,7 @@ fn merge_relay_overrides(
// Replace or append to existing values
match (existing_val, patch_override) {
(
- serde_json::Value::Object(ref mut current),
+ &mut serde_json::Value::Object(ref mut current),
serde_json::Value::Object(ref patch),
) => {
for (k, v) in patch {
@@ -274,9 +274,9 @@ fn merge_patch_to_value(
match (&permitted_key.key_type, current_value, patch_value) {
// Append or replace keys to objects
(
- PermittedKeyValue::Object(sub_permitted),
- serde_json::Value::Object(ref mut current),
- serde_json::Value::Object(ref patch),
+ &PermittedKeyValue::Object(sub_permitted),
+ &mut serde_json::Value::Object(ref mut current),
+ serde_json::Value::Object(patch),
) => {
for (k, sub_patch) in patch {
let Some((_, sub_permitted)) = sub_permitted
diff --git a/mullvad-daemon/src/version_check.rs b/mullvad-daemon/src/version_check.rs
index ed50eb6ff5..1ee879ca1f 100644
--- a/mullvad-daemon/src/version_check.rs
+++ b/mullvad-daemon/src/version_check.rs
@@ -252,7 +252,7 @@ impl VersionUpdaterInner {
/// Wait until [Self::last_app_version_info] becomes stale and needs to be refreshed.
///
/// This happens [UPDATE_INTERVAL] after the last version check.
- fn wait_until_version_is_stale(&self) -> Pin<Box<impl FusedFuture<Output = ()>>> {
+ fn wait_until_version_is_stale(&self) -> Pin<Box<impl FusedFuture<Output = ()> + use<>>> {
let time_until_stale = self.time_until_version_is_stale();
// Boxed, pinned, and fused.
@@ -396,7 +396,10 @@ struct UpdateContext {
impl UpdateContext {
/// Write [VersionUpdaterInner::last_app_version_info], if any, to the cache file
/// ([VERSION_INFO_FILENAME]). Also, notify `self.update_sender`
- fn update(&self, last_app_version: AppVersionInfo) -> impl Future<Output = Result<(), Error>> {
+ fn update(
+ &self,
+ last_app_version: AppVersionInfo,
+ ) -> impl Future<Output = Result<(), Error>> + use<> {
let _ = self.update_sender.send(last_app_version.clone());
let cache_path = self.cache_path.clone();
diff --git a/mullvad-ios/Cargo.toml b/mullvad-ios/Cargo.toml
index 91c2e99b6b..ab4a7a3050 100644
--- a/mullvad-ios/Cargo.toml
+++ b/mullvad-ios/Cargo.toml
@@ -31,7 +31,7 @@ shadowsocks-service = { workspace = true, features = [
] }
[target.'cfg(target_os = "macos")'.build-dependencies]
-cbindgen = { version = "0.27.0", default-features = false }
+cbindgen = { version = "0.28.0", default-features = false }
[lib]
crate-type = ["staticlib"]
diff --git a/mullvad-ios/src/encrypted_dns_proxy.rs b/mullvad-ios/src/encrypted_dns_proxy.rs
index f23482f355..3551d74179 100644
--- a/mullvad-ios/src/encrypted_dns_proxy.rs
+++ b/mullvad-ios/src/encrypted_dns_proxy.rs
@@ -93,7 +93,7 @@ impl EncryptedDnsProxyState {
///
/// * The caller must ensure that the pointer to the [domain_name] string contains a nul terminator
/// at the end of the string.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn encrypted_dns_proxy_init(
domain_name: *const c_char,
) -> *mut EncryptedDnsProxyState {
@@ -116,7 +116,7 @@ pub unsafe extern "C" fn encrypted_dns_proxy_init(
/// `ptr` must be a valid, exclusive pointer to `EncryptedDnsProxyState`, initialized
/// by `encrypted_dns_proxy_init`. This function is not thread safe, and should only be called
/// once.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn encrypted_dns_proxy_free(ptr: *mut EncryptedDnsProxyState) {
let _ = unsafe { Box::from_raw(ptr) };
}
@@ -130,7 +130,7 @@ pub unsafe extern "C" fn encrypted_dns_proxy_free(ptr: *mut EncryptedDnsProxySta
///
/// `proxy_handle` will only contain valid values if the return value is zero. It is still valid to
/// deallocate the memory.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn encrypted_dns_proxy_start(
encrypted_dns_proxy: *mut EncryptedDnsProxyState,
proxy_handle: *mut ProxyHandle,
@@ -166,7 +166,7 @@ pub unsafe extern "C" fn encrypted_dns_proxy_start(
/// # Safety
/// `proxy_config` must be a valid pointer to a `ProxyHandle` as initialized by
/// [`encrypted_dns_proxy_start`]. It should only ever be called once.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn encrypted_dns_proxy_stop(proxy_config: *mut ProxyHandle) -> i32 {
let ptr = unsafe { (*proxy_config).context };
if !ptr.is_null() {
diff --git a/mullvad-ios/src/ephemeral_peer_proxy/mod.rs b/mullvad-ios/src/ephemeral_peer_proxy/mod.rs
index 6d598c5e40..7318cef649 100644
--- a/mullvad-ios/src/ephemeral_peer_proxy/mod.rs
+++ b/mullvad-ios/src/ephemeral_peer_proxy/mod.rs
@@ -118,7 +118,7 @@ extern "C" {
/// # Safety
/// `sender` must be pointing to a valid instance of a `EphemeralPeerCancelToken` created by the
/// `PacketTunnelProvider`.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn cancel_ephemeral_peer_exchange(
sender: *mut peer_exchange::ExchangeCancelToken,
) {
@@ -132,7 +132,7 @@ pub unsafe extern "C" fn cancel_ephemeral_peer_exchange(
/// # Safety
/// `sender` must be pointing to a valid instance of a `EphemeralPeerCancelToken` created by the
/// `PacketTunnelProvider`.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn drop_ephemeral_peer_exchange_token(
sender: *mut peer_exchange::ExchangeCancelToken,
) {
@@ -148,7 +148,7 @@ pub unsafe extern "C" fn drop_ephemeral_peer_exchange_token(
/// function is called, and thus must be copied here. `packet_tunnel` must be valid pointers to a
/// packet tunnel, the packet tunnel pointer must outlive the ephemeral peer exchange.
/// `cancel_token` should be owned by the caller of this function.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn request_ephemeral_peer(
public_key: *const u8,
ephemeral_key: *const u8,
diff --git a/mullvad-ios/src/lib.rs b/mullvad-ios/src/lib.rs
index 61c47803a4..0d88a33df9 100644
--- a/mullvad-ios/src/lib.rs
+++ b/mullvad-ios/src/lib.rs
@@ -10,7 +10,7 @@ pub struct ProxyHandle {
pub port: u16,
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub static CONFIG_SERVICE_PORT: u16 = talpid_tunnel_config_client::CONFIG_SERVICE_PORT;
mod ios {
diff --git a/mullvad-ios/src/shadowsocks_proxy/ffi.rs b/mullvad-ios/src/shadowsocks_proxy/ffi.rs
index de16659851..229993445e 100644
--- a/mullvad-ios/src/shadowsocks_proxy/ffi.rs
+++ b/mullvad-ios/src/shadowsocks_proxy/ffi.rs
@@ -14,7 +14,7 @@ static INIT_LOGGING: Once = Once::new();
///
/// `proxy_config` must be pointing to a valid memory region for the size of a `ProxyHandle`
/// instance.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn start_shadowsocks_proxy(
forward_address: *const u8,
forward_address_len: usize,
@@ -90,7 +90,7 @@ pub unsafe extern "C" fn start_shadowsocks_proxy(
/// # Safety
/// `proxy_config` must be pointing to a valid instance of a `ProxyInstance`, as instantiated by
/// `start_shadowsocks_proxy`.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn stop_shadowsocks_proxy(proxy_config: *mut ProxyHandle) -> i32 {
let context_ptr = unsafe { (*proxy_config).context };
if context_ptr.is_null() {
diff --git a/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs b/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs
index e9ad7ba794..d36e0c6ff4 100644
--- a/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs
+++ b/mullvad-ios/src/tunnel_obfuscator_proxy/ffi.rs
@@ -14,7 +14,7 @@ pub enum TunnelObfuscatorProtocol {
Shadowsocks,
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn start_tunnel_obfuscator_proxy(
peer_address: *const u8,
peer_address_len: usize,
@@ -56,7 +56,7 @@ pub unsafe extern "C" fn start_tunnel_obfuscator_proxy(
}
}
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn stop_tunnel_obfuscator_proxy(proxy_handle: *mut ProxyHandle) -> i32 {
let context_ptr = unsafe { (*proxy_handle).context };
if context_ptr.is_null() {
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 8b1018d926..acced273a3 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -73,7 +73,7 @@ struct DaemonContext {
/// Spawn Mullvad daemon. There can only be a single instance, which must be shut down using
/// `MullvadDaemon.shutdown`. On success, nothing is returned. On error, an exception is thrown.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_initialize(
env: JNIEnv<'_>,
_class: JClass<'_>,
@@ -121,7 +121,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_initial
}
/// Shut down Mullvad daemon that was initialized using `MullvadDaemon.initialize`.
-#[no_mangle]
+#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_shutdown(
_: JNIEnv<'_>,
diff --git a/mullvad-jni/src/problem_report.rs b/mullvad-jni/src/problem_report.rs
index dc3693cfff..3819e30001 100644
--- a/mullvad-jni/src/problem_report.rs
+++ b/mullvad-jni/src/problem_report.rs
@@ -10,7 +10,7 @@ use mullvad_api::ApiEndpoint;
use std::path::Path;
use talpid_types::ErrorExt;
-#[no_mangle]
+#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_dataproxy_MullvadProblemReport_collectReport(
env: JNIEnv<'_>,
@@ -36,7 +36,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_dataproxy_MullvadProblemRepor
}
}
-#[no_mangle]
+#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_dataproxy_MullvadProblemReport_sendProblemReport(
env: JNIEnv<'_>,
diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs
index 0b74f9d9d6..fd038cc37f 100644
--- a/mullvad-management-interface/src/client.rs
+++ b/mullvad-management-interface/src/client.rs
@@ -133,7 +133,9 @@ impl MullvadProxyClient {
TunnelState::try_from(state).map_err(Error::InvalidResponse)
}
- pub async fn events_listen(&mut self) -> Result<impl Stream<Item = Result<DaemonEvent>>> {
+ pub async fn events_listen<'a>(
+ &mut self,
+ ) -> Result<impl Stream<Item = Result<DaemonEvent>> + 'a> {
let listener = self
.0
.events_listen(())
diff --git a/mullvad-nsis/src/lib.rs b/mullvad-nsis/src/lib.rs
index b97685169f..e47436da5d 100644
--- a/mullvad-nsis/src/lib.rs
+++ b/mullvad-nsis/src/lib.rs
@@ -23,7 +23,7 @@ const MAX_PATH_SIZE: isize = 32_767;
/// SAFETY: path needs to be a windows path encoded as a string of u16 that terminates in 0 (two
/// nul-bytes). The string is also not allowed to be greater than `MAX_PATH_SIZE`.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn create_privileged_directory(path: *const u16) -> Status {
catch_and_log_unwind(|| {
let mut i = 0;
@@ -52,7 +52,7 @@ pub unsafe extern "C" fn create_privileged_directory(path: *const u16) -> Status
/// is returned, and the required buffer size (in chars) is returned in `buffer_size`.
/// On success, `buffer_size` is set to the length of the string, including
/// the final null terminator.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn get_system_local_appdata(
buffer: *mut u16,
buffer_size: *mut usize,
@@ -91,7 +91,7 @@ pub unsafe extern "C" fn get_system_local_appdata(
/// `InsufficientBufferSize` is returned, and the required buffer size (in
/// chars) is returned in `buffer_size`. On success, `buffer_size` is set to the
/// length of the string, including the final null terminator.
-#[no_mangle]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn get_system_version(buffer: *mut u16, buffer_size: *mut usize) -> Status {
use talpid_platform_metadata::version;
catch_and_log_unwind(|| {
diff --git a/talpid-core/src/connectivity_listener.rs b/talpid-core/src/connectivity_listener.rs
index 9bdf4bf87a..767673123e 100644
--- a/talpid-core/src/connectivity_listener.rs
+++ b/talpid-core/src/connectivity_listener.rs
@@ -157,7 +157,7 @@ impl ConnectivityListener {
}
/// Entry point for Android Java code to notify the connectivity status.
-#[no_mangle]
+#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_talpid_ConnectivityListener_notifyConnectivityChange(
_: JNIEnv<'_>,
diff --git a/talpid-core/src/dns/windows/dnsapi.rs b/talpid-core/src/dns/windows/dnsapi.rs
index cd7731119b..03d9d44abf 100644
--- a/talpid-core/src/dns/windows/dnsapi.rs
+++ b/talpid-core/src/dns/windows/dnsapi.rs
@@ -89,7 +89,7 @@ impl DnsApi {
}
#[link(name = "dnsapi")]
-extern "system" {
+unsafe extern "system" {
// Flushes the DNS resolver cache
pub fn DnsFlushResolverCache() -> BOOL;
}
diff --git a/talpid-core/src/firewall/windows/mod.rs b/talpid-core/src/firewall/windows/mod.rs
index fa59611132..8dadd7db5c 100644
--- a/talpid-core/src/firewall/windows/mod.rs
+++ b/talpid-core/src/firewall/windows/mod.rs
@@ -720,7 +720,7 @@ mod winfw {
}
}
- extern "system" {
+ unsafe extern "system" {
#[link_name = "WinFw_Initialize"]
pub fn WinFw_Initialize(
timeout: libc::c_uint,
diff --git a/talpid-core/src/split_tunnel/windows/driver.rs b/talpid-core/src/split_tunnel/windows/driver.rs
index 9cc4a33377..e3026b0d95 100644
--- a/talpid-core/src/split_tunnel/windows/driver.rs
+++ b/talpid-core/src/split_tunnel/windows/driver.rs
@@ -42,7 +42,7 @@ const DRIVER_SYMBOLIC_NAME: &str = "\\\\.\\MULLVADSPLITTUNNEL";
const ST_DEVICE_TYPE: u32 = 0x8000;
const fn ctl_code(device_type: u32, function: u32, method: u32, access: u32) -> u32 {
- device_type << 16 | access << 14 | function << 2 | method
+ (device_type << 16) | (access << 14) | (function << 2) | method
}
#[repr(u32)]
@@ -278,7 +278,13 @@ impl DeviceHandle {
internet_ipv4: Option<Ipv4Addr>,
internet_ipv6: Option<Ipv6Addr>,
) -> io::Result<()> {
- log::debug!("Register IPs: tunnel IPv4: {:?}, tunnel IPv6 {:?}, internet IPv4: {:?}, internet IPv6: {:?}", tunnel_ipv4, tunnel_ipv6, internet_ipv4, internet_ipv6);
+ log::debug!(
+ "Register IPs: tunnel IPv4: {:?}, tunnel IPv6 {:?}, internet IPv4: {:?}, internet IPv6: {:?}",
+ tunnel_ipv4,
+ tunnel_ipv6,
+ internet_ipv4,
+ internet_ipv6
+ );
let mut addresses: SplitTunnelAddresses = unsafe { mem::zeroed() };
unsafe {
@@ -840,18 +846,20 @@ pub unsafe fn device_io_control_buffer_async(
};
let input_len = input.map(|input| input.len()).unwrap_or(0);
- let result = DeviceIoControl(
- device.as_raw_handle() as HANDLE,
- ioctl_code,
- input_ptr,
- u32::try_from(input_len).map_err(|_error| {
- io::Error::new(io::ErrorKind::InvalidInput, "the input buffer is too large")
- })?,
- output_ptr as *mut _,
- output_len,
- ptr::null_mut(),
- overlapped,
- );
+ let result = unsafe {
+ DeviceIoControl(
+ device.as_raw_handle() as HANDLE,
+ ioctl_code,
+ input_ptr,
+ u32::try_from(input_len).map_err(|_error| {
+ io::Error::new(io::ErrorKind::InvalidInput, "the input buffer is too large")
+ })?,
+ output_ptr as *mut _,
+ output_len,
+ ptr::null_mut(),
+ overlapped,
+ )
+ };
if result != 0 {
return Err(io::Error::new(
@@ -912,7 +920,7 @@ pub unsafe fn wait_for_single_object(object: HANDLE, timeout: Option<Duration>)
})?,
None => INFINITE,
};
- let result = WaitForSingleObject(object, timeout);
+ let result = unsafe { WaitForSingleObject(object, timeout) };
match result {
WAIT_OBJECT_0 => Ok(()),
WAIT_FAILED => Err(io::Error::last_os_error()),
@@ -928,22 +936,24 @@ pub unsafe fn wait_for_single_object(object: HANDLE, timeout: Option<Duration>)
///
/// * `objects` must be a slice of valid objects that can be signaled, such as event objects.
pub unsafe fn wait_for_multiple_objects(objects: &[HANDLE], wait_all: bool) -> io::Result<HANDLE> {
- let objects_len = u32::try_from(objects.len())
- .map_err(|_error| io::Error::new(io::ErrorKind::InvalidInput, "too many objects"))?;
- let result = WaitForMultipleObjects(
- objects_len,
- objects.as_ptr(),
- if wait_all { 1 } else { 0 },
- INFINITE,
- );
- let signaled_index = if result < objects_len {
- result
- } else if result >= WAIT_ABANDONED_0 && result < WAIT_ABANDONED_0 + objects_len {
- return Err(io::Error::new(io::ErrorKind::Other, "abandoned mutex"));
- } else {
- return Err(io::Error::last_os_error());
- };
- Ok(objects[usize::try_from(signaled_index).expect("usize must be larger than u32")])
+ unsafe {
+ let objects_len = u32::try_from(objects.len())
+ .map_err(|_error| io::Error::new(io::ErrorKind::InvalidInput, "too many objects"))?;
+ let result = WaitForMultipleObjects(
+ objects_len,
+ objects.as_ptr(),
+ if wait_all { 1 } else { 0 },
+ INFINITE,
+ );
+ let signaled_index = if result < objects_len {
+ result
+ } else if result >= WAIT_ABANDONED_0 && result < WAIT_ABANDONED_0 + objects_len {
+ return Err(io::Error::new(io::ErrorKind::Other, "abandoned mutex"));
+ } else {
+ return Err(io::Error::last_os_error());
+ };
+ Ok(objects[usize::try_from(signaled_index).expect("usize must be larger than u32")])
+ }
}
/// Reads the value from `buffer`, zeroing any remaining bytes.
@@ -959,12 +969,14 @@ unsafe fn deserialize_buffer<T>(buffer: &[u8]) -> T {
assert!(buffer.len() <= mem::size_of::<T>());
let mut instance = MaybeUninit::zeroed();
- ptr::copy_nonoverlapping(
- buffer.as_ptr(),
- instance.as_mut_ptr() as *mut u8,
- buffer.len(),
- );
- instance.assume_init()
+ unsafe {
+ ptr::copy_nonoverlapping(
+ buffer.as_ptr(),
+ instance.as_mut_ptr() as *mut u8,
+ buffer.len(),
+ );
+ instance.assume_init()
+ }
}
fn buffer_to_osstring(buffer: &[u8]) -> OsString {
diff --git a/talpid-core/src/split_tunnel/windows/volume_monitor.rs b/talpid-core/src/split_tunnel/windows/volume_monitor.rs
index 982a3cf6f2..1c20254c37 100644
--- a/talpid-core/src/split_tunnel/windows/volume_monitor.rs
+++ b/talpid-core/src/split_tunnel/windows/volume_monitor.rs
@@ -188,7 +188,7 @@ unsafe fn parse_device_volume_broadcast(broadcast: &DEV_BROADCAST_HDR) -> u32 {
return 0;
}
- let volume_broadcast = &*(broadcast as *const _ as *const DEV_BROADCAST_VOLUME);
+ let volume_broadcast = unsafe { &*(broadcast as *const _ as *const DEV_BROADCAST_VOLUME) };
if volume_broadcast.dbcv_flags & DBTF_NET != 0 {
// Ignore net event
return 0;
diff --git a/talpid-core/src/split_tunnel/windows/windows.rs b/talpid-core/src/split_tunnel/windows/windows.rs
index 739048b9a3..1d6c03d39c 100644
--- a/talpid-core/src/split_tunnel/windows/windows.rs
+++ b/talpid-core/src/split_tunnel/windows/windows.rs
@@ -33,7 +33,7 @@ pub fn get_device_path<T: AsRef<Path>>(path: T) -> Result<OsString, io::Error> {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"path must be absolute",
- ))
+ ));
}
};
@@ -51,15 +51,18 @@ pub fn get_device_path<T: AsRef<Path>>(path: T) -> Result<OsString, io::Error> {
pub unsafe fn get_final_path_name_by_handle(raw_handle: HANDLE) -> Result<OsString, io::Error> {
let buffer_size =
- GetFinalPathNameByHandleW(raw_handle, ptr::null_mut(), 0u32, VOLUME_NAME_NT) as usize;
+ unsafe { GetFinalPathNameByHandleW(raw_handle, ptr::null_mut(), 0u32, VOLUME_NAME_NT) }
+ as usize;
let mut buffer = vec![0; buffer_size];
- let status = GetFinalPathNameByHandleW(
- raw_handle,
- buffer.as_mut_ptr(),
- buffer_size as u32,
- VOLUME_NAME_NT,
- ) as usize;
+ let status = unsafe {
+ GetFinalPathNameByHandleW(
+ raw_handle,
+ buffer.as_mut_ptr(),
+ buffer_size as u32,
+ VOLUME_NAME_NT,
+ )
+ } as usize;
if status == 0 {
return Err(io::Error::last_os_error());
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index a617a9260d..70d496b031 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -270,7 +270,7 @@ impl TunnelMonitor {
/// Consumes the monitor and blocks until the tunnel exits or there is an error.
pub fn wait(self) -> Result<()> {
- self.monitor.wait().map_err(Error::from)
+ self.monitor.wait()
}
}
diff --git a/talpid-core/src/window.rs b/talpid-core/src/window.rs
index a78080d716..30df21f2da 100644
--- a/talpid-core/src/window.rs
+++ b/talpid-core/src/window.rs
@@ -116,15 +116,15 @@ where
F: Fn(HWND, u32, WPARAM, LPARAM) -> LRESULT,
{
if message == WM_DESTROY {
- PostQuitMessage(0);
+ unsafe { PostQuitMessage(0) };
return 0;
}
- let raw_callback = GetWindowLongPtrW(window, GWLP_USERDATA);
+ let raw_callback = unsafe { GetWindowLongPtrW(window, GWLP_USERDATA) };
if raw_callback != 0 {
- let typed_callback = &mut *(raw_callback as *mut F);
+ let typed_callback = unsafe { &mut *(raw_callback as *mut F) };
return typed_callback(window, message, wparam, lparam);
}
- DefWindowProcW(window, message, wparam, lparam)
+ unsafe { DefWindowProcW(window, message, wparam, lparam) }
}
/// Power management events
diff --git a/talpid-openvpn/src/lib.rs b/talpid-openvpn/src/lib.rs
index c3474f8e9d..d01290e6f3 100644
--- a/talpid-openvpn/src/lib.rs
+++ b/talpid-openvpn/src/lib.rs
@@ -621,7 +621,7 @@ impl<C: OpenVpnBuilder + Send + 'static> OpenVpnMonitor<C> {
.ca(resource_dir.join("ca.crt"));
#[cfg(windows)]
cmd.tunnel_alias(Some(alias));
- if let Some(proxy_settings) = params.proxy.clone().take() {
+ if let Some(proxy_settings) = params.proxy.clone() {
cmd.proxy_settings(proxy_settings);
}
if let Some(proxy_auth_file) = proxy_auth_file {
diff --git a/talpid-openvpn/src/wintun.rs b/talpid-openvpn/src/wintun.rs
index 744ce9aad0..e3e7938828 100644
--- a/talpid-openvpn/src/wintun.rs
+++ b/talpid-openvpn/src/wintun.rs
@@ -214,7 +214,7 @@ impl WintunDll {
handle: HMODULE,
name: &CStr,
) -> io::Result<unsafe extern "system" fn() -> isize> {
- let handle = GetProcAddress(handle, name.as_ptr() as *const u8);
+ let handle = unsafe { GetProcAddress(handle, name.as_ptr() as *const u8) };
handle.ok_or(io::Error::last_os_error())
}
@@ -252,13 +252,15 @@ impl WintunDll {
}
pub unsafe fn close_adapter(&self, adapter: RawHandle) {
- (self.func_close)(adapter);
+ unsafe { (self.func_close)(adapter) };
}
pub unsafe fn get_adapter_luid(&self, adapter: RawHandle) -> NET_LUID_LH {
let mut luid = mem::MaybeUninit::<NET_LUID_LH>::zeroed();
- (self.func_get_adapter_luid)(adapter, luid.as_mut_ptr());
- luid.assume_init()
+ unsafe {
+ (self.func_get_adapter_luid)(adapter, luid.as_mut_ptr());
+ luid.assume_init()
+ }
}
pub fn activate_logging(&'static self) -> WintunLoggerHandle {
diff --git a/talpid-routing/src/unix/android.rs b/talpid-routing/src/unix/android.rs
index be9f8b7d6a..137e69c1de 100644
--- a/talpid-routing/src/unix/android.rs
+++ b/talpid-routing/src/unix/android.rs
@@ -161,7 +161,7 @@ fn configured_routes(state: &NetworkState) -> HashSet<Route> {
}
/// Entry point for Android Java code to notify the current default network state.
-#[no_mangle]
+#[unsafe(no_mangle)]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_talpid_ConnectivityListener_notifyDefaultNetworkChange(
env: JNIEnv<'_>,
diff --git a/talpid-routing/src/unix/mod.rs b/talpid-routing/src/unix/mod.rs
index 042360d520..5aedc9626e 100644
--- a/talpid-routing/src/unix/mod.rs
+++ b/talpid-routing/src/unix/mod.rs
@@ -332,7 +332,9 @@ impl RouteManagerHandle {
/// Listen for route changes.
#[cfg(target_os = "linux")]
- pub async fn change_listener(&self) -> Result<impl Stream<Item = CallbackMessage>, Error> {
+ pub async fn change_listener(
+ &self,
+ ) -> Result<impl Stream<Item = CallbackMessage> + use<>, Error> {
let (response_tx, response_rx) = oneshot::channel();
self.tx
.unbounded_send(RouteManagerCommand::NewChangeListener(response_tx))
diff --git a/talpid-routing/src/windows/default_route_monitor.rs b/talpid-routing/src/windows/default_route_monitor.rs
index 5f113beaf4..fd73684821 100644
--- a/talpid-routing/src/windows/default_route_monitor.rs
+++ b/talpid-routing/src/windows/default_route_monitor.rs
@@ -302,14 +302,15 @@ unsafe extern "system" fn route_change_callback(
_notification_type: MIB_NOTIFICATION_TYPE,
) {
// SAFETY: We assume Windows provides this pointer correctly
- let row = &*row;
+ let row = unsafe { &*row };
if row.DestinationPrefix.PrefixLength != 0 || !route_has_gateway(row) {
return;
}
// SAFETY: context must not be dropped or modified until this callback has been cancelled.
- let context_and_burst: &ContextAndBurstGuard = &*(context as *const ContextAndBurstGuard);
+ let context_and_burst: &ContextAndBurstGuard =
+ unsafe { &*(context as *const ContextAndBurstGuard) };
let mut context = context_and_burst.context.lock().unwrap();
context.update_refresh_flag(&row.InterfaceLuid, row.InterfaceIndex);
@@ -325,10 +326,11 @@ unsafe extern "system" fn interface_change_callback(
_notification_type: MIB_NOTIFICATION_TYPE,
) {
// SAFETY: We assume Windows provides this pointer correctly
- let row = &*row;
+ let row = unsafe { &*row };
// SAFETY: context must not be dropped or modified until this callback has been cancelled.
- let context_and_burst: &ContextAndBurstGuard = &*(context as *const ContextAndBurstGuard);
+ let context_and_burst: &ContextAndBurstGuard =
+ unsafe { &*(context as *const ContextAndBurstGuard) };
let mut context = context_and_burst.context.lock().unwrap();
context.update_refresh_flag(&row.InterfaceLuid, row.InterfaceIndex);
@@ -344,10 +346,11 @@ unsafe extern "system" fn ip_address_change_callback(
_notification_type: MIB_NOTIFICATION_TYPE,
) {
// SAFETY: We assume Windows provides this pointer correctly
- let row = &*row;
+ let row = unsafe { &*row };
// SAFETY: context must not be dropped or modified until this callback has been cancelled.
- let context_and_burst: &ContextAndBurstGuard = &*(context as *const ContextAndBurstGuard);
+ let context_and_burst: &ContextAndBurstGuard =
+ unsafe { &*(context as *const ContextAndBurstGuard) };
let mut context = context_and_burst.context.lock().unwrap();
context.update_refresh_flag(&row.InterfaceLuid, row.InterfaceIndex);
diff --git a/talpid-routing/src/windows/route_manager.rs b/talpid-routing/src/windows/route_manager.rs
index 60ef984d08..86ccff21fa 100644
--- a/talpid-routing/src/windows/route_manager.rs
+++ b/talpid-routing/src/windows/route_manager.rs
@@ -51,7 +51,9 @@ impl Drop for CallbackHandle {
match callbacks.remove(&self.nonce) {
Some(_) => (),
None => {
- log::warn!("Could not un-register route manager callback due to it already being de-registered");
+ log::warn!(
+ "Could not un-register route manager callback due to it already being de-registered"
+ );
}
}
}
@@ -259,7 +261,9 @@ impl RouteManagerInternal {
if let Err(e) = win32_err!(unsafe {
ConvertInterfaceAliasToLuid(device_name.as_ptr(), &mut luid)
}) {
- log::error!("Unable to get interface LUID for interface \"{device_name:?}\": {e}");
+ log::error!(
+ "Unable to get interface LUID for interface \"{device_name:?}\": {e}"
+ );
return Err(Error::DeviceNameNotFound);
} else {
luid
@@ -346,7 +350,9 @@ impl RouteManagerInternal {
match win32_err!(unsafe { DeleteIpForwardEntry2(&r) }) {
Ok(()) => Ok(()),
Err(e) if e.raw_os_error() == Some(ERROR_NOT_FOUND as i32) => {
- log::warn!("Attempting to delete route which was not present in routing table, ignoring and proceeding. Route: {route}");
+ log::warn!(
+ "Attempting to delete route which was not present in routing table, ignoring and proceeding. Route: {route}"
+ );
Ok(())
}
Err(e) => {
@@ -594,7 +600,7 @@ fn interface_luid_from_gateway(gateway: &SOCKADDR_INET) -> Result<NET_LUID_LH> {
unsafe fn get_first_gateway_address_reference(
adapter: &IP_ADAPTER_ADDRESSES_LH,
) -> &IP_ADAPTER_GATEWAY_ADDRESS_LH {
- &*adapter.FirstGatewayAddress
+ unsafe { &*adapter.FirstGatewayAddress }
}
fn adapter_interface_enabled(
@@ -622,7 +628,7 @@ unsafe fn isolate_gateway_address(
loop {
// SAFETY: The contract states that Address.lpSockaddr is dereferenceable if the element is
// non-null
- if family == (*gateway.Address.lpSockaddr).sa_family {
+ if family == (unsafe { *gateway.Address.lpSockaddr }).sa_family {
// SAFETY: The contract states that this field must have lifetime 'a
matches.push(&gateway.Address);
}
@@ -633,7 +639,7 @@ unsafe fn isolate_gateway_address(
// SAFETY: Gateway.Next is not null here and the contract states it must be dereferenceable
// if non-null
- gateway = &*gateway.Next;
+ gateway = unsafe { &*gateway.Next };
}
matches
@@ -753,9 +759,15 @@ impl Adapters {
let code_size = u32::try_from(std::mem::size_of::<IP_ADAPTER_ADDRESSES_LH>()).unwrap();
if system_size < code_size {
- log::error!("Expecting IP_ADAPTER_ADDRESSES to have size {code_size} bytes. Found structure with size {system_size} bytes.");
- return Err(Error::Adapter(io::Error::new(io::ErrorKind::Other,
- format!("Expecting IP_ADAPTER_ADDRESSES to have size {code_size} bytes. Found structure with size {system_size} bytes."))));
+ log::error!(
+ "Expecting IP_ADAPTER_ADDRESSES to have size {code_size} bytes. Found structure with size {system_size} bytes."
+ );
+ return Err(Error::Adapter(io::Error::new(
+ io::ErrorKind::Other,
+ format!(
+ "Expecting IP_ADAPTER_ADDRESSES to have size {code_size} bytes. Found structure with size {system_size} bytes."
+ ),
+ )));
}
// Initialize members.
diff --git a/talpid-windows/src/net.rs b/talpid-windows/src/net.rs
index 5605021105..c744114a3a 100644
--- a/talpid-windows/src/net.rs
+++ b/talpid-windows/src/net.rs
@@ -155,11 +155,13 @@ unsafe extern "system" fn inner_callback(
row: *const MIB_IPINTERFACE_ROW,
notify_type: i32,
) {
- let context = &mut *(context as *mut IpNotifierHandle<'_>);
- context
- .callback
- .lock()
- .expect("NotifyIpInterfaceChange mutex poisoned")(&*row, notify_type);
+ unsafe {
+ let context = &mut *(context as *mut IpNotifierHandle<'_>);
+ context
+ .callback
+ .lock()
+ .expect("NotifyIpInterfaceChange mutex poisoned")(&*row, notify_type);
+ }
}
/// Registers a callback function that is invoked when an interface is added, removed,
diff --git a/talpid-wireguard/src/wireguard_go/mod.rs b/talpid-wireguard/src/wireguard_go/mod.rs
index db74ef3bac..813490899a 100644
--- a/talpid-wireguard/src/wireguard_go/mod.rs
+++ b/talpid-wireguard/src/wireguard_go/mod.rs
@@ -715,7 +715,7 @@ mod logging {
context: u64,
) {
let managed_msg = if !msg.is_null() {
- std::ffi::CStr::from_ptr(msg).to_string_lossy().to_string()
+ unsafe { std::ffi::CStr::from_ptr(msg).to_string_lossy().to_string() }
} else {
"Logging message from WireGuard is NULL".to_string()
};
diff --git a/talpid-wireguard/src/wireguard_kernel/wg_message.rs b/talpid-wireguard/src/wireguard_kernel/wg_message.rs
index 6dd3ea88a5..14ab31ee76 100644
--- a/talpid-wireguard/src/wireguard_kernel/wg_message.rs
+++ b/talpid-wireguard/src/wireguard_kernel/wg_message.rs
@@ -575,7 +575,7 @@ unsafe fn struct_as_slice<T: Sized>(t: &T) -> &[u8] {
let ptr = t as *const T as *const u8;
// SAFETY: The memory from `ptr` and `size` bytes forward is always the same as the struct.
// The caller is responsible for not using this with structs containing padding.
- std::slice::from_raw_parts(ptr, size)
+ unsafe { std::slice::from_raw_parts(ptr, size) }
}
fn ip_addr_to_bytes(addr: &IpAddr) -> Vec<u8> {
diff --git a/talpid-wireguard/src/wireguard_nt/mod.rs b/talpid-wireguard/src/wireguard_nt/mod.rs
index fb4dfcbb22..4451f36281 100644
--- a/talpid-wireguard/src/wireguard_nt/mod.rs
+++ b/talpid-wireguard/src/wireguard_nt/mod.rs
@@ -761,7 +761,7 @@ impl WgNtDll {
handle: HMODULE,
name: &CStr,
) -> io::Result<unsafe extern "system" fn() -> isize> {
- let handle = GetProcAddress(handle, name.as_ptr() as *const u8);
+ let handle = unsafe { GetProcAddress(handle, name.as_ptr() as *const u8) };
handle.ok_or(io::Error::last_os_error())
}
@@ -783,13 +783,15 @@ impl WgNtDll {
}
pub unsafe fn close_adapter(&self, adapter: RawHandle) {
- (self.func_close)(adapter);
+ unsafe { (self.func_close)(adapter) };
}
pub unsafe fn get_adapter_luid(&self, adapter: RawHandle) -> NET_LUID_LH {
let mut luid = mem::MaybeUninit::<NET_LUID_LH>::zeroed();
- (self.func_get_adapter_luid)(adapter, luid.as_mut_ptr());
- luid.assume_init()
+ unsafe {
+ (self.func_get_adapter_luid)(adapter, luid.as_mut_ptr());
+ luid.assume_init()
+ }
}
pub unsafe fn set_config(
@@ -798,8 +800,9 @@ impl WgNtDll {
config: *const MaybeUninit<u8>,
config_size: usize,
) -> io::Result<()> {
- let result =
- (self.func_set_configuration)(adapter, config, u32::try_from(config_size).unwrap());
+ let result = unsafe {
+ (self.func_set_configuration)(adapter, config, u32::try_from(config_size).unwrap())
+ };
if result == 0 {
return Err(io::Error::last_os_error());
}
@@ -810,8 +813,9 @@ impl WgNtDll {
let mut config_size = 0;
let mut config = vec![];
loop {
- let result =
- (self.func_get_configuration)(adapter, config.as_mut_ptr(), &mut config_size);
+ let result = unsafe {
+ (self.func_get_configuration)(adapter, config.as_mut_ptr(), &mut config_size)
+ };
if result == 0 {
let last_error = io::Error::last_os_error();
if last_error.raw_os_error() != Some(ERROR_MORE_DATA as i32) {
@@ -829,7 +833,7 @@ impl WgNtDll {
adapter: RawHandle,
state: WgAdapterState,
) -> io::Result<()> {
- let result = (self.func_set_adapter_state)(adapter, state);
+ let result = unsafe { (self.func_set_adapter_state)(adapter, state) };
if result == 0 {
return Err(io::Error::last_os_error());
}
@@ -845,7 +849,7 @@ impl WgNtDll {
adapter: RawHandle,
state: WireGuardAdapterLogState,
) -> io::Result<()> {
- if (self.func_set_adapter_logging)(adapter, state) == 0 {
+ if unsafe { (self.func_set_adapter_logging)(adapter, state) } == 0 {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -858,7 +862,7 @@ impl WgNtDll {
events_capacity: usize,
actions_capacity: usize,
) -> io::Result<()> {
- if (self.func_daita_activate)(adapter, events_capacity, actions_capacity) == 0 {
+ if unsafe { (self.func_daita_activate)(adapter, events_capacity, actions_capacity) } == 0 {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -869,7 +873,7 @@ impl WgNtDll {
&self,
adapter: RawHandle,
) -> io::Result<RawHandle> {
- let ready_event = (self.func_daita_event_data_available_event)(adapter);
+ let ready_event = unsafe { (self.func_daita_event_data_available_event)(adapter) };
if ready_event.is_null() {
return Err(io::Error::last_os_error());
}
@@ -882,7 +886,7 @@ impl WgNtDll {
adapter: RawHandle,
events: *mut daita::Event,
) -> io::Result<usize> {
- let num_events = (self.func_daita_receive_events)(adapter, events);
+ let num_events = unsafe { (self.func_daita_receive_events)(adapter, events) };
if num_events == 0 {
return Err(io::Error::last_os_error());
}
@@ -895,7 +899,7 @@ impl WgNtDll {
adapter: RawHandle,
action: *const daita::Action,
) -> io::Result<()> {
- if (self.func_daita_send_action)(adapter, action) == 0 {
+ if unsafe { (self.func_daita_send_action)(adapter, action) } == 0 {
return Err(io::Error::last_os_error());
}
Ok(())
@@ -985,7 +989,7 @@ unsafe fn deserialize_config(
return Err(Error::InvalidConfigData);
}
let (head, mut tail) = config.split_at(mem::size_of::<WgInterface>());
- let interface: WgInterface = *(head.as_ptr() as *const WgInterface);
+ let interface: WgInterface = unsafe { *(head.as_ptr() as *const WgInterface) };
let mut peers = vec![];
for _ in 0..interface.peers_count {
@@ -993,7 +997,7 @@ unsafe fn deserialize_config(
return Err(Error::InvalidConfigData);
}
let (peer_data, new_tail) = tail.split_at(mem::size_of::<WgPeer>());
- let peer: WgPeer = *(peer_data.as_ptr() as *const WgPeer);
+ let peer: WgPeer = unsafe { *(peer_data.as_ptr() as *const WgPeer) };
tail = new_tail;
if let Err(error) = net::try_socketaddr_from_inet_sockaddr(peer.endpoint.addr) {
@@ -1011,7 +1015,8 @@ unsafe fn deserialize_config(
return Err(Error::InvalidConfigData);
}
let (allowed_ip_data, new_tail) = tail.split_at(mem::size_of::<WgAllowedIp>());
- let allowed_ip: WgAllowedIp = *(allowed_ip_data.as_ptr() as *const WgAllowedIp);
+ let allowed_ip: WgAllowedIp =
+ unsafe { *(allowed_ip_data.as_ptr() as *const WgAllowedIp) };
if let Err(error) = WgAllowedIp::validate(
&allowed_ip.address,
allowed_ip.address_family,
diff --git a/test/Cargo.lock b/test/Cargo.lock
index ded34ced7f..c639022fa8 100644
--- a/test/Cargo.lock
+++ b/test/Cargo.lock
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "addr2line"
@@ -362,18 +362,18 @@ dependencies = [
[[package]]
name = "cbindgen"
-version = "0.24.5"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d"
+checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff"
dependencies = [
"heck 0.4.1",
- "indexmap 1.9.3",
+ "indexmap 2.2.6",
"log",
"proc-macro2",
"quote",
"serde",
"serde_json",
- "syn 1.0.109",
+ "syn 2.0.89",
"tempfile",
"toml",
]
@@ -3158,6 +3158,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3901,14 +3910,39 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.5.11"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
+name = "toml_edit"
+version = "0.22.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
+dependencies = [
+ "indexmap 2.2.6",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
name = "tonic"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4642,6 +4676,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
+name = "winnow"
+version = "0.6.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "winreg"
version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/test/Cargo.toml b/test/Cargo.toml
index a0b7782691..c5f216217f 100644
--- a/test/Cargo.toml
+++ b/test/Cargo.toml
@@ -3,16 +3,16 @@ authors = ["Mullvad VPN"]
repository = "https://github.com/mullvad/mullvadvpn-app/"
license = "GPL-3.0"
edition = "2021"
-rust-version = "1.80.0"
+rust-version = "1.83.0"
[workspace]
resolver = "2"
members = [
- "test-manager",
- "test-runner",
- "test-rpc",
- "socks-server",
- "connection-checker",
+ "test-manager",
+ "test-runner",
+ "test-rpc",
+ "socks-server",
+ "connection-checker",
]
# Keep all lints in sync with `../Cargo.toml`
@@ -60,7 +60,11 @@ tower = "0.5.1"
prost = "0.13.3"
prost-types = "0.13.3"
tarpc = { version = "0.30", features = ["tokio1", "serde-transport", "serde1"] }
-hyper-util = {version = "0.1.8", features = ["client", "client-legacy", "http2"]}
+hyper-util = { version = "0.1.8", features = [
+ "client",
+ "client-legacy",
+ "http2",
+] }
# Logging
env_logger = "0.11.0"
diff --git a/test/test-manager/src/tests/helpers.rs b/test/test-manager/src/tests/helpers.rs
index a63ff928b9..195c3da26a 100644
--- a/test/test-manager/src/tests/helpers.rs
+++ b/test/test-manager/src/tests/helpers.rs
@@ -528,7 +528,7 @@ where
break Err(Error::Daemon(format!(
"Failed to get next event: {}",
status
- )))
+ )));
}
None => break Err(Error::Daemon(String::from("Lost daemon event stream"))),
}
diff --git a/test/test-manager/src/tests/mod.rs b/test/test-manager/src/tests/mod.rs
index 19d305a8a3..4f5362167f 100644
--- a/test/test-manager/src/tests/mod.rs
+++ b/test/test-manager/src/tests/mod.rs
@@ -242,7 +242,9 @@ pub async fn ensure_daemon_environment(rpc: &ServiceClient) -> Result<(), anyhow
.await
.context("Failed to get daemon default env variables")?;
if current_env != default_env {
- log::debug!("Restarting daemon due changed environment variables. Values since last test {current_env:?}");
+ log::debug!(
+ "Restarting daemon due changed environment variables. Values since last test {current_env:?}"
+ );
rpc.set_daemon_environment(default_env)
.await
.context("Failed to restart daemon")?;
diff --git a/wireguard-go-rs/Cargo.toml b/wireguard-go-rs/Cargo.toml
index d86cb61535..8a7404cffd 100644
--- a/wireguard-go-rs/Cargo.toml
+++ b/wireguard-go-rs/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "wireguard-go-rs"
description = "Rust bindings to wireguard-go with DAITA support"
-edition = "2021"
+edition.workspace = true
license.workspace = true
[build-dependencies]
@@ -23,4 +23,9 @@ zeroize = "1.8.1"
maybenot-ffi = "2.0.1"
[target.'cfg(target_os = "windows")'.dependencies]
-windows-sys = { version = "0.52.0", features = ["Win32_Networking", "Win32_NetworkManagement", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock"] }
+windows-sys = { version = "0.52.0", features = [
+ "Win32_Networking",
+ "Win32_NetworkManagement",
+ "Win32_NetworkManagement_Ndis",
+ "Win32_Networking_WinSock",
+] }
diff --git a/wireguard-go-rs/src/lib.rs b/wireguard-go-rs/src/lib.rs
index f49c4d4e52..37756a7afb 100644
--- a/wireguard-go-rs/src/lib.rs
+++ b/wireguard-go-rs/src/lib.rs
@@ -336,7 +336,7 @@ mod ffi {
use super::{LoggingCallback, LoggingContext};
use core::ffi::{c_char, c_void};
- extern "C" {
+ unsafe extern "C" {
/// Creates a new wireguard tunnel, uses the specific interface name, and file descriptors
/// for the tunnel device and logging. For targets other than android, this also takes an
/// MTU value.