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/server/Port.h>
22 #include <ripple/beast/rfc2616.h>
23 #include <ripple/beast/core/LexicalCast.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 ||
33  protocol.count("https") > 0 ||
34  protocol.count("wss") > 0 ||
35  protocol.count("wss2") > 0;
36 }
37 
40 {
41  std::string s;
42  for (auto iter = protocol.cbegin();
43  iter != protocol.cend(); ++iter)
44  s += (iter != protocol.cbegin() ? "," : "") + *iter;
45  return s;
46 }
47 
50 {
51  os << "'" << p.name << "' (ip=" << p.ip << ":" << p.port << ", ";
52 
53  if (! p.admin_ip.empty ())
54  {
55  os << "admin IPs:";
56  for (auto const& ip : p.admin_ip)
57  os << ip.to_string () << ", ";
58  }
59 
60  if (! p.secure_gateway_ip.empty ())
61  {
62  os << "secure_gateway IPs:";
63  for (auto const& ip : p.secure_gateway_ip)
64  os << ip.to_string () << ", ";
65  }
66 
67  os << p.protocols () << ")";
68  return os;
69 }
70 
71 //------------------------------------------------------------------------------
72 
73 static
74 void
75 populate (Section const& section, std::string const& field, std::ostream& log,
76  boost::optional<std::vector<beast::IP::Address>>& ips,
77  bool allowAllIps, 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 [" <<
103  section.name () << "]";
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 (admin_ip.begin(), admin_ip.end(),
122  [&address] (beast::IP::Address const& a)
123  {
124  return address == a;
125  }
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 <<
174  "Invalid value '" << result.first << "' for key " <<
175  "'port' in [" << section.name() << "]";
176  Rethrow();
177  }
178  }
179  }
180 
181  {
182  auto const result = section.find("protocol");
183  if (result.second)
184  {
185  for (auto const& s : beast::rfc2616::split_commas(
186  result.first.begin(), result.first.end()))
187  port.protocol.insert(s);
188  }
189  }
190 
191  {
192  auto const lim = get (section, "limit", "unlimited");
193 
194  if (!boost::iequals (lim, "unlimited"))
195  {
196  try
197  {
198  port.limit = safe_cast<int> (
199  beast::lexicalCastThrow<std::uint16_t>(lim));
200  }
201  catch (std::exception const&)
202  {
203  log <<
204  "Invalid value '" << lim << "' for key " <<
205  "'limit' in [" << section.name() << "]";
206  Rethrow();
207  }
208  }
209  }
210 
211  {
212  auto const result = section.find("send_queue_limit");
213  if (result.second)
214  {
215  try
216  {
217  port.ws_queue_limit =
218  beast::lexicalCastThrow<std::uint16_t>(result.first);
219 
220  // Queue must be greater than 0
221  if (port.ws_queue_limit == 0)
222  Throw<std::exception>();
223  }
224  catch (std::exception const&)
225  {
226  log <<
227  "Invalid value '" << result.first << "' for key " <<
228  "'send_queue_limit' in [" << section.name() << "]";
229  Rethrow();
230  }
231  }
232  else
233  {
234  // Default Websocket send queue size limit
235  port.ws_queue_limit = 100;
236  }
237  }
238 
239  populate (section, "admin", log, port.admin_ip, true, {});
240  populate (section, "secure_gateway", log, port.secure_gateway_ip, false,
241  port.admin_ip.get_value_or({}));
242 
243  set(port.user, "user", section);
244  set(port.password, "password", section);
245  set(port.admin_user, "admin_user", section);
246  set(port.admin_password, "admin_password", section);
247  set(port.ssl_key, "ssl_key", section);
248  set(port.ssl_cert, "ssl_cert", section);
249  set(port.ssl_chain, "ssl_chain", section);
250  set(port.ssl_ciphers, "ssl_ciphers", section);
251 
252  port.pmd_options.server_enable =
253  section.value_or("permessage_deflate", true);
254  port.pmd_options.client_max_window_bits =
255  section.value_or("client_max_window_bits", 15);
256  port.pmd_options.server_max_window_bits =
257  section.value_or("server_max_window_bits", 15);
258  port.pmd_options.client_no_context_takeover =
259  section.value_or("client_no_context_takeover", false);
260  port.pmd_options.server_no_context_takeover =
261  section.value_or("server_no_context_takeover", false);
262  port.pmd_options.compLevel =
263  section.value_or("compress_level", 8);
264  port.pmd_options.memLevel =
265  section.value_or("memory_level", 4);
266 }
267 
268 } // 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:46
std::string
STL class.
std::exception
STL class.
ripple::Port::protocols
std::string protocols() const
Definition: Port.cpp:39
ripple::ParsedPort::ssl_ciphers
std::string ssl_ciphers
Definition: Port.h:94
std::vector< beast::IP::Address >
std::find_if
T find_if(T... args)
ripple::Port::ip
boost::asio::ip::address ip
Definition: Port.h:43
ripple::Port::secure
bool secure() const
Definition: Port.cpp:30
ripple::ParsedPort::ip
boost::optional< boost::asio::ip::address > ip
Definition: Port.h:99
ripple::ParsedPort::limit
int limit
Definition: Port.h:96
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:156
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:42
ripple::Port::port
std::uint16_t port
Definition: Port.h:44
ripple::ParsedPort
Definition: Port.h:81
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:237
ripple::Port::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:45
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:60
beast::IP::Address
boost::asio::ip::address Address
Definition: IPAddress.h:41
ripple::ParsedPort::password
std::string password
Definition: Port.h:88
std::ostream
STL class.
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:50
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:271
ripple::ParsedPort::admin_user
std::string admin_user
Definition: Port.h:89
ripple::Port::secure_gateway_ip
std::vector< beast::IP::Address > secure_gateway_ip
Definition: Port.h:47
ripple::ParsedPort::secure_gateway_ip
boost::optional< std::vector< beast::IP::Address > > secure_gateway_ip
Definition: Port.h:102
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:75
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:38
beast::rfc2616::split_commas
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:282
ripple::Section::find
std::pair< std::string, bool > find(std::string const &name) const
Retrieve a key/value pair.
Definition: BasicConfig.cpp:115
ripple::ParsedPort::ssl_chain
std::string ssl_chain
Definition: Port.h:93
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:100
ripple::ParsedPort::pmd_options
boost::beast::websocket::permessage_deflate pmd_options
Definition: Port.h:95
std::set::cbegin
T cbegin(T... args)
std::getline
T getline(T... args)
ripple::ParsedPort::ssl_key
std::string ssl_key
Definition: Port.h:91
std::set::insert
T insert(T... args)
ripple::ParsedPort::user
std::string user
Definition: Port.h:87
ripple::ParsedPort::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:97
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:101
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:37
ripple::ParsedPort::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:86
ripple::ParsedPort::admin_password
std::string admin_password
Definition: Port.h:90
ripple::ParsedPort::ssl_cert
std::string ssl_cert
Definition: Port.h:92
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:124