arti_rpcserver/
session.rs1use arti_client::{
7 TorClient,
8 rpc::{ClientConnectionResult, ConnectWithPrefs, ResolvePtrWithPrefs, ResolveWithPrefs},
9};
10use derive_deftly::Deftly;
11use std::{net::IpAddr, sync::Arc};
12use tor_error::into_internal;
13use tor_rtcompat::Runtime;
14
15use tor_rpcbase::{self as rpc, static_rpc_invoke_fn, templates::*};
16
17#[derive(Deftly)]
40#[derive_deftly(Object)]
41#[deftly(rpc(expose_outside_of_session))]
42pub struct RpcSession {
43 #[allow(unused)]
46 client: Arc<dyn Client>,
47}
48
49trait Client: rpc::Object {
51 fn isolated_client(&self) -> Arc<dyn rpc::Object>;
53
54 fn upcast_arc(self: Arc<Self>) -> Arc<dyn rpc::Object>;
56}
57
58impl<R: Runtime> Client for TorClient<R> {
59 fn isolated_client(&self) -> Arc<dyn rpc::Object> {
60 Arc::new(TorClient::isolated_client(self))
61 }
62
63 fn upcast_arc(self: Arc<Self>) -> Arc<dyn rpc::Object> {
64 self
65 }
66}
67
68impl RpcSession {
69 pub fn new_with_client<R: Runtime>(client: Arc<arti_client::TorClient<R>>) -> Arc<Self> {
71 Arc::new(Self { client })
72 }
73
74 fn client_as_object(&self) -> Arc<dyn rpc::Object> {
77 self.client.clone().upcast_arc()
78 }
79}
80
81#[derive(Debug, serde::Deserialize, serde::Serialize, Deftly)]
88#[derive_deftly(DynMethod)]
89#[deftly(rpc(method_name = "arti:get_client"))]
90struct GetClient {}
91
92impl rpc::RpcMethod for GetClient {
93 type Output = rpc::SingleIdResponse;
94 type Update = rpc::NoUpdates;
95}
96
97async fn get_client_on_session(
99 session: Arc<RpcSession>,
100 _method: Box<GetClient>,
101 ctx: Arc<dyn rpc::Context>,
102) -> Result<rpc::SingleIdResponse, rpc::RpcError> {
103 Ok(rpc::SingleIdResponse::from(
104 ctx.register_owned(session.client.clone().upcast_arc()),
105 ))
106}
107
108async fn isolated_client_on_session(
110 session: Arc<RpcSession>,
111 _method: Box<arti_client::rpc::IsolatedClient>,
112 ctx: Arc<dyn rpc::Context>,
113) -> Result<rpc::SingleIdResponse, rpc::RpcError> {
114 let new_client = session.client.isolated_client();
115 Ok(rpc::SingleIdResponse::from(ctx.register_owned(new_client)))
116}
117
118async fn session_connect_with_prefs(
122 session: Arc<RpcSession>,
123 method: Box<ConnectWithPrefs>,
124 ctx: Arc<dyn rpc::Context>,
125) -> ClientConnectionResult<arti_client::DataStream> {
126 *rpc::invoke_special_method(ctx, session.client_as_object(), method)
127 .await
128 .map_err(|e| Box::new(into_internal!("unable to delegate to TorClient")(e)) as _)?
129}
130
131async fn session_resolve_with_prefs(
135 session: Arc<RpcSession>,
136 method: Box<ResolveWithPrefs>,
137 ctx: Arc<dyn rpc::Context>,
138) -> ClientConnectionResult<Vec<IpAddr>> {
139 *rpc::invoke_special_method(ctx, session.client_as_object(), method)
140 .await
141 .map_err(|e| Box::new(into_internal!("unable to delegate to TorClient")(e)) as _)?
142}
143
144async fn session_resolve_ptr_with_prefs(
148 session: Arc<RpcSession>,
149 method: Box<ResolvePtrWithPrefs>,
150 ctx: Arc<dyn rpc::Context>,
151) -> ClientConnectionResult<Vec<String>> {
152 *rpc::invoke_special_method(ctx, session.client_as_object(), method)
153 .await
154 .map_err(|e| Box::new(into_internal!("unable to delegate to TorClient")(e)) as _)?
155}
156static_rpc_invoke_fn! {
157 get_client_on_session;
158 isolated_client_on_session;
159 @special session_connect_with_prefs;
160 @special session_resolve_with_prefs;
161 @special session_resolve_ptr_with_prefs;
162}
163
164#[cfg(feature = "describe-methods")]
165#[allow(clippy::missing_docs_in_private_items)] mod list_all_methods {
167 use std::{convert::Infallible, sync::Arc};
168
169 use derive_deftly::Deftly;
170 use tor_rpcbase::{self as rpc, RpcDispatchInformation, static_rpc_invoke_fn, templates::*};
171
172 #[derive(Debug, serde::Deserialize, Deftly)]
182 #[derive_deftly(DynMethod)]
183 #[deftly(rpc(method_name = "arti:x_list_all_rpc_methods"))]
184 struct ListAllRpcMethods {}
185
186 impl rpc::RpcMethod for ListAllRpcMethods {
187 type Output = RpcDispatchInformation;
188 type Update = rpc::NoUpdates;
189 }
190
191 async fn session_list_all_rpc_methods(
193 _session: Arc<super::RpcSession>,
194 _method: Box<ListAllRpcMethods>,
195 ctx: Arc<dyn rpc::Context>,
196 ) -> Result<RpcDispatchInformation, Infallible> {
197 Ok(ctx
198 .dispatch_table()
199 .read()
200 .expect("poisoned lock")
201 .dispatch_information())
202 }
203
204 static_rpc_invoke_fn! { session_list_all_rpc_methods; }
205}