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} set(ADC_NETWORK_HEADERS ${ADC_NETWORK_HEADERS}
net/adc_netservice_asio.h net/adc_netservice_asio.h
net/adc_netsession_asio.h
) )
add_compile_definitions(PUBLIC USE_ASIO_LIBRARY) add_compile_definitions(PUBLIC USE_ASIO_LIBRARY)

View File

@ -16,6 +16,17 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
namespace adc 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> template <typename ImplT>
class AdcNetService class AdcNetService
@ -28,13 +39,7 @@ public:
using typename ImplT::endpoint_t; using typename ImplT::endpoint_t;
using timeout_clock_t = std::chrono::steady_clock; using typename ImplT::timeout_t;
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);
template <typename... ImplCtorArgTs> template <typename... ImplCtorArgTs>
AdcNetService(ImplCtorArgTs&&... ctor_args) : _impl(std::forward<ImplCtorArgTs>(ctor_args)...) AdcNetService(ImplCtorArgTs&&... ctor_args) : _impl(std::forward<ImplCtorArgTs>(ctor_args)...)
@ -49,22 +54,20 @@ public:
// open connection // open connection
template <typename... ArgTs> template <typename... ArgTs>
auto asyncConnect(const endpoint_t& end_point, auto asyncConnect(const endpoint_t& end_point, const timeout_t& timeout, ArgTs&&... args)
const timeout_drtn_t& timeout = defaultConnectTimeout,
ArgTs&&... args)
{ {
return _impl.asyncConnect(end_point, timeout, std::forward<ArgTs>(args)...); return _impl.asyncConnect(end_point, timeout, std::forward<ArgTs>(args)...);
} }
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs> 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)...); return _impl.asyncSend(msg, timeout, std::forward<ArgTs>(args)...);
} }
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs> 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)...); return _impl.asyncReceive(timeout, std::forward<ArgTs>(args)...);
} }
@ -74,20 +77,20 @@ public:
/* blocking operations */ /* blocking operations */
template <typename... ArgTs> 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)...); return _impl.connect(endpoint, timeout, std::forward<ArgTs>(args)...);
} }
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs> 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)...); return _impl.send(msg, timeout, std::forward<ArgTs>(args)...);
} }
template <traits::adc_netmessage_c NetMessageT, typename... ArgTs> 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)...); 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 class AdcNetServiceASIO : public InetProtoT
{ {
public: public:
using socket_t = typename InetProtoT::socket; using socket_t = typename InetProtoT::socket;
using endpoint_t = typename InetProtoT::endpoint; using endpoint_t = typename InetProtoT::endpoint;
using inet_proto_t = InetProtoT;
using high_level_socket_t = HighLevelSocketT; using high_level_socket_t = HighLevelSocketT;
typedef std::chrono::steady_clock::duration timeout_t; // nanoseconds resolution
#ifdef USE_OPENSSL_WITH_ASIO #ifdef USE_OPENSSL_WITH_ASIO
static_assert(std::is_same_v<HighLevelSocketT, socket_t> static_assert(std::is_same_v<HighLevelSocketT, socket_t>
? true ? 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!!!"); "ONLY BASIC SOCKETS AND SSL::STREAM ARE SUPPORTED!!!");
static constexpr bool IsBasicSocket = std::is_same_v<high_level_socket_t, socket_t>; static constexpr bool IsBasicSocket = std::is_same_v<high_level_socket_t, socket_t>;
@ -88,7 +92,7 @@ public:
virtual ~AdcNetServiceASIO() = default; 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 asyncConnect(const endpoint_t& endpoint, const TimeoutT& timeout, CompletionTokenT&& token)
{ {
auto timer = getDeadlineTimer(timeout); auto timer = getDeadlineTimer(timeout);
@ -123,7 +127,7 @@ public:
} }
template <traits::adc_netmessage_c NetMessageT, template <traits::adc_netmessage_c NetMessageT,
typename TimeoutT, traits::adc_time_duration_c TimeoutT,
asio::completion_token_for<void(std::error_code)> CompletionTokenT> asio::completion_token_for<void(std::error_code)> CompletionTokenT>
auto asynSend(const NetMessageT& msg, const TimeoutT& timeout, CompletionTokenT&& token) 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) auto asyncReceive(const TimeoutT& timeout, CompletionTokenT&& token)
{ {
enum { starting, cancel_timer }; enum { starting, cancel_timer };
@ -241,21 +245,21 @@ public:
token, _socket); token, _socket);
} }
template <typename TimeoutT> template <traits::adc_time_duration_c TimeoutT>
auto connect(const endpoint_t& endpoint, const TimeoutT& timeout) auto connect(const endpoint_t& endpoint, const TimeoutT& timeout)
{ {
std::future<void> ftr = asyncConnect(endpoint, timeout, asio::use_future); std::future<void> ftr = asyncConnect(endpoint, timeout, asio::use_future);
ftr.get(); 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) auto send(const NetMessageT& msg, const TimeoutT& timeout)
{ {
std::future<void> ftr = asyncSend(msg, timeout, asio::use_future); std::future<void> ftr = asyncSend(msg, timeout, asio::use_future);
ftr.get(); 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) auto receive(const TimeoutT& timeout)
{ {
std::future<NetMessageT> ftr = asyncReceive(timeout, asio::use_future); std::future<NetMessageT> ftr = asyncReceive(timeout, asio::use_future);
@ -290,13 +294,13 @@ protected:
asio::streambuf _streamBuffer; 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> getDeadlineTimer(const TimeoutT& timeout, bool arm = true)
{ {
std::unique_ptr<asio::steady_timer> timer(_socket.get_executor()); std::unique_ptr<asio::steady_timer> timer(_socket.get_executor());
if (arm) { 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) { timer->async_wait([this](const std::error_code& ec) {
if (!ec) { if (!ec) {
@ -311,10 +315,25 @@ protected:
typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::tcp>> AdcNetServiceAsioTcp; 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::seq_packet_protocol>> AdcNetServiceAsioLocalSeqPack;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::stream_protocol>> AdcNetServiceAsioLocalStream; typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::stream_protocol>> AdcNetServiceAsioLocalStream;
} // namespace adc::impl } // 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 #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