use std::{net::SocketAddr, sync::Arc};
use tor_error::{ErrorKind, HasKind};
use tor_rpcbase::{self as rpc};
use crate::proxy::port_info;
use super::session::ArtiRpcSession;
#[derive(serde::Serialize, Clone, Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub(super) struct Proxy {
pub(super) listener: ProxyListener,
}
#[derive(serde::Serialize, Clone, Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub(super) enum ProxyListener {
#[serde(rename = "socks5")]
Socks5 {
tcp_address: Option<SocketAddr>,
},
#[cfg(feature = "http-connect")]
#[serde(rename = "http_connect")]
HttpConnect {
tcp_address: Option<SocketAddr>,
},
}
impl ProxyListener {
pub(crate) fn try_from_portinfo(port: &port_info::Port) -> Option<Self> {
use port_info::SupportedProtocol as SP;
use tor_rtcompat::general::{self, SocketAddr::Inet};
match (&port.address, &port.protocol) {
(Inet(a), SP::Socks) => Some(Self::Socks5 {
tcp_address: Some(*a),
}),
#[cfg(feature = "http-connect")]
(Inet(a), SP::Http) => Some(Self::HttpConnect {
tcp_address: Some(*a),
}),
(Inet(_), SP::DnsUdp) => None,
(general::SocketAddr::Unix(_), _) => None,
(_, _) => None,
}
}
}
#[derive(serde::Serialize, Clone, Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub(super) struct ProxyInfo {
pub(super) proxies: Vec<Proxy>,
}
#[derive(Debug, serde::Deserialize, derive_deftly::Deftly)]
#[derive_deftly(rpc::DynMethod)]
#[deftly(rpc(method_name = "arti:get_proxy_info"))]
struct GetProxyInfo {}
#[derive(Debug, serde::Deserialize, derive_deftly::Deftly)]
#[derive_deftly(rpc::DynMethod)]
#[deftly(rpc(method_name = "arti:get_rpc_proxy_info"))]
struct GetRpcProxyInfo {}
impl rpc::RpcMethod for GetProxyInfo {
type Output = ProxyInfo;
type Update = rpc::NoUpdates;
}
impl rpc::RpcMethod for GetRpcProxyInfo {
type Output = ProxyInfo;
type Update = rpc::NoUpdates;
}
#[derive(Clone, Debug, thiserror::Error)]
enum GetProxyInfoError {
#[error("Arti appears to be shutting down")]
Shutdown,
}
impl HasKind for GetProxyInfoError {
fn kind(&self) -> ErrorKind {
use GetProxyInfoError as E;
match self {
E::Shutdown => ErrorKind::ArtiShuttingDown,
}
}
}
async fn rpc_session_get_proxy_info(
session: Arc<ArtiRpcSession>,
_method: Box<GetProxyInfo>,
_ctx: Arc<dyn rpc::Context>,
) -> Result<ProxyInfo, GetProxyInfoError> {
let proxy_info = session.arti_state.get_proxy_info().await;
match proxy_info {
Ok(info) => Ok((*info).clone()),
Err(()) => Err(GetProxyInfoError::Shutdown),
}
}
rpc::static_rpc_invoke_fn! {rpc_session_get_proxy_info;}
async fn rpc_session_get_rpc_proxy_info(
session: Arc<ArtiRpcSession>,
_method: Box<GetRpcProxyInfo>,
_ctx: Arc<dyn rpc::Context>,
) -> Result<ProxyInfo, GetProxyInfoError> {
let proxy_info = session.arti_state.get_proxy_info().await;
match proxy_info {
Ok(info) => Ok((*info).clone()),
Err(()) => Err(GetProxyInfoError::Shutdown),
}
}
rpc::static_rpc_invoke_fn! {rpc_session_get_rpc_proxy_info;}