1use super::config::validate_onion_role_config;
2use super::*;
3
4pub struct ProcessorBuilder {
6 pub(in crate::processor) network_id: u32,
7 pub(in crate::processor) ice_servers: String,
8 pub(in crate::processor) external_address: Option<String>,
9 pub(in crate::processor) webrtc_udp_port_range: Option<WebrtcUdpPortRange>,
10 pub(in crate::processor) session_sk: SessionSk,
11 pub(in crate::processor) storage: Option<EntryStorage>,
12 pub(in crate::processor) measure: Option<Arc<PeriodicMeasure>>,
13 pub(in crate::processor) stabilize_interval: Duration,
14 pub(in crate::processor) online_node_heartbeat_interval: Duration,
15 pub(in crate::processor) online_node_ttl: Duration,
16 pub(in crate::processor) online_node_type: OnlineNodeType,
17 pub(in crate::processor) advertise_presence: bool,
18 pub(in crate::processor) dht_virtual_nodes: u16,
19 pub(in crate::processor) advertise_onion_relay: bool,
20 pub(in crate::processor) advertise_onion_exit: bool,
21 pub(in crate::processor) onion_exit_heartbeat_interval: Duration,
22 pub(in crate::processor) onion_exit_ttl: Duration,
23 pub(in crate::processor) onion_exit_services: Vec<OnionExitService>,
24 pub(in crate::processor) onion_exit_policy: OnionExitPolicy,
25 pub(in crate::processor) registration_tasks: Vec<Arc<dyn RegistrationTask>>,
26 pub(in crate::processor) dht_finger_table_size: usize,
27 pub(in crate::processor) reassembly_limits: ReassemblyLimits,
28}
29
30impl ProcessorBuilder {
31 pub fn from_serialized(config: &str) -> Result<Self> {
33 let config =
34 serde_yaml::from_str::<ProcessorConfig>(config).map_err(Error::SerdeYamlError)?;
35 Self::from_config(&config)
36 }
37
38 pub fn from_config(config: &ProcessorConfig) -> Result<Self> {
40 validate_online_node_registration_timing(
41 config.advertise_presence,
42 config.online_node_heartbeat_interval,
43 config.online_node_ttl,
44 )?;
45 validate_onion_exit_registration_timing(
46 config.advertise_onion_exit,
47 config.onion_exit_heartbeat_interval,
48 config.onion_exit_ttl,
49 )?;
50 validate_onion_role_config(
51 config.advertise_presence,
52 config.advertise_onion_relay,
53 config.advertise_onion_exit,
54 &config.onion_exit_services,
55 &config.onion_exit_policy,
56 )?;
57 Ok(Self {
58 network_id: config.network_id,
59 ice_servers: config.ice_servers.clone(),
60 external_address: config.external_address.clone(),
61 webrtc_udp_port_range: config.webrtc_udp_port_range()?,
62 session_sk: config.session_sk.clone(),
63 storage: None,
64 measure: None,
65 stabilize_interval: config.stabilize_interval,
66 online_node_heartbeat_interval: config.online_node_heartbeat_interval,
67 online_node_ttl: config.online_node_ttl,
68 online_node_type: config.online_node_type.clone(),
69 advertise_presence: config.advertise_presence,
70 dht_virtual_nodes: config.dht_virtual_nodes,
71 advertise_onion_relay: config.advertise_onion_relay,
72 advertise_onion_exit: config.advertise_onion_exit,
73 onion_exit_heartbeat_interval: config.onion_exit_heartbeat_interval,
74 onion_exit_ttl: config.onion_exit_ttl,
75 onion_exit_services: config.onion_exit_services.clone(),
76 onion_exit_policy: config.onion_exit_policy.clone(),
77 registration_tasks: Vec::new(),
78 dht_finger_table_size: DEFAULT_FINGER_TABLE_SIZE,
79 reassembly_limits: ReassemblyLimits::production(),
80 })
81 }
82
83 pub fn storage(mut self, storage: EntryStorage) -> Self {
85 self.storage = Some(storage);
86 self
87 }
88
89 pub fn measure(mut self, implement: PeriodicMeasure) -> Self {
91 self.measure = Some(Arc::new(implement));
92 self
93 }
94
95 pub fn dht_finger_table_size(mut self, size: usize) -> Self {
97 self.dht_finger_table_size = size;
98 self
99 }
100
101 pub fn dht_virtual_nodes(mut self, positions_per_peer: u16) -> Self {
109 self.dht_virtual_nodes = positions_per_peer;
110 self
111 }
112
113 pub fn reassembly_limits(mut self, limits: ReassemblyLimits) -> Self {
115 self.reassembly_limits = limits;
116 self
117 }
118
119 pub fn online_node_type(mut self, node_type: OnlineNodeType) -> Self {
121 self.online_node_type = node_type;
122 self
123 }
124
125 pub fn advertise_presence(mut self, advertise: bool) -> Self {
127 self.advertise_presence = advertise;
128 self
129 }
130
131 pub fn advertise_onion_relay(mut self, advertise: bool) -> Self {
133 self.advertise_onion_relay = advertise;
134 self
135 }
136
137 pub fn advertise_onion_exit(mut self, advertise: bool) -> Self {
139 self.advertise_onion_exit = advertise;
140 self
141 }
142
143 pub fn registration_task<T>(mut self, task: T) -> Self
145 where T: RegistrationTask + 'static {
146 self.registration_tasks.push(Arc::new(task));
147 self
148 }
149
150 pub fn shared_registration_task(mut self, task: Arc<dyn RegistrationTask>) -> Self {
152 self.registration_tasks.push(task);
153 self
154 }
155
156 pub fn build(self) -> Result<Processor> {
158 self.session_sk
159 .session()
160 .verify_self()
161 .map_err(|e| Error::VerifyError(e.to_string()))?;
162
163 let storage = self.storage.unwrap_or_else(|| Box::new(MemStorage::new()));
164 let endpoint_hint = self.external_address.clone();
165 let mut online_node_capabilities = Vec::new();
166 if self.advertise_onion_relay {
167 online_node_capabilities.push(ONION_RELAY_CAPABILITY.to_string());
168 }
169 let session_sk = self.session_sk.clone();
170 let online_node_registration = OnlineNodeRegistration::new(
171 self.online_node_heartbeat_interval,
172 self.online_node_ttl,
173 self.online_node_type.clone(),
174 endpoint_hint,
175 online_node_capabilities,
176 );
177 let mut registration_tasks = self.registration_tasks;
178 if self.advertise_presence {
179 online_node_registration.validate_enabled_schedule()?;
180 registration_tasks.push(Arc::new(online_node_registration.clone()));
181 }
182 if self.advertise_onion_exit {
183 let onion_exit_registration = OnionExitRegistration::new(
184 self.onion_exit_heartbeat_interval,
185 self.onion_exit_ttl,
186 self.online_node_type,
187 self.onion_exit_services,
188 self.onion_exit_policy,
189 );
190 onion_exit_registration.validate_enabled_schedule()?;
191 registration_tasks.push(Arc::new(onion_exit_registration));
192 }
193
194 let mut swarm_builder =
195 SwarmBuilder::new(self.network_id, &self.ice_servers, storage, self.session_sk);
196 swarm_builder = swarm_builder.dht_storage_redundancy(DATA_REDUNDANT);
197 swarm_builder = swarm_builder.dht_finger_table_size(self.dht_finger_table_size);
198 swarm_builder = swarm_builder.dht_virtual_nodes(self.dht_virtual_nodes);
199 swarm_builder = swarm_builder.reassembly_limits(self.reassembly_limits);
200
201 if let Some(external_address) = self.external_address {
202 swarm_builder = swarm_builder.external_address(external_address);
203 }
204 if let Some(range) = self.webrtc_udp_port_range {
205 swarm_builder = swarm_builder.webrtc_udp_port_range(range);
206 }
207
208 let measure = self.measure;
209 if let Some(measure) = &measure {
210 let implementation: MeasureImpl = measure.clone();
211 swarm_builder = swarm_builder.measure(implementation);
212 }
213 let swarm = Arc::new(swarm_builder.build());
214
215 Ok(Processor {
216 swarm,
217 session_sk,
218 stabilize_interval: self.stabilize_interval,
219 online_node_registration,
220 measure,
221 #[cfg(all(feature = "browser", target_family = "wasm"))]
222 advertise_onion_relay: self.advertise_onion_relay,
223 registration_tasks,
224 })
225 }
226}