This commit is contained in:
Timur A. Fatkhullin 2024-10-23 23:55:40 +03:00
parent ad0bdf062a
commit 062c26537d
2 changed files with 146 additions and 17 deletions

View File

@ -109,7 +109,92 @@ concept adc_asio_special_comp_token_c =
namespace details namespace details
{ {
struct helper_struct_t {
using asyncAcceptImplementation = std::nullptr_t;
};
template <typename SRVT, typename DRVT = std::nullptr_t>
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::derived_from<socket_t, asio::basic_datagram_socket<transport_proto_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 <asio::completion_token_for<void(std::error_code, netservice_t)> 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<acceptor_t>) {
static_assert(false, "INVALID TRANSPORT PROTOCOL TYPE!");
}
auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout);
auto srv = std::make_shared<netservice_t>(_ioContext);
// auto srv = std::make_unique<netservice_t>(_ioContext);
if constexpr (std::same_as<DRVT, std::nullptr_t>) {
return asio::async_compose<TokenT, void(std::error_code, netservice_t)>(
_impl(this, _acceptor, std::move(timer), srv, true), token, _ioContext);
} else {
return asio::async_compose<TokenT, void(std::error_code, netservice_t)>(
static_cast<DRVT*>(this)->_impl(this, _acceptor, std::move(timer), srv, true), token, _ioContext);
}
}
template <traits::adc_time_duration_c DT = decltype(DEFAULT_ACCEPT_TIMEOUT)>
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<asio::steady_timer> timer;
std::shared_ptr<netservice_t> 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 <interfaces::adc_netservice_c SRVT> // template <interfaces::adc_netservice_c SRVT>
template <typename SRVT> template <typename SRVT>
class AdcAcceptorASIO class AdcAcceptorASIO
@ -148,32 +233,37 @@ public:
auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout); auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout);
// auto srv = std::make_shared<netservice_t>(_ioContext); auto srv = std::make_shared<netservice_t>(_ioContext);
auto srv = std::make_unique<netservice_t>(_ioContext); // auto srv = std::make_unique<netservice_t>(_ioContext);
// return asio::async_compose<TokenT, void(std::error_code, netservice_t)>( // return asio::async_compose<TokenT, void(std::error_code, netservice_t)>(
// asyncAcceptImplementation{this, _acceptor, std::move(timer), srv, AdcAcceptorASIO::starting}, token, // asyncAcceptImplementation{this, _acceptor, std::move(timer), srv, AdcAcceptorASIO::starting}, token,
// _ioContext); // _ioContext);
return asio::async_compose<TokenT, void(std::error_code, netservice_t)>( return asio::async_compose<TokenT, void(std::error_code, netservice_t)>(
[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 { auto& self, std::error_code ec = {}) mutable {
if (!ec) { if (!ec) {
switch (state) { switch (state) {
case starting: case starting:
// _starting(srv, state, self); // _starting(srv, state, self);
_starting(srv, state, std::move(self)); _starting(srv, state, std::move(self));
return;
break; break;
case native_accept: case native_accept:
// _native_accept(srv, state, self); // _native_accept(srv, state, self);
_native_accept(srv, state, std::move(self)); _native_accept(srv, state, std::move(self));
return;
break; break;
case post_accept: case post_accept:
// _post_accept(srv, state, self); // _post_accept(srv, state, self);
_post_accept(srv, state, std::move(self)); _post_accept(srv, state, std::move(self));
return;
break; break;
case finishing: case finishing:
// _finishing(srv, state, self); // _finishing(srv, state, self);
_finishing(srv, state, std::move(self)); _finishing(srv, state, std::move(self));
return;
break; break;
default: default:
break; break;
@ -205,29 +295,33 @@ protected:
enum state_t { starting, native_accept, post_accept, finishing }; enum state_t { starting, native_accept, post_accept, finishing };
// using self_t = std::function<void(std::error_code)>;
using self_t = std::function<void(std::error_code)>; using self_t = std::function<void(std::error_code)>;
// using self_t = asio::any_completion_handler<void(std::error_code)>;
// using self_t = std::move_only_function<void(std::error_code)>;
typedef std::function<void(std::unique_ptr<netservice_t>&, state_t&, self_t)> stage_func_t; // typedef std::function<void(std::unique_ptr<netservice_t>&, state_t&, self_t)> stage_func_t;
// typedef std::function<void(std::shared_ptr<netservice_t>&, state_t&, self_t)> stage_func_t; typedef std::function<void(std::shared_ptr<netservice_t>, 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; 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; state = post_accept;
_acceptor.async_accept(srv->_socket, std::move(self)); _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 { struct asyncAcceptImplementation {
AdcAcceptorASIO* acp; AdcAcceptorASIO* acp;
acceptor_t& _acceptor; acceptor_t& _acceptor;
@ -284,8 +378,8 @@ protected:
self.complete(ec, std::move(*srv)); self.complete(ec, std::move(*srv));
} }
}; };
*/
}; };
*/
} // namespace details } // namespace details
@ -296,7 +390,8 @@ template <adc_asio_transport_proto_c TRANSPORT_PROTOT,
class AdcNetServiceASIOBase : public SESSION_PROTOT class AdcNetServiceASIOBase : public SESSION_PROTOT
{ {
public: public:
friend details::AdcAcceptorASIO<AdcNetServiceASIOBase>; // friend details::AdcAcceptorASIO<AdcNetServiceASIOBase>;
friend details::Accpt<AdcNetServiceASIOBase>;
// typedefs to satisfy 'adc_netservice_c' concept // typedefs to satisfy 'adc_netservice_c' concept
typedef std::string_view netservice_ident_t; typedef std::string_view netservice_ident_t;
@ -315,7 +410,41 @@ public:
// typedefs from transport protocol // typedefs from transport protocol
using socket_t = typename TRANSPORT_PROTOT::socket; using socket_t = typename TRANSPORT_PROTOT::socket;
typedef details::AdcAcceptorASIO<AdcNetServiceASIOBase> acceptor_t; // typedef details::AdcAcceptorASIO<AdcNetServiceASIOBase> acceptor_t;
// typedef details::Accpt<AdcNetServiceASIOBase> acceptor_t;
struct acceptor_t : details::Accpt<AdcNetServiceASIOBase, acceptor_t> {
using base_t = details::Accpt<AdcNetServiceASIOBase, acceptor_t>;
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<asio::steady_timer> timer;
std::shared_ptr<netservice_t> 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_CONNECT_TIMEOUT = std::chrono::seconds(10);
static constexpr std::chrono::duration DEFAULT_SEND_TIMEOUT = std::chrono::seconds(5); static constexpr std::chrono::duration DEFAULT_SEND_TIMEOUT = std::chrono::seconds(5);

View File

@ -2,8 +2,8 @@
#include <iostream> #include <iostream>
#include "../net/adc_netproto.h" #include "../net/adc_netproto.h"
#include "../net/asio/adc_netservice_asio.h" // #include "../net/asio/adc_netservice_asio.h"
// #include "../net/asio/adc_netsrv_asio.h" #include "../net/asio/adc_netsrv_asio.h"
template <typename T> template <typename T>
void receive(T srv) void receive(T srv)