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#include <xrpl/basics/Log.h>
25#include <xrpl/protocol/ErrorCodes.h>
26#include <xrpl/protocol/RPCErr.h>
27#include <xrpl/protocol/jss.h>
28
29namespace ripple {
30
33{
34 InfoSub::pointer ispSub;
36 bool removeUrl{false};
37
38 if (!context.infoSub && !context.params.isMember(jss::url))
39 {
40 // Must be a JSON-RPC call.
42 }
43
44 if (context.params.isMember(jss::url))
45 {
46 if (context.role != Role::ADMIN)
48
49 std::string strUrl = context.params[jss::url].asString();
50 ispSub = context.netOps.findRpcSub(strUrl);
51 if (!ispSub)
52 return jvResult;
53 removeUrl = true;
54 }
55 else
56 {
57 ispSub = context.infoSub;
58 }
59
60 if (context.params.isMember(jss::streams))
61 {
62 if (!context.params[jss::streams].isArray())
64
65 for (auto& it : context.params[jss::streams])
66 {
67 if (!it.isString())
69
70 std::string streamName = it.asString();
71 if (streamName == "server")
72 {
73 context.netOps.unsubServer(ispSub->getSeq());
74 }
75 else if (streamName == "ledger")
76 {
77 context.netOps.unsubLedger(ispSub->getSeq());
78 }
79 else if (streamName == "manifests")
80 {
81 context.netOps.unsubManifests(ispSub->getSeq());
82 }
83 else if (streamName == "transactions")
84 {
85 context.netOps.unsubTransactions(ispSub->getSeq());
86 }
87 else if (
88 streamName == "transactions_proposed" ||
89 streamName == "rt_transactions") // DEPRECATED
90 {
91 context.netOps.unsubRTTransactions(ispSub->getSeq());
92 }
93 else if (streamName == "validations")
94 {
95 context.netOps.unsubValidations(ispSub->getSeq());
96 }
97 else if (streamName == "peer_status")
98 {
99 context.netOps.unsubPeerStatus(ispSub->getSeq());
100 }
101 else if (streamName == "consensus")
102 {
103 context.netOps.unsubConsensus(ispSub->getSeq());
104 }
105 else
106 {
108 }
109 }
110 }
111
112 auto accountsProposed = context.params.isMember(jss::accounts_proposed)
113 ? jss::accounts_proposed
114 : jss::rt_accounts; // DEPRECATED
115 if (context.params.isMember(accountsProposed))
116 {
117 if (!context.params[accountsProposed].isArray())
119
120 auto ids = RPC::parseAccountIds(context.params[accountsProposed]);
121 if (ids.empty())
123 context.netOps.unsubAccount(ispSub, ids, true);
124 }
125
126 if (context.params.isMember(jss::accounts))
127 {
128 if (!context.params[jss::accounts].isArray())
130
131 auto ids = RPC::parseAccountIds(context.params[jss::accounts]);
132 if (ids.empty())
134 context.netOps.unsubAccount(ispSub, ids, false);
135 }
136
137 if (context.params.isMember(jss::account_history_tx_stream))
138 {
139 auto const& req = context.params[jss::account_history_tx_stream];
140 if (!req.isMember(jss::account) || !req[jss::account].isString())
142
143 auto const id = parseBase58<AccountID>(req[jss::account].asString());
144 if (!id)
146
147 bool stopHistoryOnly = false;
148 if (req.isMember(jss::stop_history_tx_only))
149 {
150 if (!req[jss::stop_history_tx_only].isBool())
152 stopHistoryOnly = req[jss::stop_history_tx_only].asBool();
153 }
154 context.netOps.unsubAccountHistory(ispSub, *id, stopHistoryOnly);
155
156 JLOG(context.j.debug())
157 << "doUnsubscribe: account_history_tx_stream: " << toBase58(*id)
158 << " stopHistoryOnly=" << (stopHistoryOnly ? "true" : "false");
159 }
160
161 if (context.params.isMember(jss::books))
162 {
163 if (!context.params[jss::books].isArray())
165
166 for (auto& jv : context.params[jss::books])
167 {
168 if (!jv.isObject() || !jv.isMember(jss::taker_pays) ||
169 !jv.isMember(jss::taker_gets) ||
170 !jv[jss::taker_pays].isObjectOrNull() ||
171 !jv[jss::taker_gets].isObjectOrNull())
172 {
174 }
175
176 Json::Value taker_pays = jv[jss::taker_pays];
177 Json::Value taker_gets = jv[jss::taker_gets];
178
179 Book book;
180
181 // Parse mandatory currency.
182 if (!taker_pays.isMember(jss::currency) ||
184 book.in.currency, taker_pays[jss::currency].asString()))
185 {
186 JLOG(context.j.info()) << "Bad taker_pays currency.";
188 }
189 // Parse optional issuer.
190 else if (
191 ((taker_pays.isMember(jss::issuer)) &&
192 (!taker_pays[jss::issuer].isString() ||
193 !to_issuer(
194 book.in.account, taker_pays[jss::issuer].asString())))
195 // Don't allow illegal issuers.
196 || !isConsistent(book.in) || noAccount() == book.in.account)
197 {
198 JLOG(context.j.info()) << "Bad taker_pays issuer.";
199
201 }
202
203 // Parse mandatory currency.
204 if (!taker_gets.isMember(jss::currency) ||
206 book.out.currency, taker_gets[jss::currency].asString()))
207 {
208 JLOG(context.j.info()) << "Bad taker_gets currency.";
209
211 }
212 // Parse optional issuer.
213 else if (
214 ((taker_gets.isMember(jss::issuer)) &&
215 (!taker_gets[jss::issuer].isString() ||
216 !to_issuer(
217 book.out.account, taker_gets[jss::issuer].asString())))
218 // Don't allow illegal issuers.
219 || !isConsistent(book.out) || noAccount() == book.out.account)
220 {
221 JLOG(context.j.info()) << "Bad taker_gets issuer.";
222
224 }
225
226 if (book.in == book.out)
227 {
228 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
229 return rpcError(rpcBAD_MARKET);
230 }
231
232 context.netOps.unsubBook(ispSub->getSeq(), book);
233
234 // both_sides is deprecated.
235 if ((jv.isMember(jss::both) && jv[jss::both].asBool()) ||
236 (jv.isMember(jss::both_sides) && jv[jss::both_sides].asBool()))
237 {
238 context.netOps.unsubBook(ispSub->getSeq(), reversed(book));
239 }
240 }
241 }
242
243 if (removeUrl)
244 {
245 context.netOps.tryRemoveRpcSub(context.params[jss::url].asString());
246 }
247
248 return jvResult;
249}
250
251} // namespace ripple
Represents a JSON value.
Definition: json_value.h:147
bool isArray() const
bool isString() const
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:943
Stream debug() const
Definition: Journal.h:317
Stream info() const
Definition: Journal.h:323
Specifies an order book.
Definition: Book.h:34
Issue in
Definition: Book.h:36
Issue out
Definition: Book.h:37
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:75
AccountID account
Definition: Issue.h:39
Currency currency
Definition: Issue.h:38
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
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:177
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:106
Json::Value doUnsubscribe(RPC::JsonContext &)
Definition: Unsubscribe.cpp:32
bool isConsistent(Book const &book)
Definition: Book.cpp:25
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:184
@ 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:45
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:80
InfoSub::pointer infoSub
Definition: Context.h:49
beast::Journal const j
Definition: Context.h:41
NetworkOPs & netOps
Definition: Context.h:44
Json::Value params
Definition: Context.h:64