From a513b7aa5b9429a8610a8df3d4eb71562fb32815 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 27 Sep 2022 14:51:09 +0100 Subject: [PATCH] add method to return list of all saved and in-range access points for the given interface --- peach-network/src/network.rs | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/peach-network/src/network.rs b/peach-network/src/network.rs index fe3dd1c..f0ec5d8 100644 --- a/peach-network/src/network.rs +++ b/peach-network/src/network.rs @@ -14,6 +14,7 @@ //! access point credentials to `wpa_supplicant-.conf`. use std::{ + collections::HashMap, fs::OpenOptions, io::prelude::*, process::{Command, Stdio}, @@ -106,8 +107,86 @@ pub struct Traffic { pub transmitted: u64, } +/// Access point data including state and signal strength. +#[derive(Debug)] +#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct AccessPoint { + /// Access point data retrieved via scan. + pub detail: Option, + /// Current state of the access point (e.g. "Available" or "Out of range"). + pub state: String, + /// Signal strength of the access point as a percentage. + pub signal: Option, +} + +impl AccessPoint { + fn available(detail: Option, signal: Option) -> AccessPoint { + AccessPoint { + detail, + state: String::from("Available"), + signal, + } + } + + fn saved() -> AccessPoint { + AccessPoint { + detail: None, + state: String::from("Out of range"), + signal: None, + } + } +} + /* GET - Methods for retrieving data */ +/// Retrieve combined list of available (in-range) and saved wireless access +/// points for a given network interface. +/// +/// # Arguments +/// +/// * `iface` - A string slice holding the name of a wireless network interface +/// +/// If the list results include one or more access points for the given network +/// interface, an `Ok` `Result` type is returned containing `HashMap`. +/// +/// Each entry in the returned `HashMap` contains an SSID (`String`) and +/// `AccessPoint` `struct`. If no access points are found, an empty `HashMap` +/// is returned in the `Result`. In the event of an error, a `NetworkError` +/// is returned in the `Result`. +pub fn all_networks(iface: &str) -> Result, NetworkError> { + let mut wlan_networks = HashMap::new(); + + if let Ok(Some(networks)) = available_networks(iface) { + for ap in networks { + let ssid = ap.ssid.clone(); + + let rssi = ap.signal_level.clone(); + // parse the string to a signed integer (for math) + let rssi_parsed = rssi.parse::().unwrap(); + // perform rssi (dBm) to quality (%) conversion + let quality_percent = 2 * (rssi_parsed + 100); + + let ap_detail = AccessPoint::available(Some(ap), Some(quality_percent)); + wlan_networks.insert(ssid, ap_detail); + } + } + + if let Ok(Some(networks)) = saved_networks() { + for saved_ssid in networks { + if !wlan_networks.contains_key(&saved_ssid) { + let ssid = saved_ssid.clone(); + + let ap_detail = AccessPoint::saved(); + wlan_networks.insert(ssid, ap_detail); + } + } + } + + Ok(wlan_networks) +} + /// Retrieve list of available wireless access points for a given network /// interface. ///