Skip to content

Commit

Permalink
Add ClearCustomLists RPC call
Browse files Browse the repository at this point in the history
  • Loading branch information
hulthe committed Apr 10, 2024
1 parent 199a2cb commit 11654e3
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 42 deletions.
1 change: 1 addition & 0 deletions mullvad-cli/src/cmds/custom_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub enum CustomList {
/// A custom list
name: String,
},
// TODO: Add `clear` command?
}

#[derive(Subcommand, Debug)]
Expand Down
101 changes: 65 additions & 36 deletions mullvad-daemon/src/custom_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ where
self.relay_selector
.set_config(new_selector_config(&self.settings));

if self.change_should_cause_reconnect(id) {
if self.change_should_cause_reconnect(Some(id)) {
log::info!("Initiating tunnel restart because a selected custom list was deleted");
self.reconnect_tunnel();
}
Expand Down Expand Up @@ -100,7 +100,7 @@ where
self.relay_selector
.set_config(new_selector_config(&self.settings));

if self.change_should_cause_reconnect(id) {
if self.change_should_cause_reconnect(Some(id)) {
log::info!("Initiating tunnel restart because a selected custom list changed");
self.reconnect_tunnel();
}
Expand All @@ -110,48 +110,77 @@ where
Ok(())
}

fn change_should_cause_reconnect(&self, custom_list_id: Id) -> bool {
pub async fn clear_custom_lists(&mut self) -> Result<(), Error> {
let settings_changed = self
.settings
.update(|settings| {
settings.custom_lists.clear();
})
.await
.map_err(Error::SettingsError);

if let Ok(true) = settings_changed {
self.relay_selector
.set_config(new_selector_config(&self.settings));

if self.change_should_cause_reconnect(None) {
log::info!("Initiating tunnel restart because a selected custom list was deleted");
self.reconnect_tunnel();
}
}

settings_changed?;
Ok(())
}

/// Check whether we need to reconnect after changing custom lists.
///
/// If `custom_list_id` is `Some`, only changes to that custom list will trigger a reconnect.
fn change_should_cause_reconnect(&self, custom_list_id: Option<Id>) -> bool {
use mullvad_types::states::TunnelState;
let mut need_to_reconnect = false;

if let RelaySettings::Normal(relay_settings) = &self.settings.relay_settings {
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
&relay_settings.location
{
need_to_reconnect |= list_id == &custom_list_id;
}
let RelaySettings::Normal(relay_settings) = &self.settings.relay_settings else {
return false;
};

if let TunnelState::Connecting {
endpoint,
location: _,
}
| TunnelState::Connected {
endpoint,
location: _,
} = &self.tunnel_state
{
match endpoint.tunnel_type {
TunnelType::Wireguard => {
if relay_settings.wireguard_constraints.multihop() {
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
&relay_settings.wireguard_constraints.entry_location
{
need_to_reconnect |= list_id == &custom_list_id;
}
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
&relay_settings.location
{
need_to_reconnect |= custom_list_id.map(|id| &id == list_id).unwrap_or(true);
}

if let TunnelState::Connecting {
endpoint,
location: _,
}
| TunnelState::Connected {
endpoint,
location: _,
} = &self.tunnel_state
{
match endpoint.tunnel_type {
TunnelType::Wireguard => {
if relay_settings.wireguard_constraints.multihop() {
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
&relay_settings.wireguard_constraints.entry_location
{
need_to_reconnect |=
custom_list_id.map(|id| &id == list_id).unwrap_or(true);
}
}
}

TunnelType::OpenVpn => {
if !matches!(self.settings.bridge_state, BridgeState::Off) {
if let Ok(ResolvedBridgeSettings::Normal(bridge_settings)) =
self.settings.bridge_settings.resolve()
TunnelType::OpenVpn => {
if !matches!(self.settings.bridge_state, BridgeState::Off) {
if let Ok(ResolvedBridgeSettings::Normal(bridge_settings)) =
self.settings.bridge_settings.resolve()
{
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
&bridge_settings.location
{
if let Constraint::Only(LocationConstraint::CustomList {
list_id,
}) = &bridge_settings.location
{
need_to_reconnect |= list_id == &custom_list_id;
}
need_to_reconnect |=
custom_list_id.map(|id| &id == list_id).unwrap_or(true);
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions mullvad-daemon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ pub enum DaemonCommand {
DeleteCustomList(ResponseTx<(), Error>, mullvad_types::custom_list::Id),
/// Update a custom list with a given id
UpdateCustomList(ResponseTx<(), Error>, CustomList),
/// Remove all custom lists
ClearCustomLists(ResponseTx<(), Error>),
/// Add API access methods
AddApiAccessMethod(
ResponseTx<mullvad_types::access_method::Id, Error>,
Expand Down Expand Up @@ -1255,6 +1257,7 @@ where
CreateCustomList(tx, name) => self.on_create_custom_list(tx, name).await,
DeleteCustomList(tx, id) => self.on_delete_custom_list(tx, id).await,
UpdateCustomList(tx, update) => self.on_update_custom_list(tx, update).await,
ClearCustomLists(tx) => self.on_clear_custom_lists(tx).await,
GetVersionInfo(tx) => self.on_get_version_info(tx),
AddApiAccessMethod(tx, name, enabled, access_method) => {
self.on_add_access_method(tx, name, enabled, access_method)
Expand Down Expand Up @@ -2435,6 +2438,11 @@ where
Self::oneshot_send(tx, result, "update_custom_list response");
}

async fn on_clear_custom_lists(&mut self, tx: ResponseTx<(), Error>) {
let result = self.clear_custom_lists().await;
Self::oneshot_send(tx, result, "clear_custom_lists response");
}

async fn on_add_access_method(
&mut self,
tx: ResponseTx<mullvad_types::access_method::Id, Error>,
Expand Down
10 changes: 10 additions & 0 deletions mullvad-daemon/src/management_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,16 @@ impl ManagementService for ManagementServiceImpl {
.map_err(map_daemon_error)
}

async fn clear_custom_lists(&self, _: Request<()>) -> ServiceResult<()> {
log::debug!("clear_custom_lists");
let (tx, rx) = oneshot::channel();
self.send_command_to_daemon(DaemonCommand::ClearCustomLists(tx))?;
self.wait_for_result(rx)
.await?
.map(Response::new)
.map_err(map_daemon_error)
}

// Access Methods

async fn add_api_access_method(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ service ManagementService {
rpc CreateCustomList(google.protobuf.StringValue) returns (google.protobuf.StringValue) {}
rpc DeleteCustomList(google.protobuf.StringValue) returns (google.protobuf.Empty) {}
rpc UpdateCustomList(CustomList) returns (google.protobuf.Empty) {}
rpc ClearCustomLists(google.protobuf.Empty) returns (google.protobuf.Empty) {}

// Access methods
rpc AddApiAccessMethod(NewAccessMethodSetting) returns (UUID) {}
Expand Down
8 changes: 8 additions & 0 deletions mullvad-management-interface/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,14 @@ impl MullvadProxyClient {
Ok(())
}

pub async fn clear_custom_lists(&mut self) -> Result<()> {
self.0
.clear_custom_lists(())
.await
.map_err(map_custom_list_error)?;
Ok(())
}

pub async fn add_access_method(
&mut self,
name: String,
Expand Down
5 changes: 5 additions & 0 deletions mullvad-types/src/custom_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ impl CustomListsSettings {
pub fn remove(&mut self, index: usize) {
self.custom_lists.remove(index);
}

/// Remove all custom lists
pub fn clear(&mut self) {
self.custom_lists.clear();
}
}

impl IntoIterator for CustomListsSettings {
Expand Down
11 changes: 5 additions & 6 deletions test/test-manager/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,11 @@ pub async fn cleanup_after_test(mullvad_client: &mut MullvadProxyClient) -> anyh
.await
.context("Could not clear PQ options in cleanup")?;

for custom_list in custom_lists {
mullvad_client
.delete_custom_list(custom_list.name)
.await
.context("Could not remove custom list")?;
}
let _ = custom_lists;
mullvad_client
.clear_custom_lists()
.await
.context("Could not remove custom list")?;

Ok(())
}

0 comments on commit 11654e3

Please sign in to comment.