96 lines
3.6 KiB
Rust
96 lines
3.6 KiB
Rust
use crate::connectors::types::{
|
|
Connects, ListsNetworkInterfaces, ListsNetworks, Network, NetworkInterface,
|
|
};
|
|
use crate::connectors::utils::call_exec;
|
|
use std::borrow::BorrowMut;
|
|
use std::str::Split;
|
|
|
|
pub struct NetworkManagerConnector {}
|
|
|
|
impl NetworkManagerConnector {
|
|
fn call_nmcli(&self, add_args: Vec<&str>) -> Result<Vec<u8>, String> {
|
|
let args = vec!["-t", "-m", "tabular", "-c", "no", "-o", "-e", "yes"]
|
|
.into_iter()
|
|
.chain(add_args.into_iter())
|
|
.collect();
|
|
call_exec("networkmanager", "nmcli", args)
|
|
}
|
|
|
|
fn get_nmcli(&self, add_args: Vec<&str>) -> Result<Vec<Vec<String>>, String> {
|
|
let output = self
|
|
.call_nmcli(add_args)
|
|
.expect("calling networkmanager failed");
|
|
let res = String::from_utf8(output).expect("networkmanager returned non-utf8");
|
|
let lines: Vec<&str> = res.split("\n").filter(|ln| !ln.is_empty()).collect();
|
|
let lines_with_fields: Vec<Split<&str>> = lines.into_iter().map(|line| line.split(":")).collect();
|
|
let mut parsed: Vec<Vec<String>> = vec![];
|
|
for old_fields_immut in lines_with_fields.clone() {
|
|
let mut old_fields = old_fields_immut;
|
|
let mut new_fields: Vec<String> = vec![];
|
|
let mut continuation = false;
|
|
loop {
|
|
match old_fields.next() {
|
|
Some(field) => {
|
|
let mut new_field = match continuation {
|
|
true => new_fields.pop().expect("new field").to_string(),
|
|
false => "".to_string(),
|
|
};
|
|
if continuation {
|
|
new_field.push(':');
|
|
}
|
|
new_field.push_str(match field.strip_suffix("\\") {
|
|
Some(stripped) => stripped,
|
|
None => field,
|
|
});
|
|
new_fields.push(new_field);
|
|
continuation = field.ends_with("\\");
|
|
},
|
|
None => {
|
|
let parsed_line = new_fields;
|
|
parsed.push(parsed_line);
|
|
break
|
|
},
|
|
}
|
|
}
|
|
}
|
|
Ok(parsed)
|
|
}
|
|
}
|
|
|
|
impl ListsNetworkInterfaces for NetworkManagerConnector {
|
|
fn list_network_interfaces(&self) -> Result<Vec<NetworkInterface>, String> {
|
|
let iface_list = match self.get_nmcli(
|
|
vec!["-f", "DEVICE,TYPE,STATE,CONNECTION", "device"],
|
|
) {
|
|
Ok(list) => list,
|
|
Err(err) => return Err(err),
|
|
};
|
|
let ifaces = iface_list.into_iter().map(|ifa| NetworkInterface {
|
|
machine_name: ifa[0].clone(),
|
|
enabled: ifa[2] != "unavailable",
|
|
..Default::default()
|
|
}).collect();
|
|
Ok(ifaces)
|
|
}
|
|
}
|
|
|
|
impl ListsNetworks for NetworkManagerConnector {
|
|
fn list_networks(&self, iface: &NetworkInterface) -> Result<Vec<Network>, String> {
|
|
let net_list = match self.get_nmcli(vec![
|
|
"-f", "SSID,BSSID,CHAN,SIGNAL,WPA-FLAGS,IN-USE",
|
|
"device", "wifi", "list", "ifname", &iface.machine_name],
|
|
) {
|
|
Ok(list) => list,
|
|
Err(err) => return Err(err),
|
|
};
|
|
let nets = net_list.into_iter().map(|net| Network {
|
|
ssid: net[0].to_string(),
|
|
bssid: Some(net[1].to_string()),
|
|
channel: Some(net[2].parse::<u8>().unwrap()),
|
|
rssi: Some(net[3].parse::<i8>().unwrap()),
|
|
..Default::default()
|
|
}).collect();
|
|
Ok(nets)
|
|
}
|
|
}
|