Skip to content

Commit

Permalink
Simplify some Access Method Settings APIs
Browse files Browse the repository at this point in the history
By utilizing the new layout of the access method settings struct, some
APIs can be simplified or outright removed. Most of these
simplifications stem from implemting `iter`, `into_iter` & `iter_mut` on
`access_methods::Settings`the direct access to the "Direct" access
method of the settings struct.
  • Loading branch information
MarkusPettersson98 committed Jan 23, 2024
1 parent a1bc00f commit aba47d3
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 91 deletions.
23 changes: 8 additions & 15 deletions mullvad-daemon/src/access_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ where
self.settings
.try_update(|settings| -> Result<(), Error> {
settings.api_access_methods.remove(&access_method)?;
ensure_direct_is_available(settings);
ensure_direct_is_enabled(settings);
Ok(())
})
.await
Expand Down Expand Up @@ -124,7 +124,8 @@ where
) -> Result<AccessMethodSetting, Error> {
self.settings
.api_access_methods
.find_by_id(&access_method)
.iter()
.find(|setting| setting.get_id() == access_method)
.ok_or(Error::NoSuchMethod(access_method))
.cloned()
}
Expand Down Expand Up @@ -172,11 +173,12 @@ where
let settings_update = |settings: &mut Settings| {
if let Some(access_method) = settings
.api_access_methods
.find_by_id_mut(&access_method_update.get_id())
.iter_mut()
.find(|setting| setting.get_id() == access_method_update.get_id())
{
*access_method = access_method_update.clone();
}
ensure_direct_is_available(settings);
ensure_direct_is_enabled(settings);
};

self.settings
Expand Down Expand Up @@ -304,17 +306,8 @@ where
/// remaining enabled access method, which would cause an inconsistent state in
/// the daemon's settings. In that case, the `Direct` access method is
/// re-enabled.
fn ensure_direct_is_available(settings: &mut Settings) {
fn ensure_direct_is_enabled(settings: &mut Settings) {
if settings.api_access_methods.collect_enabled().is_empty() {
if let Some(direct) = settings.api_access_methods.get_direct() {
direct.enabled = true;
} else {
// If the `Direct` access method does not exist within the
// settings for some reason, the settings are in an
// inconsistent state. We don't have much choice but to
// reset these settings to their default value.
log::warn!("The built-in access methods can not be found. This might be due to a corrupt settings file");
settings.api_access_methods = access_method::Settings::default();
}
settings.api_access_methods.direct.enable();
}
}
8 changes: 0 additions & 8 deletions mullvad-daemon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,6 @@ pub enum DaemonCommand {
DeleteCustomList(ResponseTx<(), Error>, mullvad_types::custom_list::Id),
/// Update a custom list with a given id
UpdateCustomList(ResponseTx<(), Error>, CustomList),
/// Get API access methods
GetApiAccessMethods(ResponseTx<Vec<AccessMethodSetting>, Error>),
/// Add API access methods
AddApiAccessMethod(
ResponseTx<mullvad_types::access_method::Id, Error>,
Expand Down Expand Up @@ -1244,7 +1242,6 @@ where
DeleteCustomList(tx, id) => self.on_delete_custom_list(tx, id).await,
UpdateCustomList(tx, update) => self.on_update_custom_list(tx, update).await,
GetVersionInfo(tx) => self.on_get_version_info(tx),
GetApiAccessMethods(tx) => self.on_get_api_access_methods(tx),
AddApiAccessMethod(tx, name, enabled, access_method) => {
self.on_add_access_method(tx, name, enabled, access_method)
.await
Expand Down Expand Up @@ -2422,11 +2419,6 @@ where
Self::oneshot_send(tx, result, "update_custom_list response");
}

fn on_get_api_access_methods(&mut self, tx: ResponseTx<Vec<AccessMethodSetting>, Error>) {
let result = Ok(self.settings.api_access_methods.cloned());
Self::oneshot_send(tx, result, "get_api_access_methods response");
}

async fn on_add_access_method(
&mut self,
tx: ResponseTx<mullvad_types::access_method::Id, Error>,
Expand Down
17 changes: 9 additions & 8 deletions mullvad-management-interface/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,20 @@ impl MullvadProxyClient {
}

pub async fn get_api_access_methods(&mut self) -> Result<Vec<AccessMethodSetting>> {
self.0
let access_method_settings = self
.0
.get_settings(())
.await
.map_err(Error::Rpc)?
.into_inner()
.api_access_methods
.ok_or(Error::ApiAccessMethodSettingsNotFound)?
.access_method_settings
.into_iter()
.map(|api_access_method| {
AccessMethodSetting::try_from(api_access_method).map_err(Error::InvalidResponse)
})
.collect()
.ok_or(Error::ApiAccessMethodSettingsNotFound)
.and_then(|access_method_settings| {
access_method::Settings::try_from(access_method_settings)
.map_err(Error::InvalidResponse)
})?;

Ok(access_method_settings.iter().cloned().collect())
}

pub async fn get_api_access_method(
Expand Down
91 changes: 31 additions & 60 deletions mullvad-types/src/access_method.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::str::FromStr;

use serde::{Deserialize, Serialize};
use talpid_types::net::proxy::{CustomProxy, Shadowsocks, Socks5Local, Socks5Remote};

/// Dttings for API access methods.
/// Settings for API access methods.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Settings {
pub direct: AccessMethodSetting,
Expand All @@ -22,87 +20,59 @@ impl Settings {
/// This function will return an error if a built-in API access is about to
/// be removed.
pub fn remove(&mut self, api_access_method: &Id) -> Result<(), Error> {
match self.find(|x| x.get_id() == *api_access_method) {
None => Ok(()),
Some(access_method_setting) => match access_method_setting.access_method {
let maybe_setting = self
.access_method_settings
.iter()
.find(|setting| setting.get_id() == *api_access_method);

match maybe_setting {
Some(x) => match x.access_method {
AccessMethod::BuiltIn(ref built_in) => Err(Error::RemoveBuiltin {
attempted: built_in.clone(),
}),
AccessMethod::Custom(_) => {
self.retain(|method| method.get_id() != *api_access_method);
self.access_method_settings
.retain(|method| method.get_id() != *api_access_method);
Ok(())
}
},
None => Ok(()),
}
}

/// Search for any [`AccessMethod`] in `api_access_methods` which matches `predicate`.
pub fn find<P>(&self, predicate: P) -> Option<&AccessMethodSetting>
where
P: Fn(&AccessMethodSetting) -> bool,
{
self.access_method_settings
.iter()
.find(|api_access_method| predicate(api_access_method))
}

/// Search for any [`AccessMethod`] in `api_access_methods`.
pub fn find_mut<P>(&mut self, predicate: P) -> Option<&mut AccessMethodSetting>
where
P: Fn(&AccessMethodSetting) -> bool,
{
self.access_method_settings
.iter_mut()
.find(|api_access_method| predicate(api_access_method))
}

/// Search for a particular [`AccessMethod`] in `api_access_methods`.
pub fn find_by_id(&self, element: &Id) -> Option<&AccessMethodSetting> {
self.find(|api_access_method| *element == api_access_method.get_id())
}

/// Search for a particular [`AccessMethod`] in `api_access_methods`.
pub fn find_by_id_mut(&mut self, element: &Id) -> Option<&mut AccessMethodSetting> {
self.find_mut(|api_access_method| *element == api_access_method.get_id())
}

/// Equivalent to [`Vec::retain`].
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&AccessMethodSetting) -> bool,
{
self.access_method_settings.retain(f)
/// Retrieve all [`AccessMethodSetting`]s which are enabled.
pub fn collect_enabled(&self) -> Vec<AccessMethodSetting> {
self.iter()
.filter(|access_method| access_method.enabled)
.cloned()
.collect()
}

/// Clone the content of `api_access_methods`.
pub fn cloned(&self) -> Vec<AccessMethodSetting> {
self.access_method_settings.clone()
/// Iterate over references of built-in & custom access methods.
pub fn iter(&self) -> impl Iterator<Item = &AccessMethodSetting> {
use std::iter::once;
once(&self.direct)
.chain(once(&self.mullvad_bridges))
.chain(&self.access_method_settings)
}

/// Get a reference to the `Direct` access method instance of this [`Settings`].
pub fn get_direct(&mut self) -> Option<&mut AccessMethodSetting> {
self.find_mut(|access_method| {
access_method.access_method == BuiltInAccessMethod::Direct.into()
})
/// Iterate over mutable references of built-in & custom access methods.
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut AccessMethodSetting> {
use std::iter::once;
once(&mut self.direct)
.chain(once(&mut self.mullvad_bridges))
.chain(&mut self.access_method_settings)
}

pub fn direct() -> AccessMethodSetting {
let method = BuiltInAccessMethod::Direct;
AccessMethodSetting::new(method.canonical_name(), true, AccessMethod::from(method))
}

pub fn mullvad_bridges() -> AccessMethodSetting {
fn mullvad_bridges() -> AccessMethodSetting {
let method = BuiltInAccessMethod::Bridge;
AccessMethodSetting::new(method.canonical_name(), true, AccessMethod::from(method))
}

/// Retrieve all [`AccessMethodSetting`]s which are enabled.
pub fn collect_enabled(&self) -> Vec<AccessMethodSetting> {
self.cloned()
.into_iter()
.filter(|access_method| access_method.enabled)
.collect()
}
}

impl Default for Settings {
Expand Down Expand Up @@ -145,6 +115,7 @@ impl Id {
/// Tries to parse a UUID from a raw String. If it is successful, an
/// [`Id`] is instantiated.
pub fn from_string(id: String) -> Option<Self> {
use std::str::FromStr;
uuid::Uuid::from_str(&id).ok().map(Self)
}
}
Expand Down

0 comments on commit aba47d3

Please sign in to comment.