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;
pub(crate) enum ConnTarget<R: Runtime> {
Rpc {
object: Arc<dyn rpc::Object>,
context: Arc<dyn rpc::Context>,
},
Client(Box<TorClient<R>>),
}
impl<R: Runtime> ConnTarget<R> {
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 _),
}
}
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 _),
}
}
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 _),
}
}
}