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