summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-daemon/src/relays.rs11
-rw-r--r--mullvad-rpc/src/bin/relay_list.rs2
-rw-r--r--mullvad-rpc/src/relay_list.rs38
-rw-r--r--mullvad-types/src/relay_list.rs2
4 files changed, 41 insertions, 12 deletions
diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs
index c3c2e7e365..ee53b7dde2 100644
--- a/mullvad-daemon/src/relays.rs
+++ b/mullvad-daemon/src/relays.rs
@@ -826,7 +826,7 @@ impl RelayListUpdater {
cmd = cmd_rx.next() => {
match cmd {
Some(_) => {
- self.consume_new_relay_list(self.rpc_client.relay_list().await).await;
+ self.consume_new_relay_list(self.rpc_client.relay_list(None).await).await;
},
None => {
log::error!("Relay list updater shutting down");
@@ -841,14 +841,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 +876,8 @@ 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();
+ ) -> impl Future<Output = Result<Option<RelayList>, mullvad_rpc::rest::Error>> + 'static {
+ let download_futures = move || rpc_handle.relay_list(None);
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/relay_list.rs b/mullvad-rpc/src/relay_list.rs
index b6784d3fda..cdf72c8c1f 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,35 @@ impl RelayListProxy {
let mut request = request?;
request.set_timeout(RELAY_LIST_TIMEOUT);
+ let has_tag = etag.is_some();
+ if let Some(tag) = etag {
+ request.add_header("If-None-Match", tag)?;
+ }
+
let response = service.request(request).await?;
+ if has_tag && 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 +82,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,
@@ -90,6 +115,7 @@ impl ServerRelayList {
relay_list::RelayList {
+ etag,
countries: countries
.into_iter()
.map(|(_key, country)| country)
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(),
}
}