summaryrefslogtreecommitdiff
path: root/crates/tor-circmgr
diff options
context:
space:
mode:
Diffstat (limited to 'crates/tor-circmgr')
-rw-r--r--crates/tor-circmgr/src/build.rs1
-rw-r--r--crates/tor-circmgr/src/hspool.rs38
-rw-r--r--crates/tor-circmgr/src/hspool/pool.rs39
3 files changed, 63 insertions, 15 deletions
diff --git a/crates/tor-circmgr/src/build.rs b/crates/tor-circmgr/src/build.rs
index c5169989b..4236a8976 100644
--- a/crates/tor-circmgr/src/build.rs
+++ b/crates/tor-circmgr/src/build.rs
@@ -385,7 +385,6 @@ pub struct CircuitBuilder<R: Runtime> {
guardmgr: tor_guardmgr::GuardMgr<R>,
/// The vanguard manager object used for HS circuits.
#[cfg(all(feature = "vanguards", feature = "hs-common"))]
- #[allow(dead_code)] // TODO HS-VANGUARDS
vanguardmgr: Arc<VanguardMgr<R>>,
}
diff --git a/crates/tor-circmgr/src/hspool.rs b/crates/tor-circmgr/src/hspool.rs
index da69805c9..5c6076d2a 100644
--- a/crates/tor-circmgr/src/hspool.rs
+++ b/crates/tor-circmgr/src/hspool.rs
@@ -29,6 +29,8 @@ use std::result::Result as StdResult;
pub use config::HsCircPoolConfig;
+use self::pool::HsCircPrefs;
+
/// The (onion-service-related) purpose for which a given circuit is going to be
/// used.
///
@@ -80,6 +82,20 @@ pub(crate) struct HsCircStub {
pub(crate) kind: HsCircStubKind,
}
+impl HsCircStub {
+ /// Whether this circuit satisfies _all_ the [`HsCircPrefs`].
+ ///
+ /// Returns `false` if any of the `prefs` are not satisfied.
+ fn satisfies_prefs(&self, prefs: &HsCircPrefs) -> bool {
+ let HsCircPrefs { kind_prefs } = prefs;
+
+ match kind_prefs {
+ Some(kind) => *kind == self.kind,
+ None => true,
+ }
+ }
+}
+
impl Deref for HsCircStub {
type Target = Arc<ClientCirc>;
@@ -265,7 +281,7 @@ impl<R: Runtime> HsCircPool<R> {
if kind == HsCircKind::ClientRend {
return Err(bad_api_usage!("get_or_launch_specific with ClientRend circuit!?").into());
}
- // TODO HS-VANGUARDS: the kind makes no difference yet, but it will at some point in the future.
+
let wanted_kind = kind.stub_kind();
// For most* of these circuit types, we want to build our circuit with
@@ -380,20 +396,22 @@ impl<R: Runtime> HsCircPool<R> {
// restrictions, and we allow the guard to appear as either of the last
// two hope of the circuit.
if vanguards_enabled {
- // TODO HS-VANGUARDS: check if the circuit is still usable using
- // circuit_still_useable
- //
- // TODO HS-VANGUARDS: this is suboptimal. If we need a STUB+
- // circuit, we need to prefer STUB+ circuits over STUB
- circ.can_become(kind)
+ circ.can_become(kind) && circuit_still_useable(netdir, circ, |_relay| true)
} else {
circuit_compatible_with_target(netdir, circ, &target_exclusion)
}
};
- let found_usable_circ = inner
- .pool
- .take_one_where(&mut rand::thread_rng(), restrictions);
+ let mut prefs = HsCircPrefs::default();
+
+ if vanguards_enabled {
+ prefs.preferred_stub_kind(kind);
+ }
+
+ let found_usable_circ =
+ inner
+ .pool
+ .take_one_where(&mut rand::thread_rng(), restrictions, &prefs);
// Tell the background task to fire immediately if we have very few circuits
// circuits left, or if we found nothing.
diff --git a/crates/tor-circmgr/src/hspool/pool.rs b/crates/tor-circmgr/src/hspool/pool.rs
index 5209ce9fb..b33538e1d 100644
--- a/crates/tor-circmgr/src/hspool/pool.rs
+++ b/crates/tor-circmgr/src/hspool/pool.rs
@@ -192,14 +192,30 @@ impl Pool {
self.stub_target + self.ext_stub_target
}
- /// If there is any circuit in this pool for which `f` returns true, return one such circuit at random, and remove it from the pool.
- pub(super) fn take_one_where<R, F>(&mut self, rng: &mut R, f: F) -> Option<HsCircStub>
+ /// If there is any circuit in this pool for which `f` returns true and that satisfies
+ /// all of the specified [`HsCircPrefs`], return one such circuit at random, and remove
+ /// it from the pool.
+ ///
+ /// If none of the circuits satisfy `prefs`, return a randomly selected circuit for which `f`
+ /// returns true, and remove it from the pool.
+ pub(super) fn take_one_where<R, F>(
+ &mut self,
+ rng: &mut R,
+ f: F,
+ prefs: &HsCircPrefs,
+ ) -> Option<HsCircStub>
where
R: Rng,
F: Fn(&HsCircStub) -> bool,
{
- // Select a circuit satisfying `f` at random.
- let rv = match random_idx_where(rng, &mut self.circuits[..], f) {
+ let rv = match random_idx_where(rng, &mut self.circuits[..], |circ_stub| {
+ // First, check if any circuit matches _all_ the prefs
+ circ_stub.satisfies_prefs(prefs) && f(circ_stub)
+ })
+ .or_else(|| {
+ // Select a circuit satisfying `f` at random.
+ random_idx_where(rng, &mut self.circuits[..], f)
+ }) {
Some(idx) => Some(self.circuits.swap_remove(idx)),
None => None,
};
@@ -292,6 +308,21 @@ impl Pool {
}
}
+/// Preferences for what kind of circuit to select from the pool.
+#[derive(Default, Debug, Clone)]
+pub(super) struct HsCircPrefs {
+ /// If `Some`, specifies the [`HsCircStubKind`] we would like.
+ pub(super) kind_prefs: Option<HsCircStubKind>,
+}
+
+impl HsCircPrefs {
+ /// Set the preferred [`HsCircStubKind`].
+ pub(super) fn preferred_stub_kind(&mut self, kind: HsCircStubKind) -> &mut Self {
+ self.kind_prefs = Some(kind);
+ self
+ }
+}
+
/// Helper: find a random item `elt` in `slice` such that `predicate(elt)` is
/// true. Return the index of that item.
///