From 9cde583688ae75ecf3ee58d7327de2730f9f7eb2 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 30 Oct 2024 18:20:16 +0300 Subject: [PATCH] ... --- device/adc_device_attribute.h | 25 +++++++-- net/adc_device_netserver.h | 5 +- net/adc_netserver.h | 13 ++--- tests/adc_asio_netserver_test.cpp | 93 ++++++++++++++++++++++++++++++- tests/adc_netmsg_test.cpp | 5 +- 5 files changed, 125 insertions(+), 16 deletions(-) diff --git a/device/adc_device_attribute.h b/device/adc_device_attribute.h index 9c11498..47a4b63 100644 --- a/device/adc_device_attribute.h +++ b/device/adc_device_attribute.h @@ -141,7 +141,10 @@ namespace adc struct AdcDeviceAttributeErrorCategory : public std::error_category { AdcDeviceAttributeErrorCategory() : std::error_category() {} - const char* name() const noexcept { return "ADC_DEVICE_ATTRIBUTE_CATEGORY"; } + const char* name() const noexcept + { + return "ADC_DEVICE_ATTRIBUTE_CATEGORY"; + } std::string message(int ec) const { @@ -416,16 +419,25 @@ public: } - virtual ~AdcDeviceAttribute() { _clearFunc(); } + virtual ~AdcDeviceAttribute() + { + _clearFunc(); + } /* PUBLIC METHODS */ - IdentT ident() const { return _ident; } + IdentT ident() const + { + return _ident; + } - AccessType accessType() const { return _accessType; } + AccessType accessType() const + { + return _accessType; + } template @@ -601,6 +613,11 @@ public: // throw std::system_error(AdcDeviceAttributeErrorCode::ERROR_INVALID_SERIALIZED_TYPE); } + default_serialized_t serialize() + { + return serialize(); + } + template AdcDeviceAttribute& deserialize(const SerializedT& sval) { diff --git a/net/adc_device_netserver.h b/net/adc_device_netserver.h index f2deb60..c4b8c4d 100644 --- a/net/adc_device_netserver.h +++ b/net/adc_device_netserver.h @@ -131,8 +131,11 @@ protected: }; public: - DeviceWrapper() { + DeviceWrapper() : _id() + { // null device + std::string_view is{"NULL-DEVICE"}; + std::ranges::copy(_id, std::back_inserter(_id)); }; template - void start(const typename SessionT::netsession_ident_t& id, - const typename SessionT::netsession_ctx_t& sess_ctx, - AcceptorCtorArgTs&&... ctor_args) + void start(SessionT::netsession_ident_t id, SessionT::netsession_ctx_t sess_ctx, AcceptorCtorArgTs&&... ctor_args) { if (!_isListening[this][id]) { auto acceptor = std::make_shared( @@ -322,7 +320,7 @@ public: _isListening[this][id] = false; }); - doAccept(acceptor, id, sess_ctx); + doAccept(acceptor, std::move(id), std::move(sess_ctx)); } // only once per SessionT @@ -369,15 +367,16 @@ protected: server_ident_t _serverIdent; template - void doAccept(std::shared_ptr acceptor, const IDT& id, const CTXT& sess_ctx) + void doAccept(std::shared_ptr acceptor, IDT id, CTXT sess_ctx) { - acceptor->asyncAccept([acceptor, &id, &sess_ctx, this](auto ec, typename SessionT::netservice_t srv) mutable { + acceptor->asyncAccept([acceptor, id = std::move(id), sess_ctx = std::move(sess_ctx), this]( + auto ec, typename SessionT::netservice_t srv) mutable { if (!ec) { auto sess = std::make_shared(id, std::move(srv), sess_ctx); startSession(sess); _isListening[this][id] = true; - doAccept(acceptor, id, sess_ctx); + doAccept(acceptor, std::move(id), std::move(sess_ctx)); } else { _isListening[this][id] = false; } diff --git a/tests/adc_asio_netserver_test.cpp b/tests/adc_asio_netserver_test.cpp index 5b55d8d..258619e 100644 --- a/tests/adc_asio_netserver_test.cpp +++ b/tests/adc_asio_netserver_test.cpp @@ -1,12 +1,86 @@ #include #include +#include "../device/adc_device.h" +#include "../device/adc_device_attribute.h" +#include "../device/adc_device_command.h" #include "../net/adc_endpoint.h" #include "../net/adc_netproto.h" #include "../net/asio/adc_device_netserver_asio.h" + +class Device1 : public adc::AdcGenericDevice, + adc::AdcDeviceCommand> +{ + typedef adc::AdcGenericDevice, adc::AdcDeviceCommand> + base_t; + +public: + template + Device1(R&& id) : base_t(id) + { + if constexpr (std::is_array_v>) { + this->_ident = std::forward(id); + } else { + std::ranges::copy(std::forward(id), std::back_inserter(this->_ident)); + } + } +}; + +class Device2 + : public adc::AdcGenericDevice, adc::AdcDeviceCommand> +{ + typedef adc::AdcGenericDevice, adc::AdcDeviceCommand> + base_t; + +public: + template + Device2(R&& id) : base_t(id) + { + if constexpr (std::is_array_v>) { + this->_ident = std::forward(id); + } else { + std::ranges::copy(std::forward(id), std::back_inserter(this->_ident)); + } + } +}; + +using t_t = std::tuple; +static t_t tuple_val{7.7, "TUPVAL"}; + +t_t gt() +{ + return tuple_val; +} + +void st(const t_t& v) +{ + tuple_val = v; +} + int main(int argc, char* argv[]) { + /* CREATE AND INIT DEVICES */ + int dev1_val1 = 1; + + Device1 dev1("DEVICE#1"); + Device2 dev2("DEVICE#2"); + + // device#1 + dev1.addCommand({"DEV1::COM1", []() { std::cout << "EXEC DEV1::COM1\n"; }}); + dev1.addAttribute( + {"DEV1::ATTR1", [&dev1_val1]() { return dev1_val1; }, [&dev1_val1](const int& v) { dev1_val1 = v; }}); + + dev1.addAttribute({"DEV1::ATTR2", gt, st}); + + // device#2 + // read-only attr + dev2.addAttribute({0x1, [&dev1_val1]() { return dev1_val1; }}); + // write-only + dev2.addAttribute({0x2, [&dev1_val1](const int& v) { dev1_val1 = v; }}); + + /* COMMANDLINE OPTS */ cxxopts::Options options(argv[0], "ADC-library test device network server (ASIO implementation)\n"); @@ -14,10 +88,14 @@ int main(int argc, char* argv[]) options.add_options()("h,help", "Print usage"); options.add_options()( - "endpoints", "endpoints server will be listening for", - cxxopts::value>()->default_value("local://stream/ADC_ASIO_TEST_SERVER")); - // cxxopts::value>()->default_value("local://stream/@ADC_ASIO_TEST_SERVER")); + "endpoints", + "endpoints server will be listening for. For 'local' endpoint the '@' symbol at the beginning of the path " + "means " + "abstract namespace socket.", + cxxopts::value>()->default_value("local://stream/@ADC_ASIO_TEST_SERVER")); + + options.positional_help("[endpoint0] [enpoint1] ... [endpointN]"); options.parse_positional({"endpoints"}); try { @@ -25,6 +103,11 @@ int main(int argc, char* argv[]) if (opt_result["help"].count()) { std::cout << options.help(); + std::cout << "\n"; + std::cout << "[endpoint0] [enpoint1] ... [endpointN] - endpoints server will be listening for. For 'local' " + "endpoint the '@' symbol at the beginning of the path " + "means abstract namespace socket." + << "\n"; return 0; } @@ -36,6 +119,10 @@ int main(int argc, char* argv[]) adc::impl::AdcDeviceNetServerASIO server("TEST SRV", io_ctx); server.setupSignals(); + server.addDevice(&dev1); + server.addDevice(&dev2, adc::traits::adc_char_identity{}, + adc::utils::AdcDefaultValueConverter<>::serialize); + auto epnt = opt_result["endpoints"].as>(); for (auto& ep : epnt) { diff --git a/tests/adc_netmsg_test.cpp b/tests/adc_netmsg_test.cpp index 936a07a..39375a3 100644 --- a/tests/adc_netmsg_test.cpp +++ b/tests/adc_netmsg_test.cpp @@ -96,7 +96,9 @@ TEST_CASE("[ADC NET MESSAGE]") std::cout << std::boolalpha << "IS UDP: " << prs.isUDP() << "\n"; std::cout << "\n"; - std::string bs = "local://seqpaCKet:dwe/tmp.dev/213"; + std::string bs = "local://seqpaCKet:dwe/@tmp.dev/213"; + auto it = std::ranges::find(bs, '@'); + *it = '\0'; std::cout << "EPT CHAR RANGE: " << bs << "\n"; prs = AdcEndpointParser(bs); std::cout << std::boolalpha << "IS VALID: " << prs.isValid() << "\n"; @@ -104,6 +106,7 @@ TEST_CASE("[ADC NET MESSAGE]") std::cout << "HOST: [" << prs.host() << "]\n"; std::cout << "PORT: [" << prs.port() << "]\n"; std::cout << "PATH: [" << prs.path() << "]\n"; + std::cout << "PATH SZ: [" << prs.path().size() << "]\n"; std::cout << std::boolalpha << "IS LOCAL STREAM: " << prs.isLocalStream() << "\n"; std::cout << std::boolalpha << "IS LOCAL SEQPACKET: " << prs.isLocalSeqpacket() << "\n"; std::cout << std::boolalpha << "IS UDP: " << prs.isUDP() << "\n";