rippled
Loading...
Searching...
No Matches
Unsubscribe.cpp
1#include <xrpld/app/misc/NetworkOPs.h>
2#include <xrpld/rpc/Context.h>
3#include <xrpld/rpc/Role.h>
4#include <xrpld/rpc/detail/RPCHelpers.h>
5
6#include <xrpl/basics/Log.h>
7#include <xrpl/protocol/ErrorCodes.h>
8#include <xrpl/protocol/RPCErr.h>
9#include <xrpl/protocol/jss.h>
10
11namespace ripple {
12
15{
16 InfoSub::pointer ispSub;
18 bool removeUrl{false};
19
20 if (!context.infoSub && !context.params.isMember(jss::url))
21 {
22 // Must be a JSON-RPC call.
24 }
25
26 if (context.params.isMember(jss::url))
27 {
28 if (context.role != Role::ADMIN)
30
31 std::string strUrl = context.params[jss::url].asString();
32 ispSub = context.netOps.findRpcSub(strUrl);
33 if (!ispSub)
34 return jvResult;
35 removeUrl = true;
36 }
37 else
38 {
39 ispSub = context.infoSub;
40 }
41
42 if (context.params.isMember(jss::streams))
43 {
44 if (!context.params[jss::streams].isArray())
46
47 for (auto& it : context.params[jss::streams])
48 {
49 if (!it.isString())
51
52 std::string streamName = it.asString();
53 if (streamName == "server")
54 {
55 context.netOps.unsubServer(ispSub->getSeq());
56 }
57 else if (streamName == "ledger")
58 {
59 context.netOps.unsubLedger(ispSub->getSeq());
60 }
61 else if (streamName == "manifests")
62 {
63 context.netOps.unsubManifests(ispSub->getSeq());
64 }
65 else if (streamName == "transactions")
66 {
67 context.netOps.unsubTransactions(ispSub->getSeq());
68 }
69 else if (
70 streamName == "transactions_proposed" ||
71 streamName == "rt_transactions") // DEPRECATED
72 {
73 context.netOps.unsubRTTransactions(ispSub->getSeq());
74 }
75 else if (streamName == "validations")
76 {
77 context.netOps.unsubValidations(ispSub->getSeq());
78 }
79 else if (streamName == "peer_status")
80 {
81 context.netOps.unsubPeerStatus(ispSub->getSeq());
82 }
83 else if (streamName == "consensus")
84 {
85 context.netOps.unsubConsensus(ispSub->getSeq());
86 }
87 else
88 {
90 }
91 }
92 }
93
94 auto accountsProposed = context.params.isMember(jss::accounts_proposed)
95 ? jss::accounts_proposed
96 : jss::rt_accounts; // DEPRECATED
97 if (context.params.isMember(accountsProposed))
98 {
99 if (!context.params[accountsProposed].isArray())
101
102 auto ids = RPC::parseAccountIds(context.params[accountsProposed]);
103 if (ids.empty())
105 context.netOps.unsubAccount(ispSub, ids, true);
106 }
107
108 if (context.params.isMember(jss::accounts))
109 {
110 if (!context.params[jss::accounts].isArray())
112
113 auto ids = RPC::parseAccountIds(context.params[jss::accounts]);
114 if (ids.empty())
116 context.netOps.unsubAccount(ispSub, ids, false);
117 }
118
119 if (context.params.isMember(jss::account_history_tx_stream))
120 {
121 auto const& req = context.params[jss::account_history_tx_stream];
122 if (!req.isMember(jss::account) || !req[jss::account].isString())
124
125 auto const id = parseBase58<AccountID>(req[jss::account].asString());
126 if (!id)
128
129 bool stopHistoryOnly = false;
130 if (req.isMember(jss::stop_history_tx_only))
131 {
132 if (!req[jss::stop_history_tx_only].isBool())
134 stopHistoryOnly = req[jss::stop_history_tx_only].asBool();
135 }
136 context.netOps.unsubAccountHistory(ispSub, *id, stopHistoryOnly);
137
138 JLOG(context.j.debug())
139 << "doUnsubscribe: account_history_tx_stream: " << toBase58(*id)
140 << " stopHistoryOnly=" << (stopHistoryOnly ? "true" : "false");
141 }
142
143 if (context.params.isMember(jss::books))
144 {
145 if (!context.params[jss::books].isArray())
147
148 for (auto& jv : context.params[jss::books])
149 {
150 if (!jv.isObject() || !jv.isMember(jss::taker_pays) ||
151 !jv.isMember(jss::taker_gets) ||
152 !jv[jss::taker_pays].isObjectOrNull() ||
153 !jv[jss::taker_gets].isObjectOrNull())
154 {
156 }
157
158 Json::Value taker_pays = jv[jss::taker_pays];
159 Json::Value taker_gets = jv[jss::taker_gets];
160
161 Book book;
162
163 // Parse mandatory currency.
164 if (!taker_pays.isMember(jss::currency) ||
166 book.in.currency, taker_pays[jss::currency].asString()))
167 {
168 JLOG(context.j.info()) << "Bad taker_pays currency.";
170 }
171 // Parse optional issuer.
172 else if (
173 ((taker_pays.isMember(jss::issuer)) &&
174 (!taker_pays[jss::issuer].isString() ||
175 !to_issuer(
176 book.in.account, taker_pays[jss::issuer].asString())))
177 // Don't allow illegal issuers.
178 || !isConsistent(book.in) || noAccount() == book.in.account)
179 {
180 JLOG(context.j.info()) << "Bad taker_pays issuer.";
181
183 }
184
185 // Parse mandatory currency.
186 if (!taker_gets.isMember(jss::currency) ||
188 book.out.currency, taker_gets[jss::currency].asString()))
189 {
190 JLOG(context.j.info()) << "Bad taker_gets currency.";
191
193 }
194 // Parse optional issuer.
195 else if (
196 ((taker_gets.isMember(jss::issuer)) &&
197 (!taker_gets[jss::issuer].isString() ||
198 !to_issuer(
199 book.out.account, taker_gets[jss::issuer].asString())))
200 // Don't allow illegal issuers.
201 || !isConsistent(book.out) || noAccount() == book.out.account)
202 {
203 JLOG(context.j.info()) << "Bad taker_gets issuer.";
204
206 }
207
208 if (book.in == book.out)
209 {
210 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
211 return rpcError(rpcBAD_MARKET);
212 }
213
214 if (jv.isMember(jss::domain))
215 {
216 uint256 domain;
217 if (!jv[jss::domain].isString() ||
218 !domain.parseHex(jv[jss::domain].asString()))
219 {
221 }
222 else
223 {
224 book.domain = domain;
225 }
226 }
227
228 context.netOps.unsubBook(ispSub->getSeq(), book);
229
230 // both_sides is deprecated.
231 if ((jv.isMember(jss::both) && jv[jss::both].asBool()) ||
232 (jv.isMember(jss::both_sides) && jv[jss::both_sides].asBool()))
233 {
234 context.netOps.unsubBook(ispSub->getSeq(), reversed(book));
235 }
236 }
237 }
238
239 if (removeUrl)
240 {
241 context.netOps.tryRemoveRpcSub(context.params[jss::url].asString());
242 }
243
244 return jvResult;
245}
246
247} // namespace ripple
Represents a JSON value.
Definition json_value.h:131
bool isArray() const
bool isString() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
Stream debug() const
Definition Journal.h:309
Stream info() const
Definition Journal.h:315
Specifies an order book.
Definition Book.h:17
Issue in
Definition Book.h:19
Issue out
Definition Book.h:20
std::optional< uint256 > domain
Definition Book.h:21
virtual bool unsubBook(std::uint64_t uListener, Book const &)=0
virtual bool unsubValidations(std::uint64_t uListener)=0
virtual bool unsubServer(std::uint64_t uListener)=0
virtual bool unsubPeerStatus(std::uint64_t uListener)=0
virtual bool tryRemoveRpcSub(std::string const &strUrl)=0
virtual bool unsubConsensus(std::uint64_t uListener)=0
virtual bool unsubLedger(std::uint64_t uListener)=0
virtual pointer findRpcSub(std::string const &strUrl)=0
virtual bool unsubTransactions(std::uint64_t uListener)=0
virtual void unsubAccount(ref isplistener, hash_set< AccountID > const &vnaAccountIDs, bool realTime)=0
virtual bool unsubManifests(std::uint64_t uListener)=0
virtual void unsubAccountHistory(ref ispListener, AccountID const &account, bool historyOnly)=0
unsubscribe an account's transactions
virtual bool unsubRTTransactions(std::uint64_t uListener)=0
std::uint64_t getSeq()
Definition InfoSub.cpp:55
AccountID account
Definition Issue.h:17
Currency currency
Definition Issue.h:16
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:484
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:27
hash_set< AccountID > parseAccountIds(Json::Value const &jvArray)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
AccountID const & noAccount()
A placeholder for empty accounts.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
Json::Value doUnsubscribe(RPC::JsonContext &)
bool isConsistent(Book const &book)
Definition Book.cpp:10
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
@ rpcACT_MALFORMED
Definition ErrorCodes.h:71
@ rpcBAD_MARKET
Definition ErrorCodes.h:78
@ rpcDOMAIN_MALFORMED
Definition ErrorCodes.h:139
@ rpcDST_ISR_MALFORMED
Definition ErrorCodes.h:89
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:65
@ rpcSTREAM_MALFORMED
Definition ErrorCodes.h:107
@ rpcSRC_ISR_MALFORMED
Definition ErrorCodes.h:106
@ rpcDST_AMT_MALFORMED
Definition ErrorCodes.h:87
@ rpcSRC_CUR_MALFORMED
Definition ErrorCodes.h:105
@ rpcNO_PERMISSION
Definition ErrorCodes.h:34
Book reversed(Book const &book)
Definition Book.cpp:30
Json::Value rpcError(int iError)
Definition RPCErr.cpp:12
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Definition UintTypes.cpp:65
InfoSub::pointer infoSub
Definition Context.h:29
beast::Journal const j
Definition Context.h:21
NetworkOPs & netOps
Definition Context.h:24