tor_circmgr/
impls.rs
1use crate::build::CircuitBuilder;
4use crate::mgr::{self, MockablePlan};
5use crate::path::OwnedPath;
6use crate::usage::{SupportedCircUsage, TargetCircUsage};
7use crate::{timeouts, DirInfo, Error, PathConfig, Result};
8use async_trait::async_trait;
9use educe::Educe;
10use futures::future::OptionFuture;
11use std::sync::Arc;
12use tor_basic_utils::skip_fmt;
13use tor_error::internal;
14#[cfg(feature = "vanguards")]
15use tor_guardmgr::vanguards::VanguardMgr;
16use tor_linkspec::CircTarget;
17use tor_proto::circuit::{CircParameters, ClientCirc, Path, UniqId};
18use tor_rtcompat::Runtime;
19
20#[async_trait]
21impl mgr::AbstractCirc for tor_proto::circuit::ClientCirc {
22 type Id = tor_proto::circuit::UniqId;
23
24 fn id(&self) -> Self::Id {
25 self.unique_id()
26 }
27
28 fn usable(&self) -> bool {
29 !self.is_closing()
30 }
31
32 fn path_ref(&self) -> Arc<Path> {
33 self.path_ref()
34 }
35
36 fn n_hops(&self) -> usize {
37 self.n_hops()
38 }
39
40 fn is_closing(&self) -> bool {
41 self.is_closing()
42 }
43
44 fn unique_id(&self) -> UniqId {
45 self.unique_id()
46 }
47
48 async fn extend_ntor<T: CircTarget + std::marker::Sync>(
49 &self,
50 target: &T,
51 params: &CircParameters,
52 ) -> tor_proto::Result<()> {
53 self.extend_ntor(target, params).await
54 }
55}
56
57#[derive(Educe)]
60#[educe(Debug)]
61pub(crate) struct Plan {
62 final_spec: SupportedCircUsage,
64 path: OwnedPath,
67 params: CircParameters,
69 guard_status: Option<tor_guardmgr::GuardMonitor>,
72 #[educe(Debug(method = "skip_fmt"))]
76 guard_usable: Option<tor_guardmgr::GuardUsable>,
77}
78
79impl MockablePlan for Plan {}
80
81#[async_trait]
82impl<R: Runtime> crate::mgr::AbstractCircBuilder<R> for crate::build::CircuitBuilder<R> {
83 type Circ = ClientCirc;
84 type Plan = Plan;
85
86 fn plan_circuit(
87 &self,
88 usage: &TargetCircUsage,
89 dir: DirInfo<'_>,
90 ) -> Result<(Plan, SupportedCircUsage)> {
91 let mut rng = rand::rng();
92 let (path, final_spec, guard_status, guard_usable) = usage.build_path(
93 &mut rng,
94 dir,
95 self.guardmgr(),
96 #[cfg(all(feature = "vanguards", feature = "hs-common"))]
97 self.vanguardmgr(),
98 self.path_config().as_ref(),
99 self.runtime().wallclock(),
100 )?;
101
102 let plan = Plan {
103 final_spec: final_spec.clone(),
104 path: (&path).try_into()?,
105 params: dir.circ_params(usage)?,
106 guard_status,
107 guard_usable,
108 };
109
110 Ok((plan, final_spec))
111 }
112
113 async fn build_circuit(&self, plan: Plan) -> Result<(SupportedCircUsage, Arc<ClientCirc>)> {
114 use crate::build::GuardStatusHandle;
115 use tor_guardmgr::GuardStatus;
116 let Plan {
117 final_spec,
118 path,
119 params,
120 guard_status,
121 guard_usable,
122 } = plan;
123
124 let guard_usable: OptionFuture<_> = guard_usable.into();
125 let guard_status: Arc<GuardStatusHandle> = Arc::new(guard_status.into());
126
127 guard_status.pending(GuardStatus::AttemptAbandoned);
128
129 match self
136 .build_owned(
137 path,
138 ¶ms,
139 Arc::clone(&guard_status),
140 final_spec.channel_usage(),
141 )
142 .await
143 {
144 Ok(circuit) => {
145 guard_status.report(GuardStatus::Success);
148
149 match guard_usable.await {
154 Some(Ok(true)) | None => (),
155 Some(Ok(false)) => return Err(Error::GuardNotUsable(circuit.unique_id())),
156 Some(Err(_)) => {
157 return Err(internal!("Guard usability status cancelled").into());
158 }
159 }
160 Ok((final_spec, circuit))
161 }
162 Err(e) => {
163 guard_status.commit();
167
168 Err(e)
169 }
170 }
171 }
172
173 fn launch_parallelism(&self, spec: &TargetCircUsage) -> usize {
174 match spec {
175 TargetCircUsage::Dir => 3,
176 _ => 1,
177 }
178 }
179
180 fn select_parallelism(&self, spec: &TargetCircUsage) -> usize {
181 self.launch_parallelism(spec)
182 }
183
184 fn learning_timeouts(&self) -> bool {
185 CircuitBuilder::learning_timeouts(self)
186 }
187
188 fn save_state(&self) -> Result<bool> {
189 CircuitBuilder::save_state(self)
190 }
191
192 fn path_config(&self) -> Arc<PathConfig> {
193 CircuitBuilder::path_config(self)
194 }
195
196 fn set_path_config(&self, new_config: PathConfig) {
197 CircuitBuilder::set_path_config(self, new_config);
198 }
199
200 fn estimator(&self) -> &timeouts::Estimator {
201 CircuitBuilder::estimator(self)
202 }
203
204 #[cfg(feature = "vanguards")]
205 fn vanguardmgr(&self) -> &Arc<VanguardMgr<R>> {
206 CircuitBuilder::vanguardmgr(self)
207 }
208
209 fn upgrade_to_owned_state(&self) -> Result<()> {
210 CircuitBuilder::upgrade_to_owned_state(self)
211 }
212
213 fn reload_state(&self) -> Result<()> {
214 CircuitBuilder::reload_state(self)
215 }
216
217 fn guardmgr(&self) -> &tor_guardmgr::GuardMgr<R> {
218 CircuitBuilder::guardmgr(self)
219 }
220
221 fn update_network_parameters(&self, p: &tor_netdir::params::NetParameters) {
222 CircuitBuilder::update_network_parameters(self, p);
223 }
224}