1
//! Administrative RPC functionality.
2
//!
3
//! In general, RPC function is "administrative", and requires superuser access,
4
//! whenever it can affect other applications.
5
//!
6
//! This is not a perfect sandbox: applications can _always_ interfere with one another's traffic by
7
//! consuming resources (like bandwidth or CPU) in a way that introduces side channels.
8

            
9
use arti_client::TorClient;
10
use derive_deftly::Deftly;
11
use std::sync::Arc;
12
use tor_rpcbase::{self as rpc};
13
use tor_rtcompat::Runtime;
14

            
15
/// An object representing superuser access to Arti over an RPC session.
16
///
17
/// In general, RPC function is "administrative", and requires superuser access,
18
/// whenever it can affect other applications.
19
#[derive(Deftly)]
20
#[derive_deftly(rpc::Object)]
21
pub(super) struct RpcSuperuser<R: Runtime> {
22
    /// A view of the underlying TorClient managed by this RpcSuperuser object.
23
    tor_client: TorClient<R>,
24
}
25

            
26
impl<R: Runtime> RpcSuperuser<R> {
27
    /// Construct a new RpcSuperuser object.
28
    pub(super) fn new(tor_client: TorClient<R>) -> Self {
29
        RpcSuperuser { tor_client }
30
    }
31

            
32
    /// Ensure that every RPC method is registered for this instantiation of TorClient.
33
    ///
34
    /// We can't use [`rpc::static_rpc_invoke_fn`] for these, since TorClient is
35
    /// parameterized.
36
    pub(super) fn rpc_methods() -> Vec<rpc::dispatch::InvokerEnt> {
37
        rpc::invoker_ent_list![enter_dormant_mode_on_rpcsuperuser::<R>,]
38
    }
39
}
40

            
41
/// Enter "dormant mode".
42
///
43
/// Currently, the only available dormant mode is "soft dormant mode",
44
/// which suspends most background operations until any client request
45
/// is received.
46
///
47
/// Since this method affects all applications using the Arti process,
48
/// it requires administrative permissions.
49
///
50
/// ## Limitations
51
///
52
/// As of 2026 March, this functionality is not perfectly implemented,
53
/// and likely does not interact well with onion services.
54
/// Additionally, there are likely background operations that
55
/// this operation doesn't cover.
56
///
57
/// This method returns a reply immediately, but it may take a little
58
/// while before all of the background tasks finish their work and stop.
59
#[derive(Debug, serde::Deserialize, serde::Serialize, Deftly)]
60
#[derive_deftly(rpc::DynMethod)]
61
#[deftly(rpc(method_name = "arti:enter_dormant_mode"))]
62
struct EnterDormantMode {}
63

            
64
impl rpc::RpcMethod for EnterDormantMode {
65
    type Output = rpc::Nil;
66
    type Update = rpc::NoUpdates;
67
}
68

            
69
/// Implementation for [`EnterDormantMode`] on [`RpcSuperuser`].
70
async fn enter_dormant_mode_on_rpcsuperuser<R: Runtime>(
71
    session: Arc<RpcSuperuser<R>>,
72
    _method: Box<EnterDormantMode>,
73
    _ctx: Arc<dyn rpc::Context>,
74
) -> Result<rpc::Nil, rpc::RpcError> {
75
    use arti_client::DormantMode;
76
    session.tor_client.set_dormant(DormantMode::Soft);
77
    Ok(rpc::Nil::default())
78
}