Electroneum
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 
38 namespace 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  {
115  typename serialization::portable_storage stg;
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 
const char * res
Definition: hmac_keccak.cpp:41
#define MERROR(x)
Definition: misc_log_ex.h:73
#define LEVIN_ERROR_FORMAT
Definition: levin_base.h:100
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
boost::uuids::uuid uuid
::std::string string
Definition: gtest-port.h:1097
bool notify_remote_command2(int command, const t_arg &out_struct, t_transport &transport)
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
bool load_from_binary(const epee::span< const uint8_t > target)
bool invoke_remote_command2(int command, const t_arg &out_struct, t_result &result_struct, t_transport &transport)
std::unique_ptr< void, terminate > context
Unique ZMQ context handle, calls zmq_term on destruction.
Definition: zmq.h:98
void load(Archive &a, std::unordered_map< h_key, hval > &x, const boost::serialization::version_type ver)
#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 store_to_binary(binarybuffer &target)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
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)
#define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED
Definition: levin_base.h:70
std::shared_ptr< Transport > transport(const std::string &path)
Definition: transport.cpp:1204