toe_beans/v4/server/config/
mod.rs1mod lease_time;
2
3use super::RESOLVED_SERVER_PORT;
4use crate::v4::MessageOptions;
5use ip_network::Ipv4Network;
6pub use lease_time::LeaseTime;
7use log::{info, warn};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::fs::{read_to_string, OpenOptions};
11use std::io::Write;
12use std::net::{Ipv4Addr, SocketAddrV4};
13use std::os::unix::fs::OpenOptionsExt;
14use std::path::PathBuf;
15use toml;
16
17#[derive(Serialize, Deserialize, Debug)]
21pub struct Config {
22 #[serde(skip)]
24 pub path: PathBuf,
25 pub lease_time: LeaseTime,
27 pub rapid_commit: bool,
29 pub network_cidr: Ipv4Network,
31 pub listen_address: SocketAddrV4,
33 pub interface: Option<String>,
36 pub server_address: Option<Ipv4Addr>,
42 pub parameters: HashMap<String, MessageOptions>,
45}
46
47impl Default for Config {
48 fn default() -> Self {
49 Self {
50 path: PathBuf::new(), lease_time: LeaseTime::new(86_400).unwrap(), rapid_commit: true,
53 network_cidr: Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 0), 16).unwrap(), listen_address: SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), RESOLVED_SERVER_PORT),
55 interface: None,
56 server_address: None,
57 parameters: HashMap::with_capacity(u8::MAX as usize),
58 }
59 }
60}
61
62impl Config {
63 pub const FILE_NAME: &'static str = "toe-beans.toml";
65
66 pub fn read(from_where: PathBuf) -> Self {
69 let read_result = read_to_string(from_where.join(Self::FILE_NAME));
70 if let Ok(config_string) = read_result {
71 let toml_result = toml::from_str(&config_string);
72 match toml_result {
73 Ok(config) => {
74 return Self {
75 path: from_where, ..config
77 };
78 }
79 Err(error) => {
80 warn!("{error}");
81 warn!(
82 "Warning: invalid {}. Using default values.",
83 Self::FILE_NAME
84 );
85 }
86 }
87 } else {
88 warn!(
89 "Warning: can't read {}. Using default values.",
90 Self::FILE_NAME
91 );
92 }
93
94 Self {
95 path: from_where,
96 ..Config::default()
97 }
98 }
99
100 pub fn write(&self) {
102 info!("Writing {}", Self::FILE_NAME);
103
104 let config_content = toml::to_string_pretty(self).expect("Failed to generate toml data");
105 let mode = 0o600;
106
107 let mut file = OpenOptions::new()
108 .read(false)
109 .write(true)
110 .create(true)
111 .truncate(true)
112 .mode(mode) .open(self.path.join(Self::FILE_NAME))
114 .unwrap_or_else(|_| panic!("Failed to open config {} for writing", Self::FILE_NAME));
115
116 file.write_all(config_content.as_bytes())
117 .unwrap_or_else(|_| panic!("Failed to write config to {}", Self::FILE_NAME));
118 }
119}