Implement missing features, some cleanup

This commit is contained in:
Nils Andreas Svee committed 2022-09-28 00:25:35 +02:00
1 parent c06078fccb
commit e3b7b7e9ba
12 files changed
+704 -174

No files matched your search

+190 -35
View File
@@ -1,3 +1,5 @@
use crate::error::{ConfigParseError, MissingConfigError};
use log::Level;
#[cfg(feature = "uci")]
use rust_uci::Uci;
use std::error::Error;
@@ -16,55 +18,208 @@ where
Ok(io::BufReader::new(file).lines())
}
#[allow(dead_code)]
#[derive(Clone)]
#[derive(Clone, Debug)]
pub(crate) enum AutorateType {
ICMP = 1,
ICMPTimestamps,
NTP,
TCPTimestamps,
}
#[derive(Clone, Debug)]
pub(crate) struct Config {
// Network section
pub(crate) download_interface: String,
pub(crate) upload_interface: String,
pub(crate) download_base_kbits: f64,
pub(crate) download_min_kbits: f64,
pub(crate) upload_base_kbits: f64,
pub(crate) upload_min_kbits: f64,
pub(crate) reflector_list_file: String,
// Output section
pub(crate) log_level: Level,
pub(crate) speed_hist_file: String,
pub(crate) stats_file: String,
pub(crate) suppress_statistics: bool,
// Advanced section
pub(crate) download_delay_ms: f64,
pub(crate) high_load_level: f64,
pub(crate) min_change_interval: f64,
pub(crate) num_reflectors: u8,
pub(crate) tick_duration: f64,
pub(crate) reflector_list_file: String,
pub(crate) speed_hist_size: u32,
pub(crate) tick_interval: f64,
pub(crate) upload_delay_ms: f64,
}
impl Config {
pub fn new() -> Self {
// First try to load from UCI (if enabled), if nothing is returned, use the environment instead.
match Self::load_from_uci() {
Some(config) => config,
None => Self {
download_interface: env::var("DOWNLOAD_INTERFACE")
.expect("A download interface is required"),
upload_interface: env::var("UPLOAD_INTERFACE")
.expect("A upload interface is required"),
reflector_list_file: env::var("REFLECTOR_LIST_FILE")
.expect("A reflector list is required"),
min_change_interval: 0.5,
num_reflectors: 5,
tick_duration: 0.5,
},
}
}
#[cfg(feature = "uci")]
fn load_from_uci() -> Option<Self> {
let uci: Uci = Uci::new().expect("Couldn't create UCI instance");
Some(Self {
download_interface: "wan".to_string(),
upload_interface: "wan".to_string(),
reflector_list_file: "".to_string(),
min_change_interval: 0.5,
num_reflectors: 5,
tick_duration: 0.5,
pub fn new() -> Result<Self, Box<dyn Error>> {
Ok(Self {
// Network section
download_base_kbits: Self::get::<f64>(
"SQMA_DOWNLOAD_BASE_KBITS",
"sqm-autorate.@network[0].download_base_kbits",
None,
)?,
download_interface: Self::get::<String>(
"SQMA_DOWNLOAD_INTERFACE",
"sqm-autorate.@network[0].download_interface",
None,
)?,
download_min_kbits: Self::get::<f64>(
"SQMA_DOWNLOAD_MIN_KBITS",
"sqm-autorate.@network[0].download_min_kbits",
None,
)?,
upload_base_kbits: Self::get::<f64>(
"SQMA_UPLOAD_BASE_KBITS",
"sqm-autorate.@network[0].upload_base_kbits",
None,
)?,
upload_interface: Self::get::<String>(
"SQMA_UPLOAD_INTERFACE",
"sqm-autorate.@network[0].upload_interface",
None,
)?,
upload_min_kbits: Self::get::<f64>(
"SQMA_UPLOAD_MIN_KBITS",
"sqm-autorate.@network[0].upload_min_kbits",
None,
)?,
// Output section
log_level: Self::get::<Level>(
"SQMA_LOG_LEVEL",
"sqm-autorate.@output[0].log_level",
Some(Level::Error),
)?,
speed_hist_file: Self::get::<String>(
"SQMA_SPEED_HIST_FILE",
"sqm-autorate.@output[0].speed_hist_file",
Some("/tmp/sqm-speedhist.csv".parse()?),
)?,
stats_file: Self::get::<String>(
"SQMA_STATS_FILE",
"sqm-autorate.@output[0].stats_file",
Some("/tmp/sqm-autorate.csv".parse()?),
)?,
suppress_statistics: Self::get::<bool>(
"SQMA_SUPPRESS_STATISTICS",
"sqm-autorate.@output[0].suppress_statistics",
Some(false),
)?,
// Advanced section
download_delay_ms: Self::get::<f64>(
"SQMA_DOWNLOAD_DELAY_MS",
"sqm-autorate.@advanced_settings[0].download_delay_ms",
Some(15.0),
)?,
high_load_level: Self::get::<f64>(
"SQMA_HIGH_LOAD_LEVEL",
"sqm-autorate.@advanced_settings[0].high_load_level",
Some(0.8),
)?,
min_change_interval: Self::get::<f64>(
"SQMA_MIN_CHANGE_INTERVAL",
"sqm-autorate.@advanced_settings[0].min_change_interval",
Some(0.5),
)?,
num_reflectors: Self::get::<u8>(
"SQMA_NUM_REFLECTORS",
"sqm-autorate.@advanced_settings[0].num_reflectors",
Some(5),
)?,
reflector_list_file: Self::get::<String>(
"SQMA_REFLECTOR_LIST_FILE",
"sqm-autorate.@advanced_settings[0].reflector_list_file",
Some("/etc/sqm-autorate/reflectors-icmp.csv".parse()?),
)?,
speed_hist_size: Self::get::<u32>(
"SQMA_SPEED_HIST_SIZE",
"sqm-autorate.@advanced_settings[0].speed_hist_size",
Some(100),
)?,
tick_interval: Self::get::<f64>(
"SQMA_TICK_INTERVAL",
"sqm-autorate.@advanced_settings[0].tick_interval",
Some(0.5),
)?,
upload_delay_ms: Self::get::<f64>(
"SQMA_UPLOAD_DELAY_MS",
"sqm-autorate.@advanced_settings[0].upload_delay_ms",
Some(15.0),
)?,
})
}
fn get<T: std::str::FromStr>(
env_key: &str,
uci_key: &str,
default: Option<T>,
) -> Result<T, Box<dyn Error>> {
return match Self::get_value(env_key, uci_key, None) {
Ok(val) => match val.parse::<T>() {
Ok(parsed_val) => Ok(parsed_val),
// Ran into an compilation error while trying to return the
// error as-is, so using my own error type to indicate something went wrong while parsing
Err(_) => Err(Box::new(ConfigParseError {
config_key: env_key.to_string(),
})),
},
Err(e) => {
return match default {
Some(val) => Ok(val),
None => Err(e),
}
}
};
}
fn get_value(
env_key: &str,
uci_key: &str,
default: Option<String>,
) -> Result<String, Box<dyn Error>> {
let mut err: Option<Box<dyn Error>>;
match env::var(env_key) {
Ok(val) => return Ok(val),
Err(e) => err = Some(Box::new(e)),
};
match Self::get_from_uci(uci_key) {
Ok(opt) => match opt {
Some(val) => return Ok(val),
None => {}
},
Err(e) => err = Some(e),
};
match default {
Some(val) => return Ok(val),
None => {
err = Some(Box::new(MissingConfigError {
config_key: env_key.to_string(),
}))
}
}
Err(err.unwrap())
}
#[cfg(feature = "uci")]
fn get_from_uci(key: &str) -> Result<Option<String>, Box<dyn Error>> {
let mut uci: Uci = Uci::new()?;
return match uci.get(key) {
Ok(val) => Ok(Some(val)),
Err(e) => Err(Box::new(e)),
};
}
#[cfg(not(feature = "uci"))]
fn load_from_uci() -> Option<Self> {
None
fn get_from_uci(_: &str) -> Result<Option<String>, Box<dyn Error>> {
Ok(None)
}
pub fn load_reflectors(&self) -> Result<Vec<IpAddr>, Box<dyn Error>> {