Skip to content

Commit 11654e3

Browse files
committed
Add ClearCustomLists RPC call
1 parent 199a2cb commit 11654e3

File tree

8 files changed

+103
-42
lines changed

8 files changed

+103
-42
lines changed

mullvad-cli/src/cmds/custom_list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub enum CustomList {
3131
/// A custom list
3232
name: String,
3333
},
34+
// TODO: Add `clear` command?
3435
}
3536

3637
#[derive(Subcommand, Debug)]

mullvad-daemon/src/custom_list.rs

+65-36
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ where
5656
self.relay_selector
5757
.set_config(new_selector_config(&self.settings));
5858

59-
if self.change_should_cause_reconnect(id) {
59+
if self.change_should_cause_reconnect(Some(id)) {
6060
log::info!("Initiating tunnel restart because a selected custom list was deleted");
6161
self.reconnect_tunnel();
6262
}
@@ -100,7 +100,7 @@ where
100100
self.relay_selector
101101
.set_config(new_selector_config(&self.settings));
102102

103-
if self.change_should_cause_reconnect(id) {
103+
if self.change_should_cause_reconnect(Some(id)) {
104104
log::info!("Initiating tunnel restart because a selected custom list changed");
105105
self.reconnect_tunnel();
106106
}
@@ -110,48 +110,77 @@ where
110110
Ok(())
111111
}
112112

113-
fn change_should_cause_reconnect(&self, custom_list_id: Id) -> bool {
113+
pub async fn clear_custom_lists(&mut self) -> Result<(), Error> {
114+
let settings_changed = self
115+
.settings
116+
.update(|settings| {
117+
settings.custom_lists.clear();
118+
})
119+
.await
120+
.map_err(Error::SettingsError);
121+
122+
if let Ok(true) = settings_changed {
123+
self.relay_selector
124+
.set_config(new_selector_config(&self.settings));
125+
126+
if self.change_should_cause_reconnect(None) {
127+
log::info!("Initiating tunnel restart because a selected custom list was deleted");
128+
self.reconnect_tunnel();
129+
}
130+
}
131+
132+
settings_changed?;
133+
Ok(())
134+
}
135+
136+
/// Check whether we need to reconnect after changing custom lists.
137+
///
138+
/// If `custom_list_id` is `Some`, only changes to that custom list will trigger a reconnect.
139+
fn change_should_cause_reconnect(&self, custom_list_id: Option<Id>) -> bool {
114140
use mullvad_types::states::TunnelState;
115141
let mut need_to_reconnect = false;
116142

117-
if let RelaySettings::Normal(relay_settings) = &self.settings.relay_settings {
118-
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
119-
&relay_settings.location
120-
{
121-
need_to_reconnect |= list_id == &custom_list_id;
122-
}
143+
let RelaySettings::Normal(relay_settings) = &self.settings.relay_settings else {
144+
return false;
145+
};
123146

124-
if let TunnelState::Connecting {
125-
endpoint,
126-
location: _,
127-
}
128-
| TunnelState::Connected {
129-
endpoint,
130-
location: _,
131-
} = &self.tunnel_state
132-
{
133-
match endpoint.tunnel_type {
134-
TunnelType::Wireguard => {
135-
if relay_settings.wireguard_constraints.multihop() {
136-
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
137-
&relay_settings.wireguard_constraints.entry_location
138-
{
139-
need_to_reconnect |= list_id == &custom_list_id;
140-
}
147+
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
148+
&relay_settings.location
149+
{
150+
need_to_reconnect |= custom_list_id.map(|id| &id == list_id).unwrap_or(true);
151+
}
152+
153+
if let TunnelState::Connecting {
154+
endpoint,
155+
location: _,
156+
}
157+
| TunnelState::Connected {
158+
endpoint,
159+
location: _,
160+
} = &self.tunnel_state
161+
{
162+
match endpoint.tunnel_type {
163+
TunnelType::Wireguard => {
164+
if relay_settings.wireguard_constraints.multihop() {
165+
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
166+
&relay_settings.wireguard_constraints.entry_location
167+
{
168+
need_to_reconnect |=
169+
custom_list_id.map(|id| &id == list_id).unwrap_or(true);
141170
}
142171
}
172+
}
143173

144-
TunnelType::OpenVpn => {
145-
if !matches!(self.settings.bridge_state, BridgeState::Off) {
146-
if let Ok(ResolvedBridgeSettings::Normal(bridge_settings)) =
147-
self.settings.bridge_settings.resolve()
174+
TunnelType::OpenVpn => {
175+
if !matches!(self.settings.bridge_state, BridgeState::Off) {
176+
if let Ok(ResolvedBridgeSettings::Normal(bridge_settings)) =
177+
self.settings.bridge_settings.resolve()
178+
{
179+
if let Constraint::Only(LocationConstraint::CustomList { list_id }) =
180+
&bridge_settings.location
148181
{
149-
if let Constraint::Only(LocationConstraint::CustomList {
150-
list_id,
151-
}) = &bridge_settings.location
152-
{
153-
need_to_reconnect |= list_id == &custom_list_id;
154-
}
182+
need_to_reconnect |=
183+
custom_list_id.map(|id| &id == list_id).unwrap_or(true);
155184
}
156185
}
157186
}

mullvad-daemon/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ pub enum DaemonCommand {
279279
DeleteCustomList(ResponseTx<(), Error>, mullvad_types::custom_list::Id),
280280
/// Update a custom list with a given id
281281
UpdateCustomList(ResponseTx<(), Error>, CustomList),
282+
/// Remove all custom lists
283+
ClearCustomLists(ResponseTx<(), Error>),
282284
/// Add API access methods
283285
AddApiAccessMethod(
284286
ResponseTx<mullvad_types::access_method::Id, Error>,
@@ -1255,6 +1257,7 @@ where
12551257
CreateCustomList(tx, name) => self.on_create_custom_list(tx, name).await,
12561258
DeleteCustomList(tx, id) => self.on_delete_custom_list(tx, id).await,
12571259
UpdateCustomList(tx, update) => self.on_update_custom_list(tx, update).await,
1260+
ClearCustomLists(tx) => self.on_clear_custom_lists(tx).await,
12581261
GetVersionInfo(tx) => self.on_get_version_info(tx),
12591262
AddApiAccessMethod(tx, name, enabled, access_method) => {
12601263
self.on_add_access_method(tx, name, enabled, access_method)
@@ -2435,6 +2438,11 @@ where
24352438
Self::oneshot_send(tx, result, "update_custom_list response");
24362439
}
24372440

2441+
async fn on_clear_custom_lists(&mut self, tx: ResponseTx<(), Error>) {
2442+
let result = self.clear_custom_lists().await;
2443+
Self::oneshot_send(tx, result, "clear_custom_lists response");
2444+
}
2445+
24382446
async fn on_add_access_method(
24392447
&mut self,
24402448
tx: ResponseTx<mullvad_types::access_method::Id, Error>,

mullvad-daemon/src/management_interface.rs

+10
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,16 @@ impl ManagementService for ManagementServiceImpl {
598598
.map_err(map_daemon_error)
599599
}
600600

601+
async fn clear_custom_lists(&self, _: Request<()>) -> ServiceResult<()> {
602+
log::debug!("clear_custom_lists");
603+
let (tx, rx) = oneshot::channel();
604+
self.send_command_to_daemon(DaemonCommand::ClearCustomLists(tx))?;
605+
self.wait_for_result(rx)
606+
.await?
607+
.map(Response::new)
608+
.map_err(map_daemon_error)
609+
}
610+
601611
// Access Methods
602612

603613
async fn add_api_access_method(

mullvad-management-interface/proto/management_interface.proto

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ service ManagementService {
7373
rpc CreateCustomList(google.protobuf.StringValue) returns (google.protobuf.StringValue) {}
7474
rpc DeleteCustomList(google.protobuf.StringValue) returns (google.protobuf.Empty) {}
7575
rpc UpdateCustomList(CustomList) returns (google.protobuf.Empty) {}
76+
rpc ClearCustomLists(google.protobuf.Empty) returns (google.protobuf.Empty) {}
7677

7778
// Access methods
7879
rpc AddApiAccessMethod(NewAccessMethodSetting) returns (UUID) {}

mullvad-management-interface/src/client.rs

+8
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,14 @@ impl MullvadProxyClient {
535535
Ok(())
536536
}
537537

538+
pub async fn clear_custom_lists(&mut self) -> Result<()> {
539+
self.0
540+
.clear_custom_lists(())
541+
.await
542+
.map_err(map_custom_list_error)?;
543+
Ok(())
544+
}
545+
538546
pub async fn add_access_method(
539547
&mut self,
540548
name: String,

mullvad-types/src/custom_list.rs

+5
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ impl CustomListsSettings {
9898
pub fn remove(&mut self, index: usize) {
9999
self.custom_lists.remove(index);
100100
}
101+
102+
/// Remove all custom lists
103+
pub fn clear(&mut self) {
104+
self.custom_lists.clear();
105+
}
101106
}
102107

103108
impl IntoIterator for CustomListsSettings {

test/test-manager/src/tests/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,11 @@ pub async fn cleanup_after_test(mullvad_client: &mut MullvadProxyClient) -> anyh
171171
.await
172172
.context("Could not clear PQ options in cleanup")?;
173173

174-
for custom_list in custom_lists {
175-
mullvad_client
176-
.delete_custom_list(custom_list.name)
177-
.await
178-
.context("Could not remove custom list")?;
179-
}
174+
let _ = custom_lists;
175+
mullvad_client
176+
.clear_custom_lists()
177+
.await
178+
.context("Could not remove custom list")?;
180179

181180
Ok(())
182181
}

0 commit comments

Comments
 (0)