Electroneum
Loading...
Searching...
No Matches
message.cpp
Go to the documentation of this file.
1// Copyright (c) 2016-2019, The Monero Project
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification, are
6// permitted provided that the following conditions are met:
7//
8// 1. Redistributions of source code must retain the above copyright notice, this list of
9// conditions and the following disclaimer.
10//
11// 2. Redistributions in binary form must reproduce the above copyright notice, this list
12// of conditions and the following disclaimer in the documentation and/or other
13// materials provided with the distribution.
14//
15// 3. Neither the name of the copyright holder nor the names of its contributors may be
16// used to endorse or promote products derived from this software without specific
17// prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "message.h"
30#include "daemon_rpc_version.h"
32
33#include "rapidjson/writer.h"
35
36namespace cryptonote
37{
38
39namespace rpc
40{
41
42const char* Message::STATUS_OK = "OK";
43const char* Message::STATUS_RETRY = "Retry";
44const char* Message::STATUS_FAILED = "Failed";
45const char* Message::STATUS_BAD_REQUEST = "Invalid request type";
46const char* Message::STATUS_BAD_JSON = "Malformed json";
47
48namespace
49{
50constexpr const char error_field[] = "error";
51constexpr const char id_field[] = "id";
52constexpr const char method_field[] = "method";
53constexpr const char params_field[] = "params";
54constexpr const char result_field[] = "result";
55}
56
57rapidjson::Value Message::toJson(rapidjson::Document& doc) const
58{
59 rapidjson::Value val(rapidjson::kObjectType);
60
61 auto& al = doc.GetAllocator();
62
63 val.AddMember("status", rapidjson::StringRef(status.c_str()), al);
64 val.AddMember("error_details", rapidjson::StringRef(error_details.c_str()), al);
65 INSERT_INTO_JSON_OBJECT(val, doc, rpc_version, DAEMON_RPC_VERSION_ZMQ);
66
67 return val;
68}
69
76
77
78FullMessage::FullMessage(const std::string& request, Message* message)
79{
80 doc.SetObject();
81
82 doc.AddMember(method_field, rapidjson::StringRef(request.c_str()), doc.GetAllocator());
83 doc.AddMember(params_field, message->toJson(doc), doc.GetAllocator());
84
85 // required by JSON-RPC 2.0 spec
86 doc.AddMember("jsonrpc", rapidjson::Value("2.0"), doc.GetAllocator());
87}
88
90{
91 doc.SetObject();
92
93 // required by JSON-RPC 2.0 spec
94 doc.AddMember("jsonrpc", "2.0", doc.GetAllocator());
95
96 if (message->status == Message::STATUS_OK)
97 {
98 doc.AddMember(result_field, message->toJson(doc), doc.GetAllocator());
99 }
100 else
101 {
103
104 err.error_str = message->status;
105 err.message = message->error_details;
106
107 INSERT_INTO_JSON_OBJECT(doc, doc, error, err);
108 }
109}
110
111FullMessage::FullMessage(const std::string& json_string, bool request)
112{
113 doc.Parse(json_string.c_str());
114 if (doc.HasParseError() || !doc.IsObject())
115 {
116 throw cryptonote::json::PARSE_FAIL();
117 }
118
119 OBJECT_HAS_MEMBER_OR_THROW(doc, "jsonrpc")
120
121 if (request)
122 {
123 OBJECT_HAS_MEMBER_OR_THROW(doc, method_field)
124 OBJECT_HAS_MEMBER_OR_THROW(doc, params_field)
125 }
126 else
127 {
128 if (!doc.HasMember(result_field) && !doc.HasMember(error_field))
129 {
130 throw cryptonote::json::MISSING_KEY("error/result");
131 }
132 }
133}
134
136{
137
138 if (!doc.HasMember(id_field))
139 {
140 doc.AddMember(id_field, rapidjson::Value("unused"), doc.GetAllocator());
141 }
142
143 rapidjson::StringBuffer buf;
144
145 rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
146
147 doc.Accept(writer);
148
149 return std::string(buf.GetString(), buf.GetSize());
150}
151
153{
154 OBJECT_HAS_MEMBER_OR_THROW(doc, method_field)
155 return doc[method_field].GetString();
156}
157
158rapidjson::Value& FullMessage::getMessage()
159{
160 if (doc.HasMember(params_field))
161 {
162 return doc[params_field];
163 }
164 else if (doc.HasMember(result_field))
165 {
166 return doc[result_field];
167 }
168
169 //else
170 OBJECT_HAS_MEMBER_OR_THROW(doc, error_field)
171 return doc[error_field];
172
173}
174
176{
177 rapidjson::Value& val = getMessage();
178
179 return rapidjson::Value(val, doc.GetAllocator());
180}
181
182rapidjson::Value& FullMessage::getID()
183{
184 OBJECT_HAS_MEMBER_OR_THROW(doc, id_field)
185 return doc[id_field];
186}
187
188void FullMessage::setID(rapidjson::Value& id)
189{
190 auto itr = doc.FindMember(id_field);
191 if (itr != doc.MemberEnd())
192 {
193 itr->value = id;
194 }
195 else
196 {
197 doc.AddMember(id_field, id, doc.GetAllocator());
198 }
199}
200
202{
204 err.use = false;
205 if (doc.HasMember(error_field))
206 {
207 GET_FROM_JSON_OBJECT(doc, err, error);
208 err.use = true;
209 }
210
211 return err;
212}
213
215{
216 return FullMessage(request, message);
217}
218
219FullMessage FullMessage::requestMessage(const std::string& request, Message* message, rapidjson::Value& id)
220{
221 auto mes = requestMessage(request, message);
222 mes.setID(id);
223 return mes;
224}
225
230
232{
233 auto mes = responseMessage(message);
234 mes.setID(id);
235 return mes;
236}
237
239{
240 auto *full_message = new FullMessage();
241
242 auto& doc = full_message->doc;
243 auto& al = full_message->doc.GetAllocator();
244
245 doc.SetObject();
246
247 // required by JSON-RPC 2.0 spec
248 doc.AddMember("jsonrpc", "2.0", al);
249
251
252 err.error_str = "RPC request timed out.";
253 INSERT_INTO_JSON_OBJECT(doc, doc, err, err);
254
255 return full_message;
256}
257
258// convenience functions for bad input
259std::string BAD_REQUEST(const std::string& request)
260{
261 Message fail;
263 fail.error_details = std::string("\"") + request + "\" is not a valid request.";
264
265 FullMessage fail_response = FullMessage::responseMessage(&fail);
266
267 return fail_response.getJson();
268}
269
270std::string BAD_REQUEST(const std::string& request, rapidjson::Value& id)
271{
272 Message fail;
274 fail.error_details = std::string("\"") + request + "\" is not a valid request.";
275
276 FullMessage fail_response = FullMessage::responseMessage(&fail, id);
277
278 return fail_response.getJson();
279}
280
281std::string BAD_JSON(const std::string& error_details)
282{
283 Message fail;
285 fail.error_details = error_details;
286
287 FullMessage fail_response = FullMessage::responseMessage(&fail);
288
289 return fail_response.getJson();
290}
291
292
293} // namespace rpc
294
295} // namespace cryptonote
rapidjson::Value & getID()
Definition message.cpp:182
static FullMessage * timeoutMessage()
Definition message.cpp:238
FullMessage(FullMessage &&rhs) noexcept
Definition message.h:86
rapidjson::Value & getMessage()
Definition message.cpp:158
static FullMessage responseMessage(Message *message)
Definition message.cpp:226
rapidjson::Value getMessageCopy()
Definition message.cpp:175
std::string getRequestType() const
Definition message.cpp:152
static FullMessage requestMessage(const std::string &request, Message *message)
Definition message.cpp:214
cryptonote::rpc::error getError()
Definition message.cpp:201
void setID(rapidjson::Value &id)
Definition message.cpp:188
static const char * STATUS_FAILED
Definition message.h:64
static const char * STATUS_OK
Definition message.h:62
static const char * STATUS_BAD_JSON
Definition message.h:66
static const char * STATUS_RETRY
Definition message.h:63
virtual void fromJson(rapidjson::Value &val)
Definition message.cpp:70
std::string error_details
Definition message.h:77
virtual rapidjson::Value toJson(rapidjson::Document &doc) const
Definition message.cpp:57
static const char * STATUS_BAD_REQUEST
Definition message.h:65
std::string message("Message requiring signing")
#define GET_FROM_JSON_OBJECT(source, dst, key)
Definition json_object.h:52
#define OBJECT_HAS_MEMBER_OR_THROW(val, key)
Definition json_object.h:38
#define INSERT_INTO_JSON_OBJECT(jsonVal, doc, key, source)
Definition json_object.h:47
std::string BAD_REQUEST(const std::string &request)
Definition message.cpp:259
std::string BAD_JSON(const std::string &error_details)
Definition message.cpp:281
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
const char * buf