145 lines
4.8 KiB
C++
145 lines
4.8 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/compose.hpp>
|
|
#include <asio/experimental/awaitable_operators.hpp>
|
|
#include <asio/read_until.hpp>
|
|
#include <asio/steady_timer.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, asio::completion_token_for<void(std::error_code, size_t)> CompletionTokenT>
|
|
auto asynSend(const NetMessageT& msg, const TimeoutT& timeout, CompletionTokenT&& token)
|
|
{
|
|
// using namespace asio::experimental::awaitable_operators;
|
|
|
|
// auto deadline = std::chrono::steady_clock::now() + timeout;
|
|
|
|
std::unique_ptr<asio::steady_timer> timer(_socket.get_executor());
|
|
|
|
timer->expires_after(timeout);
|
|
timer->async_wait([this, timer = std::move(timer)](const std::error_code& ec) {
|
|
if (!ec) {
|
|
_socket.cancel(std::make_error_code(std::errc::timed_out));
|
|
}
|
|
});
|
|
|
|
|
|
if constexpr (std::derived_from<socket_t, asio::basic_stream_socket<typename socket_t::protocol_type>>) {
|
|
return asio::async_write(_socket, createConstBufferSequence(msg), std::forward<CompletionTokenT>(token));
|
|
} else if constexpr (std::derived_from<socket_t,
|
|
asio::basic_datagram_socket<typename socket_t::protocol_type>>) {
|
|
return _socket.async_send(createConstBufferSequence(msg), std::forward<CompletionTokenT>(token));
|
|
} else if constexpr (std::derived_from<socket_t,
|
|
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) {
|
|
return _socket.async_send(createConstBufferSequence(msg), std::forward<CompletionTokenT>(token));
|
|
} else {
|
|
static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!");
|
|
}
|
|
|
|
// std::error_code ec;
|
|
|
|
// co_await (asyncSendImpl(msg) && watchdog(deadline, ec));
|
|
|
|
// std::forward<CompletionTokenT>(token)(ec);
|
|
// co_return asio::async_compose<CompletionTokenT, void(std::error_code)>(
|
|
// [ec](auto& self, const std::error_code& = {}) { self.complete(ec); }, token, _socket);
|
|
}
|
|
|
|
|
|
template <typename TimeoutT, typename CompletionTokenT>
|
|
auto asyncReceive(const TimeoutT& timeout, CompletionTokenT&& token)
|
|
{
|
|
}
|
|
|
|
|
|
protected:
|
|
socket_t& _socket;
|
|
|
|
asio::streambuf _streamBuffer;
|
|
|
|
std::vector<asio::const_buffer> createConstBufferSequence(const NetMessageT& msg)
|
|
{
|
|
std::vector<asio::const_buffer> buff;
|
|
for (const auto& el : msg.template bytesView<std::vector<std::string_view>>()) {
|
|
buff.emplace_back(asio::const_buffer(el));
|
|
}
|
|
|
|
return buff;
|
|
}
|
|
|
|
asio::awaitable<void> asyncSendImpl(const NetMessageT& msg)
|
|
{
|
|
// for (const auto& buff : msg.bytesView()) {
|
|
if constexpr (std::derived_from<socket_t, asio::basic_stream_socket<typename socket_t::protocol_type>>) {
|
|
// asio::async_write(_socket, buff, asio::use_awaitable);
|
|
co_await asio::async_write(_socket, msg.bytesView(), asio::use_awaitable);
|
|
} else if constexpr (std::derived_from<socket_t,
|
|
asio::basic_datagram_socket<typename socket_t::protocol_type>>) {
|
|
co_await _socket.async_send(msg.bytesView(), asio::use_awaitable);
|
|
} else if constexpr (std::derived_from<socket_t,
|
|
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) {
|
|
co_await _socket.async_send(msg.bytesView(), asio::use_awaitable);
|
|
} else {
|
|
static_assert(false, "UNKNOWN ASIO-LIBRARY SOCKET TYPE!!!");
|
|
}
|
|
// }
|
|
}
|
|
|
|
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
|