1
//! Help the guard manager (and other crates) deal with "pending
2
//! information".
3
//!
4
//! There are two kinds of pending information to deal with.  First,
5
//! every guard that we hand out needs to be marked as succeeded or
6
//! failed. Second, if a guard is given out on an exploratory basis,
7
//! then the circuit manager can't know whether to use a circuit built
8
//! through that guard until the guard manager tells it.  This is
9
//! handled via [`GuardUsable`].
10
use crate::{daemon, FirstHopId};
11

            
12
use educe::Educe;
13
use futures::{channel::mpsc::UnboundedSender, Future};
14
use oneshot_fused_workaround as oneshot;
15
use pin_project::pin_project;
16
use std::fmt::Debug;
17
use std::pin::Pin;
18
use std::sync::atomic::{AtomicU64, Ordering};
19
use std::task::{Context, Poll};
20
use std::time::Instant;
21
use tor_proto::ClockSkew;
22

            
23
use tor_basic_utils::skip_fmt;
24

            
25
/// A future used to see if we have "permission" to use a guard.
26
///
27
/// For efficiency, the [`GuardMgr`](crate::GuardMgr) implementation sometimes gives
28
/// out lower-priority guards when it is not certain whether
29
/// higher-priority guards are running.  After having built a circuit
30
/// with such a guard, the caller must wait on this future to see whether
31
/// the circuit is usable or not.
32
///
33
/// The circuit may be usable immediately (as happens if the guard was
34
/// of sufficient priority, or if all higher-priority guards are
35
/// _known_ to be down).  It may eventually _become_ usable (if all of
36
/// the higher-priority guards are _discovered_ to be down).  Or it may
37
/// eventually become unusable (if we find a higher-priority guard
38
/// that works).
39
///
40
/// Any [`GuardRestriction`](crate::GuardRestriction)s that were used to select this guard
41
/// may influence whether it is usable: if higher priority guards were
42
/// ignored because of a restriction, then we might use a guard that we
43
/// otherwise wouldn't.
44
9880
#[pin_project]
45
pub struct GuardUsable {
46
    /// If present, then this is a future to wait on to see whether the
47
    /// guard is usable.
48
    ///
49
    /// If absent, then the guard is ready immediately and no waiting
50
    /// is needed.
51
    //
52
    // TODO: use a type that makes the case here more distinguishable.
53
    #[pin]
54
    u: Option<oneshot::Receiver<bool>>,
55
}
56

            
57
impl Future for GuardUsable {
58
    type Output = Result<bool, oneshot::Canceled>;
59

            
60
9880
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
61
9880
        match self.project().u.as_pin_mut() {
62
9848
            None => Poll::Ready(Ok(true)),
63
32
            Some(u) => u.poll(cx),
64
        }
65
9880
    }
66
}
67

            
68
impl GuardUsable {
69
    /// Create a new GuardUsable for a primary guard or a fallback directory.
70
    ///
71
    /// (Circuits built through these are usable immediately, independently of
72
    /// whether other guards succeed or fail, so we don't need a way to report
73
    /// whether such guards/fallbacks are usable.)
74
348490
    pub(crate) fn new_usable_immediately() -> Self {
75
348490
        GuardUsable { u: None }
76
348490
    }
77

            
78
    /// Create a new GuardUsable for a guard with undecided usability status.
79
    ///
80
    /// (We use this constructor when a circuit is built through a non-primary
81
    /// guard, and there are other guards _we would prefer to use, if they turn
82
    /// out to work_.  If such a circuit succeeds, the caller must still use
83
    /// this `GuardUsable` to wait until the `GuardMgr` sees whether the
84
    /// more-preferred guards have succeeded or failed.)
85
16
    pub(crate) fn new_uncertain() -> (Self, oneshot::Sender<bool>) {
86
16
        let (snd, rcv) = oneshot::channel();
87
16
        (GuardUsable { u: Some(rcv) }, snd)
88
16
    }
89
}
90

            
91
/// A message that we can get back from the circuit manager who asked
92
/// for a guard.
93
#[derive(Copy, Clone, Debug)]
94
#[non_exhaustive]
95
pub enum GuardStatus {
96
    /// The guard was used successfully.
97
    Success,
98
    /// The guard was used unsuccessfully.
99
    Failure,
100
    /// The circuit failed in a way that we cannot prove is the guard's
101
    /// fault, but which _might_ be the guard's fault.
102
    Indeterminate,
103
    /// Our attempt to use the guard didn't get far enough to be sure
104
    /// whether the guard is usable or not.
105
    AttemptAbandoned,
106
}
107

            
108
/// An object used to tell the [`GuardMgr`](crate::GuardMgr) about the result of
109
/// trying to build a circuit through a guard.
110
///
111
/// The `GuardMgr` needs to know about these statuses, so that it can tell
112
/// whether the guard is running or not.
113
#[must_use = "You need to report the status of any guard that you asked for"]
114
#[derive(Educe)]
115
#[educe(Debug)]
116
pub struct GuardMonitor {
117
    /// The Id that we're going to report about.
118
    id: RequestId,
119
    /// The status that we will report if this monitor is dropped now.
120
    pending_status: GuardStatus,
121
    /// If set, we change `Indeterminate` to `AttemptAbandoned` before
122
    /// reporting it to the guard manager.
123
    ///
124
    /// We do this when a failure to finish the circuit doesn't reflect
125
    /// badly against the guard at all: typically, because the circuit's
126
    /// path is not random.
127
    ignore_indeterminate: bool,
128
    /// If set, we will report the given clock skew as having been observed and
129
    /// authenticated from this guard or fallback.
130
    pending_skew: Option<ClockSkew>,
131
    /// A sender that needs to get told when the attempt to use the guard is
132
    /// finished or abandoned.
133
    ///
134
    /// TODO: This doesn't really need to be an Option, but we use None
135
    /// here to indicate that we've already used the sender, and it can't
136
    /// be used again.
137
    #[educe(Debug(method = "skip_fmt"))]
138
    snd: Option<UnboundedSender<daemon::Msg>>,
139
}
140

            
141
impl GuardMonitor {
142
    /// Create a new GuardMonitor object.
143
348506
    pub(crate) fn new(id: RequestId, snd: UnboundedSender<daemon::Msg>) -> Self {
144
348506
        GuardMonitor {
145
348506
            id,
146
348506
            pending_status: GuardStatus::AttemptAbandoned,
147
348506
            ignore_indeterminate: false,
148
348506
            pending_skew: None,
149
348506
            snd: Some(snd),
150
348506
        }
151
348506
    }
152

            
153
    /// Report that a circuit was successfully built in a way that
154
    /// indicates that the guard is working.
155
    ///
156
    /// Note that this doesn't necessarily mean that the circuit
157
    /// succeeded. For example, we might decide that extending to a
158
    /// second hop means that a guard is usable, even if the circuit
159
    /// stalled at the third hop.
160
9880
    pub fn succeeded(self) {
161
9880
        self.report(GuardStatus::Success);
162
9880
    }
163

            
164
    /// Report that the circuit could not be built successfully, in
165
    /// a way that indicates that the guard isn't working.
166
    ///
167
    /// (This either be because of a network failure, a timeout, or
168
    /// something else.)
169
24
    pub fn failed(self) {
170
24
        self.report(GuardStatus::Failure);
171
24
    }
172

            
173
    /// Report that we did not try to build a circuit using the guard,
174
    /// or that we can't tell whether the guard is working.
175
    ///
176
    /// Dropping a `GuardMonitor` is without calling `succeeded` or
177
    /// `failed` or `pending_status` is equivalent to calling this
178
    /// function.
179
    pub fn attempt_abandoned(self) {
180
        self.report(GuardStatus::AttemptAbandoned);
181
    }
182

            
183
    /// Configure this monitor so that, if it is dropped before use,
184
    /// it sends the status `status`.
185
    pub fn pending_status(&mut self, status: GuardStatus) {
186
        self.pending_status = status;
187
    }
188

            
189
    /// Set the given clock skew value to be reported to the guard manager.
190
    ///
191
    /// Clock skew can be reported on success or failure, but it should only be
192
    /// reported if the first hop is actually authenticated.
193
    pub fn skew(&mut self, skew: ClockSkew) {
194
        self.pending_skew = Some(skew);
195
    }
196

            
197
    /// Return the current pending status and "ignore indeterminate"
198
    /// status for this guard monitor.
199
    #[cfg(feature = "testing")]
200
3280
    pub fn inspect_pending_status(&self) -> (GuardStatus, bool) {
201
3280
        (self.pending_status, self.ignore_indeterminate)
202
3280
    }
203

            
204
    /// Configure this monitor to ignore any indeterminate status
205
    /// values, and treat them as abandoned attempts.
206
    ///
207
    /// We should use this whenever the path being built with this guard
208
    /// is not randomly generated.
209
    pub fn ignore_indeterminate_status(&mut self) {
210
        self.ignore_indeterminate = true;
211
    }
212

            
213
    /// Report a message for this guard.
214
9904
    pub fn report(mut self, msg: GuardStatus) {
215
9904
        self.report_impl(msg);
216
9904
    }
217

            
218
    /// As [`GuardMonitor::report`], but take a &mut reference.
219
348506
    fn report_impl(&mut self, msg: GuardStatus) {
220
348506
        let msg = match (msg, self.ignore_indeterminate) {
221
            (GuardStatus::Indeterminate, true) => GuardStatus::AttemptAbandoned,
222
348506
            (m, _) => m,
223
        };
224
348506
        let _ignore = self
225
348506
            .snd
226
348506
            .take()
227
348506
            .expect("GuardMonitor initialized with no sender")
228
348506
            .unbounded_send(daemon::Msg::Status(self.id, msg, self.pending_skew));
229
348506
    }
230

            
231
    /// Report the pending message for his guard, whatever it is.
232
    pub fn commit(self) {
233
        let status = self.pending_status;
234
        self.report(status);
235
    }
236
}
237

            
238
impl Drop for GuardMonitor {
239
348506
    fn drop(&mut self) {
240
348506
        if self.snd.is_some() {
241
338602
            self.report_impl(self.pending_status);
242
338642
        }
243
348506
    }
244
}
245

            
246
/// Internal unique identifier used to tell PendingRequest objects apart.
247
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
248
pub(crate) struct RequestId {
249
    /// The value of the identifier.
250
    id: u64,
251
}
252

            
253
impl RequestId {
254
    /// Create a new, never-before-used RequestId.
255
    ///
256
    /// # Panics
257
    ///
258
    /// Panics if we have somehow exhausted a 64-bit space of request IDs.
259
348506
    pub(crate) fn next() -> RequestId {
260
        /// The next identifier in sequence we'll give out.
261
        static NEXT_VAL: AtomicU64 = AtomicU64::new(1);
262
348506
        let id = NEXT_VAL.fetch_add(1, Ordering::Relaxed);
263
348506
        assert!(id != 0, "Exhausted guard request Id space.");
264
348506
        RequestId { id }
265
348506
    }
266
}
267

            
268
/// Pending information about a guard that we handed out in response to
269
/// some request, but where we have not yet reported whether the guard
270
/// is usable.
271
///
272
/// We create one of these whenever we give out a guard with an
273
/// uncertain usability status via [`GuardUsable::new_uncertain`].
274
#[derive(Debug)]
275
pub(crate) struct PendingRequest {
276
    /// Identity of the guard that we gave out.
277
    guard_id: FirstHopId,
278
    /// The usage for which this guard was requested.
279
    ///
280
    /// We need this information because, if we find that a better guard
281
    /// than this one might be usable, we should only give it precedence
282
    /// if that guard is also allowable _for this usage_.
283
    usage: crate::GuardUsage,
284
    /// A oneshot channel used to tell the circuit manager that a circuit
285
    /// built through this guard can be used.
286
    ///
287
    /// (This is an option so that we can safely make reply() once-only.
288
    /// Otherwise we run into lifetime issues elsewhere.)
289
    usable: Option<oneshot::Sender<bool>>,
290
    /// The time at which the circuit manager told us that this guard was
291
    /// successful.
292
    waiting_since: Option<Instant>,
293
    /// If true, then the network has been down for a long time when we
294
    /// launched this request.
295
    ///
296
    /// If this request succeeds, it probably means that the net has
297
    /// come back up.
298
    net_has_been_down: bool,
299
}
300

            
301
impl PendingRequest {
302
    /// Create a new PendingRequest.
303
348506
    pub(crate) fn new(
304
348506
        guard_id: FirstHopId,
305
348506
        usage: crate::GuardUsage,
306
348506
        usable: Option<oneshot::Sender<bool>>,
307
348506
        net_has_been_down: bool,
308
348506
    ) -> Self {
309
348506
        PendingRequest {
310
348506
            guard_id,
311
348506
            usage,
312
348506
            usable,
313
348506
            waiting_since: None,
314
348506
            net_has_been_down,
315
348506
        }
316
348506
    }
317

            
318
    /// Return the Id of the guard we gave out.
319
347831
    pub(crate) fn guard_id(&self) -> &FirstHopId {
320
347831
        &self.guard_id
321
347831
    }
322

            
323
    /// Return the usage for which we gave out the guard.
324
9552
    pub(crate) fn usage(&self) -> &crate::GuardUsage {
325
9552
        &self.usage
326
9552
    }
327

            
328
    /// Return the time (if any) when we were told that the guard
329
    /// was successful.
330
    pub(crate) fn waiting_since(&self) -> Option<Instant> {
331
        self.waiting_since
332
    }
333

            
334
    /// Return true if the network had been down for a long time when
335
    /// this guard was handed out.
336
9552
    pub(crate) fn net_has_been_down(&self) -> bool {
337
9552
        self.net_has_been_down
338
9552
    }
339

            
340
    /// Tell the circuit manager that the guard is usable (or unusable),
341
    /// depending on the argument.
342
    ///
343
    /// Does nothing if reply() has already been called.
344
338279
    pub(crate) fn reply(&mut self, usable: bool) {
345
338279
        if let Some(sender) = self.usable.take() {
346
16
            // If this gives us an error, then the circuit manager doesn't
347
16
            // care about this circuit any more.
348
16
            let _ignore = sender.send(usable);
349
338263
        }
350
338279
    }
351

            
352
    /// Mark this request as "waiting" since the time `now`.
353
    ///
354
    /// This function should only be called once per request.
355
    pub(crate) fn mark_waiting(&mut self, now: Instant) {
356
        debug_assert!(self.waiting_since.is_none());
357
        self.waiting_since = Some(now);
358
    }
359
}