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 xrpl {
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 (streamName == "transactions_proposed" || streamName == "rt_transactions") // DEPRECATED
70 {
71 context.netOps.unsubRTTransactions(ispSub->getSeq());
72 }
73 else if (streamName == "validations")
74 {
75 context.netOps.unsubValidations(ispSub->getSeq());
76 }
77 else if (streamName == "peer_status")
78 {
79 context.netOps.unsubPeerStatus(ispSub->getSeq());
80 }
81 else if (streamName == "consensus")
82 {
83 context.netOps.unsubConsensus(ispSub->getSeq());
84 }
85 else
86 {
88 }
89 }
90 }
91
92 auto accountsProposed =
93 context.params.isMember(jss::accounts_proposed) ? jss::accounts_proposed : jss::rt_accounts; // DEPRECATED
94 if (context.params.isMember(accountsProposed))
95 {
96 if (!context.params[accountsProposed].isArray())
98
99 auto ids = RPC::parseAccountIds(context.params[accountsProposed]);
100 if (ids.empty())
102 context.netOps.unsubAccount(ispSub, ids, true);
103 }
104
105 if (context.params.isMember(jss::accounts))
106 {
107 if (!context.params[jss::accounts].isArray())
109
110 auto ids = RPC::parseAccountIds(context.params[jss::accounts]);
111 if (ids.empty())
113 context.netOps.unsubAccount(ispSub, ids, false);
114 }
115
116 if (context.params.isMember(jss::account_history_tx_stream))
117 {
118 auto const& req = context.params[jss::account_history_tx_stream];
119 if (!req.isMember(jss::account) || !req[jss::account].isString())
121
122 auto const id = parseBase58<AccountID>(req[jss::account].asString());
123 if (!id)
125
126 bool stopHistoryOnly = false;
127 if (req.isMember(jss::stop_history_tx_only))
128 {
129 if (!req[jss::stop_history_tx_only].isBool())
131 stopHistoryOnly = req[jss::stop_history_tx_only].asBool();
132 }
133 context.netOps.unsubAccountHistory(ispSub, *id, stopHistoryOnly);
134
135 JLOG(context.j.debug()) << "doUnsubscribe: account_history_tx_stream: " << toBase58(*id)
136 << " stopHistoryOnly=" << (stopHistoryOnly ? "true" : "false");
137 }
138
139 if (context.params.isMember(jss::books))
140 {
141 if (!context.params[jss::books].isArray())
143
144 for (auto& jv : context.params[jss::books])
145 {
146 if (!jv.isObject() || !jv.isMember(jss::taker_pays) || !jv.isMember(jss::taker_gets) ||
147 !jv[jss::taker_pays].isObjectOrNull() || !jv[jss::taker_gets].isObjectOrNull())
148 {
150 }
151
152 Json::Value taker_pays = jv[jss::taker_pays];
153 Json::Value taker_gets = jv[jss::taker_gets];
154
155 Book book;
156
157 // Parse mandatory currency.
158 if (!taker_pays.isMember(jss::currency) ||
159 !to_currency(book.in.currency, taker_pays[jss::currency].asString()))
160 {
161 JLOG(context.j.info()) << "Bad taker_pays currency.";
163 }
164 // Parse optional issuer.
165 else if (
166 ((taker_pays.isMember(jss::issuer)) &&
167 (!taker_pays[jss::issuer].isString() ||
168 !to_issuer(book.in.account, taker_pays[jss::issuer].asString())))
169 // Don't allow illegal issuers.
170 || !isConsistent(book.in) || noAccount() == book.in.account)
171 {
172 JLOG(context.j.info()) << "Bad taker_pays issuer.";
173
175 }
176
177 // Parse mandatory currency.
178 if (!taker_gets.isMember(jss::currency) ||
179 !to_currency(book.out.currency, taker_gets[jss::currency].asString()))
180 {
181 JLOG(context.j.info()) << "Bad taker_gets currency.";
182
184 }
185 // Parse optional issuer.
186 else if (
187 ((taker_gets.isMember(jss::issuer)) &&
188 (!taker_gets[jss::issuer].isString() ||
189 !to_issuer(book.out.account, taker_gets[jss::issuer].asString())))
190 // Don't allow illegal issuers.
191 || !isConsistent(book.out) || noAccount() == book.out.account)
192 {
193 JLOG(context.j.info()) << "Bad taker_gets issuer.";
194
196 }
197
198 if (book.in == book.out)
199 {
200 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
201 return rpcError(rpcBAD_MARKET);
202 }
203
204 if (jv.isMember(jss::domain))
205 {
206 uint256 domain;
207 if (!jv[jss::domain].isString() || !domain.parseHex(jv[jss::domain].asString()))
208 {
210 }
211 else
212 {
213 book.domain = domain;
214 }
215 }
216
217 context.netOps.unsubBook(ispSub->getSeq(), book);
218
219 // both_sides is deprecated.
220 if ((jv.isMember(jss::both) && jv[jss::both].asBool()) ||
221 (jv.isMember(jss::both_sides) && jv[jss::both_sides].asBool()))
222 {
223 context.netOps.unsubBook(ispSub->getSeq(), reversed(book));
224 }
225 }
226 }
227
228 if (removeUrl)
229 {
230 context.netOps.tryRemoveRpcSub(context.params[jss::url].asString());
231 }
232
233 return jvResult;
234}
235
236} // namespace xrpl
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:301
Stream info() const
Definition Journal.h:307
Specifies an order book.
Definition Book.h:17
Issue in
Definition Book.h:19
std::optional< uint256 > domain
Definition Book.h:21
Issue out
Definition Book.h:20
virtual bool unsubRTTransactions(std::uint64_t uListener)=0
virtual bool unsubConsensus(std::uint64_t uListener)=0
virtual bool unsubTransactions(std::uint64_t uListener)=0
virtual bool unsubServer(std::uint64_t uListener)=0
virtual bool tryRemoveRpcSub(std::string const &strUrl)=0
virtual void unsubAccountHistory(ref ispListener, AccountID const &account, bool historyOnly)=0
unsubscribe an account's transactions
virtual bool unsubLedger(std::uint64_t uListener)=0
virtual bool unsubBook(std::uint64_t uListener, Book const &)=0
virtual bool unsubPeerStatus(std::uint64_t uListener)=0
virtual bool unsubManifests(std::uint64_t uListener)=0
virtual bool unsubValidations(std::uint64_t uListener)=0
virtual pointer findRpcSub(std::string const &strUrl)=0
virtual void unsubAccount(ref isplistener, hash_set< AccountID > const &vnaAccountIDs, bool realTime)=0
std::uint64_t getSeq()
Definition InfoSub.cpp:54
Currency currency
Definition Issue.h:16
AccountID account
Definition Issue.h:17
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:472
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:27
hash_set< AccountID > parseAccountIds(Json::Value const &jvArray)
Parses an array of account IDs from a JSON value.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
bool isConsistent(Book const &book)
Definition Book.cpp:10
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:92
Book reversed(Book const &book)
Definition Book.cpp:29
Json::Value doUnsubscribe(RPC::JsonContext &)
Json::Value rpcError(error_code_i iError)
Definition RPCErr.cpp:12
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
AccountID const & noAccount()
A placeholder for empty accounts.
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Definition UintTypes.cpp:62
@ rpcSRC_CUR_MALFORMED
Definition ErrorCodes.h:105
@ rpcSTREAM_MALFORMED
Definition ErrorCodes.h:107
@ rpcNO_PERMISSION
Definition ErrorCodes.h:34
@ rpcBAD_MARKET
Definition ErrorCodes.h:78
@ rpcSRC_ISR_MALFORMED
Definition ErrorCodes.h:106
@ rpcDST_AMT_MALFORMED
Definition ErrorCodes.h:87
@ rpcDOMAIN_MALFORMED
Definition ErrorCodes.h:139
@ rpcDST_ISR_MALFORMED
Definition ErrorCodes.h:89
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:65
@ rpcACT_MALFORMED
Definition ErrorCodes.h:71
beast::Journal const j
Definition Context.h:21
InfoSub::pointer infoSub
Definition Context.h:29
NetworkOPs & netOps
Definition Context.h:24
Json::Value params
Definition Context.h:44