...
This commit is contained in:
parent
1f9615a6ba
commit
8b2e8fcaaa
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(ADC LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# set(CMAKE_BUILD_TYPE Release)
|
||||
@ -32,7 +34,22 @@ set(ADC_NETWORK_HEADERS
|
||||
)
|
||||
|
||||
|
||||
option(SPDLOG_LIBRARY "Use SPDLOG library for logging" ON)
|
||||
option(ASIO_LIBRARY "Use of ASIO library for networking implementation" ON)
|
||||
|
||||
if (ASIO_LIBRARY)
|
||||
find_package(ASIO REQUIRED)
|
||||
|
||||
set(ADC_NETWORK_HEADERS ${ADC_NETWORK_HEADERS}
|
||||
net/adc_netservice_asio.h
|
||||
)
|
||||
|
||||
add_compile_options(ASIO::ASIO)
|
||||
add_compile_definitions(PUBLIC USE_ASIO_LIBRARY)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
option(SPDLOG_LIBRARY "Use of SPDLOG library for logging" ON)
|
||||
|
||||
if (SPDLOG_LIBRARY)
|
||||
find_package(spdlog REQUIRED)
|
||||
|
||||
24
FindASIO.cmake
Normal file
24
FindASIO.cmake
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# ASIO
|
||||
#
|
||||
|
||||
set(ASIO_FOUND FALSE)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_path(ASIO_DIR asio.hpp HINTS ${ASIO_INSTALL_DIR} PATH_SUFFIXES include)
|
||||
|
||||
if (NOT ASIO_DIR)
|
||||
message(FATAL_ERROR "Cannot find ASIO library headers!")
|
||||
endif()
|
||||
|
||||
message(STATUS "Found ASIO: TRUE (${ASIO_DIR})")
|
||||
|
||||
# ASIO is header-only library so it is IMPORTED target
|
||||
add_library(ASIO::ASIO INTERFACE IMPORTED GLOBAL)
|
||||
|
||||
# set standalone version (do not use Boost)
|
||||
set_target_properties(ASIO::ASIO PROPERTIES INTERFACE_COMPILE_DEFINITIONS "ASIO_STANDALONE" INTERFACE_INCLUDE_DIRECTORIES "${ASIO_DIR}")
|
||||
|
||||
target_link_libraries(ASIO::ASIO INTERFACE Threads::Threads)
|
||||
set(ASIO_FOUND TRUE)
|
||||
@ -46,11 +46,14 @@ void convertToBytes(ByteStorageT& res, const T& v, const Ts&... vs)
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
template <typename T, typename IT>
|
||||
concept adc_netmessage_c = requires(const T t) { // const methods
|
||||
requires std::same_as<std::iter_value_t<IT>, char>;
|
||||
{ t.empty() } -> std::convertible_to<bool>;
|
||||
{ t.byteSize() } -> std::convertible_to<size_t>;
|
||||
{ t.bytes() } -> adc_output_char_range;
|
||||
{ t.byteView() } -> adc_range_of_view_char_range;
|
||||
{ t.setFromBytes(std::input_iterator<IT>) } -> std::same_as<void>;
|
||||
};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
@ -29,6 +29,7 @@ public:
|
||||
using timeout_drtn_t = timeout_clock_t::duration;
|
||||
|
||||
static constexpr timeout_drtn_t defaultConnectTimeout = std::chrono::seconds(5);
|
||||
// static constexpr std::chrono::duration defaultConnectTimeout = std::chrono::seconds(5);
|
||||
static constexpr timeout_drtn_t defaultSendTimeout = std::chrono::seconds(5);
|
||||
static constexpr timeout_drtn_t defaultRecvTimeout = std::chrono::seconds(5);
|
||||
|
||||
|
||||
100
net/adc_netservice_asio.h
Normal file
100
net/adc_netservice_asio.h
Normal file
@ -0,0 +1,100 @@
|
||||
#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
|
||||
Loading…
x
Reference in New Issue
Block a user