use std::collections::HashMap;
use tokio::sync::watch;
use zbus::Connection;
use zvariant::OwnedValue;
use crate::Result;
use crate::api::models::access_point::AccessPoint;
use crate::api::models::{
AirplaneModeState, Device, Network, NetworkInfo, RadioState, SavedConnection,
SavedConnectionBrief, SettingsPatch, WifiDevice, WifiSecurity,
};
use crate::api::wifi_scope::WifiScope;
use crate::core::airplane;
use crate::core::bluetooth::connect_bluetooth;
use crate::core::connection::{
connect, connect_to_bssid, connect_wired, disconnect, forget_by_name_and_type,
get_device_by_interface, is_connected,
};
use crate::core::connection_settings::{get_saved_connection_path, has_saved_connection};
use crate::core::device::{
is_connecting, list_bluetooth_devices, list_devices, wait_for_wifi_ready,
};
use crate::core::saved_connection as saved_profiles;
use crate::core::scan::{current_network, list_access_points, list_networks, scan_networks};
use crate::core::vpn::{
active_vpn_connections, connect_vpn, connect_vpn_by_id, connect_vpn_by_uuid, disconnect_vpn,
disconnect_vpn_by_uuid, get_vpn_info, list_vpn_connections,
};
use crate::core::wifi_device::{list_wifi_devices, set_wifi_enabled_for_interface};
use crate::models::{
BluetoothDevice, BluetoothIdentity, VpnConfig, VpnConfiguration, VpnConnection,
VpnConnectionInfo,
};
use crate::monitoring::device as device_monitor;
use crate::monitoring::info::show_details;
use crate::monitoring::network as network_monitor;
use crate::monitoring::wifi::{current_connection_info, current_ssid};
use crate::types::constants::device_type;
#[derive(Debug, Clone)]
pub struct NetworkManager {
conn: Connection,
timeout_config: crate::api::models::TimeoutConfig,
}
impl NetworkManager {
pub async fn new() -> Result<Self> {
let conn = Connection::system().await?;
Ok(Self {
conn,
timeout_config: crate::api::models::TimeoutConfig::default(),
})
}
pub async fn with_config(timeout_config: crate::api::models::TimeoutConfig) -> Result<Self> {
let conn = Connection::system().await?;
Ok(Self {
conn,
timeout_config,
})
}
#[must_use]
pub fn timeout_config(&self) -> crate::api::models::TimeoutConfig {
self.timeout_config
}
pub async fn list_devices(&self) -> Result<Vec<Device>> {
list_devices(&self.conn).await
}
pub async fn list_bluetooth_devices(&self) -> Result<Vec<BluetoothDevice>> {
list_bluetooth_devices(&self.conn).await
}
pub async fn list_wireless_devices(&self) -> Result<Vec<Device>> {
let devices = list_devices(&self.conn).await?;
Ok(devices.into_iter().filter(|d| d.is_wireless()).collect())
}
pub async fn list_wired_devices(&self) -> Result<Vec<Device>> {
let devices = list_devices(&self.conn).await?;
Ok(devices.into_iter().filter(|d| d.is_wired()).collect())
}
pub async fn list_networks(&self, interface: Option<&str>) -> Result<Vec<Network>> {
list_networks(&self.conn, interface).await
}
pub async fn list_wifi_devices(&self) -> Result<Vec<WifiDevice>> {
list_wifi_devices(&self.conn).await
}
pub async fn wifi_device_by_interface(&self, name: &str) -> Result<WifiDevice> {
let all = list_wifi_devices(&self.conn).await?;
all.into_iter()
.find(|d| d.interface == name)
.ok_or_else(|| crate::ConnectionError::WifiInterfaceNotFound {
interface: name.to_string(),
})
}
#[must_use]
pub fn wifi(&self, interface: impl Into<String>) -> WifiScope {
WifiScope {
conn: self.conn.clone(),
interface: interface.into(),
timeout_config: self.timeout_config,
}
}
pub async fn list_access_points(&self, interface: Option<&str>) -> Result<Vec<AccessPoint>> {
list_access_points(&self.conn, interface).await
}
pub async fn connect_to_bssid(
&self,
ssid: &str,
bssid: Option<&str>,
interface: Option<&str>,
creds: WifiSecurity,
) -> Result<()> {
connect_to_bssid(
&self.conn,
ssid,
bssid,
creds,
interface,
Some(self.timeout_config),
)
.await
}
pub async fn connect(
&self,
ssid: &str,
interface: Option<&str>,
creds: WifiSecurity,
) -> Result<()> {
connect(
&self.conn,
ssid,
creds,
interface,
Some(self.timeout_config),
)
.await
}
pub async fn connect_wired(&self) -> Result<()> {
connect_wired(&self.conn, Some(self.timeout_config)).await
}
pub async fn connect_bluetooth(&self, name: &str, identity: &BluetoothIdentity) -> Result<()> {
connect_bluetooth(&self.conn, name, identity, Some(self.timeout_config)).await
}
pub async fn connect_vpn<C>(&self, config: C) -> Result<()>
where
C: VpnConfig + Into<VpnConfiguration>,
{
connect_vpn(&self.conn, config.into(), Some(self.timeout_config)).await
}
pub async fn import_ovpn(
&self,
path: impl AsRef<std::path::Path>,
username: Option<&str>,
password: Option<&str>,
) -> Result<()> {
use crate::builders::OpenVpnBuilder;
let mut builder = OpenVpnBuilder::from_ovpn_file(path)?;
if let Some(u) = username {
builder = builder.username(u);
}
if let Some(p) = password {
builder = builder.password(p);
}
let config = builder.build()?;
self.connect_vpn(config).await
}
pub async fn disconnect_vpn(&self, name: &str) -> Result<()> {
disconnect_vpn(&self.conn, name).await
}
pub async fn list_vpn_connections(&self) -> Result<Vec<VpnConnection>> {
list_vpn_connections(&self.conn).await
}
pub async fn active_vpn_connections(&self) -> Result<Vec<VpnConnection>> {
active_vpn_connections(&self.conn).await
}
pub async fn connect_vpn_by_uuid(&self, uuid: &str) -> Result<()> {
connect_vpn_by_uuid(&self.conn, uuid, Some(self.timeout_config)).await
}
pub async fn connect_vpn_by_id(&self, id: &str) -> Result<()> {
connect_vpn_by_id(&self.conn, id, Some(self.timeout_config)).await
}
pub async fn disconnect_vpn_by_uuid(&self, uuid: &str) -> Result<()> {
disconnect_vpn_by_uuid(&self.conn, uuid).await
}
pub async fn forget_vpn(&self, name: &str) -> Result<()> {
crate::core::vpn::forget_vpn(&self.conn, name).await
}
pub async fn get_vpn_info(&self, name: &str) -> Result<VpnConnectionInfo> {
get_vpn_info(&self.conn, name).await
}
pub async fn wifi_state(&self) -> Result<RadioState> {
airplane::wifi_state(&self.conn).await
}
pub async fn wwan_state(&self) -> Result<RadioState> {
airplane::wwan_state(&self.conn).await
}
pub async fn bluetooth_radio_state(&self) -> Result<RadioState> {
airplane::bluetooth_radio_state(&self.conn).await
}
pub async fn airplane_mode_state(&self) -> Result<AirplaneModeState> {
airplane::airplane_mode_state(&self.conn).await
}
pub async fn set_wireless_enabled(&self, enabled: bool) -> Result<()> {
airplane::set_wireless_enabled(&self.conn, enabled).await
}
pub async fn set_wwan_enabled(&self, enabled: bool) -> Result<()> {
airplane::set_wwan_enabled(&self.conn, enabled).await
}
pub async fn set_bluetooth_radio_enabled(&self, enabled: bool) -> Result<()> {
airplane::set_bluetooth_radio_enabled(&self.conn, enabled).await
}
pub async fn set_airplane_mode(&self, enabled: bool) -> Result<()> {
airplane::set_airplane_mode(&self.conn, enabled).await
}
pub async fn connectivity(&self) -> Result<crate::ConnectivityState> {
crate::core::connectivity::connectivity(&self.conn).await
}
pub async fn check_connectivity(&self) -> Result<crate::ConnectivityState> {
crate::core::connectivity::check_connectivity(&self.conn).await
}
pub async fn connectivity_report(&self) -> Result<crate::ConnectivityReport> {
crate::core::connectivity::connectivity_report(&self.conn).await
}
pub async fn captive_portal_url(&self) -> Result<Option<String>> {
let report = crate::core::connectivity::connectivity_report(&self.conn).await?;
Ok(report.captive_portal_url)
}
pub async fn set_wifi_enabled(&self, interface: &str, enabled: bool) -> Result<()> {
set_wifi_enabled_for_interface(&self.conn, interface, enabled).await
}
pub async fn wait_for_wifi_ready(&self) -> Result<()> {
wait_for_wifi_ready(&self.conn).await
}
pub async fn scan_networks(&self, interface: Option<&str>) -> Result<()> {
scan_networks(&self.conn, interface).await
}
pub async fn is_connecting(&self) -> Result<bool> {
is_connecting(&self.conn).await
}
pub async fn is_connected(&self, ssid: &str) -> Result<bool> {
is_connected(&self.conn, ssid).await
}
pub async fn disconnect(&self, interface: Option<&str>) -> Result<()> {
disconnect(&self.conn, interface, Some(self.timeout_config)).await
}
pub async fn current_network(&self) -> Result<Option<Network>> {
current_network(&self.conn).await
}
pub async fn list_saved_connections(&self) -> Result<Vec<SavedConnection>> {
saved_profiles::list_saved_connections(&self.conn).await
}
pub async fn list_saved_connections_brief(&self) -> Result<Vec<SavedConnectionBrief>> {
saved_profiles::list_saved_connections_brief(&self.conn).await
}
pub async fn list_saved_connection_ids(&self) -> Result<Vec<String>> {
Ok(saved_profiles::list_saved_connections_brief(&self.conn)
.await?
.into_iter()
.map(|c| c.id)
.collect())
}
pub async fn get_saved_connection(&self, uuid: &str) -> Result<SavedConnection> {
saved_profiles::get_saved_connection(&self.conn, uuid).await
}
pub async fn get_saved_connection_raw(
&self,
uuid: &str,
) -> Result<HashMap<String, HashMap<String, OwnedValue>>> {
saved_profiles::get_saved_connection_raw(&self.conn, uuid).await
}
pub async fn delete_saved_connection(&self, uuid: &str) -> Result<()> {
saved_profiles::delete_saved_connection(&self.conn, uuid).await
}
pub async fn update_saved_connection(&self, uuid: &str, patch: SettingsPatch) -> Result<()> {
saved_profiles::update_saved_connection(&self.conn, uuid, &patch).await
}
pub async fn reload_saved_connections(&self) -> Result<()> {
saved_profiles::reload_saved_connections(&self.conn).await
}
pub async fn get_device_by_interface(&self, name: &str) -> Result<zvariant::OwnedObjectPath> {
get_device_by_interface(&self.conn, name).await
}
#[must_use]
pub async fn current_ssid(&self) -> Option<String> {
current_ssid(&self.conn).await
}
#[must_use]
pub async fn current_connection_info(&self) -> Option<(String, Option<u32>)> {
current_connection_info(&self.conn).await
}
pub async fn show_details(&self, net: &Network) -> Result<NetworkInfo> {
show_details(&self.conn, net).await
}
pub async fn has_saved_connection(&self, ssid: &str) -> Result<bool> {
has_saved_connection(&self.conn, ssid).await
}
pub async fn get_saved_connection_path(
&self,
ssid: &str,
) -> Result<Option<zvariant::OwnedObjectPath>> {
get_saved_connection_path(&self.conn, ssid).await
}
pub async fn forget(&self, ssid: &str) -> Result<()> {
forget_by_name_and_type(
&self.conn,
ssid,
Some(device_type::WIFI),
Some(self.timeout_config),
)
.await
}
pub async fn forget_bluetooth(&self, name: &str) -> Result<()> {
forget_by_name_and_type(
&self.conn,
name,
Some(device_type::BLUETOOTH),
Some(self.timeout_config),
)
.await
}
pub async fn monitor_network_changes<F>(&self, callback: F) -> Result<()>
where
F: Fn() + Send + 'static,
{
let (_tx, rx) = watch::channel(());
network_monitor::monitor_network_changes(&self.conn, rx, callback).await
}
pub async fn monitor_device_changes<F>(&self, callback: F) -> Result<()>
where
F: Fn() + Send + 'static,
{
let (_tx, rx) = watch::channel(());
device_monitor::monitor_device_changes(&self.conn, rx, callback).await
}
}