diff options
Diffstat (limited to 'contrib/epee/include/storages/levin_abstract_invoke2.h')
-rw-r--r-- | contrib/epee/include/storages/levin_abstract_invoke2.h | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h new file mode 100644 index 000000000..1b32c51d1 --- /dev/null +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -0,0 +1,289 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include "portable_storage_template_helper.h" +#include <boost/utility/value_init.hpp> +#include "net/levin_base.h" + +namespace epee +{ + namespace net_utils + { + template<class t_arg, class t_result, class t_transport> + bool invoke_remote_command2(int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) + { + if(!transport.is_connected()) + return false; + + serialization::portable_storage stg; + out_struct.store(stg); + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + + int res = transport.invoke(command, buff_to_send, buff_to_recv); + if( res <=0 ) + { + LOG_PRINT_RED("Failed to invoke command " << command << " return code " << res, LOG_LEVEL_1); + return false; + } + serialization::portable_storage stg_ret; + if(!stg_ret.load_from_binary(buff_to_recv)) + { + LOG_ERROR("Failed to load_from_binary on command " << command); + return false; + } + result_struct.load(stg_ret); + return true; + } + + template<class t_arg, class t_transport> + bool notify_remote_command2(int command, const t_arg& out_struct, t_transport& transport) + { + if(!transport.is_connected()) + return false; + + serialization::portable_storage stg; + out_struct.store(&stg); + std::string buff_to_send; + stg.store_to_binary(buff_to_send); + + int res = transport.notify(command, buff_to_send); + if(res <=0 ) + { + LOG_ERROR("Failed to notify command " << command << " return code " << res); + return false; + } + return true; + } + + template<class t_arg, class t_result, class t_transport> + bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) + { + + typename serialization::portable_storage stg; + out_struct.store(stg); + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + + int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id); + if( res <=0 ) + { + LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); + return false; + } + typename serialization::portable_storage stg_ret; + if(!stg_ret.load_from_binary(buff_to_recv)) + { + LOG_ERROR("Failed to load_from_binary on command " << command); + return false; + } + result_struct.load(stg_ret); + + return true; + } + + template<class t_result, class t_arg, class callback_t, class t_transport> + bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport, callback_t cb, size_t inv_timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) + { + typename serialization::portable_storage stg; + const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + int res = transport.invoke_async(command, buff_to_send, conn_id, [cb, command](int code, const std::string& buff, typename t_transport::connection_context& context)->bool + { + t_result result_struct = AUTO_VAL_INIT(result_struct); + if( code <=0 ) + { + LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code); + cb(code, result_struct, context); + return false; + } + serialization::portable_storage stg_ret; + if(!stg_ret.load_from_binary(buff)) + { + LOG_ERROR("Failed to load_from_binary on command " << command); + cb(LEVIN_ERROR_FORMAT, result_struct, context); + return false; + } + result_struct.load(stg_ret); + cb(code, result_struct, context); + return true; + }, inv_timeout); + if( res <=0 ) + { + LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); + return false; + } + return true; + } + + template<class t_arg, class t_transport> + bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport) + { + + serialization::portable_storage stg; + out_struct.store(stg); + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + + int res = transport.notify(command, buff_to_send, conn_id); + if(res <=0 ) + { + LOG_PRINT_RED_L0("Failed to notify command " << command << " return code " << res); + return false; + } + return true; + } + //---------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------- + template<class t_owner, class t_in_type, class t_out_type, class t_context, class callback_t> + int buff_to_t_adapter(int command, const std::string& in_buff, std::string& buff_out, callback_t cb, t_context& context ) + { + serialization::portable_storage strg; + if(!strg.load_from_binary(in_buff)) + { + LOG_ERROR("Failed to load_from_binary in command " << command); + return -1; + } + boost::value_initialized<t_in_type> in_struct; + boost::value_initialized<t_out_type> out_struct; + + static_cast<t_in_type&>(in_struct).load(strg); + int res = cb(command, static_cast<t_in_type&>(in_struct), static_cast<t_out_type&>(out_struct), context); + serialization::portable_storage strg_out; + static_cast<t_out_type&>(out_struct).store(strg_out); + + if(!strg_out.store_to_binary(buff_out)) + { + LOG_ERROR("Failed to store_to_binary in command" << command); + return -1; + } + + return res; + }; + + template<class t_owner, class t_in_type, class t_context, class callback_t> + int buff_to_t_adapter(t_owner* powner, int command, const std::string& in_buff, callback_t cb, t_context& context) + { + serialization::portable_storage strg; + if(!strg.load_from_binary(in_buff)) + { + LOG_ERROR("Failed to load_from_binary in notify " << command); + return -1; + } + boost::value_initialized<t_in_type> in_struct; + static_cast<t_in_type&>(in_struct).load(strg); + return cb(command, in_struct, context); + }; + +#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \ + int invoke(int command, const std::string& in_buff, std::string& buff_out, context_type& context) \ + { \ + bool handled = false; \ + return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ + } + +#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \ + int notify(int command, const std::string& in_buff, context_type& context) \ + { \ + bool handled = false; std::string fake_str;\ + return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ + } + + +#define CHAIN_LEVIN_INVOKE_MAP() \ + int invoke(int command, const std::string& in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ + { \ + bool handled = false; \ + return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ + } + +#define CHAIN_LEVIN_NOTIFY_MAP() \ + int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + { \ + bool handled = false; std::string fake_str;\ + return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ + } + +#define CHAIN_LEVIN_NOTIFY_STUB() \ + int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + { \ + return -1; \ + } + +#define BEGIN_INVOKE_MAP2(owner_type) \ + template <class t_context> int handle_invoke_map(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, t_context& context, bool& handled) \ + { \ + typedef owner_type internal_owner_type_name; + +#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \ + if(!is_notify && command_id == command) \ + {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, boost::bind(func, this, _1, _2, _3, _4), context);} + +#define HANDLE_INVOKE_T2(COMMAND, func) \ + if(!is_notify && COMMAND::ID == command) \ + {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, boost::bind(func, this, _1, _2, _3, _4), context);} + + +#define HANDLE_NOTIFY2(command_id, func, type_name_in) \ + if(is_notify && command_id == command) \ + {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} + +#define HANDLE_NOTIFY_T2(NOTIFY, func) \ + if(is_notify && NOTIFY::ID == command) \ + {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} + + +#define CHAIN_INVOKE_MAP2(func) \ + { \ + int res = func(is_notify, command, in_buff, buff_out, context, handled); \ + if(handled) \ + return res; \ + } + +#define CHAIN_INVOKE_MAP_TO_OBJ2(obj) \ + { \ + int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, context, handled); \ + if(handled) \ + return res; \ + } + +#define CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(obj, context_type) \ + { \ + int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, static_cast<context_type>(context), handled); \ + if(handled) return res; \ + } + + +#define END_INVOKE_MAP2() \ + LOG_ERROR("Unkonown command:" << command); \ + return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \ + } + } +} + |