tor_circmgr/path/
dirpath.rs

1//! Code to construct paths to a directory for non-anonymous downloads
2use super::TorPath;
3use crate::Result;
4use tor_guardmgr::{GuardMgr, GuardMonitor, GuardUsable};
5use tor_rtcompat::Runtime;
6
7/// A PathBuilder that can connect to a directory.
8#[non_exhaustive]
9pub(crate) struct DirPathBuilder {}
10
11impl Default for DirPathBuilder {
12    fn default() -> Self {
13        Self::new()
14    }
15}
16
17impl DirPathBuilder {
18    /// Create a new DirPathBuilder.
19    pub(crate) fn new() -> Self {
20        DirPathBuilder {}
21    }
22
23    /// Try to create and return a path corresponding to the requirements of
24    /// this builder.
25    pub(crate) fn pick_path<'a, RT: Runtime>(
26        &self,
27        guards: &GuardMgr<RT>,
28    ) -> Result<(TorPath<'a>, GuardMonitor, GuardUsable)> {
29        let guard_usage = tor_guardmgr::GuardUsageBuilder::default()
30            .kind(tor_guardmgr::GuardUsageKind::OneHopDirectory)
31            .build()
32            .expect("Unable to build directory guard usage");
33        let (guard, mon, usable) = guards.select_guard(guard_usage)?;
34        Ok((TorPath::new_one_hop_owned(&guard), mon, usable))
35    }
36}
37
38#[cfg(test)]
39mod test {
40    // @@ begin test lint list maintained by maint/add_warning @@
41    #![allow(clippy::bool_assert_comparison)]
42    #![allow(clippy::clone_on_copy)]
43    #![allow(clippy::dbg_macro)]
44    #![allow(clippy::mixed_attributes_style)]
45    #![allow(clippy::print_stderr)]
46    #![allow(clippy::print_stdout)]
47    #![allow(clippy::single_char_pattern)]
48    #![allow(clippy::unwrap_used)]
49    #![allow(clippy::unchecked_duration_subtraction)]
50    #![allow(clippy::useless_vec)]
51    #![allow(clippy::needless_pass_by_value)]
52    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
53
54    use super::*;
55    use std::collections::HashSet;
56    use tor_guardmgr::TestConfig;
57    use tor_linkspec::RelayIds;
58    use tor_netdir::testnet;
59    use tor_persist::TestingStateMgr;
60
61    #[test]
62    fn dirpath() {
63        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
64            let netdir = testnet::construct_netdir().unwrap_if_sufficient().unwrap();
65            let statemgr = TestingStateMgr::new();
66            let guards =
67                tor_guardmgr::GuardMgr::new(rt.clone(), statemgr, &TestConfig::default()).unwrap();
68            guards.install_test_netdir(&netdir);
69
70            let mut distinct_guards = HashSet::new();
71
72            // This is a nice easy case, since we tested the harder cases
73            // in guard-spec.  We'll just have every path succeed.
74            for _ in 0..40 {
75                let (path, mon, usable) = DirPathBuilder::new().pick_path(&guards).unwrap();
76                if let crate::path::TorPathInner::OwnedOneHop(relay) = path.inner {
77                    distinct_guards.insert(RelayIds::from_relay_ids(&relay));
78                    mon.succeeded();
79                    assert!(usable.await.unwrap());
80                } else {
81                    panic!("Generated the wrong kind of path.");
82                }
83            }
84            assert_eq!(
85                distinct_guards.len(),
86                netdir.params().guard_dir_use_parallelism.get() as usize
87            );
88        });
89    }
90}