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
103
104
105
106
107
108
109
110
111
112
|
//! A wrapper around an RPC Object that can be used as a connection target.
use arti_client::{
DataStream, StreamPrefs, TorAddr, TorClient,
rpc::{ClientConnectionResult, ConnectWithPrefs, ResolvePtrWithPrefs, ResolveWithPrefs},
};
use std::{net::IpAddr, sync::Arc};
use tor_error::into_internal;
use tor_rpcbase as rpc;
use tor_rtcompat::Runtime;
/// Wrapper around an RPC object that can be used as a connection target,
/// or around a TorClient if no RPC object is given.
///
/// Provides an API similar to TorClient, for use when opening SOCKS connections.
pub(crate) enum ConnTarget<R: Runtime> {
/// An RPC object with accompanying context.
Rpc {
/// The RPC object on which to build our connections.
object: Arc<dyn rpc::Object>,
/// The RPC context in which to invoke methods
context: Arc<dyn rpc::Context>,
},
/// A Tor client, without RPC information
Client(Box<TorClient<R>>),
}
impl<R: Runtime> ConnTarget<R> {
/// As [`TorClient::connect_with_prefs`].
pub(crate) async fn connect_with_prefs(
&self,
target: &TorAddr,
prefs: &StreamPrefs,
) -> ClientConnectionResult<DataStream> {
match self {
ConnTarget::Rpc {
object: obj,
context,
} => {
let method = ConnectWithPrefs {
target: target.clone(),
prefs: prefs.clone(),
};
*rpc::invoke_special_method(context.clone(), obj.clone(), Box::new(method) as _)
.await
.map_err(|e| {
Box::new(into_internal!("unable to delegate to RPC object")(e)) as _
})?
}
ConnTarget::Client(client) => client
.connect_with_prefs(target, prefs)
.await
.map_err(|e| Box::new(e) as _),
}
}
/// As [`TorClient::resolve_with_prefs`]
pub(crate) async fn resolve_with_prefs(
&self,
hostname: &str,
prefs: &StreamPrefs,
) -> ClientConnectionResult<Vec<IpAddr>> {
match self {
ConnTarget::Rpc {
object: obj,
context,
} => {
let method = ResolveWithPrefs {
hostname: hostname.to_string(),
prefs: prefs.clone(),
};
*rpc::invoke_special_method(context.clone(), obj.clone(), Box::new(method) as _)
.await
.map_err(|e| {
Box::new(into_internal!("unable to delegate to RPC object")(e)) as _
})?
}
ConnTarget::Client(client) => client
.resolve_with_prefs(hostname, prefs)
.await
.map_err(|e| Box::new(e) as _),
}
}
/// As [`TorClient::resolve_ptr_with_prefs`]
pub(crate) async fn resolve_ptr_with_prefs(
self,
addr: IpAddr,
prefs: &StreamPrefs,
) -> ClientConnectionResult<Vec<String>> {
match self {
ConnTarget::Rpc {
object: obj,
context,
} => {
let method = ResolvePtrWithPrefs {
addr,
prefs: prefs.clone(),
};
*rpc::invoke_special_method(context.clone(), obj.clone(), Box::new(method) as _)
.await
.map_err(|e| {
Box::new(into_internal!("unable to delegate to RPC object")(e)) as _
})?
}
ConnTarget::Client(client) => client
.resolve_ptr_with_prefs(addr, prefs)
.await
.map_err(|e| Box::new(e) as _),
}
}
}
|