summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-12-02 17:36:39 +0100
committerDavid Lönnhager <david.l@mullvad.net>2021-01-04 16:50:18 +0100
commit29260429f5cdf04ef4e51a42a4abd11f5e2e03b7 (patch)
tree35db7806efabbf85c79cc919dc2fea07f30578ff
parent1680065e267b84f1443317ae942cd0c609e86b14 (diff)
downloadmullvadvpn-29260429f5cdf04ef4e51a42a4abd11f5e2e03b7.tar.xz
mullvadvpn-29260429f5cdf04ef4e51a42a4abd11f5e2e03b7.zip
Always prefer the last used API address
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt2
-rwxr-xr-xdist-assets/pkg-scripts/preinstall3
-rwxr-xr-xdist-assets/uninstall_macos.sh2
-rw-r--r--mullvad-daemon/src/lib.rs6
-rw-r--r--mullvad-daemon/src/main.rs3
-rw-r--r--mullvad-jni/src/lib.rs1
-rw-r--r--mullvad-jni/src/problem_report.rs8
-rw-r--r--mullvad-paths/src/cache.rs23
-rw-r--r--mullvad-paths/src/lib.rs2
-rw-r--r--mullvad-problem-report/src/lib.rs8
-rw-r--r--mullvad-problem-report/src/main.rs4
-rw-r--r--mullvad-rpc/src/address_cache.rs150
-rw-r--r--mullvad-rpc/src/lib.rs48
-rw-r--r--mullvad-rpc/src/rest.rs15
-rw-r--r--mullvad-setup/src/daemon_paths.rs14
-rw-r--r--mullvad-setup/src/main.rs44
-rw-r--r--windows/nsis-plugins/src/cleanup/cleaningops.cpp8
18 files changed, 219 insertions, 128 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt
index ae2d1b2df2..52795f0964 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt
@@ -22,7 +22,7 @@ class MullvadProblemReport {
}
val logDirectory = CompletableDeferred<File>()
- val resourcesDirectory = CompletableDeferred<File>()
+ val cacheDirectory = CompletableDeferred<File>()
private val commandChannel = spawnActor()
@@ -112,7 +112,7 @@ class MullvadProblemReport {
userEmail,
userMessage,
problemReportPath.await().absolutePath,
- resourcesDirectory.await().absolutePath
+ cacheDirectory.await().absolutePath
)
if (result) {
@@ -132,6 +132,6 @@ class MullvadProblemReport {
userEmail: String,
userMessage: String,
reportPath: String,
- resourcesDirectory: String
+ cacheDirectory: String
): Boolean
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
index 44996b55b8..613927fe49 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
@@ -88,7 +88,7 @@ class MainActivity : FragmentActivity() {
problemReport.apply {
logDirectory.complete(filesDir)
- resourcesDirectory.complete(filesDir)
+ cacheDirectory.complete(cacheDir)
}
setContentView(R.layout.main)
diff --git a/dist-assets/pkg-scripts/preinstall b/dist-assets/pkg-scripts/preinstall
index 5b56185a58..6c0ee99ff3 100755
--- a/dist-assets/pkg-scripts/preinstall
+++ b/dist-assets/pkg-scripts/preinstall
@@ -80,7 +80,10 @@ fi
# 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
+# Old API IP cache
rm "$NEW_CACHE_DIR/api-ip-address.txt" || true
+# New API IP cache
+rm "/Library/Caches/mullvad-vpn/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/uninstall_macos.sh b/dist-assets/uninstall_macos.sh
index 622457f994..4c02245a30 100755
--- a/dist-assets/uninstall_macos.sh
+++ b/dist-assets/uninstall_macos.sh
@@ -40,7 +40,7 @@ sudo pkgutil --forget net.mullvad.vpn || true
read -p "Do you want to delete the log and cache files the app has created? (y/n) "
if [[ "$REPLY" =~ [Yy]$ ]]; then
- sudo rm -rf /var/log/mullvad-vpn /var/root/Library/Caches/mullvad-vpn
+ sudo rm -rf /var/log/mullvad-vpn /var/root/Library/Caches/mullvad-vpn /Library/Caches/mullvad-vpn
for user in /Users/*; do
user_log_dir="$user/Library/Logs/Mullvad VPN"
if [[ -d "$user_log_dir" ]]; then
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 290fdaa9ee..b182686e19 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -483,6 +483,7 @@ where
resource_dir: PathBuf,
settings_dir: PathBuf,
cache_dir: PathBuf,
+ user_cache_dir: PathBuf,
event_listener: L,
command_channel: DaemonCommandChannel,
#[cfg(target_os = "android")] android_context: AndroidContext,
@@ -492,8 +493,9 @@ where
let mut rpc_runtime = mullvad_rpc::MullvadRpcRuntime::with_cache(
tokio::runtime::Handle::current(),
- &resource_dir,
- Some(&cache_dir),
+ Some(&resource_dir),
+ &user_cache_dir,
+ true,
)
.await
.map_err(Error::InitRpcFactory)?;
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index 4e055183b9..bd91729af1 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -123,6 +123,8 @@ async fn create_daemon(
.map_err(|e| e.display_chain_with_msg("Unable to get settings dir"))?;
let cache_dir = mullvad_paths::cache_dir()
.map_err(|e| e.display_chain_with_msg("Unable to get cache dir"))?;
+ let user_cache_dir = mullvad_paths::user_cache_dir()
+ .map_err(|e| e.display_chain_with_msg("Unable to get user cache dir"))?;
let command_channel = DaemonCommandChannel::new();
let event_listener = spawn_management_interface(command_channel.sender()).await?;
@@ -132,6 +134,7 @@ async fn create_daemon(
resource_dir,
settings_dir,
cache_dir,
+ user_cache_dir,
event_listener,
command_channel,
)
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 35fe78dd01..0b95495746 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -236,6 +236,7 @@ fn spawn_daemon(
Some(resource_dir.clone()),
resource_dir.clone(),
resource_dir,
+ cache_dir.clone(),
cache_dir,
listener,
command_channel,
diff --git a/mullvad-jni/src/problem_report.rs b/mullvad-jni/src/problem_report.rs
index fb83c06bdc..f1a7e884db 100644
--- a/mullvad-jni/src/problem_report.rs
+++ b/mullvad-jni/src/problem_report.rs
@@ -43,21 +43,21 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_dataproxy_MullvadProblemRepor
userEmail: JString<'_>,
userMessage: JString<'_>,
outputPath: JString<'_>,
- resourcesDirectory: JString<'_>,
+ cacheDirectory: JString<'_>,
) -> jboolean {
let env = JnixEnv::from(env);
let user_email = String::from_java(&env, userEmail);
let user_message = String::from_java(&env, userMessage);
let output_path_string = String::from_java(&env, outputPath);
let output_path = Path::new(&output_path_string);
- let resources_directory_string = String::from_java(&env, resourcesDirectory);
- let resources_directory = Path::new(&resources_directory_string);
+ let cache_directory_string = String::from_java(&env, cacheDirectory);
+ let cache_directory = Path::new(&cache_directory_string);
let send_result = mullvad_problem_report::send_problem_report(
&user_email,
&user_message,
output_path,
- resources_directory,
+ cache_directory,
);
match send_result {
diff --git a/mullvad-paths/src/cache.rs b/mullvad-paths/src/cache.rs
index 35b99738f0..490fe9f702 100644
--- a/mullvad-paths/src/cache.rs
+++ b/mullvad-paths/src/cache.rs
@@ -33,3 +33,26 @@ pub fn get_default_cache_dir() -> Result<PathBuf> {
Ok(std::path::Path::new(crate::APP_PATH).join("cache"))
}
}
+
+/// Creates and returns a cache directory that is readable by all users.
+pub fn user_cache_dir() -> Result<PathBuf> {
+ #[cfg(not(target_os = "macos"))]
+ let permissions = None;
+ #[cfg(target_os = "macos")]
+ let permissions = Some(std::os::unix::fs::PermissionsExt::from_mode(0o755));
+ crate::create_and_return(get_user_cache_dir, permissions)
+}
+
+pub fn get_user_cache_dir() -> Result<PathBuf> {
+ #[cfg(windows)]
+ {
+ let dir = crate::get_allusersprofile_dir();
+ dir.map(|dir| dir.join(crate::PRODUCT_NAME))
+ }
+ #[cfg(target_os = "macos")]
+ {
+ Ok(std::path::Path::new("/Library/Caches").join(crate::PRODUCT_NAME))
+ }
+ #[cfg(not(any(target_os = "macos", windows)))]
+ get_cache_dir()
+}
diff --git a/mullvad-paths/src/lib.rs b/mullvad-paths/src/lib.rs
index 7b06c9937d..03453e9adc 100644
--- a/mullvad-paths/src/lib.rs
+++ b/mullvad-paths/src/lib.rs
@@ -56,7 +56,7 @@ fn create_and_return(
}
mod cache;
-pub use crate::cache::{cache_dir, get_default_cache_dir};
+pub use crate::cache::{cache_dir, get_default_cache_dir, get_user_cache_dir, user_cache_dir};
mod logs;
pub use crate::logs::{get_default_log_dir, get_log_dir, log_dir};
diff --git a/mullvad-problem-report/src/lib.rs b/mullvad-problem-report/src/lib.rs
index 276a1557b1..4601a810ea 100644
--- a/mullvad-problem-report/src/lib.rs
+++ b/mullvad-problem-report/src/lib.rs
@@ -69,6 +69,9 @@ pub enum Error {
#[error(display = "Unable to spawn Tokio runtime")]
CreateRuntime(#[error(source)] io::Error),
+
+ #[error(display = "Unable to find cache directory")]
+ ObtainCacheDirectory(#[error(source)] mullvad_paths::Error),
}
/// These are errors that can happen during problem report collection.
@@ -253,7 +256,7 @@ pub fn send_problem_report(
user_email: &str,
user_message: &str,
report_path: &Path,
- resource_dir: &Path,
+ user_cache_dir: &Path,
) -> Result<(), Error> {
let report_content = normalize_newlines(
read_file_lossy(report_path, REPORT_MAX_SIZE).map_err(|source| {
@@ -275,8 +278,9 @@ pub fn send_problem_report(
let mut rpc_manager = runtime
.block_on(mullvad_rpc::MullvadRpcRuntime::with_cache(
runtime.handle().clone(),
- resource_dir,
None,
+ user_cache_dir,
+ false,
))
.map_err(Error::CreateRpcClientError)?;
let rpc_client = mullvad_rpc::ProblemReportProxy::new(rpc_manager.mullvad_rest_handle());
diff --git a/mullvad-problem-report/src/main.rs b/mullvad-problem-report/src/main.rs
index 7090cecd6d..4f0dfb0265 100644
--- a/mullvad-problem-report/src/main.rs
+++ b/mullvad-problem-report/src/main.rs
@@ -113,8 +113,8 @@ fn run() -> Result<(), Error> {
let report_path = Path::new(send_matches.value_of_os("report").unwrap());
let user_email = send_matches.value_of("email").unwrap_or("");
let user_message = send_matches.value_of("message").unwrap_or("");
- let resource_dir = mullvad_paths::get_resource_dir();
- send_problem_report(user_email, user_message, report_path, &resource_dir)
+ let user_cache_dir = mullvad_paths::get_user_cache_dir()?;
+ send_problem_report(user_email, user_message, report_path, &user_cache_dir)
} else {
unreachable!("No sub command given");
}
diff --git a/mullvad-rpc/src/address_cache.rs b/mullvad-rpc/src/address_cache.rs
index b2181c763b..73b85e4998 100644
--- a/mullvad-rpc/src/address_cache.rs
+++ b/mullvad-rpc/src/address_cache.rs
@@ -6,6 +6,7 @@ use std::{
path::Path,
sync::{Arc, Mutex},
};
+use talpid_types::ErrorExt;
use tokio::{
fs,
io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
@@ -20,6 +21,9 @@ pub enum Error {
#[error(display = "Failed to read the address cache file")]
ReadAddressCache(#[error(source)] io::Error),
+ #[error(display = "Failed to update the address cache file")]
+ WriteAddressCache(#[error(source)] io::Error),
+
#[error(display = "The address cache is empty")]
EmptyAddressCache,
}
@@ -27,34 +31,41 @@ pub enum Error {
#[derive(Clone)]
pub struct AddressCache {
inner: Arc<Mutex<AddressCacheInner>>,
- cache_path: Option<Arc<Path>>,
+ write_path: Option<Arc<Path>>,
}
impl AddressCache {
- /// 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)?;
+ /// Initialize cache using the given list, and write changes to `write_path`.
+ pub fn new(addresses: Vec<SocketAddr>, write_path: Option<Box<Path>>) -> Result<Self, Error> {
+ let mut cache = AddressCacheInner::from_addresses(addresses)?;
+ cache.shuffle_tail();
+ log::trace!("API address cache: {:?}", cache.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)),
+ write_path: write_path.map(|cache| Arc::from(cache)),
};
Ok(address_cache)
}
- /// 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> {
+ /// Initialize cache using `read_path`, and write changes to `write_path`.
+ pub async fn from_file(read_path: &Path, write_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)
+ Self::new(read_address_file(read_path).await?, write_path)
}
+ /// Returns the currently selected address.
pub fn get_address(&self) -> SocketAddr {
let mut inner = self.inner.lock().unwrap();
- inner.last_try = Some(inner.choice);
+ inner.tried_current = true;
+ Self::get_address_inner(&inner)
+ }
+ /// Returns the current address without registering it as "tried"
+ /// in [`has_tried_current_address`].
+ pub fn peek_address(&self) -> SocketAddr {
+ let inner = self.inner.lock().unwrap();
Self::get_address_inner(&inner)
}
@@ -68,26 +79,38 @@ impl AddressCache {
.unwrap_or(&API_ADDRESS.into())
}
- pub fn register_failure(&self, failed_addr: SocketAddr, err: &dyn std::error::Error) {
- let mut inner = self.inner.lock().unwrap();
+ pub fn has_tried_current_address(&self) -> bool {
+ let inner = self.inner.lock().unwrap();
+ inner.tried_current
+ }
- let current_address = Self::get_address_inner(&inner);
- // Only choose the next server if the current one has been tried before and it failed
- if failed_addr == current_address
- && inner
- .last_try
- .map(|last_try| last_try == inner.choice)
- .unwrap_or(false)
- {
+ pub async fn select_new_address(&self) {
+ let (new_choice, old_choice) = {
+ let mut inner = self.inner.lock().unwrap();
+ let old_choice = inner.choice;
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
- );
+ (inner.choice, old_choice)
+ };
+
+ if new_choice == old_choice {
+ return;
+ }
+
+ if let Err(error) = self.save_to_disk().await {
+ log::error!("{}", error.display_chain());
+ }
+ }
+
+ /// Forgets the currently selected address and randomizes
+ /// the entire list.
+ pub async fn randomize(&self) -> Result<(), Error> {
+ {
+ let mut inner = self.inner.lock().unwrap();
+ inner.shuffle();
+ inner.choice = 0;
+ inner.tried_current = false;
}
+ self.save_to_disk().await.map_err(Error::WriteAddressCache)
}
pub async fn set_addresses(&self, mut addresses: Vec<SocketAddr>) -> io::Result<()> {
@@ -97,9 +120,20 @@ impl AddressCache {
let mut current_sorted = inner.addresses.clone();
current_sorted.sort();
if addresses != current_sorted {
+ let current_address = Self::get_address_inner(&inner);
+
inner.addresses = addresses.clone();
inner.shuffle();
- inner.choice = 0;
+
+ // Prefer a likely-working address
+ let choice = inner.addresses.iter().position(|&addr| addr == current_address);
+ if let Some(choice) = choice {
+ inner.choice = choice;
+ } else {
+ inner.choice = 0;
+ inner.tried_current = false;
+ }
+
true
} else {
false
@@ -107,26 +141,41 @@ impl AddressCache {
};
if should_update {
log::trace!("API address cache: {:?}", addresses);
- self.save_to_disk(addresses).await?;
+ self.save_to_disk().await?;
}
Ok(())
}
- async fn save_to_disk(&self, addresses: Vec<SocketAddr>) -> io::Result<()> {
- if let Some(cache_path) = self.cache_path.as_ref() {
- let mut file = fs::File::create(cache_path).await?;
- let mut contents = addresses
- .iter()
- .map(ToString::to_string)
- .collect::<Vec<String>>()
- .join("\n");
- contents += "\n";
+ async fn save_to_disk(&self) -> io::Result<()> {
+ let write_path = match self.write_path.as_ref() {
+ Some(write_path) => write_path,
+ None => return Ok(()),
+ };
+
+ let (mut addresses, choice) = {
+ let inner = self.inner.lock().unwrap();
+ (inner.addresses.clone(), inner.choice)
+ };
- file.write_all(contents.as_bytes()).await?;
- file.sync_data().await?;
+ // Place the current choice on top
+ if !addresses.is_empty() {
+ let addresses_len = addresses.len();
+ addresses.swap(0, choice % addresses_len);
}
- Ok(())
+ let temp_path = write_path.with_file_name("api-cache.temp");
+
+ let mut file = fs::File::create(&temp_path).await?;
+ let mut contents = addresses
+ .iter()
+ .map(ToString::to_string)
+ .collect::<Vec<String>>()
+ .join("\n");
+ contents += "\n";
+ file.write_all(contents.as_bytes()).await?;
+ file.sync_data().await?;
+
+ fs::rename(&temp_path, write_path).await
}
}
@@ -144,7 +193,7 @@ impl crate::rest::AddressProvider for AddressCache {
struct AddressCacheInner {
addresses: Vec<SocketAddr>,
choice: usize,
- last_try: Option<usize>,
+ tried_current: bool,
}
impl AddressCacheInner {
@@ -152,19 +201,23 @@ impl AddressCacheInner {
if addresses.is_empty() {
return Err(Error::EmptyAddressCache);
}
- let mut cache = Self {
+ Ok(Self {
addresses,
choice: 0,
- last_try: None,
- };
- cache.shuffle();
- Ok(cache)
+ tried_current: false,
+ })
}
fn shuffle(&mut self) {
let mut rng = rand::thread_rng();
(&mut self.addresses[..]).shuffle(&mut rng);
}
+
+ /// Shuffle all but the first element
+ fn shuffle_tail(&mut self) {
+ let mut rng = rand::thread_rng();
+ (&mut self.addresses[1..]).shuffle(&mut rng);
+ }
}
async fn read_address_file(path: &Path) -> Result<Vec<SocketAddr>, Error> {
@@ -178,7 +231,6 @@ async fn read_address_file(path: &Path) -> Result<Vec<SocketAddr>, Error> {
.await
.map_err(|error| Error::ReadAddressCache(error))?
{
- // for line in lines.next_line() {
match line.trim().parse() {
Ok(address) => addresses.push(address),
Err(err) => {
diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs
index d92be6e8be..10c5ca74a8 100644
--- a/mullvad-rpc/src/lib.rs
+++ b/mullvad-rpc/src/lib.rs
@@ -69,31 +69,41 @@ impl MullvadRpcRuntime {
/// if it fails.
pub async fn with_cache(
handle: tokio::runtime::Handle,
- resource_dir: &Path,
- cache_dir: Option<&Path>,
+ resource_dir: Option<&Path>,
+ cache_dir: &Path,
+ write_changes: bool,
) -> Result<Self, Error> {
- let resource_file = resource_dir.join(API_IP_CACHE_FILENAME);
+ let cache_file = cache_dir.join(API_IP_CACHE_FILENAME);
+ let write_file = if write_changes {
+ Some(cache_file.clone().into_boxed_path())
+ } else {
+ None
+ };
- 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();
+ let address_cache = match AddressCache::from_file(&cache_file, write_file.clone()).await {
+ Ok(cache) => cache,
+ Err(error) => {
+ let cache_exists = cache_file.exists();
+ if cache_exists {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg(
+ "Failed to load cached API addresses. Falling back on bundled list"
+ )
+ );
+ }
- 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"
- )
- );
+ // Initialize the cache directory cache using the resource directory
+ match resource_dir {
+ Some(resource_dir) => {
+ let read_file = resource_dir.join(API_IP_CACHE_FILENAME);
+ let cache = AddressCache::from_file(&read_file, write_file).await?;
+ cache.randomize().await?;
+ cache
}
- AddressCache::from_file(&resource_file, Some(cache_file_boxed)).await?
+ None => return Err(Error::AddressCacheError(error)),
}
}
- } else {
- AddressCache::from_file(&resource_file, None).await?
};
let https_connector = HttpsConnectorWithSni::new();
diff --git a/mullvad-rpc/src/rest.rs b/mullvad-rpc/src/rest.rs
index 2bf8511d24..12bc10263e 100644
--- a/mullvad-rpc/src/rest.rs
+++ b/mullvad-rpc/src/rest.rs
@@ -139,7 +139,20 @@ impl<C: Connect + Clone + Send + Sync + 'static> RequestService<C> {
if let Err(err) = &response {
match err {
Error::HyperError(_) | Error::TimeoutError(_) => {
- address_cache.register_failure(host_addr, err);
+ let current_address = address_cache.peek_address();
+ if current_address == host_addr
+ && address_cache.has_tried_current_address()
+ {
+ address_cache.select_new_address().await;
+ let new_address = address_cache.peek_address();
+
+ log::error!(
+ "HTTP request failed: {}, using address {}. Trying next API address: {}",
+ err,
+ current_address,
+ new_address,
+ );
+ }
}
_ => (),
}
diff --git a/mullvad-setup/src/daemon_paths.rs b/mullvad-setup/src/daemon_paths.rs
index 6f00952703..fce81ede8c 100644
--- a/mullvad-setup/src/daemon_paths.rs
+++ b/mullvad-setup/src/daemon_paths.rs
@@ -15,9 +15,7 @@ use winapi::{
um::{
combaseapi::CoTaskMemFree,
handleapi::CloseHandle,
- knownfolders::{
- FOLDERID_LocalAppData, FOLDERID_ProgramFiles, FOLDERID_RoamingAppData, FOLDERID_System,
- },
+ knownfolders::{FOLDERID_LocalAppData, FOLDERID_System},
processthreadsapi::{GetCurrentThread, OpenProcess, OpenProcessToken, OpenThreadToken},
psapi::K32EnumProcesses,
securitybaseapi::{AdjustTokenPrivileges, ImpersonateSelf, RevertToSelf},
@@ -37,16 +35,6 @@ pub fn get_mullvad_daemon_settings_path() -> io::Result<PathBuf> {
.map(|settings| settings.join(mullvad_paths::PRODUCT_NAME))
}
-pub fn get_mullvad_resource_path() -> io::Result<PathBuf> {
- get_known_folder_path(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, ptr::null_mut())
- .map(|settings| settings.join(mullvad_paths::PRODUCT_NAME).join("resources"))
-}
-
-pub fn get_mullvad_daemon_cache_path() -> io::Result<PathBuf> {
- get_system_service_known_folder(FOLDERID_RoamingAppData)
- .map(|settings| settings.join(mullvad_paths::PRODUCT_NAME))
-}
-
/// Get local AppData path for the system service user. Requires elevated privileges to work.
/// Useful for deducing the config path for the daemon on Windows when running as a user that
diff --git a/mullvad-setup/src/main.rs b/mullvad-setup/src/main.rs
index 2e109089a4..7afb1fad16 100644
--- a/mullvad-setup/src/main.rs
+++ b/mullvad-setup/src/main.rs
@@ -24,11 +24,11 @@ enum ExitStatus {
#[cfg(windows)]
mod daemon_paths;
-#[cfg(not(windows))]
-type PathError = mullvad_paths::Error;
-
#[cfg(windows)]
-type PathError = std::io::Error;
+type SettingsPathErrorType = std::io::Error;
+
+#[cfg(not(windows))]
+type SettingsPathErrorType = mullvad_paths::Error;
#[derive(err_derive::Error, Debug)]
#[error(no_from)]
@@ -49,14 +49,10 @@ pub enum Error {
RpcInitializationError(#[error(source)] mullvad_rpc::Error),
#[error(display = "Failed to obtain settings directory path")]
- SettingsPathError(#[error(source)] PathError),
-
- #[cfg(windows)]
- #[error(display = "Failed to obtain resource directory path")]
- ResourcePathError(#[error(source)] PathError),
+ SettingsPathError(#[error(source)] SettingsPathErrorType),
#[error(display = "Failed to obtain cache directory path")]
- CachePathError(#[error(source)] PathError),
+ CachePathError(#[error(source)] mullvad_paths::Error),
#[error(display = "Failed to initialize account history")]
InitializeAccountHistoryError(#[error(source)] account_history::Error),
@@ -155,18 +151,19 @@ async fn reset_firewall() -> Result<(), Error> {
}
async fn clear_history() -> Result<(), Error> {
- let (cache_path, resource_path, settings_path) = get_paths()?;
+ let (user_cache_path, settings_path) = get_paths()?;
let mut rpc_runtime = MullvadRpcRuntime::with_cache(
tokio::runtime::Handle::current(),
- &resource_path,
- Some(&cache_path),
+ None,
+ &user_cache_path,
+ false,
)
.await
.map_err(Error::RpcInitializationError)?;
let mut account_history = account_history::AccountHistory::new(
- &cache_path,
+ &user_cache_path,
&settings_path,
rpc_runtime.mullvad_rest_handle(),
)
@@ -180,21 +177,16 @@ async fn clear_history() -> Result<(), Error> {
}
#[cfg(not(windows))]
-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();
+fn get_paths() -> Result<(PathBuf, PathBuf), Error> {
+ let user_cache_path = mullvad_paths::user_cache_dir().map_err(Error::CachePathError)?;
let settings_path = mullvad_paths::settings_dir().map_err(Error::SettingsPathError)?;
- Ok((cache_path, resource_path, settings_path))
+ Ok((user_cache_path, settings_path))
}
#[cfg(windows)]
-fn get_paths() -> Result<(PathBuf, PathBuf, PathBuf), Error> {
+fn get_paths() -> Result<(PathBuf, PathBuf), Error> {
+ let user_cache_path = mullvad_paths::user_cache_dir().map_err(Error::CachePathError)?;
let settings_path =
- daemon_paths::get_mullvad_daemon_settings_path().map_err(Error::CachePathError)?;
- let resource_path =
- daemon_paths::get_mullvad_resource_path().map_err(Error::ResourcePathError)?;
- let cache_path =
- daemon_paths::get_mullvad_daemon_cache_path().map_err(Error::SettingsPathError)?;
-
- Ok((cache_path, resource_path, settings_path))
+ daemon_paths::get_mullvad_daemon_settings_path().map_err(Error::SettingsPathError)?;
+ Ok((user_cache_path, settings_path))
}
diff --git a/windows/nsis-plugins/src/cleanup/cleaningops.cpp b/windows/nsis-plugins/src/cleanup/cleaningops.cpp
index 475c78d8b7..1a711bf3d8 100644
--- a/windows/nsis-plugins/src/cleanup/cleaningops.cpp
+++ b/windows/nsis-plugins/src/cleanup/cleaningops.cpp
@@ -333,14 +333,14 @@ void RemoveRelayCacheServiceUser()
void RemoveApiAddressCacheServiceUser()
{
- const auto localAppData = GetSystemUserLocalAppData();
- const auto mullvadAppData = std::filesystem::path(localAppData).append(L"Mullvad VPN");
+ const auto programData = common::fs::GetKnownFolderPath(FOLDERID_ProgramData, KF_FLAG_DEFAULT, nullptr);
+ const auto mullvadProgramData = std::filesystem::path(programData).append(L"Mullvad VPN");
common::fs::ScopedNativeFileSystem nativeFileSystem;
- common::security::AddAdminToObjectDacl(mullvadAppData, SE_FILE_OBJECT);
+ common::security::AddAdminToObjectDacl(mullvadProgramData, SE_FILE_OBJECT);
- const auto cacheFile = std::filesystem::path(mullvadAppData).append(L"api-ip-address.txt");
+ const auto cacheFile = std::filesystem::path(mullvadProgramData).append(L"api-ip-address.txt");
std::filesystem::remove(cacheFile);
}