This commit is contained in:
Timur A. Fatkhullin 2024-06-17 13:38:01 +03:00
parent 143f54b989
commit 1cefae2953
4 changed files with 137 additions and 25 deletions

View File

@ -41,6 +41,7 @@ if (ASIO_LIBRARY)
set(ADC_NETWORK_HEADERS ${ADC_NETWORK_HEADERS}
net/adc_netservice_asio.h
net/adc_netsession_asio.h
)
add_compile_definitions(PUBLIC USE_ASIO_LIBRARY)

View File

@ -16,6 +16,17 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
namespace adc
{
namespace traits
{
template <typename T>
// from https://stackoverflow.com/questions/74383254/concept-that-models-only-the-stdchrono-duration-types
concept adc_time_duration_c = requires {
[]<class Rep, class Period>(std::type_identity<std::chrono::duration<Rep, Period>>) {}(std::type_identity<T>());
};
} // namespace traits
template <typename ImplT>
class AdcNetService
@ -28,13 +39,7 @@ public:
using typename ImplT::endpoint_t;
using timeout_clock_t = std::chrono::steady_clock;
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);
using typename ImplT::timeout_t;
template <typename... ImplCtorArgTs>
AdcNetService(ImplCtorArgTs&&... ctor_args) : _impl(std::forward<ImplCtorArgTs>(ctor_args)...)
@ -49,22 +54,20 @@ public:
// open connection
template <typename... ArgTs>
auto asyncConnect(const endpoint_t& end_point,
const timeout_drtn_t& timeout = defaultConnectTimeout,
ArgTs&&... args)
auto asyncConnect(const endpoint_t& end_point, const timeout_t& timeout, ArgTs&&... args)
{
return _impl.asyncConnect(end_point, timeout, std::forward<ArgTs>(args)...);
}
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs>
auto asyncSend(const NetMessageT& msg, const timeout_drtn_t& timeout = defaultSendTimeout, ArgTs&&... args)
auto asyncSend(const NetMessageT& msg, const timeout_t& timeout, ArgTs&&... args)
{
return _impl.asyncSend(msg, timeout, std::forward<ArgTs>(args)...);
}
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs>
auto asyncReceive(const timeout_drtn_t& timeout = defaultRecvTimeout, ArgTs&&... args)
auto asyncReceive(const timeout_t& timeout, ArgTs&&... args)
{
return _impl.asyncReceive(timeout, std::forward<ArgTs>(args)...);
}
@ -74,20 +77,20 @@ public:
/* blocking operations */
template <typename... ArgTs>
auto connect(const endpoint_t& endpoint, const timeout_drtn_t& timeout = defaultConnectTimeout, ArgTs&&... args)
auto connect(const endpoint_t& endpoint, const timeout_t& timeout, ArgTs&&... args)
{
return _impl.connect(endpoint, timeout, std::forward<ArgTs>(args)...);
}
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs>
auto send(const NetMessageT& msg, const timeout_drtn_t& timeout = defaultSendTimeout, ArgTs&&... args)
auto send(const NetMessageT& msg, const timeout_t& timeout, ArgTs&&... args)
{
return _impl.send(msg, timeout, std::forward<ArgTs>(args)...);
}
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs>
NetMessageT receive(const timeout_drtn_t& timeout = defaultRecvTimeout, ArgTs&&... args)
NetMessageT receive(const timeout_t& timeout, ArgTs&&... args)
{
return _impl.receive(timeout, std::forward<ArgTs>(args)...);
}

View File

@ -58,20 +58,24 @@ namespace adc::impl
{
template <typename InetProtoT, typename HighLevelSocketT = typename InetProtoT::socket>
template <traits::adc_asio_inet_proto_c InetProtoT, typename HighLevelSocketT = typename InetProtoT::socket>
class AdcNetServiceASIO : public InetProtoT
{
public:
using socket_t = typename InetProtoT::socket;
using endpoint_t = typename InetProtoT::endpoint;
using inet_proto_t = InetProtoT;
using high_level_socket_t = HighLevelSocketT;
typedef std::chrono::steady_clock::duration timeout_t; // nanoseconds resolution
#ifdef USE_OPENSSL_WITH_ASIO
static_assert(std::is_same_v<HighLevelSocketT, socket_t>
? true
: std::is_same_v<HighLevelSocketT, asio::ssl::stream<InetProtoT>>,
: std::is_same_v<HighLevelSocketT, asio::ssl::stream<socket_t>>,
"ONLY BASIC SOCKETS AND SSL::STREAM ARE SUPPORTED!!!");
static constexpr bool IsBasicSocket = std::is_same_v<high_level_socket_t, socket_t>;
@ -88,7 +92,7 @@ public:
virtual ~AdcNetServiceASIO() = default;
template <typename TimeoutT, asio::completion_token_for<void(std::error_code)> CompletionTokenT>
template <traits::adc_time_duration_c TimeoutT, asio::completion_token_for<void(std::error_code)> CompletionTokenT>
auto asyncConnect(const endpoint_t& endpoint, const TimeoutT& timeout, CompletionTokenT&& token)
{
auto timer = getDeadlineTimer(timeout);
@ -123,7 +127,7 @@ public:
}
template <traits::adc_netmessage_c NetMessageT,
typename TimeoutT,
traits::adc_time_duration_c TimeoutT,
asio::completion_token_for<void(std::error_code)> CompletionTokenT>
auto asynSend(const NetMessageT& msg, const TimeoutT& timeout, CompletionTokenT&& token)
{
@ -171,7 +175,7 @@ public:
}
template <traits::adc_netmessage_c NetMessageT, typename TimeoutT, typename CompletionTokenT>
template <traits::adc_netmessage_c NetMessageT, traits::adc_time_duration_c TimeoutT, typename CompletionTokenT>
auto asyncReceive(const TimeoutT& timeout, CompletionTokenT&& token)
{
enum { starting, cancel_timer };
@ -241,21 +245,21 @@ public:
token, _socket);
}
template <typename TimeoutT>
template <traits::adc_time_duration_c TimeoutT>
auto connect(const endpoint_t& endpoint, const TimeoutT& timeout)
{
std::future<void> ftr = asyncConnect(endpoint, timeout, asio::use_future);
ftr.get();
}
template <traits::adc_netmessage_c NetMessageT, typename TimeoutT>
template <traits::adc_netmessage_c NetMessageT, traits::adc_time_duration_c TimeoutT>
auto send(const NetMessageT& msg, const TimeoutT& timeout)
{
std::future<void> ftr = asyncSend(msg, timeout, asio::use_future);
ftr.get();
}
template <traits::adc_netmessage_c NetMessageT, typename TimeoutT>
template <traits::adc_netmessage_c NetMessageT, traits::adc_time_duration_c TimeoutT>
auto receive(const TimeoutT& timeout)
{
std::future<NetMessageT> ftr = asyncReceive(timeout, asio::use_future);
@ -290,13 +294,13 @@ protected:
asio::streambuf _streamBuffer;
template <typename TimeoutT>
template <traits::adc_time_duration_c TimeoutT>
std::unique_ptr<asio::steady_timer> getDeadlineTimer(const TimeoutT& timeout, bool arm = true)
{
std::unique_ptr<asio::steady_timer> timer(_socket.get_executor());
if (arm) {
timer->expires_after(timeout);
timer->expires_after(std::chrono::duration_cast<timeout_t>(timeout));
timer->async_wait([this](const std::error_code& ec) {
if (!ec) {
@ -311,10 +315,25 @@ protected:
typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::tcp>> AdcNetServiceAsioTcp;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::tcp, asio::ssl::stream<asio::ip::tcp>>> AdcNetServiceAsioTls;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::seq_packet_protocol>> AdcNetServiceAsioLocalSeqPack;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::stream_protocol>> AdcNetServiceAsioLocalStream;
} // namespace adc::impl
namespace adc::traits
{
template <typename T>
concept adc_netservice_asio_c = requires {
typename T::inet_proto_t;
typename T::high_level_socket_t;
requires std::derived_from<T,
adc::impl::AdcNetServiceASIO<typename T::inet_proto_t, typename T::high_level_socket_t>>;
};
} // namespace adc::traits
#endif

89
net/adc_netsession_asio.h Normal file
View File

@ -0,0 +1,89 @@
#pragma once
/*
ABSTRACT DEVICE COMPONENTS LIBRARY
ASIO-library implementation of network server session
*/
#ifdef USE_ASIO_LIBRARY
#include "adc_netservice_asio.h"
// #ifdef USE_SPDLOG_LIBRARY
// #include "adc_netserver_spdlog.h"
// #endif // USE_SPDLOG_LIBRARY
namespace adc::impl
{
template <traits::adc_netservice_asio_c NetServiceT, typename ContextT = std::nullptr_t>
class AdcNetServerSessionASIO
{
public:
typedef std::string_view session_ident_t;
typedef NetServiceT netservice_t;
typedef ContextT context_t;
typedef std::chrono::duration<double, std::milli> timeout_t;
static constexpr timeout_t defaultSendTimeout = std::chrono::milliseconds(5000);
static constexpr timeout_t defaultRecvTimeout = std::chrono::milliseconds(5000);
template <traits::adc_input_char_range R>
AdcNetServerSessionASIO(netservice_t::socket_t&& sock, const R& sess_ident, ContextT&& context = nullptr)
: _socket(std::move(sock)),
_netService(_socket),
_sessionIdent(sess_ident.begin(), sess_ident.end()),
_context(context),
_sendTimeout(defaultSendTimeout),
_recvTimeout(defaultRecvTimeout)
{
}
virtual ~AdcNetServerSessionASIO()
{
_netService.close();
}
template <traits::adc_time_duration_c TimeoutT>
AdcNetServerSessionASIO& setDefaultTimeouts(const TimeoutT& send_timeout = defaultSendTimeout,
const TimeoutT& recv_timeout = defaultRecvTimeout)
{
_sendTimeout = send_timeout;
_recvTimeout = recv_timeout;
return *this;
}
session_ident_t sessionIdent() const
{
return {_sessionIdent.begin(), _sessionIdent.end()};
}
virtual void start() {}
virtual void stop() {}
protected:
netservice_t::socket_t _socket;
netservice_t _netService;
std::string _sessionIdent;
ContextT _context;
timeout_t _sendTimeout, _recvTimeout;
};
} // namespace adc::impl
#endif // USE_ASIO_LIBRARY