rippled
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 <ripple/app/misc/NetworkOPs.h>
21 #include <ripple/basics/Log.h>
22 #include <ripple/net/RPCErr.h>
23 #include <ripple/protocol/ErrorCodes.h>
24 #include <ripple/protocol/jss.h>
25 #include <ripple/rpc/Context.h>
26 #include <ripple/rpc/impl/RPCHelpers.h>
27 #include <ripple/rpc/Role.h>
28 
29 namespace ripple {
30 
32 {
33 
34  InfoSub::pointer ispSub;
35  Json::Value jvResult (Json::objectValue);
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)
47  return rpcError(rpcNO_PERMISSION);
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())
63  return rpcError (rpcINVALID_PARAMS);
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 (streamName == "transactions_proposed"
88  || streamName == "rt_transactions") // DEPRECATED
89  {
90  context.netOps.unsubRTTransactions (ispSub->getSeq ());
91  }
92  else if (streamName == "validations")
93  {
94  context.netOps.unsubValidations (ispSub->getSeq ());
95  }
96  else if (streamName == "peer_status")
97  {
98  context.netOps.unsubPeerStatus (ispSub->getSeq ());
99  }
100  else if (streamName == "consensus")
101  {
102  context.netOps.unsubConsensus (ispSub->getSeq());
103  }
104  else
105  {
107  }
108  }
109  }
110 
111  auto accountsProposed = context.params.isMember(jss::accounts_proposed)
112  ? jss::accounts_proposed : jss::rt_accounts; // DEPRECATED
113  if (context.params.isMember(accountsProposed))
114  {
115  if (! context.params[accountsProposed].isArray())
116  return rpcError(rpcINVALID_PARAMS);
117 
118  auto ids = RPC::parseAccountIds(context.params[accountsProposed]);
119  if (ids.empty())
120  return rpcError(rpcACT_MALFORMED);
121  context.netOps.unsubAccount(ispSub, ids, true);
122  }
123 
124  if (context.params.isMember(jss::accounts))
125  {
126  if (! context.params[jss::accounts].isArray())
127  return rpcError(rpcINVALID_PARAMS);
128 
129  auto ids = RPC::parseAccountIds(context.params[jss::accounts]);
130  if (ids.empty())
131  return rpcError(rpcACT_MALFORMED);
132  context.netOps.unsubAccount(ispSub, ids, false);
133  }
134 
135  if (context.params.isMember(jss::books))
136  {
137  if (! context.params[jss::books].isArray())
138  return rpcError(rpcINVALID_PARAMS);
139 
140  for (auto& jv: context.params[jss::books])
141  {
142  if (! jv.isObject() ||
143  ! jv.isMember(jss::taker_pays) ||
144  ! jv.isMember(jss::taker_gets) ||
145  ! jv[jss::taker_pays].isObjectOrNull() ||
146  ! jv[jss::taker_gets].isObjectOrNull())
147  {
148  return rpcError(rpcINVALID_PARAMS);
149  }
150 
151  Json::Value taker_pays = jv[jss::taker_pays];
152  Json::Value taker_gets = jv[jss::taker_gets];
153 
154  Book book;
155 
156  // Parse mandatory currency.
157  if (!taker_pays.isMember (jss::currency)
158  || !to_currency (
159  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 (((taker_pays.isMember (jss::issuer))
166  && (!taker_pays[jss::issuer].isString ()
167  || !to_issuer (
168  book.in.account, taker_pays[jss::issuer].asString ())))
169  // Don't allow illegal issuers.
170  || !isConsistent (book.in)
171  || noAccount() == book.in.account)
172  {
173  JLOG (context.j.info()) << "Bad taker_pays issuer.";
174 
176  }
177 
178  // Parse mandatory currency.
179  if (!taker_gets.isMember (jss::currency)
180  || !to_currency (book.out.currency,
181  taker_gets[jss::currency].asString ()))
182  {
183  JLOG (context.j.info()) << "Bad taker_gets currency.";
184 
186  }
187  // Parse optional issuer.
188  else if (((taker_gets.isMember (jss::issuer))
189  && (!taker_gets[jss::issuer].isString ()
190  || !to_issuer (book.out.account,
191  taker_gets[jss::issuer].asString ())))
192  // Don't allow illegal issuers.
193  || !isConsistent (book.out)
194  || noAccount() == book.out.account)
195  {
196  JLOG (context.j.info()) << "Bad taker_gets issuer.";
197 
199  }
200 
201  if (book.in == book.out)
202  {
203  JLOG (context.j.info())
204  << "taker_gets same as taker_pays.";
205  return rpcError (rpcBAD_MARKET);
206  }
207 
208  context.netOps.unsubBook (ispSub->getSeq (), book);
209 
210  // both_sides is deprecated.
211  if ((jv.isMember(jss::both) && jv[jss::both].asBool()) ||
212  (jv.isMember(jss::both_sides) && jv[jss::both_sides].asBool()))
213  {
214  context.netOps.unsubBook(ispSub->getSeq(), reversed(book));
215  }
216  }
217  }
218 
219  if (removeUrl)
220  {
221  context.netOps.tryRemoveRpcSub(context.params[jss::url].asString ());
222  }
223 
224  return jvResult;
225 }
226 
227 } // ripple
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:67
ripple::RPC::Context::infoSub
InfoSub::pointer infoSub
Definition: Context.h:49
ripple::RPC::JsonContext
Definition: Context.h:52
ripple::rpcDST_AMT_MALFORMED
@ rpcDST_AMT_MALFORMED
Definition: ErrorCodes.h:107
std::string
STL class.
std::shared_ptr< InfoSub >
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:85
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1049
ripple::isConsistent
bool isConsistent(Book const &book)
Definition: Book.cpp:25
ripple::InfoSub::Source::unsubTransactions
virtual bool unsubTransactions(std::uint64_t uListener)=0
ripple::Book::out
Issue out
Definition: Book.h:36
ripple::InfoSub::Source::unsubConsensus
virtual bool unsubConsensus(std::uint64_t uListener)=0
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::RPC::Context::role
Role role
Definition: Context.h:47
ripple::InfoSub::Source::unsubValidations
virtual bool unsubValidations(std::uint64_t uListener)=0
ripple::RPC::Context::j
const beast::Journal j
Definition: Context.h:41
ripple::InfoSub::Source::findRpcSub
virtual pointer findRpcSub(std::string const &strUrl)=0
ripple::Role::ADMIN
@ ADMIN
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
ripple::InfoSub::Source::unsubBook
virtual bool unsubBook(std::uint64_t uListener, Book const &)=0
ripple::reversed
Book reversed(Book const &book)
Definition: Book.cpp:45
ripple::rpcSRC_ISR_MALFORMED
@ rpcSRC_ISR_MALFORMED
Definition: ErrorCodes.h:126
beast::Journal::info
Stream info() const
Definition: Journal.h:297
ripple::rpcSTREAM_MALFORMED
@ rpcSTREAM_MALFORMED
Definition: ErrorCodes.h:127
ripple::InfoSub::Source::unsubAccount
virtual void unsubAccount(ref isplistener, hash_set< AccountID > const &vnaAccountIDs, bool realTime)=0
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:961
ripple::rpcDST_ISR_MALFORMED
@ rpcDST_ISR_MALFORMED
Definition: ErrorCodes.h:109
ripple::InfoSub::Source::unsubRTTransactions
virtual bool unsubRTTransactions(std::uint64_t uListener)=0
ripple::InfoSub::Source::unsubPeerStatus
virtual bool unsubPeerStatus(std::uint64_t uListener)=0
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:28
ripple::RPC::Context::netOps
NetworkOPs & netOps
Definition: Context.h:44
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1056
ripple::InfoSub::Source::unsubServer
virtual bool unsubServer(std::uint64_t uListener)=0
ripple::doUnsubscribe
Json::Value doUnsubscribe(RPC::JsonContext &)
Definition: Unsubscribe.cpp:31
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::rpcACT_MALFORMED
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:91
ripple::InfoSub::getSeq
std::uint64_t getSeq()
Definition: InfoSub.cpp:85
ripple::InfoSub::Source::unsubManifests
virtual bool unsubManifests(std::uint64_t uListener)=0
ripple::rpcNO_PERMISSION
@ rpcNO_PERMISSION
Definition: ErrorCodes.h:54
ripple::InfoSub::Source::tryRemoveRpcSub
virtual bool tryRemoveRpcSub(std::string const &strUrl)=0
ripple::Book
Specifies an order book.
Definition: Book.h:32
ripple::rpcBAD_MARKET
@ rpcBAD_MARKET
Definition: ErrorCodes.h:98
ripple::rpcSRC_CUR_MALFORMED
@ rpcSRC_CUR_MALFORMED
Definition: ErrorCodes.h:125
ripple::RPC::parseAccountIds
hash_set< AccountID > parseAccountIds(Json::Value const &jvArray)
Definition: RPCHelpers.cpp:517
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:63
ripple::noAccount
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:156
ripple::Book::in
Issue in
Definition: Book.h:35
ripple::Issue::account
AccountID account
Definition: Issue.h:38
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::to_issuer
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:163
ripple::InfoSub::Source::unsubLedger
virtual bool unsubLedger(std::uint64_t uListener)=0
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482