diff options
| author | David Lönnhager <david.l@mullvad.net> | 2022-05-10 13:29:00 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2022-05-10 13:29:00 +0200 |
| commit | e817b5e83072df627235397f50b0597e2066cd52 (patch) | |
| tree | 58f258e631828f1ae999719b6eea9b8beef6ab4d | |
| parent | ffb55003448bbe1e09765a2ff00d3e386a37d6c8 (diff) | |
| parent | 21a44b75d95b83d328365ad0cafba75f693d526d (diff) | |
| download | mullvadvpn-e817b5e83072df627235397f50b0597e2066cd52.tar.xz mullvadvpn-e817b5e83072df627235397f50b0597e2066cd52.zip | |
Merge branch 'refactor-device-removal'
| -rw-r--r-- | mullvad-daemon/src/device/mod.rs | 30 | ||||
| -rw-r--r-- | mullvad-daemon/src/device/service.rs | 33 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 64 |
3 files changed, 59 insertions, 68 deletions
diff --git a/mullvad-daemon/src/device/mod.rs b/mullvad-daemon/src/device/mod.rs index dc43ce9ee1..ebf51c5210 100644 --- a/mullvad-daemon/src/device/mod.rs +++ b/mullvad-daemon/src/device/mod.rs @@ -4,7 +4,7 @@ use futures::{ stream::StreamExt, }; -use mullvad_api::{availability::ApiAvailabilityHandle, rest}; +use mullvad_api::rest; use mullvad_types::{ account::AccountToken, device::{AccountAndDevice, Device, DeviceEvent, DeviceId, DeviceName, DevicePort}, @@ -201,7 +201,6 @@ enum AccountManagerCommand { RotateKey(ResponseTx<()>), SetRotationInterval(RotationInterval, ResponseTx<()>), ValidateDevice(ResponseTx<()>), - ReceiveEvents(Box<dyn Sender<PrivateDeviceEvent> + Send>, ResponseTx<()>), Shutdown(oneshot::Sender<()>), } @@ -253,16 +252,6 @@ impl AccountManagerHandle { .await } - pub async fn receive_events( - &self, - events_tx: impl Sender<PrivateDeviceEvent> + Send + 'static, - ) -> Result<(), Error> { - self.send_command(|tx| { - AccountManagerCommand::ReceiveEvents(Box::new(events_tx) as Box<_>, tx) - }) - .await - } - pub async fn shutdown(self) { let (tx, rx) = oneshot::channel(); let _ = self @@ -296,14 +285,17 @@ pub(crate) struct AccountManager { } impl AccountManager { + /// Starts the account manager actor and returns a handle to it as well as the + /// current device. pub async fn spawn( rest_handle: rest::MullvadRestHandle, - api_availability: ApiAvailabilityHandle, settings_dir: &Path, initial_rotation_interval: RotationInterval, - ) -> Result<AccountManagerHandle, Error> { + listener_tx: impl Sender<PrivateDeviceEvent> + Send + 'static, + ) -> Result<(AccountManagerHandle, Option<PrivateAccountAndDevice>), Error> { let (cacher, data) = DeviceCacher::new(settings_dir).await?; let token = data.as_ref().map(|state| state.account_token.clone()); + let api_availability = rest_handle.availability.clone(); let account_service = service::spawn_account_service(rest_handle.clone(), token, api_availability.clone()); @@ -313,9 +305,9 @@ impl AccountManager { let manager = AccountManager { cacher, device_service: device_service.clone(), - data, + data: data.clone(), rotation_interval: initial_rotation_interval, - listeners: vec![], + listeners: vec![Box::new(listener_tx)], last_validation: None, validation_requests: vec![], rotation_requests: vec![], @@ -328,7 +320,7 @@ impl AccountManager { account_service, device_service, }; - Ok(handle) + Ok((handle, data)) } async fn run(mut self, mut cmd_rx: mpsc::UnboundedReceiver<AccountManagerCommand>) { @@ -397,9 +389,6 @@ impl AccountManager { } Some(AccountManagerCommand::ValidateDevice(tx)) => { self.handle_validation_request(tx, &mut current_api_call); - } - Some(AccountManagerCommand::ReceiveEvents(events_tx, tx)) => { - let _ = tx.send(Ok(self.listeners.push(events_tx))); }, None => { @@ -862,6 +851,7 @@ impl DeviceCacher { let _ = tokio::task::spawn_blocking(move || drop(std_file)).await; } } + /// Checks if the current device is valid if a WireGuard tunnel cannot be set up /// after multiple attempts. pub(crate) struct TunnelStateChangeHandler { diff --git a/mullvad-daemon/src/device/service.rs b/mullvad-daemon/src/device/service.rs index f511a35f67..c2b09d322a 100644 --- a/mullvad-daemon/src/device/service.rs +++ b/mullvad-daemon/src/device/service.rs @@ -105,7 +105,38 @@ impl DeviceService { }) } - pub async fn remove_device(&self, token: AccountToken, device: DeviceId) -> Result<(), Error> { + pub async fn remove_device( + &self, + account_token: AccountToken, + device_id: DeviceId, + ) -> Result<(Device, Vec<Device>), Error> { + let mut devices = self.list_devices(account_token.clone()).await?; + self.remove_device_inner(account_token, device_id.clone()) + .await?; + if let Some(index) = devices.iter().position(|device| device.id == device_id) { + Ok((devices.swap_remove(index), devices)) + } else { + // You would only end up here if the API service successfully removed a device that + // was previously not included in the list returned by it, which should be impossible. + // Just return a bogus device in its place. + log::error!("List did not contain the revoked device"); + Ok(( + Device { + id: device_id, + name: "unknown device".to_string(), + pubkey: talpid_types::net::wireguard::PublicKey::from([0u8; 32]), + ports: vec![], + }, + devices, + )) + } + } + + async fn remove_device_inner( + &self, + token: AccountToken, + device: DeviceId, + ) -> Result<(), Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); retry_future_n( diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 302a0f8f57..fee22f1d70 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -597,26 +597,18 @@ where migrations::MigrationComplete::new(true) }; - let account_manager = device::AccountManager::spawn( + let (account_manager, data) = device::AccountManager::spawn( api_handle.clone(), - api_availability.clone(), &settings_dir, settings .tunnel_options .wireguard .rotation_interval .unwrap_or_default(), + internal_event_tx.to_specialized_sender(), ) .await .map_err(Error::LoadAccountManager)?; - account_manager - .receive_events(internal_event_tx.to_specialized_sender()) - .await - .map_err(Error::LoadAccountManager)?; - let data = account_manager - .data() - .await - .map_err(Error::LoadAccountManager)?; let account_history = account_history::AccountHistory::new( &settings_dir, @@ -1376,50 +1368,28 @@ where async fn on_remove_device( &mut self, tx: ResponseTx<(), Error>, - token: AccountToken, + account_token: AccountToken, device_id: DeviceId, ) { let device_service = self.account_manager.device_service.clone(); let event_listener = self.event_listener.clone(); tokio::spawn(async move { - let mut devices = match device_service - .list_devices(token.clone()) + let result = device_service + .remove_device(account_token.clone(), device_id) .await - .map_err(Error::ListDevicesError) - { - Ok(devices) => devices, - Err(error) => { - Self::oneshot_send(tx, Err(error), "remove_device response"); - return; - } - }; - if let Err(error) = device_service - .remove_device(token.clone(), device_id.clone()) - .await - .map_err(Error::RemoveDeviceError) - { - Self::oneshot_send(tx, Err(error), "remove_device response"); - return; - }; - let removed_device = - if let Some(index) = devices.iter().position(|device| device.id == device_id) { - devices.swap_remove(index) - } else { - log::error!("List did not contain the revoked device"); - Device { - id: device_id, - name: "unknown device".to_string(), - pubkey: talpid_types::net::wireguard::PublicKey::from([0u8; 32]), - ports: vec![], - } - }; - event_listener.notify_remove_device_event(RemoveDeviceEvent { - account_token: token, - removed_device, - new_devices: devices, - }); - Self::oneshot_send(tx, Ok(()), "remove_device response"); + .map(move |(removed_device, new_devices)| { + event_listener.notify_remove_device_event(RemoveDeviceEvent { + account_token, + removed_device, + new_devices, + }); + }); + Self::oneshot_send( + tx, + result.map_err(Error::RemoveDeviceError), + "remove_device response", + ); }); } |
