tor_circmgr/
impls.rs
1use crate::build::TunnelBuilder;
4use crate::mgr::{self, MockablePlan};
5use crate::path::OwnedPath;
6use crate::usage::{SupportedTunnelUsage, TargetTunnelUsage};
7use crate::{DirInfo, Error, PathConfig, Result, timeouts};
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::{bad_api_usage, internal};
14#[cfg(feature = "vanguards")]
15use tor_guardmgr::vanguards::VanguardMgr;
16use tor_linkspec::CircTarget;
17use tor_proto::ClientTunnel;
18use tor_proto::circuit::UniqId;
19use tor_proto::client::circuit::{CircParameters, Path};
20use tor_rtcompat::Runtime;
21
22#[async_trait]
23impl mgr::AbstractTunnel for tor_proto::ClientTunnel {
24 type Id = tor_proto::circuit::UniqId;
25
26 fn id(&self) -> Self::Id {
27 self.unique_id()
28 }
29
30 fn usable(&self) -> bool {
31 !self.is_closing()
32 }
33
34 fn single_path(&self) -> tor_proto::Result<Arc<Path>> {
35 use itertools::Itertools as _;
36
37 self.all_paths().into_iter().exactly_one().map_err(|_| {
38 bad_api_usage!("requested the single path of a multi-path tunnel?!").into()
39 })
40 }
41
42 fn n_hops(&self) -> tor_proto::Result<usize> {
43 self.n_hops()
44 }
45
46 fn is_closing(&self) -> bool {
47 self.is_closed()
48 }
49
50 fn unique_id(&self) -> UniqId {
51 self.unique_id()
52 }
53
54 async fn extend<T: CircTarget + Sync>(
55 &self,
56 target: &T,
57 params: CircParameters,
58 ) -> tor_proto::Result<()> {
59 let circ = self.as_single_circ()?;
60 circ.extend(target, params).await
61 }
62}
63
64#[derive(Educe)]
67#[educe(Debug)]
68pub(crate) struct Plan {
69 final_spec: SupportedTunnelUsage,
71 path: OwnedPath,
74 params: CircParameters,
76 guard_status: Option<tor_guardmgr::GuardMonitor>,
79 #[educe(Debug(method = "skip_fmt"))]
83 guard_usable: Option<tor_guardmgr::GuardUsable>,
84}
85
86impl MockablePlan for Plan {}
87
88#[async_trait]
89impl<R: Runtime> crate::mgr::AbstractTunnelBuilder<R> for crate::build::TunnelBuilder<R> {
90 type Tunnel = ClientTunnel;
91 type Plan = Plan;
92
93 fn plan_tunnel(
94 &self,
95 usage: &TargetTunnelUsage,
96 dir: DirInfo<'_>,
97 ) -> Result<(Plan, SupportedTunnelUsage)> {
98 let mut rng = rand::rng();
99 let (path, final_spec, guard_status, guard_usable) = usage.build_path(
100 &mut rng,
101 dir,
102 self.guardmgr(),
103 #[cfg(all(feature = "vanguards", feature = "hs-common"))]
104 self.vanguardmgr(),
105 self.path_config().as_ref(),
106 self.runtime().wallclock(),
107 )?;
108
109 let plan = Plan {
110 final_spec: final_spec.clone(),
111 path: (&path).try_into()?,
112 params: dir.circ_params(usage)?,
113 guard_status,
114 guard_usable,
115 };
116
117 Ok((plan, final_spec))
118 }
119
120 async fn build_tunnel(&self, plan: Plan) -> Result<(SupportedTunnelUsage, Self::Tunnel)> {
121 use crate::build::GuardStatusHandle;
122 use tor_guardmgr::GuardStatus;
123 let Plan {
124 final_spec,
125 path,
126 params,
127 guard_status,
128 guard_usable,
129 } = plan;
130
131 let guard_usable: OptionFuture<_> = guard_usable.into();
132 let guard_status: Arc<GuardStatusHandle> = Arc::new(guard_status.into());
133
134 guard_status.pending(GuardStatus::AttemptAbandoned);
135
136 match self
143 .build_owned(
144 path,
145 ¶ms,
146 Arc::clone(&guard_status),
147 final_spec.channel_usage(),
148 )
149 .await
150 {
151 Ok(tunnel) => {
152 guard_status.report(GuardStatus::Success);
155
156 match guard_usable.await {
161 Some(Ok(true)) | None => (),
162 Some(Ok(false)) => return Err(Error::GuardNotUsable(tunnel.unique_id())),
163 Some(Err(_)) => {
164 return Err(internal!("Guard usability status cancelled").into());
165 }
166 }
167 Ok((final_spec, tunnel))
168 }
169 Err(e) => {
170 guard_status.commit();
174
175 Err(e)
176 }
177 }
178 }
179
180 fn launch_parallelism(&self, spec: &TargetTunnelUsage) -> usize {
181 match spec {
182 TargetTunnelUsage::Dir => 3,
183 _ => 1,
184 }
185 }
186
187 fn select_parallelism(&self, spec: &TargetTunnelUsage) -> usize {
188 self.launch_parallelism(spec)
189 }
190
191 fn learning_timeouts(&self) -> bool {
192 TunnelBuilder::learning_timeouts(self)
193 }
194
195 fn save_state(&self) -> Result<bool> {
196 TunnelBuilder::save_state(self)
197 }
198
199 fn path_config(&self) -> Arc<PathConfig> {
200 TunnelBuilder::path_config(self)
201 }
202
203 fn set_path_config(&self, new_config: PathConfig) {
204 TunnelBuilder::set_path_config(self, new_config);
205 }
206
207 fn estimator(&self) -> &timeouts::Estimator {
208 TunnelBuilder::estimator(self)
209 }
210
211 #[cfg(feature = "vanguards")]
212 fn vanguardmgr(&self) -> &Arc<VanguardMgr<R>> {
213 TunnelBuilder::vanguardmgr(self)
214 }
215
216 fn upgrade_to_owned_state(&self) -> Result<()> {
217 TunnelBuilder::upgrade_to_owned_state(self)
218 }
219
220 fn reload_state(&self) -> Result<()> {
221 TunnelBuilder::reload_state(self)
222 }
223
224 fn guardmgr(&self) -> &tor_guardmgr::GuardMgr<R> {
225 TunnelBuilder::guardmgr(self)
226 }
227
228 fn update_network_parameters(&self, p: &tor_netdir::params::NetParameters) {
229 TunnelBuilder::update_network_parameters(self, p);
230 }
231}