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