This commit is contained in:
Timur A. Fatkhullin 2024-06-18 17:30:11 +03:00
parent ebe93f1d74
commit 9f915d932f
3 changed files with 98 additions and 21 deletions

View File

@ -44,6 +44,36 @@ concept adc_netserver_session_impl_c = requires(T t, const T t_const) {
/* Server session */
class AdcNetServerGenericSession
{
public:
struct Opt {
std::function<void()> startSess;
std::function<void()> stopSess;
std::function<void()> run;
};
AdcNetServerGenericSession(Opt&& opts) : _opts(std::move(opts)) {}
virtual void start()
{
_opts.startSess();
}
virtual void stop()
{
_opts.stopSess();
}
protected:
Opt _opts;
virtual void run()
{
_opts.run();
}
};
template <traits::adc_netserver_session_impl_c ImplT>
class AdcNetServerSession : std::enable_shared_from_this<AdcNetServerSession<ImplT>>
{

View File

@ -44,15 +44,26 @@
namespace adc::traits
{
// typedef for ASIO streambuf iterators
using asio_streambuff_iter_t = asio::buffers_iterator<asio::streambuf::const_buffers_type>;
// still only TCP, UDP and UNIX
template <typename T>
concept adc_asio_inet_proto_c =
concept adc_asio_inet_proto_c = requires(T t, asio_streambuff_iter_t begin, asio_streambuff_iter_t end) {
std::derived_from<T, asio::ip::tcp> || std::derived_from<T, asio::ip::udp> ||
std::derived_from<T, asio::local::seq_packet_protocol> || std::derived_from<T, asio::local::stream_protocol>;
std::derived_from<T, asio::local::seq_packet_protocol> || std::derived_from<T, asio::local::stream_protocol>;
{ t.matchCondition(begin, end) } -> std::same_as<std::pair<asio_streambuff_iter_t, bool>>;
{ t.fromLowLevel(begin, end) } -> std::same_as<std::pair<asio_streambuff_iter_t, bool>>;
};
// only stream-based protocols
template <typename T>
concept adc_asio_inet_stream_proto_c =
concept adc_asio_inet_stream_proto_c = requires(T t, asio_streambuff_iter_t begin, asio_streambuff_iter_t end) {
std::derived_from<T, asio::ip::tcp> || std::derived_from<T, asio::local::stream_protocol>;
{ t.matchCondition(begin, end) } -> std::same_as<std::pair<asio_streambuff_iter_t, bool>>;
{ t.fromLowLevel(begin, end) } -> std::same_as<std::pair<asio_streambuff_iter_t, bool>>;
};
} // namespace adc::traits
@ -77,14 +88,16 @@ public:
typedef std::chrono::steady_clock::duration timeout_t; // nanoseconds resolution
using streambuff_iter_t = asio::buffers_iterator<asio::streambuf::const_buffers_type>;
AdcNetServiceASIO(asio::io_context& io_context) : _ioContext(io_context), _socket(io_context), _acceptor(io_context)
{
}
virtual ~AdcNetServiceASIO() = default;
const asio::io_context& getExecutor() const
{
return _ioContext;
}
template <traits::adc_time_duration_c TimeoutT, asio::completion_token_for<void(std::error_code)> CompletionTokenT>
auto asyncAccept(const endpoint_t& endpoint, const TimeoutT& timeout, CompletionTokenT&& token)
@ -210,7 +223,9 @@ public:
}
template <traits::adc_netmessage_c NetMessageT, traits::adc_time_duration_c TimeoutT, typename CompletionTokenT>
template <traits::adc_netmessage_c NetMessageT,
traits::adc_time_duration_c TimeoutT,
asio::completion_token_for<void(std::error_code, const NetMessageT&)> CompletionTokenT>
auto asyncReceive(const TimeoutT& timeout, CompletionTokenT&& token)
{
enum { starting, finishing };
@ -251,7 +266,7 @@ public:
break;
}
auto begin_it = streambuff_iter_t::begin(_streamBuffer.data());
auto begin_it = traits::asio_streambuff_iter_t::begin(_streamBuffer.data());
auto end_it = begin_it + _streamBuffer.data().size();
// check for byte sequence is valid byte sequence and find the limits
@ -368,7 +383,7 @@ public:
typedef std::function<int(const std::string& serial, const std::vector<unsigned char>& fingerprint, int depth)>
cert_comp_func_t;
using streambuff_iter_t = asio::buffers_iterator<asio::streambuf::const_buffers_type>;
using asio_streambuff_iter_t = asio::buffers_iterator<asio::streambuf::const_buffers_type>;
AdcNetServiceAsioTls(asio::io_context& io_context,
asio::ssl::context&& tls_context = asio::ssl::context(asio::ssl::context::tlsv13),
@ -540,7 +555,7 @@ public:
break;
}
auto begin_it = streambuff_iter_t::begin(_streamBuffer.data());
auto begin_it = asio_streambuff_iter_t::begin(_streamBuffer.data());
auto end_it = begin_it + _streamBuffer.data().size();
// check for byte sequence is valid byte sequence and find the limits
@ -708,10 +723,10 @@ protected:
};
#endif
typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::tcp>> AdcNetServiceAsioTcp;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::udp>> AdcNetServiceAsioUdp;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::seq_packet_protocol>> AdcNetServiceAsioLocalSeqPack;
typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::stream_protocol>> AdcNetServiceAsioLocalStream;
// typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::tcp>> AdcNetServiceAsioTcp;
// typedef AdcNetService<impl::AdcNetServiceASIO<asio::ip::udp>> AdcNetServiceAsioUdp;
// typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::seq_packet_protocol>> AdcNetServiceAsioLocalSeqPack;
// typedef AdcNetService<impl::AdcNetServiceASIO<asio::local::stream_protocol>> AdcNetServiceAsioLocalStream;
} // namespace adc::impl

View File

@ -21,7 +21,7 @@ namespace adc::impl
{
template <traits::adc_netservice_asio_c NetServiceT, typename ContextT = std::nullptr_t>
class AdcNetServerSessionASIO
class AdcNetServerSessionASIO : std::enable_shared_from_this<AdcNetServerSessionASIO<NetServiceT, ContextT>>
{
public:
typedef std::string_view session_ident_t;
@ -32,24 +32,43 @@ public:
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);
static constexpr timeout_t defaultSendTimeout = std::chrono::milliseconds(5000); // 5 seconds
static constexpr timeout_t defaultRecvTimeout =
std::chrono::hours(12); // actualy, it is a time to wait something from client
template <traits::adc_input_char_range R>
AdcNetServerSessionASIO(netservice_t::socket_t&& sock, const R& sess_ident, ContextT&& context = nullptr)
: _socket(std::move(sock)),
AdcNetServerSessionASIO(std::shared_ptr<netservice_t>& net_service,
const R& sess_ident,
ContextT&& context = nullptr)
: _socket(net_service.get_executor()),
// _socket(std::move(sock)),
_netService(_socket),
_sessionIdent(sess_ident.begin(), sess_ident.end()),
_context(context),
_sendTimeout(defaultSendTimeout),
_recvTimeout(defaultRecvTimeout)
{
// generic implementation
_stopFunc = [net_service = net_service]() { net_service->close(); };
_startFunc = [this]() { acceptMessage(); };
_acceptMessageFunc = [net_service = net_service, this]() {
net_service->asynReceive<NetMessageT>(
_recvTimeout, [self = this->shared_from_this(), this](std::error_code ec, const auto& mess) {
if (ec) {
stop();
} else {
acceptMessage();
}
});
};
}
virtual ~AdcNetServerSessionASIO()
{
_netService.close();
stop();
}
template <traits::adc_time_duration_c TimeoutT>
@ -68,10 +87,16 @@ public:
}
virtual void start() {}
virtual void start()
{
_startFunc();
}
virtual void stop() {}
virtual void stop()
{
_stopFunc();
}
protected:
netservice_t::socket_t _socket;
@ -81,6 +106,13 @@ protected:
ContextT _context;
timeout_t _sendTimeout, _recvTimeout;
std::function<void()> _startFunc, _stopFunc, _acceptMessageFunc;
virtual void acceptMessage()
{
_acceptMessageFunc();
}
};
} // namespace adc::impl