From 062c26537daf49eb2107347b1eaf6bd1262dae91 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 23 Oct 2024 23:55:40 +0300 Subject: [PATCH] .... --- net/asio/adc_netsrv_asio.h | 159 ++++++++++++++++++++++++++++++---- tests/adc_netservice_test.cpp | 4 +- 2 files changed, 146 insertions(+), 17 deletions(-) diff --git a/net/asio/adc_netsrv_asio.h b/net/asio/adc_netsrv_asio.h index 082935e..f59c228 100644 --- a/net/asio/adc_netsrv_asio.h +++ b/net/asio/adc_netsrv_asio.h @@ -109,7 +109,92 @@ concept adc_asio_special_comp_token_c = namespace details { +struct helper_struct_t { + using asyncAcceptImplementation = std::nullptr_t; +}; +template +class Accpt +{ +public: + using netservice_t = SRVT; + + // deduce needed types + using transport_proto_t = typename SRVT::endpoint_t::protocol_type; + using socket_t = typename SRVT::endpoint_t::protocol_type::socket; + using acceptor_t = std::conditional_t>, + std::nullptr_t, // there is no acceptor + typename transport_proto_t::acceptor>; + + static constexpr std::chrono::duration DEFAULT_ACCEPT_TIMEOUT = std::chrono::seconds::max(); + + Accpt(asio::io_context& io_ctx, const netservice_t::endpoint_t& endpoint) + : _ioContext(io_ctx), _acceptor(io_ctx, endpoint) + { + } + + template TokenT, + traits::adc_time_duration_c DT = decltype(DEFAULT_ACCEPT_TIMEOUT)> + auto asyncAccept(TokenT&& token, const DT& timeout = DEFAULT_ACCEPT_TIMEOUT) + { + if constexpr (std::is_null_pointer_v) { + static_assert(false, "INVALID TRANSPORT PROTOCOL TYPE!"); + } + + auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout); + + auto srv = std::make_shared(_ioContext); + // auto srv = std::make_unique(_ioContext); + + if constexpr (std::same_as) { + return asio::async_compose( + _impl(this, _acceptor, std::move(timer), srv, true), token, _ioContext); + } else { + return asio::async_compose( + static_cast(this)->_impl(this, _acceptor, std::move(timer), srv, true), token, _ioContext); + } + } + + template + auto accept(const DT& timeout = DEFAULT_ACCEPT_TIMEOUT) + { + auto f = asyncAccept(asio::use_future, timeout); + + return f.get(); + } + +protected: + asio::io_context& _ioContext; + acceptor_t _acceptor; + + struct asyncAcceptImplementation { + Accpt* acp; + acceptor_t& _acceptor; + std::shared_ptr timer; + std::shared_ptr srv; + bool start; + + void operator()(auto& self, std::error_code ec = {}) + { + if (!ec) { + if (start) { + start = false; + return _acceptor.async_accept(srv->_socket, std::move(self)); + } + } + + if (netservice_t::isTimeout(timer, ec)) { + ec = std::make_error_code(std::errc::timed_out); + } else { // an error occured in async_accept + timer->cancel(); + } + + self.complete(ec, std::move(*srv)); + } + } _impl; +}; + +/* // template template class AdcAcceptorASIO @@ -148,32 +233,37 @@ public: auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout); - // auto srv = std::make_shared(_ioContext); - auto srv = std::make_unique(_ioContext); + auto srv = std::make_shared(_ioContext); + // auto srv = std::make_unique(_ioContext); // return asio::async_compose( // asyncAcceptImplementation{this, _acceptor, std::move(timer), srv, AdcAcceptorASIO::starting}, token, // _ioContext); return asio::async_compose( - [timer = std::move(timer), srv = std::move(srv), state = AdcAcceptorASIO::starting, this]( + // [timer = std::move(timer), srv = std::move(srv), state = AdcAcceptorASIO::native_accept, this]( + [timer = std::move(timer), srv, state = AdcAcceptorASIO::native_accept, this]( auto& self, std::error_code ec = {}) mutable { if (!ec) { switch (state) { case starting: // _starting(srv, state, self); _starting(srv, state, std::move(self)); + return; break; case native_accept: // _native_accept(srv, state, self); _native_accept(srv, state, std::move(self)); + return; break; case post_accept: // _post_accept(srv, state, self); _post_accept(srv, state, std::move(self)); + return; break; case finishing: // _finishing(srv, state, self); _finishing(srv, state, std::move(self)); + return; break; default: break; @@ -205,29 +295,33 @@ protected: enum state_t { starting, native_accept, post_accept, finishing }; - // using self_t = std::function; using self_t = std::function; + // using self_t = asio::any_completion_handler; + // using self_t = std::move_only_function; - typedef std::function&, state_t&, self_t)> stage_func_t; - // typedef std::function&, state_t&, self_t)> stage_func_t; + // typedef std::function&, state_t&, self_t)> stage_func_t; + typedef std::function, state_t&, self_t)> stage_func_t; - stage_func_t _starting = [this](auto&, state_t& state, self_t self) mutable { + // stage_func_t _starting = [this](auto&, state_t& state, self_t self) mutable { + stage_func_t _starting = [this](auto, state_t& state, self_t self) mutable { state = native_accept; - // asio::post(_ioContext, std::bind([](auto, auto) {}, std::move(self), std::error_code{})); + asio::post(_ioContext, std::bind([](auto&, auto) {}, std::move(self), std::error_code{})); }; - stage_func_t _native_accept = [this](auto& srv, state_t& state, self_t self) mutable { + // stage_func_t _native_accept = [this](auto& srv, state_t& state, self_t self) mutable { + stage_func_t _native_accept = [this](auto srv, state_t& state, self_t self) mutable { state = post_accept; _acceptor.async_accept(srv->_socket, std::move(self)); }; - stage_func_t _post_accept = [this](auto&, state_t& state, self_t self) mutable { state = finishing; }; + // stage_func_t _post_accept = [this](auto&, state_t& state, self_t self) mutable { state = finishing; }; + stage_func_t _post_accept = [this](auto, state_t& state, self_t self) mutable { state = finishing; }; - stage_func_t _finishing = [](auto&, state_t&, self_t) mutable {}; + // stage_func_t _finishing = [](auto&, state_t&, self_t) mutable {}; + stage_func_t _finishing = [](auto, state_t&, self_t) mutable {}; - /* struct asyncAcceptImplementation { AdcAcceptorASIO* acp; acceptor_t& _acceptor; @@ -284,8 +378,8 @@ protected: self.complete(ec, std::move(*srv)); } }; - */ }; + */ } // namespace details @@ -296,7 +390,8 @@ template ; + // friend details::AdcAcceptorASIO; + friend details::Accpt; // typedefs to satisfy 'adc_netservice_c' concept typedef std::string_view netservice_ident_t; @@ -315,7 +410,41 @@ public: // typedefs from transport protocol using socket_t = typename TRANSPORT_PROTOT::socket; - typedef details::AdcAcceptorASIO acceptor_t; + // typedef details::AdcAcceptorASIO acceptor_t; + // typedef details::Accpt acceptor_t; + struct acceptor_t : details::Accpt { + using base_t = details::Accpt; + using base_t::base_t; + + protected: + using typename base_t::netservice_t; + + struct asyncAcceptImplementation { + acceptor_t* acp; + typename base_t::acceptor_t& _acceptor; + std::shared_ptr timer; + std::shared_ptr srv; + bool start; + + void operator()(auto& self, std::error_code ec = {}) + { + if (!ec) { + if (start) { + start = false; + return _acceptor.async_accept(srv->_socket, std::move(self)); + } + } + + if (netservice_t::isTimeout(timer, ec)) { + ec = std::make_error_code(std::errc::timed_out); + } else { // an error occured in async_accept + timer->cancel(); + } + + self.complete(ec, std::move(*srv)); + } + }; + }; static constexpr std::chrono::duration DEFAULT_CONNECT_TIMEOUT = std::chrono::seconds(10); static constexpr std::chrono::duration DEFAULT_SEND_TIMEOUT = std::chrono::seconds(5); diff --git a/tests/adc_netservice_test.cpp b/tests/adc_netservice_test.cpp index dd53a9c..114d88e 100644 --- a/tests/adc_netservice_test.cpp +++ b/tests/adc_netservice_test.cpp @@ -2,8 +2,8 @@ #include #include "../net/adc_netproto.h" -#include "../net/asio/adc_netservice_asio.h" -// #include "../net/asio/adc_netsrv_asio.h" +// #include "../net/asio/adc_netservice_asio.h" +#include "../net/asio/adc_netsrv_asio.h" template void receive(T srv)