use super::config::validate_onion_role_config;
use super::*;
pub struct ProcessorBuilder {
pub(in crate::processor) network_id: u32,
pub(in crate::processor) ice_servers: String,
pub(in crate::processor) external_address: Option<String>,
pub(in crate::processor) webrtc_udp_port_range: Option<WebrtcUdpPortRange>,
pub(in crate::processor) session_sk: SessionSk,
pub(in crate::processor) storage: Option<EntryStorage>,
pub(in crate::processor) measure: Option<Arc<PeriodicMeasure>>,
pub(in crate::processor) stabilize_interval: Duration,
pub(in crate::processor) online_node_heartbeat_interval: Duration,
pub(in crate::processor) online_node_ttl: Duration,
pub(in crate::processor) online_node_type: OnlineNodeType,
pub(in crate::processor) advertise_presence: bool,
pub(in crate::processor) dht_virtual_nodes: u16,
pub(in crate::processor) advertise_onion_relay: bool,
pub(in crate::processor) advertise_onion_exit: bool,
pub(in crate::processor) onion_exit_heartbeat_interval: Duration,
pub(in crate::processor) onion_exit_ttl: Duration,
pub(in crate::processor) onion_exit_services: Vec<OnionExitService>,
pub(in crate::processor) onion_exit_policy: OnionExitPolicy,
pub(in crate::processor) registration_tasks: Vec<Arc<dyn RegistrationTask>>,
pub(in crate::processor) dht_finger_table_size: usize,
pub(in crate::processor) reassembly_limits: ReassemblyLimits,
}
impl ProcessorBuilder {
pub fn from_serialized(config: &str) -> Result<Self> {
let config =
serde_yaml::from_str::<ProcessorConfig>(config).map_err(Error::SerdeYamlError)?;
Self::from_config(&config)
}
pub fn from_config(config: &ProcessorConfig) -> Result<Self> {
validate_online_node_registration_timing(
config.advertise_presence,
config.online_node_heartbeat_interval,
config.online_node_ttl,
)?;
validate_onion_exit_registration_timing(
config.advertise_onion_exit,
config.onion_exit_heartbeat_interval,
config.onion_exit_ttl,
)?;
validate_onion_role_config(
config.advertise_presence,
config.advertise_onion_relay,
config.advertise_onion_exit,
&config.onion_exit_services,
&config.onion_exit_policy,
)?;
Ok(Self {
network_id: config.network_id,
ice_servers: config.ice_servers.clone(),
external_address: config.external_address.clone(),
webrtc_udp_port_range: config.webrtc_udp_port_range()?,
session_sk: config.session_sk.clone(),
storage: None,
measure: None,
stabilize_interval: config.stabilize_interval,
online_node_heartbeat_interval: config.online_node_heartbeat_interval,
online_node_ttl: config.online_node_ttl,
online_node_type: config.online_node_type.clone(),
advertise_presence: config.advertise_presence,
dht_virtual_nodes: config.dht_virtual_nodes,
advertise_onion_relay: config.advertise_onion_relay,
advertise_onion_exit: config.advertise_onion_exit,
onion_exit_heartbeat_interval: config.onion_exit_heartbeat_interval,
onion_exit_ttl: config.onion_exit_ttl,
onion_exit_services: config.onion_exit_services.clone(),
onion_exit_policy: config.onion_exit_policy.clone(),
registration_tasks: Vec::new(),
dht_finger_table_size: DEFAULT_FINGER_TABLE_SIZE,
reassembly_limits: ReassemblyLimits::production(),
})
}
pub fn storage(mut self, storage: EntryStorage) -> Self {
self.storage = Some(storage);
self
}
pub fn measure(mut self, implement: PeriodicMeasure) -> Self {
self.measure = Some(Arc::new(implement));
self
}
pub fn dht_finger_table_size(mut self, size: usize) -> Self {
self.dht_finger_table_size = size;
self
}
pub fn dht_virtual_nodes(mut self, positions_per_peer: u16) -> Self {
self.dht_virtual_nodes = positions_per_peer;
self
}
pub fn reassembly_limits(mut self, limits: ReassemblyLimits) -> Self {
self.reassembly_limits = limits;
self
}
pub fn online_node_type(mut self, node_type: OnlineNodeType) -> Self {
self.online_node_type = node_type;
self
}
pub fn advertise_presence(mut self, advertise: bool) -> Self {
self.advertise_presence = advertise;
self
}
pub fn advertise_onion_relay(mut self, advertise: bool) -> Self {
self.advertise_onion_relay = advertise;
self
}
pub fn advertise_onion_exit(mut self, advertise: bool) -> Self {
self.advertise_onion_exit = advertise;
self
}
pub fn registration_task<T>(mut self, task: T) -> Self
where T: RegistrationTask + 'static {
self.registration_tasks.push(Arc::new(task));
self
}
pub fn shared_registration_task(mut self, task: Arc<dyn RegistrationTask>) -> Self {
self.registration_tasks.push(task);
self
}
pub fn build(self) -> Result<Processor> {
self.session_sk
.session()
.verify_self()
.map_err(|e| Error::VerifyError(e.to_string()))?;
let storage = self.storage.unwrap_or_else(|| Box::new(MemStorage::new()));
let endpoint_hint = self.external_address.clone();
let mut online_node_capabilities = Vec::new();
if self.advertise_onion_relay {
online_node_capabilities.push(ONION_RELAY_CAPABILITY.to_string());
}
let session_sk = self.session_sk.clone();
let online_node_registration = OnlineNodeRegistration::new(
self.online_node_heartbeat_interval,
self.online_node_ttl,
self.online_node_type.clone(),
endpoint_hint,
online_node_capabilities,
);
let mut registration_tasks = self.registration_tasks;
if self.advertise_presence {
online_node_registration.validate_enabled_schedule()?;
registration_tasks.push(Arc::new(online_node_registration.clone()));
}
if self.advertise_onion_exit {
let onion_exit_registration = OnionExitRegistration::new(
self.onion_exit_heartbeat_interval,
self.onion_exit_ttl,
self.online_node_type,
self.onion_exit_services,
self.onion_exit_policy,
);
onion_exit_registration.validate_enabled_schedule()?;
registration_tasks.push(Arc::new(onion_exit_registration));
}
let mut swarm_builder =
SwarmBuilder::new(self.network_id, &self.ice_servers, storage, self.session_sk);
swarm_builder = swarm_builder.dht_storage_redundancy(DATA_REDUNDANT);
swarm_builder = swarm_builder.dht_finger_table_size(self.dht_finger_table_size);
swarm_builder = swarm_builder.dht_virtual_nodes(self.dht_virtual_nodes);
swarm_builder = swarm_builder.reassembly_limits(self.reassembly_limits);
if let Some(external_address) = self.external_address {
swarm_builder = swarm_builder.external_address(external_address);
}
if let Some(range) = self.webrtc_udp_port_range {
swarm_builder = swarm_builder.webrtc_udp_port_range(range);
}
let measure = self.measure;
if let Some(measure) = &measure {
let implementation: MeasureImpl = measure.clone();
swarm_builder = swarm_builder.measure(implementation);
}
let swarm = Arc::new(swarm_builder.build());
Ok(Processor {
swarm,
session_sk,
stabilize_interval: self.stabilize_interval,
online_node_registration,
measure,
#[cfg(all(feature = "browser", target_family = "wasm"))]
advertise_onion_relay: self.advertise_onion_relay,
registration_tasks,
})
}
}