use crate::v4::{LeaseConfig, MessageOptions, SocketConfig};
use log::{info, warn};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::{OpenOptions, read_to_string};
use std::io::Write;
use std::net::Ipv4Addr;
use std::os::unix::fs::OpenOptionsExt;
use std::path::PathBuf;
use toml;
#[derive(Serialize, Deserialize, Debug)]
pub struct InnerServerConfig {
pub rapid_commit: bool,
pub server_address: Option<Ipv4Addr>,
pub parameters: HashMap<u8, MessageOptions>,
}
impl Default for InnerServerConfig {
fn default() -> Self {
Self {
rapid_commit: true,
server_address: None,
parameters: HashMap::with_capacity(u8::MAX as usize),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ServerConfig {
#[serde(skip)]
pub path: PathBuf,
pub server: InnerServerConfig,
pub socket_config: SocketConfig,
pub lease_config: LeaseConfig,
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
path: PathBuf::new(), server: InnerServerConfig::default(),
socket_config: SocketConfig::default_server(),
lease_config: LeaseConfig::default(),
}
}
}
impl ServerConfig {
pub const FILE_NAME: &'static str = "toe-beans.toml";
pub fn read(from_where: PathBuf) -> Self {
let read_result = read_to_string(from_where.join(Self::FILE_NAME));
if let Ok(config_string) = read_result {
let toml_result = toml::from_str(&config_string);
match toml_result {
Ok(config) => {
return Self {
path: from_where, ..config
};
}
Err(error) => {
warn!("{error}");
warn!(
"Warning: invalid {}. Using default values.",
Self::FILE_NAME
);
}
}
} else {
warn!(
"Warning: can't read {}. Using default values.",
Self::FILE_NAME
);
}
Self {
path: from_where,
..ServerConfig::default()
}
}
pub fn write(&self) {
info!("Writing {}", Self::FILE_NAME);
let config_content = toml::to_string_pretty(self).expect("Failed to generate toml data");
let mode = 0o600;
let mut file = OpenOptions::new()
.read(false)
.write(true)
.create(true)
.truncate(true)
.mode(mode) .open(self.path.join(Self::FILE_NAME))
.unwrap_or_else(|_| panic!("Failed to open config {} for writing", Self::FILE_NAME));
file.write_all(config_content.as_bytes())
.unwrap_or_else(|_| panic!("Failed to write config to {}", Self::FILE_NAME));
}
}