alopex_chirps_core/
config.rs1use std::net::SocketAddr;
2use std::path::PathBuf;
3use std::time::Duration;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum ConfigError {
8 #[error("Invalid certificate or key: {0}")]
9 Certificate(String),
10 #[error("I/O error: {0}")]
11 Io(#[from] std::io::Error),
12}
13
14#[derive(Debug, Clone)]
16pub struct NodeConfig {
17 pub bind_addr: SocketAddr,
19 pub seeds: Vec<SocketAddr>,
21 pub cert_path: Option<PathBuf>,
23 pub key_path: Option<PathBuf>,
25 pub trusted_cert_paths: Vec<PathBuf>,
30 pub ping_timeout: Duration,
32 pub indirect_ping_timeout: Duration,
34 pub suspect_to_dead_timeout: Duration,
36 pub gossip_interval: Duration,
38 pub max_clock_skew: Duration,
40 pub broadcast_timeout: Duration,
42 pub send_queue_capacity: usize,
44 pub fanout: Option<usize>,
46 pub convergence_rounds: usize,
48 pub node_id_path: PathBuf,
50}
51
52impl Default for NodeConfig {
53 fn default() -> Self {
54 Self {
55 bind_addr: "127.0.0.1:0".parse().unwrap(),
56 seeds: Vec::new(),
57 cert_path: None,
58 key_path: None,
59 trusted_cert_paths: Vec::new(),
60 ping_timeout: Duration::from_secs(1),
61 indirect_ping_timeout: Duration::from_secs(3),
62 suspect_to_dead_timeout: Duration::from_secs(6),
63 gossip_interval: Duration::from_millis(200),
64 max_clock_skew: Duration::from_secs(1),
65 broadcast_timeout: Duration::from_millis(200),
66 send_queue_capacity: 1024,
67 fanout: None,
68 convergence_rounds: 3,
69 node_id_path: PathBuf::from(".chirps_node_id"),
70 }
71 }
72}
73
74impl NodeConfig {
75 pub fn validate(&self) -> Result<(), ConfigError> {
77 match (&self.cert_path, &self.key_path) {
78 (Some(cert), Some(key)) => {
79 if !cert.exists() {
80 return Err(ConfigError::Certificate(format!(
81 "Certificate file not found: {}",
82 cert.display()
83 )));
84 }
85 if !key.exists() {
86 return Err(ConfigError::Certificate(format!(
87 "Key file not found: {}",
88 key.display()
89 )));
90 }
91 }
92 (Some(_), None) => {
93 return Err(ConfigError::Certificate(
94 "Key file must be provided if certificate is provided".to_string(),
95 ));
96 }
97 (None, Some(_)) => {
98 return Err(ConfigError::Certificate(
99 "Certificate file must be provided if key is provided".to_string(),
100 ));
101 }
102 (None, None) => {
103 }
105 }
106 for cert in &self.trusted_cert_paths {
107 if !cert.exists() {
108 return Err(ConfigError::Certificate(format!(
109 "Trusted certificate file not found: {}",
110 cert.display()
111 )));
112 }
113 }
114 Ok(())
115 }
116}