diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-11-19 01:37:02 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-11-19 01:37:02 +0100 |
| commit | b72f29cd885c2e9c02b27f72cd93683aba253e8d (patch) | |
| tree | 2ae9c173dd125573d34f0d0eb1e8638110390fe5 | |
| parent | e3f66f7dc55fb68efbb605b21aa66336ea653c7a (diff) | |
| parent | 2c6cd3a4797821984e1c212803890276b0ef3626 (diff) | |
| download | mullvadvpn-b72f29cd885c2e9c02b27f72cd93683aba253e8d.tar.xz mullvadvpn-b72f29cd885c2e9c02b27f72cd93683aba253e8d.zip | |
Merge branch 'update-api-ip-cache'
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | android/build.gradle | 1 | ||||
| -rwxr-xr-x | build.sh | 1 | ||||
| -rw-r--r-- | dist-assets/linux/before-install.sh | 1 | ||||
| -rwxr-xr-x | dist-assets/pkg-scripts/preinstall | 5 | ||||
| -rw-r--r-- | dist-assets/windows/installer.nsh | 35 | ||||
| -rw-r--r-- | gui/tasks/distribution.js | 1 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 5 | ||||
| -rw-r--r-- | mullvad-problem-report/src/lib.rs | 7 | ||||
| -rw-r--r-- | mullvad-rpc/Cargo.toml | 4 | ||||
| -rw-r--r-- | mullvad-rpc/src/address_cache.rs | 124 | ||||
| -rw-r--r-- | mullvad-rpc/src/bin/address_cache.rs | 39 | ||||
| -rw-r--r-- | mullvad-rpc/src/lib.rs | 46 | ||||
| -rw-r--r-- | mullvad-setup/src/main.rs | 23 | ||||
| -rwxr-xr-x | update-api-address.sh | 6 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/cleanup/cleaningops.cpp | 14 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/cleanup/cleaningops.h | 1 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/cleanup/cleanup.cpp | 31 | ||||
| -rw-r--r-- | windows/nsis-plugins/src/cleanup/cleanup.def | 1 |
21 files changed, 283 insertions, 66 deletions
diff --git a/.gitignore b/.gitignore index 9db2f0d726..3cbba48396 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ .DS_Store *.log /dist-assets/relays.json +/dist-assets/api-ip-address.txt /dist-assets/mullvad /dist-assets/mullvad.exe /dist-assets/mullvad-daemon diff --git a/CHANGELOG.md b/CHANGELOG.md index 6706c48985..c7bcd6ad37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ Line wrap the file at 100 chars. Th ### Changed - Use the API to fetch API IP addresses instead of DNS. - Remove WireGuard keys during uninstallation after the firewall is unlocked. +- Randomly select addresses to use for communicating with the API. +- Bundle a list of API addresses to use instead of assuming that the primary address can be reached. #### Android - Remove the Quit button. diff --git a/Cargo.lock b/Cargo.lock index 2819952a10..0d7cbadde1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1385,6 +1385,7 @@ dependencies = [ "ipnetwork", "log 0.4.11", "mullvad-types", + "rand", "regex", "serde", "serde_json", diff --git a/android/build.gradle b/android/build.gradle index e9307b1df6..9bfb4d23c3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -108,5 +108,6 @@ buildscript { task copyExtraAssets(type: Copy) { from "$repoRootPath/dist-assets" include "relays.json" + include "api-ip-address.txt" into extraAssetsDirectory } @@ -210,6 +210,7 @@ fi ./update-relays.sh +./update-api-address.sh pushd "$SCRIPT_DIR/gui" diff --git a/dist-assets/linux/before-install.sh b/dist-assets/linux/before-install.sh index fc27f787ae..d3f53a1f40 100644 --- a/dist-assets/linux/before-install.sh +++ b/dist-assets/linux/before-install.sh @@ -12,3 +12,4 @@ fi pkill -x "mullvad-gui" || true rm -f /var/cache/mullvad-vpn/relays.json +rm -f /var/cache/mullvad-vpn/api-ip-address.txt diff --git a/dist-assets/pkg-scripts/preinstall b/dist-assets/pkg-scripts/preinstall index e03ca867a8..5b56185a58 100755 --- a/dist-assets/pkg-scripts/preinstall +++ b/dist-assets/pkg-scripts/preinstall @@ -77,9 +77,10 @@ if [ -d "$OLD_CACHE_DIR" ]; then rm -rf "$OLD_CACHE_DIR" fi -# Remove the existing relay list. -# There is a risk that it's incompatible with the format this version wants +# Remove the existing relay and API address cache lists. +# There is a risk that they're incompatible with the format this version wants rm "$NEW_CACHE_DIR/relays.json" || true +rm "$NEW_CACHE_DIR/api-ip-address.txt" || true # Notify the running daemon that we are going to kill it and replace it with a newer version. # This will make the daemon save it's state to a file and then lock the firewall to prevent diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh index a8925cd039..93f62f9703 100644 --- a/dist-assets/windows/installer.nsh +++ b/dist-assets/windows/installer.nsh @@ -510,6 +510,40 @@ !define RemoveRelayCache '!insertmacro "RemoveRelayCache"' # +# RemoveApiAddressCache +# +# Call into helper DLL instructing it to remove all API address cache. +# Currently, errors are only logged and not propagated. +# +!macro RemoveApiAddressCache + + log::Log "RemoveApiAddressCache()" + + Push $0 + Push $1 + + cleanup::RemoveApiAddressCache + + Pop $0 + Pop $1 + + ${If} $0 != ${MULLVAD_SUCCESS} + log::Log "Failed to remove address cache: $1" + Goto RemoveApiAddressCache_return + ${EndIf} + + log::Log "RemoveApiAddressCache() completed successfully" + + RemoveApiAddressCache_return: + + Pop $1 + Pop $0 + +!macroend + +!define RemoveApiAddressCache '!insertmacro "RemoveApiAddressCache"' + +# # AddCLIToEnvironPath # # Add "$INSTDIR\resources" to system env PATH, @@ -703,6 +737,7 @@ RMDir /r "$LOCALAPPDATA\mullvad-vpn-updater" ${RemoveRelayCache} + ${RemoveApiAddressCache} ${ExtractTapDriver} ${InstallTapDriver} diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js index 56fe2d4318..0623c0b660 100644 --- a/gui/tasks/distribution.js +++ b/gui/tasks/distribution.js @@ -23,6 +23,7 @@ const config = { extraResources: [ { from: distAssets('ca.crt'), to: '.' }, { from: distAssets('relays.json'), to: '.' }, + { from: distAssets('api-ip-address.txt'), to: '.' }, { from: root('CHANGELOG.md'), to: '.' }, ], diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 0599cb052a..b4e5dd3279 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -494,9 +494,10 @@ where let (tunnel_state_machine_shutdown_tx, tunnel_state_machine_shutdown_signal) = oneshot::channel(); - let mut rpc_runtime = mullvad_rpc::MullvadRpcRuntime::with_cache_dir( + let mut rpc_runtime = mullvad_rpc::MullvadRpcRuntime::with_cache( tokio::runtime::Handle::current(), - &cache_dir, + &resource_dir, + Some(&cache_dir), ) .await .map_err(Error::InitRpcFactory)?; diff --git a/mullvad-problem-report/src/lib.rs b/mullvad-problem-report/src/lib.rs index 1c3fa00461..eac0dd4638 100644 --- a/mullvad-problem-report/src/lib.rs +++ b/mullvad-problem-report/src/lib.rs @@ -271,7 +271,12 @@ pub fn send_problem_report( .build() .map_err(Error::CreateRuntime)?; - let mut rpc_manager = mullvad_rpc::MullvadRpcRuntime::new(runtime.handle().clone()) + let mut rpc_manager = runtime + .block_on(mullvad_rpc::MullvadRpcRuntime::with_cache( + runtime.handle().clone(), + &mullvad_paths::get_resource_dir(), + None, + )) .map_err(Error::CreateRpcClientError)?; let rpc_client = mullvad_rpc::ProblemReportProxy::new(rpc_manager.mullvad_rest_handle()); diff --git a/mullvad-rpc/Cargo.toml b/mullvad-rpc/Cargo.toml index a5acd75be4..cf27d2e287 100644 --- a/mullvad-rpc/Cargo.toml +++ b/mullvad-rpc/Cargo.toml @@ -15,6 +15,7 @@ http = "0.2" hyper = "0.13" ipnetwork = "0.16" log = "0.4" +rand = "0.7" regex = "1" serde = "1" serde_json = "1.0" @@ -33,3 +34,6 @@ tempfile = "3.0" [[bin]] name = "relay_list" + +[[bin]] +name = "address_cache" diff --git a/mullvad-rpc/src/address_cache.rs b/mullvad-rpc/src/address_cache.rs index 7c1859173e..b2181c763b 100644 --- a/mullvad-rpc/src/address_cache.rs +++ b/mullvad-rpc/src/address_cache.rs @@ -1,6 +1,8 @@ +use super::API_ADDRESS; +use rand::seq::SliceRandom; use std::{ io, - net::{IpAddr, SocketAddr}, + net::SocketAddr, path::Path, sync::{Arc, Mutex}, }; @@ -9,7 +11,18 @@ use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, }; -const FALLBACK_API_ADDRESS: (IpAddr, u16) = (crate::API_IP, 443); +#[derive(err_derive::Error, Debug)] +#[error(no_from)] +pub enum Error { + #[error(display = "Failed to open the address cache file")] + OpenAddressCache(#[error(source)] io::Error), + + #[error(display = "Failed to read the address cache file")] + ReadAddressCache(#[error(source)] io::Error), + + #[error(display = "The address cache is empty")] + EmptyAddressCache, +} #[derive(Clone)] pub struct AddressCache { @@ -18,20 +31,24 @@ pub struct AddressCache { } impl AddressCache { - pub fn new() -> Self { - Self { - inner: Arc::new(Mutex::new(Default::default())), - cache_path: None, - } + /// Initialize cache using the given list, and write changes to `cache_path`. + pub fn new(addresses: Vec<SocketAddr>, cache_path: Option<Box<Path>>) -> Result<Self, Error> { + log::trace!("API address cache: {:?}", addresses); + + let cache = AddressCacheInner::from_addresses(addresses)?; + log::debug!("Using API address: {:?}", Self::get_address_inner(&cache)); + + let address_cache = Self { + inner: Arc::new(Mutex::new(cache)), + cache_path: cache_path.map(|cache| Arc::from(cache)), + }; + Ok(address_cache) } - pub async fn with_cache(cache_path: Box<Path>) -> Self { - let cache = AddressCacheInner::from_cache_file(&cache_path) - .await - .unwrap_or_default(); - let inner = Arc::new(Mutex::new(cache)); - let cache_path = Some(cache_path.into()); - Self { inner, cache_path } + /// Initialize cache using `read_path`, and write changes to `cache_path`. + pub async fn from_file(read_path: &Path, cache_path: Option<Box<Path>>) -> Result<Self, Error> { + log::debug!("Loading API addresses from {:?}", read_path); + Self::new(read_address_file(read_path).await?, cache_path) } pub fn get_address(&self) -> SocketAddr { @@ -43,12 +60,12 @@ impl AddressCache { fn get_address_inner(inner: &AddressCacheInner) -> SocketAddr { if inner.addresses.is_empty() { - return FALLBACK_API_ADDRESS.into(); + return API_ADDRESS.into(); } *inner .addresses .get(inner.choice % inner.addresses.len()) - .unwrap_or(&FALLBACK_API_ADDRESS.into()) + .unwrap_or(&API_ADDRESS.into()) } pub fn register_failure(&self, failed_addr: SocketAddr, err: &dyn std::error::Error) { @@ -62,16 +79,26 @@ impl AddressCache { .map(|last_try| last_try == inner.choice) .unwrap_or(false) { - log::error!("HTTP request failed: {}, will try next API address", err); inner.choice = inner.choice.wrapping_add(1); + let new_address = Self::get_address_inner(&inner); + log::error!( + "HTTP request failed: {}, using address {}. Trying next API address: {}", + err, + failed_addr, + new_address + ); } } - pub async fn set_addresses(&self, addresses: Vec<SocketAddr>) -> io::Result<()> { + pub async fn set_addresses(&self, mut addresses: Vec<SocketAddr>) -> io::Result<()> { let should_update = { let mut inner = self.inner.lock().unwrap(); - if addresses != inner.addresses { + addresses.sort(); + let mut current_sorted = inner.addresses.clone(); + current_sorted.sort(); + if addresses != current_sorted { inner.addresses = addresses.clone(); + inner.shuffle(); inner.choice = 0; true } else { @@ -79,6 +106,7 @@ impl AddressCache { } }; if should_update { + log::trace!("API address cache: {:?}", addresses); self.save_to_disk(addresses).await?; } Ok(()) @@ -120,37 +148,43 @@ struct AddressCacheInner { } impl AddressCacheInner { - async fn from_cache_file(path: &Path) -> io::Result<Self> { - let file = fs::File::open(path).await?; - let mut lines = BufReader::new(file).lines(); - let mut addresses = vec![]; - while let Some(line) = lines.next_line().await? { - // for line in lines.next_line() { - match line.trim().parse() { - Ok(address) => addresses.push(address), - Err(err) => { - log::error!("Failed to parse cached address line: {}", err); - } - } - } - - if !addresses.contains(&FALLBACK_API_ADDRESS.into()) { - addresses.push(FALLBACK_API_ADDRESS.into()); + fn from_addresses(addresses: Vec<SocketAddr>) -> Result<Self, Error> { + if addresses.is_empty() { + return Err(Error::EmptyAddressCache); } - - Ok(Self { + let mut cache = Self { addresses, - ..Default::default() - }) + choice: 0, + last_try: None, + }; + cache.shuffle(); + Ok(cache) + } + + fn shuffle(&mut self) { + let mut rng = rand::thread_rng(); + (&mut self.addresses[..]).shuffle(&mut rng); } } -impl Default for AddressCacheInner { - fn default() -> Self { - Self { - addresses: vec![FALLBACK_API_ADDRESS.into()], - choice: 0, - last_try: None, +async fn read_address_file(path: &Path) -> Result<Vec<SocketAddr>, Error> { + let file = fs::File::open(path) + .await + .map_err(|error| Error::OpenAddressCache(error))?; + let mut lines = BufReader::new(file).lines(); + let mut addresses = vec![]; + while let Some(line) = lines + .next_line() + .await + .map_err(|error| Error::ReadAddressCache(error))? + { + // for line in lines.next_line() { + match line.trim().parse() { + Ok(address) => addresses.push(address), + Err(err) => { + log::error!("Failed to parse cached address line: {}", err); + } } } + Ok(addresses) } diff --git a/mullvad-rpc/src/bin/address_cache.rs b/mullvad-rpc/src/bin/address_cache.rs new file mode 100644 index 0000000000..efb2501ba9 --- /dev/null +++ b/mullvad-rpc/src/bin/address_cache.rs @@ -0,0 +1,39 @@ +/// Generate a first list of IP addresses for Mullvad VPN to use to talk to the API. +use mullvad_rpc::{rest::Error as RestError, ApiProxy, MullvadRpcRuntime}; +use std::process; +use talpid_types::ErrorExt; + +#[tokio::main] +async fn main() { + let mut runtime = + MullvadRpcRuntime::new(tokio::runtime::Handle::current()).expect("Failed to load runtime"); + + let api_proxy = ApiProxy::new(runtime.mullvad_rest_handle()); + let request = api_proxy.get_api_addrs().await; + + let api_list = match request { + Ok(api_list) => api_list, + Err(RestError::TimeoutError(_)) => { + eprintln!("Request timed out"); + process::exit(2); + } + Err(e @ RestError::DeserializeError(_)) => { + eprintln!( + "{}", + e.display_chain_with_msg("Failed to deserialize API address list") + ); + process::exit(3); + } + Err(e) => { + eprintln!( + "{}", + e.display_chain_with_msg("Failed to fetch API address list") + ); + process::exit(1); + } + }; + + for address in api_list { + println!("{}", address); + } +} diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs index 69f39b6349..d92be6e8be 100644 --- a/mullvad-rpc/src/lib.rs +++ b/mullvad-rpc/src/lib.rs @@ -12,7 +12,7 @@ use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, path::Path, }; -use talpid_types::net::wireguard; +use talpid_types::{net::wireguard, ErrorExt}; pub mod rest; @@ -35,6 +35,7 @@ pub const INVALID_VOUCHER: &str = "INVALID_VOUCHER"; const API_HOST: &str = "api.mullvad.net"; pub const API_IP_CACHE_FILENAME: &str = "api-ip-address.txt"; const API_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 78)); +const API_ADDRESS: (IpAddr, u16) = (crate::API_IP, 443); /// A type that helps with the creation of RPC connections. @@ -48,6 +49,9 @@ pub struct MullvadRpcRuntime { pub enum Error { #[error(display = "Failed to construct a rest client")] RestError(#[error(source)] rest::Error), + + #[error(display = "Failed to load address cache")] + AddressCacheError(#[error(source)] address_cache::Error), } impl MullvadRpcRuntime { @@ -56,17 +60,41 @@ impl MullvadRpcRuntime { Ok(MullvadRpcRuntime { https_connector: HttpsConnectorWithSni::new(), handle, - address_cache: AddressCache::new(), + address_cache: AddressCache::new(vec![API_ADDRESS.into()], None)?, }) } - /// Create a new `MullvadRpcRuntime` using the specified cache directory. - pub async fn with_cache_dir( + /// Create a new `MullvadRpcRuntime` using the specified directories. + /// Try to use the cache directory first, and fall back on the resource directory + /// if it fails. + pub async fn with_cache( handle: tokio::runtime::Handle, - cache_dir: &Path, + resource_dir: &Path, + cache_dir: Option<&Path>, ) -> Result<Self, Error> { - let cache_file = cache_dir.join(API_IP_CACHE_FILENAME); - let address_cache = AddressCache::with_cache(cache_file.into_boxed_path()).await; + let resource_file = resource_dir.join(API_IP_CACHE_FILENAME); + + let address_cache = if let Some(cache_dir) = cache_dir { + let cache_file = cache_dir.join(API_IP_CACHE_FILENAME); + let cache_file_boxed = cache_file.clone().into_boxed_path(); + + match AddressCache::from_file(&cache_file, Some(cache_file_boxed.clone())).await { + Ok(cache) => cache, + Err(error) => { + if cache_file.exists() { + log::error!( + "{}", + error.display_chain_with_msg( + "Failed to load cached API addresses. Falling back on bundled list" + ) + ); + } + AddressCache::from_file(&resource_file, Some(cache_file_boxed)).await? + } + } + } else { + AddressCache::from_file(&resource_file, None).await? + }; let https_connector = HttpsConnectorWithSni::new(); @@ -426,6 +454,10 @@ pub struct ApiProxy { } impl ApiProxy { + pub fn new(handle: rest::MullvadRestHandle) -> Self { + Self { handle } + } + pub async fn get_api_addrs(&self) -> Result<Vec<SocketAddr>, rest::Error> { let service = self.handle.service.clone(); diff --git a/mullvad-setup/src/main.rs b/mullvad-setup/src/main.rs index 0e0776fe92..396b86fa2b 100644 --- a/mullvad-setup/src/main.rs +++ b/mullvad-setup/src/main.rs @@ -109,12 +109,15 @@ async fn reset_firewall() -> Result<(), Error> { } async fn clear_history() -> Result<(), Error> { - let (cache_path, settings_path) = get_paths()?; + let (cache_path, resource_path, settings_path) = get_paths()?; - let mut rpc_runtime = - MullvadRpcRuntime::with_cache_dir(tokio::runtime::Handle::current(), &cache_path) - .await - .map_err(Error::RpcInitializationError)?; + let mut rpc_runtime = MullvadRpcRuntime::with_cache( + tokio::runtime::Handle::current(), + &resource_path, + Some(&cache_path), + ) + .await + .map_err(Error::RpcInitializationError)?; let mut account_history = account_history::AccountHistory::new( &cache_path, @@ -131,18 +134,20 @@ async fn clear_history() -> Result<(), Error> { } #[cfg(not(windows))] -fn get_paths() -> Result<(PathBuf, PathBuf), Error> { +fn get_paths() -> Result<(PathBuf, PathBuf, PathBuf), Error> { let cache_path = mullvad_paths::cache_dir().map_err(Error::CachePathError)?; + let resource_path = mullvad_paths::get_resource_dir(); let settings_path = mullvad_paths::settings_dir().map_err(Error::SettingsPathError)?; - Ok((cache_path, settings_path)) + Ok((cache_path, resource_path, settings_path)) } #[cfg(windows)] -fn get_paths() -> Result<(PathBuf, PathBuf), Error> { +fn get_paths() -> Result<(PathBuf, PathBuf, PathBuf), Error> { let settings_path = daemon_paths::get_mullvad_daemon_settings_path().map_err(Error::CachePathError)?; + let resource_path = mullvad_paths::get_resource_dir(); let cache_path = daemon_paths::get_mullvad_daemon_cache_path().map_err(Error::SettingsPathError)?; - Ok((cache_path, settings_path)) + Ok((cache_path, resource_path, settings_path)) } diff --git a/update-api-address.sh b/update-api-address.sh new file mode 100755 index 0000000000..5013a56f61 --- /dev/null +++ b/update-api-address.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +echo "Updating API address cache..." +set -e + +cargo +stable run --bin address_cache --release > dist-assets/api-ip-address.txt diff --git a/windows/nsis-plugins/src/cleanup/cleaningops.cpp b/windows/nsis-plugins/src/cleanup/cleaningops.cpp index 8653bb50a9..475c78d8b7 100644 --- a/windows/nsis-plugins/src/cleanup/cleaningops.cpp +++ b/windows/nsis-plugins/src/cleanup/cleaningops.cpp @@ -331,4 +331,18 @@ void RemoveRelayCacheServiceUser() std::filesystem::remove(cacheFile); } +void RemoveApiAddressCacheServiceUser() +{ + const auto localAppData = GetSystemUserLocalAppData(); + const auto mullvadAppData = std::filesystem::path(localAppData).append(L"Mullvad VPN"); + + common::fs::ScopedNativeFileSystem nativeFileSystem; + + common::security::AddAdminToObjectDacl(mullvadAppData, SE_FILE_OBJECT); + + const auto cacheFile = std::filesystem::path(mullvadAppData).append(L"api-ip-address.txt"); + + std::filesystem::remove(cacheFile); +} + } diff --git a/windows/nsis-plugins/src/cleanup/cleaningops.h b/windows/nsis-plugins/src/cleanup/cleaningops.h index 40ce97e81e..057eb305b8 100644 --- a/windows/nsis-plugins/src/cleanup/cleaningops.h +++ b/windows/nsis-plugins/src/cleanup/cleaningops.h @@ -12,5 +12,6 @@ void RemoveSettingsServiceUser(); // Remove only the relay cache, leaving other cache files untouched. // This is useful when updating the app. void RemoveRelayCacheServiceUser(); +void RemoveApiAddressCacheServiceUser(); } diff --git a/windows/nsis-plugins/src/cleanup/cleanup.cpp b/windows/nsis-plugins/src/cleanup/cleanup.cpp index faef07c2f0..528efb2f7a 100644 --- a/windows/nsis-plugins/src/cleanup/cleanup.cpp +++ b/windows/nsis-plugins/src/cleanup/cleanup.cpp @@ -100,3 +100,34 @@ void __declspec(dllexport) NSISCALL RemoveRelayCache pushint(NsisStatus::GENERAL_ERROR); } } + +void __declspec(dllexport) NSISCALL RemoveApiAddressCache +( + HWND hwndParent, + int string_size, + LPTSTR variables, + stack_t **stacktop, + extra_parameters *extra, + ... +) +{ + EXDLL_INIT(); + + try + { + cleaningops::RemoveApiAddressCacheServiceUser(); + + pushstring(L""); + pushint(NsisStatus::SUCCESS); + } + catch (const std::exception &err) + { + pushstring(common::string::ToWide(err.what()).c_str()); + pushint(NsisStatus::GENERAL_ERROR); + } + catch (...) + { + pushstring(L"Unspecified error"); + pushint(NsisStatus::GENERAL_ERROR); + } +} diff --git a/windows/nsis-plugins/src/cleanup/cleanup.def b/windows/nsis-plugins/src/cleanup/cleanup.def index 8752772b8d..779e620691 100644 --- a/windows/nsis-plugins/src/cleanup/cleanup.def +++ b/windows/nsis-plugins/src/cleanup/cleanup.def @@ -5,3 +5,4 @@ EXPORTS RemoveLogsAndCache RemoveSettings RemoveRelayCache +RemoveApiAddressCache |
