diff options
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | installer-downloader/Cargo.toml | 1 | ||||
| -rw-r--r-- | installer-downloader/src/controller.rs | 15 | ||||
| -rw-r--r-- | talpid-platform-metadata/Cargo.toml | 1 | ||||
| -rw-r--r-- | talpid-platform-metadata/src/arch.rs | 58 | ||||
| -rw-r--r-- | talpid-platform-metadata/src/lib.rs | 4 |
6 files changed, 78 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock index d2eb110f8f..4205eb9adc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2033,6 +2033,7 @@ dependencies = [ "rand 0.8.5", "reqwest", "serde", + "talpid-platform-metadata", "tokio", "windows-sys 0.52.0", "winres", diff --git a/installer-downloader/Cargo.toml b/installer-downloader/Cargo.toml index 80b7450b7c..a468abb8cb 100644 --- a/installer-downloader/Cargo.toml +++ b/installer-downloader/Cargo.toml @@ -28,6 +28,7 @@ chrono = { workspace = true, features = ["clock"] } fern = { version = "0.6", default-features = false } log = { workspace = true } +talpid-platform-metadata = { path = "../talpid-platform-metadata" } mullvad-update = { path = "../mullvad-update", features = ["client"] } [target.'cfg(target_os = "windows")'.dependencies] diff --git a/installer-downloader/src/controller.rs b/installer-downloader/src/controller.rs index 2f8f228d83..ff02b3cd0c 100644 --- a/installer-downloader/src/controller.rs +++ b/installer-downloader/src/controller.rs @@ -129,10 +129,12 @@ async fn fetch_app_version_info<Delegate, VersionProvider>( Delegate: AppDelegate + 'static, VersionProvider: VersionInfoProvider + Send, { + // TODO: Do not unwrap + // TODO: Construct a proper error instead + let architecture = get_arch().unwrap().unwrap(); loop { let version_params = VersionParameters { - // TODO: detect current architecture - architecture: VersionArchitecture::X86, + architecture, // For the downloader, the rollout version is always preferred rollout: 1., // The downloader allows any version @@ -410,3 +412,12 @@ fn select_cdn_url(urls: &[String]) -> Option<&str> { fn format_latest_version(version: &Version) -> String { format!("{}: {}", resource::LATEST_VERSION_PREFIX, version.version) } + +/// Try to map the host's CPU architecture to one of the CPU architectures the Mullvad VPN app +/// supports. +fn get_arch() -> Result<Option<VersionArchitecture>, std::io::Error> { + match talpid_platform_metadata::get_native_arch()?? { + talpid_platform_metadata::Architecture::X86 => VersionArchitecture::X86, + talpid_platform_metadata::Architecture::Arm64 => VersionArchitecture::Arm64, + } +} diff --git a/talpid-platform-metadata/Cargo.toml b/talpid-platform-metadata/Cargo.toml index d82479c0c4..9eb58f4a55 100644 --- a/talpid-platform-metadata/Cargo.toml +++ b/talpid-platform-metadata/Cargo.toml @@ -25,4 +25,5 @@ features = [ "Win32_System_LibraryLoader", "Win32_System_SystemInformation", "Win32_System_SystemServices", + "Win32_System_Threading", ] diff --git a/talpid-platform-metadata/src/arch.rs b/talpid-platform-metadata/src/arch.rs new file mode 100644 index 0000000000..1f6de901cd --- /dev/null +++ b/talpid-platform-metadata/src/arch.rs @@ -0,0 +1,58 @@ +//! Detect the running platform's CPU architecture. + +/// CPU architectures supported by the talpid family of crates. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Architecture { + /// x86-64 architecture + X86, + /// ARM64 architecture + Arm64, +} + +/// Return native architecture (ignoring WOW64). If the native architecture can not be detected, +/// [`None`] is returned. This should never be the case on working X86_64 or Arm64 systems. +#[cfg(target_os = "windows")] +pub fn get_native_arch() -> Result<Option<Architecture>, std::io::Error> { + use core::ffi::c_ushort; + use windows_sys::Win32::System::SystemInformation::{ + IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_ARM64, + }; + use windows_sys::Win32::System::Threading::{GetCurrentProcess, IsWow64Process2}; + + let native_arch = { + let mut running_arch: c_ushort = 0; + let mut native_arch: c_ushort = 0; + + // SAFETY: Trivially safe. The current process handle is a glorified constant. + let current_process = unsafe { GetCurrentProcess() }; + + // IsWow64Process2: + // Determines whether the specified process is running under WOW64; also returns additional machine process and architecture information. + // + // SAFETY: Trivially safe, since we provide the required arguments. + if 0 == unsafe { IsWow64Process2(current_process, &mut running_arch, &mut native_arch) } { + return Err(std::io::Error::last_os_error()); + } + + native_arch + }; + + match native_arch { + IMAGE_FILE_MACHINE_AMD64 => Ok(Some(Architecture::X86)), + IMAGE_FILE_MACHINE_ARM64 => Ok(Some(Architecture::Arm64)), + _other => Ok(None), + } +} + +/// Return native architecture. +#[cfg(not(target_os = "windows"))] +pub fn get_native_arch() -> Result<Option<Architecture>, std::io::Error> { + const TARGET_ARCH: Option<Architecture> = if cfg!(any(target_arch = "x86_64",)) { + Some(Architecture::X86) + } else if cfg!(target_arch = "aarch64") { + Some(Architecture::Arm64) + } else { + None + }; + Ok(TARGET_ARCH) +} diff --git a/talpid-platform-metadata/src/lib.rs b/talpid-platform-metadata/src/lib.rs index 7a11c97f18..98640fabef 100644 --- a/talpid-platform-metadata/src/lib.rs +++ b/talpid-platform-metadata/src/lib.rs @@ -1,3 +1,4 @@ +mod arch; #[cfg(target_os = "linux")] #[path = "linux.rs"] mod imp; @@ -19,3 +20,6 @@ pub use self::imp::MacosVersion; #[cfg(windows)] pub use self::imp::WindowsVersion; pub use self::imp::{extra_metadata, short_version, version}; + +pub use arch::get_native_arch; +pub use arch::Architecture; |
