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