diff --git a/src/backend/network.rs b/src/backend/network.rs index a5d949d..834b417 100644 --- a/src/backend/network.rs +++ b/src/backend/network.rs @@ -10,7 +10,9 @@ use nmrs::raw::zvariant::OwnedObjectPath; use nmrs::{ActiveConnection, ConnectionError, NetworkEvent, NetworkManager, WifiSecurity}; use std::cmp::Ordering; use std::pin::Pin; +use std::sync::Arc; use std::time::Duration; +use tokio::sync::Mutex; use tokio::sync::mpsc::UnboundedSender; use tokio::time::{Instant, Sleep}; @@ -109,8 +111,8 @@ pub enum NetworkState { ConnectSuccess(String), } -#[derive(Debug, Clone)] -pub struct NetworkBackendHandle { +#[derive(Debug)] +pub struct NetworkBackend { subscribers: Vec>, command_tx: Option>, } @@ -121,7 +123,7 @@ struct EventDebouncer { sleep: Pin>, } -impl BackendThread> for NetworkBackendHandle { +impl BackendThread> for NetworkBackend { fn subscribe( registrator: Sender>, ) -> (Receiver, UnboundedSender) { @@ -143,6 +145,7 @@ impl BackendThread> for NetworkBac fn init(mut self, registration_rx: Receiver>) { let (command_tx, mut command_rx) = tokio::sync::mpsc::unbounded_channel::(); self.command_tx = Some(command_tx); + let instance = Arc::new(Mutex::new(self)); std::thread::spawn(move || { let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() @@ -159,8 +162,8 @@ impl BackendThread> for NetworkBac }; std::thread::spawn({ + let instance = instance.clone(); let nm = nm.clone(); - let mut instance = self.clone(); move || { let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() @@ -169,10 +172,12 @@ impl BackendThread> for NetworkBac runtime.block_on(async move { while let Ok(tx) = registration_rx.recv() { - if tx.send(NetworkState::Init(instance.command_tx.clone().unwrap())).is_ok() { - instance.subscribers.push(tx); - let _ = instance.send_all_networks(&nm).await; - let _ = instance.send_active_connection(&nm).await; + let mut instance_guard = instance.lock().await; + if tx.send(NetworkState::Init(instance_guard.command_tx.clone().unwrap())).is_ok() { + instance_guard.subscribers.push(tx); + println!("Added subscriber: {:?}", instance_guard.subscribers); + let _ = instance_guard.send_all_networks(&nm).await; + let _ = instance_guard.send_active_connection(&nm).await; } } }); @@ -202,15 +207,16 @@ impl BackendThread> for NetworkBac // Run the command without stopping event processing // while a potentially slow connection operation runs. let nm = nm.clone(); - let instance_clone = self.clone(); + let instance = instance.clone(); - tokio::spawn(async move { + tokio::spawn( + async move { match command { - NetworkCommand::ToggleVpn(profile) => instance_clone.toggle_vpn(profile, &nm).await, + NetworkCommand::ToggleVpn(profile) => instance.lock().await.toggle_vpn(profile, &nm).await, NetworkCommand::Connect(ssid, auth) => { if let Ok(saved) = nm.list_saved_connections().await { if saved.iter().find(|c| c.id.eq(&ssid)).is_some() { - instance_clone.connect(&nm, ssid, WifiSecurity::Open).await; + instance.lock().await.connect(&nm, ssid, WifiSecurity::Open).await; } else { match auth { Auth::Open => { @@ -218,19 +224,18 @@ impl BackendThread> for NetworkBac && let Some(ap) = networks.iter().find(|net| net.ssid.eq(&ssid)) { if ap.security.is_open() { - instance_clone.connect(&nm, ssid, WifiSecurity::Open).await; + instance.lock().await.connect(&nm, ssid, WifiSecurity::Open).await; } else { - instance_clone.publish(NetworkState::Auth(ssid, AuthType::Password)); + instance.lock().await.publish(NetworkState::Auth(ssid, AuthType::Password)); } } } - Auth::Password(password) => instance_clone.connect(&nm, ssid, WifiSecurity::WpaPsk { psk: password }).await, + Auth::Password(password) => instance.lock().await.connect(&nm, ssid, WifiSecurity::WpaPsk { psk: password }).await, } } } } }; - let _ = nm; }); } @@ -238,7 +243,7 @@ impl BackendThread> for NetworkBac match event { Some(event_res) => { match event_res { - Ok(event) => self.handle_event(&nm, event, &mut debouncer).await, + Ok(event) => instance.lock().await.handle_event(&nm, event, &mut debouncer).await, Err(err) => error!(&LOGGER, "Error: {err:?}"), } } @@ -247,7 +252,7 @@ impl BackendThread> for NetworkBac } _ = &mut debouncer.sleep, if debouncer.deadline.is_some() => { debouncer.deadline = None; - let _ = self.send_all_networks(&nm).await; + let _ = instance.lock().await.send_all_networks(&nm).await; } } } @@ -256,8 +261,8 @@ impl BackendThread> for NetworkBac } } -impl NetworkBackendHandle { - pub fn new() -> NetworkBackendHandle { +impl NetworkBackend { + pub fn new() -> NetworkBackend { Self { subscribers: vec![], command_tx: None, @@ -434,44 +439,58 @@ impl NetworkBackendHandle { async fn send_active_connection(&self, nm: &NetworkManager) { trace!(&LOGGER, "Sending Active Connection"); if let Ok(connections) = nm.list_active_connections().await { - let connection = if let Some(primary) = Self::primary_connection(nm).await { - connections.iter().find(|c| match c { - ActiveConnection::Wired(c) => c.uuid.eq(&primary), - ActiveConnection::Wifi(c) => c.uuid.eq(&primary), - _ => false, - }) + let Some(connection) = (if let Some(primary) = Self::primary_connection(nm).await { + connections + .iter() + .find(|c| match c { + ActiveConnection::Wired(c) => c.uuid.eq(&primary), + ActiveConnection::Wifi(c) => c.uuid.eq(&primary), + _ => false, + }) + .cloned() } else { - connections.first() - }; - match connection { - Some(conn) => { + let mut iter = connections.into_iter(); + loop { + let Some(conn) = iter.next() else { + break None; + }; match conn { - ActiveConnection::Wired(c) => { - let info = NetworkInfo { - name: c.id.clone(), - network_type: NetworkType::Wired, - signal: 0, - secured: None, - known: true, - }; - self.publish(NetworkState::ChangeNetwork(Some(info))); + ActiveConnection::Other(_) | ActiveConnection::Vpn(_) => continue, + other => { + break Some(other); } - ActiveConnection::Wifi(c) => { - let info = NetworkInfo { - name: c.ssid.clone(), - network_type: NetworkType::Wifi, - signal: c.strength.unwrap_or(0), - secured: None, // Not relevant here - known: true, - }; - self.publish(NetworkState::ChangeNetwork(Some(info))); - } - _ => {} } } - None => { - self.publish(NetworkState::ChangeNetwork(None)); + }) else { + debug!(&LOGGER, "Disconnected from all Networks"); + self.publish(NetworkState::ChangeNetwork(None)); + return; + }; + debug!(&LOGGER, "Found active connection: {connection:#?}"); + match connection { + ActiveConnection::Wired(c) => { + let info = NetworkInfo { + name: c.id.clone(), + network_type: NetworkType::Wired, + signal: 0, + secured: None, + known: true, + }; + debug!(&LOGGER, "Connected to wired network"); + self.publish(NetworkState::ChangeNetwork(Some(info))); } + ActiveConnection::Wifi(c) => { + let info = NetworkInfo { + name: c.ssid.clone(), + network_type: NetworkType::Wifi, + signal: c.strength.unwrap_or(0), + secured: None, // Not relevant here + known: true, + }; + debug!(&LOGGER, "Connected to wireless network"); + self.publish(NetworkState::ChangeNetwork(Some(info))); + } + _ => {} } } }