//! Administrative RPC functionality. //! //! In general, RPC function is "administrative", and requires superuser access, //! whenever it can affect other applications. //! //! This is not a perfect sandbox: applications can _always_ interfere with one another's traffic by //! consuming resources (like bandwidth or CPU) in a way that introduces side channels. use arti_client::TorClient; use derive_deftly::Deftly; use std::sync::Arc; use tor_rpcbase::{self as rpc}; use tor_rtcompat::Runtime; /// An object representing superuser access to Arti over an RPC session. /// /// In general, RPC function is "administrative", and requires superuser access, /// whenever it can affect other applications. #[derive(Deftly)] #[derive_deftly(rpc::Object)] pub(super) struct RpcSuperuser { /// A view of the underlying TorClient managed by this RpcSuperuser object. tor_client: TorClient, } impl RpcSuperuser { /// Construct a new RpcSuperuser object. pub(super) fn new(tor_client: TorClient) -> Self { RpcSuperuser { tor_client } } /// Ensure that every RPC method is registered for this instantiation of TorClient. /// /// We can't use [`rpc::static_rpc_invoke_fn`] for these, since TorClient is /// parameterized. pub(super) fn rpc_methods() -> Vec { rpc::invoker_ent_list![enter_dormant_mode_on_rpcsuperuser::,] } } /// Enter "dormant mode". /// /// Currently, the only available dormant mode is "soft dormant mode", /// which suspends most background operations until any client request /// is received. /// /// Since this method affects all applications using the Arti process, /// it requires administrative permissions. /// /// ## Limitations /// /// As of 2026 March, this functionality is not perfectly implemented, /// and likely does not interact well with onion services. /// Additionally, there are likely background operations that /// this operation doesn't cover. /// /// This method returns a reply immediately, but it may take a little /// while before all of the background tasks finish their work and stop. #[derive(Debug, serde::Deserialize, serde::Serialize, Deftly)] #[derive_deftly(rpc::DynMethod)] #[deftly(rpc(method_name = "arti:enter_dormant_mode"))] struct EnterDormantMode {} impl rpc::RpcMethod for EnterDormantMode { type Output = rpc::Nil; type Update = rpc::NoUpdates; } /// Implementation for [`EnterDormantMode`] on [`RpcSuperuser`]. async fn enter_dormant_mode_on_rpcsuperuser( session: Arc>, _method: Box, _ctx: Arc, ) -> Result { use arti_client::DormantMode; session.tor_client.set_dormant(DormantMode::Soft); Ok(rpc::Nil::default()) }