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