Monero
Toggle main menu visibility
Loading...
Searching...
No Matches
contrib
epee
include
net
http_server_handlers_map2.h
Go to the documentation of this file.
1
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
// * Redistributions of source code must retain the above copyright
7
// notice, this list of conditions and the following disclaimer.
8
// * Redistributions in binary form must reproduce the above copyright
9
// notice, this list of conditions and the following disclaimer in the
10
// documentation and/or other materials provided with the distribution.
11
// * Neither the name of the Andrey N. Sabelnikov nor the
12
// names of its contributors may be used to endorse or promote products
13
// derived from this software without specific prior written permission.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
//
26
27
28
#pragma once
29
#include "
http_base.h
"
30
#include "
jsonrpc_structs.h
"
31
#include "
storages/portable_storage.h
"
32
#include "
storages/portable_storage_template_helper.h
"
33
34
#undef MONERO_DEFAULT_LOG_CATEGORY
35
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
36
37
38
#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \
39
epee::net_utils::http::http_response_info& response, \
40
context_type& m_conn_context) \
41
{\
42
MINFO("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \
43
response.m_response_code = 200; \
44
response.m_response_comment = "Ok"; \
45
try \
46
{ \
47
if(!handle_http_request_map(query_info, response, m_conn_context)) \
48
{response.m_response_code = 404;response.m_response_comment = "Not found";} \
49
} \
50
catch (const std::exception &e) \
51
{ \
52
MERROR(m_conn_context << "Exception in handle_http_request_map: " << e.what()); \
53
response.m_response_code = 500; \
54
response.m_response_comment = "Internal Server Error"; \
55
} \
56
return true; \
57
}
58
59
60
#define BEGIN_URI_MAP2() template<class t_context> bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \
61
epee::net_utils::http::http_response_info& response_info, \
62
t_context& m_conn_context) { \
63
bool handled = false; \
64
if(false) return true;
//just a stub to have "else if"
65
66
#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, &m_conn_context);
67
68
#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type)
//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
69
70
#define MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, cond) \
71
else if((query_info.m_URI == s_pattern) && (cond)) \
72
{ \
73
handled = true; \
74
uint64_t ticks = epee::misc_utils::get_tick_count(); \
75
boost::value_initialized<command_type::request> req; \
76
bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
77
if (!parse_res) \
78
{ \
79
MERROR("Failed to parse json: \r\n" << query_info.m_body); \
80
response_info.m_response_code = 400; \
81
response_info.m_response_comment = "Bad request"; \
82
return true; \
83
} \
84
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
85
boost::value_initialized<command_type::response> resp;\
86
MINFO(m_conn_context << "calling " << s_pattern); \
87
bool res = false; \
88
try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \
89
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
90
if (!res) \
91
{ \
92
response_info.m_response_code = 500; \
93
response_info.m_response_comment = "Internal Server Error"; \
94
return true; \
95
} \
96
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
97
epee::serialization::store_t_to_json(static_cast<command_type::response&>(resp), response_info.m_body); \
98
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
99
response_info.m_mime_tipe = "application/json"; \
100
response_info.m_header_info.m_content_type = " application/json"; \
101
MDEBUG( s_pattern << " processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \
102
}
103
104
#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, true)
105
106
#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \
107
else if(query_info.m_URI == s_pattern) \
108
{ \
109
handled = true; \
110
uint64_t ticks = epee::misc_utils::get_tick_count(); \
111
boost::value_initialized<command_type::request> req; \
112
bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), epee::strspan<uint8_t>(query_info.m_body)); \
113
if (!parse_res) \
114
{ \
115
MERROR("Failed to parse bin body data, body size=" << query_info.m_body.size()); \
116
response_info.m_response_code = 400; \
117
response_info.m_response_comment = "Bad request"; \
118
return true; \
119
} \
120
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
121
boost::value_initialized<command_type::response> resp;\
122
MINFO(m_conn_context << "calling " << s_pattern); \
123
bool res = false; \
124
try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \
125
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "()"); } \
126
if (!res) \
127
{ \
128
response_info.m_response_code = 500; \
129
response_info.m_response_comment = "Internal Server Error"; \
130
return true; \
131
} \
132
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
133
epee::byte_slice buffer; \
134
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), buffer, 64 * 1024); \
135
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
136
response_info.m_body.assign(reinterpret_cast<const char*>(buffer.data()), buffer.size()); \
137
response_info.m_mime_tipe = " application/octet-stream"; \
138
response_info.m_header_info.m_content_type = " application/octet-stream"; \
139
MDEBUG( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \
140
}
141
142
#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);handled = true;}
143
144
#define END_URI_MAP2() return handled;}
145
146
147
#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \
148
{ \
149
uint64_t ticks = epee::misc_utils::get_tick_count(); \
150
response_info.m_mime_tipe = "application/json"; \
151
epee::serialization::portable_storage ps; \
152
if(!ps.load_from_json(query_info.m_body)) \
153
{ \
154
boost::value_initialized<epee::json_rpc::error_response> rsp; \
155
static_cast<epee::json_rpc::error_response&>(rsp).jsonrpc = "2.0"; \
156
static_cast<epee::json_rpc::error_response&>(rsp).error.code = -32700; \
157
static_cast<epee::json_rpc::error_response&>(rsp).error.message = "Parse error"; \
158
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
159
return true; \
160
} \
161
epee::serialization::storage_entry id_; \
162
id_ = epee::serialization::storage_entry(std::string()); \
163
ps.get_value("id", id_, nullptr); \
164
std::string callback_name; \
165
if(!ps.get_value("method", callback_name, nullptr)) \
166
{ \
167
epee::json_rpc::error_response rsp; \
168
rsp.jsonrpc = "2.0"; \
169
rsp.error.code = -32600; \
170
rsp.error.message = "Invalid Request"; \
171
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
172
return true; \
173
} \
174
epee::serialization::storage_entry params_; \
175
params_ = epee::serialization::storage_entry(epee::serialization::section()); \
176
if(!ps.get_value("params", params_, nullptr)) \
177
{ \
178
epee::serialization::section params_section; \
179
ps.set_value("params", std::move(params_section), nullptr); \
180
} \
181
if(false) return true;
//just a stub to have "else if"
182
183
184
#define PREPARE_OBJECTS_FROM_JSON(command_type) \
185
handled = true; \
186
response_info.m_mime_tipe = "application/json"; \
187
boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \
188
epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\
189
if(!req.load(ps)) \
190
{ \
191
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
192
fail_resp.jsonrpc = "2.0"; \
193
fail_resp.id = req.id; \
194
fail_resp.error.code = -32602; \
195
fail_resp.error.message = "Invalid params"; \
196
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
197
return true; \
198
} \
199
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
200
boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \
201
epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(resp_); \
202
resp.jsonrpc = "2.0"; \
203
resp.id = req.id;
204
205
#define FINALIZE_OBJECTS_TO_JSON(method_name) \
206
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
207
epee::serialization::store_t_to_json(resp, response_info.m_body); \
208
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
209
response_info.m_mime_tipe = "application/json"; \
210
response_info.m_header_info.m_content_type = " application/json"; \
211
MDEBUG( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms");
212
213
#define MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, cond) \
214
else if((callback_name == method_name) && (cond)) \
215
{ \
216
PREPARE_OBJECTS_FROM_JSON(command_type) \
217
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
218
fail_resp.jsonrpc = "2.0"; \
219
fail_resp.id = req.id; \
220
MINFO(m_conn_context << "Calling RPC method " << method_name); \
221
bool res = false; \
222
try { res = callback_f(req.params, resp.result, fail_resp.error, &m_conn_context); } \
223
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
224
if (!res) \
225
{ \
226
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
227
return true; \
228
} \
229
FINALIZE_OBJECTS_TO_JSON(method_name) \
230
return true;\
231
}
232
233
#define MAP_JON_RPC_WE(method_name, callback_f, command_type) MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, true)
234
235
#define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \
236
else if(callback_name == method_name) \
237
{ \
238
PREPARE_OBJECTS_FROM_JSON(command_type) \
239
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
240
fail_resp.jsonrpc = "2.0"; \
241
fail_resp.id = req.id; \
242
MINFO(m_conn_context << "calling RPC method " << method_name); \
243
bool res = false; \
244
try { res = callback_f(req.params, resp.result, fail_resp.error, response_info, &m_conn_context); } \
245
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
246
if (!res) \
247
{ \
248
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
249
return true; \
250
} \
251
FINALIZE_OBJECTS_TO_JSON(method_name) \
252
return true;\
253
}
254
255
#define MAP_JON_RPC(method_name, callback_f, command_type) \
256
else if(callback_name == method_name) \
257
{ \
258
PREPARE_OBJECTS_FROM_JSON(command_type) \
259
MINFO(m_conn_context << "calling RPC method " << method_name); \
260
bool res = false; \
261
try { res = callback_f(req.params, resp.result, &m_conn_context); } \
262
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
263
if (!res) \
264
{ \
265
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
266
fail_resp.jsonrpc = "2.0"; \
267
fail_resp.id = req.id; \
268
fail_resp.error.code = -32603; \
269
fail_resp.error.message = "Internal error"; \
270
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
271
return true; \
272
} \
273
FINALIZE_OBJECTS_TO_JSON(method_name) \
274
return true;\
275
}
276
277
#define END_JSON_RPC_MAP() \
278
epee::json_rpc::error_response rsp; \
279
rsp.id = id_; \
280
rsp.jsonrpc = "2.0"; \
281
rsp.error.code = -32601; \
282
rsp.error.message = "Method not found"; \
283
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
284
return true; \
285
}
286
287
http_base.h
jsonrpc_structs.h
portable_storage.h
portable_storage_template_helper.h
Generated on
for Monero by
1.17.0