xrpld
Loading...
Searching...
No Matches
Port.cpp
1#include <xrpl/server/Port.h>
2
3#include <xrpl/basics/contract.h>
4#include <xrpl/basics/safe_cast.h>
5#include <xrpl/beast/core/LexicalCast.h>
6#include <xrpl/beast/net/IPEndpoint.h>
7#include <xrpl/beast/rfc2616.h>
8#include <xrpl/config/BasicConfig.h>
9#include <xrpl/config/Constants.h>
10
11#include <boost/algorithm/string/predicate.hpp>
12#include <boost/algorithm/string/trim.hpp>
13#include <boost/asio/ip/address.hpp>
14#include <boost/asio/ip/impl/network_v4.ipp>
15#include <boost/asio/ip/impl/network_v6.ipp>
16#include <boost/system/system_error.hpp>
17
18#include <cstdint>
19#include <exception>
20#include <ostream>
21#include <sstream>
22#include <string>
23#include <vector>
24
25namespace xrpl {
26
27bool
29{
30 return protocol.contains("peer") || protocol.contains("https") || protocol.contains("wss") ||
31 protocol.contains("wss2");
32}
33
36{
38 for (auto iter = protocol.cbegin(); iter != protocol.cend(); ++iter)
39 s += (iter != protocol.cbegin() ? "," : "") + *iter;
40 return s;
41}
42
44operator<<(std::ostream& os, Port const& p)
45{
46 os << "'" << p.name << "' (ip=" << p.ip << ":" << p.port << ", ";
47
48 if (!p.adminNetsV4.empty() || !p.adminNetsV6.empty())
49 {
50 os << "admin nets:";
51 for (auto const& net : p.adminNetsV4)
52 {
53 os << net.to_string();
54 os << ", ";
55 }
56 for (auto const& net : p.adminNetsV6)
57 {
58 os << net.to_string();
59 os << ", ";
60 }
61 }
62
64 {
65 os << "secure_gateway nets:";
66 for (auto const& net : p.secureGatewayNetsV4)
67 {
68 os << net.to_string();
69 os << ", ";
70 }
71 for (auto const& net : p.secureGatewayNetsV6)
72 {
73 os << net.to_string();
74 os << ", ";
75 }
76 }
77
78 os << p.protocols() << ")";
79 return os;
80}
81
82//------------------------------------------------------------------------------
83
84static void
86 Section const& section,
87 std::string const& field,
88 std::ostream& log,
91{
92 auto const optResult = section.get(field);
93 if (!optResult)
94 return;
95
96 std::stringstream ss(*optResult);
97 std::string ip;
98
99 while (std::getline(ss, ip, ','))
100 {
101 boost::algorithm::trim(ip);
102 bool v4 = false;
103 boost::asio::ip::network_v4 v4Net;
104 boost::asio::ip::network_v6 v6Net;
105
106 try
107 {
108 // First, check to see if 0.0.0.0 or ipv6 equivalent was configured,
109 // which means all IP addresses.
110 auto const addr = beast::IP::Endpoint::fromStringChecked(ip);
111 if (addr)
112 {
113 if (isUnspecified(*addr))
114 {
115 nets4.push_back(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->isV4();
126 std::string addressString = addr->toString();
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();
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();
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 [" << section.name()
188 << "]: " << e.what();
190 }
191 }
192}
193
194void
195parsePort(ParsedPort& port, Section const& section, std::ostream& log)
196{
197 port.name = section.name();
198 {
199 auto const optResult = section.get(Keys::kIp);
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 [" << section.name()
209 << "]";
210 rethrow();
211 }
212 }
213 }
214
215 {
216 auto const optResult = section.get(Keys::kPort);
217 if (optResult)
218 {
219 try
220 {
222
223 // Port 0 is not supported for [server]
224 if ((*port.port == 0) && (port.name == "server"))
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(Keys::kProtocol);
238 if (optResult)
239 {
240 for (auto const& s : beast::rfc2616::splitCommas(optResult->begin(), optResult->end()))
241 port.protocol.insert(s);
242 }
243 }
244
245 {
246 auto const lim = get(section, Keys::kLimit, "unlimited");
247
248 if (!boost::iequals(lim, "unlimited"))
249 {
250 try
251 {
253 }
254 catch (std::exception const&)
255 {
256 log << "Invalid value '" << lim << "' for key "
257 << "'limit' in [" << section.name() << "]";
258 rethrow();
259 }
260 }
261 }
262
263 {
264 auto const optResult = section.get(Keys::kSendQueueLimit);
265 if (optResult)
266 {
267 try
268 {
270
271 // Queue must be greater than 0
272 if (port.wsQueueLimit == 0)
274 }
275 catch (std::exception const&)
276 {
277 log << "Invalid value '" << *optResult << "' for key "
278 << "'send_queue_limit' in [" << section.name() << "]";
279 rethrow();
280 }
281 }
282 else
283 {
284 // Default Websocket send queue size limit
285 port.wsQueueLimit = 100;
286 }
287 }
288
289 populate(section, Keys::kAdmin, log, port.adminNetsV4, port.adminNetsV6);
290 populate(
292
293 set(port.user, Keys::kUser, section);
294 set(port.password, Keys::kPassword, section);
295 set(port.adminUser, Keys::kAdminUser, section);
296 set(port.adminPassword, Keys::kAdminPassword, section);
297 set(port.sslKey, Keys::kSslKey, section);
298 set(port.sslCert, Keys::kSslCert, section);
299 set(port.sslChain, Keys::kSslChain, section);
300 set(port.sslCiphers, Keys::kSslCiphers, section);
301
302 port.pmdOptions.server_enable = section.valueOr(Keys::kPermessageDeflate, true);
303 port.pmdOptions.client_max_window_bits = section.valueOr(Keys::kClientMaxWindowBits, 15);
304 port.pmdOptions.server_max_window_bits = section.valueOr(Keys::kServerMaxWindowBits, 15);
305 port.pmdOptions.client_no_context_takeover =
307 port.pmdOptions.server_no_context_takeover =
309 port.pmdOptions.compLevel = section.valueOr(Keys::kCompressLevel, 8);
310 port.pmdOptions.memLevel = section.valueOr(Keys::kMemoryLevel, 4);
311}
312
313} // namespace xrpl
static std::optional< Endpoint > fromStringChecked(std::string const &s)
Create an Endpoint from a string.
Holds a collection of configuration values.
Definition BasicConfig.h:24
std::optional< T > get(std::string const &name) const
std::string const & name() const
Returns the name of this section.
Definition BasicConfig.h:40
T valueOr(std::string const &name, T const &other) const
Returns a value if present, else another value.
T empty(T... args)
T getline(T... args)
T insert(T... args)
Result splitCommas(FwdIt first, FwdIt last)
Definition rfc2616.h:177
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
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,...
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:85
void parsePort(ParsedPort &port, Section const &section, std::ostream &log)
Definition Port.cpp:195
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
Definition safe_cast.h:21
std::ostream & operator<<(std::ostream &out, BaseUInt< Bits, Tag > const &u)
Definition base_uint.h:648
XRPL_NO_SANITIZE_ADDRESS void rethrow()
Rethrow the exception currently being handled.
Definition contract.h:33
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T push_back(T... args)
static constexpr auto kSslChain
Definition Constants.h:159
static constexpr auto kProtocol
Definition Constants.h:144
static constexpr auto kLimit
Definition Constants.h:117
static constexpr auto kClientNoContextTakeover
Definition Constants.h:100
static constexpr auto kMemoryLevel
Definition Constants.h:124
static constexpr auto kServerMaxWindowBits
Definition Constants.h:154
static constexpr auto kPermessageDeflate
Definition Constants.h:141
static constexpr auto kSslKey
Definition Constants.h:162
static constexpr auto kAdminPassword
Definition Constants.h:86
static constexpr auto kUser
Definition Constants.h:174
static constexpr auto kAdmin
Definition Constants.h:85
static constexpr auto kSslCiphers
Definition Constants.h:160
static constexpr auto kPort
Definition Constants.h:142
static constexpr auto kServerNoContextTakeover
Definition Constants.h:155
static constexpr auto kSslCert
Definition Constants.h:157
static constexpr auto kSecureGateway
Definition Constants.h:151
static constexpr auto kClientMaxWindowBits
Definition Constants.h:99
static constexpr auto kIp
Definition Constants.h:113
static constexpr auto kCompressLevel
Definition Constants.h:101
static constexpr auto kAdminUser
Definition Constants.h:87
static constexpr auto kSendQueueLimit
Definition Constants.h:152
static constexpr auto kPassword
Definition Constants.h:139
std::set< std::string, boost::beast::iless > protocol
Definition Port.h:80
std::vector< boost::asio::ip::network_v4 > adminNetsV4
Definition Port.h:95
std::optional< boost::asio::ip::address > ip
Definition Port.h:93
std::vector< boost::asio::ip::network_v6 > adminNetsV6
Definition Port.h:96
std::string sslKey
Definition Port.h:85
std::vector< boost::asio::ip::network_v6 > secureGatewayNetsV6
Definition Port.h:98
std::string name
Definition Port.h:79
std::string sslCiphers
Definition Port.h:88
std::string adminUser
Definition Port.h:83
std::string user
Definition Port.h:81
std::optional< std::uint16_t > port
Definition Port.h:94
std::vector< boost::asio::ip::network_v4 > secureGatewayNetsV4
Definition Port.h:97
std::string sslCert
Definition Port.h:86
std::string password
Definition Port.h:82
std::uint16_t wsQueueLimit
Definition Port.h:91
boost::beast::websocket::permessage_deflate pmdOptions
Definition Port.h:89
std::string adminPassword
Definition Port.h:84
std::string sslChain
Definition Port.h:87
Configuration information for a Server listening port.
Definition Port.h:28
std::string protocols() const
Definition Port.cpp:35
std::vector< boost::asio::ip::network_v6 > adminNetsV6
Definition Port.h:36
bool secure() const
Definition Port.cpp:28
std::vector< boost::asio::ip::network_v4 > secureGatewayNetsV4
Definition Port.h:37
std::vector< boost::asio::ip::network_v4 > adminNetsV4
Definition Port.h:35
std::vector< boost::asio::ip::network_v6 > secureGatewayNetsV6
Definition Port.h:38
boost::asio::ip::address ip
Definition Port.h:32
std::string name
Definition Port.h:31
std::uint16_t port
Definition Port.h:33