rippled
ServerHandlerImp.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/app/main/Application.h>
21 #include <ripple/app/misc/NetworkOPs.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/basics/base64.h>
24 #include <ripple/basics/contract.h>
25 #include <ripple/basics/make_SSLContext.h>
26 #include <ripple/beast/net/IPAddressConversion.h>
27 #include <ripple/beast/rfc2616.h>
28 #include <ripple/core/JobQueue.h>
29 #include <ripple/json/json_reader.h>
30 #include <ripple/json/to_string.h>
31 #include <ripple/net/RPCErr.h>
32 #include <ripple/overlay/Overlay.h>
33 #include <ripple/resource/Fees.h>
34 #include <ripple/resource/ResourceManager.h>
35 #include <ripple/rpc/RPCHandler.h>
36 #include <ripple/rpc/Role.h>
37 #include <ripple/rpc/ServerHandler.h>
38 #include <ripple/rpc/impl/RPCHelpers.h>
39 #include <ripple/rpc/impl/ServerHandlerImp.h>
40 #include <ripple/rpc/impl/Tuning.h>
41 #include <ripple/rpc/json_body.h>
42 #include <ripple/server/Server.h>
43 #include <ripple/server/SimpleWriter.h>
44 #include <ripple/server/impl/JSONRPCUtil.h>
45 #include <boost/algorithm/string.hpp>
46 #include <boost/beast/http/fields.hpp>
47 #include <boost/beast/http/string_body.hpp>
48 #include <boost/type_traits.hpp>
49 #include <algorithm>
50 #include <mutex>
51 #include <stdexcept>
52 
53 namespace ripple {
54 
55 static bool
57 {
58  return request.version() >= 11 && request.target() == "/" &&
59  request.body().size() == 0 &&
60  request.method() == boost::beast::http::verb::get;
61 }
62 
63 static Handoff
65  http_request_type const& request,
66  boost::beast::http::status status)
67 {
68  using namespace boost::beast::http;
69  Handoff handoff;
70  response<string_body> msg;
71  msg.version(request.version());
72  msg.result(status);
73  msg.insert("Server", BuildInfo::getFullVersionString());
74  msg.insert("Content-Type", "text/html");
75  msg.insert("Connection", "close");
76  msg.body() = "Invalid protocol.";
77  msg.prepare_payload();
78  handoff.response = std::make_shared<SimpleWriter>(msg);
79  return handoff;
80 }
81 
82 // VFALCO TODO Rewrite to use boost::beast::http::fields
83 static bool
85 {
86  if (port.user.empty() || port.password.empty())
87  return true;
88 
89  auto const it = h.find("authorization");
90  if ((it == h.end()) || (it->second.substr(0, 6) != "Basic "))
91  return false;
92  std::string strUserPass64 = it->second.substr(6);
93  boost::trim(strUserPass64);
94  std::string strUserPass = base64_decode(strUserPass64);
95  std::string::size_type nColon = strUserPass.find(":");
96  if (nColon == std::string::npos)
97  return false;
98  std::string strUser = strUserPass.substr(0, nColon);
99  std::string strPassword = strUserPass.substr(nColon + 1);
100  return strUser == port.user && strPassword == port.password;
101 }
102 
104  Application& app,
105  boost::asio::io_service& io_service,
106  JobQueue& jobQueue,
107  NetworkOPs& networkOPs,
108  Resource::Manager& resourceManager,
109  CollectorManager& cm)
110  : app_(app)
111  , m_resourceManager(resourceManager)
112  , m_journal(app_.journal("Server"))
113  , m_networkOPs(networkOPs)
114  , m_server(make_Server(*this, io_service, app_.journal("Server")))
115  , m_jobQueue(jobQueue)
116 {
117  auto const& group(cm.group("rpc"));
118  rpc_requests_ = group->make_counter("requests");
119  rpc_size_ = group->make_event("size");
120  rpc_time_ = group->make_event("time");
121 }
122 
124 {
125  m_server = nullptr;
126 }
127 
128 void
130 {
131  setup_ = setup;
132  m_server->ports(setup.ports);
133 }
134 
135 //------------------------------------------------------------------------------
136 
137 void
139 {
140  m_server->close();
141  {
142  std::unique_lock lock(mutex_);
143  condition_.wait(lock, [this] { return stopped_; });
144  }
145 }
146 
147 //------------------------------------------------------------------------------
148 
149 bool
151  Session& session,
152  boost::asio::ip::tcp::endpoint endpoint)
153 {
154  auto const& port = session.port();
155 
156  auto const c = [this, &port]() {
157  std::lock_guard lock(mutex_);
158  return ++count_[port];
159  }();
160 
161  if (port.limit && c >= port.limit)
162  {
163  JLOG(m_journal.trace())
164  << port.name << " is full; dropping " << endpoint;
165  return false;
166  }
167 
168  return true;
169 }
170 
171 Handoff
173  Session& session,
175  http_request_type&& request,
176  boost::asio::ip::tcp::endpoint const& remote_address)
177 {
178  using namespace boost::beast;
179  auto const& p{session.port().protocol};
180  bool const is_ws{
181  p.count("ws") > 0 || p.count("ws2") > 0 || p.count("wss") > 0 ||
182  p.count("wss2") > 0};
183 
184  if (websocket::is_upgrade(request))
185  {
186  if (!is_ws)
187  return statusRequestResponse(request, http::status::unauthorized);
188 
190  try
191  {
192  ws = session.websocketUpgrade();
193  }
194  catch (std::exception const& e)
195  {
196  JLOG(m_journal.error())
197  << "Exception upgrading websocket: " << e.what() << "\n";
198  return statusRequestResponse(
199  request, http::status::internal_server_error);
200  }
201 
202  auto is{std::make_shared<WSInfoSub>(m_networkOPs, ws)};
203  auto const beast_remote_address =
205  is->getConsumer() = requestInboundEndpoint(
207  beast_remote_address,
208  requestRole(
209  Role::GUEST,
210  session.port(),
211  Json::Value(),
212  beast_remote_address,
213  is->user()),
214  is->user(),
215  is->forwarded_for());
216  ws->appDefined = std::move(is);
217  ws->run();
218 
219  Handoff handoff;
220  handoff.moved = true;
221  return handoff;
222  }
223 
224  if (bundle && p.count("peer") > 0)
225  return app_.overlay().onHandoff(
226  std::move(bundle), std::move(request), remote_address);
227 
228  if (is_ws && isStatusRequest(request))
229  return statusResponse(request);
230 
231  // Otherwise pass to legacy onRequest or websocket
232  return {};
233 }
234 
235 static inline Json::Output
237 {
238  return [&](boost::beast::string_view const& b) {
239  session.write(b.data(), b.size());
240  };
241 }
242 
244 build_map(boost::beast::http::fields const& h)
245 {
247  for (auto const& e : h)
248  {
249  auto key(e.name_string().to_string());
250  std::transform(key.begin(), key.end(), key.begin(), [](auto kc) {
251  return std::tolower(static_cast<unsigned char>(kc));
252  });
253  c[key] = e.value().to_string();
254  }
255  return c;
256 }
257 
258 template <class ConstBufferSequence>
259 static std::string
260 buffers_to_string(ConstBufferSequence const& bs)
261 {
262  using boost::asio::buffer_cast;
263  using boost::asio::buffer_size;
264  std::string s;
265  s.reserve(buffer_size(bs));
266  // Use auto&& so the right thing happens whether bs returns a copy or
267  // a reference
268  for (auto&& b : bs)
269  s.append(buffer_cast<char const*>(b), buffer_size(b));
270  return s;
271 }
272 
273 void
275 {
276  // Make sure RPC is enabled on the port
277  if (session.port().protocol.count("http") == 0 &&
278  session.port().protocol.count("https") == 0)
279  {
280  HTTPReply(403, "Forbidden", makeOutput(session), app_.journal("RPC"));
281  session.close(true);
282  return;
283  }
284 
285  // Check user/password authorization
286  if (!authorized(session.port(), build_map(session.request())))
287  {
288  HTTPReply(403, "Forbidden", makeOutput(session), app_.journal("RPC"));
289  session.close(true);
290  return;
291  }
292 
293  std::shared_ptr<Session> detachedSession = session.detach();
294  auto const postResult = m_jobQueue.postCoro(
295  jtCLIENT,
296  "RPC-Client",
297  [this, detachedSession](std::shared_ptr<JobQueue::Coro> coro) {
298  processSession(detachedSession, coro);
299  });
300  if (postResult == nullptr)
301  {
302  // The coroutine was rejected, probably because we're shutting down.
303  HTTPReply(
304  503,
305  "Service Unavailable",
306  makeOutput(*detachedSession),
307  app_.journal("RPC"));
308  detachedSession->close(true);
309  return;
310  }
311 }
312 
313 void
317 {
318  Json::Value jv;
319  auto const size = boost::asio::buffer_size(buffers);
320  if (size > RPC::Tuning::maxRequestSize ||
321  !Json::Reader{}.parse(jv, buffers) || !jv.isObject())
322  {
323  Json::Value jvResult(Json::objectValue);
324  jvResult[jss::type] = jss::error;
325  jvResult[jss::error] = "jsonInvalid";
326  jvResult[jss::value] = buffers_to_string(buffers);
327  boost::beast::multi_buffer sb;
328  Json::stream(jvResult, [&sb](auto const p, auto const n) {
329  sb.commit(boost::asio::buffer_copy(
330  sb.prepare(n), boost::asio::buffer(p, n)));
331  });
332  JLOG(m_journal.trace()) << "Websocket sending '" << jvResult << "'";
333  session->send(
334  std::make_shared<StreambufWSMsg<decltype(sb)>>(std::move(sb)));
335  session->complete();
336  return;
337  }
338 
339  JLOG(m_journal.trace()) << "Websocket received '" << jv << "'";
340 
341  auto const postResult = m_jobQueue.postCoro(
342  jtCLIENT,
343  "WS-Client",
344  [this, session, jv = std::move(jv)](
345  std::shared_ptr<JobQueue::Coro> const& coro) {
346  auto const jr = this->processSession(session, coro, jv);
347  auto const s = to_string(jr);
348  auto const n = s.length();
349  boost::beast::multi_buffer sb(n);
350  sb.commit(boost::asio::buffer_copy(
351  sb.prepare(n), boost::asio::buffer(s.c_str(), n)));
352  session->send(
353  std::make_shared<StreambufWSMsg<decltype(sb)>>(std::move(sb)));
354  session->complete();
355  });
356  if (postResult == nullptr)
357  {
358  // The coroutine was rejected, probably because we're shutting down.
359  session->close({boost::beast::websocket::going_away, "Shutting Down"});
360  }
361 }
362 
363 void
364 ServerHandlerImp::onClose(Session& session, boost::system::error_code const&)
365 {
366  std::lock_guard lock(mutex_);
367  --count_[session.port()];
368 }
369 
370 void
372 {
373  std::lock_guard lock(mutex_);
374  stopped_ = true;
376 }
377 
378 //------------------------------------------------------------------------------
379 
382  std::shared_ptr<WSSession> const& session,
384  Json::Value const& jv)
385 {
386  auto is = std::static_pointer_cast<WSInfoSub>(session->appDefined);
387  if (is->getConsumer().disconnect())
388  {
389  session->close(
390  {boost::beast::websocket::policy_error, "threshold exceeded"});
391  // FIX: This rpcError is not delivered since the session
392  // was just closed.
393  return rpcError(rpcSLOW_DOWN);
394  }
395 
396  // Requests without "command" are invalid.
399  try
400  {
401  auto apiVersion =
403  if (apiVersion == RPC::apiInvalidVersion ||
404  (!jv.isMember(jss::command) && !jv.isMember(jss::method)) ||
405  (jv.isMember(jss::command) && !jv[jss::command].isString()) ||
406  (jv.isMember(jss::method) && !jv[jss::method].isString()) ||
407  (jv.isMember(jss::command) && jv.isMember(jss::method) &&
408  jv[jss::command].asString() != jv[jss::method].asString()))
409  {
410  jr[jss::type] = jss::response;
411  jr[jss::status] = jss::error;
412  jr[jss::error] = apiVersion == RPC::apiInvalidVersion
413  ? jss::invalid_API_version
414  : jss::missingCommand;
415  jr[jss::request] = jv;
416  if (jv.isMember(jss::id))
417  jr[jss::id] = jv[jss::id];
418  if (jv.isMember(jss::jsonrpc))
419  jr[jss::jsonrpc] = jv[jss::jsonrpc];
420  if (jv.isMember(jss::ripplerpc))
421  jr[jss::ripplerpc] = jv[jss::ripplerpc];
422  if (jv.isMember(jss::api_version))
423  jr[jss::api_version] = jv[jss::api_version];
424 
425  is->getConsumer().charge(Resource::feeInvalidRPC);
426  return jr;
427  }
428 
429  auto required = RPC::roleRequired(
430  apiVersion,
432  jv.isMember(jss::command) ? jv[jss::command].asString()
433  : jv[jss::method].asString());
434  auto role = requestRole(
435  required,
436  session->port(),
437  jv,
438  beast::IP::from_asio(session->remote_endpoint().address()),
439  is->user());
440  if (Role::FORBID == role)
441  {
442  loadType = Resource::feeInvalidRPC;
443  jr[jss::result] = rpcError(rpcFORBIDDEN);
444  }
445  else
446  {
447  RPC::JsonContext context{
448  {app_.journal("RPCHandler"),
449  app_,
450  loadType,
451  app_.getOPs(),
453  is->getConsumer(),
454  role,
455  coro,
456  is,
457  apiVersion},
458  jv,
459  {is->user(), is->forwarded_for()}};
460 
461  RPC::doCommand(context, jr[jss::result]);
462  }
463  }
464  catch (std::exception const& ex)
465  {
466  jr[jss::result] = RPC::make_error(rpcINTERNAL);
467  JLOG(m_journal.error())
468  << "Exception while processing WS: " << ex.what() << "\n"
469  << "Input JSON: " << Json::Compact{Json::Value{jv}};
470  }
471 
472  is->getConsumer().charge(loadType);
473  if (is->getConsumer().warn())
474  jr[jss::warning] = jss::load;
475 
476  // Currently we will simply unwrap errors returned by the RPC
477  // API, in the future maybe we can make the responses
478  // consistent.
479  //
480  // Regularize result. This is duplicate code.
481  if (jr[jss::result].isMember(jss::error))
482  {
483  jr = jr[jss::result];
484  jr[jss::status] = jss::error;
485 
486  auto rq = jv;
487 
488  if (rq.isObject())
489  {
490  if (rq.isMember(jss::passphrase.c_str()))
491  rq[jss::passphrase.c_str()] = "<masked>";
492  if (rq.isMember(jss::secret.c_str()))
493  rq[jss::secret.c_str()] = "<masked>";
494  if (rq.isMember(jss::seed.c_str()))
495  rq[jss::seed.c_str()] = "<masked>";
496  if (rq.isMember(jss::seed_hex.c_str()))
497  rq[jss::seed_hex.c_str()] = "<masked>";
498  }
499 
500  jr[jss::request] = rq;
501  }
502  else
503  {
504  if (jr[jss::result].isMember("forwarded") &&
505  jr[jss::result]["forwarded"])
506  jr = jr[jss::result];
507  jr[jss::status] = jss::success;
508  }
509 
510  if (jv.isMember(jss::id))
511  jr[jss::id] = jv[jss::id];
512  if (jv.isMember(jss::jsonrpc))
513  jr[jss::jsonrpc] = jv[jss::jsonrpc];
514  if (jv.isMember(jss::ripplerpc))
515  jr[jss::ripplerpc] = jv[jss::ripplerpc];
516  if (jv.isMember(jss::api_version))
517  jr[jss::api_version] = jv[jss::api_version];
518 
519  jr[jss::type] = jss::response;
520  return jr;
521 }
522 
523 // Run as a coroutine.
524 void
526  std::shared_ptr<Session> const& session,
528 {
530  session->port(),
531  buffers_to_string(session->request().body().data()),
532  session->remoteAddress().at_port(0),
533  makeOutput(*session),
534  coro,
535  forwardedFor(session->request()),
536  [&] {
537  auto const iter = session->request().find("X-User");
538  if (iter != session->request().end())
539  return iter->value();
540  return boost::beast::string_view{};
541  }());
542 
543  if (beast::rfc2616::is_keep_alive(session->request()))
544  session->complete();
545  else
546  session->close(true);
547 }
548 
549 static Json::Value
551 {
553  sub["code"] = code;
554  sub["message"] = std::move(message);
556  r["error"] = sub;
557  return r;
558 }
559 
560 Json::Int constexpr method_not_found = -32601;
561 Json::Int constexpr server_overloaded = -32604;
562 Json::Int constexpr forbidden = -32605;
563 Json::Int constexpr wrong_version = -32606;
564 
565 void
567  Port const& port,
568  std::string const& request,
569  beast::IP::Endpoint const& remoteIPAddress,
570  Output&& output,
572  boost::string_view forwardedFor,
573  boost::string_view user)
574 {
575  auto rpcJ = app_.journal("RPC");
576 
577  Json::Value jsonOrig;
578  {
579  Json::Reader reader;
580  if ((request.size() > RPC::Tuning::maxRequestSize) ||
581  !reader.parse(request, jsonOrig) || !jsonOrig ||
582  !jsonOrig.isObject())
583  {
584  HTTPReply(
585  400,
586  "Unable to parse request: " + reader.getFormatedErrorMessages(),
587  output,
588  rpcJ);
589  return;
590  }
591  }
592 
593  bool batch = false;
594  unsigned size = 1;
595  if (jsonOrig.isMember(jss::method) && jsonOrig[jss::method] == "batch")
596  {
597  batch = true;
598  if (!jsonOrig.isMember(jss::params) || !jsonOrig[jss::params].isArray())
599  {
600  HTTPReply(400, "Malformed batch request", output, rpcJ);
601  return;
602  }
603  size = jsonOrig[jss::params].size();
604  }
605 
607  auto const start(std::chrono::high_resolution_clock::now());
608  for (unsigned i = 0; i < size; ++i)
609  {
610  Json::Value const& jsonRPC =
611  batch ? jsonOrig[jss::params][i] : jsonOrig;
612 
613  if (!jsonRPC.isObject())
614  {
616  r[jss::request] = jsonRPC;
617  r[jss::error] =
618  make_json_error(method_not_found, "Method not found");
619  reply.append(r);
620  continue;
621  }
622 
623  auto apiVersion = RPC::apiVersionIfUnspecified;
624  if (jsonRPC.isMember(jss::params) && jsonRPC[jss::params].isArray() &&
625  jsonRPC[jss::params].size() > 0 &&
626  jsonRPC[jss::params][0u].isObject())
627  {
628  apiVersion = RPC::getAPIVersionNumber(
629  jsonRPC[jss::params][Json::UInt(0)],
631  }
632 
633  if (apiVersion == RPC::apiVersionIfUnspecified && batch)
634  {
635  // for batch request, api_version may be at a different level
636  apiVersion =
638  }
639 
640  if (apiVersion == RPC::apiInvalidVersion)
641  {
642  if (!batch)
643  {
644  HTTPReply(400, jss::invalid_API_version.c_str(), output, rpcJ);
645  return;
646  }
648  r[jss::request] = jsonRPC;
649  r[jss::error] = make_json_error(
650  wrong_version, jss::invalid_API_version.c_str());
651  reply.append(r);
652  continue;
653  }
654 
655  /* ------------------------------------------------------------------ */
656  auto role = Role::FORBID;
657  auto required = Role::FORBID;
658  if (jsonRPC.isMember(jss::method) && jsonRPC[jss::method].isString())
659  required = RPC::roleRequired(
660  apiVersion,
662  jsonRPC[jss::method].asString());
663 
664  if (jsonRPC.isMember(jss::params) && jsonRPC[jss::params].isArray() &&
665  jsonRPC[jss::params].size() > 0 &&
666  jsonRPC[jss::params][Json::UInt(0)].isObjectOrNull())
667  {
668  role = requestRole(
669  required,
670  port,
671  jsonRPC[jss::params][Json::UInt(0)],
672  remoteIPAddress,
673  user);
674  }
675  else
676  {
677  role = requestRole(
678  required, port, Json::objectValue, remoteIPAddress, user);
679  }
680 
681  Resource::Consumer usage;
682  if (isUnlimited(role))
683  {
684  usage = m_resourceManager.newUnlimitedEndpoint(remoteIPAddress);
685  }
686  else
687  {
689  remoteIPAddress, role == Role::PROXY, forwardedFor);
690  if (usage.disconnect())
691  {
692  if (!batch)
693  {
694  HTTPReply(503, "Server is overloaded", output, rpcJ);
695  return;
696  }
697  Json::Value r = jsonRPC;
698  r[jss::error] =
699  make_json_error(server_overloaded, "Server is overloaded");
700  reply.append(r);
701  continue;
702  }
703  }
704 
705  if (role == Role::FORBID)
706  {
708  if (!batch)
709  {
710  HTTPReply(403, "Forbidden", output, rpcJ);
711  return;
712  }
713  Json::Value r = jsonRPC;
714  r[jss::error] = make_json_error(forbidden, "Forbidden");
715  reply.append(r);
716  continue;
717  }
718 
719  if (!jsonRPC.isMember(jss::method) || jsonRPC[jss::method].isNull())
720  {
722  if (!batch)
723  {
724  HTTPReply(400, "Null method", output, rpcJ);
725  return;
726  }
727  Json::Value r = jsonRPC;
728  r[jss::error] = make_json_error(method_not_found, "Null method");
729  reply.append(r);
730  continue;
731  }
732 
733  Json::Value const& method = jsonRPC[jss::method];
734  if (!method.isString())
735  {
737  if (!batch)
738  {
739  HTTPReply(400, "method is not string", output, rpcJ);
740  return;
741  }
742  Json::Value r = jsonRPC;
743  r[jss::error] =
744  make_json_error(method_not_found, "method is not string");
745  reply.append(r);
746  continue;
747  }
748 
749  std::string strMethod = method.asString();
750  if (strMethod.empty())
751  {
753  if (!batch)
754  {
755  HTTPReply(400, "method is empty", output, rpcJ);
756  return;
757  }
758  Json::Value r = jsonRPC;
759  r[jss::error] =
760  make_json_error(method_not_found, "method is empty");
761  reply.append(r);
762  continue;
763  }
764 
765  // Extract request parameters from the request Json as `params`.
766  //
767  // If the field "params" is empty, `params` is an empty object.
768  //
769  // Otherwise, that field must be an array of length 1 (why?)
770  // and we take that first entry and validate that it's an object.
771  Json::Value params;
772  if (!batch)
773  {
774  params = jsonRPC[jss::params];
775  if (!params)
776  params = Json::Value(Json::objectValue);
777 
778  else if (!params.isArray() || params.size() != 1)
779  {
781  HTTPReply(400, "params unparseable", output, rpcJ);
782  return;
783  }
784  else
785  {
786  params = std::move(params[0u]);
787  if (!params.isObjectOrNull())
788  {
790  HTTPReply(400, "params unparseable", output, rpcJ);
791  return;
792  }
793  }
794  }
795  else // batch
796  {
797  params = jsonRPC;
798  }
799 
800  std::string ripplerpc = "1.0";
801  if (params.isMember(jss::ripplerpc))
802  {
803  if (!params[jss::ripplerpc].isString())
804  {
806  if (!batch)
807  {
808  HTTPReply(400, "ripplerpc is not a string", output, rpcJ);
809  return;
810  }
811 
812  Json::Value r = jsonRPC;
813  r[jss::error] = make_json_error(
814  method_not_found, "ripplerpc is not a string");
815  reply.append(r);
816  continue;
817  }
818  ripplerpc = params[jss::ripplerpc].asString();
819  }
820 
825  if (role != Role::IDENTIFIED && role != Role::PROXY)
826  {
827  forwardedFor.clear();
828  user.clear();
829  }
830 
831  JLOG(m_journal.debug()) << "Query: " << strMethod << params;
832 
833  // Provide the JSON-RPC method as the field "command" in the request.
834  params[jss::command] = strMethod;
835  JLOG(m_journal.trace())
836  << "doRpcCommand:" << strMethod << ":" << params;
837 
839 
840  RPC::JsonContext context{
841  {m_journal,
842  app_,
843  loadType,
844  m_networkOPs,
846  usage,
847  role,
848  coro,
850  apiVersion},
851  params,
852  {user, forwardedFor}};
853  Json::Value result;
854  RPC::doCommand(context, result);
855  usage.charge(loadType);
856  if (usage.warn())
857  result[jss::warning] = jss::load;
858 
860  if (ripplerpc >= "2.0")
861  {
862  if (result.isMember(jss::error))
863  {
864  result[jss::status] = jss::error;
865  result["code"] = result[jss::error_code];
866  result["message"] = result[jss::error_message];
867  result.removeMember(jss::error_message);
868  JLOG(m_journal.debug()) << "rpcError: " << result[jss::error]
869  << ": " << result[jss::error_message];
870  r[jss::error] = std::move(result);
871  }
872  else
873  {
874  result[jss::status] = jss::success;
875  r[jss::result] = std::move(result);
876  }
877  }
878  else
879  {
880  // Always report "status". On an error report the request as
881  // received.
882  if (result.isMember(jss::error))
883  {
884  auto rq = params;
885 
886  if (rq.isObject())
887  { // But mask potentially sensitive information.
888  if (rq.isMember(jss::passphrase.c_str()))
889  rq[jss::passphrase.c_str()] = "<masked>";
890  if (rq.isMember(jss::secret.c_str()))
891  rq[jss::secret.c_str()] = "<masked>";
892  if (rq.isMember(jss::seed.c_str()))
893  rq[jss::seed.c_str()] = "<masked>";
894  if (rq.isMember(jss::seed_hex.c_str()))
895  rq[jss::seed_hex.c_str()] = "<masked>";
896  }
897 
898  result[jss::status] = jss::error;
899  result[jss::request] = rq;
900 
901  JLOG(m_journal.debug()) << "rpcError: " << result[jss::error]
902  << ": " << result[jss::error_message];
903  }
904  else
905  {
906  result[jss::status] = jss::success;
907  }
908  r[jss::result] = std::move(result);
909  }
910 
911  if (params.isMember(jss::jsonrpc))
912  r[jss::jsonrpc] = params[jss::jsonrpc];
913  if (params.isMember(jss::ripplerpc))
914  r[jss::ripplerpc] = params[jss::ripplerpc];
915  if (params.isMember(jss::id))
916  r[jss::id] = params[jss::id];
917  if (batch)
918  reply.append(std::move(r));
919  else
920  reply = std::move(r);
921 
922  if (reply.isMember(jss::result) &&
923  reply[jss::result].isMember(jss::result))
924  {
925  reply = reply[jss::result];
926  if (reply.isMember(jss::status))
927  {
928  reply[jss::result][jss::status] = reply[jss::status];
929  reply.removeMember(jss::status);
930  }
931  }
932  }
933  auto response = to_string(reply);
934 
935  rpc_time_.notify(std::chrono::duration_cast<std::chrono::milliseconds>(
937  ++rpc_requests_;
939 
940  response += '\n';
941 
942  if (auto stream = m_journal.debug())
943  {
944  static const int maxSize = 10000;
945  if (response.size() <= maxSize)
946  stream << "Reply: " << response;
947  else
948  stream << "Reply: " << response.substr(0, maxSize);
949  }
950 
951  HTTPReply(200, response, output, rpcJ);
952 }
953 
954 //------------------------------------------------------------------------------
955 
956 /* This response is used with load balancing.
957  If the server is overloaded, status 500 is reported. Otherwise status 200
958  is reported, meaning the server can accept more connections.
959 */
960 Handoff
962 {
963  using namespace boost::beast::http;
964  Handoff handoff;
965  response<string_body> msg;
966  std::string reason;
967  if (app_.serverOkay(reason))
968  {
969  msg.result(boost::beast::http::status::ok);
970  msg.body() = "<!DOCTYPE html><html><head><title>" + systemName() +
971  " Test page for rippled</title></head><body><h1>" + systemName() +
972  " Test</h1><p>This page shows rippled http(s) "
973  "connectivity is working.</p></body></html>";
974  }
975  else
976  {
977  msg.result(boost::beast::http::status::internal_server_error);
978  msg.body() = "<HTML><BODY>Server cannot accept clients: " + reason +
979  "</BODY></HTML>";
980  }
981  msg.version(request.version());
982  msg.insert("Server", BuildInfo::getFullVersionString());
983  msg.insert("Content-Type", "text/html");
984  msg.insert("Connection", "close");
985  msg.prepare_payload();
986  handoff.response = std::make_shared<SimpleWriter>(msg);
987  return handoff;
988 }
989 
990 //------------------------------------------------------------------------------
991 
992 void
994 {
995  for (auto& p : ports)
996  {
997  if (p.secure())
998  {
999  if (p.ssl_key.empty() && p.ssl_cert.empty() && p.ssl_chain.empty())
1000  p.context = make_SSLContext(p.ssl_ciphers);
1001  else
1002  p.context = make_SSLContextAuthed(
1003  p.ssl_key, p.ssl_cert, p.ssl_chain, p.ssl_ciphers);
1004  }
1005  else
1006  {
1007  p.context = std::make_shared<boost::asio::ssl::context>(
1008  boost::asio::ssl::context::sslv23);
1009  }
1010  }
1011 }
1012 
1013 static Port
1014 to_Port(ParsedPort const& parsed, std::ostream& log)
1015 {
1016  Port p;
1017  p.name = parsed.name;
1018 
1019  if (!parsed.ip)
1020  {
1021  log << "Missing 'ip' in [" << p.name << "]";
1022  Throw<std::exception>();
1023  }
1024  p.ip = *parsed.ip;
1025 
1026  if (!parsed.port)
1027  {
1028  log << "Missing 'port' in [" << p.name << "]";
1029  Throw<std::exception>();
1030  }
1031  else if (*parsed.port == 0)
1032  {
1033  log << "Port " << *parsed.port << "in [" << p.name << "] is invalid";
1034  Throw<std::exception>();
1035  }
1036  p.port = *parsed.port;
1037  if (parsed.admin_ip)
1038  p.admin_ip = *parsed.admin_ip;
1039  if (parsed.secure_gateway_ip)
1041 
1042  if (parsed.protocol.empty())
1043  {
1044  log << "Missing 'protocol' in [" << p.name << "]";
1045  Throw<std::exception>();
1046  }
1047  p.protocol = parsed.protocol;
1048 
1049  p.user = parsed.user;
1050  p.password = parsed.password;
1051  p.admin_user = parsed.admin_user;
1052  p.admin_password = parsed.admin_password;
1053  p.ssl_key = parsed.ssl_key;
1054  p.ssl_cert = parsed.ssl_cert;
1055  p.ssl_chain = parsed.ssl_chain;
1056  p.ssl_ciphers = parsed.ssl_ciphers;
1057  p.pmd_options = parsed.pmd_options;
1058  p.ws_queue_limit = parsed.ws_queue_limit;
1059  p.limit = parsed.limit;
1060 
1061  return p;
1062 }
1063 
1064 static std::vector<Port>
1065 parse_Ports(Config const& config, std::ostream& log)
1066 {
1067  std::vector<Port> result;
1068 
1069  if (!config.exists("server"))
1070  {
1071  log << "Required section [server] is missing";
1072  Throw<std::exception>();
1073  }
1074 
1075  ParsedPort common;
1076  parse_Port(common, config["server"], log);
1077 
1078  auto const& names = config.section("server").values();
1079  result.reserve(names.size());
1080  for (auto const& name : names)
1081  {
1082  if (!config.exists(name))
1083  {
1084  log << "Missing section: [" << name << "]";
1085  Throw<std::exception>();
1086  }
1087  ParsedPort parsed = common;
1088  parsed.name = name;
1089  parse_Port(parsed, config[name], log);
1090  result.push_back(to_Port(parsed, log));
1091  }
1092 
1093  if (config.standalone())
1094  {
1095  auto it = result.begin();
1096 
1097  while (it != result.end())
1098  {
1099  auto& p = it->protocol;
1100 
1101  // Remove the peer protocol, and if that would
1102  // leave the port empty, remove the port as well
1103  if (p.erase("peer") && p.empty())
1104  it = result.erase(it);
1105  else
1106  ++it;
1107  }
1108  }
1109  else
1110  {
1111  auto const count =
1112  std::count_if(result.cbegin(), result.cend(), [](Port const& p) {
1113  return p.protocol.count("peer") != 0;
1114  });
1115 
1116  if (count > 1)
1117  {
1118  log << "Error: More than one peer protocol configured in [server]";
1119  Throw<std::exception>();
1120  }
1121 
1122  if (count == 0)
1123  log << "Warning: No peer protocol configured";
1124  }
1125 
1126  return result;
1127 }
1128 
1129 // Fill out the client portion of the Setup
1130 static void
1132 {
1133  decltype(setup.ports)::const_iterator iter;
1134  for (iter = setup.ports.cbegin(); iter != setup.ports.cend(); ++iter)
1135  if (iter->protocol.count("http") > 0 ||
1136  iter->protocol.count("https") > 0)
1137  break;
1138  if (iter == setup.ports.cend())
1139  return;
1140  setup.client.secure = iter->protocol.count("https") > 0;
1142  ?
1143  // VFALCO HACK! to make localhost work
1144  (iter->ip.is_v6() ? "::1" : "127.0.0.1")
1145  : iter->ip.to_string();
1146  setup.client.port = iter->port;
1147  setup.client.user = iter->user;
1148  setup.client.password = iter->password;
1149  setup.client.admin_user = iter->admin_user;
1150  setup.client.admin_password = iter->admin_password;
1151 }
1152 
1153 // Fill out the overlay portion of the Setup
1154 static void
1156 {
1157  auto const iter = std::find_if(
1158  setup.ports.cbegin(), setup.ports.cend(), [](Port const& port) {
1159  return port.protocol.count("peer") != 0;
1160  });
1161  if (iter == setup.ports.cend())
1162  {
1163  setup.overlay.port = 0;
1164  return;
1165  }
1166  setup.overlay.ip = iter->ip;
1167  setup.overlay.port = iter->port;
1168 }
1169 
1170 ServerHandler::Setup
1172 {
1174  setup.ports = parse_Ports(config, log);
1175 
1178 
1179  return setup;
1180 }
1181 
1184  Application& app,
1185  boost::asio::io_service& io_service,
1186  JobQueue& jobQueue,
1187  NetworkOPs& networkOPs,
1188  Resource::Manager& resourceManager,
1189  CollectorManager& cm)
1190 {
1191  return std::make_unique<ServerHandlerImp>(
1192  app, io_service, jobQueue, networkOPs, resourceManager, cm);
1193 }
1194 
1195 } // namespace ripple
ripple::Resource::Manager::newInboundEndpoint
virtual Consumer newInboundEndpoint(beast::IP::Endpoint const &address)=0
Create a new endpoint keyed by inbound IP address or the forwarded IP if proxied.
ripple::NetworkOPs
Provides server functionality for clients.
Definition: NetworkOPs.h:86
ripple::RPC::apiInvalidVersion
constexpr unsigned int apiInvalidVersion
API version numbers used in later API versions.
Definition: RPCHelpers.h:221
ripple::Port::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:71
ripple::Application
Definition: Application.h:115
ripple::RPC::apiVersionIfUnspecified
constexpr unsigned int apiVersionIfUnspecified
Definition: RPCHelpers.h:222
ripple::Port::admin_ip
std::vector< beast::IP::Address > admin_ip
Definition: Port.h:53
ripple::ServerHandlerImp::count_
std::map< std::reference_wrapper< Port const >, int > count_
Definition: ServerHandlerImp.h:105
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::make_Server
std::unique_ptr< Server > make_Server(Handler &handler, boost::asio::io_service &io_service, beast::Journal journal)
Create the HTTP server using the specified handler.
Definition: Server.h:34
ripple::ParsedPort::admin_ip
std::optional< std::vector< beast::IP::Address > > admin_ip
Definition: Port.h:111
ripple::ServerHandlerImp::Setup::client_t::user
std::string user
Definition: ServerHandlerImp.h:64
ripple::Resource::Consumer::warn
bool warn()
Returns true if the consumer should be warned.
Definition: Consumer.cpp:110
ripple::ServerHandlerImp::m_journal
beast::Journal m_journal
Definition: ServerHandlerImp.h:94
ripple::Overlay::onHandoff
virtual Handoff onHandoff(std::unique_ptr< stream_type > &&bundle, http_request_type &&request, boost::asio::ip::tcp::endpoint remote_address)=0
Conditionally accept an incoming HTTP request.
ripple::Dir::const_iterator
Definition: Directory.h:49
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
std::string
STL class.
std::shared_ptr
STL class.
ripple::ServerHandlerImp::ServerHandlerImp
ServerHandlerImp(Application &app, boost::asio::io_service &io_service, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
Definition: ServerHandlerImp.cpp:103
ripple::makeOutput
static Json::Output makeOutput(Session &session)
Definition: ServerHandlerImp.cpp:236
ripple::JobQueue::postCoro
std::shared_ptr< Coro > postCoro(JobType t, std::string const &name, F &&f)
Creates a coroutine and adds a job to the queue which will run it.
Definition: JobQueue.h:429
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1009
ripple::jtCLIENT
@ jtCLIENT
Definition: Job.h:44
std::exception
STL class.
ripple::ServerHandlerImp::m_jobQueue
JobQueue & m_jobQueue
Definition: ServerHandlerImp.h:98
ripple::Session::websocketUpgrade
virtual std::shared_ptr< WSSession > websocketUpgrade()=0
Convert the connection to WebSocket.
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::ServerHandlerImp::setup_
Setup setup_
Definition: ServerHandlerImp.h:97
Json::stream
void stream(Json::Value const &jv, Write const &write)
Stream compact JSON to the specified function.
Definition: json_writer.h:300
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::make_json_error
static Json::Value make_json_error(Json::Int code, Json::Value &&message)
Definition: ServerHandlerImp.cpp:550
ripple::RPC::roleRequired
Role roleRequired(unsigned int version, bool betaEnabled, std::string const &method)
Definition: RPCHandler.cpp:293
ripple::ParsedPort::ssl_ciphers
std::string ssl_ciphers
Definition: Port.h:104
std::string::reserve
T reserve(T... args)
ripple::ServerHandlerImp::Setup::client_t::secure
bool secure
Definition: ServerHandlerImp.h:61
std::make_shared
T make_shared(T... args)
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
Json::Compact
Decorator for streaming out compact json.
Definition: json_writer.h:316
ripple::RPC::getAPIVersionNumber
unsigned int getAPIVersionNumber(Json::Value const &jv, bool betaEnabled)
Retrieve the api version number from the json value.
Definition: RPCHelpers.cpp:892
std::vector
STL class.
ripple::ServerHandlerImp::Setup::client_t::admin_user
std::string admin_user
Definition: ServerHandlerImp.h:66
std::map::find
T find(T... args)
ripple::Port::ssl_key
std::string ssl_key
Definition: Port.h:59
std::string::size
T size(T... args)
ripple::ServerHandlerImp::stop
void stop()
Definition: ServerHandlerImp.cpp:138
ripple::ServerHandlerImp::Setup
Definition: ServerHandlerImp.h:50
ripple::make_SSLContext
std::shared_ptr< boost::asio::ssl::context > make_SSLContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
Definition: make_SSLContext.cpp:400
ripple::requestInboundEndpoint
Resource::Consumer requestInboundEndpoint(Resource::Manager &manager, beast::IP::Endpoint const &remoteAddress, Role const &role, boost::string_view const &user, boost::string_view const &forwardedFor)
Definition: Role.cpp:111
ripple::CollectorManager
Provides the beast::insight::Collector service.
Definition: CollectorManager.h:29
ripple::Port::ip
boost::asio::ip::address ip
Definition: Port.h:50
ripple::method_not_found
constexpr Json::Int method_not_found
Definition: ServerHandlerImp.cpp:560
std::chrono::milliseconds
ripple::ParsedPort::limit
int limit
Definition: Port.h:106
std::lock_guard
STL class.
ripple::server_overloaded
constexpr Json::Int server_overloaded
Definition: ServerHandlerImp.cpp:561
ripple::Resource::feeReferenceRPC
const Charge feeReferenceRPC
ripple::Role::IDENTIFIED
@ IDENTIFIED
ripple::HTTPReply
void HTTPReply(int nStatus, std::string const &content, Json::Output const &output, beast::Journal j)
Definition: JSONRPCUtil.cpp:56
Json::Value::isNull
bool isNull() const
isNull() tests to see if this field is null.
Definition: json_value.cpp:967
ripple::ServerHandlerImp::rpc_requests_
beast::insight::Counter rpc_requests_
Definition: ServerHandlerImp.h:99
ripple::Port::admin_user
std::string admin_user
Definition: Port.h:57
ripple::ServerHandlerImp::Setup::client_t::port
std::uint16_t port
Definition: ServerHandlerImp.h:63
std::function
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
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
ripple::Session
Persistent state information for a connection session.
Definition: Session.h:40
ripple::Session::write
void write(std::string const &s)
Send a copy of data asynchronously.
Definition: Session.h:74
ripple::forbidden
constexpr Json::Int forbidden
Definition: ServerHandlerImp.cpp:562
ripple::ServerHandlerImp::Setup::overlay_t::ip
boost::asio::ip::address ip
Definition: ServerHandlerImp.h:78
ripple::Port::port
std::uint16_t port
Definition: Port.h:51
ripple::ParsedPort
Definition: Port.h:91
ripple::ServerHandlerImp::onRequest
void onRequest(Session &session)
Definition: ServerHandlerImp.cpp:274
ripple::ServerHandlerImp::Setup::makeContexts
void makeContexts()
Definition: ServerHandlerImp.cpp:993
ripple::ServerHandlerImp::statusResponse
Handoff statusResponse(http_request_type const &request) const
Definition: ServerHandlerImp.cpp:961
ripple::Port::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:52
algorithm
ripple::isStatusRequest
static bool isStatusRequest(http_request_type const &request)
Definition: ServerHandlerImp.cpp:56
ripple::Application::getOPs
virtual NetworkOPs & getOPs()=0
ripple::ServerHandlerImp::onClose
void onClose(Session &session, boost::system::error_code const &)
Definition: ServerHandlerImp.cpp:364
ripple::ServerHandlerImp::m_networkOPs
NetworkOPs & m_networkOPs
Definition: ServerHandlerImp.h:95
ripple::Section::values
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:77
ripple::ServerHandlerImp::Setup::client_t::ip
std::string ip
Definition: ServerHandlerImp.h:62
ripple::Port::user
std::string user
Definition: Port.h:55
ripple::Port::ssl_cert
std::string ssl_cert
Definition: Port.h:60
ripple::make_SSLContextAuthed
std::shared_ptr< boost::asio::ssl::context > make_SSLContextAuthed(std::string const &keyFile, std::string const &certFile, std::string const &chainFile, std::string const &cipherList)
Create an authenticated SSL context using the specified files.
Definition: make_SSLContext.cpp:411
std::vector::push_back
T push_back(T... args)
beast::IPAddressConversion::from_asio
static IP::Endpoint from_asio(boost::asio::ip::address const &address)
Definition: IPAddressConversion.h:63
ripple::ServerHandlerImp::rpc_time_
beast::insight::Event rpc_time_
Definition: ServerHandlerImp.h:101
ripple::setup_ServerHandler
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
Definition: ServerHandlerImp.cpp:1171
stdexcept
ripple::CollectorManager::group
virtual beast::insight::Group::ptr const & group(std::string const &name)=0
beast::rfc2616::is_keep_alive
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition: rfc2616.h:386
ripple::RPC::doCommand
Status doCommand(RPC::JsonContext &context, Json::Value &result)
Execute an RPC command and store the results in a Json::Value.
Definition: RPCHandler.cpp:246
ripple::setup_Overlay
Overlay::Setup setup_Overlay(BasicConfig const &config)
Definition: OverlayImpl.cpp:1537
ripple::ServerHandlerImp::Setup::overlay_t::port
std::uint16_t port
Definition: ServerHandlerImp.h:79
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::rpcSLOW_DOWN
@ rpcSLOW_DOWN
Definition: ErrorCodes.h:57
ripple::ServerHandlerImp::mutex_
std::mutex mutex_
Definition: ServerHandlerImp.h:102
ripple::statusRequestResponse
static Handoff statusRequestResponse(http_request_type const &request, boost::beast::http::status status)
Definition: ServerHandlerImp.cpp:64
ripple::make_ServerHandler
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_service &io_service, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
Definition: ServerHandlerImp.cpp:1183
ripple::Application::serverOkay
virtual bool serverOkay(std::string &reason)=0
ripple::ServerHandlerImp::processRequest
void processRequest(Port const &port, std::string const &request, beast::IP::Endpoint const &remoteIPAddress, Output &&, std::shared_ptr< JobQueue::Coro > coro, boost::string_view forwardedFor, boost::string_view user)
Definition: ServerHandlerImp.cpp:566
ripple::InfoSub::pointer
std::shared_ptr< InfoSub > pointer
Definition: InfoSub.h:43
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::authorized
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
Definition: ServerHandlerImp.cpp:84
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::ServerHandlerImp::stopped_
bool stopped_
Definition: ServerHandlerImp.h:104
ripple::Config
Definition: Config.h:68
ripple::Port::ssl_chain
std::string ssl_chain
Definition: Port.h:61
ripple::ParsedPort::password
std::string password
Definition: Port.h:98
std::ostream
STL class.
ripple::Application::config
virtual Config & config()=0
ripple::ServerHandlerImp::condition_
std::condition_variable condition_
Definition: ServerHandlerImp.h:103
ripple::Config::standalone
bool standalone() const
Definition: Config.h:303
ripple::ServerHandlerImp::processSession
Json::Value processSession(std::shared_ptr< WSSession > const &session, std::shared_ptr< JobQueue::Coro > const &coro, Json::Value const &jv)
Definition: ServerHandlerImp.cpp:381
std::unique_lock
STL class.
ripple::RPC::Tuning::maxRequestSize
static constexpr int maxRequestSize
Definition: rpc/impl/Tuning.h:60
ripple::ParsedPort::secure_gateway_ip
std::optional< std::vector< beast::IP::Address > > secure_gateway_ip
Definition: Port.h:112
ripple::ServerHandlerImp::onAccept
bool onAccept(Session &session, boost::asio::ip::tcp::endpoint endpoint)
Definition: ServerHandlerImp.cpp:150
ripple::forwardedFor
boost::string_view forwardedFor(http_request_type const &request)
Definition: Role.cpp:126
ripple::Role::PROXY
@ PROXY
ripple::base64_decode
std::string base64_decode(std::string const &data)
Definition: base64.cpp:245
beast::Journal::error
Stream error() const
Definition: Journal.h:333
ripple::Config::BETA_RPC_API
bool BETA_RPC_API
Definition: Config.h:267
ripple::Server
A multi-protocol server.
Definition: ServerImpl.h:44
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:706
std::vector::erase
T erase(T... args)
ripple::ParsedPort::admin_user
std::string admin_user
Definition: Port.h:99
ripple::ServerHandlerImp::Setup::client
client_t client
Definition: ServerHandlerImp.h:71
ripple::Port::secure_gateway_ip
std::vector< beast::IP::Address > secure_gateway_ip
Definition: Port.h:54
ripple::Session::request
virtual http_request_type & request()=0
Returns the current HTTP request.
ripple::ServerHandlerImp::rpc_size_
beast::insight::Event rpc_size_
Definition: ServerHandlerImp.h:100
ripple::Role::FORBID
@ FORBID
beast::IP::from_asio
Endpoint from_asio(boost::asio::ip::address const &address)
Convert to Endpoint.
Definition: IPAddressConversion.cpp:26
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::requestRole
Role requestRole(Role const &required, Port const &port, Json::Value const &params, beast::IP::Endpoint const &remoteIp, boost::string_view const &user)
Return the allowed privilege role.
Definition: Role.cpp:67
std::condition_variable::wait
T wait(T... args)
ripple::Port::ssl_ciphers
std::string ssl_ciphers
Definition: Port.h:62
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:45
std::map< std::string, std::string >
ripple::Session::detach
virtual std::shared_ptr< Session > detach()=0
Detach the session.
ripple::ServerHandlerImp::app_
Application & app_
Definition: ServerHandlerImp.h:92
std::transform
T transform(T... args)
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:29
ripple::ServerHandlerImp::m_server
std::unique_ptr< Server > m_server
Definition: ServerHandlerImp.h:96
Json::Int
int Int
Definition: json_forwards.h:26
ripple::Resource::feeInvalidRPC
const Charge feeInvalidRPC
ripple::Handoff::moved
bool moved
Definition: Handoff.h:41
ripple::ServerHandlerImp::m_resourceManager
Resource::Manager & m_resourceManager
Definition: ServerHandlerImp.h:93
std::string::append
T append(T... args)
ripple::to_Port
static Port to_Port(ParsedPort const &parsed, std::ostream &log)
Definition: ServerHandlerImp.cpp:1014
ripple::StreambufWSMsg
Definition: WSSession.h:72
ripple::Port::pmd_options
boost::beast::websocket::permessage_deflate pmd_options
Definition: Port.h:63
ripple::ParsedPort::ssl_chain
std::string ssl_chain
Definition: Port.h:103
ripple::wrong_version
constexpr Json::Int wrong_version
Definition: ServerHandlerImp.cpp:563
ripple::JobQueue
A pool of threads to perform work.
Definition: JobQueue.h:55
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:130
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1015
ripple::Port::admin_password
std::string admin_password
Definition: Port.h:58
ripple::isUnlimited
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition: Role.cpp:94
std::condition_variable::notify_one
T notify_one(T... args)
ripple::Resource::Manager
Tracks load and resource consumption.
Definition: ResourceManager.h:36
std::string::substr
T substr(T... args)
ripple::BuildInfo::getFullVersionString
std::string const & getFullVersionString()
Full server version string.
Definition: BuildInfo.cpp:74
ripple::ServerHandlerImp::Setup::client_t::admin_password
std::string admin_password
Definition: ServerHandlerImp.h:67
ripple::ServerHandlerImp::onWSMessage
void onWSMessage(std::shared_ptr< WSSession > session, std::vector< boost::asio::const_buffer > const &buffers)
Definition: ServerHandlerImp.cpp:314
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::buffers_to_string
static std::string buffers_to_string(ConstBufferSequence const &bs)
Definition: ServerHandlerImp.cpp:260
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::rpcFORBIDDEN
@ rpcFORBIDDEN
Definition: ErrorCodes.h:48
ripple::ParsedPort::ip
std::optional< boost::asio::ip::address > ip
Definition: Port.h:109
ripple::Role::GUEST
@ GUEST
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
ripple::Resource::Manager::newUnlimitedEndpoint
virtual Consumer newUnlimitedEndpoint(beast::IP::Endpoint const &address)=0
Create a new unlimited endpoint keyed by forwarded IP.
ripple::ParsedPort::pmd_options
boost::beast::websocket::permessage_deflate pmd_options
Definition: Port.h:105
std::vector::begin
T begin(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
ripple::Resource::Consumer::disconnect
bool disconnect()
Returns true if the consumer should be disconnected.
Definition: Consumer.cpp:117
std::string::insert
T insert(T... args)
ripple::ParsedPort::user
std::string user
Definition: Port.h:97
ripple::Port::limit
int limit
Definition: Port.h:68
ripple::ServerHandlerImp::setup
Setup const & setup() const
Definition: ServerHandlerImp.h:124
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:74
ripple::Resource::Consumer
An endpoint that consumes resources.
Definition: Consumer.h:33
ripple::Resource::Charge
A consumption charge.
Definition: Charge.h:30
ripple::ParsedPort::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:107
ripple::setup_Client
static void setup_Client(ServerHandler::Setup &setup)
Definition: ServerHandlerImp.cpp:1131
ripple::Port::password
std::string password
Definition: Port.h:56
Json::Reader::getFormatedErrorMessages
std::string getFormatedErrorMessages() const
Returns a user friendly string that list errors in the parsed document.
Definition: json_reader.cpp:931
ripple::Application::overlay
virtual Overlay & overlay()=0
std::set::count
T count(T... args)
ripple::ServerHandlerImp::Setup::ports
std::vector< Port > ports
Definition: ServerHandlerImp.h:54
ripple::Session::port
virtual Port const & port()=0
Returns the Port settings for this connection.
std::string::empty
T empty(T... args)
ripple::Session::close
virtual void close(bool graceful)=0
Close the session.
ripple::Handoff
Used to indicate the result of a server connection handoff.
Definition: Handoff.h:37
ripple::systemName
static std::string const & systemName()
Definition: SystemParameters.h:34
mutex
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:38
ripple::ServerHandlerImp::~ServerHandlerImp
~ServerHandlerImp()
Definition: ServerHandlerImp.cpp:123
beast::IP::Endpoint
A version-independent IP address and port combination.
Definition: IPEndpoint.h:38
std::map::end
T end(T... args)
ripple::Handoff::response
std::shared_ptr< Writer > response
Definition: Handoff.h:47
ripple::build_map
static std::map< std::string, std::string > build_map(boost::beast::http::fields const &h)
Definition: ServerHandlerImp.cpp:244
ripple::ParsedPort::protocol
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:96
ripple::ParsedPort::name
std::string name
Definition: Port.h:95
ripple::Resource::Consumer::charge
Disposition charge(Charge const &fee)
Apply a load charge to the consumer.
Definition: Consumer.cpp:99
ripple::ServerHandlerImp::Setup::overlay
overlay_t overlay
Definition: ServerHandlerImp.h:82
ripple::ServerHandlerImp::Setup::client_t::password
std::string password
Definition: ServerHandlerImp.h:65
beast::IP::is_unspecified
bool is_unspecified(Address const &addr)
Returns true if the address is unspecified.
Definition: IPAddress.h:59
ripple::http_request_type
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition: Handshake.h:47
std::unique_ptr< stream_type >
ripple::ServerHandlerImp::onStopped
void onStopped(Server &)
Definition: ServerHandlerImp.cpp:371
ripple::ParsedPort::admin_password
std::string admin_password
Definition: Port.h:100
ripple::ParsedPort::ssl_cert
std::string ssl_cert
Definition: Port.h:102
Json::Value::isObjectOrNull
bool isObjectOrNull() const
Definition: json_value.cpp:1033
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:209
std::exception::what
T what(T... args)
ripple::ServerHandlerImp::onHandoff
Handoff onHandoff(Session &session, std::unique_ptr< stream_type > &&bundle, http_request_type &&request, boost::asio::ip::tcp::endpoint const &remote_address)
Definition: ServerHandlerImp.cpp:172
ripple::BasicConfig::exists
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Definition: BasicConfig.cpp:121
Json::Value
Represents a JSON value.
Definition: json_value.h:145
beast::insight::Event::notify
void notify(std::chrono::duration< Rep, Period > const &value) const
Push an event notification.
Definition: Event.h:64
ripple::parse_Ports
static std::vector< Port > parse_Ports(Config const &config, std::ostream &log)
Definition: ServerHandlerImp.cpp:1065
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:127
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
std::chrono::high_resolution_clock::now
T now(T... args)