1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
//! Implement traits from [`crate::mgr`] for the circuit types we use.
use crate::mgr::{self};
use crate::usage::{SupportedCircUsage, TargetCircUsage};
use crate::{DirInfo, Result};
use async_trait::async_trait;
use rand::{rngs::StdRng, SeedableRng};
use std::convert::TryInto;
use std::sync::Arc;
use std::time::Duration;
use tor_chanmgr::ChanMgr;
use tor_proto::circuit::ClientCirc;
use tor_rtcompat::{Runtime, SleepProviderExt};
impl mgr::AbstractCirc for tor_proto::circuit::ClientCirc {
type Id = tor_proto::circuit::UniqId;
fn id(&self) -> Self::Id {
self.unique_id()
}
fn usable(&self) -> bool {
!self.is_closing()
}
}
/// The information generated by circuit planning, and used to build a
/// circuit.
pub(crate) struct Plan {
/// The supported usage that the circuit will have when complete
final_spec: SupportedCircUsage,
/// An owned copy of the path to build.
// TODO: it would be nice if this weren't owned.
path: crate::path::OwnedPath,
/// The protocol parameters to use when constructing the circuit.
params: tor_proto::circuit::CircParameters,
}
/// An object that knows how to build circuits.
pub(crate) struct Builder<R: Runtime> {
/// The runtime used by this circuit builder.
runtime: R,
/// A channel manager that this circuit builder uses to make chanels.
chanmgr: Arc<ChanMgr<R>>,
}
impl<R: Runtime> Builder<R> {
/// Construct a new Builder
pub(crate) fn new(runtime: R, chanmgr: Arc<ChanMgr<R>>) -> Self {
Builder { runtime, chanmgr }
}
}
#[async_trait]
impl<R: Runtime> crate::mgr::AbstractCircBuilder for Builder<R> {
type Circ = ClientCirc;
type Spec = SupportedCircUsage;
type Plan = Plan;
fn plan_circuit(
&self,
usage: &TargetCircUsage,
dir: DirInfo<'_>,
) -> Result<(Plan, SupportedCircUsage)> {
let mut rng = rand::thread_rng();
let (path, final_spec) = usage.build_path(&mut rng, dir)?;
let plan = Plan {
final_spec: final_spec.clone(),
path: (&path).try_into()?,
params: dir.circ_params(),
};
Ok((plan, final_spec))
}
async fn build_circuit(&self, plan: Plan) -> Result<(SupportedCircUsage, Arc<ClientCirc>)> {
let delay = Duration::from_secs(5); // TODO: make this configurable and inferred.
let Plan {
final_spec,
path,
params,
} = plan;
let mut rng =
StdRng::from_rng(rand::thread_rng()).expect("couldn't construct temporary rng");
let build_future = path.build_circuit(&mut rng, &self.runtime, &self.chanmgr, ¶ms);
let circuit = self.runtime.timeout(delay, build_future).await??;
Ok((final_spec, circuit))
}
fn launch_parallelism(&self, spec: &TargetCircUsage) -> usize {
match spec {
TargetCircUsage::Dir => 3,
_ => 1,
}
}
fn select_parallelism(&self, spec: &TargetCircUsage) -> usize {
self.launch_parallelism(spec)
}
}
|