cuprated/config/rpc.rs
1use std::{
2 net::{IpAddr, Ipv4Addr},
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 #[comment_out = true]
62 /// Maximum amount of RPC connections allowed by a single public IP address.
63 ///
64 /// Setting this to `0` will disable the limit.
65 ///
66 /// Type | Number
67 /// Valid values | >= 0
68 /// Examples | 0 (no limit), 2, 4
69 pub public_ip_connection_limit: usize,
70
71 #[comment_out = true]
72 /// Maximum amount of RPC connections allowed by a single private IP address.
73 ///
74 /// Setting this to `0` will disable the limit.
75 ///
76 /// Type | Number
77 /// Valid values | >= 0
78 /// Examples | 0 (no limit), 16, 100
79 pub private_ip_connection_limit: usize,
80
81 #[comment_out = true]
82 /// Maximum amount of RPC connections allowed by a loopback address.
83 ///
84 /// Setting this to `0` will disable the limit.
85 ///
86 /// Type | Number
87 /// Valid values | >= 0
88 /// Examples | 0 (no limit), 67
89 pub loopback_connection_limit: usize,
90
91 #[comment_out = true]
92 /// Maximum amount of RPC connections allowed globally.
93 ///
94 /// Setting this to `0` will disable the limit.
95 ///
96 /// Type | Number
97 /// Valid values | >= 0
98 /// Examples | 0 (no limit), 16, 300
99 pub total_connection_limit: usize,
100
101 #[comment_out = true]
102 /// The list of IP addresses that are excluded from
103 /// all RPC connection limits.
104 ///
105 /// This can be useful if you are using a reverse proxy
106 /// in front of this node.
107 ///
108 /// Type | IPv4/IPv6 address
109 /// Examples | "", "127.0.0.1", "192.168.1.50"
110 pub excluded_ips_connection_limit: Vec<IpAddr>,
111
112 /// The time period during which the node can try sending data.
113 /// If a send operation do not complete within this Duration,
114 /// the connection is dropped.
115 ///
116 /// Type | Duration
117 /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
118 pub send_timeout: Duration,
119
120 /// The maximum time allowed to receive an HTTP/1 request header.
121 /// Receiving progress does not restart this deadline.
122 ///
123 /// Type | Duration
124 /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
125 pub header_read_timeout: Duration,
126
127 /// The maximum wall-clock time allowed to consume an HTTP request body.
128 /// Receiving progress does not restart this deadline.
129 ///
130 /// Type | Duration
131 /// Examples | { secs = 10, nanos = 0 }, { secs = 29, nanos = 123 }
132 pub body_read_timeout: Duration,
133
134 // TODO: <https://github.com/Cuprate/cuprate/issues/445>
135 }
136
137 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
138 #[serde(deny_unknown_fields, default)]
139 pub struct UnrestrictedRpcConfig {
140 /// Allow the unrestricted RPC server to be public.
141 ///
142 /// ⚠️ WARNING ⚠️
143 /// -------------
144 /// Unrestricted RPC should almost never be made available
145 /// to the wider internet. If the unrestricted address
146 /// is a non-local address, `cuprated` will crash,
147 /// unless this setting is set to `true`.
148 ///
149 /// Type | boolean
150 /// Valid values | true, false
151 pub i_know_what_im_doing_allow_public_unrestricted_rpc: bool,
152 }
153
154 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
155 #[serde(deny_unknown_fields, default)]
156 pub struct RestrictedRpcConfig {
157 /// Advertise the restricted RPC port.
158 ///
159 /// Setting this to `true` will make `cuprated`
160 /// share the restricted RPC server's port
161 /// publicly to the P2P network.
162 ///
163 /// Type | boolean
164 /// Valid values | true, false
165 pub advertise: bool,
166 }
167}
168
169impl Default for UnrestrictedRpcConfig {
170 fn default() -> Self {
171 Self {
172 i_know_what_im_doing_allow_public_unrestricted_rpc: false,
173 address: IpAddr::V4(Ipv4Addr::LOCALHOST),
174 port: DefaultOrCustom::Default,
175 enable: true,
176 request_byte_limit: 0,
177 public_ip_connection_limit: 0,
178 private_ip_connection_limit: 0,
179 loopback_connection_limit: 0,
180 total_connection_limit: 0,
181 excluded_ips_connection_limit: Vec::new(),
182 send_timeout: Duration::from_secs(5),
183 header_read_timeout: Duration::from_secs(30),
184 body_read_timeout: Duration::from_secs(5),
185 }
186 }
187}
188
189impl Default for RestrictedRpcConfig {
190 fn default() -> Self {
191 Self {
192 advertise: false,
193 address: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
194 port: DefaultOrCustom::Default,
195 enable: false,
196 // 1 megabyte.
197 // <https://github.com/monero-project/monero/blob/3b01c490953fe92f3c6628fa31d280a4f0490d28/src/cryptonote_config.h#L134>
198 request_byte_limit: 1024 * 1024,
199 public_ip_connection_limit: 3,
200 private_ip_connection_limit: 25,
201 loopback_connection_limit: 50,
202 total_connection_limit: 100,
203 excluded_ips_connection_limit: Vec::new(),
204 send_timeout: Duration::from_secs(5),
205 header_read_timeout: Duration::from_secs(30),
206 body_read_timeout: Duration::from_secs(5),
207 }
208 }
209}
210
211/// Gets the port to listen on for restricted RPC connections.
212pub const fn restricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
213 match config {
214 DefaultOrCustom::Default => match network {
215 Network::Mainnet | Network::FakeChain => 18089,
216 Network::Stagenet => 38089,
217 Network::Testnet => 28089,
218 },
219 DefaultOrCustom::Custom(port) => port,
220 }
221}
222
223/// Gets the port to listen on for unrestricted RPC connections.
224pub const fn unrestricted_rpc_port(config: DefaultOrCustom<u16>, network: Network) -> u16 {
225 match config {
226 DefaultOrCustom::Default => match network {
227 Network::Mainnet | Network::FakeChain => 18081,
228 Network::Stagenet => 38081,
229 Network::Testnet => 28081,
230 },
231 DefaultOrCustom::Custom(port) => port,
232 }
233}
234
235impl RestrictedRpcConfig {
236 /// Return the restricted RPC port for P2P if available and public.
237 pub const fn port_for_p2p(&self, network: Network) -> u16 {
238 if self.advertise && self.enable {
239 restricted_rpc_port(self.port, network)
240 } else {
241 0
242 }
243 }
244}