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/regex.hpp>
49 #include <boost/type_traits.hpp>
50 #include <algorithm>
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  Stoppable& parent,
106  boost::asio::io_service& io_service,
107  JobQueue& jobQueue,
108  NetworkOPs& networkOPs,
109  Resource::Manager& resourceManager,
110  CollectorManager& cm)
111  : Stoppable("ServerHandler", parent)
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 
145 //------------------------------------------------------------------------------
146 
147 bool
149  Session& session,
150  boost::asio::ip::tcp::endpoint endpoint)
151 {
153 
154  auto const c = ++count_[session.port()];
155 
156  if (session.port().limit && c >= session.port().limit)
157  {
158  JLOG(m_journal.trace())
159  << session.port().name << " is full; dropping " << endpoint;
160  return false;
161  }
162 
163  return true;
164 }
165 
166 Handoff
168  Session& session,
170  http_request_type&& request,
171  boost::asio::ip::tcp::endpoint const& remote_address)
172 {
173  using namespace boost::beast;
174  auto const& p{session.port().protocol};
175  bool const is_ws{
176  p.count("ws") > 0 || p.count("ws2") > 0 || p.count("wss") > 0 ||
177  p.count("wss2") > 0};
178 
179  if (websocket::is_upgrade(request))
180  {
181  if (!is_ws)
182  return statusRequestResponse(request, http::status::unauthorized);
183 
185  try
186  {
187  ws = session.websocketUpgrade();
188  }
189  catch (std::exception const& e)
190  {
191  JLOG(m_journal.error())
192  << "Exception upgrading websocket: " << e.what() << "\n";
193  return statusRequestResponse(
194  request, http::status::internal_server_error);
195  }
196 
197  auto is{std::make_shared<WSInfoSub>(m_networkOPs, ws)};
198  auto const beast_remote_address =
200  is->getConsumer() = requestInboundEndpoint(
202  beast_remote_address,
203  requestRole(
204  Role::GUEST,
205  session.port(),
206  Json::Value(),
207  beast_remote_address,
208  is->user()),
209  is->user(),
210  is->forwarded_for());
211  ws->appDefined = std::move(is);
212  ws->run();
213 
214  Handoff handoff;
215  handoff.moved = true;
216  return handoff;
217  }
218 
219  if (bundle && p.count("peer") > 0)
220  return app_.overlay().onHandoff(
221  std::move(bundle), std::move(request), remote_address);
222 
223  if (is_ws && isStatusRequest(request))
224  return statusResponse(request);
225 
226  // Otherwise pass to legacy onRequest or websocket
227  return {};
228 }
229 
230 static inline Json::Output
232 {
233  return [&](boost::beast::string_view const& b) {
234  session.write(b.data(), b.size());
235  };
236 }
237 
239 build_map(boost::beast::http::fields const& h)
240 {
242  for (auto const& e : h)
243  {
244  auto key(e.name_string().to_string());
245  std::transform(key.begin(), key.end(), key.begin(), [](auto kc) {
246  return std::tolower(static_cast<unsigned char>(kc));
247  });
248  c[key] = e.value().to_string();
249  }
250  return c;
251 }
252 
253 template <class ConstBufferSequence>
254 static std::string
255 buffers_to_string(ConstBufferSequence const& bs)
256 {
257  using boost::asio::buffer_cast;
258  using boost::asio::buffer_size;
259  std::string s;
260  s.reserve(buffer_size(bs));
261  for (auto const& b : bs)
262  s.append(buffer_cast<char const*>(b), buffer_size(b));
263  return s;
264 }
265 
266 void
268 {
269  // Make sure RPC is enabled on the port
270  if (session.port().protocol.count("http") == 0 &&
271  session.port().protocol.count("https") == 0)
272  {
273  HTTPReply(403, "Forbidden", makeOutput(session), app_.journal("RPC"));
274  session.close(true);
275  return;
276  }
277 
278  // Check user/password authorization
279  if (!authorized(session.port(), build_map(session.request())))
280  {
281  HTTPReply(403, "Forbidden", makeOutput(session), app_.journal("RPC"));
282  session.close(true);
283  return;
284  }
285 
286  std::shared_ptr<Session> detachedSession = session.detach();
287  auto const postResult = m_jobQueue.postCoro(
288  jtCLIENT,
289  "RPC-Client",
290  [this, detachedSession](std::shared_ptr<JobQueue::Coro> coro) {
291  processSession(detachedSession, coro);
292  });
293  if (postResult == nullptr)
294  {
295  // The coroutine was rejected, probably because we're shutting down.
296  HTTPReply(
297  503,
298  "Service Unavailable",
299  makeOutput(*detachedSession),
300  app_.journal("RPC"));
301  detachedSession->close(true);
302  return;
303  }
304 }
305 
306 void
310 {
311  Json::Value jv;
312  auto const size = boost::asio::buffer_size(buffers);
313  if (size > RPC::Tuning::maxRequestSize ||
314  !Json::Reader{}.parse(jv, buffers) || !jv.isObject())
315  {
316  Json::Value jvResult(Json::objectValue);
317  jvResult[jss::type] = jss::error;
318  jvResult[jss::error] = "jsonInvalid";
319  jvResult[jss::value] = buffers_to_string(buffers);
320  boost::beast::multi_buffer sb;
321  Json::stream(jvResult, [&sb](auto const p, auto const n) {
322  sb.commit(boost::asio::buffer_copy(
323  sb.prepare(n), boost::asio::buffer(p, n)));
324  });
325  JLOG(m_journal.trace()) << "Websocket sending '" << jvResult << "'";
326  session->send(
327  std::make_shared<StreambufWSMsg<decltype(sb)>>(std::move(sb)));
328  session->complete();
329  return;
330  }
331 
332  JLOG(m_journal.trace()) << "Websocket received '" << jv << "'";
333 
334  auto const postResult = m_jobQueue.postCoro(
335  jtCLIENT,
336  "WS-Client",
337  [this, session, jv = std::move(jv)](
338  std::shared_ptr<JobQueue::Coro> const& coro) {
339  auto const jr = this->processSession(session, coro, jv);
340  auto const s = to_string(jr);
341  auto const n = s.length();
342  boost::beast::multi_buffer sb(n);
343  sb.commit(boost::asio::buffer_copy(
344  sb.prepare(n), boost::asio::buffer(s.c_str(), n)));
345  session->send(
346  std::make_shared<StreambufWSMsg<decltype(sb)>>(std::move(sb)));
347  session->complete();
348  });
349  if (postResult == nullptr)
350  {
351  // The coroutine was rejected, probably because we're shutting down.
352  session->close({boost::beast::websocket::going_away, "Shutting Down"});
353  }
354 }
355 
356 void
357 ServerHandlerImp::onClose(Session& session, boost::system::error_code const&)
358 {
360  --count_[session.port()];
361 }
362 
363 void
365 {
366  stopped();
367 }
368 
369 //------------------------------------------------------------------------------
370 
373  std::shared_ptr<WSSession> const& session,
375  Json::Value const& jv)
376 {
377  auto is = std::static_pointer_cast<WSInfoSub>(session->appDefined);
378  if (is->getConsumer().disconnect())
379  {
380  session->close(
381  {boost::beast::websocket::policy_error, "threshold exceeded"});
382  // FIX: This rpcError is not delivered since the session
383  // was just closed.
384  return rpcError(rpcSLOW_DOWN);
385  }
386 
387  // Requests without "command" are invalid.
390  try
391  {
392  auto apiVersion = RPC::getAPIVersionNumber(jv);
393  if (apiVersion == RPC::APIInvalidVersion ||
394  (!jv.isMember(jss::command) && !jv.isMember(jss::method)) ||
395  (jv.isMember(jss::command) && !jv[jss::command].isString()) ||
396  (jv.isMember(jss::method) && !jv[jss::method].isString()) ||
397  (jv.isMember(jss::command) && jv.isMember(jss::method) &&
398  jv[jss::command].asString() != jv[jss::method].asString()))
399  {
400  jr[jss::type] = jss::response;
401  jr[jss::status] = jss::error;
402  jr[jss::error] = apiVersion == RPC::APIInvalidVersion
403  ? jss::invalid_API_version
404  : jss::missingCommand;
405  jr[jss::request] = jv;
406  if (jv.isMember(jss::id))
407  jr[jss::id] = jv[jss::id];
408  if (jv.isMember(jss::jsonrpc))
409  jr[jss::jsonrpc] = jv[jss::jsonrpc];
410  if (jv.isMember(jss::ripplerpc))
411  jr[jss::ripplerpc] = jv[jss::ripplerpc];
412  if (jv.isMember(jss::api_version))
413  jr[jss::api_version] = jv[jss::api_version];
414 
415  is->getConsumer().charge(Resource::feeInvalidRPC);
416  return jr;
417  }
418 
419  auto required = RPC::roleRequired(
420  apiVersion,
421  jv.isMember(jss::command) ? jv[jss::command].asString()
422  : jv[jss::method].asString());
423  auto role = requestRole(
424  required,
425  session->port(),
426  jv,
427  beast::IP::from_asio(session->remote_endpoint().address()),
428  is->user());
429  if (Role::FORBID == role)
430  {
431  loadType = Resource::feeInvalidRPC;
432  jr[jss::result] = rpcError(rpcFORBIDDEN);
433  }
434  else
435  {
436  RPC::JsonContext context{
437  {app_.journal("RPCHandler"),
438  app_,
439  loadType,
440  app_.getOPs(),
442  is->getConsumer(),
443  role,
444  coro,
445  is,
446  apiVersion},
447  jv,
448  {is->user(), is->forwarded_for()}};
449 
450  RPC::doCommand(context, jr[jss::result]);
451  }
452  }
453  catch (std::exception const& ex)
454  {
455  jr[jss::result] = RPC::make_error(rpcINTERNAL);
456  JLOG(m_journal.error())
457  << "Exception while processing WS: " << ex.what() << "\n"
458  << "Input JSON: " << Json::Compact{Json::Value{jv}};
459  }
460 
461  is->getConsumer().charge(loadType);
462  if (is->getConsumer().warn())
463  jr[jss::warning] = jss::load;
464 
465  // Currently we will simply unwrap errors returned by the RPC
466  // API, in the future maybe we can make the responses
467  // consistent.
468  //
469  // Regularize result. This is duplicate code.
470  if (jr[jss::result].isMember(jss::error))
471  {
472  jr = jr[jss::result];
473  jr[jss::status] = jss::error;
474 
475  auto rq = jv;
476 
477  if (rq.isObject())
478  {
479  if (rq.isMember(jss::passphrase.c_str()))
480  rq[jss::passphrase.c_str()] = "<masked>";
481  if (rq.isMember(jss::secret.c_str()))
482  rq[jss::secret.c_str()] = "<masked>";
483  if (rq.isMember(jss::seed.c_str()))
484  rq[jss::seed.c_str()] = "<masked>";
485  if (rq.isMember(jss::seed_hex.c_str()))
486  rq[jss::seed_hex.c_str()] = "<masked>";
487  }
488 
489  jr[jss::request] = rq;
490  }
491  else
492  {
493  if (jr[jss::result].isMember("forwarded") &&
494  jr[jss::result]["forwarded"])
495  jr = jr[jss::result];
496  jr[jss::status] = jss::success;
497  }
498 
499  if (jv.isMember(jss::id))
500  jr[jss::id] = jv[jss::id];
501  if (jv.isMember(jss::jsonrpc))
502  jr[jss::jsonrpc] = jv[jss::jsonrpc];
503  if (jv.isMember(jss::ripplerpc))
504  jr[jss::ripplerpc] = jv[jss::ripplerpc];
505  if (jv.isMember(jss::api_version))
506  jr[jss::api_version] = jv[jss::api_version];
507 
508  jr[jss::type] = jss::response;
509  return jr;
510 }
511 
512 // Run as a coroutine.
513 void
515  std::shared_ptr<Session> const& session,
517 {
519  session->port(),
520  buffers_to_string(session->request().body().data()),
521  session->remoteAddress().at_port(0),
522  makeOutput(*session),
523  coro,
524  forwardedFor(session->request()),
525  [&] {
526  auto const iter = session->request().find("X-User");
527  if (iter != session->request().end())
528  return iter->value();
529  return boost::beast::string_view{};
530  }());
531 
532  if (beast::rfc2616::is_keep_alive(session->request()))
533  session->complete();
534  else
535  session->close(true);
536 }
537 
538 static Json::Value
540 {
542  sub["code"] = code;
543  sub["message"] = std::move(message);
545  r["error"] = sub;
546  return r;
547 }
548 
549 Json::Int constexpr method_not_found = -32601;
550 Json::Int constexpr server_overloaded = -32604;
551 Json::Int constexpr forbidden = -32605;
552 Json::Int constexpr wrong_version = -32606;
553 
554 void
556  Port const& port,
557  std::string const& request,
558  beast::IP::Endpoint const& remoteIPAddress,
559  Output&& output,
561  boost::string_view forwardedFor,
562  boost::string_view user)
563 {
564  auto rpcJ = app_.journal("RPC");
565 
566  Json::Value jsonOrig;
567  {
568  Json::Reader reader;
569  if ((request.size() > RPC::Tuning::maxRequestSize) ||
570  !reader.parse(request, jsonOrig) || !jsonOrig ||
571  !jsonOrig.isObject())
572  {
573  HTTPReply(
574  400,
575  "Unable to parse request: " + reader.getFormatedErrorMessages(),
576  output,
577  rpcJ);
578  return;
579  }
580  }
581 
582  bool batch = false;
583  unsigned size = 1;
584  if (jsonOrig.isMember(jss::method) && jsonOrig[jss::method] == "batch")
585  {
586  batch = true;
587  if (!jsonOrig.isMember(jss::params) || !jsonOrig[jss::params].isArray())
588  {
589  HTTPReply(400, "Malformed batch request", output, rpcJ);
590  return;
591  }
592  size = jsonOrig[jss::params].size();
593  }
594 
596  auto const start(std::chrono::high_resolution_clock::now());
597  for (unsigned i = 0; i < size; ++i)
598  {
599  Json::Value const& jsonRPC =
600  batch ? jsonOrig[jss::params][i] : jsonOrig;
601 
602  if (!jsonRPC.isObject())
603  {
605  r[jss::request] = jsonRPC;
606  r[jss::error] =
607  make_json_error(method_not_found, "Method not found");
608  reply.append(r);
609  continue;
610  }
611 
612  auto apiVersion = RPC::APIVersionIfUnspecified;
613  if (jsonRPC.isMember(jss::params) && jsonRPC[jss::params].isArray() &&
614  jsonRPC[jss::params].size() > 0 &&
615  jsonRPC[jss::params][0u].isObject())
616  {
617  apiVersion =
618  RPC::getAPIVersionNumber(jsonRPC[jss::params][Json::UInt(0)]);
619  }
620 
621  if (apiVersion == RPC::APIVersionIfUnspecified && batch)
622  {
623  // for batch request, api_version may be at a different level
624  apiVersion = RPC::getAPIVersionNumber(jsonRPC);
625  }
626 
627  if (apiVersion == RPC::APIInvalidVersion)
628  {
629  if (!batch)
630  {
631  HTTPReply(400, jss::invalid_API_version.c_str(), output, rpcJ);
632  return;
633  }
635  r[jss::request] = jsonRPC;
636  r[jss::error] = make_json_error(
637  wrong_version, jss::invalid_API_version.c_str());
638  reply.append(r);
639  continue;
640  }
641 
642  /* ------------------------------------------------------------------ */
643  auto role = Role::FORBID;
644  auto required = Role::FORBID;
645  if (jsonRPC.isMember(jss::method) && jsonRPC[jss::method].isString())
646  required =
647  RPC::roleRequired(apiVersion, jsonRPC[jss::method].asString());
648 
649  if (jsonRPC.isMember(jss::params) && jsonRPC[jss::params].isArray() &&
650  jsonRPC[jss::params].size() > 0 &&
651  jsonRPC[jss::params][Json::UInt(0)].isObjectOrNull())
652  {
653  role = requestRole(
654  required,
655  port,
656  jsonRPC[jss::params][Json::UInt(0)],
657  remoteIPAddress,
658  user);
659  }
660  else
661  {
662  role = requestRole(
663  required, port, Json::objectValue, remoteIPAddress, user);
664  }
665 
666  Resource::Consumer usage;
667  if (isUnlimited(role))
668  {
669  usage = m_resourceManager.newUnlimitedEndpoint(remoteIPAddress);
670  }
671  else
672  {
674  remoteIPAddress, role == Role::PROXY, forwardedFor);
675  if (usage.disconnect())
676  {
677  if (!batch)
678  {
679  HTTPReply(503, "Server is overloaded", output, rpcJ);
680  return;
681  }
682  Json::Value r = jsonRPC;
683  r[jss::error] =
684  make_json_error(server_overloaded, "Server is overloaded");
685  reply.append(r);
686  continue;
687  }
688  }
689 
690  if (role == Role::FORBID)
691  {
693  if (!batch)
694  {
695  HTTPReply(403, "Forbidden", output, rpcJ);
696  return;
697  }
698  Json::Value r = jsonRPC;
699  r[jss::error] = make_json_error(forbidden, "Forbidden");
700  reply.append(r);
701  continue;
702  }
703 
704  if (!jsonRPC.isMember(jss::method) || jsonRPC[jss::method].isNull())
705  {
707  if (!batch)
708  {
709  HTTPReply(400, "Null method", output, rpcJ);
710  return;
711  }
712  Json::Value r = jsonRPC;
713  r[jss::error] = make_json_error(method_not_found, "Null method");
714  reply.append(r);
715  continue;
716  }
717 
718  Json::Value const& method = jsonRPC[jss::method];
719  if (!method.isString())
720  {
722  if (!batch)
723  {
724  HTTPReply(400, "method is not string", output, rpcJ);
725  return;
726  }
727  Json::Value r = jsonRPC;
728  r[jss::error] =
729  make_json_error(method_not_found, "method is not string");
730  reply.append(r);
731  continue;
732  }
733 
734  std::string strMethod = method.asString();
735  if (strMethod.empty())
736  {
738  if (!batch)
739  {
740  HTTPReply(400, "method is empty", output, rpcJ);
741  return;
742  }
743  Json::Value r = jsonRPC;
744  r[jss::error] =
745  make_json_error(method_not_found, "method is empty");
746  reply.append(r);
747  continue;
748  }
749 
750  // Extract request parameters from the request Json as `params`.
751  //
752  // If the field "params" is empty, `params` is an empty object.
753  //
754  // Otherwise, that field must be an array of length 1 (why?)
755  // and we take that first entry and validate that it's an object.
756  Json::Value params;
757  if (!batch)
758  {
759  params = jsonRPC[jss::params];
760  if (!params)
761  params = Json::Value(Json::objectValue);
762 
763  else if (!params.isArray() || params.size() != 1)
764  {
766  HTTPReply(400, "params unparseable", output, rpcJ);
767  return;
768  }
769  else
770  {
771  params = std::move(params[0u]);
772  if (!params.isObjectOrNull())
773  {
775  HTTPReply(400, "params unparseable", output, rpcJ);
776  return;
777  }
778  }
779  }
780  else // batch
781  {
782  params = jsonRPC;
783  }
784 
785  std::string ripplerpc = "1.0";
786  if (params.isMember(jss::ripplerpc))
787  {
788  if (!params[jss::ripplerpc].isString())
789  {
791  if (!batch)
792  {
793  HTTPReply(400, "ripplerpc is not a string", output, rpcJ);
794  return;
795  }
796 
797  Json::Value r = jsonRPC;
798  r[jss::error] = make_json_error(
799  method_not_found, "ripplerpc is not a string");
800  reply.append(r);
801  continue;
802  }
803  ripplerpc = params[jss::ripplerpc].asString();
804  }
805 
810  if (role != Role::IDENTIFIED && role != Role::PROXY)
811  {
812  forwardedFor.clear();
813  user.clear();
814  }
815 
816  JLOG(m_journal.debug()) << "Query: " << strMethod << params;
817 
818  // Provide the JSON-RPC method as the field "command" in the request.
819  params[jss::command] = strMethod;
820  JLOG(m_journal.trace())
821  << "doRpcCommand:" << strMethod << ":" << params;
822 
824 
825  RPC::JsonContext context{
826  {m_journal,
827  app_,
828  loadType,
829  m_networkOPs,
831  usage,
832  role,
833  coro,
835  apiVersion},
836  params,
837  {user, forwardedFor}};
838  Json::Value result;
839  RPC::doCommand(context, result);
840  usage.charge(loadType);
841  if (usage.warn())
842  result[jss::warning] = jss::load;
843 
845  if (ripplerpc >= "2.0")
846  {
847  if (result.isMember(jss::error))
848  {
849  result[jss::status] = jss::error;
850  result["code"] = result[jss::error_code];
851  result["message"] = result[jss::error_message];
852  result.removeMember(jss::error_message);
853  JLOG(m_journal.debug()) << "rpcError: " << result[jss::error]
854  << ": " << result[jss::error_message];
855  r[jss::error] = std::move(result);
856  }
857  else
858  {
859  result[jss::status] = jss::success;
860  r[jss::result] = std::move(result);
861  }
862  }
863  else
864  {
865  // Always report "status". On an error report the request as
866  // received.
867  if (result.isMember(jss::error))
868  {
869  auto rq = params;
870 
871  if (rq.isObject())
872  { // But mask potentially sensitive information.
873  if (rq.isMember(jss::passphrase.c_str()))
874  rq[jss::passphrase.c_str()] = "<masked>";
875  if (rq.isMember(jss::secret.c_str()))
876  rq[jss::secret.c_str()] = "<masked>";
877  if (rq.isMember(jss::seed.c_str()))
878  rq[jss::seed.c_str()] = "<masked>";
879  if (rq.isMember(jss::seed_hex.c_str()))
880  rq[jss::seed_hex.c_str()] = "<masked>";
881  }
882 
883  result[jss::status] = jss::error;
884  result[jss::request] = rq;
885 
886  JLOG(m_journal.debug()) << "rpcError: " << result[jss::error]
887  << ": " << result[jss::error_message];
888  }
889  else
890  {
891  result[jss::status] = jss::success;
892  }
893  r[jss::result] = std::move(result);
894  }
895 
896  if (params.isMember(jss::jsonrpc))
897  r[jss::jsonrpc] = params[jss::jsonrpc];
898  if (params.isMember(jss::ripplerpc))
899  r[jss::ripplerpc] = params[jss::ripplerpc];
900  if (params.isMember(jss::id))
901  r[jss::id] = params[jss::id];
902  if (batch)
903  reply.append(std::move(r));
904  else
905  reply = std::move(r);
906  }
907  auto response = to_string(reply);
908 
909  rpc_time_.notify(std::chrono::duration_cast<std::chrono::milliseconds>(
911  ++rpc_requests_;
913 
914  response += '\n';
915 
916  if (auto stream = m_journal.debug())
917  {
918  static const int maxSize = 10000;
919  if (response.size() <= maxSize)
920  stream << "Reply: " << response;
921  else
922  stream << "Reply: " << response.substr(0, maxSize);
923  }
924 
925  HTTPReply(200, response, output, rpcJ);
926 }
927 
928 //------------------------------------------------------------------------------
929 
930 /* This response is used with load balancing.
931  If the server is overloaded, status 500 is reported. Otherwise status 200
932  is reported, meaning the server can accept more connections.
933 */
934 Handoff
936 {
937  using namespace boost::beast::http;
938  Handoff handoff;
939  response<string_body> msg;
940  std::string reason;
941  if (app_.serverOkay(reason))
942  {
943  msg.result(boost::beast::http::status::ok);
944  msg.body() = "<!DOCTYPE html><html><head><title>" + systemName() +
945  " Test page for rippled</title></head><body><h1>" + systemName() +
946  " Test</h1><p>This page shows rippled http(s) "
947  "connectivity is working.</p></body></html>";
948  }
949  else
950  {
951  msg.result(boost::beast::http::status::internal_server_error);
952  msg.body() = "<HTML><BODY>Server cannot accept clients: " + reason +
953  "</BODY></HTML>";
954  }
955  msg.version(request.version());
956  msg.insert("Server", BuildInfo::getFullVersionString());
957  msg.insert("Content-Type", "text/html");
958  msg.insert("Connection", "close");
959  msg.prepare_payload();
960  handoff.response = std::make_shared<SimpleWriter>(msg);
961  return handoff;
962 }
963 
964 //------------------------------------------------------------------------------
965 
966 void
968 {
969  for (auto& p : ports)
970  {
971  if (p.secure())
972  {
973  if (p.ssl_key.empty() && p.ssl_cert.empty() && p.ssl_chain.empty())
974  p.context = make_SSLContext(p.ssl_ciphers);
975  else
976  p.context = make_SSLContextAuthed(
977  p.ssl_key, p.ssl_cert, p.ssl_chain, p.ssl_ciphers);
978  }
979  else
980  {
981  p.context = std::make_shared<boost::asio::ssl::context>(
982  boost::asio::ssl::context::sslv23);
983  }
984  }
985 }
986 
987 static Port
988 to_Port(ParsedPort const& parsed, std::ostream& log)
989 {
990  Port p;
991  p.name = parsed.name;
992 
993  if (!parsed.ip)
994  {
995  log << "Missing 'ip' in [" << p.name << "]";
996  Throw<std::exception>();
997  }
998  p.ip = *parsed.ip;
999 
1000  if (!parsed.port)
1001  {
1002  log << "Missing 'port' in [" << p.name << "]";
1003  Throw<std::exception>();
1004  }
1005  else if (*parsed.port == 0)
1006  {
1007  log << "Port " << *parsed.port << "in [" << p.name << "] is invalid";
1008  Throw<std::exception>();
1009  }
1010  p.port = *parsed.port;
1011  if (parsed.admin_ip)
1012  p.admin_ip = *parsed.admin_ip;
1013  if (parsed.secure_gateway_ip)
1015 
1016  if (parsed.protocol.empty())
1017  {
1018  log << "Missing 'protocol' in [" << p.name << "]";
1019  Throw<std::exception>();
1020  }
1021  p.protocol = parsed.protocol;
1022 
1023  p.user = parsed.user;
1024  p.password = parsed.password;
1025  p.admin_user = parsed.admin_user;
1026  p.admin_password = parsed.admin_password;
1027  p.ssl_key = parsed.ssl_key;
1028  p.ssl_cert = parsed.ssl_cert;
1029  p.ssl_chain = parsed.ssl_chain;
1030  p.ssl_ciphers = parsed.ssl_ciphers;
1031  p.pmd_options = parsed.pmd_options;
1032  p.ws_queue_limit = parsed.ws_queue_limit;
1033  p.limit = parsed.limit;
1034 
1035  return p;
1036 }
1037 
1038 static std::vector<Port>
1039 parse_Ports(Config const& config, std::ostream& log)
1040 {
1041  std::vector<Port> result;
1042 
1043  if (!config.exists("server"))
1044  {
1045  log << "Required section [server] is missing";
1046  Throw<std::exception>();
1047  }
1048 
1049  ParsedPort common;
1050  parse_Port(common, config["server"], log);
1051 
1052  auto const& names = config.section("server").values();
1053  result.reserve(names.size());
1054  for (auto const& name : names)
1055  {
1056  if (!config.exists(name))
1057  {
1058  log << "Missing section: [" << name << "]";
1059  Throw<std::exception>();
1060  }
1061  ParsedPort parsed = common;
1062  parsed.name = name;
1063  parse_Port(parsed, config[name], log);
1064  result.push_back(to_Port(parsed, log));
1065  }
1066 
1067  if (config.standalone())
1068  {
1069  auto it = result.begin();
1070 
1071  while (it != result.end())
1072  {
1073  auto& p = it->protocol;
1074 
1075  // Remove the peer protocol, and if that would
1076  // leave the port empty, remove the port as well
1077  if (p.erase("peer") && p.empty())
1078  it = result.erase(it);
1079  else
1080  ++it;
1081  }
1082  }
1083  else
1084  {
1085  auto const count =
1086  std::count_if(result.cbegin(), result.cend(), [](Port const& p) {
1087  return p.protocol.count("peer") != 0;
1088  });
1089 
1090  if (count > 1)
1091  {
1092  log << "Error: More than one peer protocol configured in [server]";
1093  Throw<std::exception>();
1094  }
1095 
1096  if (count == 0)
1097  log << "Warning: No peer protocol configured";
1098  }
1099 
1100  return result;
1101 }
1102 
1103 // Fill out the client portion of the Setup
1104 static void
1106 {
1107  decltype(setup.ports)::const_iterator iter;
1108  for (iter = setup.ports.cbegin(); iter != setup.ports.cend(); ++iter)
1109  if (iter->protocol.count("http") > 0 ||
1110  iter->protocol.count("https") > 0)
1111  break;
1112  if (iter == setup.ports.cend())
1113  return;
1114  setup.client.secure = iter->protocol.count("https") > 0;
1116  ?
1117  // VFALCO HACK! to make localhost work
1118  (iter->ip.is_v6() ? "::1" : "127.0.0.1")
1119  : iter->ip.to_string();
1120  setup.client.port = iter->port;
1121  setup.client.user = iter->user;
1122  setup.client.password = iter->password;
1123  setup.client.admin_user = iter->admin_user;
1124  setup.client.admin_password = iter->admin_password;
1125 }
1126 
1127 // Fill out the overlay portion of the Setup
1128 static void
1130 {
1131  auto const iter = std::find_if(
1132  setup.ports.cbegin(), setup.ports.cend(), [](Port const& port) {
1133  return port.protocol.count("peer") != 0;
1134  });
1135  if (iter == setup.ports.cend())
1136  {
1137  setup.overlay.port = 0;
1138  return;
1139  }
1140  setup.overlay.ip = iter->ip;
1141  setup.overlay.port = iter->port;
1142 }
1143 
1144 ServerHandler::Setup
1146 {
1148  setup.ports = parse_Ports(config, log);
1149 
1152 
1153  return setup;
1154 }
1155 
1158  Application& app,
1159  Stoppable& parent,
1160  boost::asio::io_service& io_service,
1161  JobQueue& jobQueue,
1162  NetworkOPs& networkOPs,
1163  Resource::Manager& resourceManager,
1164  CollectorManager& cm)
1165 {
1166  return std::make_unique<ServerHandlerImp>(
1167  app, parent, io_service, jobQueue, networkOPs, resourceManager, cm);
1168 }
1169 
1170 } // 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:87
ripple::Port::ws_queue_limit
std::uint16_t ws_queue_limit
Definition: Port.h:71
ripple::Application
Definition: Application.h:102
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:102
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:63
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:93
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::makeOutput
static Json::Output makeOutput(Session &session)
Definition: ServerHandlerImp.cpp:231
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:427
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1009
ripple::jtCLIENT
@ jtCLIENT
Definition: Job.h:50
std::exception
STL class.
ripple::Stoppable::stopped
void stopped()
Called by derived classes to indicate that the stoppable has stopped.
Definition: Stoppable.cpp:72
ripple::ServerHandlerImp::m_jobQueue
JobQueue & m_jobQueue
Definition: ServerHandlerImp.h:97
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:96
Json::stream
void stream(Json::Value const &jv, Write const &write)
Stream compact JSON to the specified function.
Definition: json_writer.h:300
ripple::RPC::getAPIVersionNumber
unsigned int getAPIVersionNumber(Json::Value const &jv)
Retrieve the api version number from the json value.
Definition: RPCHelpers.cpp:887
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:539
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:60
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
std::vector
STL class.
ripple::ServerHandlerImp::Setup::client_t::admin_user
std::string admin_user
Definition: ServerHandlerImp.h:65
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::Setup
Definition: ServerHandlerImp.h:49
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:450
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:549
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:550
ripple::Resource::feeReferenceRPC
const Charge feeReferenceRPC
ripple::Role::IDENTIFIED
@ IDENTIFIED
ripple::RPC::APIVersionIfUnspecified
constexpr unsigned int APIVersionIfUnspecified
Definition: RPCHelpers.h:218
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:98
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:62
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:551
ripple::ServerHandlerImp::Setup::overlay_t::ip
boost::asio::ip::address ip
Definition: ServerHandlerImp.h:77
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:267
ripple::ServerHandlerImp::Setup::makeContexts
void makeContexts()
Definition: ServerHandlerImp.cpp:967
ripple::ServerHandlerImp::statusResponse
Handoff statusResponse(http_request_type const &request) const
Definition: ServerHandlerImp.cpp:935
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:357
ripple::ServerHandlerImp::m_networkOPs
NetworkOPs & m_networkOPs
Definition: ServerHandlerImp.h:94
ripple::Section::values
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:76
ripple::ServerHandlerImp::Setup::client_t::ip
std::string ip
Definition: ServerHandlerImp.h:61
ripple::Port::user
std::string user
Definition: Port.h:55
ripple::Port::ssl_cert
std::string ssl_cert
Definition: Port.h:60
ripple::ServerHandlerImp::ServerHandlerImp
ServerHandlerImp(Application &app, Stoppable &parent, boost::asio::io_service &io_service, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
Definition: ServerHandlerImp.cpp:103
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:461
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:100
ripple::setup_ServerHandler
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
Definition: ServerHandlerImp.cpp:1145
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:245
ripple::setup_Overlay
Overlay::Setup setup_Overlay(BasicConfig const &config)
Definition: OverlayImpl.cpp:1463
ripple::ServerHandlerImp::Setup::overlay_t::port
std::uint16_t port
Definition: ServerHandlerImp.h:78
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::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:201
ripple::statusRequestResponse
static Handoff statusRequestResponse(http_request_type const &request, boost::beast::http::status status)
Definition: ServerHandlerImp.cpp:64
ripple::Application::serverOkay
virtual bool serverOkay(std::string &reason)=0
ripple::ServerHandlerImp::onStop
void onStop() override
Override called when the stop notification is issued.
Definition: ServerHandlerImp.cpp:140
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:555
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::Config
Definition: Config.h:67
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::Config::standalone
bool standalone() const
Definition: Config.h:265
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:372
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:148
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::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:70
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:99
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
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
STL class.
ripple::Session::detach
virtual std::shared_ptr< Session > detach()=0
Detach the session.
ripple::ServerHandlerImp::app_
Application & app_
Definition: ServerHandlerImp.h:91
std::transform
T transform(T... args)
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:29
ripple::RPC::APIInvalidVersion
constexpr unsigned int APIInvalidVersion
API version numbers used in later API versions.
Definition: RPCHelpers.h:217
ripple::ServerHandlerImp::m_server
std::unique_ptr< Server > m_server
Definition: ServerHandlerImp.h:95
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:92
std::string::append
T append(T... args)
ripple::to_Port
static Port to_Port(ParsedPort const &parsed, std::ostream &log)
Definition: ServerHandlerImp.cpp:988
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:552
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
ripple::RPC::roleRequired
Role roleRequired(unsigned int version, std::string const &method)
Definition: RPCHandler.cpp:292
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:66
ripple::ServerHandlerImp::onWSMessage
void onWSMessage(std::shared_ptr< WSSession > session, std::vector< boost::asio::const_buffer > const &buffers)
Definition: ServerHandlerImp.cpp:307
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:255
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:122
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:1105
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:53
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
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:125
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:239
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:81
ripple::ServerHandlerImp::Setup::client_t::password
std::string password
Definition: ServerHandlerImp.h:64
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:364
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
ripple::make_ServerHandler
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, Stoppable &parent, boost::asio::io_service &io_service, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
Definition: ServerHandlerImp.cpp:1157
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:167
ripple::BasicConfig::exists
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Definition: BasicConfig.cpp:132
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:66
ripple::ServerHandlerImp::countlock_
std::mutex countlock_
Definition: ServerHandlerImp.h:101
ripple::parse_Ports
static std::vector< Port > parse_Ports(Config const &config, std::ostream &log)
Definition: ServerHandlerImp.cpp:1039
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:138
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)