From a594e62763129a7afc9771428562da3cc799b8cc Mon Sep 17 00:00:00 2001 From: notplants Date: Mon, 17 Jan 2022 15:16:37 -0500 Subject: [PATCH] Revert "working router" This reverts commit f0a01c1f89d89828a2d77f246dc3cdcf5c680610. --- Cargo.lock | 2 + peach-web/Cargo.toml | 4 +- peach-web/src/context/mod.rs | 2 +- peach-web/src/context/network.rs | 398 +++++++++++++++++++++++++++ peach-web/src/router.rs | 228 +++++---------- peach-web/src/routes/mod.rs | 2 +- peach-web/src/routes/settings/mod.rs | 2 +- 7 files changed, 471 insertions(+), 167 deletions(-) create mode 100644 peach-web/src/context/network.rs diff --git a/Cargo.lock b/Cargo.lock index 1719a15..71095a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2902,6 +2902,8 @@ dependencies = [ "log 0.4.14", "nest", "peach-lib", + "peach-network", + "peach-stats", "rocket", "rocket_dyn_templates", "serde 1.0.133", diff --git a/peach-web/Cargo.toml b/peach-web/Cargo.toml index afabf3f..561a277 100644 --- a/peach-web/Cargo.toml +++ b/peach-web/Cargo.toml @@ -40,8 +40,8 @@ lazy_static = "1.4.0" log = "0.4" nest = "1.0.0" peach-lib = { path = "../peach-lib" } -#peach-network = { path = "../peach-network", features = ["serde_support"] } -#peach-stats = { path = "../peach-stats", features = ["serde_support"] } +peach-network = { path = "../peach-network", features = ["serde_support"] } +peach-stats = { path = "../peach-stats", features = ["serde_support"] } rocket = { version = "0.5.0-rc.1", features = ["json", "secrets"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/peach-web/src/context/mod.rs b/peach-web/src/context/mod.rs index ed845bb..d2d350c 100644 --- a/peach-web/src/context/mod.rs +++ b/peach-web/src/context/mod.rs @@ -1,2 +1,2 @@ pub mod dns; -// pub mod network; +pub mod network; diff --git a/peach-web/src/context/network.rs b/peach-web/src/context/network.rs new file mode 100644 index 0000000..3ce1ee5 --- /dev/null +++ b/peach-web/src/context/network.rs @@ -0,0 +1,398 @@ +//! Data retrieval for the purpose of serving routes and hydrating +//! network-related HTML templates. + +use std::collections::HashMap; + +use rocket::{ + form::FromForm, + serde::{Deserialize, Serialize}, + UriDisplayQuery, +}; + +use peach_network::{ + network, + network::{Scan, Status, Traffic}, +}; + +use crate::{ + utils::{ + monitor, + monitor::{Alert, Data, Threshold}, + }, + AP_IFACE, WLAN_IFACE, +}; + +#[derive(Debug, Serialize)] +pub struct AccessPoint { + pub detail: Option, + pub signal: Option, + pub state: String, +} + +pub fn ap_state() -> String { + match network::state(&*AP_IFACE) { + Ok(Some(state)) => state, + _ => "Interface unavailable".to_string(), + } +} + +#[derive(Debug, Deserialize, FromForm, UriDisplayQuery)] +pub struct Ssid { + pub ssid: String, +} + +#[derive(Debug, Deserialize, FromForm)] +pub struct WiFi { + pub ssid: String, + pub pass: String, +} + +fn convert_traffic(traffic: Traffic) -> Option { + // modify traffic values & assign measurement unit + // based on received and transmitted values + let (rx, rx_unit) = if traffic.received > 1_047_527_424 { + // convert to GB + (traffic.received / 1_073_741_824, "GB".to_string()) + } else if traffic.received > 0 { + // otherwise, convert it to MB + ((traffic.received / 1024) / 1024, "MB".to_string()) + } else { + (0, "MB".to_string()) + }; + + let (tx, tx_unit) = if traffic.transmitted > 1_047_527_424 { + // convert to GB + (traffic.transmitted / 1_073_741_824, "GB".to_string()) + } else if traffic.transmitted > 0 { + ((traffic.transmitted / 1024) / 1024, "MB".to_string()) + } else { + (0, "MB".to_string()) + }; + + Some(IfaceTraffic { + rx, + rx_unit, + tx, + tx_unit, + }) +} + +#[derive(Debug, Serialize)] +pub struct IfaceTraffic { + pub rx: u64, + pub rx_unit: String, + pub tx: u64, + pub tx_unit: String, +} + +#[derive(Debug, Serialize)] +pub struct NetworkAlertContext { + pub alert: Alert, + pub back: Option, + pub data_total: Option, // combined stored and current wifi traffic in bytes + pub flash_name: Option, + pub flash_msg: Option, + pub threshold: Threshold, + pub title: Option, + pub traffic: Option, // current wifi traffic in bytes (since boot) +} + +impl NetworkAlertContext { + pub fn build() -> NetworkAlertContext { + let alert = monitor::get_alerts().unwrap(); + // stored wifi data values as bytes + let stored_traffic = monitor::get_data().unwrap(); + let threshold = monitor::get_thresholds().unwrap(); + + let (traffic, data_total) = match network::traffic(&*WLAN_IFACE) { + // convert bytes to mb or gb and add appropriate units + Ok(Some(t)) => { + let current_traffic = t.received + t.transmitted; + let traffic = convert_traffic(t); + let total = stored_traffic.total + current_traffic; + let data_total = Data { total }; + (traffic, Some(data_total)) + } + _ => (None, None), + }; + + NetworkAlertContext { + alert, + back: None, + data_total, + flash_name: None, + flash_msg: None, + threshold, + title: None, + traffic, + } + } +} + +#[derive(Debug, Serialize)] +pub struct NetworkDetailContext { + pub back: Option, + pub flash_name: Option, + pub flash_msg: Option, + pub selected: Option, + pub title: Option, + pub saved_aps: Vec, + pub wlan_ip: String, + pub wlan_networks: HashMap, + pub wlan_rssi: Option, + pub wlan_ssid: String, + pub wlan_state: String, + pub wlan_status: Option, + pub wlan_traffic: Option, +} + +impl NetworkDetailContext { + pub fn build() -> NetworkDetailContext { + let wlan_ip = match network::ip(&*WLAN_IFACE) { + Ok(Some(ip)) => ip, + _ => "x.x.x.x".to_string(), + }; + + // list of networks saved in wpa_supplicant.conf + let wlan_list = match network::saved_networks() { + Ok(Some(ssids)) => ssids, + _ => Vec::new(), + }; + + // list of networks saved in wpa_supplicant.conf + let saved_aps = wlan_list.clone(); + + let wlan_rssi = match network::rssi_percent(&*WLAN_IFACE) { + Ok(rssi) => rssi, + Err(_) => None, + }; + + // list of networks currently in range (online & accessible) + let wlan_scan = match network::available_networks(&*WLAN_IFACE) { + Ok(Some(networks)) => networks, + _ => Vec::new(), + }; + + let wlan_ssid = match network::ssid(&*WLAN_IFACE) { + Ok(Some(ssid)) => ssid, + _ => "Not connected".to_string(), + }; + + let wlan_state = match network::state(&*WLAN_IFACE) { + Ok(Some(state)) => state, + _ => "Interface unavailable".to_string(), + }; + + let wlan_status = match network::status(&*WLAN_IFACE) { + Ok(status) => status, + // interface unavailable + _ => None, + }; + + let wlan_traffic = match network::traffic(&*WLAN_IFACE) { + // convert bytes to mb or gb and add appropriate units + Ok(Some(traffic)) => convert_traffic(traffic), + _ => None, + }; + + // create a hashmap to combine wlan_list & wlan_scan without repetition + let mut wlan_networks = HashMap::new(); + + for ap in wlan_scan { + 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 { + detail: Some(ap), + state: "Available".to_string(), + signal: Some(quality_percent), + }; + wlan_networks.insert(ssid, ap_detail); + } + + for network in wlan_list { + // avoid repetition by checking that ssid is not already in list + if !wlan_networks.contains_key(&network) { + let ssid = network.clone(); + let net_detail = AccessPoint { + detail: None, + state: "Not in range".to_string(), + signal: None, + }; + wlan_networks.insert(ssid, net_detail); + } + } + + NetworkDetailContext { + back: None, + flash_name: None, + flash_msg: None, + selected: None, + title: None, + saved_aps, + wlan_ip, + wlan_networks, + wlan_rssi, + wlan_ssid, + wlan_state, + wlan_status, + wlan_traffic, + } + } +} + +#[derive(Debug, Serialize)] +pub struct NetworkListContext { + pub ap_state: String, + pub back: Option, + pub flash_name: Option, + pub flash_msg: Option, + pub title: Option, + pub wlan_networks: HashMap, + pub wlan_ssid: String, +} + +impl NetworkListContext { + pub fn build() -> NetworkListContext { + // list of networks saved in wpa_supplicant.conf + let wlan_list = match network::saved_networks() { + Ok(Some(ssids)) => ssids, + _ => Vec::new(), + }; + + // list of networks currently in range (online & accessible) + let wlan_scan = match network::available_networks(&*WLAN_IFACE) { + Ok(Some(networks)) => networks, + _ => Vec::new(), + }; + + let wlan_ssid = match network::ssid(&*WLAN_IFACE) { + Ok(Some(ssid)) => ssid, + _ => "Not connected".to_string(), + }; + + // create a hashmap to combine wlan_list & wlan_scan without repetition + let mut wlan_networks = HashMap::new(); + for ap in wlan_scan { + wlan_networks.insert(ap.ssid, "Available".to_string()); + } + for network in wlan_list { + // insert ssid (with state) only if it doesn't already exist + wlan_networks + .entry(network) + .or_insert_with(|| "Not in range".to_string()); + } + + let ap_state = match network::state(&*AP_IFACE) { + Ok(Some(state)) => state, + _ => "Interface unavailable".to_string(), + }; + + NetworkListContext { + ap_state, + back: None, + flash_msg: None, + flash_name: None, + title: None, + wlan_networks, + wlan_ssid, + } + } +} + +#[derive(Debug, Serialize)] +pub struct NetworkStatusContext { + pub ap_ip: String, + pub ap_ssid: String, + pub ap_state: String, + pub ap_traffic: Option, + pub wlan_ip: String, + pub wlan_rssi: Option, + pub wlan_ssid: String, + pub wlan_state: String, + pub wlan_status: Option, + pub wlan_traffic: Option, + pub flash_name: Option, + pub flash_msg: Option, + // passing in the ssid of a chosen access point + pub selected: Option, + pub title: Option, + pub back: Option, +} + +impl NetworkStatusContext { + pub fn build() -> Self { + let ap_ip = match network::ip(&*AP_IFACE) { + Ok(Some(ip)) => ip, + _ => "x.x.x.x".to_string(), + }; + + let ap_ssid = match network::ssid(&*AP_IFACE) { + Ok(Some(ssid)) => ssid, + _ => "Not currently activated".to_string(), + }; + + let ap_state = match network::state(&*AP_IFACE) { + Ok(Some(state)) => state, + _ => "Interface unavailable".to_string(), + }; + + let ap_traffic = match network::traffic(&*AP_IFACE) { + // convert bytes to mb or gb and add appropriate units + Ok(Some(traffic)) => convert_traffic(traffic), + _ => None, + }; + + let wlan_ip = match network::ip(&*WLAN_IFACE) { + Ok(Some(ip)) => ip, + _ => "x.x.x.x".to_string(), + }; + + let wlan_rssi = match network::rssi_percent(&*WLAN_IFACE) { + Ok(rssi) => rssi, + _ => None, + }; + + let wlan_ssid = match network::ssid(&*WLAN_IFACE) { + Ok(Some(ssid)) => ssid, + _ => "Not connected".to_string(), + }; + + let wlan_state = match network::state(&*WLAN_IFACE) { + Ok(Some(state)) => state, + _ => "Interface unavailable".to_string(), + }; + + let wlan_status = match network::status(&*WLAN_IFACE) { + Ok(status) => status, + _ => None, + }; + + let wlan_traffic = match network::traffic(&*WLAN_IFACE) { + // convert bytes to mb or gb and add appropriate units + Ok(Some(traffic)) => convert_traffic(traffic), + _ => None, + }; + + NetworkStatusContext { + ap_ip, + ap_ssid, + ap_state, + ap_traffic, + wlan_ip, + wlan_rssi, + wlan_ssid, + wlan_state, + wlan_status, + wlan_traffic, + flash_name: None, + flash_msg: None, + selected: None, + title: None, + back: None, + } + } +} diff --git a/peach-web/src/router.rs b/peach-web/src/router.rs index bf72599..77de400 100644 --- a/peach-web/src/router.rs +++ b/peach-web/src/router.rs @@ -6,12 +6,13 @@ use crate::routes::{ catchers::*, index::*, scuttlebutt::*, - settings::{admin::*, dns::*, menu::*, - // network::*, - scuttlebutt::*}, - // status::{device::*, network::*}, + settings::{admin::*, dns::*, menu::*, network::*, scuttlebutt::*}, + status::{device::*, network::*}, }; +/// Create minimal rocket instance and mount routes. This excludes settings +/// and status routes related to networking and the device (memory, +/// hard disk, CPU etc.). pub fn build_minimal_rocket() -> Rocket { rocket::build() .mount( @@ -20,7 +21,12 @@ pub fn build_minimal_rocket() -> Rocket { help, home, login, - login_post + login_post, + logout, + reboot_cmd, + shutdown_cmd, + power_menu, + settings_menu, ], ) // ADMIN SETTINGS HTML ROUTES @@ -41,15 +47,38 @@ pub fn build_minimal_rocket() -> Rocket { ], ) // SCUTTLEBUTT SETTINGS HTML ROUTES + .mount("/settings/scuttlebutt", routes![ssb_settings_menu]) + // SCUTTLEBUTT SOCIAL HTML ROUTES + .mount( + "/scuttlebutt", + routes![ + admin_menu, + configure_admin, + add_admin, + add_admin_post, + delete_admin_post, + change_password, + change_password_post, + reset_password, + reset_password_post, + forgot_password_page, + send_password_reset_post, + ], + ) + // SCUTTLEBUTT SETTINGS HTML ROUTES .mount( "/settings/scuttlebutt", routes![ssb_settings_menu, configure_sbot], ) + // STATUS HTML ROUTES + // TODO: replace this with a route for `scuttlebutt_status` + .mount("/status", routes![device_status, network_status]) .mount("/", FileServer::from("static")) .register("/", catchers![not_found, internal_error, forbidden]) .attach(Template::fairing()) } +/// Create complete rocket instance and mount all routes. pub fn build_complete_rocket() -> Rocket { rocket::build() // GENERAL HTML ROUTES @@ -60,6 +89,11 @@ pub fn build_complete_rocket() -> Rocket { home, login, login_post, + logout, + reboot_cmd, + shutdown_cmd, + power_menu, + settings_menu, ], ) // ADMIN SETTINGS HTML ROUTES @@ -79,35 +113,37 @@ pub fn build_complete_rocket() -> Rocket { send_password_reset_post, ], ) - // // NETWORK SETTINGS HTML ROUTES - // .mount( - // "/settings/network", - // routes![ - // add_credentials, - // connect_wifi, - // configure_dns, - // configure_dns_post, - // disconnect_wifi, - // deploy_ap, - // deploy_client, - // forget_wifi, - // network_home, - // add_ssid, - // add_wifi, - // network_detail, - // wifi_list, - // wifi_password, - // wifi_set_password, - // wifi_usage, - // wifi_usage_alerts, - // wifi_usage_reset, - // ], - // ) // SCUTTLEBUTT SETTINGS HTML ROUTES .mount( "/settings/scuttlebutt", routes![ssb_settings_menu, configure_sbot], ) + // NETWORK SETTINGS HTML ROUTES + .mount( + "/settings/network", + routes![ + add_credentials, + connect_wifi, + configure_dns, + configure_dns_post, + disconnect_wifi, + deploy_ap, + deploy_client, + forget_wifi, + network_home, + add_ssid, + add_wifi, + network_detail, + wifi_list, + wifi_password, + wifi_set_password, + wifi_usage, + wifi_usage_alerts, + wifi_usage_reset, + ], + ) + // SCUTTLEBUTT SETTINGS HTML ROUTES + .mount("/settings/scuttlebutt", routes![ssb_settings_menu]) // SCUTTLEBUTT SOCIAL HTML ROUTES .mount( "/scuttlebutt", @@ -117,140 +153,8 @@ pub fn build_complete_rocket() -> Rocket { ], ) // STATUS HTML ROUTES - // .mount("/status", routes![device_status, network_status]) + .mount("/status", routes![device_status, network_status]) .mount("/", FileServer::from("static")) .register("/", catchers![not_found, internal_error, forbidden]) .attach(Template::fairing()) } - -// -// /// Create minimal rocket instance and mount routes. This excludes settings -// /// and status routes related to networking and the device (memory, -// /// hard disk, CPU etc.). -// pub fn build_minimal_rocket() -> Rocket { -// rocket::build() -// // GENERAL HTML ROUTES -// .mount( -// "/", -// routes![ -// help, -// home, -// login, -// login_post, -// logout, -// reboot_cmd, -// shutdown_cmd, -// power_menu, -// settings_menu, -// ], -// ) -// // ADMIN SETTINGS HTML ROUTES -// .mount( -// "/settings/admin", -// routes![ -// admin_menu, -// configure_admin, -// add_admin, -// add_admin_post, -// delete_admin_post, -// change_password, -// change_password_post, -// reset_password, -// reset_password_post, -// forgot_password_page, -// send_password_reset_post, -// ], -// ) -// // SCUTTLEBUTT SETTINGS HTML ROUTES -// .mount("/settings/scuttlebutt", routes![ssb_settings_menu]) -// // SCUTTLEBUTT SOCIAL HTML ROUTES -// .mount( -// "/scuttlebutt", -// routes![ -// peers, friends, follows, followers, blocks, profile, private, follow, unfollow, -// block, publish, -// ], -// ) -// // STATUS HTML ROUTES -// // TODO: replace this with a route for `scuttlebutt_status` -// .mount("/status", routes![device_status, network_status]) -// .mount("/", FileServer::from("static")) -// .register("/", catchers![not_found, internal_error, forbidden]) -// .attach(Template::fairing()) -// } -// -// /// Create complete rocket instance and mount all routes. -// pub fn build_complete_rocket() -> Rocket { -// rocket::build() -// // GENERAL HTML ROUTES -// .mount( -// "/", -// routes![ -// help, -// home, -// login, -// login_post, -// logout, -// reboot_cmd, -// shutdown_cmd, -// power_menu, -// settings_menu, -// ], -// ) -// // ADMIN SETTINGS HTML ROUTES -// .mount( -// "/settings/admin", -// routes![ -// admin_menu, -// configure_admin, -// add_admin, -// add_admin_post, -// delete_admin_post, -// change_password, -// change_password_post, -// reset_password, -// reset_password_post, -// forgot_password_page, -// send_password_reset_post, -// ], -// ) -// // NETWORK SETTINGS HTML ROUTES -// .mount( -// "/settings/network", -// routes![ -// add_credentials, -// connect_wifi, -// configure_dns, -// configure_dns_post, -// disconnect_wifi, -// deploy_ap, -// deploy_client, -// forget_wifi, -// network_home, -// add_ssid, -// add_wifi, -// network_detail, -// wifi_list, -// wifi_password, -// wifi_set_password, -// wifi_usage, -// wifi_usage_alerts, -// wifi_usage_reset, -// ], -// ) -// // SCUTTLEBUTT SETTINGS HTML ROUTES -// .mount("/settings/scuttlebutt", routes![ssb_settings_menu]) -// // SCUTTLEBUTT SOCIAL HTML ROUTES -// .mount( -// "/scuttlebutt", -// routes![ -// peers, friends, follows, followers, blocks, profile, private, follow, unfollow, -// block, publish, -// ], -// ) -// // STATUS HTML ROUTES -// .mount("/status", routes![device_status, network_status]) -// .mount("/", FileServer::from("static")) -// .register("/", catchers![not_found, internal_error, forbidden]) -// .attach(Template::fairing()) -// } diff --git a/peach-web/src/routes/mod.rs b/peach-web/src/routes/mod.rs index ffd0fd6..830e23b 100644 --- a/peach-web/src/routes/mod.rs +++ b/peach-web/src/routes/mod.rs @@ -3,4 +3,4 @@ pub mod catchers; pub mod index; pub mod scuttlebutt; pub mod settings; -// pub mod status; +pub mod status; diff --git a/peach-web/src/routes/settings/mod.rs b/peach-web/src/routes/settings/mod.rs index 98a061e..1096c8d 100644 --- a/peach-web/src/routes/settings/mod.rs +++ b/peach-web/src/routes/settings/mod.rs @@ -1,5 +1,5 @@ pub mod admin; pub mod dns; pub mod menu; -// pub mod network; +pub mod network; pub mod scuttlebutt;