use std::process::{ Command, Output };
use super::connector::{ WifiConnectError, WifiConnector };
use super::credentials::{ WifiCredentials, WifiSecurity };
pub struct LinuxNetworkManagerConnector;
impl LinuxNetworkManagerConnector {
fn check_output_status(output: Output) -> Result<(), WifiConnectError> {
if output.status.success() {
Ok(())
} else {
Err(
WifiConnectError::CommandFailed(String::from_utf8_lossy(&output.stderr).to_string())
)
}
}
fn delete_network_profile(&self, credentials: &WifiCredentials) {
let _ = Command::new("nmcli") .args(["connection", "delete", credentials.ssid.as_str()])
.output();
}
}
impl WifiConnector for LinuxNetworkManagerConnector {
fn connect(&self, credentials: &WifiCredentials) -> Result<(), WifiConnectError> {
match credentials.security_type {
WifiSecurity::Wpa => {
let password = credentials.password
.as_ref() .ok_or(WifiConnectError::MissingPassword)?;
self.delete_network_profile(credentials);
let add_output = Command::new("nmcli") .args([
"connection",
"add",
"type", "wifi",
"ifname", "*",
"con-name", credentials.ssid.as_str(), "ssid", credentials.ssid.as_str(),
"wifi-sec.key-mgmt", "wpa-psk",
"wifi-sec.psk", password.as_str(),
])
.output()?;
Self::check_output_status(add_output)?;
let up_output = Command::new("nmcli") .args(["connection", "up", credentials.ssid.as_str()])
.output()?;
Self::check_output_status(up_output)
}
WifiSecurity::Wep => { Err(WifiConnectError::UnsupportedSecurity) }
WifiSecurity::Open => {
self.delete_network_profile(credentials);
let add_output = Command::new("nmcli")
.args([
"connection",
"add",
"type",
"wifi",
"ifname",
"*",
"con-name",
credentials.ssid.as_str(),
"ssid",
credentials.ssid.as_str(),
])
.output()?;
Self::check_output_status(add_output)?;
let up_output = Command::new("nmcli")
.args(["connection", "up", credentials.ssid.as_str()])
.output()?;
Self::check_output_status(up_output)
}
}
}
}