From 319276845adb4e32d7fda1e9ec72df7c6b1b93a8 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 20 Nov 2024 12:23:50 +0300 Subject: [PATCH] ... --- net/adc_device_netclient.h | 149 ++++++++++++++++++++----------------- net/adc_device_netmsg.h | 79 ++++++++++++-------- 2 files changed, 127 insertions(+), 101 deletions(-) diff --git a/net/adc_device_netclient.h b/net/adc_device_netclient.h index cf94990..91f117e 100644 --- a/net/adc_device_netclient.h +++ b/net/adc_device_netclient.h @@ -98,6 +98,11 @@ public: typedef SessionIdentT netsession_ident_t; typedef NetServiceT netservice_t; + // default server respond type + typedef std::vector default_server_resp_t; + // asynchronous callback callable type for ADC device getter/setter/executor + typedef std::function async_callback_func_t; + struct netsession_ctx_t { AdcDeviceNetClient* clientPtr; std::chrono::milliseconds recvTimeout; @@ -147,21 +152,14 @@ public: // ADC device helper methods (blocking) - typedef std::vector default_server_resp_t; // get names of devices template R deviceNames(ServerResponseType& rtype) { - typename netservice_t::send_msg_t bytes; - - AdcDeviceProtoMessage msg(bytes); - msg.names(); - using m_t = std::remove_cvref_t; - // expected respond: ACK NAMES DEV1 DEV2 ... // return DEV1 DEV2 ... (or error description 'code category what') - return _getFromServer(m_t::NAMES_KEY, bytes, rtype); + return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, rtype); } default_server_resp_t deviceNames(ServerResponseType& rtype) @@ -173,15 +171,10 @@ public: template R bindDevice(DevNameT&& dev_name, ServerResponseType& rtype) { - typename netservice_t::send_msg_t bytes; - - AdcDeviceProtoMessage msg(bytes); - msg.device(std::forward(dev_name)); - using m_t = std::remove_cvref_t; - // expected respond: ACK DEVICE DEV_NAME // return DEV_NAME ... (or error description 'code category what') - return _getFromServer(m_t::DEVICE_KEY, bytes, rtype); + return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, rtype, + std::forward(dev_name)); } template @@ -195,16 +188,9 @@ public: template R exec(CmdNameT&& cmd_name, ServerResponseType& rtype) { - typename netservice_t::send_msg_t bytes; - - AdcDeviceProtoMessage msg(bytes); - msg.cmd(std::forward(cmd_name)); - using m_t = std::remove_cvref_t; - - // expected respond: ACK CMD CMD_NAME // return CMD_NAME ... (or error description 'code category what') - return _getFromServer(m_t::CMD_KEY, bytes, rtype); + return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_CMD, rtype, std::forward(cmd_name)); } template @@ -218,15 +204,10 @@ public: template R getAttr(AttrNameT&& attr_name, ServerResponseType& rtype) { - typename netservice_t::send_msg_t bytes; - - AdcDeviceProtoMessage msg(bytes); - msg.get(std::forward(attr_name)); - using m_t = std::remove_cvref_t; - // expected respond: ACK GET ATTR_NAME ATTR_VALUE // return ATTR_NAME ATTR_VALUE (or error description 'code category what') - return _getFromServer(m_t::GET_KEY, bytes, rtype); + return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_GET, rtype, + std::forward(attr_name)); } template @@ -243,15 +224,10 @@ public: typename... ValueTs> R setAttr(AttrNameT&& attr_name, ServerResponseType& rtype, ValueT&& value, ValueTs&&... values) { - typename netservice_t::send_msg_t bytes; - - AdcDeviceProtoMessage msg(bytes); - msg.set(std::forward(attr_name), std::forward(value), std::forward(values)...); - using m_t = std::remove_cvref_t; - // expected respond: ACK SET ATTR_NAME ATTR_VALUE // return ATTR_NAME ATTR_VALUE (or error description 'code category what') - return _getFromServer(m_t::SET_KEY, bytes, rtype); + return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_SET, rtype, std::forward(value), + std::forward(values)...); } template @@ -264,6 +240,23 @@ public: std::forward(value), std::forward(values)...); } + // ADC device helper methods (asynchronous) + + // get device names + + template CallbackT> + auto asyncDeviceNames(CallbackT&& callback_func) + { + return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, + std::forward(callback_func)); + } + + template CallbackT> + auto asyncBindDevice(DevNameT&& dev_name, CallbackT&& callback_func) + { + return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, + std::forward(callback_func), std::forward(dev_name)); + } protected: netsession_ident_t _ident; @@ -279,12 +272,10 @@ public: // helper methods - template - R _getFromServer(std::string_view key, const typename netservice_t::send_msg_t& bytes, ServerResponseType& type) + R checkServerRespond(std::string_view key, const auto& bytes, ServerResponseType& type) const { - auto rbytes = sendRecv(bytes); - AdcDeviceProtoMessage dev_msg(rbytes); + AdcDeviceProtoMessage dev_msg(bytes); if (!dev_msg.isValid()) { throw std::system_error(AdcDeviceNetClientSessionError::ERROR_INVALID_SERVER_RESPOND); @@ -301,32 +292,59 @@ public: } } - - void _sendRecvCallbackWrapper(auto err, - typename netservice_t::recv_msg_t msg, - auto&& ack_func, - auto&& error_func) + template + R getFromServer(std::string_view key, const typename netservice_t::send_msg_t& bytes, ServerResponseType& type) { - if (err) { - _clientPtr->logError("An error occured while receiving server respond: {}", - netservice_t::formattableError(err)); - } else { - AdcDeviceProtoMessage dev_msg(msg); + auto rbytes = sendRecv(bytes); - if (!dev_msg.isValid()) { - _clientPtr->logError("Invalid server respond"); - return; - } + return checkServerRespond(key, rbytes, type); + } - if (dev_msg.isACK()) { - std::forward(ack_func)(dev_msg.attrs()); - } else if (dev_msg.isERROR()) { - std::forward(error_func)(dev_msg.attrs()); + template + R deviceFuncHelper(std::string_view key, ServerResponseType& rtype, ArgTs&&... args) + { + typename netservice_t::send_msg_t bytes; + + AdcDeviceProtoMessage msg(bytes); + msg.setKeyValue(key, std::forward(args)...); + + return getFromServer(key, bytes, rtype); + } + + + template CallbackT, typename... ArgTs> + auto asyncDeviceFuncHelper(std::string_view key, CallbackT&& callback_func, ArgTs&&... args) + { + auto bytes = std::shared_ptr(); + + AdcDeviceProtoMessage msg(*bytes); + msg.setKeyValue(key, std::forward(args)...); + + asyncSendRecv(*bytes, [bytes, key, wrapper = traits::adc_pf_wrapper(std::forward(callback_func)), + this](auto err, auto rmsg) mutable { + if (err) { + _clientPtr->logError("An error occured while receiving server respond: {}", + netservice_t::formattableError(err)); } else { - _clientPtr->logError("Unexpectable server respond (msg key: {})", dev_msg.key()); + try { + ServerResponseType type; + auto attrs = checkServerRespond(key, rmsg, type); + + std::forward(std::get<0>(wrapper))(type, attrs); + + } catch (const std::system_error& err) { + _clientPtr->logError("An error occured while getting server respond: {}", err.what()); + } } - } - }; + }); + } + + template + auto sendRecv(const SendMsgT& send_msg) + { + _netService.send(send_msg, _sendTimeout); + return _netService.receive(_recvTimeout); + } template auto asyncSendRecv(const SendMsgT& send_msg, TokenT&& token) @@ -344,13 +362,6 @@ public: _sendTimeout); } - template - auto sendRecv(const SendMsgT& send_msg) - { - _netService.send(send_msg, _sendTimeout); - return _netService.receive(_recvTimeout); - } - }; // end of 'Session' class declaration using base_t::base_t; diff --git a/net/adc_device_netmsg.h b/net/adc_device_netmsg.h index 36aa2ee..2e2f93d 100644 --- a/net/adc_device_netmsg.h +++ b/net/adc_device_netmsg.h @@ -291,6 +291,27 @@ protected: }; +/* ADC client-server network protocol definitions */ + +namespace constants +{ + +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_ACK{"ACK"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_SET{"SET"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_GET{"GET"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_CMD{"CMD"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_ERR{"ERR"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_HELLO{"HELLO"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_DEVICE{"DEVICE"}; +static constexpr std::string_view ADC_DEVICE_NETPROTO_KEY_NAMES{"NAMES"}; + +static constexpr std::array ADC_DEVICE_NETPROTO_VALID_KEY{ + ADC_DEVICE_NETPROTO_KEY_ACK, ADC_DEVICE_NETPROTO_KEY_SET, ADC_DEVICE_NETPROTO_KEY_GET, + ADC_DEVICE_NETPROTO_KEY_CMD, ADC_DEVICE_NETPROTO_KEY_ERR, ADC_DEVICE_NETPROTO_KEY_HELLO, + ADC_DEVICE_NETPROTO_KEY_DEVICE, ADC_DEVICE_NETPROTO_KEY_NAMES}; + +} // namespace constants + template ; public: - static constexpr std::string_view ACK_KEY{"ACK"}; - static constexpr std::string_view SET_KEY{"SET"}; - static constexpr std::string_view GET_KEY{"GET"}; - static constexpr std::string_view CMD_KEY{"CMD"}; - static constexpr std::string_view ERR_KEY{"ERR"}; - static constexpr std::string_view HELLO_KEY{"HELLO"}; - static constexpr std::string_view DEVICE_KEY{"DEVICE"}; - static constexpr std::string_view NAMES_KEY{"NAMES"}; - - static constexpr std::array VALID_KEY{ACK_KEY, SET_KEY, GET_KEY, CMD_KEY, - ERR_KEY, HELLO_KEY, DEVICE_KEY, NAMES_KEY}; - - - typedef std::array keyword_hash_array_t; + typedef std::array keyword_hash_array_t; enum KEY_IDX : size_t { ACK_KEY_IDX, @@ -324,7 +332,8 @@ public: ERR_KEY_IDX, HELLO_KEY_IDX, DEVICE_KEY_IDX, - NAMES_KEY_IDX + NAMES_KEY_IDX, + INVALID_KEY_IDX }; private: // include here to allow clang compilation @@ -333,9 +342,9 @@ private: // include here to allow clang compilation template static constexpr auto computeKeywordHashesImpl(std::index_sequence) { - return keyword_hash_array_t{utils::AdcFNV1aHash(VALID_KEY[I])...}; + return keyword_hash_array_t{utils::AdcFNV1aHash(constants::ADC_DEVICE_NETPROTO_VALID_KEY[I])...}; } - template > + template > static constexpr auto computeKeywordHashes() { return computeKeywordHashesImpl(Indices{}); @@ -350,6 +359,9 @@ private: // include here to allow clang compilation bool isKey(size_t idx) const { + if (idx >= INVALID_KEY_IDX) + return false; + return _keyHash == KEY_HASHES[idx]; } @@ -452,9 +464,11 @@ public: } + using base_t::setKeyValue; // import to public area + void ack() { - base_t::setKey(ACK_KEY); + base_t::setKey(constants::ADC_DEVICE_NETPROTO_KEY_ACK); keyHash(); } @@ -463,7 +477,7 @@ public: template void ack(const ParT& param, const ParTs&... params) { - base_t::setKeyValue(ACK_KEY, param, params...); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_ACK, param, params...); keyHash(); } @@ -474,7 +488,7 @@ public: requires(!traits::adc_input_char_range) void ack(const ParT& param) { - base_t::setKeyValue(ACK_KEY, param); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_ACK, param); keyHash(); } @@ -483,7 +497,7 @@ public: template void ack(const ParT& param) { - base_t::setKeyValue(ACK_KEY, param); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_ACK, param); keyHash(); } @@ -492,8 +506,8 @@ public: template void set(AttrNameT&& attr_name, ValueT&& value, ValueTs&&... values) { - base_t::setKeyValue(SET_KEY, std::forward(attr_name), std::forward(value), - std::forward(values)...); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_SET, std::forward(attr_name), + std::forward(value), std::forward(values)...); keyHash(); } @@ -501,7 +515,7 @@ public: template void get(AttrNameT&& attr_name) { - base_t::setKeyValue(GET_KEY, std::forward(attr_name)); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_GET, std::forward(attr_name)); keyHash(); } @@ -509,14 +523,14 @@ public: template void cmd(CmdNameT&& cmd_name) { - base_t::setKeyValue(CMD_KEY, std::forward(cmd_name)); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_CMD, std::forward(cmd_name)); keyHash(); } void err(const std::error_code& ec) { - base_t::setKeyValue(ERR_KEY, ec.value(), ec.category().name(), ec.message()); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_ERR, ec.value(), ec.category().name(), ec.message()); keyHash(); } @@ -524,7 +538,8 @@ public: template void hello(SenderNameT&& name, ParamTs&&... params) { - base_t::setKeyValue(HELLO_KEY, std::forward(name), std::forward(params)...); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_HELLO, std::forward(name), + std::forward(params)...); keyHash(); } @@ -532,14 +547,14 @@ public: template void device(DevNameT&& dev_name) { - base_t::setKeyValue(DEVICE_KEY, std::forward(dev_name)); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, std::forward(dev_name)); keyHash(); } void names() { - base_t::setKey(NAMES_KEY); + base_t::setKey(constants::ADC_DEVICE_NETPROTO_KEY_NAMES); keyHash(); } @@ -547,7 +562,7 @@ public: template void names(const DevNameT& dev_name, const DevNameTs&... dev_names) { - base_t::setKeyValue(NAMES_KEY, dev_name, dev_names...); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, dev_name, dev_names...); keyHash(); } @@ -556,7 +571,7 @@ public: requires(!traits::adc_input_char_range>) void names(const R& dev_names) { - base_t::setKeyValue(NAMES_KEY, dev_names); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, dev_names); keyHash(); } @@ -564,7 +579,7 @@ public: template void names(const T& dev_names) { - base_t::setKeyValue(NAMES_KEY, dev_names); + base_t::setKeyValue(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, dev_names); keyHash(); }