Skip to content

Commit

Permalink
Add docstrings and restructure code
Browse files Browse the repository at this point in the history
  • Loading branch information
dormant-user committed Sep 21, 2024
1 parent 230cc46 commit d394dae
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 82 deletions.
2 changes: 2 additions & 0 deletions src/squire/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ pub mod custom;
pub mod authenticator;
/// Module for the functions that handle encryption/encoding and decryption/decoding.
pub mod secure;
/// Module for utility functions.
pub mod util;
4 changes: 2 additions & 2 deletions src/squire/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ pub fn default_host() -> String {
/// Returns the default port (8000)
pub fn default_port() -> u16 { 8000 }

/// Returns the default session duration (3600 seconds)
pub fn default_session_duration() -> i64 { 3600 }
/// Returns the default session duration (900 seconds)
pub fn default_session_duration() -> i64 { 900 }

/// Returns the default number of worker threads (half of logical cores)
pub fn default_workers() -> usize {
Expand Down
87 changes: 87 additions & 0 deletions src/squire/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use regex::Regex;
use std::collections::HashMap;

/// Function to retrieve the REGEX object for an IPv4 address format
///
/// # Returns
///
/// A `Regex` object that can be used to match an IPv4 address format
pub fn ip_regex() -> Regex {
Regex::new(
r"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"
).unwrap()
}

/// Mapping of URLs to check for public IP addresses
///
/// # Returns
///
/// A `HashMap` containing the URL and a boolean value indicating whether the URL expects text or JSON response
pub fn public_ip_mapping() -> HashMap<String, bool> {
let mapping: HashMap<String, bool> = vec![
("https://checkip.amazonaws.com/".to_string(), true), // expects text
("https://api.ipify.org/".to_string(), true), // expects text
("https://ipinfo.io/ip/".to_string(), true), // expects text
("https://v4.ident.me/".to_string(), true), // expects text
("https://httpbin.org/ip".to_string(), false), // expects JSON
("https://myip.dnsomatic.com/".to_string(), true), // expects text
]
.into_iter()
.collect();
mapping
}


/// Function to convert seconds to human-readable format
///
/// # Arguments
///
/// * `seconds` - The number of seconds to convert
///
/// # Returns
///
/// A `String` containing the human-readable format of the seconds
pub fn convert_seconds(seconds: i64) -> String {
let days = seconds / 86_400; // 86,400 seconds in a day
let hours = (seconds % 86_400) / 3_600; // 3,600 seconds in an hour
let minutes = (seconds % 3_600) / 60; // 60 seconds in a minute
let remaining_seconds = seconds % 60;

let mut result = Vec::new();

if days > 0 {
result.push(format!("{} day{}", days, if days > 1 { "s" } else { "" }));
}
if hours > 0 {
result.push(format!("{} hour{}", hours, if hours > 1 { "s" } else { "" }));
}
if minutes > 0 && result.len() < 2 {
result.push(format!("{} minute{}", minutes, if minutes > 1 { "s" } else { "" }));
}
if remaining_seconds > 0 && result.len() < 2 {
result.push(format!("{} second{}", remaining_seconds, if remaining_seconds > 1 { "s" } else { "" }));
}
result.join(" and ")
}

/// Function to convert byte size to human-readable format
///
/// # Arguments
///
/// * `byte_size` - The size in bytes to convert
///
/// # Returns
///
/// A `String` containing the human-readable format of the byte size
pub fn size_converter(byte_size: u64) -> String {
let size_name = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
let mut index = 0;
let mut size = byte_size as f64;

while size >= 1024.0 && index < size_name.len() - 1 {
size /= 1024.0;
index += 1;
}

format!("{:.2} {}", size, size_name[index])
}
2 changes: 2 additions & 0 deletions src/system_info/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/// This module contains all the system information related functions
pub mod sys_info;
/// This module contains all the network related functions
pub mod network;
79 changes: 50 additions & 29 deletions src/system_info/network.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
use regex::Regex;
use reqwest;
use serde::{Deserialize, Serialize};
use std::net::{SocketAddr, UdpSocket};
use std::net::UdpSocket;
use crate::squire;

// Define the IP regex pattern
fn ip_regex() -> Regex {
Regex::new(
r"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"
).unwrap()
}

// Synchronous function to retrieve the public IP address
/// Function to retrieve the public IP address
///
/// # Returns
///
/// An `Option` containing the public IP address as a `String` if found, otherwise `None`
async fn public_ip_address() -> Option<String> {
let ip_regex = ip_regex();

// Mapping URLs to their expected response types
let mapping: Vec<(&str, bool)> = vec![
("https://checkip.amazonaws.com/", true), // expects text
("https://api.ipify.org/", true), // expects text
("https://ipinfo.io/ip/", true), // expects text
("https://v4.ident.me/", true), // expects text
("https://httpbin.org/ip", false), // expects JSON
("https://myip.dnsomatic.com/", true), // expects text
];
let ip_regex = squire::util::ip_regex();
let mapping = squire::util::public_ip_mapping();

for (url, expects_text) in mapping {
match reqwest::get(url).await {
match reqwest::get(&url).await {
Ok(response) => {
let extracted_ip = if expects_text {
response.text().await.unwrap_or_default().trim().to_string()
Expand All @@ -39,8 +27,8 @@ async fn public_ip_address() -> Option<String> {
return Some(extracted_ip);
}
}
Err(e) => {
eprintln!("Failed to fetch from {}: {}", url, e);
Err(err) => {
log::error!("Failed to fetch from {}: {}", &url, err);
continue; // Move on to the next URL
}
}
Expand All @@ -49,21 +37,54 @@ async fn public_ip_address() -> Option<String> {
None
}

// Function to retrieve the private IP address
/// Function to retrieve the private IP address
///
/// # Returns
///
/// An `Option` containing the private IP address as a `String` if found, otherwise `None`
fn private_ip_address() -> Option<String> {
let socket = UdpSocket::bind("0.0.0.0:0").ok()?;
socket.connect("8.8.8.8:80").ok()?;
let local_addr: SocketAddr = socket.local_addr().ok()?;
let socket = match UdpSocket::bind("0.0.0.0:0") {
Ok(s) => s,
Err(err) => {
log::error!("Failed to bind to a socket: {}", err);
return None;
}
};
if socket.connect("8.8.8.8:80").is_err() {
log::error!("Failed to connect to a socket");
return None;
}
let local_addr = match socket.local_addr() {
Ok(addr) => addr,
Err(err) => {
log::error!("Failed to get local IP address: {}", err);
return None;
}
};
Some(local_addr.ip().to_string())
}

/// Struct to hold the network information of the system
///
/// This struct holds the private and public IP addresses of the system.
///
/// # Fields
///
/// * `private_ip_address` - The private IP address of the system
/// * `public_ip_address` - The public IP address of the system
#[derive(Serialize, Deserialize, Debug)]
pub struct SystemInfoNetwork {
private_ip_address: String,
public_ip_address: String,
}


/// Function to get network information
///
/// This function retrieves the private and public IP addresses of the system.
///
/// # Returns
///
/// A `SystemInfoNetwork` struct containing the private and public IP addresses.
pub async fn get_network_info() -> SystemInfoNetwork {
let private_ip = private_ip_address().unwrap_or_default();
let public_ip = public_ip_address().await.unwrap_or_default();
Expand Down
81 changes: 34 additions & 47 deletions src/system_info/sys_info.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,19 @@
use chrono::Utc;
use serde::{Deserialize, Serialize};
use sysinfo::{DiskExt, System, SystemExt};
use crate::squire;

// Helper function to format the duration
fn convert_seconds(seconds: i64) -> String {
let days = seconds / 86_400; // 86,400 seconds in a day
let hours = (seconds % 86_400) / 3_600; // 3,600 seconds in an hour
let minutes = (seconds % 3_600) / 60; // 60 seconds in a minute
let remaining_seconds = seconds % 60;

let mut result = Vec::new();

if days > 0 {
result.push(format!("{} day{}", days, if days > 1 { "s" } else { "" }));
}
if hours > 0 {
result.push(format!("{} hour{}", hours, if hours > 1 { "s" } else { "" }));
}
if minutes > 0 && result.len() < 2 {
result.push(format!("{} minute{}", minutes, if minutes > 1 { "s" } else { "" }));
}
if remaining_seconds > 0 && result.len() < 2 {
result.push(format!("{} second{}", remaining_seconds, if remaining_seconds > 1 { "s" } else { "" }));
}
result.join(" and ")
}

// Helper function to convert size
fn size_converter(byte_size: u64) -> String {
let size_name = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
let mut index = 0;
let mut size = byte_size as f64;

while size >= 1024.0 && index < size_name.len() - 1 {
size /= 1024.0;
index += 1;
}

format!("{:.2} {}", size, size_name[index])
}

// Struct to hold system information in a JSON-serializable format
/// Struct to hold basic system information
///
/// This struct holds basic system information such as the node name, system name, architecture, CPU cores, and uptime.
///
/// # Fields
///
/// * `node` - The node name of the system
/// * `system` - The system name
/// * `architecture` - The system architecture
/// * `cpu_cores` - The number of CPU cores
/// * `uptime` - The system uptime
#[derive(Serialize, Deserialize, Debug)]
pub struct SystemInfoBasic {
node: String,
Expand All @@ -50,32 +23,46 @@ pub struct SystemInfoBasic {
uptime: String,
}

/// Struct to hold memory and storage information
///
/// This struct holds memory and storage information such as the total memory, total swap, and total storage.
///
/// # Fields
///
/// * `memory` - The total memory of the system
/// * `swap` - The total swap space of the system
/// * `storage` - The total storage space of the system
#[derive(Serialize, Deserialize, Debug)]
pub struct SystemInfoMemStorage {
memory: String,
swap: String,
storage: String,
}


// Function to collect system information and return as a JSON-serializable struct
/// Function to get system information
///
/// This function retrieves system information such as basic system information and memory/storage information.
///
/// # Returns
///
/// A tuple containing the `SystemInfoBasic` and `SystemInfoMemStorage` structs.
pub fn get_sys_info() -> (SystemInfoBasic, SystemInfoMemStorage) {
let mut sys = System::new_all();
sys.refresh_all();

// Uptime
let boot_time = sys.boot_time();
let uptime_duration = Utc::now().timestamp() - boot_time as i64;
let uptime = convert_seconds(uptime_duration);
let uptime = squire::util::convert_seconds(uptime_duration);

let total_memory = size_converter(sys.total_memory()); // in bytes
let total_swap = size_converter(sys.total_swap()); // in bytes
let total_storage = size_converter(sys.disks().iter().map(|disk| disk.total_space()).sum::<u64>());
let total_memory = squire::util::size_converter(sys.total_memory()); // in bytes
let total_swap = squire::util::size_converter(sys.total_swap()); // in bytes
let total_storage = squire::util::size_converter(sys.disks().iter().map(|disk| disk.total_space()).sum::<u64>());

// Basic and Memory/Storage Info
let basic = SystemInfoBasic {
node: sys.host_name().unwrap_or_else(|| "Unknown".to_string()),
system: sys.name().unwrap_or_else(|| "Unknown".to_string()),
node: sys.host_name().unwrap_or("Unknown".to_string()),
system: sys.name().unwrap_or("Unknown".to_string()),
architecture: std::env::consts::ARCH.to_string(),
uptime,
cpu_cores: sys.cpus().len().to_string(),
Expand Down
3 changes: 1 addition & 2 deletions src/templates/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
///
/// # See Also
///
/// - This page is served as a response for all the entry points,
/// when the user tries to access a page without valid authentication.
/// This page is served as a response, when the user tries to access a page without valid authentication.
///
/// # Returns
///
Expand Down
3 changes: 1 addition & 2 deletions src/templates/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
///
/// # See Also
///
/// - This page is served as a response for all the content delivery entry points,
/// when the user's `session_token` is invalid or expired.
/// This page is served as a response when the user's `session_token` is invalid or expired.
///
/// # Returns
///
Expand Down

0 comments on commit d394dae

Please sign in to comment.