rippled
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 <ripple/basics/safe_cast.h>
21 #include <ripple/beast/core/LexicalCast.h>
22 #include <ripple/beast/rfc2616.h>
23 #include <ripple/server/Port.h>
24 
25 #include <boost/algorithm/string/predicate.hpp>
26 
27 namespace ripple {
28 
29 bool
30 Port::secure() const
31 {
32  return protocol.count("peer") > 0 || protocol.count("https") > 0 ||
33  protocol.count("wss") > 0 || protocol.count("wss2") > 0;
34 }
35 
38 {
39  std::string s;
40  for (auto iter = protocol.cbegin(); iter != protocol.cend(); ++iter)
41  s += (iter != protocol.cbegin() ? "," : "") + *iter;
42  return s;
43 }
44 
47 {
48  os << "'" << p.name << "' (ip=" << p.ip << ":" << p.port << ", ";
49 
50  if (!p.admin_ip.empty())
51  {
52  os << "admin IPs:";
53  for (auto const& ip : p.admin_ip)
54  os << ip.to_string() << ", ";
55  }
56 
57  if (!p.secure_gateway_ip.empty())
58  {
59  os << "secure_gateway IPs:";
60  for (auto const& ip : p.secure_gateway_ip)
61  os << ip.to_string() << ", ";
62  }
63 
64  os << p.protocols() << ")";
65  return os;
66 }
67 
68 //------------------------------------------------------------------------------
69 
70 static void
72  Section const& section,
73  std::string const& field,
74  std::ostream& log,
76  bool allowAllIps,
77  std::vector<beast::IP::Address> const& admin_ip)
78 {
79  auto const optResult = section.get(field);
80  if (optResult)
81  {
82  std::stringstream ss(*optResult);
83  std::string ip;
84  bool has_any(false);
85 
86  ips.emplace();
87  while (std::getline(ss, ip, ','))
88  {
89  auto const addr = beast::IP::Endpoint::from_string_checked(ip);
90  if (!addr)
91  {
92  log << "Invalid value '" << ip << "' for key '" << field
93  << "' in [" << section.name() << "]";
94  Throw<std::exception>();
95  }
96 
97  if (is_unspecified(*addr))
98  {
99  if (!allowAllIps)
100  {
101  log << addr->address() << " not allowed'"
102  << "' for key '" << field << "' in [" << section.name()
103  << "]";
104  Throw<std::exception>();
105  }
106  else
107  {
108  has_any = true;
109  }
110  }
111 
112  if (has_any && !ips->empty())
113  {
114  log << "IP specified along with " << addr->address() << " '"
115  << ip << "' for key '" << field << "' in ["
116  << section.name() << "]";
117  Throw<std::exception>();
118  }
119 
120  auto const& address = addr->address();
121  if (std::find_if(
122  admin_ip.begin(),
123  admin_ip.end(),
124  [&address](beast::IP::Address const& a) {
125  return address == a;
126  }) != admin_ip.end())
127  {
128  log << "IP specified for " << field << " is also for "
129  << "admin: " << ip << " in [" << section.name() << "]";
130  Throw<std::exception>();
131  }
132 
133  ips->emplace_back(addr->address());
134  }
135  }
136 }
137 
138 void
139 parse_Port(ParsedPort& port, Section const& section, std::ostream& log)
140 {
141  {
142  auto const optResult = section.get("ip");
143  if (optResult)
144  {
145  try
146  {
147  port.ip = boost::asio::ip::address::from_string(*optResult);
148  }
149  catch (std::exception const&)
150  {
151  log << "Invalid value '" << *optResult << "' for key 'ip' in ["
152  << section.name() << "]";
153  Rethrow();
154  }
155  }
156  }
157 
158  {
159  auto const optResult = section.get("port");
160  if (optResult)
161  {
162  try
163  {
164  port.port = beast::lexicalCastThrow<std::uint16_t>(*optResult);
165 
166  // Port 0 is not supported
167  if (*port.port == 0)
168  Throw<std::exception>();
169  }
170  catch (std::exception const&)
171  {
172  log << "Invalid value '" << *optResult << "' for key "
173  << "'port' in [" << section.name() << "]";
174  Rethrow();
175  }
176  }
177  }
178 
179  {
180  auto const optResult = section.get("protocol");
181  if (optResult)
182  {
183  for (auto const& s : beast::rfc2616::split_commas(
184  optResult->begin(), optResult->end()))
185  port.protocol.insert(s);
186  }
187  }
188 
189  {
190  auto const lim = get(section, "limit", "unlimited");
191 
192  if (!boost::iequals(lim, "unlimited"))
193  {
194  try
195  {
196  port.limit =
197  safe_cast<int>(beast::lexicalCastThrow<std::uint16_t>(lim));
198  }
199  catch (std::exception const&)
200  {
201  log << "Invalid value '" << lim << "' for key "
202  << "'limit' in [" << section.name() << "]";
203  Rethrow();
204  }
205  }
206  }
207 
208  {
209  auto const optResult = section.get("send_queue_limit");
210  if (optResult)
211  {
212  try
213  {
214  port.ws_queue_limit =
215  beast::lexicalCastThrow<std::uint16_t>(*optResult);
216 
217  // Queue must be greater than 0
218  if (port.ws_queue_limit == 0)
219  Throw<std::exception>();
220  }
221  catch (std::exception const&)
222  {
223  log << "Invalid value '" << *optResult << "' for key "
224  << "'send_queue_limit' in [" << section.name() << "]";
225  Rethrow();
226  }
227  }
228  else
229  {
230  // Default Websocket send queue size limit
231  port.ws_queue_limit = 100;
232  }
233  }
234 
235  populate(section, "admin", log, port.admin_ip, true, {});
236  populate(
237  section,
238  "secure_gateway",
239  log,
240  port.secure_gateway_ip,
241  false,
243 
244  set(port.user, "user", section);
245  set(port.password, "password", section);
246  set(port.admin_user, "admin_user", section);
247  set(port.admin_password, "admin_password", section);
248  set(port.ssl_key, "ssl_key", section);
249  set(port.ssl_cert, "ssl_cert", section);
250  set(port.ssl_chain, "ssl_chain", section);
251  set(port.ssl_ciphers, "ssl_ciphers", section);
252 
253  port.pmd_options.server_enable =
254  section.value_or("permessage_deflate", true);
255  port.pmd_options.client_max_window_bits =
256  section.value_or("client_max_window_bits", 15);
257  port.pmd_options.server_max_window_bits =
258  section.value_or("server_max_window_bits", 15);
259  port.pmd_options.client_no_context_takeover =
260  section.value_or("client_no_context_takeover", false);
261  port.pmd_options.server_no_context_takeover =
262  section.value_or("server_no_context_takeover", false);
263  port.pmd_options.compLevel = section.value_or("compress_level", 8);
264  port.pmd_options.memLevel = section.value_or("memory_level", 4);
265 }
266 
267 } // namespace ripple
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::Port::admin_ip
std::vector< beast::IP::Address > admin_ip
Definition: Port.h:53
ripple::ParsedPort::admin_ip
std::optional< std::vector< beast::IP::Address > > admin_ip
Definition: Port.h:111
std::string
STL class.
std::exception
STL class.
ripple::Port::protocols
std::string protocols() const
Definition: Port.cpp:37
ripple::ParsedPort::ssl_ciphers
std::string ssl_ciphers
Definition: Port.h:104
std::vector< beast::IP::Address >
std::find_if
T find_if(T... args)
std::optional::value_or
T value_or(T... args)
ripple::Port::ip
boost::asio::ip::address ip
Definition: Port.h:50
ripple::Port::secure
bool secure() const
Definition: Port.cpp:30
ripple::ParsedPort::limit
int limit
Definition: Port.h:106
std::stringstream
STL class.
ripple::Section::value_or
T value_or(std::string const &name, T const &other) const
Returns a value if present, else another value.
Definition: BasicConfig.h:149
ripple::parse_Port
void parse_Port(ParsedPort &port, Section const &section, std::ostream &log)
Definition: Port.cpp:139
ripple::Port::name
std::string name
Definition: Port.h:49
ripple::Port::port
std::uint16_t port
Definition: Port.h:51
ripple::ParsedPort
Definition: Port.h:91
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:59
ripple::populate
static void populate(Section const &section, std::string const &field, std::ostream &log, std::optional< std::vector< beast::IP::Address >> &ips, bool allowAllIps, std::vector< beast::IP::Address > const &admin_ip)
Definition: Port.cpp:71
beast::IP::Address
boost::asio::ip::address Address
Definition: IPAddress.h:41
ripple::ParsedPort::password
std::string password
Definition: Port.h:98
std::ostream
STL class.
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
ripple::ParsedPort::secure_gateway_ip
std::optional< std::vector< beast::IP::Address > > secure_gateway_ip
Definition: Port.h:112
ripple::set
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:313
ripple::ParsedPort::admin_user
std::string admin_user
Definition: Port.h:99
ripple::Port::secure_gateway_ip
std::vector< beast::IP::Address > secure_gateway_ip
Definition: Port.h:54
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:45
beast::rfc2616::split_commas
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:199
ripple::ParsedPort::ssl_chain
std::string ssl_chain
Definition: Port.h:103
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ParsedPort::ip
std::optional< boost::asio::ip::address > ip
Definition: Port.h:109
protocol
Definition: ValidatorList.h:38
ripple::ParsedPort::pmd_options
boost::beast::websocket::permessage_deflate pmd_options
Definition: Port.h:105
std::vector::begin
T begin(T... args)
std::getline
T getline(T... args)
ripple::ParsedPort::ssl_key
std::string ssl_key
Definition: Port.h:101
ripple::ParsedPort::port
std::optional< std::uint16_t > port
Definition: Port.h:110
std::set::insert
T insert(T... args)
ripple::ParsedPort::user
std::string user
Definition: Port.h:97
ripple::ParsedPort::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:107
ripple::Section::get
std::optional< T > get(std::string const &name) const
Definition: BasicConfig.h:138
std::vector::empty
T empty(T... args)
std::optional
std::vector::end
T end(T... args)
ripple::ParsedPort::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:96
ripple::ParsedPort::admin_password
std::string admin_password
Definition: Port.h:100
beast::IP::Endpoint::from_string_checked
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
ripple::ParsedPort::ssl_cert
std::string ssl_cert
Definition: Port.h:102
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118