Fix typos

This commit is contained in:
omahs 2025-05-11 09:49:55 +02:00
parent 6f05ce41a5
commit 73fcc2275c
29 changed files with 47 additions and 47 deletions

View File

@ -182,8 +182,8 @@ See [this](Release.md) for instructions on how to make a new release.
* `MULLVAD_BACKTRACE_ON_FAULT` - When enabled, if the daemon encounters a fault (e.g. `SIGSEGV`), * `MULLVAD_BACKTRACE_ON_FAULT` - When enabled, if the daemon encounters a fault (e.g. `SIGSEGV`),
it will log a backtrace to stdout, and to `daemon.log`. By default, this is disabled in it will log a backtrace to stdout, and to `daemon.log`. By default, this is disabled in
release-builds and enabled in debug-builds. Set variable to `1` or `0` to explicitly enable or release-builds and enabled in debug-builds. Set variable to `1` or `0` to explicitly enable or
disable this feature. Logging the backtrace cause heap allocation. Allocation is not signal safe, disable this feature. Logging the backtrace causes heap allocation. Allocation is not signal safe,
but here it runs in the signal handler. This in technically undefined behavior and therefore but here it runs in the signal handler. This is technically undefined behavior and therefore
disabled by default. This usually works, but enable at your own risk. disabled by default. This usually works, but enable at your own risk.
### Development builds only ### Development builds only
@ -262,7 +262,7 @@ launchctl load -w /Library/LaunchDaemons/net.mullvad.daemon.plist
## Tray icon on Linux ## Tray icon on Linux
The requirements for displaying a tray icon varies between different desktop environments. If the The requirements for displaying a tray icon vary between different desktop environments. If the
tray icon doesn't appear, try installing one of these packages: tray icon doesn't appear, try installing one of these packages:
- `libappindicator3-1` - `libappindicator3-1`
- `libappindicator1` - `libappindicator1`

View File

@ -45,7 +45,7 @@ private fun PreviewDeleteConfirmationDialogError() {
AppTheme { AppTheme {
NegativeConfirmationDialog( NegativeConfirmationDialog(
message = "Do you want to delete Cookie?", message = "Do you want to delete Cookie?",
errorMessage = "An error occured", errorMessage = "An error occurred",
onConfirm = {}, onConfirm = {},
onBack = {}, onBack = {},
) )

View File

@ -1,6 +1,6 @@
package net.mullvad.mullvadvpn.lib.model package net.mullvad.mullvadvpn.lib.model
// All suppported shadowsocks ciphers // All supported shadowsocks ciphers
enum class Cipher(val label: String) { enum class Cipher(val label: String) {
AES_128_CFB("aes-128-cfb"), AES_128_CFB("aes-128-cfb"),
AES_128_CFB1("aes-128-cfb1"), AES_128_CFB1("aes-128-cfb1"),

View File

@ -35,7 +35,7 @@ to them.
The script we use to automate part of the desktop app release process (`4-make-release`) uses The script we use to automate part of the desktop app release process (`4-make-release`) uses
`gpg --verify` to ensure that the installers it has fetched from Mullvad's internal release `gpg --verify` to ensure that the installers it has fetched from Mullvad's internal release
servers are not tampered with. servers are not tampered with.
Both the installer and the accompanying signature comes from the same server. Both the installer and the accompanying signature come from the same server.
The audit report claims that `gpg --verify` will succeed as long as the signature matches the data, The audit report claims that `gpg --verify` will succeed as long as the signature matches the data,
no matter which key produced the signature. This claim is not fully accurate according no matter which key produced the signature. This claim is not fully accurate according
@ -54,7 +54,7 @@ identified two potential risks here:
The manpage for `gpg` explicitly states that only using the exit code, like we do, for signature The manpage for `gpg` explicitly states that only using the exit code, like we do, for signature
validation is not appropriate. So Assured is correct in pointing out this behavior as risky. validation is not appropriate. So Assured is correct in pointing out this behavior as risky.
Both Assured and the manpage for `gpg` recommends `gpgv` as an alternative for usage in scripts. Both Assured and the manpage for `gpg` recommend `gpgv` as an alternative for usage in scripts.
However, even `gpgv` is a bit unclear about how it handles key servers and bundled pubkeys. However, even `gpgv` is a bit unclear about how it handles key servers and bundled pubkeys.
So instead we decided use [Sequoia] to verify the signatures, as it allows explicitly specifying So instead we decided use [Sequoia] to verify the signatures, as it allows explicitly specifying
what PGP pubkey to trust. It also does not require us to initialize any keyring, so it is simpler what PGP pubkey to trust. It also does not require us to initialize any keyring, so it is simpler
@ -83,7 +83,7 @@ The recommendation here is to deserialize `canon_json` and return that as the tr
A sidenote here is that the code was initially implemented according to the recommendation. A sidenote here is that the code was initially implemented according to the recommendation.
The code was changed to return `partial_data.signed` just before the audit. This change was The code was changed to return `partial_data.signed` just before the audit. This change was
a result of a pre-audit meeting between Mullvad and Assured where we probably missunderstood a result of a pre-audit meeting between Mullvad and Assured where we probably misunderstood
some of their early feedback on the metadata verification best practices. some of their early feedback on the metadata verification best practices.
We [changed the implementation back] to only use the verified data, as recommended. We [changed the implementation back] to only use the verified data, as recommended.
@ -97,7 +97,7 @@ We [changed the implementation back] to only use the verified data, as recommend
The macOS version of the installer downloader runs as the user who launched it. The program will The macOS version of the installer downloader runs as the user who launched it. The program will
save the downloaded installer to a temporary directory writable by the user. The installer save the downloaded installer to a temporary directory writable by the user. The installer
downloader will then verify the checksum of the file and launch it if it matches. This leaves downloader will then verify the checksum of the file and launch it if it matches. This leaves
a possible Time-of-Check, Time-of-Use (TOCTOU) attack vector. Any program running as the the same a possible Time-of-Check, Time-of-Use (TOCTOU) attack vector. Any program running as the same
user can replace the installer downloader between the time it was verified and it was launched. user can replace the installer downloader between the time it was verified and it was launched.
Causing the installer downloader to launch a potentially malicious installer. Causing the installer downloader to launch a potentially malicious installer.

View File

@ -14,7 +14,7 @@ performed on this app so far:
## Additional audits and certifications ## Additional audits and certifications
Apart from the biannual audits mentioned above, we've also conducted the the following: Apart from the biannual audits mentioned above, we've also conducted the following:
* [2025-02-24 - NCC Group Mobile Application Security Assessment (MASA) of the Android app](./2025-02-24-nccgroup-android-masa.md) * [2025-02-24 - NCC Group Mobile Application Security Assessment (MASA) of the Android app](./2025-02-24-nccgroup-android-masa.md)
* [2025-03-20 - Audit of the installer downloader by Assured](./2025-03-20-assured-installer-downloader.md) * [2025-03-20 - Audit of the installer downloader by Assured](./2025-03-20-assured-installer-downloader.md)

View File

@ -275,7 +275,7 @@ function featureUnavailableMessage() {
return sprintf( return sprintf(
messages.pgettext( messages.pgettext(
// TRANSLATORS: Informs the user that the the feature is only available when WireGuard // TRANSLATORS: Informs the user that the feature is only available when WireGuard
// TRANSLATORS: is selected. // TRANSLATORS: is selected.
// TRANSLATORS: Available placeholders: // TRANSLATORS: Available placeholders:
// TRANSLATORS: %(wireguard)s - will be replaced with WireGuard // TRANSLATORS: %(wireguard)s - will be replaced with WireGuard

View File

@ -111,7 +111,7 @@ function featureUnavailableMessage() {
return sprintf( return sprintf(
messages.pgettext( messages.pgettext(
// TRANSLATORS: Informs the user that the the feature is only available when WireGuard // TRANSLATORS: Informs the user that the feature is only available when WireGuard
// TRANSLATORS: is selected. // TRANSLATORS: is selected.
// TRANSLATORS: Available placeholders: // TRANSLATORS: Available placeholders:
// TRANSLATORS: %(wireguard)s - will be replaced with WireGuard // TRANSLATORS: %(wireguard)s - will be replaced with WireGuard

View File

@ -143,7 +143,7 @@ function InputWithRef(props: IInputProps, forwardedRef: React.Ref<HTMLInputEleme
} }
}); });
// If the the initialValue changes in the uncontrolled mode when the user isn't currently writing, // If the initialValue changes in the uncontrolled mode when the user isn't currently writing,
// then we want to update the value. // then we want to update the value.
useEffect(() => { useEffect(() => {
handleInitialValueChange(props.initialValue); handleInitialValueChange(props.initialValue);

View File

@ -130,7 +130,7 @@ A high-level overview of the tunnel state machine can be seen in the diagram bel
#### State machine inputs #### State machine inputs
There are two types of inputs that the tunnel state machine react to. The first one is commands sent There are two types of inputs that the tunnel state machine reacts to. The first one is commands sent
to the state machine, and the second is external events that the state machine listens to. Reacting to the state machine, and the second is external events that the state machine listens to. Reacting
to any event can result in the state machine transitioning away to a different state. to any event can result in the state machine transitioning away to a different state.
@ -246,7 +246,7 @@ on Linux.
#### macOS #### macOS
On macOS, the offline monitor uses `route -n monitor -` to listen for changes in the routing table, On macOS, the offline monitor uses `route -n monitor -` to listen for changes in the routing table,
reasserting that a default route exists any time a change is detected. It's only assumed that the reasserting that a default route exists any time a change is detected. It's only assumed that the
host is offline if a default route doesn't exist. host is offline if a default route doesn't exist.
@ -261,7 +261,7 @@ needed for routing tunnel traffic.
#### Android #### Android
To detect connectivity on Android, the app relies on [`ConnectivityManager`] by listening for To detect connectivity on Android, the app relies on [`ConnectivityManager`] by listening for
changes to the availability of non-VPN networks that provide internet connectivity. Connectivity changes to the availability of non-VPN networks that provide internet connectivity. Connectivity
is inferred if such a network exists. is inferred if such a network exists.
#### iOS #### iOS

View File

@ -11,7 +11,7 @@ decided to not address for some reason. Some example reasons why issues might en
provide a mitigation for provide a mitigation for
* The only known fixes for the issue comes with other drawbacks, that we consider as bad, or worse * The only known fixes for the issue comes with other drawbacks, that we consider as bad, or worse
than the original issue than the original issue
* We are not able to reliably reproduce the issue. Enough anecdotal evidence exist to indicate * We are not able to reliably reproduce the issue. Enough anecdotal evidence exists to indicate
the issue is real, but Mullvad is unable to reproduce it. As a result, it is really hard to fix. the issue is real, but Mullvad is unable to reproduce it. As a result, it is really hard to fix.
This document should only contain issues related to security and privacy. This document is a This document should only contain issues related to security and privacy. This document is a

View File

@ -26,7 +26,7 @@ struct Socks5Handshake {
// Append socks version // Append socks version
data.append(Socks5Constants.socksVersion) data.append(Socks5Constants.socksVersion)
// Append number of suppported authentication methods supported. // Append number of supported authentication methods supported.
data.append(UInt8(methods.count)) data.append(UInt8(methods.count))
// Append authentication methods // Append authentication methods

View File

@ -154,7 +154,7 @@ class MullvadApiTests: XCTestCase {
UInt(expectedResponseCode), UInt(expectedResponseCode),
""" """
{"code": "\(expectedErrorCode)", {"code": "\(expectedErrorCode)",
"error": "A magical error occured" "error": "A magical error occurred"
} }
""" """
) )

View File

@ -35,7 +35,7 @@ public struct MigrationManager {
/// and writes back to `store` when settings are updated. /// and writes back to `store` when settings are updated.
/// ///
/// In order to avoid migration happening from both the VPN and the host processes at the same time, /// In order to avoid migration happening from both the VPN and the host processes at the same time,
/// a non existant file path is used as a lock to synchronize access between the processes. /// a non existent file path is used as a lock to synchronize access between the processes.
/// This file is accessed by `NSFileCoordinator` in order to prevent multiple processes accessing at the same time. /// This file is accessed by `NSFileCoordinator` in order to prevent multiple processes accessing at the same time.
/// - Parameters: /// - Parameters:
/// - store: The store to from which settings are read and written to. /// - store: The store to from which settings are read and written to.

View File

@ -133,7 +133,7 @@ final class StorePaymentManager: NSObject, SKPaymentTransactionObserver, @unchec
/// Validates the user account with backend before adding the payment to the queue. /// Validates the user account with backend before adding the payment to the queue.
/// ///
/// - Parameters: /// - Parameters:
/// - payment: an intance of `SKPayment`. /// - payment: an instance of `SKPayment`.
/// - accountNumber: the account number to credit. /// - accountNumber: the account number to credit.
func addPayment(_ payment: SKPayment, for accountNumber: String) { func addPayment(_ payment: SKPayment, for accountNumber: String) {
logger.debug("Validating account before the purchase.") logger.debug("Validating account before the purchase.")

View File

@ -68,12 +68,12 @@ extension LocationCellViewModel {
We check this by doing the following, in order: We check this by doing the following, in order:
1. Count hostnames in the tree. More than one means that there are other locations than 1. Count hostnames in the tree. More than one means that there are other locations than
the excluded one for the relay selector to choose from. No exlusion. the excluded one for the relay selector to choose from. No exclusion.
2. Count hostnames in the excluded node. More than one means that there are multiple 2. Count hostnames in the excluded node. More than one means that there are multiple
locations for the relay selector to choose from. No exclusion. locations for the relay selector to choose from. No exclusion.
3. Check existance of a location in the tree that matches the currently excluded location. 3. Check existence of a location in the tree that matches the currently excluded location.
No match means no exclusion. No match means no exclusion.
*/ */
func shouldExcludeLocation(_ excludedLocation: LocationCellViewModel?) -> Bool { func shouldExcludeLocation(_ excludedLocation: LocationCellViewModel?) -> Bool {
@ -87,7 +87,7 @@ extension LocationCellViewModel {
if case .hostname = location { true } else { false } if case .hostname = location { true } else { false }
}.count }.count
// If the there's more than one selectable relay in the current node we don't need // If there's more than one selectable relay in the current node we don't need
// to show this in the location tree and can return early. // to show this in the location tree and can return early.
guard hostCount == 1 else { return false } guard hostCount == 1 else { return false }
@ -97,7 +97,7 @@ extension LocationCellViewModel {
if case .hostname = location { true } else { false } if case .hostname = location { true } else { false }
}.count }.count
// If the there's more than one selectable relay in the excluded node we don't need // If there's more than one selectable relay in the excluded node we don't need
// to show this in the location tree and can return early. // to show this in the location tree and can return early.
guard excludedHostCount == 1 else { return false } guard excludedHostCount == 1 else { return false }

View File

@ -20,7 +20,7 @@ import WireGuardKitTypes
tunnel process. tunnel process.
Packet tunnel runs this operation immediately as it starts, with `rotateImmediatelyOnKeyMismatch` flag set to Packet tunnel runs this operation immediately as it starts, with `rotateImmediatelyOnKeyMismatch` flag set to
`true` which forces key rotation to happpen immediately given that the key stored on server does not match the key `true` which forces key rotation to happen immediately given that the key stored on server does not match the key
stored on device. Unless the last rotation attempt took place less than 15 seconds ago in which case the key rotation stored on device. Unless the last rotation attempt took place less than 15 seconds ago in which case the key rotation
is not performed. is not performed.

View File

@ -25,9 +25,9 @@ struct KeyExchangingResultStub: EphemeralPeerReceiving {
public func receiveEphemeralPeerPrivateKey( public func receiveEphemeralPeerPrivateKey(
_ ephemeralPeerPrivateKey: PrivateKey, _ ephemeralPeerPrivateKey: PrivateKey,
daitaParameters daitaParamters: MullvadTypes.DaitaV2Parameters? daitaParameters daitaParameters: MullvadTypes.DaitaV2Parameters?
) async { ) async {
await onReceiveEphemeralPeerPrivateKey?(ephemeralPeerPrivateKey, daitaParamters) await onReceiveEphemeralPeerPrivateKey?(ephemeralPeerPrivateKey, daitaParameters)
} }
func ephemeralPeerExchangeFailed() { func ephemeralPeerExchangeFailed() {

View File

@ -75,7 +75,7 @@ enum Cli {
Relay(relay::Relay), Relay(relay::Relay),
/// Manage Mullvad API access methods. /// Manage Mullvad API access methods.
/// ///
/// Access methods are used to connect to the the Mullvad API via one of /// Access methods are used to connect to the Mullvad API via one of
/// Mullvad's bridge servers or a custom proxy (SOCKS5 & Shadowsocks) when /// Mullvad's bridge servers or a custom proxy (SOCKS5 & Shadowsocks) when
/// and where establishing a direct connection does not work. /// and where establishing a direct connection does not work.
/// ///

View File

@ -13,9 +13,9 @@ pub enum Error {
/// Can not find access method /// Can not find access method
#[error("Cannot find custom access method {0}")] #[error("Cannot find custom access method {0}")]
NoSuchMethod(access_method::Id), NoSuchMethod(access_method::Id),
/// Some error occured in the daemon's state of handling /// Some error occurred in the daemon's state of handling
/// [`AccessMethodSetting`]s & [`ApiConnectionMode`]s /// [`AccessMethodSetting`]s & [`ApiConnectionMode`]s
#[error("Error occured when handling connection settings & details")] #[error("Error occurred when handling connection settings & details")]
ApiService(#[from] access_mode::Error), ApiService(#[from] access_mode::Error),
/// A REST request failed /// A REST request failed
#[error("Reset request failed")] #[error("Reset request failed")]

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# #
# Find and print all remote branches not commited to in over two months. # Find and print all remote branches not committed to in over two months.
# Prints grouped by commiter email. Used to detect stale branches that # Prints grouped by committer email. Used to detect stale branches that
# could potentially be removed. # could potentially be removed.
TWO_MONTHS=$((60 * 60 * 24 * 60)) TWO_MONTHS=$((60 * 60 * 24 * 60))

View File

@ -31,7 +31,7 @@ pub use imp::{
pub use imp::{Error, RouteManagerHandle}; pub use imp::{Error, RouteManagerHandle};
/// Link-layer/MAC adress /// Link-layer/MAC address
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
#[derive(Debug, Eq, PartialEq, Clone, Copy)] #[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct MacAddress(pub [u8; 6]); pub struct MacAddress(pub [u8; 6]);

View File

@ -92,7 +92,7 @@ impl DefaultRouteMonitor {
} }
fn handle_events(&mut self, events: Vec<InterfaceEvent>) { fn handle_events(&mut self, events: Vec<InterfaceEvent>) {
// Split events by address family and handle them seperately. // Split events by address family and handle them separately.
let mut ipv4_events = vec![]; let mut ipv4_events = vec![];
let mut ipv6_events = vec![]; let mut ipv6_events = vec![];
for event in events { for event in events {

View File

@ -48,7 +48,7 @@ pub enum Error {
WireguardNetlinkInterfaceUnavailable, WireguardNetlinkInterfaceUnavailable,
#[error("Unknown WireGuard command: {0}")] #[error("Unknown WireGuard command: {0}")]
UnnkownWireguardCommmand(u8), UnknownWireguardCommand(u8),
#[error("Received no response")] #[error("Received no response")]
NoResponse, NoResponse,

View File

@ -140,7 +140,7 @@ impl DeviceMessage {
if cmd == WG_CMD_GET_DEVICE || cmd == WG_CMD_SET_DEVICE { if cmd == WG_CMD_GET_DEVICE || cmd == WG_CMD_SET_DEVICE {
Ok(cmd) Ok(cmd)
} else { } else {
Err(Error::UnnkownWireguardCommmand(cmd)) Err(Error::UnknownWireguardCommand(cmd))
} }
} }
} }

View File

@ -36,7 +36,7 @@ pub struct TestConfig {
pub host_bridge_name: String, pub host_bridge_name: String,
pub host_bridge_ip: Ipv4Addr, pub host_bridge_ip: Ipv4Addr,
pub os: Os, pub os: Os,
/// The OpenVPN CA certificate to use with the the installed Mullvad App. /// The OpenVPN CA certificate to use with the installed Mullvad App.
pub openvpn_certificate: OpenVPNCertificate, pub openvpn_certificate: OpenVPNCertificate,
} }

View File

@ -354,7 +354,7 @@ pub async fn test_installation_idempotency(
tokio::time::sleep(delay).await; tokio::time::sleep(delay).await;
} }
} }
// Make sure that no network leak occured during any installation process. // Make sure that no network leak occurred during any installation process.
let guest_ip = pinger.guest_ip; let guest_ip = pinger.guest_ip;
let monitor_result = pinger.stop().await.unwrap(); let monitor_result = pinger.stop().await.unwrap();
assert_eq!( assert_eq!(

View File

@ -60,7 +60,7 @@ pub enum Error {
#[error("The daemon returned an error: {0}")] #[error("The daemon returned an error: {0}")]
Daemon(String), Daemon(String),
#[error("The daemon ended up in the the wrong tunnel-state: {0:?}")] #[error("The daemon ended up in the wrong tunnel-state: {0:?}")]
UnexpectedTunnelState(Box<mullvad_types::states::TunnelState>), UnexpectedTunnelState(Box<mullvad_types::states::TunnelState>),
#[error("The daemon ended up in the error state: {0:?}")] #[error("The daemon ended up in the error state: {0:?}")]

View File

@ -410,7 +410,7 @@ impl EnvVar {
let pre = input.next().ok_or(error)?; let pre = input.next().ok_or(error)?;
match pre { match pre {
"Environment" => { "Environment" => {
// Proccess the input just a bit more - remove the leading and trailing quote ("). // Process the input just a bit more - remove the leading and trailing quote (").
let var = input let var = input
.next() .next()
.ok_or(error)? .ok_or(error)?

View File

@ -77,7 +77,7 @@ impl Tunnel {
/// for the tunnel device and logging. For targets other than android, this also takes an MTU /// for the tunnel device and logging. For targets other than android, this also takes an MTU
/// value. /// value.
/// ///
/// The `logging_callback` let's you provide a Rust function that receives any logging output /// The `logging_callback` lets you provide a Rust function that receives any logging output
/// from wireguard-go. `logging_context` is a value that will be passed to each invocation of /// from wireguard-go. `logging_context` is a value that will be passed to each invocation of
/// `logging_callback`. /// `logging_callback`.
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -88,7 +88,7 @@ impl Tunnel {
logging_callback: Option<LoggingCallback>, logging_callback: Option<LoggingCallback>,
logging_context: LoggingContext, logging_context: LoggingContext,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
// SAFETY: pointer is valid for the the lifetime of this function // SAFETY: pointer is valid for the lifetime of this function
let code = unsafe { let code = unsafe {
ffi::wgTurnOn( ffi::wgTurnOn(
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
@ -122,7 +122,7 @@ impl Tunnel {
let mut assigned_name = [0u8; 128]; let mut assigned_name = [0u8; 128];
let mut luid = MaybeUninit::uninit(); let mut luid = MaybeUninit::uninit();
// SAFETY: pointers are valid for the the lifetime of this function // SAFETY: pointers are valid for the lifetime of this function
let code = unsafe { let code = unsafe {
ffi::wgTurnOn( ffi::wgTurnOn(
interface_name.as_ptr(), interface_name.as_ptr(),
@ -144,7 +144,7 @@ impl Tunnel {
Ok(Tunnel { Ok(Tunnel {
handle: code, handle: code,
assigned_name: assigned_name.to_owned(), assigned_name: assigned_name.to_owned(),
// SAFETY: wgTurnOn succeeded and the LUID is guaranteed to be intialized by wgTurnOn // SAFETY: wgTurnOn succeeded and the LUID is guaranteed to be initialized by wgTurnOn
luid: unsafe { luid.assume_init() }, luid: unsafe { luid.assume_init() },
}) })
} }
@ -173,7 +173,7 @@ impl Tunnel {
/// Special function for android multihop since that behavior is different from desktop /// Special function for android multihop since that behavior is different from desktop
/// and android non-multihop. /// and android non-multihop.
/// ///
/// The `logging_callback` let's you provide a Rust function that receives any logging output /// The `logging_callback` lets you provide a Rust function that receives any logging output
/// from wireguard-go. `logging_context` is a value that will be passed to each invocation of /// from wireguard-go. `logging_context` is a value that will be passed to each invocation of
/// `logging_callback`. /// `logging_callback`.
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
@ -185,7 +185,7 @@ impl Tunnel {
logging_callback: Option<LoggingCallback>, logging_callback: Option<LoggingCallback>,
logging_context: LoggingContext, logging_context: LoggingContext,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
// SAFETY: pointer is valid for the the lifetime of this function // SAFETY: pointer is valid for the lifetime of this function
let code = unsafe { let code = unsafe {
ffi::wgTurnOnMultihop( ffi::wgTurnOnMultihop(
exit_settings.as_ptr(), exit_settings.as_ptr(),