Skip to content

Commit df37a0d

Browse files
committed
Merge branch 'move-api-address-updater' into main
2 parents 6d5d592 + 8bb84af commit df37a0d

File tree

6 files changed

+75
-74
lines changed

6 files changed

+75
-74
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Line wrap the file at 100 chars. Th
4242
- Fix connectivity issues that would occur when using quantum-resistant tunnels with an incorrectly
4343
configured MTU.
4444
- Fix custom list name validation by not allowing empty names.
45+
- Continual excessive attempts to update the API IP were made after testing access methods.
46+
- Fix pointless API access method rotations for concurrent requests.
4547

4648
#### Linux
4749
- Fix Bash shell completions for subcommands in the CLI.

mullvad-api/src/address_cache.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! This module keeps track of the last known good API IP address and reads and stores it on disk.
2+
13
use super::API;
24
use std::{io, net::SocketAddr, path::Path, sync::Arc};
35
use tokio::{

mullvad-api/src/lib.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl ApiEndpoint {
308308
/// A type that helps with the creation of API connections.
309309
pub struct Runtime {
310310
handle: tokio::runtime::Handle,
311-
pub address_cache: AddressCache,
311+
address_cache: AddressCache,
312312
api_availability: availability::ApiAvailability,
313313
#[cfg(target_os = "android")]
314314
socket_bypass_tx: Option<mpsc::Sender<SocketBypassRequest>>,
@@ -437,12 +437,7 @@ impl Runtime {
437437
let token_store = access::AccessTokenStore::new(service.clone());
438438
let factory = rest::RequestFactory::new(API.host(), Some(token_store));
439439

440-
rest::MullvadRestHandle::new(
441-
service,
442-
factory,
443-
self.address_cache.clone(),
444-
self.availability_handle(),
445-
)
440+
rest::MullvadRestHandle::new(service, factory, self.availability_handle())
446441
}
447442

448443
/// This is only to be used in test code
@@ -456,12 +451,7 @@ impl Runtime {
456451
let token_store = access::AccessTokenStore::new(service.clone());
457452
let factory = rest::RequestFactory::new(hostname, Some(token_store));
458453

459-
rest::MullvadRestHandle::new(
460-
service,
461-
factory,
462-
self.address_cache.clone(),
463-
self.availability_handle(),
464-
)
454+
rest::MullvadRestHandle::new(service, factory, self.availability_handle())
465455
}
466456

467457
/// Returns a new request service handle
@@ -481,6 +471,10 @@ impl Runtime {
481471
pub fn availability_handle(&self) -> ApiAvailabilityHandle {
482472
self.api_availability.handle()
483473
}
474+
475+
pub fn address_cache(&self) -> &AddressCache {
476+
&self.address_cache
477+
}
484478
}
485479

486480
#[derive(Clone)]

mullvad-api/src/rest.rs

+1-60
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ pub use hyper::StatusCode;
3030

3131
const USER_AGENT: &str = "mullvad-app";
3232

33-
const API_IP_CHECK_INITIAL: Duration = Duration::from_secs(15 * 60);
34-
const API_IP_CHECK_INTERVAL: Duration = Duration::from_secs(24 * 60 * 60);
35-
const API_IP_CHECK_ERROR_INTERVAL: Duration = Duration::from_secs(15 * 60);
36-
3733
pub type Result<T> = std::result::Result<T, Error>;
3834
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
3935

@@ -616,68 +612,13 @@ impl MullvadRestHandle {
616612
pub(crate) fn new(
617613
service: RequestServiceHandle,
618614
factory: RequestFactory,
619-
address_cache: AddressCache,
620615
availability: ApiAvailabilityHandle,
621616
) -> Self {
622-
let handle = Self {
617+
Self {
623618
service,
624619
factory,
625620
availability,
626-
};
627-
#[cfg(feature = "api-override")]
628-
{
629-
if crate::API.disable_address_cache {
630-
return handle;
631-
}
632621
}
633-
handle.spawn_api_address_fetcher(address_cache);
634-
handle
635-
}
636-
637-
fn spawn_api_address_fetcher(&self, address_cache: AddressCache) {
638-
let handle = self.clone();
639-
let availability = self.availability.clone();
640-
641-
tokio::spawn(async move {
642-
let api_proxy = crate::ApiProxy::new(handle);
643-
let mut next_delay = API_IP_CHECK_INITIAL;
644-
645-
loop {
646-
talpid_time::sleep(next_delay).await;
647-
648-
if let Err(error) = availability.wait_background().await {
649-
log::error!("Failed while waiting for API: {}", error);
650-
continue;
651-
}
652-
match api_proxy.clone().get_api_addrs().await {
653-
Ok(new_addrs) => {
654-
if let Some(addr) = new_addrs.first() {
655-
log::debug!(
656-
"Fetched new API address {:?}. Fetching again in {} hours",
657-
addr,
658-
API_IP_CHECK_INTERVAL.as_secs() / (60 * 60)
659-
);
660-
if let Err(err) = address_cache.set_address(*addr).await {
661-
log::error!("Failed to save newly updated API address: {}", err);
662-
}
663-
} else {
664-
log::error!("API returned no API addresses");
665-
}
666-
667-
next_delay = API_IP_CHECK_INTERVAL;
668-
}
669-
Err(err) => {
670-
log::error!(
671-
"Failed to fetch new API addresses: {}. Retrying in {} seconds",
672-
err,
673-
API_IP_CHECK_ERROR_INTERVAL.as_secs()
674-
);
675-
676-
next_delay = API_IP_CHECK_ERROR_INTERVAL;
677-
}
678-
}
679-
}
680-
});
681622
}
682623

683624
pub fn service(&self) -> RequestServiceHandle {
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//! A small updater that keeps the API IP address cache up to date by fetching changes from the
2+
//! Mullvad API.
3+
use mullvad_api::{rest::MullvadRestHandle, AddressCache, ApiProxy};
4+
use std::time::Duration;
5+
6+
const API_IP_CHECK_INITIAL: Duration = Duration::from_secs(15 * 60);
7+
const API_IP_CHECK_INTERVAL: Duration = Duration::from_secs(24 * 60 * 60);
8+
const API_IP_CHECK_ERROR_INTERVAL: Duration = Duration::from_secs(15 * 60);
9+
10+
pub async fn run_api_address_fetcher(address_cache: AddressCache, handle: MullvadRestHandle) {
11+
#[cfg(feature = "api-override")]
12+
if API.disable_address_cache {
13+
return;
14+
}
15+
16+
let availability = handle.availability.clone();
17+
let api_proxy = ApiProxy::new(handle);
18+
let mut next_delay = API_IP_CHECK_INITIAL;
19+
20+
loop {
21+
talpid_time::sleep(next_delay).await;
22+
23+
if let Err(error) = availability.wait_background().await {
24+
log::error!("Failed while waiting for API: {}", error);
25+
continue;
26+
}
27+
match api_proxy.clone().get_api_addrs().await {
28+
Ok(new_addrs) => {
29+
if let Some(addr) = new_addrs.first() {
30+
log::debug!(
31+
"Fetched new API address {:?}. Fetching again in {} hours",
32+
addr,
33+
API_IP_CHECK_INTERVAL.as_secs() / (60 * 60)
34+
);
35+
if let Err(err) = address_cache.set_address(*addr).await {
36+
log::error!("Failed to save newly updated API address: {}", err);
37+
}
38+
} else {
39+
log::error!("API returned no API addresses");
40+
}
41+
42+
next_delay = API_IP_CHECK_INTERVAL;
43+
}
44+
Err(err) => {
45+
log::error!(
46+
"Failed to fetch new API addresses: {}. Retrying in {} seconds",
47+
err,
48+
API_IP_CHECK_ERROR_INTERVAL.as_secs()
49+
);
50+
51+
next_delay = API_IP_CHECK_ERROR_INTERVAL;
52+
}
53+
}
54+
}
55+
}

mullvad-daemon/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
mod access_method;
44
pub mod account_history;
55
mod api;
6+
mod api_address_updater;
67
#[cfg(not(target_os = "android"))]
78
mod cleanup;
89
mod custom_list;
@@ -712,13 +713,19 @@ where
712713
relay_selector.clone(),
713714
settings.api_access_methods.clone(),
714715
internal_event_tx.to_specialized_sender(),
715-
api_runtime.address_cache.clone().clone(),
716+
api_runtime.address_cache().clone(),
716717
)
717718
.await
718719
.map_err(Error::ApiConnectionModeError)?;
719720

720721
let api_handle = api_runtime.mullvad_rest_handle(access_mode_provider);
721722

723+
// Continually update the API IP
724+
tokio::spawn(api_address_updater::run_api_address_fetcher(
725+
api_runtime.address_cache().clone(),
726+
api_handle.clone(),
727+
));
728+
722729
let access_method_handle = access_mode_handler.clone();
723730
settings.register_change_listener(move |settings| {
724731
let handle = access_method_handle.clone();

0 commit comments

Comments
 (0)