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 
877  auto start = std::chrono::system_clock::now();
878 
879  try
880  {
881  RPC::doCommand(context, result);
882  }
883  catch (std::exception const& ex)
884  {
885  result = RPC::make_error(rpcINTERNAL);
886  JLOG(m_journal.error()) << "Internal error : " << ex.what()
887  << " when processing request: "
888  << Json::Compact{Json::Value{params}};
889  }
890 
891  auto end = std::chrono::system_clock::now();
892 
893  logDuration(params, end - start, m_journal);
894 
895  usage.charge(loadType);
896  if (usage.warn())
897  result[jss::warning] = jss::load;
898 
900  if (ripplerpc >= "2.0")
901  {
902  if (result.isMember(jss::error))
903  {
904  result[jss::status] = jss::error;
905  result["code"] = result[jss::error_code];
906  result["message"] = result[jss::error_message];
907  result.removeMember(jss::error_message);
908  JLOG(m_journal.debug()) << "rpcError: " << result[jss::error]
909  << ": " << result[jss::error_message];
910  r[jss::error] = std::move(result);
911  }
912  else
913  {
914  result[jss::status] = jss::success;
915  r[jss::result] = std::move(result);
916  }
917  }
918  else
919  {
920  // Always report "status". On an error report the request as
921  // received.
922  if (result.isMember(jss::error))
923  {
924  auto rq = params;
925 
926  if (rq.isObject())
927  { // But mask potentially sensitive information.
928  if (rq.isMember(jss::passphrase.c_str()))
929  rq[jss::passphrase.c_str()] = "<masked>";
930  if (rq.isMember(jss::secret.c_str()))
931  rq[jss::secret.c_str()] = "<masked>";
932  if (rq.isMember(jss::seed.c_str()))
933  rq[jss::seed.c_str()] = "<masked>";
934  if (rq.isMember(jss::seed_hex.c_str()))
935  rq[jss::seed_hex.c_str()] = "<masked>";
936  }
937 
938  result[jss::status] = jss::error;
939  result[jss::request] = rq;
940 
941  JLOG(m_journal.debug()) << "rpcError: " << result[jss::error]
942  << ": " << result[jss::error_message];
943  }
944  else
945  {
946  result[jss::status] = jss::success;
947  }
948  r[jss::result] = std::move(result);
949  }
950 
951  if (params.isMember(jss::jsonrpc))
952  r[jss::jsonrpc] = params[jss::jsonrpc];
953  if (params.isMember(jss::ripplerpc))
954  r[jss::ripplerpc] = params[jss::ripplerpc];
955  if (params.isMember(jss::id))
956  r[jss::id] = params[jss::id];
957  if (batch)
958  reply.append(std::move(r));
959  else
960  reply = std::move(r);
961 
962  if (reply.isMember(jss::result) &&
963  reply[jss::result].isMember(jss::result))
964  {
965  reply = reply[jss::result];
966  if (reply.isMember(jss::status))
967  {
968  reply[jss::result][jss::status] = reply[jss::status];
969  reply.removeMember(jss::status);
970  }
971  }
972  }
973  auto response = to_string(reply);
974 
975  rpc_time_.notify(std::chrono::duration_cast<std::chrono::milliseconds>(
977  ++rpc_requests_;
979 
980  response += '\n';
981 
982  if (auto stream = m_journal.debug())
983  {
984  static const int maxSize = 10000;
985  if (response.size() <= maxSize)
986  stream << "Reply: " << response;
987  else
988  stream << "Reply: " << response.substr(0, maxSize);
989  }
990 
991  HTTPReply(200, response, output, rpcJ);
992 }
993 
994 //------------------------------------------------------------------------------
995 
996 /* This response is used with load balancing.
997  If the server is overloaded, status 500 is reported. Otherwise status 200
998  is reported, meaning the server can accept more connections.
999 */
1000 Handoff
1002 {
1003  using namespace boost::beast::http;
1004  Handoff handoff;
1005  response<string_body> msg;
1006  std::string reason;
1007  if (app_.serverOkay(reason))
1008  {
1009  msg.result(boost::beast::http::status::ok);
1010  msg.body() = "<!DOCTYPE html><html><head><title>" + systemName() +
1011  " Test page for rippled</title></head><body><h1>" + systemName() +
1012  " Test</h1><p>This page shows rippled http(s) "
1013  "connectivity is working.</p></body></html>";
1014  }
1015  else
1016  {
1017  msg.result(boost::beast::http::status::internal_server_error);
1018  msg.body() = "<HTML><BODY>Server cannot accept clients: " + reason +
1019  "</BODY></HTML>";
1020  }
1021  msg.version(request.version());
1022  msg.insert("Server", BuildInfo::getFullVersionString());
1023  msg.insert("Content-Type", "text/html");
1024  msg.insert("Connection", "close");
1025  msg.prepare_payload();
1026  handoff.response = std::make_shared<SimpleWriter>(msg);
1027  return handoff;
1028 }
1029 
1030 //------------------------------------------------------------------------------
1031 
1032 void
1034 {
1035  for (auto& p : ports)
1036  {
1037  if (p.secure())
1038  {
1039  if (p.ssl_key.empty() && p.ssl_cert.empty() && p.ssl_chain.empty())
1040  p.context = make_SSLContext(p.ssl_ciphers);
1041  else
1042  p.context = make_SSLContextAuthed(
1043  p.ssl_key, p.ssl_cert, p.ssl_chain, p.ssl_ciphers);
1044  }
1045  else
1046  {
1047  p.context = std::make_shared<boost::asio::ssl::context>(
1048  boost::asio::ssl::context::sslv23);
1049  }
1050  }
1051 }
1052 
1053 static Port
1054 to_Port(ParsedPort const& parsed, std::ostream& log)
1055 {
1056  Port p;
1057  p.name = parsed.name;
1058 
1059  if (!parsed.ip)
1060  {
1061  log << "Missing 'ip' in [" << p.name << "]";
1062  Throw<std::exception>();
1063  }
1064  p.ip = *parsed.ip;
1065 
1066  if (!parsed.port)
1067  {
1068  log << "Missing 'port' in [" << p.name << "]";
1069  Throw<std::exception>();
1070  }
1071  else if (*parsed.port == 0)
1072  {
1073  log << "Port " << *parsed.port << "in [" << p.name << "] is invalid";
1074  Throw<std::exception>();
1075  }
1076  p.port = *parsed.port;
1077 
1078  if (parsed.protocol.empty())
1079  {
1080  log << "Missing 'protocol' in [" << p.name << "]";
1081  Throw<std::exception>();
1082  }
1083  p.protocol = parsed.protocol;
1084 
1085  p.user = parsed.user;
1086  p.password = parsed.password;
1087  p.admin_user = parsed.admin_user;
1088  p.admin_password = parsed.admin_password;
1089  p.ssl_key = parsed.ssl_key;
1090  p.ssl_cert = parsed.ssl_cert;
1091  p.ssl_chain = parsed.ssl_chain;
1092  p.ssl_ciphers = parsed.ssl_ciphers;
1093  p.pmd_options = parsed.pmd_options;
1094  p.ws_queue_limit = parsed.ws_queue_limit;
1095  p.limit = parsed.limit;
1096  p.admin_nets_v4 = parsed.admin_nets_v4;
1097  p.admin_nets_v6 = parsed.admin_nets_v6;
1100 
1101  return p;
1102 }
1103 
1104 static std::vector<Port>
1105 parse_Ports(Config const& config, std::ostream& log)
1106 {
1107  std::vector<Port> result;
1108 
1109  if (!config.exists("server"))
1110  {
1111  log << "Required section [server] is missing";
1112  Throw<std::exception>();
1113  }
1114 
1115  ParsedPort common;
1116  parse_Port(common, config["server"], log);
1117 
1118  auto const& names = config.section("server").values();
1119  result.reserve(names.size());
1120  for (auto const& name : names)
1121  {
1122  if (!config.exists(name))
1123  {
1124  log << "Missing section: [" << name << "]";
1125  Throw<std::exception>();
1126  }
1127  ParsedPort parsed = common;
1128  parsed.name = name;
1129  parse_Port(parsed, config[name], log);
1130  result.push_back(to_Port(parsed, log));
1131  }
1132 
1133  if (config.standalone())
1134  {
1135  auto it = result.begin();
1136 
1137  while (it != result.end())
1138  {
1139  auto& p = it->protocol;
1140 
1141  // Remove the peer protocol, and if that would
1142  // leave the port empty, remove the port as well
1143  if (p.erase("peer") && p.empty())
1144  it = result.erase(it);
1145  else
1146  ++it;
1147  }
1148  }
1149  else
1150  {
1151  auto const count =
1152  std::count_if(result.cbegin(), result.cend(), [](Port const& p) {
1153  return p.protocol.count("peer") != 0;
1154  });
1155 
1156  if (count > 1)
1157  {
1158  log << "Error: More than one peer protocol configured in [server]";
1159  Throw<std::exception>();
1160  }
1161 
1162  if (count == 0)
1163  log << "Warning: No peer protocol configured";
1164  }
1165 
1166  return result;
1167 }
1168 
1169 // Fill out the client portion of the Setup
1170 static void
1172 {
1173  decltype(setup.ports)::const_iterator iter;
1174  for (iter = setup.ports.cbegin(); iter != setup.ports.cend(); ++iter)
1175  if (iter->protocol.count("http") > 0 ||
1176  iter->protocol.count("https") > 0)
1177  break;
1178  if (iter == setup.ports.cend())
1179  return;
1180  setup.client.secure = iter->protocol.count("https") > 0;
1182  ?
1183  // VFALCO HACK! to make localhost work
1184  (iter->ip.is_v6() ? "::1" : "127.0.0.1")
1185  : iter->ip.to_string();
1186  setup.client.port = iter->port;
1187  setup.client.user = iter->user;
1188  setup.client.password = iter->password;
1189  setup.client.admin_user = iter->admin_user;
1190  setup.client.admin_password = iter->admin_password;
1191 }
1192 
1193 // Fill out the overlay portion of the Setup
1194 static void
1196 {
1197  auto const iter = std::find_if(
1198  setup.ports.cbegin(), setup.ports.cend(), [](Port const& port) {
1199  return port.protocol.count("peer") != 0;
1200  });
1201  if (iter == setup.ports.cend())
1202  {
1203  setup.overlay.port = 0;
1204  return;
1205  }
1206  setup.overlay.ip = iter->ip;
1207  setup.overlay.port = iter->port;
1208 }
1209 
1210 ServerHandler::Setup
1212 {
1214  setup.ports = parse_Ports(config, log);
1215 
1218 
1219  return setup;
1220 }
1221 
1224  Application& app,
1225  boost::asio::io_service& io_service,
1226  JobQueue& jobQueue,
1227  NetworkOPs& networkOPs,
1228  Resource::Manager& resourceManager,
1229  CollectorManager& cm)
1230 {
1231  return std::make_unique<ServerHandlerImp>(
1232  app, io_service, jobQueue, networkOPs, resourceManager, cm);
1233 }
1234 
1235 } // 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: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: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: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: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:361
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:1033
ripple::jtCLIENT_RPC
@ jtCLIENT_RPC
Definition: Job.h:51
ripple::ServerHandlerImp::statusResponse
Handoff statusResponse(http_request_type const &request) const
Definition: ServerHandlerImp.cpp:1001
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:372
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:1211
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: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:1223
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: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:84
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::ServerHandlerImp::stopped_
bool stopped_
Definition: ServerHandlerImp.h:104
ripple::Config
Definition: Config.h:69
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:312
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:66
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:273
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:1054
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:1171
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: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:188
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:1105
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)