start rewriting ASIO-related network service implementation

This commit is contained in:
Timur A. Fatkhullin 2024-09-16 23:28:18 +03:00
parent d33c101d70
commit 52de9a861b
3 changed files with 67 additions and 39 deletions

View File

@ -50,20 +50,20 @@ using adc_common_duration_t = adc_duration_common_type_t<std::chrono::nanosecond
/* /*
struct NetService { struct NetService {
typedef ImplementationDependentT netservice_ident_t; typedef ImplementationDependentT netservice_ident_t;
typedef ImplementationDependentT async_ctx_t; typedef ImplementationDependentT async_call_ctx_t;
typedef ImplementationDependentT endpoint_t; typedef ImplementationDependentT endpoint_t;
template<typename Rep, typename Period> template<typename Rep, typename Period>
auto asyncAccept(const endpoint_t&, async_ctx_t&, const std::chrono::duration<Rep, Period>&) auto asyncAccept(const endpoint_t&, async_call_ctx_t&, const std::chrono::duration<Rep, Period>&)
template<typename Rep, typename Period> template<typename Rep, typename Period>
auto asyncConnect(const endpoint_t&, async_ctx_t&, const std::chrono::duration<Rep, Period>&) auto asyncConnect(const endpoint_t&, async_call_ctx_t&, const std::chrono::duration<Rep, Period>&)
template<typename Rep, typename Period, adc::traits::adc_input_char_range R> template<typename Rep, typename Period, adc::traits::adc_input_char_range R>
auto asyncSend(const R&, async_ctx_t&, const std::chrono::duration<Rep, Period>&) auto asyncSend(const R&, async_call_ctx_t&, const std::chrono::duration<Rep, Period>&)
template<typename Rep, typename Period> template<typename Rep, typename Period>
auto asyncReceived(async_ctx_t&, const std::chrono::duration<Rep, Period>&) auto asyncReceived(async_call_ctx_t&, const std::chrono::duration<Rep, Period>&)
template<typename Rep, typename Period> template<typename Rep, typename Period>
auto accept(const endpoint_t&, const std::chrono::duration<Rep, Period>&) auto accept(const endpoint_t&, const std::chrono::duration<Rep, Period>&)
@ -92,20 +92,20 @@ concept adc_netservice_c =
// netservice_ident_t ident() const // netservice_ident_t ident() const
{ srv_const.ident() } -> std::same_as<typename SRVT::netservice_ident_t>; { srv_const.ident() } -> std::same_as<typename SRVT::netservice_ident_t>;
typename SRVT::async_ctx_t; typename SRVT::async_call_ctx_t;
typename SRVT::endpoint_t; typename SRVT::endpoint_t;
// asynchronous (non-blocking) operations // asynchronous (non-blocking) operations
srv.asyncAccept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<typename SRVT::async_ctx_t&>(), srv.asyncAccept(std::declval<const typename SRVT::endpoint_t&>(),
std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(),
std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
srv.asyncSend(std::declval<const SMSGT&>(), std::declval<typename SRVT::async_call_ctx_t&>(),
std::declval<const DURT&>()); std::declval<const DURT&>());
srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<typename SRVT::async_ctx_t&>(), srv.asyncReceive(std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
std::declval<const DURT&>());
srv.asyncSend(std::declval<const SMSGT&>(), std::declval<typename SRVT::async_ctx_t&>(),
std::declval<const DURT&>());
srv.asyncReceive(std::declval<typename SRVT::async_ctx_t&>(), std::declval<const DURT&>());
// synchronous (blocking) operations // synchronous (blocking) operations
srv.accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>()); srv.accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>());

View File

@ -5,6 +5,7 @@
#include <asio/basic_stream_socket.hpp> #include <asio/basic_stream_socket.hpp>
#include <asio/bind_executor.hpp> #include <asio/bind_executor.hpp>
#include <asio/compose.hpp> #include <asio/compose.hpp>
#include <asio/deferred.hpp>
#include <asio/ip/tcp.hpp> #include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp> #include <asio/ip/udp.hpp>
#include <asio/local/seq_packet_protocol.hpp> #include <asio/local/seq_packet_protocol.hpp>
@ -13,6 +14,7 @@
#include <asio/steady_timer.hpp> #include <asio/steady_timer.hpp>
#include <asio/strand.hpp> #include <asio/strand.hpp>
#include <asio/streambuf.hpp> #include <asio/streambuf.hpp>
#include <asio/use_awaitable.hpp>
#include <asio/use_future.hpp> #include <asio/use_future.hpp>
#include <asio/write.hpp> #include <asio/write.hpp>
@ -48,6 +50,26 @@ concept adc_asio_stream_transport_proto_c =
std::derived_from<T, asio::ip::tcp> || std::derived_from<T, asio::local::stream_protocol>; std::derived_from<T, asio::ip::tcp> || std::derived_from<T, asio::local::stream_protocol>;
template <typename T>
concept adc_asio_is_future = requires {
[]<typename AllocatorT>(std::type_identity<asio::use_future_t<AllocatorT>>) {
}(std::type_identity<std::remove_cvref_t<T>>());
};
template <typename T>
concept adc_asio_is_awaitable = requires {
[]<typename ExecutorT>(std::type_identity<asio::use_awaitable_t<ExecutorT>>) {
}(std::type_identity<std::remove_cvref_t<T>>());
};
struct adc_asio_async_call_ctx_t {
};
template <typename T>
concept adc_completion_token_c = traits::adc_is_callable<T> || std::same_as<T, adc_asio_async_call_ctx_t> ||
std::same_as<T, asio::deferred_t> || adc_asio_is_future<T> || adc_asio_is_awaitable<T>;
template <adc_asio_transport_proto_c TRANSPORT_PROTOT, template <adc_asio_transport_proto_c TRANSPORT_PROTOT,
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT, interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
traits::adc_output_char_range RMSGT = std::vector<char>> traits::adc_output_char_range RMSGT = std::vector<char>>
@ -67,6 +89,9 @@ public:
std::function<void(std::error_code, RMSGT)> receive_comp_token; std::function<void(std::error_code, RMSGT)> receive_comp_token;
}; };
// to satisfy 'adc_netservice_c' concept
using async_call_ctx_t = adc_asio_async_call_ctx_t;
static constexpr std::chrono::duration DEFAULT_ACCEPT_TIMEOUT = std::chrono::years::max(); static constexpr std::chrono::duration DEFAULT_ACCEPT_TIMEOUT = std::chrono::years::max();
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);
@ -81,7 +106,10 @@ public:
virtual ~AdcNetServiceASIOBase() {} virtual ~AdcNetServiceASIOBase() {}
netservice_ident_t ident() const { return _ident; } netservice_ident_t ident() const
{
return _ident;
}
void clear() void clear()
@ -92,39 +120,31 @@ public:
} }
template <traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_CONNECT_TIMEOUT)> template <adc_completion_token_c TokenT, traits::adc_time_duration_c TimeoutT = decltype(DEFAULT_CONNECT_TIMEOUT)>
auto asyncConnect(const endpoint_t& endpoint, auto asyncConnect(const endpoint_t& endpoint, TokenT&& token, const TimeoutT& timeout = DEFAULT_CONNECT_TIMEOUT)
asio_async_ctx_t& ctx,
const TimeoutT& timeout = DEFAULT_CONNECT_TIMEOUT)
{ {
static_assert(std::is_same_v<TokenT, async_call_ctx_t>, "'async_call_ctx_t'-TYPE MUST NOT BE USED!");
auto timer = getDeadlineTimer(timeout); auto timer = getDeadlineTimer(timeout);
auto comp_token = [&ctx, timer = std::move(timer), this](std::error_code ec) { auto comp_token = [wrapper = traits::adc_pf_wrapper(std::forward<TokenT>(token)),
timer = std::move(timer)](std::error_code ec) {
if (isTimeout(timer, ec)) { if (isTimeout(timer, ec)) {
ec = std::make_error_code(std::errc::timed_out); ec = std::make_error_code(std::errc::timed_out);
} else { } else {
timer->cancel(); timer->cancel();
} }
if (!ctx.use_future) {
ctx.connect_comp_token(ec); if constexpr (!adc_asio_is_future<TokenT>) {
std::get<0>(wrapper)(ec);
} }
}; };
if (ctx.use_future) { if constexpr (!adc_asio_is_future<TokenT>) {
comp_token = asio::use_future(comp_token); return _socket.async_connect(endpoint, asio::use_future(std::move(comp_token)));
} else {
return _socket.async_connect(endpoint, std::move(comp_token));
} }
return _socket.async_connect(endpoint, comp_token);
// if (ctx.use_future) {
// return _socket.async_connect(
// endpoint, asio::use_future([&ctx, timer = std::move(timer)](std::error_code) { timer->cancel(); }));
// } else {
// return _socket.async_connect(endpoint, [&ctx, timer = std::move(timer)](std::error_code ec) {
// timer->cancel();
// ctx.connect_comp_token(ec);
// });
// }
} }
@ -170,7 +190,7 @@ public:
auto timer = getDeadlineTimer(timeout); auto timer = getDeadlineTimer(timeout);
auto comp_token = [&ctx, timer = std::move(timer)](std::error_code ec, size_t) { auto comp_token = [&ctx, buff_seq, timer = std::move(timer)](std::error_code ec, size_t) {
timer->cancel(); timer->cancel();
if (!ctx.use_future) { if (!ctx.use_future) {
@ -364,9 +384,15 @@ public:
return ftr.get(); return ftr.get();
} }
void setShutdownType(asio::socket_base::shutdown_type shutdown_type) { _shutdownType = shutdown_type; } void setShutdownType(asio::socket_base::shutdown_type shutdown_type)
{
_shutdownType = shutdown_type;
}
asio::socket_base::shutdown_type getShutdownType() const { return _shutdownType; } asio::socket_base::shutdown_type getShutdownType() const
{
return _shutdownType;
}
std::error_code close() std::error_code close()
{ {
@ -415,7 +441,7 @@ protected:
} }
template <typename TimerT> template <typename TimerT>
bool isTimeout(const std::unique_ptr<TimerT>& timer, const std::error_code& ec) static bool isTimeout(const std::unique_ptr<TimerT>& timer, const std::error_code& ec)
{ {
auto exp_time = timer->expiry(); auto exp_time = timer->expiry();
return (exp_time < std::chrono::steady_clock::now()) && (ec == asio::error::operation_aborted); return (exp_time < std::chrono::steady_clock::now()) && (ec == asio::error::operation_aborted);

View File

@ -18,7 +18,9 @@ int main()
}; };
// srv.asyncAccept(ept_s, srv_ctx, std::chrono::seconds(120)); // srv.asyncAccept(ept_s, srv_ctx, std::chrono::seconds(120));
srv.asyncConnect(ept_c, srv_ctx); srv.asyncConnect(ept_c, [](std::error_code ec) {
});
ctx.run(); ctx.run();