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) -> tor_proto::Result<Arc<Path>> {
33 self.path_ref()
34 }
35
36 fn n_hops(&self) -> tor_proto::Result<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<T: CircTarget + std::marker::Sync>(
49 &self,
50 target: &T,
51 params: CircParameters,
52 ) -> tor_proto::Result<()> {
53 ClientCirc::extend(self, target, params).await
55 }
56}
57
58#[derive(Educe)]
61#[educe(Debug)]
62pub(crate) struct Plan {
63 final_spec: SupportedCircUsage,
65 path: OwnedPath,
68 params: CircParameters,
70 guard_status: Option<tor_guardmgr::GuardMonitor>,
73 #[educe(Debug(method = "skip_fmt"))]
77 guard_usable: Option<tor_guardmgr::GuardUsable>,
78}
79
80impl MockablePlan for Plan {}
81
82#[async_trait]
83impl<R: Runtime> crate::mgr::AbstractCircBuilder<R> for crate::build::CircuitBuilder<R> {
84 type Circ = ClientCirc;
85 type Plan = Plan;
86
87 fn plan_circuit(
88 &self,
89 usage: &TargetCircUsage,
90 dir: DirInfo<'_>,
91 ) -> Result<(Plan, SupportedCircUsage)> {
92 let mut rng = rand::rng();
93 let (path, final_spec, guard_status, guard_usable) = usage.build_path(
94 &mut rng,
95 dir,
96 self.guardmgr(),
97 #[cfg(all(feature = "vanguards", feature = "hs-common"))]
98 self.vanguardmgr(),
99 self.path_config().as_ref(),
100 self.runtime().wallclock(),
101 )?;
102
103 let plan = Plan {
104 final_spec: final_spec.clone(),
105 path: (&path).try_into()?,
106 params: dir.circ_params(usage)?,
107 guard_status,
108 guard_usable,
109 };
110
111 Ok((plan, final_spec))
112 }
113
114 async fn build_circuit(&self, plan: Plan) -> Result<(SupportedCircUsage, Arc<ClientCirc>)> {
115 use crate::build::GuardStatusHandle;
116 use tor_guardmgr::GuardStatus;
117 let Plan {
118 final_spec,
119 path,
120 params,
121 guard_status,
122 guard_usable,
123 } = plan;
124
125 let guard_usable: OptionFuture<_> = guard_usable.into();
126 let guard_status: Arc<GuardStatusHandle> = Arc::new(guard_status.into());
127
128 guard_status.pending(GuardStatus::AttemptAbandoned);
129
130 match self
137 .build_owned(
138 path,
139 ¶ms,
140 Arc::clone(&guard_status),
141 final_spec.channel_usage(),
142 )
143 .await
144 {
145 Ok(circuit) => {
146 guard_status.report(GuardStatus::Success);
149
150 match guard_usable.await {
155 Some(Ok(true)) | None => (),
156 Some(Ok(false)) => return Err(Error::GuardNotUsable(circuit.unique_id())),
157 Some(Err(_)) => {
158 return Err(internal!("Guard usability status cancelled").into());
159 }
160 }
161 Ok((final_spec, circuit))
162 }
163 Err(e) => {
164 guard_status.commit();
168
169 Err(e)
170 }
171 }
172 }
173
174 fn launch_parallelism(&self, spec: &TargetCircUsage) -> usize {
175 match spec {
176 TargetCircUsage::Dir => 3,
177 _ => 1,
178 }
179 }
180
181 fn select_parallelism(&self, spec: &TargetCircUsage) -> usize {
182 self.launch_parallelism(spec)
183 }
184
185 fn learning_timeouts(&self) -> bool {
186 CircuitBuilder::learning_timeouts(self)
187 }
188
189 fn save_state(&self) -> Result<bool> {
190 CircuitBuilder::save_state(self)
191 }
192
193 fn path_config(&self) -> Arc<PathConfig> {
194 CircuitBuilder::path_config(self)
195 }
196
197 fn set_path_config(&self, new_config: PathConfig) {
198 CircuitBuilder::set_path_config(self, new_config);
199 }
200
201 fn estimator(&self) -> &timeouts::Estimator {
202 CircuitBuilder::estimator(self)
203 }
204
205 #[cfg(feature = "vanguards")]
206 fn vanguardmgr(&self) -> &Arc<VanguardMgr<R>> {
207 CircuitBuilder::vanguardmgr(self)
208 }
209
210 fn upgrade_to_owned_state(&self) -> Result<()> {
211 CircuitBuilder::upgrade_to_owned_state(self)
212 }
213
214 fn reload_state(&self) -> Result<()> {
215 CircuitBuilder::reload_state(self)
216 }
217
218 fn guardmgr(&self) -> &tor_guardmgr::GuardMgr<R> {
219 CircuitBuilder::guardmgr(self)
220 }
221
222 fn update_network_parameters(&self, p: &tor_netdir::params::NetParameters) {
223 CircuitBuilder::update_network_parameters(self, p);
224 }
225}