diff --git a/CMakeLists.txt b/CMakeLists.txt index 021e3f5..9664f2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/net/adc_netservice.h b/net/adc_netservice.h index 534291a..558c4b3 100644 --- a/net/adc_netservice.h +++ b/net/adc_netservice.h @@ -16,6 +16,17 @@ ABSTRACT DEVICE COMPONENTS LIBRARY namespace adc { +namespace traits +{ + +template +// from https://stackoverflow.com/questions/74383254/concept-that-models-only-the-stdchrono-duration-types +concept adc_time_duration_c = requires { + [](std::type_identity>) {}(std::type_identity()); +}; + +} // namespace traits + template 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 AdcNetService(ImplCtorArgTs&&... ctor_args) : _impl(std::forward(ctor_args)...) @@ -49,22 +54,20 @@ public: // open connection template - 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(args)...); } template - 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(args)...); } template - auto asyncReceive(const timeout_drtn_t& timeout = defaultRecvTimeout, ArgTs&&... args) + auto asyncReceive(const timeout_t& timeout, ArgTs&&... args) { return _impl.asyncReceive(timeout, std::forward(args)...); } @@ -74,20 +77,20 @@ public: /* blocking operations */ template - 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(args)...); } template - 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(args)...); } template - NetMessageT receive(const timeout_drtn_t& timeout = defaultRecvTimeout, ArgTs&&... args) + NetMessageT receive(const timeout_t& timeout, ArgTs&&... args) { return _impl.receive(timeout, std::forward(args)...); } diff --git a/net/adc_netservice_asio.h b/net/adc_netservice_asio.h index 88eac7b..1e5527a 100644 --- a/net/adc_netservice_asio.h +++ b/net/adc_netservice_asio.h @@ -58,20 +58,24 @@ namespace adc::impl { -template +template 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 ? true - : std::is_same_v>, + : std::is_same_v>, "ONLY BASIC SOCKETS AND SSL::STREAM ARE SUPPORTED!!!"); static constexpr bool IsBasicSocket = std::is_same_v; @@ -88,7 +92,7 @@ public: virtual ~AdcNetServiceASIO() = default; - template CompletionTokenT> + template CompletionTokenT> auto asyncConnect(const endpoint_t& endpoint, const TimeoutT& timeout, CompletionTokenT&& token) { auto timer = getDeadlineTimer(timeout); @@ -123,7 +127,7 @@ public: } template CompletionTokenT> auto asynSend(const NetMessageT& msg, const TimeoutT& timeout, CompletionTokenT&& token) { @@ -171,7 +175,7 @@ public: } - template + template auto asyncReceive(const TimeoutT& timeout, CompletionTokenT&& token) { enum { starting, cancel_timer }; @@ -241,21 +245,21 @@ public: token, _socket); } - template + template auto connect(const endpoint_t& endpoint, const TimeoutT& timeout) { std::future ftr = asyncConnect(endpoint, timeout, asio::use_future); ftr.get(); } - template + template auto send(const NetMessageT& msg, const TimeoutT& timeout) { std::future ftr = asyncSend(msg, timeout, asio::use_future); ftr.get(); } - template + template auto receive(const TimeoutT& timeout) { std::future ftr = asyncReceive(timeout, asio::use_future); @@ -290,13 +294,13 @@ protected: asio::streambuf _streamBuffer; - template + template std::unique_ptr getDeadlineTimer(const TimeoutT& timeout, bool arm = true) { std::unique_ptr timer(_socket.get_executor()); if (arm) { - timer->expires_after(timeout); + timer->expires_after(std::chrono::duration_cast(timeout)); timer->async_wait([this](const std::error_code& ec) { if (!ec) { @@ -311,10 +315,25 @@ protected: typedef AdcNetService> AdcNetServiceAsioTcp; +typedef AdcNetService>> AdcNetServiceAsioTls; typedef AdcNetService> AdcNetServiceAsioLocalSeqPack; typedef AdcNetService> AdcNetServiceAsioLocalStream; } // namespace adc::impl +namespace adc::traits +{ + +template +concept adc_netservice_asio_c = requires { + typename T::inet_proto_t; + typename T::high_level_socket_t; + + requires std::derived_from>; +}; + +} // namespace adc::traits + #endif diff --git a/net/adc_netsession_asio.h b/net/adc_netsession_asio.h new file mode 100644 index 0000000..667ff5d --- /dev/null +++ b/net/adc_netsession_asio.h @@ -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 +class AdcNetServerSessionASIO +{ +public: + typedef std::string_view session_ident_t; + + typedef NetServiceT netservice_t; + + typedef ContextT context_t; + + typedef std::chrono::duration timeout_t; + + static constexpr timeout_t defaultSendTimeout = std::chrono::milliseconds(5000); + static constexpr timeout_t defaultRecvTimeout = std::chrono::milliseconds(5000); + + template + 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 + 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