rippled
Loading...
Searching...
No Matches
Port.cpp
1#include <xrpl/basics/BasicConfig.h>
2#include <xrpl/basics/contract.h>
3#include <xrpl/basics/safe_cast.h>
4#include <xrpl/beast/core/LexicalCast.h>
5#include <xrpl/beast/net/IPEndpoint.h>
6#include <xrpl/beast/rfc2616.h>
7#include <xrpl/server/Port.h>
8
9#include <boost/algorithm/string/predicate.hpp>
10#include <boost/algorithm/string/trim.hpp>
11#include <boost/asio/ip/address.hpp>
12#include <boost/asio/ip/impl/network_v4.ipp>
13#include <boost/asio/ip/impl/network_v6.ipp>
14#include <boost/system/system_error.hpp>
15
16#include <cstdint>
17#include <exception>
18#include <ostream>
19#include <sstream>
20#include <stdexcept>
21#include <string>
22#include <vector>
23
24namespace ripple {
25
26bool
28{
29 return protocol.count("peer") > 0 || protocol.count("https") > 0 ||
30 protocol.count("wss") > 0 || protocol.count("wss2") > 0;
31}
32
35{
37 for (auto iter = protocol.cbegin(); iter != protocol.cend(); ++iter)
38 s += (iter != protocol.cbegin() ? "," : "") + *iter;
39 return s;
40}
41
43operator<<(std::ostream& os, Port const& p)
44{
45 os << "'" << p.name << "' (ip=" << p.ip << ":" << p.port << ", ";
46
47 if (p.admin_nets_v4.size() || p.admin_nets_v6.size())
48 {
49 os << "admin nets:";
50 for (auto const& net : p.admin_nets_v4)
51 {
52 os << net.to_string();
53 os << ", ";
54 }
55 for (auto const& net : p.admin_nets_v6)
56 {
57 os << net.to_string();
58 os << ", ";
59 }
60 }
61
63 {
64 os << "secure_gateway nets:";
65 for (auto const& net : p.secure_gateway_nets_v4)
66 {
67 os << net.to_string();
68 os << ", ";
69 }
70 for (auto const& net : p.secure_gateway_nets_v6)
71 {
72 os << net.to_string();
73 os << ", ";
74 }
75 }
76
77 os << p.protocols() << ")";
78 return os;
79}
80
81//------------------------------------------------------------------------------
82
83static void
85 Section const& section,
86 std::string const& field,
87 std::ostream& log,
90{
91 auto const optResult = section.get(field);
92 if (!optResult)
93 return;
94
95 std::stringstream ss(*optResult);
96 std::string ip;
97
98 while (std::getline(ss, ip, ','))
99 {
100 boost::algorithm::trim(ip);
101 bool v4;
102 boost::asio::ip::network_v4 v4Net;
103 boost::asio::ip::network_v6 v6Net;
104
105 try
106 {
107 // First, check to see if 0.0.0.0 or ipv6 equivalent was configured,
108 // which means all IP addresses.
109 auto const addr = beast::IP::Endpoint::from_string_checked(ip);
110 if (addr)
111 {
112 if (is_unspecified(*addr))
113 {
114 nets4.push_back(
115 boost::asio::ip::make_network_v4("0.0.0.0/0"));
116 nets6.push_back(boost::asio::ip::make_network_v6("::/0"));
117 // No reason to allow more IPs--it would be redundant.
118 break;
119 }
120
121 // The configured address is a single IP (or else addr would
122 // be unset). We need this to be a subnet, so append
123 // the number of network bits to make a subnet of 1,
124 // depending on type.
125 v4 = addr->is_v4();
126 std::string addressString = addr->to_string();
127 if (v4)
128 {
129 addressString += "/32";
130 v4Net = boost::asio::ip::make_network_v4(addressString);
131 }
132 else
133 {
134 addressString += "/128";
135 v6Net = boost::asio::ip::make_network_v6(addressString);
136 }
137 }
138 else
139 {
140 // Since addr is empty, assume that the entry is
141 // for a subnet which includes trailing /0-32 or /0-128
142 // depending on ip type.
143 // First, see if it's an ipv4 subnet. If not, try ipv6.
144 // If that throws, then there's nothing we can do with
145 // the entry.
146 try
147 {
148 v4Net = boost::asio::ip::make_network_v4(ip);
149 v4 = true;
150 }
151 catch (boost::system::system_error const&)
152 {
153 v6Net = boost::asio::ip::make_network_v6(ip);
154 v4 = false;
155 }
156 }
157
158 // Confirm that the address entry is the same as the subnet's
159 // underlying network address.
160 // 10.1.2.3/24 makes no sense. The underlying network address
161 // is 10.1.2.0/24.
162 if (v4)
163 {
164 if (v4Net != v4Net.canonical())
165 {
166 log << "The configured subnet " << v4Net.to_string()
167 << " is not the same as the network address, which is "
168 << v4Net.canonical().to_string();
169 Throw<std::exception>();
170 }
171 nets4.push_back(v4Net);
172 }
173 else
174 {
175 if (v6Net != v6Net.canonical())
176 {
177 log << "The configured subnet " << v6Net.to_string()
178 << " is not the same as the network address, which is "
179 << v6Net.canonical().to_string();
180 Throw<std::exception>();
181 }
182 nets6.push_back(v6Net);
183 }
184 }
185 catch (boost::system::system_error const& e)
186 {
187 log << "Invalid value '" << ip << "' for key '" << field << "' in ["
188 << section.name() << "]: " << e.what();
189 Throw<std::exception>();
190 }
191 }
192}
193
194void
195parse_Port(ParsedPort& port, Section const& section, std::ostream& log)
196{
197 port.name = section.name();
198 {
199 auto const optResult = section.get("ip");
200 if (optResult)
201 {
202 try
203 {
204 port.ip = boost::asio::ip::make_address(*optResult);
205 }
206 catch (std::exception const&)
207 {
208 log << "Invalid value '" << *optResult << "' for key 'ip' in ["
209 << section.name() << "]";
210 Rethrow();
211 }
212 }
213 }
214
215 {
216 auto const optResult = section.get("port");
217 if (optResult)
218 {
219 try
220 {
221 port.port = beast::lexicalCastThrow<std::uint16_t>(*optResult);
222
223 // Port 0 is not supported for [server]
224 if ((*port.port == 0) && (port.name == "server"))
225 Throw<std::exception>();
226 }
227 catch (std::exception const&)
228 {
229 log << "Invalid value '" << *optResult << "' for key "
230 << "'port' in [" << section.name() << "]";
231 Rethrow();
232 }
233 }
234 }
235
236 {
237 auto const optResult = section.get("protocol");
238 if (optResult)
239 {
240 for (auto const& s : beast::rfc2616::split_commas(
241 optResult->begin(), optResult->end()))
242 port.protocol.insert(s);
243 }
244 }
245
246 {
247 auto const lim = get(section, "limit", "unlimited");
248
249 if (!boost::iequals(lim, "unlimited"))
250 {
251 try
252 {
253 port.limit =
254 safe_cast<int>(beast::lexicalCastThrow<std::uint16_t>(lim));
255 }
256 catch (std::exception const&)
257 {
258 log << "Invalid value '" << lim << "' for key "
259 << "'limit' in [" << section.name() << "]";
260 Rethrow();
261 }
262 }
263 }
264
265 {
266 auto const optResult = section.get("send_queue_limit");
267 if (optResult)
268 {
269 try
270 {
271 port.ws_queue_limit =
272 beast::lexicalCastThrow<std::uint16_t>(*optResult);
273
274 // Queue must be greater than 0
275 if (port.ws_queue_limit == 0)
276 Throw<std::exception>();
277 }
278 catch (std::exception const&)
279 {
280 log << "Invalid value '" << *optResult << "' for key "
281 << "'send_queue_limit' in [" << section.name() << "]";
282 Rethrow();
283 }
284 }
285 else
286 {
287 // Default Websocket send queue size limit
288 port.ws_queue_limit = 100;
289 }
290 }
291
292 populate(section, "admin", log, port.admin_nets_v4, port.admin_nets_v6);
293 populate(
294 section,
295 "secure_gateway",
296 log,
299
300 set(port.user, "user", section);
301 set(port.password, "password", section);
302 set(port.admin_user, "admin_user", section);
303 set(port.admin_password, "admin_password", section);
304 set(port.ssl_key, "ssl_key", section);
305 set(port.ssl_cert, "ssl_cert", section);
306 set(port.ssl_chain, "ssl_chain", section);
307 set(port.ssl_ciphers, "ssl_ciphers", section);
308
309 port.pmd_options.server_enable =
310 section.value_or("permessage_deflate", true);
311 port.pmd_options.client_max_window_bits =
312 section.value_or("client_max_window_bits", 15);
313 port.pmd_options.server_max_window_bits =
314 section.value_or("server_max_window_bits", 15);
315 port.pmd_options.client_no_context_takeover =
316 section.value_or("client_no_context_takeover", false);
317 port.pmd_options.server_no_context_takeover =
318 section.value_or("server_no_context_takeover", false);
319 port.pmd_options.compLevel = section.value_or("compress_level", 8);
320 port.pmd_options.memLevel = section.value_or("memory_level", 4);
321}
322
323} // namespace ripple
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Holds a collection of configuration values.
Definition BasicConfig.h:26
std::string const & name() const
Returns the name of this section.
Definition BasicConfig.h:42
T value_or(std::string const &name, T const &other) const
Returns a value if present, else another value.
std::optional< T > get(std::string const &name) const
T getline(T... args)
T insert(T... args)
Result split_commas(FwdIt first, FwdIt last)
Definition rfc2616.h:180
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
static void populate(Section const &section, std::string const &field, std::ostream &log, std::vector< boost::asio::ip::network_v4 > &nets4, std::vector< boost::asio::ip::network_v6 > &nets6)
Definition Port.cpp:84
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
void parse_Port(ParsedPort &port, Section const &section, std::ostream &log)
Definition Port.cpp:195
std::ostream & operator<<(std::ostream &out, base_uint< Bits, Tag > const &u)
Definition base_uint.h:628
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
void Rethrow()
Rethrow the exception currently being handled.
Definition contract.h:29
T push_back(T... args)
T size(T... args)
std::string ssl_ciphers
Definition Port.h:91
boost::beast::websocket::permessage_deflate pmd_options
Definition Port.h:92
std::optional< std::uint16_t > port
Definition Port.h:97
std::vector< boost::asio::ip::network_v4 > admin_nets_v4
Definition Port.h:98
std::string user
Definition Port.h:84
std::string ssl_key
Definition Port.h:88
std::uint16_t ws_queue_limit
Definition Port.h:94
std::vector< boost::asio::ip::network_v6 > secure_gateway_nets_v6
Definition Port.h:101
std::set< std::string, boost::beast::iless > protocol
Definition Port.h:83
std::string admin_password
Definition Port.h:87
std::string name
Definition Port.h:82
std::string ssl_chain
Definition Port.h:90
std::string password
Definition Port.h:85
std::vector< boost::asio::ip::network_v6 > admin_nets_v6
Definition Port.h:99
std::string ssl_cert
Definition Port.h:89
std::string admin_user
Definition Port.h:86
std::optional< boost::asio::ip::address > ip
Definition Port.h:96
std::vector< boost::asio::ip::network_v4 > secure_gateway_nets_v4
Definition Port.h:100
Configuration information for a Server listening port.
Definition Port.h:31
std::uint16_t port
Definition Port.h:36
bool secure() const
Definition Port.cpp:27
std::vector< boost::asio::ip::network_v6 > admin_nets_v6
Definition Port.h:39
std::string protocols() const
Definition Port.cpp:34
std::vector< boost::asio::ip::network_v6 > secure_gateway_nets_v6
Definition Port.h:41
std::vector< boost::asio::ip::network_v4 > secure_gateway_nets_v4
Definition Port.h:40
boost::asio::ip::address ip
Definition Port.h:35
std::string name
Definition Port.h:34
std::vector< boost::asio::ip::network_v4 > admin_nets_v4
Definition Port.h:38