tor_circmgr/build/
guardstatus.rs

1//! Helpers for reporting information about guard status to the guard manager.
2
3use std::sync::Mutex;
4use tor_guardmgr::{GuardMonitor, GuardStatus};
5use tor_proto::ClockSkew;
6
7/// A shareable object that we can use to report guard status to the guard
8/// manager.
9pub(crate) struct GuardStatusHandle {
10    /// An inner guard monitor.
11    ///
12    /// If this is None, then either we aren't using the guard
13    /// manager, or we already reported a status to it.
14    mon: Mutex<Option<GuardMonitor>>,
15}
16
17impl From<Option<GuardMonitor>> for GuardStatusHandle {
18    fn from(mon: Option<GuardMonitor>) -> Self {
19        Self {
20            mon: Mutex::new(mon),
21        }
22    }
23}
24
25impl GuardStatusHandle {
26    /// Finalize this guard status handle, and report its pending status
27    /// to the guard manager.
28    ///
29    /// Future calls to methods on this object will do nothing.
30    pub(crate) fn commit(&self) {
31        let mut mon = self.mon.lock().expect("Poisoned lock");
32        if let Some(mon) = mon.take() {
33            mon.commit();
34        }
35    }
36
37    /// Change the pending status on this guard.
38    ///
39    /// Note that the pending status will not be sent to the guard manager
40    /// immediately: only committing this GuardStatusHandle, or dropping it,
41    /// will do so.
42    pub(crate) fn pending(&self, status: GuardStatus) {
43        let mut mon = self.mon.lock().expect("Poisoned lock");
44        if let Some(mon) = mon.as_mut() {
45            mon.pending_status(status);
46        }
47    }
48
49    /// Change the pending clock skew for this guard.
50    ///
51    /// As with pending status, this value won't be sent to the guard manager
52    /// until this `GuardStatusHandle` is dropped or committed.
53    pub(crate) fn skew(&self, skew: ClockSkew) {
54        let mut mon = self.mon.lock().expect("Poisoned lock");
55        if let Some(mon) = mon.as_mut() {
56            mon.skew(skew);
57        }
58    }
59
60    /// Report the provided status to the guard manager.
61    ///
62    /// Future calls to methods on this object will do nothing.
63    pub(crate) fn report(&self, status: GuardStatus) {
64        let mut mon = self.mon.lock().expect("Poisoned lock");
65        if let Some(mon) = mon.take() {
66            mon.report(status);
67        }
68    }
69}