arti/rpc/
proxyinfo.rs

1//! Implement RPC functionality for finding what ports are running as proxies.
2
3use std::{net::SocketAddr, sync::Arc};
4use tor_error::{ErrorKind, HasKind};
5use tor_rpcbase::{self as rpc};
6
7use super::session::ArtiRpcSession;
8
9/// Representation of a single proxy, as delivered by the RPC API.
10#[derive(serde::Serialize, Clone, Debug)]
11#[cfg_attr(test, derive(PartialEq, Eq))]
12pub(super) struct Proxy {
13    /// Where the proxy is listening, and what protocol-specific options it expects.
14    pub(super) listener: ProxyListener,
15}
16
17/// Representation of a single proxy's listener location, as delivered by the RPC API.
18#[derive(serde::Serialize, Clone, Debug)]
19#[cfg_attr(test, derive(PartialEq, Eq))]
20pub(super) enum ProxyListener {
21    /// A SOCKS5 proxy.
22    #[serde(rename = "socks5")]
23    Socks5 {
24        /// The address at which we're listening for SOCKS connections.
25        tcp_address: Option<SocketAddr>,
26    },
27}
28
29/// A representation of the set of proxy addresses available from the RPC API.
30#[derive(serde::Serialize, Clone, Debug)]
31#[cfg_attr(test, derive(PartialEq, Eq))]
32pub(super) struct ProxyInfo {
33    /// A list of the supported proxies.
34    ///
35    /// (So far, only SOCKS proxies are listed, but other kinds may be listed in the future.)
36    pub(super) proxies: Vec<Proxy>,
37}
38
39/// Get a list of all the currently running proxies.
40///
41/// This method should not be used when deciding which proxy
42/// an RPC application should connect to.
43/// Instead, the application should use
44/// [`arti:get_rpc_proxy_info`](GetRpcProxyInfo).
45#[derive(Debug, serde::Deserialize, derive_deftly::Deftly)]
46#[derive_deftly(rpc::DynMethod)]
47#[deftly(rpc(method_name = "arti:get_proxy_info"))]
48struct GetProxyInfo {}
49
50/// Get a list of the currently running proxies
51/// that are integrated with the RPC system.
52///
53/// This method returns a list of proxies.
54/// The RPC application may be not be able to use all proxies from the list,
55/// and may prefer some proxies over other.
56/// When multiple proxies are equally preferred,
57/// the application SHOULD use whichever appears first in the list.
58///
59/// You typically won't need to invoke this method yourself:
60/// your RPC library (like `arti-rpc-client-core`)
61/// should take care if it for you.
62#[derive(Debug, serde::Deserialize, derive_deftly::Deftly)]
63#[derive_deftly(rpc::DynMethod)]
64#[deftly(rpc(method_name = "arti:get_rpc_proxy_info"))]
65struct GetRpcProxyInfo {}
66
67impl rpc::RpcMethod for GetProxyInfo {
68    type Output = ProxyInfo;
69    type Update = rpc::NoUpdates;
70}
71
72impl rpc::RpcMethod for GetRpcProxyInfo {
73    type Output = ProxyInfo;
74    type Update = rpc::NoUpdates;
75}
76
77/// An error encountered while asking for the proxy addresses.
78#[derive(Clone, Debug, thiserror::Error)]
79enum GetProxyInfoError {
80    /// The Sender was dropped without setting any proxy info;
81    /// likely, Arti is shutting down.
82    #[error("Arti appears to be shutting down")]
83    Shutdown,
84}
85impl HasKind for GetProxyInfoError {
86    fn kind(&self) -> ErrorKind {
87        use GetProxyInfoError as E;
88        match self {
89            E::Shutdown => ErrorKind::ArtiShuttingDown,
90        }
91    }
92}
93
94/// Implementation for GetProxyInfo on ArtiRpcSession.
95async fn rpc_session_get_proxy_info(
96    session: Arc<ArtiRpcSession>,
97    _method: Box<GetProxyInfo>,
98    _ctx: Arc<dyn rpc::Context>,
99) -> Result<ProxyInfo, GetProxyInfoError> {
100    let proxy_info = session.arti_state.get_proxy_info().await;
101
102    match proxy_info {
103        Ok(info) => Ok((*info).clone()),
104        Err(()) => Err(GetProxyInfoError::Shutdown),
105    }
106}
107rpc::static_rpc_invoke_fn! {rpc_session_get_proxy_info;}
108
109/// Implementation for GetProxyInfo on ArtiRpcSession.
110async fn rpc_session_get_rpc_proxy_info(
111    session: Arc<ArtiRpcSession>,
112    _method: Box<GetRpcProxyInfo>,
113    _ctx: Arc<dyn rpc::Context>,
114) -> Result<ProxyInfo, GetProxyInfoError> {
115    let proxy_info = session.arti_state.get_proxy_info().await;
116
117    match proxy_info {
118        Ok(info) => Ok((*info).clone()),
119        Err(()) => Err(GetProxyInfoError::Shutdown),
120    }
121}
122rpc::static_rpc_invoke_fn! {rpc_session_get_rpc_proxy_info;}