Update active networks without needing to poll every 5 seconds

This commit is contained in:
Lucy 2022-02-10 14:25:25 -05:00
parent 9b60cc758b
commit fc8e6e4d4d
No known key found for this signature in database
GPG key ID: EBC517FAD666BBF1

View file

@ -1,10 +1,15 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
use cosmic_dbus_networkmanager::{ use cosmic_dbus_networkmanager::{
active_connection::ActiveConnection,
device::SpecificDevice, device::SpecificDevice,
interface::enums::{ApFlags, ApSecurityFlags}, interface::{
active_connection::ActiveConnectionProxy,
enums::{ApFlags, ApSecurityFlags},
},
nm::NetworkManager, nm::NetworkManager,
}; };
use futures_util::StreamExt;
use gtk4::{ use gtk4::{
glib::{self, clone, source::PRIORITY_DEFAULT, MainContext, Sender}, glib::{self, clone, source::PRIORITY_DEFAULT, MainContext, Sender},
prelude::*, prelude::*,
@ -127,72 +132,92 @@ fn render_vpn(name: String, ip_addresses: Vec<IpAddr>) -> gtk4::Box {
async fn handle_devices(tx: Sender<Vec<ActiveConnectionInfo>>) -> zbus::Result<()> { async fn handle_devices(tx: Sender<Vec<ActiveConnectionInfo>>) -> zbus::Result<()> {
let conn = Connection::system().await?; let conn = Connection::system().await?;
let network_manager = NetworkManager::new(&conn).await?; let network_manager = NetworkManager::new(&conn).await?;
loop { handle_active_connections(tx.clone(), network_manager.active_connections().await?).await?;
let active_connections = network_manager.active_connections().await?; let mut active_connections_changed = network_manager.receive_active_connections_changed().await;
let mut info = Vec::<ActiveConnectionInfo>::with_capacity(active_connections.len()); while let Some(active_connection_objects) = active_connections_changed.next().await {
for connection in active_connections { let active_connection_objects = active_connection_objects.get().await?;
if connection.vpn().await? { let mut active_connections = Vec::with_capacity(active_connection_objects.len());
let mut ip_addresses = Vec::new(); for object in active_connection_objects {
for address_data in connection.ip4_config().await?.address_data().await? { active_connections.push(
ip_addresses.push(IpAddr::V4(address_data.address)); ActiveConnectionProxy::builder(&conn)
} .path(object)?
for address_data in connection.ip6_config().await?.address_data().await? { .build()
ip_addresses.push(IpAddr::V6(address_data.address)); .await
} .map(ActiveConnection::from)?,
info.push(ActiveConnectionInfo::Vpn { );
name: connection.id().await?, }
ip_addresses, handle_active_connections(tx.clone(), active_connections).await?;
}); }
continue; Ok(())
}
async fn handle_active_connections(
tx: Sender<Vec<ActiveConnectionInfo>>,
active_connections: Vec<ActiveConnection<'_>>,
) -> zbus::Result<()> {
let mut info = Vec::<ActiveConnectionInfo>::with_capacity(active_connections.len());
for connection in active_connections {
if connection.vpn().await? {
let mut ip_addresses = Vec::new();
for address_data in connection.ip4_config().await?.address_data().await? {
ip_addresses.push(IpAddr::V4(address_data.address));
} }
for device in connection.devices().await? { for address_data in connection.ip6_config().await?.address_data().await? {
match device.downcast_to_device().await? { ip_addresses.push(IpAddr::V6(address_data.address));
Some(SpecificDevice::Wired(wired_device)) => { }
let mut ip_addresses = Vec::new(); info.push(ActiveConnectionInfo::Vpn {
for address_data in device.ip4_config().await?.address_data().await? { name: connection.id().await?,
ip_addresses.push(IpAddr::V4(address_data.address)); ip_addresses,
} });
for address_data in device.ip6_config().await?.address_data().await? { continue;
ip_addresses.push(IpAddr::V6(address_data.address)); }
} for device in connection.devices().await? {
info.push(ActiveConnectionInfo::Wired { match device.downcast_to_device().await? {
name: connection.id().await?, Some(SpecificDevice::Wired(wired_device)) => {
hw_address: wired_device.hw_address().await?, let mut ip_addresses = Vec::new();
speed: wired_device.speed().await?, for address_data in device.ip4_config().await?.address_data().await? {
ip_addresses, ip_addresses.push(IpAddr::V4(address_data.address));
});
} }
Some(SpecificDevice::Wireless(wireless_device)) => { for address_data in device.ip6_config().await?.address_data().await? {
let access_point = wireless_device.active_access_point().await?; ip_addresses.push(IpAddr::V6(address_data.address));
info.push(ActiveConnectionInfo::WiFi {
name: String::from_utf8_lossy(&access_point.ssid().await?).into_owned(),
hw_address: wireless_device.hw_address().await?,
flags: access_point.flags().await?,
rsn_flags: access_point.rsn_flags().await?,
wpa_flags: access_point.wpa_flags().await?,
});
} }
Some(SpecificDevice::WireGuard(_)) => { info.push(ActiveConnectionInfo::Wired {
let mut ip_addresses = Vec::new(); name: connection.id().await?,
for address_data in connection.ip4_config().await?.address_data().await? { hw_address: wired_device.hw_address().await?,
ip_addresses.push(IpAddr::V4(address_data.address)); speed: wired_device.speed().await?,
} ip_addresses,
for address_data in connection.ip6_config().await?.address_data().await? { });
ip_addresses.push(IpAddr::V6(address_data.address));
}
info.push(ActiveConnectionInfo::Vpn {
name: connection.id().await?,
ip_addresses,
});
}
_ => {}
} }
Some(SpecificDevice::Wireless(wireless_device)) => {
let access_point = wireless_device.active_access_point().await?;
info.push(ActiveConnectionInfo::WiFi {
name: String::from_utf8_lossy(&access_point.ssid().await?).into_owned(),
hw_address: wireless_device.hw_address().await?,
flags: access_point.flags().await?,
rsn_flags: access_point.rsn_flags().await?,
wpa_flags: access_point.wpa_flags().await?,
});
}
Some(SpecificDevice::WireGuard(_)) => {
let mut ip_addresses = Vec::new();
for address_data in connection.ip4_config().await?.address_data().await? {
ip_addresses.push(IpAddr::V4(address_data.address));
}
for address_data in connection.ip6_config().await?.address_data().await? {
ip_addresses.push(IpAddr::V6(address_data.address));
}
info.push(ActiveConnectionInfo::Vpn {
name: connection.id().await?,
ip_addresses,
});
}
_ => {}
} }
} }
tx.send(info)
.expect("failed to send active connections back to main thread");
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
} }
tx.send(info)
.expect("failed to send active connections back to main thread");
Ok(())
} }
enum ActiveConnectionInfo { enum ActiveConnectionInfo {