rippled
RPCHandler.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/ledger/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/NetworkOPs.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/PerfLog.h>
25 #include <ripple/basics/contract.h>
26 #include <ripple/core/Config.h>
27 #include <ripple/core/JobQueue.h>
28 #include <ripple/json/Object.h>
29 #include <ripple/json/to_string.h>
30 #include <ripple/net/InfoSub.h>
31 #include <ripple/net/RPCErr.h>
32 #include <ripple/protocol/jss.h>
33 #include <ripple/resource/Fees.h>
34 #include <ripple/rpc/RPCHandler.h>
35 #include <ripple/rpc/Role.h>
36 #include <ripple/rpc/impl/Handler.h>
37 #include <ripple/rpc/impl/Tuning.h>
38 #include <atomic>
39 #include <chrono>
40 
41 namespace ripple {
42 namespace RPC {
43 
44 namespace {
45 
127 fillHandler(JsonContext& context, Handler const*& result)
128 {
129  if (!isUnlimited(context.role))
130  {
131  // VFALCO NOTE Should we also add up the jtRPC jobs?
132  //
133  int jc = context.app.getJobQueue().getJobCountGE(jtCLIENT);
135  {
136  JLOG(context.j.debug()) << "Too busy for command: " << jc;
137  return rpcTOO_BUSY;
138  }
139  }
140 
141  if (!context.params.isMember(jss::command) &&
142  !context.params.isMember(jss::method))
143  return rpcCOMMAND_MISSING;
144  if (context.params.isMember(jss::command) &&
145  context.params.isMember(jss::method))
146  {
147  if (context.params[jss::command].asString() !=
148  context.params[jss::method].asString())
149  return rpcUNKNOWN_COMMAND;
150  }
151 
152  std::string strCommand = context.params.isMember(jss::command)
153  ? context.params[jss::command].asString()
154  : context.params[jss::method].asString();
155 
156  JLOG(context.j.trace()) << "COMMAND:" << strCommand;
157  JLOG(context.j.trace()) << "REQUEST:" << context.params;
158  auto handler = getHandler(context.apiVersion, strCommand);
159 
160  if (!handler)
161  return rpcUNKNOWN_COMMAND;
162 
163  if (handler->role_ == Role::ADMIN && context.role != Role::ADMIN)
164  return rpcNO_PERMISSION;
165 
166  error_code_i res = conditionMet(handler->condition_, context);
167  if (res != rpcSUCCESS)
168  {
169  return res;
170  }
171 
172  result = handler;
173  return rpcSUCCESS;
174 }
175 
176 template <class Object, class Method>
177 Status
178 callMethod(
179  JsonContext& context,
180  Method method,
181  std::string const& name,
182  Object& result)
183 {
184  static std::atomic<std::uint64_t> requestId{0};
185  auto& perfLog = context.app.getPerfLog();
186  std::uint64_t const curId = ++requestId;
187  try
188  {
189  perfLog.rpcStart(name, curId);
190  auto v =
191  context.app.getJobQueue().makeLoadEvent(jtGENERIC, "cmd:" + name);
192 
193  auto ret = method(context, result);
194  perfLog.rpcFinish(name, curId);
195  return ret;
196  }
197  catch (std::exception& e)
198  {
199  perfLog.rpcError(name, curId);
200  JLOG(context.j.info()) << "Caught throw: " << e.what();
201 
202  if (context.loadType == Resource::feeReferenceRPC)
203  context.loadType = Resource::feeExceptionRPC;
204 
205  inject_error(rpcINTERNAL, result);
206  return rpcINTERNAL;
207  }
208 }
209 
210 } // namespace
211 
212 Status
214 {
215  Handler const* handler = nullptr;
216  if (auto error = fillHandler(context, handler))
217  {
218  inject_error(error, result);
219  return error;
220  }
221 
222  if (auto method = handler->valueMethod_)
223  {
224  if (!context.headers.user.empty() ||
225  !context.headers.forwardedFor.empty())
226  {
227  JLOG(context.j.debug())
228  << "start command: " << handler->name_
229  << ", user: " << context.headers.user
230  << ", forwarded for: " << context.headers.forwardedFor;
231 
232  auto ret = callMethod(context, method, handler->name_, result);
233 
234  JLOG(context.j.debug())
235  << "finish command: " << handler->name_
236  << ", user: " << context.headers.user
237  << ", forwarded for: " << context.headers.forwardedFor;
238 
239  return ret;
240  }
241  else
242  {
243  return callMethod(context, method, handler->name_, result);
244  }
245  }
246 
247  return rpcUNKNOWN_COMMAND;
248 }
249 
250 Role
251 roleRequired(unsigned int version, std::string const& method)
252 {
253  auto handler = RPC::getHandler(version, method);
254 
255  if (!handler)
256  return Role::FORBID;
257 
258  return handler->role_;
259 }
260 
261 } // namespace RPC
262 } // namespace ripple
ripple::RPC::JsonContext
Definition: Context.h:53
std::string
STL class.
ripple::jtCLIENT
@ jtCLIENT
Definition: Job.h:48
std::exception
STL class.
ripple::RPC::JsonContext::Headers::user
boost::string_view user
Definition: Context.h:60
ripple::rpcTOO_BUSY
@ rpcTOO_BUSY
Definition: ErrorCodes.h:56
ripple::Resource::feeReferenceRPC
const Charge feeReferenceRPC
ripple::RPC::Handler::name_
const char * name_
Definition: Handler.h:51
ripple::RPC::JsonContext::headers
Headers headers
Definition: Context.h:66
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::RPC::Context::j
const beast::Journal j
Definition: Context.h:41
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:213
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::RPC::Handler
Definition: Handler.h:46
ripple::Role::ADMIN
@ ADMIN
chrono
ripple::jtGENERIC
@ jtGENERIC
Definition: Job.h:74
ripple::Role::FORBID
@ FORBID
std::uint64_t
atomic
ripple::rpcCOMMAND_MISSING
@ rpcCOMMAND_MISSING
Definition: ErrorCodes.h:102
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:130
ripple::isUnlimited
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition: Role.cpp:94
ripple::NodeStore::Status
Status
Return codes from Backend operations.
Definition: nodestore/Types.h:44
ripple::RPC::roleRequired
Role roleRequired(unsigned int version, std::string const &method)
Definition: RPCHandler.cpp:251
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::RPC::Handler::valueMethod_
Method< Json::Value > valueMethod_
Definition: Handler.h:52
ripple::rpcUNKNOWN_COMMAND
@ rpcUNKNOWN_COMMAND
Definition: ErrorCodes.h:85
ripple::RPC::conditionMet
error_code_i conditionMet(Condition condition_required, T &context)
Definition: Handler.h:78
ripple::rpcNO_PERMISSION
@ rpcNO_PERMISSION
Definition: ErrorCodes.h:53
ripple::Resource::feeExceptionRPC
const Charge feeExceptionRPC
ripple::RPC::JsonContext::Headers::forwardedFor
boost::string_view forwardedFor
Definition: Context.h:61
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::RPC::inject_error
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:186
ripple::RPC::getHandler
Handler const * getHandler(unsigned version, std::string const &name)
Definition: Handler.cpp:255
ripple::RPC::Tuning::maxJobQueueClients
static constexpr int maxJobQueueClients
Definition: rpc/impl/Tuning.h:58
ripple::Role
Role
Indicates the level of administrative permission to grant.
Definition: Role.h:40
std::exception::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145