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