rippled
Loading...
Searching...
No Matches
JSONRPCClient.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2016 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#include <test/jtx/JSONRPCClient.h>
20#include <xrpl/json/json_reader.h>
21#include <xrpl/json/to_string.h>
22#include <xrpl/protocol/jss.h>
23#include <xrpl/server/Port.h>
24#include <boost/asio.hpp>
25#include <boost/beast/http/dynamic_body.hpp>
26#include <boost/beast/http/message.hpp>
27#include <boost/beast/http/read.hpp>
28#include <boost/beast/http/string_body.hpp>
29#include <boost/beast/http/write.hpp>
30#include <string>
31
32namespace ripple {
33namespace test {
34
36{
37 static boost::asio::ip::tcp::endpoint
39 {
40 auto& log = std::cerr;
41 ParsedPort common;
42 parse_Port(common, cfg["server"], log);
43 for (auto const& name : cfg.section("server").values())
44 {
45 if (!cfg.exists(name))
46 continue;
47 ParsedPort pp;
48 parse_Port(pp, cfg[name], log);
49 if (pp.protocol.count("http") == 0)
50 continue;
51 using namespace boost::asio::ip;
52 if (pp.ip && pp.ip->is_unspecified())
53 *pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()}
54 : address{address_v4::loopback()};
55 return {*pp.ip, *pp.port};
56 }
57 Throw<std::runtime_error>("Missing HTTP port");
58 return {}; // Silence compiler control paths return value warning
59 }
60
61 template <class ConstBufferSequence>
62 static std::string
63 buffer_string(ConstBufferSequence const& b)
64 {
65 using namespace boost::asio;
67 s.resize(buffer_size(b));
68 buffer_copy(buffer(&s[0], s.size()), b);
69 return s;
70 }
71
72 boost::asio::ip::tcp::endpoint ep_;
73 boost::asio::io_service ios_;
74 boost::asio::ip::tcp::socket stream_;
75 boost::beast::multi_buffer bin_;
76 boost::beast::multi_buffer bout_;
77 unsigned rpc_version_;
78
79public:
80 explicit JSONRPCClient(Config const& cfg, unsigned rpc_version)
81 : ep_(getEndpoint(cfg)), stream_(ios_), rpc_version_(rpc_version)
82 {
83 stream_.connect(ep_);
84 }
85
86 ~JSONRPCClient() override
87 {
88 // stream_.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
89 // stream_.close();
90 }
91
92 /*
93 Return value is an Object type with up to three keys:
94 status
95 error
96 result
97 */
99 invoke(std::string const& cmd, Json::Value const& params) override
100 {
101 using namespace boost::beast::http;
102 using namespace boost::asio;
103 using namespace std::string_literals;
104
105 request<string_body> req;
106 req.method(boost::beast::http::verb::post);
107 req.target("/");
108 req.version(11);
109 req.insert("Content-Type", "application/json; charset=UTF-8");
110 {
112 ostr << ep_;
113 req.insert("Host", ostr.str());
114 }
115 {
116 Json::Value jr;
117 jr[jss::method] = cmd;
118 if (rpc_version_ == 2)
119 {
120 jr[jss::jsonrpc] = "2.0";
121 jr[jss::ripplerpc] = "2.0";
122 jr[jss::id] = 5;
123 }
124 if (params)
125 {
126 Json::Value& ja = jr[jss::params] = Json::arrayValue;
127 ja.append(params);
128 }
129 req.body() = to_string(jr);
130 }
131 req.prepare_payload();
132 write(stream_, req);
133
134 response<dynamic_body> res;
135 read(stream_, bin_, res);
136
137 Json::Reader jr;
138 Json::Value jv;
139 jr.parse(buffer_string(res.body().data()), jv);
140 if (jv["result"].isMember("error"))
141 jv["error"] = jv["result"]["error"];
142 if (jv["result"].isMember("status"))
143 jv["status"] = jv["result"]["status"];
144 return jv;
145 }
146
147 unsigned
148 version() const override
149 {
150 return rpc_version_;
151 }
152};
153
155makeJSONRPCClient(Config const& cfg, unsigned rpc_version)
156{
157 return std::make_unique<JSONRPCClient>(cfg, rpc_version);
158}
159
160} // namespace test
161} // namespace ripple
Unserialize a JSON document into a Value.
Definition: json_reader.h:37
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:73
Represents a JSON value.
Definition: json_value.h:147
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:891
Holds unparsed configuration information.
Definition: BasicConfig.h:216
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Section & section(std::string const &name)
Returns the section with the given name.
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:77
static boost::asio::ip::tcp::endpoint getEndpoint(BasicConfig const &cfg)
unsigned version() const override
Get RPC 1.0 or RPC 2.0.
boost::asio::ip::tcp::socket stream_
boost::asio::ip::tcp::endpoint ep_
boost::beast::multi_buffer bout_
JSONRPCClient(Config const &cfg, unsigned rpc_version)
Json::Value invoke(std::string const &cmd, Json::Value const &params) override
Submit a command synchronously.
static std::string buffer_string(ConstBufferSequence const &b)
boost::asio::io_service ios_
boost::beast::multi_buffer bin_
T count(T... args)
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
std::unique_ptr< AbstractClient > makeJSONRPCClient(Config const &cfg, unsigned rpc_version)
Returns a client using JSON-RPC over HTTP/S.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
void parse_Port(ParsedPort &port, Section const &section, std::ostream &log)
Definition: Port.cpp:199
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:629
T resize(T... args)
T size(T... args)
T str(T... args)
std::optional< std::uint16_t > port
Definition: Port.h:115
std::set< std::string, boost::beast::iless > protocol
Definition: Port.h:101
std::optional< boost::asio::ip::address > ip
Definition: Port.h:114