offline_protocol/protocol/
config_accessors.rs1use super::mesh_relay::MeshRelayStats;
4use super::{
5 lock_shared_state, OfflineProtocol, PendingQueueMetrics, ProtocolState, KNOWN_PEER_TTL_SECS,
6 MEDIA_TRANSFER_STALE_TIMEOUT_SECS,
7};
8use crate::events::Event;
9use crate::file_transfer::FileTransferManager;
10use crate::{Error, ProtocolConfig, Result, TransportManager};
11use offline_protocol_core::{MessageId, ServiceDescriptor};
12use offline_protocol_mls::MlsManager;
13use offline_protocol_reliability::{
14 AckConfig, AckManager, Deduplicator, DeduplicatorConfig, DeduplicatorStats, RetryConfig,
15 RetryQueue,
16};
17use offline_protocol_router::DorsConfig;
18use offline_protocol_services::MeshServices;
19use std::sync::{Arc, RwLock};
20use std::time::Duration as StdDuration;
21use tracing::{error, warn};
22
23impl OfflineProtocol {
24 pub fn state(&self) -> ProtocolState {
26 let Ok(state) = lock_shared_state(&self.shared_state) else {
27 error!("Failed to lock shared state in state()");
28 return ProtocolState::Stopped;
29 };
30 state.state
31 }
32
33 pub fn config(&self) -> &ProtocolConfig {
35 &self.config
36 }
37
38 pub fn mesh_services(&self) -> &MeshServices {
40 &self.mesh_services
41 }
42
43 pub fn transport_manager_mut(&mut self) -> &mut TransportManager {
47 &mut self.transport_manager
48 }
49
50 pub fn transport_manager(&self) -> &TransportManager {
52 &self.transport_manager
53 }
54
55 pub fn file_transfer_manager_mut(&mut self) -> &mut FileTransferManager {
57 &mut self.file_transfer_manager
58 }
59
60 pub fn file_transfer_manager(&self) -> &FileTransferManager {
62 &self.file_transfer_manager
63 }
64
65 pub fn mls_manager(&self) -> Option<&Arc<RwLock<MlsManager>>> {
69 self.mls_manager.as_ref()
70 }
71
72 pub fn update_dors_config(&mut self, config: DorsConfig) {
76 self.transport_manager.update_selector_config(config);
77 }
78
79 pub fn update_ack_config(&mut self, config: AckConfig) -> crate::Result<()> {
88 let mut candidate = self.config.clone();
89 candidate.reliability.ack = config.clone();
90 candidate.validate()?;
91 self.ack_manager = AckManager::with_config(config.clone());
92 self.config.reliability.ack = config;
93 Ok(())
94 }
95
96 pub fn update_retry_config(&mut self, config: RetryConfig) -> crate::Result<()> {
100 let mut candidate = self.config.clone();
101 candidate.reliability.retry = config.clone();
102 candidate.validate()?;
103 self.retry_queue = RetryQueue::with_config(config.clone());
104 self.config.reliability.retry = config;
105 self.recompute_next_pending_message_expiry();
106 self.cleanup_expired_pending_messages();
107 Ok(())
108 }
109
110 pub fn update_dedup_config(&mut self, config: DeduplicatorConfig) -> crate::Result<()> {
125 let mut candidate = self.config.clone();
126 candidate.reliability.dedup = config.clone();
127 candidate.validate()?;
128 self.deduplicator = Deduplicator::with_config(config.clone());
129 self.config.reliability.dedup = config;
130 Ok(())
131 }
132
133 pub fn deduplicator_stats(&self) -> DeduplicatorStats {
135 self.deduplicator.stats()
136 }
137
138 pub fn pending_queue_metrics(&self) -> PendingQueueMetrics {
140 self.pending_queue.metrics().clone()
141 }
142
143 pub fn pending_ack_count(&self) -> usize {
145 self.ack_manager.pending_count()
146 }
147
148 pub fn retry_queue_size(&self) -> usize {
150 self.retry_queue.len()
151 }
152
153 pub fn is_known_peer(&self, peer_id: &str) -> bool {
161 self.known_peers.contains_key(peer_id)
162 }
163
164 pub fn mesh_relay_stats(&self) -> MeshRelayStats {
172 let counters = self.mesh_relay.counters();
173 MeshRelayStats {
174 forwarded: counters.forwarded,
175 transmissions: counters.transmissions,
176 queued: counters.queued,
177 awaiting_transmission: self.mesh_relay.pending_len(),
178 duplicates_suppressed: counters.duplicates_suppressed,
179 covered_by_a_neighbor: counters.cancelled_by_duplicate,
180 peer_rate_limited: counters.peer_rate_limited,
181 rate_deferred: counters.rate_deferred,
182 hop_limit_reached: counters.hop_limit_reached,
183 reach_clamped: counters.ttl_clamped,
184 dropped_for_capacity: self.mesh_relay.seen_capacity_evictions(),
185 }
186 }
187
188 #[cfg(test)]
190 pub(crate) fn retry_queue_mut(&mut self) -> &mut offline_protocol_reliability::RetryQueue {
191 &mut self.retry_queue
192 }
193
194 pub(crate) fn cleanup_expired_entries(&mut self) {
197 self.deduplicator.cleanup_expired();
198 self.retry_queue.cleanup_expired();
199 self.mesh_relay.maintain(std::time::Instant::now());
200 self.prune_stale_known_peers(std::time::Instant::now());
201 self.cleanup_expired_pending_messages_if_due();
202 self.cleanup_outbox();
203 self.mesh_services.cleanup_expired();
204 self.cleanup_group_message_dedup();
205 self.check_epoch_forks();
206 self.check_leave_election_timeouts();
207 self.check_relay_group_sync();
208 let stale_transfers = self
209 .file_transfer_manager
210 .cleanup_stale_transfers(StdDuration::from_secs(MEDIA_TRANSFER_STALE_TIMEOUT_SECS));
211 for stale in stale_transfers {
212 self.pending_media_metadata.remove(&stale.file_id);
213 self.emit_event(Event::file_receive_failed(
217 stale.file_id,
218 stale.file_name,
219 stale.sender,
220 "stale_timeout".to_string(),
221 ));
222 }
223 self.cleanup_stale_media_state(StdDuration::from_secs(MEDIA_TRANSFER_STALE_TIMEOUT_SECS));
224 self.ack_manager
226 .prune_old_timeouts(std::time::Duration::from_secs(300)); }
228
229 pub(crate) fn prune_stale_known_peers(&mut self, now: std::time::Instant) {
235 let ttl = StdDuration::from_secs(KNOWN_PEER_TTL_SECS);
236 let stale: Vec<String> = self
237 .known_peers
238 .iter()
239 .filter(|(_, seen)| now.saturating_duration_since(**seen) > ttl)
240 .map(|(id, _)| id.clone())
241 .collect();
242 if stale.is_empty() {
243 return;
244 }
245 tracing::debug!(
246 count = stale.len(),
247 ttl_secs = KNOWN_PEER_TTL_SECS,
248 "Evicting stale known peers"
249 );
250 for peer_id in &stale {
251 self.evict_known_peer(peer_id);
252 }
253 }
254
255 pub fn register_service(&mut self, descriptor: ServiceDescriptor) -> Result<()> {
261 self.mesh_services
262 .register_service(descriptor)
263 .map_err(Error::Service)
264 }
265
266 pub fn unregister_service(&mut self, service_id: &str) -> Result<bool> {
268 self.mesh_services
269 .unregister_service(service_id)
270 .map_err(Error::Service)
271 }
272
273 pub fn discover_services(&mut self, service_id: Option<&str>) -> Result<String> {
281 let peers: Vec<String> = self.known_peers.keys().cloned().collect();
285 let result = self
286 .mesh_services
287 .discover_services(&self.local_id, &peers, service_id)
288 .map_err(Error::Service)?;
289 let mut send_failures = 0usize;
290 for msg in result.messages {
291 if self
292 .send_internal_message(&msg.recipient, msg.content, msg.priority)
293 .is_err()
294 {
295 send_failures += 1;
296 }
297 }
298 if send_failures > 0 {
299 warn!(
300 failures = send_failures,
301 total = peers.len(),
302 "Some discovery broadcasts failed to send"
303 );
304 }
305 Ok(result.query_id)
306 }
307
308 pub fn send_service_request(
311 &mut self,
312 provider: &str,
313 service_id: &str,
314 method: &str,
315 body: &str,
316 ) -> Result<String> {
317 Self::validate_outbound_recipient(provider)?;
320
321 let result = self
322 .mesh_services
323 .send_service_request(provider, service_id, method, body)
324 .map_err(Error::Service)?;
325 let msg = result.message;
326 self.send_internal_message(&msg.recipient, msg.content, msg.priority)?;
327 Ok(result.request_id)
328 }
329
330 pub fn respond_to_service_request(
332 &mut self,
333 request_id: &str,
334 requester: &str,
335 service_id: &str,
336 status: &str,
337 body: &str,
338 ) -> Result<MessageId> {
339 Self::validate_outbound_recipient(requester)?;
342
343 let result = self
344 .mesh_services
345 .respond_to_service_request(request_id, requester, service_id, status, body)
346 .map_err(Error::Service)?;
347 let msg = result.message;
348 let message_id = self.send_internal_message(&msg.recipient, msg.content, msg.priority)?;
349 Ok(message_id)
350 }
351}