rippled
RPCSub.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/net/RPCSub.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/json/to_string.h>
25 #include <ripple/net/RPCCall.h>
26 #include <deque>
27 
28 namespace ripple {
29 
30 // Subscription object for JSON-RPC
31 class RPCSubImp
32  : public RPCSub
33 {
34 public:
35  RPCSubImp (InfoSub::Source& source, boost::asio::io_service& io_service,
36  JobQueue& jobQueue, std::string const& strUrl, std::string const& strUsername,
37  std::string const& strPassword, Logs& logs)
38  : RPCSub (source)
39  , m_io_service (io_service)
40  , m_jobQueue (jobQueue)
41  , mUrl (strUrl)
42  , mSSL (false)
43  , mUsername (strUsername)
44  , mPassword (strPassword)
45  , mSending (false)
46  , j_ (logs.journal ("RPCSub"))
47  , logs_ (logs)
48  {
49  parsedURL pUrl;
50 
51  if (!parseUrl (pUrl, strUrl))
52  Throw<std::runtime_error> ("Failed to parse url.");
53  else if (pUrl.scheme == "https")
54  mSSL = true;
55  else if (pUrl.scheme != "http")
56  Throw<std::runtime_error> ("Only http and https is supported.");
57 
58  mSeq = 1;
59 
60  mIp = pUrl.domain;
61  mPort = (! pUrl.port) ? (mSSL ? 443 : 80) : *pUrl.port;
62  mPath = pUrl.path;
63 
64  JLOG (j_.info()) <<
65  "RPCCall::fromNetwork sub: ip=" << mIp <<
66  " port=" << mPort <<
67  " ssl= "<< (mSSL ? "yes" : "no") <<
68  " path='" << mPath << "'";
69  }
70 
71  ~RPCSubImp() = default;
72 
73  void send (Json::Value const& jvObj, bool broadcast) override
74  {
76 
77  if (mDeque.size () >= eventQueueMax)
78  {
79  // Drop the previous event.
80  JLOG (j_.warn()) << "RPCCall::fromNetwork drop";
81  mDeque.pop_back ();
82  }
83 
84  auto jm = broadcast ? j_.debug() : j_.info();
85  JLOG (jm) <<
86  "RPCCall::fromNetwork push: " << jvObj;
87 
88  mDeque.push_back (std::make_pair (mSeq++, jvObj));
89 
90  if (!mSending)
91  {
92  // Start a sending thread.
93  JLOG (j_.info()) << "RPCCall::fromNetwork start";
94 
96  jtCLIENT, "RPCSub::sendThread", [this] (Job&) {
97  sendThread();
98  });
99  }
100  }
101 
102  void setUsername (std::string const& strUsername) override
103  {
104  std::lock_guard sl (mLock);
105 
106  mUsername = strUsername;
107  }
108 
109  void setPassword (std::string const& strPassword) override
110  {
111  std::lock_guard sl (mLock);
112 
113  mPassword = strPassword;
114  }
115 
116 private:
117  // XXX Could probably create a bunch of send jobs in a single get of the lock.
118  void sendThread ()
119  {
120  Json::Value jvEvent;
121  bool bSend;
122 
123  do
124  {
125  {
126  // Obtain the lock to manipulate the queue and change sending.
127  std::lock_guard sl (mLock);
128 
129  if (mDeque.empty ())
130  {
131  mSending = false;
132  bSend = false;
133  }
134  else
135  {
136  auto const [seq, env] = mDeque.front ();
137 
138  mDeque.pop_front ();
139 
140  jvEvent = env;
141  jvEvent["seq"] = seq;
142 
143  bSend = true;
144  }
145  }
146 
147  // Send outside of the lock.
148  if (bSend)
149  {
150  // XXX Might not need this in a try.
151  try
152  {
153  JLOG (j_.info()) << "RPCCall::fromNetwork: " << mIp;
154 
156  m_io_service,
157  mIp, mPort,
159  mPath, "event",
160  jvEvent,
161  mSSL,
162  true,
163  logs_);
164  }
165  catch (const std::exception& e)
166  {
167  JLOG (j_.info()) << "RPCCall::fromNetwork exception: " << e.what ();
168  }
169  }
170  }
171  while (bSend);
172  }
173 
174 private:
175  enum
176  {
178  };
179 
180  boost::asio::io_service& m_io_service;
182 
186  bool mSSL;
190 
191  int mSeq; // Next id to allocate.
192 
193  bool mSending; // Sending threead is active.
194 
196 
199 };
200 
201 //------------------------------------------------------------------------------
202 
204  : InfoSub (source, Consumer())
205 {
206 }
207 
209  InfoSub::Source& source, boost::asio::io_service& io_service,
210  JobQueue& jobQueue, std::string const& strUrl,
211  std::string const& strUsername, std::string const& strPassword,
212  Logs& logs)
213 {
214  return std::make_shared<RPCSubImp> (std::ref (source),
215  std::ref (io_service), std::ref (jobQueue),
216  strUrl, strUsername, strPassword, logs);
217 }
218 
219 } // ripple
ripple::RPCSubImp::mDeque
std::deque< std::pair< int, Json::Value > > mDeque
Definition: RPCSub.cpp:195
ripple::RPCSubImp::mUrl
std::string mUrl
Definition: RPCSub.cpp:183
ripple::RPCSubImp::mPassword
std::string mPassword
Definition: RPCSub.cpp:188
ripple::RPCSub::RPCSub
RPCSub(InfoSub::Source &source)
Definition: RPCSub.cpp:203
std::string
STL class.
std::shared_ptr
STL class.
ripple::jtCLIENT
@ jtCLIENT
Definition: Job.h:49
ripple::RPCSub
Subscription object for JSON RPC.
Definition: RPCSub.h:31
std::exception
STL class.
ripple::Logs
Manages partitions for logging.
Definition: Log.h:49
ripple::parsedURL
Definition: StringUtilities.h:122
ripple::RPCSubImp::m_io_service
boost::asio::io_service & m_io_service
Definition: RPCSub.cpp:180
std::deque::pop_front
T pop_front(T... args)
ripple::RPCSubImp::mPath
std::string mPath
Definition: RPCSub.cpp:189
ripple::RPCSubImp::~RPCSubImp
~RPCSubImp()=default
ripple::InfoSub
Manages a client's subscription to data feeds.
Definition: InfoSub.h:40
ripple::RPCSubImp::mPort
std::uint16_t mPort
Definition: RPCSub.cpp:185
std::deque::size
T size(T... args)
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
std::lock_guard
STL class.
ripple::RPCSubImp::eventQueueMax
@ eventQueueMax
Definition: RPCSub.cpp:177
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:156
ripple::parsedURL::path
std::string path
Definition: StringUtilities.h:131
ripple::RPCSubImp::mSSL
bool mSSL
Definition: RPCSub.cpp:186
ripple::RPCSubImp::logs_
Logs & logs_
Definition: RPCSub.cpp:198
std::deque::front
T front(T... args)
ripple::RPCSubImp::setPassword
void setPassword(std::string const &strPassword) override
Definition: RPCSub.cpp:109
std::deque::push_back
T push_back(T... args)
ripple::RPCSubImp::setUsername
void setUsername(std::string const &strUsername) override
Definition: RPCSub.cpp:102
ripple::InfoSub::mLock
std::mutex mLock
Definition: InfoSub.h:153
ripple::RPCSubImp
Definition: RPCSub.cpp:31
ripple::RPCSubImp::send
void send(Json::Value const &jvObj, bool broadcast) override
Definition: RPCSub.cpp:73
ripple::RPCSubImp::mSeq
int mSeq
Definition: RPCSub.cpp:191
ripple::InfoSub::Source
Abstracts the source of subscription data.
Definition: InfoSub.h:58
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:53
beast::Journal::info
Stream info() const
Definition: Journal.h:297
ripple::Job
Definition: Job.h:83
deque
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
std::uint16_t
ripple::RPCSubImp::m_jobQueue
JobQueue & m_jobQueue
Definition: RPCSub.cpp:181
ripple::RPCSubImp::mSending
bool mSending
Definition: RPCSub.cpp:193
ripple::RPCSubImp::mIp
std::string mIp
Definition: RPCSub.cpp:184
std::deque::pop_back
T pop_back(T... args)
ripple::make_RPCSub
std::shared_ptr< RPCSub > make_RPCSub(InfoSub::Source &source, boost::asio::io_service &io_service, JobQueue &jobQueue, std::string const &strUrl, std::string const &strUsername, std::string const &strPassword, Logs &logs)
Definition: RPCSub.cpp:208
ripple::JobQueue
A pool of threads to perform work.
Definition: JobQueue.h:56
ripple::parsedURL::port
boost::optional< std::uint16_t > port
Definition: StringUtilities.h:130
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Resource::Consumer
An endpoint that consumes resources.
Definition: Consumer.h:33
ripple::RPCSubImp::mUsername
std::string mUsername
Definition: RPCSub.cpp:187
std::deque::empty
T empty(T... args)
ripple::parsedURL::scheme
std::string scheme
Definition: StringUtilities.h:126
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
std::make_pair
T make_pair(T... args)
ripple::parsedURL::domain
std::string domain
Definition: StringUtilities.h:129
ripple::RPCCall::fromNetwork
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1589
ripple::RPCSubImp::j_
const beast::Journal j_
Definition: RPCSub.cpp:197
ripple::RPCSubImp::RPCSubImp
RPCSubImp(InfoSub::Source &source, boost::asio::io_service &io_service, JobQueue &jobQueue, std::string const &strUrl, std::string const &strUsername, std::string const &strPassword, Logs &logs)
Definition: RPCSub.cpp:35
std::ref
T ref(T... args)
std::exception::what
T what(T... args)
ripple::RPCSubImp::sendThread
void sendThread()
Definition: RPCSub.cpp:118
Json::Value
Represents a JSON value.
Definition: json_value.h:141