rippled
Loading...
Searching...
No Matches
Handler.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 <xrpld/rpc/detail/Handler.h>
21#include <xrpld/rpc/detail/RPCHelpers.h>
22#include <xrpld/rpc/handlers/Handlers.h>
23#include <xrpld/rpc/handlers/Version.h>
24#include <xrpl/basics/contract.h>
25
26#include <map>
27
28namespace ripple {
29namespace RPC {
30namespace {
31
33template <typename Function>
34Handler::Method<Json::Value>
35byRef(Function const& f)
36{
37 return [f](JsonContext& context, Json::Value& result) {
38 result = f(context);
39 if (result.type() != Json::objectValue)
40 {
41 UNREACHABLE("ripple::RPC::byRef : result is object");
42 result = RPC::makeObjectValue(result);
43 }
44
45 return Status();
46 };
47}
48
49template <class Object, class HandlerImpl>
51handle(JsonContext& context, Object& object)
52{
53 XRPL_ASSERT(
54 context.apiVersion >= HandlerImpl::minApiVer &&
55 context.apiVersion <= HandlerImpl::maxApiVer,
56 "ripple::RPC::handle : valid API version");
57 HandlerImpl handler(context);
58
59 auto status = handler.check();
60 if (status)
61 status.inject(object);
62 else
63 handler.writeResult(object);
64 return status;
65}
66
67template <typename HandlerImpl>
68Handler
69handlerFrom()
70{
71 return {
72 HandlerImpl::name,
73 &handle<Json::Value, HandlerImpl>,
74 HandlerImpl::role,
75 HandlerImpl::condition,
76 HandlerImpl::minApiVer,
77 HandlerImpl::maxApiVer};
78}
79
80Handler const handlerArray[]{
81 // Some handlers not specified here are added to the table via addHandler()
82 // Request-response methods
83 {"account_info", byRef(&doAccountInfo), Role::USER, NO_CONDITION},
84 {"account_currencies",
85 byRef(&doAccountCurrencies),
88 {"account_lines", byRef(&doAccountLines), Role::USER, NO_CONDITION},
89 {"account_channels", byRef(&doAccountChannels), Role::USER, NO_CONDITION},
90 {"account_nfts", byRef(&doAccountNFTs), Role::USER, NO_CONDITION},
91 {"account_objects", byRef(&doAccountObjects), Role::USER, NO_CONDITION},
92 {"account_offers", byRef(&doAccountOffers), Role::USER, NO_CONDITION},
93 {"account_tx", byRef(&doAccountTxJson), Role::USER, NO_CONDITION},
94 {"amm_info", byRef(&doAMMInfo), Role::USER, NO_CONDITION},
95 {"blacklist", byRef(&doBlackList), Role::ADMIN, NO_CONDITION},
96 {"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION},
97 {"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION},
98 {"can_delete", byRef(&doCanDelete), Role::ADMIN, NO_CONDITION},
99 {"channel_authorize", byRef(&doChannelAuthorize), Role::USER, NO_CONDITION},
100 {"channel_verify", byRef(&doChannelVerify), Role::USER, NO_CONDITION},
101 {"connect", byRef(&doConnect), Role::ADMIN, NO_CONDITION},
102 {"consensus_info", byRef(&doConsensusInfo), Role::ADMIN, NO_CONDITION},
103 {"deposit_authorized",
104 byRef(&doDepositAuthorized),
107 {"feature", byRef(&doFeature), Role::USER, NO_CONDITION},
108 {"fee", byRef(&doFee), Role::USER, NEEDS_CURRENT_LEDGER},
109 {"fetch_info", byRef(&doFetchInfo), Role::ADMIN, NO_CONDITION},
110 {"gateway_balances", byRef(&doGatewayBalances), Role::USER, NO_CONDITION},
111 {"get_counts", byRef(&doGetCounts), Role::ADMIN, NO_CONDITION},
112 {"get_aggregate_price",
113 byRef(&doGetAggregatePrice),
116 {"ledger_accept",
117 byRef(&doLedgerAccept),
120 {"ledger_cleaner",
121 byRef(&doLedgerCleaner),
124 {"ledger_closed", byRef(&doLedgerClosed), Role::USER, NEEDS_CLOSED_LEDGER},
125 {"ledger_current",
126 byRef(&doLedgerCurrent),
129 {"ledger_data", byRef(&doLedgerData), Role::USER, NO_CONDITION},
130 {"ledger_entry", byRef(&doLedgerEntry), Role::USER, NO_CONDITION},
131 {"ledger_header", byRef(&doLedgerHeader), Role::USER, NO_CONDITION, 1, 1},
132 {"ledger_request", byRef(&doLedgerRequest), Role::ADMIN, NO_CONDITION},
133 {"log_level", byRef(&doLogLevel), Role::ADMIN, NO_CONDITION},
134 {"logrotate", byRef(&doLogRotate), Role::ADMIN, NO_CONDITION},
135 {"manifest", byRef(&doManifest), Role::USER, NO_CONDITION},
136 {"nft_buy_offers", byRef(&doNFTBuyOffers), Role::USER, NO_CONDITION},
137 {"nft_sell_offers", byRef(&doNFTSellOffers), Role::USER, NO_CONDITION},
138 {"noripple_check", byRef(&doNoRippleCheck), Role::USER, NO_CONDITION},
139 {"owner_info", byRef(&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER},
140 {"peers", byRef(&doPeers), Role::ADMIN, NO_CONDITION},
141 {"path_find", byRef(&doPathFind), Role::USER, NEEDS_CURRENT_LEDGER},
142 {"ping", byRef(&doPing), Role::USER, NO_CONDITION},
143 {"print", byRef(&doPrint), Role::ADMIN, NO_CONDITION},
144 // { "profile", byRef (&doProfile), Role::USER,
145 // NEEDS_CURRENT_LEDGER },
146 {"random", byRef(&doRandom), Role::USER, NO_CONDITION},
147 {"peer_reservations_add",
148 byRef(&doPeerReservationsAdd),
151 {"peer_reservations_del",
152 byRef(&doPeerReservationsDel),
155 {"peer_reservations_list",
159 {"ripple_path_find", byRef(&doRipplePathFind), Role::USER, NO_CONDITION},
160 {"server_definitions",
161 byRef(&doServerDefinitions),
164 {"server_info", byRef(&doServerInfo), Role::USER, NO_CONDITION},
165 {"server_state", byRef(&doServerState), Role::USER, NO_CONDITION},
166 {"sign", byRef(&doSign), Role::USER, NO_CONDITION},
167 {"sign_for", byRef(&doSignFor), Role::USER, NO_CONDITION},
168 {"simulate", byRef(&doSimulate), Role::USER, NEEDS_CURRENT_LEDGER},
169 {"stop", byRef(&doStop), Role::ADMIN, NO_CONDITION},
170 {"submit", byRef(&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER},
171 {"submit_multisigned",
172 byRef(&doSubmitMultiSigned),
175 {"transaction_entry", byRef(&doTransactionEntry), Role::USER, NO_CONDITION},
177 {"tx_history", byRef(&doTxHistory), Role::USER, NO_CONDITION, 1, 1},
178 {"tx_reduce_relay", byRef(&doTxReduceRelay), Role::USER, NO_CONDITION},
179 {"unl_list", byRef(&doUnlList), Role::ADMIN, NO_CONDITION},
180 {"validation_create",
181 byRef(&doValidationCreate),
184 {"validators", byRef(&doValidators), Role::ADMIN, NO_CONDITION},
185 {"validator_list_sites",
186 byRef(&doValidatorListSites),
189 {"validator_info", byRef(&doValidatorInfo), Role::ADMIN, NO_CONDITION},
190 {"wallet_propose", byRef(&doWalletPropose), Role::ADMIN, NO_CONDITION},
191 // Evented methods
192 {"subscribe", byRef(&doSubscribe), Role::USER, NO_CONDITION},
193 {"unsubscribe", byRef(&doUnsubscribe), Role::USER, NO_CONDITION},
194};
195
196class HandlerTable
197{
198private:
199 using handler_table_t = std::multimap<std::string, Handler>;
200
201 // Use with equal_range to enforce that API range of a newly added handler
202 // does not overlap with API range of an existing handler with same name
203 [[nodiscard]] bool
204 overlappingApiVersion(
206 unsigned minVer,
207 unsigned maxVer)
208 {
209 XRPL_ASSERT(
210 minVer <= maxVer,
211 "ripple::RPC::HandlerTable : valid API version range");
212 XRPL_ASSERT(
214 "ripple::RPC::HandlerTable : valid max API version");
215
216 return std::any_of(
217 range.first,
218 range.second, //
219 [minVer, maxVer](auto const& item) {
220 return item.second.minApiVer_ <= maxVer &&
221 item.second.maxApiVer_ >= minVer;
222 });
223 }
224
225 template <std::size_t N>
226 explicit HandlerTable(const Handler (&entries)[N])
227 {
228 for (auto const& entry : entries)
229 {
230 if (overlappingApiVersion(
231 table_.equal_range(entry.name_),
232 entry.minApiVer_,
233 entry.maxApiVer_))
235 std::string("Handler for ") + entry.name_ +
236 " overlaps with an existing handler");
237
238 table_.insert({entry.name_, entry});
239 }
240
241 // This is where the new-style handlers are added.
242 addHandler<LedgerHandler>();
243 addHandler<VersionHandler>();
244 }
245
246public:
247 static HandlerTable const&
248 instance()
249 {
250 static HandlerTable const handlerTable(handlerArray);
251 return handlerTable;
252 }
253
254 [[nodiscard]] Handler const*
255 getHandler(unsigned version, bool betaEnabled, std::string const& name)
256 const
257 {
258 if (version < RPC::apiMinimumSupportedVersion ||
259 version > (betaEnabled ? RPC::apiBetaVersion
261 return nullptr;
262
263 auto const range = table_.equal_range(name);
264 auto const i = std::find_if(
265 range.first, range.second, [version](auto const& entry) {
266 return entry.second.minApiVer_ <= version &&
267 version <= entry.second.maxApiVer_;
268 });
269
270 return i == range.second ? nullptr : &i->second;
271 }
272
273 [[nodiscard]] std::set<char const*>
274 getHandlerNames() const
275 {
277 for (auto const& i : table_)
278 ret.insert(i.second.name_);
279
280 return ret;
281 }
282
283private:
284 handler_table_t table_;
285
286 template <class HandlerImpl>
287 void
288 addHandler()
289 {
290 static_assert(HandlerImpl::minApiVer <= HandlerImpl::maxApiVer);
291 static_assert(HandlerImpl::maxApiVer <= RPC::apiMaximumValidVersion);
292 static_assert(
293 RPC::apiMinimumSupportedVersion <= HandlerImpl::minApiVer);
294
295 if (overlappingApiVersion(
296 table_.equal_range(HandlerImpl::name),
297 HandlerImpl::minApiVer,
298 HandlerImpl::maxApiVer))
300 std::string("Handler for ") + HandlerImpl::name +
301 " overlaps with an existing handler");
302
303 table_.insert({HandlerImpl::name, handlerFrom<HandlerImpl>()});
304 }
305};
306
307} // namespace
308
309Handler const*
310getHandler(unsigned version, bool betaEnabled, std::string const& name)
311{
312 return HandlerTable::instance().getHandler(version, betaEnabled, name);
313}
314
317{
318 return HandlerTable::instance().getHandlerNames();
319}
320
321} // namespace RPC
322} // namespace ripple
T any_of(T... args)
Represents a JSON value.
Definition: json_value.h:147
T equal_range(T... args)
T find_if(T... args)
T insert(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
Status
Return codes from Backend operations.
@ NEEDS_CURRENT_LEDGER
Definition: Handler.h:43
@ NEEDS_NETWORK_CONNECTION
Definition: Handler.h:42
@ NO_CONDITION
Definition: Handler.h:41
@ NEEDS_CLOSED_LEDGER
Definition: Handler.h:44
static constexpr auto apiMaximumSupportedVersion
Definition: ApiVersion.h:58
std::set< char const * > getHandlerNames()
Return names of all methods.
Definition: Handler.cpp:316
Json::Value makeObjectValue(Value const &value, Json::StaticString const &field=jss::message)
Return a Json::objectValue with a single entry.
Definition: Handler.h:67
static constexpr auto apiMaximumValidVersion
Definition: ApiVersion.h:63
static constexpr auto apiBetaVersion
Definition: ApiVersion.h:62
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition: Handler.cpp:310
static constexpr auto apiMinimumSupportedVersion
Definition: ApiVersion.h:57
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
Json::Value doPeers(RPC::JsonContext &)
Definition: Peers.cpp:32
Json::Value doTxHistory(RPC::JsonContext &)
Definition: TxHistory.cpp:42
Json::Value doLedgerAccept(RPC::JsonContext &)
Json::Value doUnsubscribe(RPC::JsonContext &)
Definition: Unsubscribe.cpp:32
Json::Value doTxReduceRelay(RPC::JsonContext &)
Json::Value doServerState(RPC::JsonContext &)
Definition: ServerState.cpp:31
Json::Value doChannelVerify(RPC::JsonContext &)
Json::Value doValidationCreate(RPC::JsonContext &)
Json::Value doGetAggregatePrice(RPC::JsonContext &context)
oracles: array of {account, oracle_document_id} base_asset: is the asset to be priced quote_asset: is...
Json::Value doSubmitMultiSigned(RPC::JsonContext &)
Json::Value doLedgerEntry(RPC::JsonContext &)
Json::Value doNFTBuyOffers(RPC::JsonContext &)
Definition: NFTOffers.cpp:165
Json::Value doChannelAuthorize(RPC::JsonContext &)
Json::Value doNoRippleCheck(RPC::JsonContext &)
Json::Value doTransactionEntry(RPC::JsonContext &)
Json::Value doConsensusInfo(RPC::JsonContext &context)
Json::Value doBookChanges(RPC::JsonContext &context)
Definition: BookOffers.cpp:205
Json::Value doLedgerRequest(RPC::JsonContext &)
Json::Value doSimulate(RPC::JsonContext &)
Definition: Simulate.cpp:289
Json::Value doPeerReservationsAdd(RPC::JsonContext &)
Json::Value doLedgerCleaner(RPC::JsonContext &)
Json::Value doSign(RPC::JsonContext &)
Definition: SignHandler.cpp:33
Json::Value doAccountTxJson(RPC::JsonContext &context)
Definition: AccountTx.cpp:407
Json::Value doAccountLines(RPC::JsonContext &context)
Json::Value doTxJson(RPC::JsonContext &)
Definition: Tx.cpp:282
Json::Value doAMMInfo(RPC::JsonContext &context)
Definition: AMMInfo.cpp:74
Json::Value doPeerReservationsList(RPC::JsonContext &)
Json::Value doServerInfo(RPC::JsonContext &)
Definition: ServerInfo.cpp:323
Json::Value doFee(RPC::JsonContext &context)
Definition: Fee1.cpp:30
Json::Value doConnect(RPC::JsonContext &context)
Definition: Connect.cpp:38
Json::Value doNFTSellOffers(RPC::JsonContext &)
Definition: NFTOffers.cpp:151
Json::Value doDepositAuthorized(RPC::JsonContext &context)
Json::Value doStop(RPC::JsonContext &)
Definition: Stop.cpp:33
Json::Value doLedgerClosed(RPC::JsonContext &)
Json::Value doLogLevel(RPC::JsonContext &)
Definition: LogLevel.cpp:32
Json::Value doSubmit(RPC::JsonContext &)
Definition: Submit.cpp:47
Json::Value doServerDefinitions(RPC::JsonContext &)
Definition: ServerInfo.cpp:300
Json::Value doSubscribe(RPC::JsonContext &)
Definition: Subscribe.cpp:37
Json::Value doAccountObjects(RPC::JsonContext &context)
Json::Value doFeature(RPC::JsonContext &context)
Definition: Feature1.cpp:36
Json::Value doAccountNFTs(RPC::JsonContext &context)
General RPC command that can retrieve objects in the account root.
Json::Value doFetchInfo(RPC::JsonContext &context)
Definition: FetchInfo.cpp:31
Json::Value doLedgerHeader(RPC::JsonContext &)
Json::Value doRandom(RPC::JsonContext &)
Definition: Random.cpp:39
Json::Value doManifest(RPC::JsonContext &)
Json::Value doGetCounts(RPC::JsonContext &context)
Definition: GetCounts.cpp:139
Json::Value doPing(RPC::JsonContext &)
Definition: Ping.cpp:32
Json::Value doBlackList(RPC::JsonContext &context)
Definition: BlackList.cpp:28
Json::Value doLedgerData(RPC::JsonContext &)
Definition: LedgerData.cpp:45
Json::Value doValidatorListSites(RPC::JsonContext &)
Json::Value doSignFor(RPC::JsonContext &)
Definition: SignFor.cpp:35
Json::Value doLedgerCurrent(RPC::JsonContext &)
Json::Value doAccountOffers(RPC::JsonContext &context)
Json::Value doValidatorInfo(RPC::JsonContext &)
Json::Value doGatewayBalances(RPC::JsonContext &context)
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:54
Json::Value doRipplePathFind(RPC::JsonContext &)
Json::Value doBookOffers(RPC::JsonContext &context)
Definition: BookOffers.cpp:36
Json::Value doAccountCurrencies(RPC::JsonContext &context)
Json::Value doAccountInfo(RPC::JsonContext &context)
Definition: AccountInfo.cpp:51
Json::Value doLogRotate(RPC::JsonContext &)
Definition: LogRotate.cpp:28
Json::Value doCanDelete(RPC::JsonContext &context)
Definition: CanDelete.cpp:35
Json::Value doWalletPropose(RPC::JsonContext &)
Json::Value doAccountChannels(RPC::JsonContext &context)
Json::Value doPeerReservationsDel(RPC::JsonContext &)
Json::Value doValidators(RPC::JsonContext &)
Definition: Validators.cpp:29
Json::Value doOwnerInfo(RPC::JsonContext &)
Definition: OwnerInfo.cpp:35
Json::Value doPrint(RPC::JsonContext &)
Definition: Print.cpp:29
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
Json::Value doUnlList(RPC::JsonContext &)
Definition: UnlList.cpp:30
Json::Value doPathFind(RPC::JsonContext &)
Definition: PathFind.cpp:33