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