rippled
Loading...
Searching...
No Matches
RPCHandler.cpp
1#include <xrpld/app/ledger/InboundLedgers.h>
2#include <xrpld/app/ledger/LedgerMaster.h>
3#include <xrpld/app/ledger/LedgerToJson.h>
4#include <xrpld/app/main/Application.h>
5#include <xrpld/app/misc/NetworkOPs.h>
6#include <xrpld/core/Config.h>
7#include <xrpld/core/JobQueue.h>
8#include <xrpld/perflog/PerfLog.h>
9#include <xrpld/rpc/Context.h>
10#include <xrpld/rpc/InfoSub.h>
11#include <xrpld/rpc/RPCHandler.h>
12#include <xrpld/rpc/Role.h>
13#include <xrpld/rpc/detail/Handler.h>
14#include <xrpld/rpc/detail/Tuning.h>
15
16#include <xrpl/basics/Log.h>
17#include <xrpl/json/to_string.h>
18#include <xrpl/protocol/ErrorCodes.h>
19#include <xrpl/protocol/jss.h>
20#include <xrpl/resource/Fees.h>
21
22#include <atomic>
23#include <chrono>
24
25namespace ripple {
26namespace RPC {
27
28namespace {
29
111fillHandler(JsonContext& context, Handler const*& result)
112{
113 if (!isUnlimited(context.role))
114 {
115 // Count all jobs at jtCLIENT priority or higher.
116 int const jobCount = context.app.getJobQueue().getJobCountGE(jtCLIENT);
117 if (jobCount > Tuning::maxJobQueueClients)
118 {
119 JLOG(context.j.debug()) << "Too busy for command: " << jobCount;
120 return rpcTOO_BUSY;
121 }
122 }
123
124 if (!context.params.isMember(jss::command) &&
125 !context.params.isMember(jss::method))
126 return rpcCOMMAND_MISSING;
127 if (context.params.isMember(jss::command) &&
128 context.params.isMember(jss::method))
129 {
130 if (context.params[jss::command].asString() !=
131 context.params[jss::method].asString())
132 return rpcUNKNOWN_COMMAND;
133 }
134
135 std::string strCommand = context.params.isMember(jss::command)
136 ? context.params[jss::command].asString()
137 : context.params[jss::method].asString();
138
139 JLOG(context.j.trace()) << "COMMAND:" << strCommand;
140 JLOG(context.j.trace()) << "REQUEST:" << context.params;
141 auto handler = getHandler(
142 context.apiVersion, context.app.config().BETA_RPC_API, strCommand);
143
144 if (!handler)
145 return rpcUNKNOWN_COMMAND;
146
147 if (handler->role_ == Role::ADMIN && context.role != Role::ADMIN)
148 return rpcNO_PERMISSION;
149
150 error_code_i res = conditionMet(handler->condition_, context);
151 if (res != rpcSUCCESS)
152 {
153 return res;
154 }
155
156 result = handler;
157 return rpcSUCCESS;
158}
159
160template <class Object, class Method>
161Status
162callMethod(
163 JsonContext& context,
164 Method method,
165 std::string const& name,
166 Object& result)
167{
168 static std::atomic<std::uint64_t> requestId{0};
169 auto& perfLog = context.app.getPerfLog();
170 std::uint64_t const curId = ++requestId;
171 try
172 {
173 perfLog.rpcStart(name, curId);
174 auto v =
175 context.app.getJobQueue().makeLoadEvent(jtGENERIC, "cmd:" + name);
176
177 auto start = std::chrono::system_clock::now();
178 auto ret = method(context, result);
180
181 JLOG(context.j.debug())
182 << "RPC call " << name << " completed in "
183 << ((end - start).count() / 1000000000.0) << "seconds";
184 perfLog.rpcFinish(name, curId);
185 return ret;
186 }
187 catch (std::exception& e)
188 {
189 perfLog.rpcError(name, curId);
190 JLOG(context.j.info()) << "Caught throw: " << e.what();
191
192 if (context.loadType == Resource::feeReferenceRPC)
193 context.loadType = Resource::feeExceptionRPC;
194
195 inject_error(rpcINTERNAL, result);
196 return rpcINTERNAL;
197 }
198}
199
200} // namespace
201
202Status
204{
205 Handler const* handler = nullptr;
206 if (auto error = fillHandler(context, handler))
207 {
208 inject_error(error, result);
209 return error;
210 }
211
212 if (auto method = handler->valueMethod_)
213 {
214 if (!context.headers.user.empty() ||
215 !context.headers.forwardedFor.empty())
216 {
217 JLOG(context.j.debug())
218 << "start command: " << handler->name_
219 << ", user: " << context.headers.user
220 << ", forwarded for: " << context.headers.forwardedFor;
221
222 auto ret = callMethod(context, method, handler->name_, result);
223
224 JLOG(context.j.debug())
225 << "finish command: " << handler->name_
226 << ", user: " << context.headers.user
227 << ", forwarded for: " << context.headers.forwardedFor;
228
229 return ret;
230 }
231 else
232 {
233 auto ret = callMethod(context, method, handler->name_, result);
234 return ret;
235 }
236 }
237
238 return rpcUNKNOWN_COMMAND;
239}
240
241Role
242roleRequired(unsigned int version, bool betaEnabled, std::string const& method)
243{
244 auto handler = RPC::getHandler(version, betaEnabled, method);
245
246 if (!handler)
247 return Role::FORBID;
248
249 return handler->role_;
250}
251
252} // namespace RPC
253} // namespace ripple
Represents a JSON value.
Definition json_value.h:130
Stream debug() const
Definition Journal.h:309
T count(T... args)
T empty(T... args)
T end(T... args)
Status
Return codes from Backend operations.
static int constexpr maxJobQueueClients
Role roleRequired(unsigned int version, bool betaEnabled, std::string const &method)
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition ErrorCodes.h:214
Status doCommand(RPC::JsonContext &context, Json::Value &result)
Execute an RPC command and store the results in a Json::Value.
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition Handler.cpp:294
error_code_i conditionMet(Condition condition_required, T &context)
Definition Handler.h:62
Charge const feeReferenceRPC
Charge const feeExceptionRPC
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@ rpcUNKNOWN_COMMAND
Definition ErrorCodes.h:66
@ rpcTOO_BUSY
Definition ErrorCodes.h:37
@ rpcSUCCESS
Definition ErrorCodes.h:25
@ rpcINTERNAL
Definition ErrorCodes.h:111
@ rpcCOMMAND_MISSING
Definition ErrorCodes.h:83
@ rpcNO_PERMISSION
Definition ErrorCodes.h:34
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition Role.cpp:106
Role
Indicates the level of administrative permission to grant.
Definition Role.h:25
@ jtGENERIC
Definition Job.h:68
@ jtCLIENT
Definition Job.h:26
beast::Journal const j
Definition Context.h:21
char const * name_
Definition Handler.h:32
Method< Json::Value > valueMethod_
Definition Handler.h:33
std::string_view forwardedFor
Definition Context.h:41
T what(T... args)