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