cosmic-applets/cosmic-applet-network/src/network_manager/current_networks.rs

173 lines
5.5 KiB
Rust
Raw Normal View History

// SPDX-License-Identifier: GPL-3.0-or-later
use cosmic_dbus_networkmanager::{
2023-11-13 10:38:28 -05:00
active_connection::ActiveConnection, device::SpecificDevice,
interface::enums::ActiveConnectionState,
};
use std::net::Ipv4Addr;
2024-12-04 22:33:41 +02:00
use super::hw_address::HwAddress;
pub async fn active_connections(
active_connections: Vec<ActiveConnection<'_>>,
) -> zbus::Result<Vec<ActiveConnectionInfo>> {
let mut info = Vec::<ActiveConnectionInfo>::with_capacity(active_connections.len());
for connection in active_connections {
let ipv4 = connection
.ip4_config()
.await?
.address_data()
.await
.unwrap_or_default();
let addresses: Vec<_> = ipv4.iter().map(|d| d.address).collect();
let state = connection
.state()
.await
2023-11-17 07:04:57 +00:00
.unwrap_or(ActiveConnectionState::Unknown);
if connection.vpn().await.unwrap_or_default() {
info.push(ActiveConnectionInfo::Vpn {
name: connection.id().await?,
ip_addresses: addresses.clone(),
});
continue;
}
for device in connection.devices().await.unwrap_or_default() {
match device
.downcast_to_device()
.await
.ok()
.and_then(|inner| inner)
{
Some(SpecificDevice::Wired(wired_device)) => {
info.push(ActiveConnectionInfo::Wired {
name: connection.id().await?,
hw_address: HwAddress::from_str(&wired_device.hw_address().await?)
2024-12-04 22:33:41 +02:00
.unwrap_or_default(),
speed: wired_device.speed().await?,
ip_addresses: addresses.clone(),
});
}
Some(SpecificDevice::Wireless(wireless_device)) => {
if let Ok(access_point) = wireless_device.active_access_point().await {
info.push(ActiveConnectionInfo::WiFi {
name: String::from_utf8_lossy(&access_point.ssid().await?).into_owned(),
ip_addresses: addresses.clone(),
hw_address: HwAddress::from_str(&wireless_device.hw_address().await?)
.unwrap_or_default(),
state,
strength: access_point.strength().await.unwrap_or_default(),
});
}
}
Some(SpecificDevice::WireGuard(_)) => {
info.push(ActiveConnectionInfo::Vpn {
name: connection.id().await?,
ip_addresses: addresses.clone(),
});
}
_ => {}
}
}
}
info.sort();
Ok(info)
}
#[derive(Debug, Clone)]
pub enum ActiveConnectionInfo {
Wired {
name: String,
2024-12-04 22:33:41 +02:00
hw_address: HwAddress,
speed: u32,
ip_addresses: Vec<Ipv4Addr>,
},
WiFi {
name: String,
ip_addresses: Vec<Ipv4Addr>,
2024-12-04 22:33:41 +02:00
hw_address: HwAddress,
state: ActiveConnectionState,
strength: u8,
},
Vpn {
name: String,
ip_addresses: Vec<Ipv4Addr>,
},
}
2023-01-04 22:12:46 -05:00
impl ActiveConnectionInfo {
pub fn name(&self) -> String {
match &self {
Self::Wired { name, .. } | Self::WiFi { name, .. } | Self::Vpn { name, .. } => {
name.clone()
}
2023-01-04 22:12:46 -05:00
}
}
2024-12-04 22:33:41 +02:00
pub fn hw_address(&self) -> HwAddress {
match &self {
Self::Wired { hw_address, .. } | Self::WiFi { hw_address, .. } => *hw_address,
2024-12-04 22:33:41 +02:00
Self::Vpn { .. } => HwAddress::default(),
}
}
2023-01-04 22:12:46 -05:00
}
impl std::cmp::Ord for ActiveConnectionInfo {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(Self::Vpn { .. }, Self::Wired { .. } | Self::WiFi { .. })
| (Self::Wired { .. }, Self::WiFi { .. }) => std::cmp::Ordering::Greater,
(Self::WiFi { .. }, Self::Wired { .. } | Self::Vpn { .. })
| (Self::Wired { .. }, Self::Vpn { .. }) => std::cmp::Ordering::Less,
(Self::Vpn { name: n1, .. }, Self::Vpn { name: n2, .. })
| (Self::Wired { name: n1, .. }, Self::Wired { name: n2, .. })
| (Self::WiFi { name: n1, .. }, Self::WiFi { name: n2, .. }) => n1.cmp(n2),
}
}
}
impl std::cmp::Eq for ActiveConnectionInfo {}
impl std::cmp::PartialOrd for ActiveConnectionInfo {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl std::cmp::PartialEq for ActiveConnectionInfo {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(
Self::Wired {
name: n1,
hw_address: a1,
..
},
Self::Wired {
name: n2,
hw_address: a2,
..
},
)
| (
Self::WiFi {
name: n1,
hw_address: a1,
..
},
Self::WiFi {
name: n2,
hw_address: a2,
..
},
) => n1 == n2 && a1 == a2,
(Self::Vpn { name: n1, .. }, Self::Vpn { name: n2, .. }) => n1 == n2,
_ => false,
}
}
}