Electroneum
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"
34 #include "rapidjson/stringbuffer.h"
35 
36 namespace cryptonote
37 {
38 
39 namespace rpc
40 {
41 
42 const char* Message::STATUS_OK = "OK";
43 const char* Message::STATUS_RETRY = "Retry";
44 const char* Message::STATUS_FAILED = "Failed";
45 const char* Message::STATUS_BAD_REQUEST = "Invalid request type";
46 const char* Message::STATUS_BAD_JSON = "Malformed json";
47 
48 namespace
49 {
50 constexpr const char error_field[] = "error";
51 constexpr const char id_field[] = "id";
52 constexpr const char method_field[] = "method";
53 constexpr const char params_field[] = "params";
54 constexpr const char result_field[] = "result";
55 }
56 
58 {
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 
71 {
75 }
76 
77 
78 FullMessage::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 
89 FullMessage::FullMessage(Message* message)
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 
111 FullMessage::FullMessage(const std::string& json_string, bool request)
112 {
113  doc.Parse(json_string.c_str());
114  if (doc.HasParseError() || !doc.IsObject())
115  {
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 
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 
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 
183 {
184  OBJECT_HAS_MEMBER_OR_THROW(doc, id_field)
185  return doc[id_field];
186 }
187 
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 
220 {
221  auto mes = requestMessage(request, message);
222  mes.setID(id);
223  return mes;
224 }
225 
227 {
228  return FullMessage(message);
229 }
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
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 
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 
281 std::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
#define INSERT_INTO_JSON_OBJECT(jsonVal, doc, key, source)
Definition: json_object.h:47
std::string error_details
Definition: message.h:77
static const char * STATUS_BAD_JSON
Definition: message.h:66
std::string status
Definition: message.h:76
object
Definition: rapidjson.h:624
::std::string string
Definition: gtest-port.h:1097
std::string BAD_REQUEST(const std::string &request)
Definition: message.cpp:259
virtual rapidjson::Value toJson(rapidjson::Document &doc) const
Definition: message.cpp:57
#define GET_FROM_JSON_OBJECT(source, dst, key)
Definition: json_object.h:52
static const char * STATUS_FAILED
Definition: message.h:64
rapidjson::Value & getID()
Definition: message.cpp:182
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
std::string getRequestType() const
Definition: message.cpp:152
static const char * STATUS_BAD_REQUEST
Definition: message.h:65
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2116
#define OBJECT_HAS_MEMBER_OR_THROW(val, key)
Definition: json_object.h:38
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
Definition: document.h:2512
virtual void fromJson(rapidjson::Value &val)
Definition: message.cpp:70
GenericStringBuffer< UTF8< char >, CrtAllocator > StringBuffer
Definition: fwd.h:59
static FullMessage requestMessage(const std::string &request, Message *message)
Definition: message.cpp:214
static FullMessage * timeoutMessage()
Definition: message.cpp:238
const char * buf
Definition: slow_memmem.cpp:74
std::string message("Message requiring signing")
static const char * STATUS_RETRY
Definition: message.h:63
GenericStringRef< CharType > StringRef(const CharType *str)
Mark a character pointer as constant string.
Definition: document.h:361
cryptonote::rpc::error getError()
Definition: message.cpp:201
static FullMessage responseMessage(Message *message)
Definition: message.cpp:226
void setID(rapidjson::Value &id)
Definition: message.cpp:188
rapidjson::Value & getMessage()
Definition: message.cpp:158
static const char * STATUS_OK
Definition: message.h:62
error
Tracks LMDB error codes.
Definition: error.h:44
rapidjson::Value getMessageCopy()
Definition: message.cpp:175
std::string BAD_JSON(const std::string &error_details)
Definition: message.cpp:281