summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--mullvad-daemon/src/relays.rs20
-rw-r--r--mullvad-rpc/src/bin/relay_list.rs2
-rw-r--r--mullvad-rpc/src/lib.rs2
-rw-r--r--mullvad-rpc/src/relay_list.rs43
-rw-r--r--mullvad-rpc/src/rest.rs5
-rw-r--r--mullvad-types/src/relay_list.rs2
7 files changed, 57 insertions, 18 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 94c52430ce..ff77257909 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,7 @@ Line wrap the file at 100 chars. Th
- Update Electron from 11.0.2 to 11.2.1 which includes a newer Chromium version and
security patches.
- Allow provider constraint to specify multiple hosting providers.
+- Only download a new relay list if it has been modified.
#### Android
- WireGuard key is now rotated sooner: every four days instead of seven.
diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs
index c3c2e7e365..26b855b3b4 100644
--- a/mullvad-daemon/src/relays.rs
+++ b/mullvad-daemon/src/relays.rs
@@ -140,6 +140,10 @@ impl ParsedRelays {
pub fn relays(&self) -> &Vec<Relay> {
&self.relays
}
+
+ pub fn tag(&self) -> Option<&str> {
+ self.locations.etag.as_deref()
+ }
}
pub struct RelaySelector {
@@ -813,7 +817,8 @@ impl RelayListUpdater {
futures::select! {
_check_update = check_interval.next() => {
if download_future.is_terminated() && self.should_update() {
- download_future = Box::pin(Self::download_relay_list(self.rpc_client.clone()).fuse());
+ let tag = self.parsed_relays.lock().tag().map(|tag| tag.to_string());
+ download_future = Box::pin(Self::download_relay_list(self.rpc_client.clone(), tag).fuse());
self.earliest_next_try = Instant::now() + UPDATE_INTERVAL;
}
},
@@ -826,7 +831,8 @@ impl RelayListUpdater {
cmd = cmd_rx.next() => {
match cmd {
Some(_) => {
- self.consume_new_relay_list(self.rpc_client.relay_list().await).await;
+ let tag = self.parsed_relays.lock().tag().map(|tag| tag.to_string());
+ self.consume_new_relay_list(self.rpc_client.relay_list(tag).await).await;
},
None => {
log::error!("Relay list updater shutting down");
@@ -841,14 +847,15 @@ impl RelayListUpdater {
async fn consume_new_relay_list(
&mut self,
- result: Result<RelayList, mullvad_rpc::rest::Error>,
+ result: Result<Option<RelayList>, mullvad_rpc::rest::Error>,
) {
match result {
- Ok(relay_list) => {
+ Ok(Some(relay_list)) => {
if let Err(err) = self.update_cache(relay_list).await {
log::error!("Failed to update relay list cache: {}", err);
}
}
+ Ok(None) => log::debug!("Relay list is up-to-date"),
Err(err) => {
log::error!(
"Failed to fetch new relay list: {}. Will retry in {} minutes",
@@ -875,8 +882,9 @@ impl RelayListUpdater {
fn download_relay_list(
rpc_handle: RelayListProxy,
- ) -> impl Future<Output = Result<RelayList, mullvad_rpc::rest::Error>> + 'static {
- let download_futures = move || rpc_handle.relay_list();
+ tag: Option<String>,
+ ) -> impl Future<Output = Result<Option<RelayList>, mullvad_rpc::rest::Error>> + 'static {
+ let download_futures = move || rpc_handle.relay_list(tag.clone());
let exponential_backoff = ExponentialBackoff::from_millis(EXPONENTIAL_BACKOFF_DELAY_MS)
.factor(EXPONENTIAL_BACKOFF_FACTOR)
diff --git a/mullvad-rpc/src/bin/relay_list.rs b/mullvad-rpc/src/bin/relay_list.rs
index 8213d736da..e3ca00a9bc 100644
--- a/mullvad-rpc/src/bin/relay_list.rs
+++ b/mullvad-rpc/src/bin/relay_list.rs
@@ -10,7 +10,7 @@ async fn main() {
MullvadRpcRuntime::new(tokio::runtime::Handle::current()).expect("Failed to load runtime");
let relay_list_request = RelayListProxy::new(runtime.mullvad_rest_handle())
- .relay_list()
+ .relay_list(None)
.await;
let relay_list = match relay_list_request {
diff --git a/mullvad-rpc/src/lib.rs b/mullvad-rpc/src/lib.rs
index 7fd3a2480f..1b02ec0f2e 100644
--- a/mullvad-rpc/src/lib.rs
+++ b/mullvad-rpc/src/lib.rs
@@ -365,7 +365,7 @@ impl AppVersionProxy {
async move {
let mut request = request?;
- request.add_header("M-Platform-Version", platform_version)?;
+ request.add_header("M-Platform-Version", &platform_version)?;
let response = service.request(request).await?;
let parsed_response = rest::parse_rest_response(response, StatusCode::OK).await?;
diff --git a/mullvad-rpc/src/relay_list.rs b/mullvad-rpc/src/relay_list.rs
index b6784d3fda..847c0687de 100644
--- a/mullvad-rpc/src/relay_list.rs
+++ b/mullvad-rpc/src/relay_list.rs
@@ -1,7 +1,7 @@
/// A module dedicated to retrieving the relay list from the master API.
use crate::rest;
-use hyper::{Method, StatusCode};
+use hyper::{header, Method, StatusCode};
use mullvad_types::{location, relay_list};
use talpid_types::net::wireguard;
@@ -27,7 +27,10 @@ impl RelayListProxy {
}
/// Fetch the relay list
- pub fn relay_list(&self) -> impl Future<Output = Result<relay_list::RelayList, rest::Error>> {
+ pub fn relay_list(
+ &self,
+ etag: Option<String>,
+ ) -> impl Future<Output = Result<Option<relay_list::RelayList>, rest::Error>> {
let service = self.handle.service.clone();
let request = self.handle.factory.request("/v1/relays", Method::GET);
@@ -35,13 +38,34 @@ impl RelayListProxy {
let mut request = request?;
request.set_timeout(RELAY_LIST_TIMEOUT);
+ if let Some(ref tag) = etag {
+ request.add_header(header::IF_NONE_MATCH, tag)?;
+ }
+
let response = service.request(request).await?;
+ if etag.is_some() && response.status() == StatusCode::NOT_MODIFIED {
+ return Ok(None);
+ }
if response.status() != StatusCode::OK {
return rest::handle_error_response(response).await;
}
- Ok(rest::deserialize_body::<ServerRelayList>(response)
- .await?
- .into_relay_list())
+
+ let etag = response
+ .headers()
+ .get(header::ETAG)
+ .and_then(|tag| match tag.to_str() {
+ Ok(tag) => Some(tag.to_string()),
+ Err(_) => {
+ log::error!("Ignoring invalid tag from server: {:?}", tag.as_bytes());
+ None
+ }
+ });
+
+ Ok(Some(
+ rest::deserialize_body::<ServerRelayList>(response)
+ .await?
+ .into_relay_list(etag),
+ ))
};
future
}
@@ -57,7 +81,7 @@ struct ServerRelayList {
}
impl ServerRelayList {
- fn into_relay_list(self) -> relay_list::RelayList {
+ fn into_relay_list(self, etag: Option<String>) -> relay_list::RelayList {
let mut countries = BTreeMap::new();
let Self {
locations,
@@ -88,8 +112,13 @@ impl ServerRelayList {
Self::add_wireguard_relays(&mut countries, wireguard);
Self::add_bridge_relays(&mut countries, bridge);
-
relay_list::RelayList {
+ etag: etag.map(|mut tag| {
+ if tag.starts_with("\"") {
+ tag.insert_str(0, "W/");
+ }
+ tag
+ }),
countries: countries
.into_iter()
.map(|(_key, country)| country)
diff --git a/mullvad-rpc/src/rest.rs b/mullvad-rpc/src/rest.rs
index 07746a3150..d21e20fbcd 100644
--- a/mullvad-rpc/src/rest.rs
+++ b/mullvad-rpc/src/rest.rs
@@ -342,9 +342,8 @@ impl RestRequest {
self.timeout
}
- pub fn add_header(&mut self, key: &'static str, value: String) -> Result<()> {
- let header_value =
- http::HeaderValue::from_str(&value).map_err(Error::InvalidHeaderError)?;
+ pub fn add_header<T: header::IntoHeaderName>(&mut self, key: T, value: &str) -> Result<()> {
+ let header_value = http::HeaderValue::from_str(value).map_err(Error::InvalidHeaderError)?;
self.request.headers_mut().insert(key, header_value);
Ok(())
}
diff --git a/mullvad-types/src/relay_list.rs b/mullvad-types/src/relay_list.rs
index c3bbc33b6f..863e704792 100644
--- a/mullvad-types/src/relay_list.rs
+++ b/mullvad-types/src/relay_list.rs
@@ -21,12 +21,14 @@ use talpid_types::net::{
#[cfg_attr(target_os = "android", derive(IntoJava))]
#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))]
pub struct RelayList {
+ pub etag: Option<String>,
pub countries: Vec<RelayListCountry>,
}
impl RelayList {
pub fn empty() -> Self {
Self {
+ etag: None,
countries: Vec::new(),
}
}