use std::net::IpAddr;
use std::time::Duration;
use gossip::auth::ClusterKey;
use ipnet::IpNet;
use crate::clock::NodeId;
pub(super) const DEFAULT_BULK_SEND_RATE: usize = 32 * 1024 * 1024;
pub(crate) const MIN_BULK_SEND_RATE: usize = 1024 * 1024;
pub(super) const DEFAULT_SOCKET_BUFFER_SIZE: usize = 8 * 1024 * 1024;
pub(super) const DEFAULT_MAX_PEERS: usize = 1024;
pub(super) const DEFAULT_MAX_CONCURRENT_BULK_DUMPS: usize = 4;
pub const MAX_NETS: usize = 8;
#[derive(Clone)]
pub struct Config {
pub port: u16,
pub listen_addr: IpAddr,
pub nets: [Option<IpNet>; MAX_NETS],
pub remote_interval: u32,
pub remote_fanout: usize,
pub cluster_key: Option<ClusterKey>,
pub insecure_no_key: bool,
pub node_id: Option<NodeId>,
pub encrypt: bool,
pub reconcile_interval: Duration,
pub bulk_send_rate: Option<usize>,
pub recv_buffer_size: Option<usize>,
pub send_buffer_size: Option<usize>,
pub freshness_window: Duration,
pub max_peers: usize,
pub max_concurrent_bulk_dumps: usize,
}
impl Default for Config {
fn default() -> Self {
Config {
port: 0,
listen_addr: "127.0.0.1".parse().unwrap(),
nets: [None; MAX_NETS],
remote_interval: 6,
remote_fanout: 2,
cluster_key: None,
insecure_no_key: false,
node_id: None,
encrypt: false,
reconcile_interval: Duration::from_secs(1),
bulk_send_rate: Some(DEFAULT_BULK_SEND_RATE),
recv_buffer_size: Some(DEFAULT_SOCKET_BUFFER_SIZE),
send_buffer_size: Some(DEFAULT_SOCKET_BUFFER_SIZE),
freshness_window: gossip::replay::FRESHNESS_WINDOW_DEFAULT,
max_peers: DEFAULT_MAX_PEERS,
max_concurrent_bulk_dumps: DEFAULT_MAX_CONCURRENT_BULK_DUMPS,
}
}
}
impl Config {
#[must_use]
pub fn with_port(mut self, port: u16) -> Self {
self.port = port;
self
}
#[must_use]
pub fn with_listen_addr(mut self, listen_addr: IpAddr) -> Self {
self.listen_addr = listen_addr;
self
}
#[must_use]
pub fn with_net(mut self, net: IpNet) -> Self {
let slot = self
.nets
.iter_mut()
.find(|slot| slot.is_none())
.unwrap_or_else(|| panic!("at most {MAX_NETS} networks are supported"));
*slot = Some(net);
self
}
#[must_use]
pub fn with_nets(mut self, nets: &[IpNet]) -> Self {
for &net in nets {
self = self.with_net(net);
}
self
}
#[must_use]
pub fn with_remote_interval(mut self, interval: u32) -> Self {
self.remote_interval = interval;
self
}
#[must_use]
pub fn with_remote_fanout(mut self, fanout: usize) -> Self {
self.remote_fanout = fanout;
self
}
#[must_use]
pub fn with_reconcile_interval(mut self, interval: Duration) -> Self {
self.reconcile_interval = interval;
self
}
#[must_use]
pub fn with_bulk_send_rate(mut self, bytes_per_sec: usize) -> Self {
self.bulk_send_rate = Some(bytes_per_sec);
self
}
#[must_use]
pub fn with_recv_buffer_size(mut self, size: usize) -> Self {
self.recv_buffer_size = Some(size);
self
}
#[must_use]
pub fn with_send_buffer_size(mut self, size: usize) -> Self {
self.send_buffer_size = Some(size);
self
}
#[must_use]
pub fn with_cluster_key(mut self, key: ClusterKey) -> Self {
self.cluster_key = Some(key);
self
}
#[must_use]
pub fn with_insecure_no_key(mut self) -> Self {
self.insecure_no_key = true;
self
}
pub(crate) fn check_key_or_insecure_opt_in(&self) {
assert!(
self.cluster_key.is_some() || self.insecure_no_key,
"Config::cluster_key is None: every peer this node ever discovers (any host inside \
the configured nets) would receive the entire dataset, unauthenticated, via paced \
diff dumps. Set Config::with_cluster_key, or opt in explicitly with \
Config::with_insecure_no_key() if the network is a trusted underlay. See README \
\"Security model\"."
);
}
#[must_use]
pub fn with_node_id(mut self, node_id: NodeId) -> Self {
self.node_id = Some(node_id);
self
}
#[must_use]
pub fn with_freshness_window(mut self, window: Duration) -> Self {
self.freshness_window = window;
self
}
#[must_use]
pub fn with_max_peers(mut self, max: usize) -> Self {
self.max_peers = max;
self
}
#[must_use]
pub fn with_max_concurrent_bulk_dumps(mut self, max: usize) -> Self {
self.max_concurrent_bulk_dumps = max;
self
}
#[cfg(feature = "encryption")]
#[must_use]
pub fn with_encryption(mut self) -> Self {
self.encrypt = true;
self
}
}