ADC/net/adc_netservice_asio.h
Timur A. Fatkhullin 8b2e8fcaaa ...
2024-06-11 00:45:50 +03:00

101 lines
2.4 KiB
C++

#pragma once
/*
ABSTRACT DEVICE COMPONENTS LIBRARY
ASIO-library implementation of network service
*/
#ifdef USE_ASIO_LIBRARY
#include <asio/awaitable.hpp>
#include <asio/basic_datagram_socket.hpp>
#include <asio/basic_seq_packet_socket.hpp>
#include <asio/basic_stream_socket.hpp>
#include <asio/experimental/awaitable_operators.hpp>
#include <asio/read_until.hpp>
#include <asio/streambuf.hpp>
#include <asio/write.hpp>
#include <concepts>
namespace adc::impl
{
template <typename NetMessageT, typename InetProtoT>
class AdcNetServiceASIOStream
{
public:
using socket_t = typename InetProtoT::socket;
AdcNetServiceASIOStream(socket_t& sock) : _socket(sock) {}
virtual ~AdcNetServiceASIOStream() = default;
template <typename TimeoutT, typename CompletionTokenT>
auto asynSend(const NetMessageT& msg, const TimeoutT& timeout, CompletionTokenT&& token)
requires std::derived_from<socket_t, asio::basic_stream_socket<typename socket_t::protocol_type>>
{
using namespace asio::experimental::awaitable_operators;
auto deadline = std::chrono::steady_clock::now() + timeout;
std::error_code ec;
co_await (asio::async_write(_socket, msg.bytes(), asio::use_awaitable) && watchdog(deadline, ec));
std::forward<CompletionTokenT>(token)(ec);
}
template <typename CompletionTokenT>
auto asynSend(const NetMessageT& msg, CompletionTokenT&& token)
requires std::derived_from<socket_t, asio::basic_datagram_socket<typename socket_t::protocol_type>>
{
}
template <typename CompletionTokenT>
auto asynSend(const NetMessageT& msg, CompletionTokenT&& token)
requires std::derived_from<socket_t, asio::basic_seq_packet_socket<typename socket_t::protocol_type>>
{
}
protected:
socket_t& _socket;
asio::streambuf _streamBuffer;
template <typename TimepointT>
asio::awaitable<void> watchdog(TimepointT& deadline, std::error_code& ec)
{
ec.clear();
typename TimepointT::clock timer(co_await asio::this_coro::executor);
auto now = TimepointT::clock::template now();
while (deadline > now) {
timer.expires_at(deadline);
co_await timer.async_wait(asio::use_awaitable);
now = TimepointT::clock::template now();
}
ec = std::make_error_code(std::errc::timed_out);
throw std::system_error(ec);
}
};
} // namespace adc::impl
#endif