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}