use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct ConfigToml { listen: Option, log: Option, tarpit: Option } #[derive(Serialize, Deserialize, Debug)] struct ConfigTomlListen { bind_addr: Option, bind_port: Option, } #[derive(Serialize, Deserialize, Debug)] struct ConfigTomlLog { log_file: Option, level: Option, } #[derive(Serialize, Deserialize, Debug)] struct ConfigTomlTarpit { delay: Option, } #[derive(Serialize, Deserialize, Debug)] pub struct Config { pub bind_addr: String, pub bind_port: u16, pub log_file: String, pub log_level: String, pub delay: u64, } impl Config { pub fn new() -> Self { let config_filepaths: [&str; 3] = [ "./config.toml", "~/.config/sip-tarpit/config.toml", "/etc/sip-tarpit/config.toml", ]; let mut content: String = "".to_owned(); for filepath in config_filepaths { let result: Result = std::fs::read_to_string(filepath); if result.is_ok() { content = result.unwrap(); break; } } let config_toml: ConfigToml = toml::from_str(&content).unwrap_or_else(|_| { println!("Failed to create Config from config file."); ConfigToml { listen: None, log: None, tarpit: None } }); let (bind_addr, bind_port): (String, u16) = match config_toml.listen { Some(ConfigTomlListen { bind_addr, bind_port }) => ( bind_addr.unwrap_or("127.0.0.1".to_owned()), bind_port.unwrap_or(5060) ), None => ("127.0.0.1".to_owned(), 5060) }; let (log_file, log_level) = match config_toml.log { Some(ConfigTomlLog { log_file, level }) => ( log_file.unwrap_or("sip-tarpit.log".to_owned()), level.unwrap_or("INFO".to_owned()) ), None => ("CONSOLE".to_owned(), "INFO".to_owned()) }; let delay = match config_toml.tarpit { Some(ConfigTomlTarpit { delay }) => delay.unwrap_or(0), None => 0 }; Config { bind_addr, bind_port, log_file, log_level, delay } } }