From f4c071a5f4bd17bc57666e2d957a749cf0fa2d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20P=C5=82aczek?= Date: Fri, 13 Sep 2024 00:24:41 +0100 Subject: [PATCH] docs: simple docs for `main.rs` --- Cargo.toml | 2 +- build.rs | 7 +++++ src/main.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 22617bc..f1b3838 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ unused_imports = "deny" unused_variables = "deny" unused_must_use = "deny" dead_code = "warn" -missing_docs = "allow" +missing_docs = "deny" [lints.clippy] all = { level = "warn", priority = -1 } diff --git a/build.rs b/build.rs index 21871ce..c1958c4 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,10 @@ +//! RSPI-BIOS build script +//! Author: Piotr Placzek (piotrpdev) +//! SPDX-License-Identifier: GPL-3.0-only + +/// Parses `RSPI_BIOS_VERSION` environment variable and passes it to `main.rs`. +/// +/// Used in CI for automatic versioning instead of manually creating tags. fn main() { let version = std::env::var("RSPI_BIOS_VERSION").unwrap_or_else(|_| "dev".to_string()); println!("cargo:rustc-env=RSPI_BIOS_VERSION={version}"); diff --git a/src/main.rs b/src/main.rs index 6e9f88f..72d025b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,7 @@ +//! RSPI-BIOS: Raspberry Pi dashboard that mimics the style of old BIOS designs. +//! Author: Piotr Placzek (piotrpdev) +//! SPDX-License-Identifier: GPL-3.0-only + use std::env; use std::net::{IpAddr, Ipv4Addr}; use std::path::PathBuf; @@ -107,12 +111,19 @@ struct Args { force_debug_local: bool, } -// https://stackoverflow.com/a/72314001/19020549 +/// Used for parsing [`Duration`] in [`clap`] CLI parameters e.g. `graceful_shutdown_duration` +/// +/// Taken from: fn parse_duration(arg: &str) -> Result { let seconds = arg.parse()?; Ok(Duration::from_secs(seconds)) } +/// State used by different parts of the app, including [`tokio`] tasks. +/// +/// Has to be thread safe. +/// +/// Stores some system information to avoid recomputing it every time. struct AppState { args: Mutex, system_tx: watch::Sender, @@ -124,6 +135,18 @@ struct AppState { networks: Mutex, } +/// Main function. Returns [`ExitCode`] on error. +/// +/// Sets up: +/// - Logging +/// - TLS config +/// - State for the HTTPS server +/// +/// Spawns [`tokio`] tasks to handle: +/// - Graceful shutdown +/// - `HTTP` to `HTTPS` redirection +/// - Expensive system information fetching +/// - `HTTPS` server #[allow(clippy::too_many_lines)] #[tokio::main] async fn main() -> ExitCode { @@ -287,7 +310,9 @@ async fn main() -> ExitCode { ExitCode::SUCCESS } -/// Returns `false` on failure +/// Runs the main `HTTPS` server. +/// +/// Returns `false` if starting the server fails e.g. if unable to bind to port. async fn https_server( addr: std::net::SocketAddr, state: Arc, @@ -319,8 +344,11 @@ async fn https_server( true } -// https://github.com/tokio-rs/axum/blob/6efcb75d99a437fa80c81e2308ec8234b023e1a7/examples/tls-rustls/src/main.rs -/// Returns `false` on failure +/// Runs the server that redirects `HTTP` requests to the `HTTPS` server. +/// +/// Returns `false` if starting the server fails e.g. if unable to bind to port. +/// +/// Based on example code from: #[allow(clippy::similar_names)] async fn redirect_http_to_https( ip_address: std::net::IpAddr, @@ -389,6 +417,7 @@ async fn redirect_http_to_https( true } +/// Describes data used in the provided [`askama`] `index.html` template. #[derive(Template)] #[template(path = "index.html")] struct IndexTemplate { @@ -411,8 +440,10 @@ struct IndexTemplate { cpu_arch: String, } +/// Generic [`askama`] template type. struct HtmlTemplate(T); +/// Renders the provided [`askama`] template. impl IntoResponse for HtmlTemplate where T: Template, @@ -429,6 +460,9 @@ where } } +/// Handles `GET` requests to `index.html`. +/// +/// Takes [`sysinfo`] data, formats it into a nicer looking format, and returns a rendered [`askama`] template containing it. async fn index_handler( ConnectInfo(addr): ConnectInfo, state: State>, @@ -517,6 +551,9 @@ async fn index_handler( HtmlTemplate(template) } +/// Handles [Server-Sent Events (SSE)](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events). +/// +/// Uses a [`WatchStream`] to only send users the latest information. async fn sse_handler( ConnectInfo(addr): ConnectInfo, state: State>, @@ -531,6 +568,10 @@ async fn sse_handler( .keep_alive(KeepAlive::new().interval(state.args.lock().await.sse_keep_alive_interval)) } +/// Creates SSE events used by `sse_handler()`. +/// +/// Some system information is expensive to fetch for every connection, this function does so once every couple of +/// seconds and sends it to `sse_handler()` instances over a [`watch`]. async fn send_system_messages(state: Arc) { let mut interval = tokio::time::interval(state.args.lock().await.system_refresh_interval); loop { @@ -563,8 +604,13 @@ async fn send_system_messages(state: Arc) { } } -// https://github.com/tokio-rs/axum/blob/1ac617a1b540e8523347f5ee889d65cad9a45ec4/examples/tls-graceful-shutdown/src/main.rs -// https://github.com/programatik29/axum-server/blob/d48b1a931909d156177bc87684910769e67be905/examples/graceful_shutdown.rs +/// Shuts down the `HTTPS` server gracefully by initially refusing new connections, then terminating after a given period. +/// +/// Shutdown initiated via `SIGTERM` or `CTRL+C`. +/// +/// Based on these examples: +/// - +/// - async fn graceful_shutdown( handle: axum_server::Handle, graceful_shutdown_duration: Duration, @@ -607,6 +653,11 @@ async fn graceful_shutdown( } } +/// Searches for `.pem` TLS certificate and key files in the provided directories. +/// +/// Attempts to create a [`RustlsConfig`] using them. +/// +/// Returns [`None`] if process was unsuccessful. async fn create_tls_config( cert_dirs_to_search: Vec, tls_cert_file_name: &str, @@ -634,10 +685,10 @@ async fn create_tls_config( None } -fn get_cert_dirs_to_search( - exe_path: &std::path::Path, - tls_dir: &std::path::Path, -) -> std::vec::Vec { +/// Creates list of directories to search for `.pem` TLS certificate and key files. +/// +/// Returned list varies depending on platform and release vs development build. +fn get_cert_dirs_to_search(exe_path: &std::path::Path, tls_dir: &std::path::Path) -> Vec { let mut cert_dirs_to_search = Vec::::new(); if cfg!(debug_assertions) { @@ -661,11 +712,14 @@ fn get_cert_dirs_to_search( cert_dirs_to_search } +/// Returns path to use for `debug.log` file. +/// +/// Returned path varies depending on platform and release vs development build. fn get_log_path( exe_path: &std::path::Path, log_path_arg: &std::path::Path, force_debug_local: bool, -) -> std::path::PathBuf { +) -> PathBuf { let exe_log_path = { let mut log_path = exe_path.to_path_buf(); log_path.pop();