cuprated/config/rpc.rs
1use std::{
2 net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
3 time::Duration,
4};
5
6use serde::{Deserialize, Serialize};
7
8use cuprate_helper::network::Network;
9
10use super::{default::DefaultOrCustom, macros::config_struct};
11
12config_struct! {
13 /// RPC config.
14 #[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
15 #[serde(deny_unknown_fields, default)]
16 pub struct RpcConfig {
17 #[child = true]
18 /// Configuration for the unrestricted RPC server.
19 pub unrestricted: UnrestrictedRpcConfig,
20
21 #[child = true]
22 /// Configuration for the restricted RPC server.
23 pub restricted: RestrictedRpcConfig,
24 }
25}
26
27config_struct! {
28 Shared {
29 /// The address the RPC server will listen on.
30 ///
31 /// Type | IPv4/IPv6 address
32 /// Examples | "", "127.0.0.1", "192.168.1.50"
33 pub address: IpAddr,
34
35 /// The port the RPC server will listen on.
36 ///
37 /// Type | Number or "Default"
38 /// Valid values | 0..65534, "Default"
39 /// Examples | 18081, 18089, 5432
40 pub port: DefaultOrCustom<u16>,
41
42 /// Toggle the RPC server.
43 ///
44 /// If `true` the RPC server will be enabled.
45 /// If `false` the RPC server will be disabled.
46 ///
47 /// Type | boolean
48 /// Examples | true, false
49 pub enable: bool,
50
51 #[comment_out = true]
52 /// If a request is above this byte limit, it will be rejected.
53 ///
54 /// Setting this to `0` will disable the limit.
55 ///
56 /// Type | Number
57 /// Valid values | >= 0
58 /// Examples | 0 (no limit), 5242880 (5MB), 10485760 (10MB)
59 pub request_byte_limit: usize,
60
61 /// The time period during which the node can try sending data.
62 /// If a send operation do not complete within this Duration,
63 /// the connection is dropped.
64 ///
65 /// Type | Duration
66 /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
67 pub send_timeout: Duration,
68
69 /// The maximum time allowed to receive an HTTP/1 request header.
70 /// Receiving progress does not restart this deadline.
71 ///
72 /// Type | Duration
73 /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
74 pub header_read_timeout: Duration,
75
76 /// The maximum wall-clock time allowed to consume an HTTP request body.
77 /// Receiving progress does not restart this deadline.
78 ///
79 /// Type | Duration
80 /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
81 pub body_read_timeout: Duration,
82
83 // TODO: <https://github.com/Cuprate/cuprate/issues/445>
84 }
85
86 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
87 #[serde(deny_unknown_fields, default)]
88 pub struct UnrestrictedRpcConfig {
89 /// Allow the unrestricted RPC server to be public.
90 ///
91 /// ⚠️ WARNING ⚠️
92 /// -------------
93 /// Unrestricted RPC should almost never be made available
94 /// to the wider internet. If the unrestricted address
95 /// is a non-local address, `cuprated` will crash,
96 /// unless this setting is set to `true`.
97 ///
98 /// Type | boolean
99 /// Valid values | true, false
100 pub i_know_what_im_doing_allow_public_unrestricted_rpc: bool,
101 }
102
103 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
104 #[serde(deny_unknown_fields, default)]
105 pub struct RestrictedRpcConfig {
106 /// Advertise the restricted RPC port.
107 ///
108 /// Setting this to `true` will make `cuprated`
109 /// share the restricted RPC server's port
110 /// publicly to the P2P network.
111 ///
112 /// Type | boolean
113 /// Valid values | true, false
114 pub advertise: bool,
115 }
116}
117
118impl Default for UnrestrictedRpcConfig {
119 fn default() -> Self {
120 Self {
121 i_know_what_im_doing_allow_public_unrestricted_rpc: false,
122 address: IpAddr::V4(Ipv4Addr::LOCALHOST),
123 port: DefaultOrCustom::Default,
124 enable: true,
125 request_byte_limit: 0,
126 send_timeout: Duration::from_secs(5),
127 header_read_timeout: Duration::from_secs(30),
128 body_read_timeout: Duration::from_secs(5),
129 }
130 }
131}
132
133impl Default for RestrictedRpcConfig {
134 fn default() -> Self {
135 Self {
136 advertise: false,
137 address: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
138 port: DefaultOrCustom::Default,
139 enable: false,
140 // 1 megabyte.
141 // <https://github.com/monero-project/monero/blob/3b01c490953fe92f3c6628fa31d280a4f0490d28/src/cryptonote_config.h#L134>
142 request_byte_limit: 1024 * 1024,
143 send_timeout: Duration::from_secs(5),
144 header_read_timeout: Duration::from_secs(30),
145 body_read_timeout: Duration::from_secs(5),
146 }
147 }
148}
149
150/// Gets the port to listen on for restricted RPC connections.
151pub const fn restricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
152 match config {
153 DefaultOrCustom::Default => match network {
154 Network::Mainnet | Network::FakeChain => 18089,
155 Network::Stagenet => 38089,
156 Network::Testnet => 28089,
157 },
158 DefaultOrCustom::Custom(port) => port,
159 }
160}
161
162/// Gets the port to listen on for unrestricted RPC connections.
163pub const fn unrestricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
164 match config {
165 DefaultOrCustom::Default => match network {
166 Network::Mainnet | Network::FakeChain => 18081,
167 Network::Stagenet => 38081,
168 Network::Testnet => 28081,
169 },
170 DefaultOrCustom::Custom(port) => port,
171 }
172}
173
174impl RestrictedRpcConfig {
175 /// Return the restricted RPC port for P2P if available and public.
176 pub const fn port_for_p2p(&self, network: Network) -> u16 {
177 if self.advertise && self.enable {
178 restricted_rpc_port(self.port, network)
179 } else {
180 0
181 }
182 }
183}