use std::net::SocketAddr;
use std::time::Duration;
use crate::Error;
use crate::key::KmsProtection;
use crate::SEED_LENGTH;
pub use self::environment::EnvironmentConfig;
pub use self::file::FileConfig;
pub use self::memory::MemoryConfig;
mod environment;
mod file;
mod memory;
pub const DEFAULT_BATCH_SIZE: u8 = 64;
pub const DEFAULT_STATUS_INTERVAL: Duration = Duration::from_secs(600);
pub trait ServerConfig {
fn interface(&self) -> &str;
fn port(&self) -> u16;
fn seed(&self) -> Vec<u8>;
fn batch_size(&self) -> u8;
fn status_interval(&self) -> Duration;
fn kms_protection(&self) -> &KmsProtection;
fn health_check_port(&self) -> Option<u16>;
fn client_stats_enabled(&self) -> bool;
fn fault_percentage(&self) -> u8;
fn udp_socket_addr(&self) -> Result<SocketAddr, Error> {
let addr = format!("{}:{}", self.interface(), self.port());
match addr.parse() {
Ok(v) => Ok(v),
Err(_) => Err(Error::InvalidConfiguration(addr)),
}
}
}
pub fn make_config(arg: &str) -> Result<Box<dyn ServerConfig>, Error> {
if arg == "ENV" {
match EnvironmentConfig::new() {
Ok(cfg) => Ok(Box::new(cfg)),
Err(e) => Err(e),
}
} else {
match FileConfig::new(arg) {
Ok(cfg) => Ok(Box::new(cfg)),
Err(e) => Err(e),
}
}
}
#[allow(clippy::useless_let_if_seq)]
pub fn is_valid_config(cfg: &dyn ServerConfig) -> bool {
let mut is_valid = true;
if cfg.port() == 0 {
error!("server port not set: {}", cfg.port());
is_valid = false;
}
if cfg.interface().is_empty() {
error!("'interface' is missing");
is_valid = false;
}
if cfg.seed().is_empty() {
error!("'seed' value is missing");
is_valid = false;
} else if *cfg.kms_protection() == KmsProtection::Plaintext
&& cfg.seed().len() != SEED_LENGTH as usize
{
error!(
"plaintext seed value must be 32 characters long, found {}",
cfg.seed().len()
);
is_valid = false;
} else if *cfg.kms_protection() != KmsProtection::Plaintext
&& cfg.seed().len() <= SEED_LENGTH as usize
{
error!("KMS use enabled but seed value is too short to be an encrypted blob");
is_valid = false;
}
if cfg.batch_size() < 1 || cfg.batch_size() > 64 {
error!(
"batch_size {} is invalid; valid range 1-64",
cfg.batch_size()
);
is_valid = false;
}
if cfg.fault_percentage() > 50 {
error!(
"fault_percentage {} is invalid; valid range 0-50",
cfg.fault_percentage()
);
is_valid = false;
}
if is_valid {
if let Err(e) = cfg.udp_socket_addr() {
error!(
"failed to create UDP socket {}:{} {:?}",
cfg.interface(),
cfg.port(),
e
);
is_valid = false;
}
}
is_valid
}