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