1use std::{net::SocketAddr, sync::Arc};
4use tor_error::{ErrorKind, HasKind};
5use tor_rpcbase::{self as rpc};
6
7use crate::proxy::port_info;
8
9use super::session::ArtiRpcSession;
10
11#[derive(serde::Serialize, Clone, Debug)]
13#[cfg_attr(test, derive(PartialEq, Eq))]
14pub(super) struct Proxy {
15 pub(super) listener: ProxyListener,
18}
19
20#[derive(serde::Serialize, Clone, Debug)]
22#[cfg_attr(test, derive(PartialEq, Eq))]
23pub(super) enum ProxyListener {
24 #[serde(rename = "socks5")]
26 Socks5 {
27 tcp_address: Option<SocketAddr>,
29 },
30 #[cfg(feature = "http-connect")]
32 #[serde(rename = "http_connect")]
33 HttpConnect {
34 tcp_address: Option<SocketAddr>,
36 },
37}
38
39impl ProxyListener {
40 pub(crate) fn try_from_portinfo(port: &port_info::Port) -> Option<Self> {
44 use port_info::SupportedProtocol as SP;
45 use tor_rtcompat::general::{self, SocketAddr::Inet};
46
47 match (&port.address, &port.protocol) {
48 (Inet(a), SP::Socks) => Some(Self::Socks5 {
49 tcp_address: Some(*a),
50 }),
51 #[cfg(feature = "http-connect")]
52 (Inet(a), SP::Http) => Some(Self::HttpConnect {
53 tcp_address: Some(*a),
54 }),
55 (Inet(_), SP::DnsUdp) => None,
56 (general::SocketAddr::Unix(_), _) => None,
58 (_, _) => None,
59 }
60 }
61}
62
63#[derive(serde::Serialize, Clone, Debug)]
65#[cfg_attr(test, derive(PartialEq, Eq))]
66pub(super) struct ProxyInfo {
67 pub(super) proxies: Vec<Proxy>,
69}
70
71#[derive(Debug, serde::Deserialize, derive_deftly::Deftly)]
78#[derive_deftly(rpc::DynMethod)]
79#[deftly(rpc(method_name = "arti:get_proxy_info"))]
80struct GetProxyInfo {}
81
82#[derive(Debug, serde::Deserialize, derive_deftly::Deftly)]
95#[derive_deftly(rpc::DynMethod)]
96#[deftly(rpc(method_name = "arti:get_rpc_proxy_info"))]
97struct GetRpcProxyInfo {}
98
99impl rpc::RpcMethod for GetProxyInfo {
100 type Output = ProxyInfo;
101 type Update = rpc::NoUpdates;
102}
103
104impl rpc::RpcMethod for GetRpcProxyInfo {
105 type Output = ProxyInfo;
106 type Update = rpc::NoUpdates;
107}
108
109#[derive(Clone, Debug, thiserror::Error)]
111enum GetProxyInfoError {
112 #[error("Arti appears to be shutting down")]
115 Shutdown,
116}
117impl HasKind for GetProxyInfoError {
118 fn kind(&self) -> ErrorKind {
119 use GetProxyInfoError as E;
120 match self {
121 E::Shutdown => ErrorKind::ArtiShuttingDown,
122 }
123 }
124}
125
126async fn rpc_session_get_proxy_info(
128 session: Arc<ArtiRpcSession>,
129 _method: Box<GetProxyInfo>,
130 _ctx: Arc<dyn rpc::Context>,
131) -> Result<ProxyInfo, GetProxyInfoError> {
132 let proxy_info = session.arti_state.get_proxy_info().await;
133
134 match proxy_info {
135 Ok(info) => Ok((*info).clone()),
136 Err(()) => Err(GetProxyInfoError::Shutdown),
137 }
138}
139rpc::static_rpc_invoke_fn! {rpc_session_get_proxy_info;}
140
141async fn rpc_session_get_rpc_proxy_info(
143 session: Arc<ArtiRpcSession>,
144 _method: Box<GetRpcProxyInfo>,
145 _ctx: Arc<dyn rpc::Context>,
146) -> Result<ProxyInfo, GetProxyInfoError> {
147 let proxy_info = session.arti_state.get_proxy_info().await;
148
149 match proxy_info {
150 Ok(info) => Ok((*info).clone()),
151 Err(()) => Err(GetProxyInfoError::Shutdown),
152 }
153}
154rpc::static_rpc_invoke_fn! {rpc_session_get_rpc_proxy_info;}