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,
75  boost::optional<std::vector<beast::IP::Address>>& ips,
76  bool allowAllIps,
77  std::vector<beast::IP::Address> const& admin_ip)
78 {
79  auto const result = section.find(field);
80  if (result.second)
81  {
82  std::stringstream ss(result.first);
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 result = section.find("ip");
143  if (result.second)
144  {
145  try
146  {
147  port.ip = boost::asio::ip::address::from_string(result.first);
148  }
149  catch (std::exception const&)
150  {
151  log << "Invalid value '" << result.first
152  << "' for key 'ip' in [" << section.name() << "]";
153  Rethrow();
154  }
155  }
156  }
157 
158  {
159  auto const result = section.find("port");
160  if (result.second)
161  {
162  try
163  {
164  port.port =
165  beast::lexicalCastThrow<std::uint16_t>(result.first);
166 
167  // Port 0 is not supported
168  if (*port.port == 0)
169  Throw<std::exception>();
170  }
171  catch (std::exception const&)
172  {
173  log << "Invalid value '" << result.first << "' for key "
174  << "'port' in [" << section.name() << "]";
175  Rethrow();
176  }
177  }
178  }
179 
180  {
181  auto const result = section.find("protocol");
182  if (result.second)
183  {
184  for (auto const& s : beast::rfc2616::split_commas(
185  result.first.begin(), result.first.end()))
186  port.protocol.insert(s);
187  }
188  }
189 
190  {
191  auto const lim = get(section, "limit", "unlimited");
192 
193  if (!boost::iequals(lim, "unlimited"))
194  {
195  try
196  {
197  port.limit =
198  safe_cast<int>(beast::lexicalCastThrow<std::uint16_t>(lim));
199  }
200  catch (std::exception const&)
201  {
202  log << "Invalid value '" << lim << "' for key "
203  << "'limit' in [" << section.name() << "]";
204  Rethrow();
205  }
206  }
207  }
208 
209  {
210  auto const result = section.find("send_queue_limit");
211  if (result.second)
212  {
213  try
214  {
215  port.ws_queue_limit =
216  beast::lexicalCastThrow<std::uint16_t>(result.first);
217 
218  // Queue must be greater than 0
219  if (port.ws_queue_limit == 0)
220  Throw<std::exception>();
221  }
222  catch (std::exception const&)
223  {
224  log << "Invalid value '" << result.first << "' for key "
225  << "'send_queue_limit' in [" << section.name() << "]";
226  Rethrow();
227  }
228  }
229  else
230  {
231  // Default Websocket send queue size limit
232  port.ws_queue_limit = 100;
233  }
234  }
235 
236  populate(section, "admin", log, port.admin_ip, true, {});
237  populate(
238  section,
239  "secure_gateway",
240  log,
241  port.secure_gateway_ip,
242  false,
243  port.admin_ip.get_value_or({}));
244 
245  set(port.user, "user", section);
246  set(port.password, "password", section);
247  set(port.admin_user, "admin_user", section);
248  set(port.admin_password, "admin_password", section);
249  set(port.ssl_key, "ssl_key", section);
250  set(port.ssl_cert, "ssl_cert", section);
251  set(port.ssl_chain, "ssl_chain", section);
252  set(port.ssl_ciphers, "ssl_ciphers", section);
253 
254  port.pmd_options.server_enable =
255  section.value_or("permessage_deflate", true);
256  port.pmd_options.client_max_window_bits =
257  section.value_or("client_max_window_bits", 15);
258  port.pmd_options.server_max_window_bits =
259  section.value_or("server_max_window_bits", 15);
260  port.pmd_options.client_no_context_takeover =
261  section.value_or("client_no_context_takeover", false);
262  port.pmd_options.server_no_context_takeover =
263  section.value_or("server_no_context_takeover", false);
264  port.pmd_options.compLevel = section.value_or("compress_level", 8);
265  port.pmd_options.memLevel = section.value_or("memory_level", 4);
266 }
267 
268 } // namespace ripple
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
ripple::Port::admin_ip
std::vector< beast::IP::Address > admin_ip
Definition: Port.h:52
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:103
std::vector< beast::IP::Address >
std::find_if
T find_if(T... args)
ripple::Port::ip
boost::asio::ip::address ip
Definition: Port.h:49
ripple::Port::secure
bool secure() const
Definition: Port.cpp:30
ripple::ParsedPort::ip
boost::optional< boost::asio::ip::address > ip
Definition: Port.h:108
ripple::ParsedPort::limit
int limit
Definition: Port.h:105
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:154
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:48
ripple::Port::port
std::uint16_t port
Definition: Port.h:50
ripple::ParsedPort
Definition: Port.h:90
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
ripple::Port::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:51
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:58
beast::IP::Address
boost::asio::ip::address Address
Definition: IPAddress.h:41
ripple::ParsedPort::password
std::string password
Definition: Port.h:97
std::ostream
STL class.
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
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:276
ripple::ParsedPort::admin_user
std::string admin_user
Definition: Port.h:98
ripple::Port::secure_gateway_ip
std::vector< beast::IP::Address > secure_gateway_ip
Definition: Port.h:53
ripple::ParsedPort::secure_gateway_ip
boost::optional< std::vector< beast::IP::Address > > secure_gateway_ip
Definition: Port.h:111
ripple::populate
static void populate(Section const &section, std::string const &field, std::ostream &log, boost::optional< std::vector< beast::IP::Address >> &ips, bool allowAllIps, std::vector< beast::IP::Address > const &admin_ip)
Definition: Port.cpp:71
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:44
beast::rfc2616::split_commas
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:186
ripple::Section::find
std::pair< std::string, bool > find(std::string const &name) const
Retrieve a key/value pair.
Definition: BasicConfig.cpp:113
ripple::ParsedPort::ssl_chain
std::string ssl_chain
Definition: Port.h:102
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ParsedPort::port
boost::optional< std::uint16_t > port
Definition: Port.h:109
ripple::ParsedPort::pmd_options
boost::beast::websocket::permessage_deflate pmd_options
Definition: Port.h:104
std::set::cbegin
T cbegin(T... args)
std::getline
T getline(T... args)
ripple::ParsedPort::ssl_key
std::string ssl_key
Definition: Port.h:100
std::set::insert
T insert(T... args)
ripple::ParsedPort::user
std::string user
Definition: Port.h:96
ripple::ParsedPort::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:106
std::set::count
T count(T... args)
std::vector::empty
T empty(T... args)
std::set::cend
T cend(T... args)
ripple::ParsedPort::admin_ip
boost::optional< std::vector< beast::IP::Address > > admin_ip
Definition: Port.h:110
beast::IP::Endpoint::from_string_checked
static boost::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
ripple::ParsedPort::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:95
ripple::ParsedPort::admin_password
std::string admin_password
Definition: Port.h:99
ripple::ParsedPort::ssl_cert
std::string ssl_cert
Definition: Port.h:101
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:116