Electroneum
Loading...
Searching...
No Matches
levin_abstract_invoke2.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#pragma once
28
30#include <boost/utility/value_init.hpp>
31#include <functional>
32#include "span.h"
33#include "net/levin_base.h"
34
35#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
36#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "net"
37
38namespace epee
39{
40 namespace net_utils
41 {
42 template<class t_arg, class t_result, class t_transport>
43 bool invoke_remote_command2(int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport)
44 {
45 if(!transport.is_connected())
46 return false;
47
49 out_struct.store(stg);
50 std::string buff_to_send, buff_to_recv;
51 stg.store_to_binary(buff_to_send);
52
53 int res = transport.invoke(command, buff_to_send, buff_to_recv);
54 if( res <=0 )
55 {
56 MERROR("Failed to invoke command " << command << " return code " << res);
57 return false;
58 }
60 if(!stg_ret.load_from_binary(buff_to_recv))
61 {
62 LOG_ERROR("Failed to load_from_binary on command " << command);
63 return false;
64 }
65 return result_struct.load(stg_ret);
66 }
67
68 template<class t_arg, class t_transport>
69 bool notify_remote_command2(int command, const t_arg& out_struct, t_transport& transport)
70 {
71 if(!transport.is_connected())
72 return false;
73
75 out_struct.store(&stg);
76 std::string buff_to_send;
77 stg.store_to_binary(buff_to_send);
78
79 int res = transport.notify(command, buff_to_send);
80 if(res <=0 )
81 {
82 LOG_ERROR("Failed to notify command " << command << " return code " << res);
83 return false;
84 }
85 return true;
86 }
87
88 template<class t_arg, class t_result, class t_transport>
89 bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport)
90 {
91
93 out_struct.store(stg);
94 std::string buff_to_send, buff_to_recv;
95 stg.store_to_binary(buff_to_send);
96
97 int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id);
98 if( res <=0 )
99 {
100 LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res);
101 return false;
102 }
103 typename serialization::portable_storage stg_ret;
104 if(!stg_ret.load_from_binary(buff_to_recv))
105 {
106 LOG_ERROR("Failed to load_from_binary on command " << command);
107 return false;
108 }
109 return result_struct.load(stg_ret);
110 }
111
112 template<class t_result, class t_arg, class callback_t, class t_transport>
113 bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport, const callback_t &cb, size_t inv_timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
114 {
116 const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation
117 std::string buff_to_send;
118 stg.store_to_binary(buff_to_send);
119 int res = transport.invoke_async(command, epee::strspan<uint8_t>(buff_to_send), conn_id, [cb, command](int code, const epee::span<const uint8_t> buff, typename t_transport::connection_context& context)->bool
120 {
121 t_result result_struct = AUTO_VAL_INIT(result_struct);
122 if( code <=0 )
123 {
124 LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code);
125 cb(code, result_struct, context);
126 return false;
127 }
129 if(!stg_ret.load_from_binary(buff))
130 {
131 LOG_ERROR("Failed to load_from_binary on command " << command);
132 cb(LEVIN_ERROR_FORMAT, result_struct, context);
133 return false;
134 }
135 if (!result_struct.load(stg_ret))
136 {
137 LOG_ERROR("Failed to load result struct on command " << command);
138 cb(LEVIN_ERROR_FORMAT, result_struct, context);
139 return false;
140 }
141 cb(code, result_struct, context);
142 return true;
143 }, inv_timeout);
144 if( res <=0 )
145 {
146 LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res);
147 return false;
148 }
149 return true;
150 }
151
152 template<class t_arg, class t_transport>
153 bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport)
154 {
155
157 out_struct.store(stg);
158 std::string buff_to_send;
159 stg.store_to_binary(buff_to_send);
160
161 int res = transport.notify(command, epee::strspan<uint8_t>(buff_to_send), conn_id);
162 if(res <=0 )
163 {
164 MERROR("Failed to notify command " << command << " return code " << res);
165 return false;
166 }
167 return true;
168 }
169 //----------------------------------------------------------------------------------------------------
170 //----------------------------------------------------------------------------------------------------
171 template<class t_owner, class t_in_type, class t_out_type, class t_context, class callback_t>
172 int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, callback_t cb, t_context& context )
173 {
175 if(!strg.load_from_binary(in_buff))
176 {
177 LOG_ERROR("Failed to load_from_binary in command " << command);
178 return -1;
179 }
180 boost::value_initialized<t_in_type> in_struct;
181 boost::value_initialized<t_out_type> out_struct;
182
183 if (!static_cast<t_in_type&>(in_struct).load(strg))
184 {
185 LOG_ERROR("Failed to load in_struct in command " << command);
186 return -1;
187 }
188 int res = cb(command, static_cast<t_in_type&>(in_struct), static_cast<t_out_type&>(out_struct), context);
190 static_cast<t_out_type&>(out_struct).store(strg_out);
191
192 if(!strg_out.store_to_binary(buff_out))
193 {
194 LOG_ERROR("Failed to store_to_binary in command" << command);
195 return -1;
196 }
197
198 return res;
199 }
200
201 template<class t_owner, class t_in_type, class t_context, class callback_t>
202 int buff_to_t_adapter(t_owner* powner, int command, const epee::span<const uint8_t> in_buff, callback_t cb, t_context& context)
203 {
205 if(!strg.load_from_binary(in_buff))
206 {
207 LOG_ERROR("Failed to load_from_binary in notify " << command);
208 return -1;
209 }
210 boost::value_initialized<t_in_type> in_struct;
211 if (!static_cast<t_in_type&>(in_struct).load(strg))
212 {
213 LOG_ERROR("Failed to load in_struct in notify " << command);
214 return -1;
215 }
216 return cb(command, in_struct, context);
217 }
218
219#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \
220 int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, context_type& context) \
221 { \
222 bool handled = false; \
223 return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
224 }
225
226#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \
227 int notify(int command, const epee::span<const uint8_t> in_buff, context_type& context) \
228 { \
229 bool handled = false; std::string fake_str;\
230 return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
231 }
232
233
234#define CHAIN_LEVIN_INVOKE_MAP() \
235 int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \
236 { \
237 bool handled = false; \
238 return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
239 }
240
241#define CHAIN_LEVIN_NOTIFY_MAP() \
242 int notify(int command, const epee::span<const uint8_t> in_buff, epee::net_utils::connection_context_base& context) \
243 { \
244 bool handled = false; std::string fake_str;\
245 return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
246 }
247
248#define CHAIN_LEVIN_NOTIFY_STUB() \
249 int notify(int command, const epee::span<const uint8_t> in_buff, epee::net_utils::connection_context_base& context) \
250 { \
251 return -1; \
252 }
253
254#define BEGIN_INVOKE_MAP2(owner_type) \
255 template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_context& context, bool& handled) \
256 { \
257 typedef owner_type internal_owner_type_name;
258
259#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \
260 if(!is_notify && command_id == command) \
261 {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in, typename_out>(this, command, in_buff, buff_out, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), context);}
262
263#define HANDLE_INVOKE_T2(COMMAND, func) \
264 if(!is_notify && COMMAND::ID == command) \
265 {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename COMMAND::request, typename COMMAND::response>(command, in_buff, buff_out, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), context);}
266
267
268#define HANDLE_NOTIFY2(command_id, func, type_name_in) \
269 if(is_notify && command_id == command) \
270 {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in>(this, command, in_buff, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), context);}
271
272#define HANDLE_NOTIFY_T2(NOTIFY, func) \
273 if(is_notify && NOTIFY::ID == command) \
274 {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), context);}
275
276
277#define CHAIN_INVOKE_MAP2(func) \
278 { \
279 int res = func(is_notify, command, in_buff, buff_out, context, handled); \
280 if(handled) \
281 return res; \
282 }
283
284#define CHAIN_INVOKE_MAP_TO_OBJ2(obj) \
285 { \
286 int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, context, handled); \
287 if(handled) \
288 return res; \
289 }
290
291#define CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(obj, context_type) \
292 { \
293 int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, static_cast<context_type>(context), handled); \
294 if(handled) return res; \
295 }
296
297
298#define END_INVOKE_MAP2() \
299 LOG_ERROR("Unknown command:" << command); \
300 return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \
301 }
302 }
303}
304
bool store_to_binary(binarybuffer &target)
bool load_from_binary(const epee::span< const uint8_t > target)
Non-owning sequence of data. Does not deep copy.
Definition span.h:57
const char * res
#define LEVIN_ERROR_FORMAT
Definition levin_base.h:100
#define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED
Definition levin_base.h:70
#define AUTO_VAL_INIT(v)
#define MERROR(x)
Definition misc_log_ex.h:73
#define LOG_PRINT_L1(x)
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
int buff_to_t_adapter(int command, const epee::span< const uint8_t > in_buff, std::string &buff_out, callback_t cb, t_context &context)
bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg &out_struct, t_transport &transport, const callback_t &cb, size_t inv_timeout=LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
bool invoke_remote_command2(int command, const t_arg &out_struct, t_result &result_struct, t_transport &transport)
bool notify_remote_command2(int command, const t_arg &out_struct, t_transport &transport)
span< const T > strspan(const std::string &s) noexcept
make a span from a std::string
Definition span.h:171