rewrite SESSION_PROTO.search

rewrite ASIO NETSERVICE.asyncReceive
rewrite ASIO NETSESSION
This commit is contained in:
Timur A. Fatkhullin 2024-09-29 00:40:38 +03:00
parent 242a0571e0
commit 8aef1a7c25
6 changed files with 285 additions and 176 deletions

View File

@ -211,5 +211,35 @@ concept adc_time_duration_c = requires {
}; };
template <adc_time_duration_c... Ts>
struct adc_duration_common_type;
template <adc_time_duration_c T1, adc_time_duration_c T2>
struct adc_duration_common_type<T1, T2> : std::common_type<T1, T2> {
};
template <adc_time_duration_c T1, adc_time_duration_c T2, adc_time_duration_c... Ts>
struct adc_duration_common_type<T1, T2, Ts...> : adc_duration_common_type<std::common_type_t<T1, T2>, Ts...> {
};
template <adc_time_duration_c... Ts>
using adc_duration_common_type_t = typename adc_duration_common_type<Ts...>::type;
/* all STL helper duration types */
using adc_common_duration_t = adc_duration_common_type_t<std::chrono::nanoseconds,
std::chrono::microseconds,
std::chrono::milliseconds,
std::chrono::seconds,
std::chrono::minutes,
std::chrono::hours,
std::chrono::days,
std::chrono::weeks,
std::chrono::months,
std::chrono::years>;
} // namespace adc::traits } // namespace adc::traits

View File

@ -93,45 +93,46 @@ concept adc_async_callback_t = traits::adc_is_callable<T> && traits::adc_func_tr
} }
*/ */
template <typename SRVT, template <typename SRVT>
typename SMSGT = std::vector<char>, // sending message type concept adc_netservice_c = std::movable<SRVT> && requires(SRVT srv, const SRVT srv_const) {
typename RMSGT = std::vector<char>, // receiving message type typename SRVT::netservice_ident_t; // service identificator type
typename DURT = adc_common_duration_t // time duration type
>
concept adc_netservice_c =
traits::adc_input_char_range<SMSGT> && traits::adc_output_char_range<RMSGT> && traits::adc_time_duration_c<DURT> &&
requires(SRVT srv, const SRVT srv_const) {
typename SRVT::netservice_ident_t;
// netservice_ident_t ident() const typename SRVT::send_msg_t; // sending message type
{ srv_const.ident() } -> std::same_as<typename SRVT::netservice_ident_t>; typename SRVT::recv_msg_t; // receiving message type
typename SRVT::timeout_t; // a type representing timeout (e.g. time duration)
typename SRVT::async_call_ctx_t; typename SRVT::endpoint_t; // a type representing endpoint of the network service
typename SRVT::endpoint_t; // underlying protocol
// asynchronous (non-blocking) operations // netservice_ident_t ident() const
srv.asyncAccept(std::declval<const typename SRVT::endpoint_t&>(), { srv_const.ident() } -> std::same_as<typename SRVT::netservice_ident_t>;
std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(), typename SRVT::async_call_ctx_t;
std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
srv.asyncSend(std::declval<const SMSGT&>(), std::declval<typename SRVT::async_call_ctx_t&>(),
std::declval<const DURT&>());
srv.asyncReceive(std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>()); // asynchronous (non-blocking) operations
srv.asyncAccept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<typename SRVT::async_call_ctx_t&>(),
std::declval<const typename SRVT::timeout_t&>());
// synchronous (blocking) operations srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<typename SRVT::async_call_ctx_t&>(),
srv.accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>()); std::declval<const typename SRVT::timeout_t&>());
srv.connect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>()); srv.asyncSend(std::declval<const typename SRVT::send_msg_t&>(), std::declval<typename SRVT::async_call_ctx_t&>(),
std::declval<const typename SRVT::timeout_t&>());
srv.send(std::declval<const SMSGT&>(), std::declval<const DURT&>()); srv.asyncReceive(std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const typename SRVT::timeout_t&>());
{ srv.receive(std::declval<const DURT&>()) } -> std::same_as<RMSGT>; // synchronous (blocking) operations
srv.accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const typename SRVT::timeout_t&>());
srv.close(); srv.connect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const typename SRVT::timeout_t&>());
};
srv.send(std::declval<const typename SRVT::send_msg_t&>(), std::declval<const typename SRVT::timeout_t&>());
{ srv.receive(std::declval<const typename SRVT::timeout_t&>()) } -> std::same_as<typename SRVT::recv_msg_t>;
srv.close();
};
/* NETWORK SESSION */ /* NETWORK SESSION */
@ -140,6 +141,7 @@ template <typename SESST>
concept adc_netsession_c = concept adc_netsession_c =
std::derived_from<SESST, std::enable_shared_from_this<SESST>> && requires(SESST sess, const SESST sess_const) { std::derived_from<SESST, std::enable_shared_from_this<SESST>> && requires(SESST sess, const SESST sess_const) {
typename SESST::netsession_ident_t; typename SESST::netsession_ident_t;
typename SESST::netsession_ctx_t;
// netsession_ident_t ident() const // netsession_ident_t ident() const
{ sess_const.ident() } -> std::same_as<typename SESST::netsession_ident_t>; { sess_const.ident() } -> std::same_as<typename SESST::netsession_ident_t>;
@ -169,7 +171,8 @@ concept adc_netsession_proto_c =
// flag - true if valid sequence was found, false - otherwise // flag - true if valid sequence was found, false - otherwise
{ {
proto.search(std::declval<const BUFFT&>()) proto.search(std::declval<const BUFFT&>())
} -> std::same_as<std::tuple<std::ranges::iterator_t<BUFFT>, std::ranges::iterator_t<BUFFT>, bool>>; // } -> std::same_as<std::tuple<std::ranges::iterator_t<BUFFT>, std::ranges::iterator_t<BUFFT>, bool>>;
} -> traits::adc_view_or_output_char_range;
// construct netsession protocol representation of input user byte sequence // construct netsession protocol representation of input user byte sequence

View File

@ -41,52 +41,67 @@ struct AdcStopSeqSessionProto {
return "STOP SEQUENCE PROTO"; return "STOP SEQUENCE PROTO";
} }
// template <traits::adc_input_char_range R>
// auto search(const R& r)
// {
// std::tuple<std::ranges::iterator_t<R>, std::ranges::iterator_t<R>, bool> res{r.begin(), r.end(), false};
// if (!r.size()) {
// return res;
// }
// // std::get<1>(res) = std::search(r.begin(), r.end(), STOP_SEQ.begin(), STOP_SEQ.end());
// auto found = std::ranges::search(r, STOP_SEQ);
// // if (std::get<1>(res) != r.end()) { // move iterator to the one-past-the-end position
// if (!found.empty()) { // move iterator to the one-past-the-end position
// // std::advance(std::get<1>(res), STOP_SEQ_SIZE);
// // std::get<1>(res) = found.begin() + STOP_SEQ_SIZE;
// std::get<1>(res) = found.end();
// std::get<2>(res) = true;
// }
// return res;
// }
template <traits::adc_input_char_range R> template <traits::adc_input_char_range R>
auto search(const R& r) auto search(const R& r)
{ {
std::tuple<std::ranges::iterator_t<R>, std::ranges::iterator_t<R>, bool> res{r.begin(), r.end(), false};
if (!r.size()) {
return res;
}
// std::get<1>(res) = std::search(r.begin(), r.end(), STOP_SEQ.begin(), STOP_SEQ.end());
auto found = std::ranges::search(r, STOP_SEQ); auto found = std::ranges::search(r, STOP_SEQ);
// if (std::get<1>(res) != r.end()) { // move iterator to the one-past-the-end position
if (!found.empty()) { // move iterator to the one-past-the-end position
// std::advance(std::get<1>(res), STOP_SEQ_SIZE);
// std::get<1>(res) = found.begin() + STOP_SEQ_SIZE;
std::get<1>(res) = found.end();
std::get<2>(res) = true;
}
return res; if constexpr (std::ranges::viewable_range<R>) {
} return found.empty() ? std::span(r.begin(), r.begin()) : std::span(r.begin(), found.end());
} else {
std::vector<char> res; // to guaranty adc_output_char_range
template <std::input_iterator IT> if (!found.empty()) {
auto search(IT begin, IT end) std::copy(r.begin(), found.end(), std::back_inserter(res));
{ }
std::tuple<IT, IT, bool> res{begin, end, false};
if (begin == end) {
return res; return res;
} }
auto it = std::search(begin, end, STOP_SEQ.begin(), STOP_SEQ.end());
if (it != end) {
// std::advance(it, STOP_SEQ_SIZE); // move iterator to the one-past-the-end position
std::get<1>(res) = it + STOP_SEQ_SIZE;
std::get<2>(res) = true;
} else {
// may be only a part of valid byte sequence was received,
// so start next matching from previous begin-iterator
std::get<1>(res) = begin;
}
return res;
} }
// template <std::input_iterator IT>
// auto search(IT begin, IT end)
// {
// std::tuple<IT, IT, bool> res{begin, end, false};
// if (begin == end) {
// return res;
// }
// auto it = std::search(begin, end, STOP_SEQ.begin(), STOP_SEQ.end());
// if (it != end) {
// // std::advance(it, STOP_SEQ_SIZE); // move iterator to the one-past-the-end position
// std::get<1>(res) = it + STOP_SEQ_SIZE;
// std::get<2>(res) = true;
// } else {
// // may be only a part of valid byte sequence was received,
// // so start next matching from previous begin-iterator
// std::get<1>(res) = begin;
// }
// return res;
// }
template <traits::adc_input_char_range R> template <traits::adc_input_char_range R>
auto toProto(const R& r) auto toProto(const R& r)
{ {

View File

@ -25,7 +25,6 @@ namespace adc
{ {
class AdcNetServer class AdcNetServer
{ {
protected: protected:
@ -41,10 +40,28 @@ public:
return _serverIdent; return _serverIdent;
} }
template <interfaces::adc_netservice_c SRVT> template <interfaces::adc_netsession_c SessionT, typename... NetsrvCtorArgTs>
void start(SRVT&& netservice, const typename SRVT::endpoint_t& endpoint) {}; void start(const typename SessionT::netservice_t::endpoint_t& endpoint,
const typename SessionT::netsession_ident_t& id,
typename SessionT::netsession_ctx_t&& sess_ctx,
NetsrvCtorArgTs&&... ctor_args)
{
typename SessionT::netservice_t netservice(std::forward<NetsrvCtorArgTs>(ctor_args)...);
virtual void stop() {}; netservice.asyncAccept(endpoint, [&endpoint, &id, sess_ctx, this](auto ec, auto...) {
if (!ec) {
auto sess = std::make_shared<SessionT>(id, std::forward<typename SessionT::netsession_ctx_t>(sess_ctx));
startSession(sess);
start(endpoint, id, sess_ctx);
}
});
};
virtual void stop()
{
stopAllSessions();
};
// run server as daemon (still only on POSIX OSes) // run server as daemon (still only on POSIX OSes)

View File

@ -8,8 +8,10 @@
#include <asio/deferred.hpp> #include <asio/deferred.hpp>
#include <asio/ip/tcp.hpp> #include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp> #include <asio/ip/udp.hpp>
#include <asio/local/datagram_protocol.hpp>
#include <asio/local/seq_packet_protocol.hpp> #include <asio/local/seq_packet_protocol.hpp>
#include <asio/local/stream_protocol.hpp> #include <asio/local/stream_protocol.hpp>
#include <asio/read.hpp>
#include <asio/read_until.hpp> #include <asio/read_until.hpp>
#include <asio/steady_timer.hpp> #include <asio/steady_timer.hpp>
#include <asio/strand.hpp> #include <asio/strand.hpp>
@ -46,7 +48,8 @@ using asio_matchcond_result_t = std::pair<asio_streambuff_iter_t, bool>;
template <typename T> template <typename T>
concept adc_asio_transport_proto_c = concept adc_asio_transport_proto_c =
std::derived_from<T, asio::ip::tcp> || std::derived_from<T, asio::ip::udp> || 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> ||
std::derived_from<T, asio::local::datagram_protocol>;
template <typename T> template <typename T>
@ -90,23 +93,33 @@ concept adc_asio_special_comp_token_c =
template <adc_asio_transport_proto_c TRANSPORT_PROTOT, template <adc_asio_transport_proto_c TRANSPORT_PROTOT,
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT, interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
traits::adc_output_char_range RMSGT = std::vector<char>> traits::adc_output_char_range RMSGT =
std::vector<char>> // used only for inner storing of message byte sequence
class AdcNetServiceASIOBase : public SESSION_PROTOT class AdcNetServiceASIOBase : public SESSION_PROTOT
{ {
public: public:
// typedefs to satisfy 'adc_netservice_c' concept
typedef std::string_view netservice_ident_t; typedef std::string_view netservice_ident_t;
using socket_t = typename TRANSPORT_PROTOT::socket; typedef std::vector<char> send_msg_t; // in general, only one of several possible
typedef RMSGT recv_msg_t; // in general, only one of several possible (see class template arguments declaration)
typedef traits::adc_common_duration_t timeout_t;
using endpoint_t = typename TRANSPORT_PROTOT::endpoint; using endpoint_t = typename TRANSPORT_PROTOT::endpoint;
// typedefs for completion tokens (callbacks, required by 'adc_netservice_c' concept)
typedef std::function<void(std::error_code)> async_accept_callback_t;
typedef std::function<void(std::error_code)> async_connect_callback_t;
typedef std::function<void(std::error_code)> async_send_callback_t;
typedef std::function<void(std::error_code, RMSGT)> async_receive_callback_t;
// typedefs from transport protocol
using socket_t = typename TRANSPORT_PROTOT::socket;
using acceptor_t = using acceptor_t =
std::conditional_t<std::derived_from<socket_t, asio::basic_datagram_socket<typename socket_t::protocol_type>>, std::conditional_t<std::derived_from<socket_t, asio::basic_datagram_socket<typename socket_t::protocol_type>>,
std::nullptr_t, // there is no acceptor std::nullptr_t, // there is no acceptor
typename TRANSPORT_PROTOT::acceptor>; typename TRANSPORT_PROTOT::acceptor>;
typedef std::function<void(std::error_code)> async_accept_callback_t;
typedef std::function<void(std::error_code)> async_connect_callback_t;
typedef std::function<void(std::error_code)> async_send_callback_t;
typedef std::function<void(std::error_code, RMSGT)> async_receive_callback_t;
// to satisfy 'adc_netservice_c' concept // to satisfy 'adc_netservice_c' concept
@ -361,59 +374,35 @@ public:
adc_asio_special_comp_token_c<TokenT> || is_async_ctx_t, RMSGT, adc_asio_special_comp_token_c<TokenT> || is_async_ctx_t, RMSGT,
std::remove_cvref_t<std::tuple_element_t<1, typename traits::adc_func_traits<TokenT>::args_t>>>; std::remove_cvref_t<std::tuple_element_t<1, typename traits::adc_func_traits<TokenT>::args_t>>>;
// auto s_res = std::make_shared<std::invoke_result_t<decltype(this->template search<RMSGT>), RMSGT>>();
// auto tp = this->search(std::span<const char>());
// auto s_res = std::make_shared<decltype(tp)>();
auto s_res = std::make_shared<std::tuple<asio_streambuff_iter_t, asio_streambuff_iter_t, bool>>();
auto out_flags = std::make_shared<asio::socket_base::message_flags>(); auto out_flags = std::make_shared<asio::socket_base::message_flags>();
auto timer = getDeadlineTimer(_socket, timeout); auto timer = getDeadlineTimer(_socket, timeout);
return asio::async_compose<TokenT, void(asio::error_code, msg_t)>( return asio::async_compose<TokenT, void(asio::error_code, msg_t)>(
[s_res, out_flags, start = true, timer = std::move(timer), this](auto& self, asio::error_code ec = {}, [out_flags, do_read = true, timer = std::move(timer), this](auto& self, asio::error_code ec = {},
size_t = 0) mutable { size_t nbytes = 0) mutable {
RMSGT msg; // RMSGT msg;
msg_t msg;
if (!ec) { if (!ec) {
if (start) { if (do_read) {
start = false; do_read = false;
if (_receiveQueue.size()) { // return message from queue if (_receiveQueue.size()) { // return message from queue
timer->cancel(); timer->cancel();
msg = _receiveQueue.front(); auto imsg = _receiveQueue.front();
_receiveQueue.pop(); _receiveQueue.pop();
if constexpr (std::is_same_v<msg_t, RMSGT>) { if constexpr (std::is_same_v<msg_t, RMSGT>) {
self.complete(std::error_code(), std::move(msg)); self.complete(std::error_code(), std::move(imsg));
} else { } else {
// msg_t user_msg{msg.begin(), msg.end()}; self.complete(std::error_code(), {imsg.begin(), imsg.end()});
self.complete(std::error_code(), {msg.begin(), msg.end()});
} }
return; return;
} }
if constexpr (std::derived_from<socket_t, if constexpr (std::derived_from<socket_t,
asio::basic_stream_socket<typename socket_t::protocol_type>>) { asio::basic_stream_socket<typename socket_t::protocol_type>>) {
// adapt to ASIO's MatchCondition return asio::async_read(_socket, _streamBuffer, asio::transfer_at_least(1),
auto match_func = std::move(self));
std::function<asio_matchcond_result_t(asio_streambuff_iter_t, asio_streambuff_iter_t)>(
[s_res, this](asio_streambuff_iter_t begin, asio_streambuff_iter_t end) {
// *s_res = this->search(std::span(&*begin, &*end));
*s_res = this->search(begin, end);
auto N = std::distance(std::get<0>(*s_res), std::get<1>(*s_res));
asio_matchcond_result_t res{begin + N, std::get<2>(*s_res)};
return res;
});
return asio::async_read_until(_socket, _streamBuffer, std::move(match_func),
std::move(self));
// return asio::async_read_until(
// _socket, _streamBuffer,
// std::bind(&AdcNetServiceASIOBase::template MatchCondition<decltype(s_res)>, this,
// std::placeholders::_1, std::placeholders::_2, s_res),
// std::move(self));
} else if constexpr (std::derived_from<socket_t, asio::basic_datagram_socket< } else if constexpr (std::derived_from<socket_t, asio::basic_datagram_socket<
typename socket_t::protocol_type>>) { typename socket_t::protocol_type>>) {
// datagram, so it should be received at once // datagram, so it should be received at once
@ -427,54 +416,49 @@ public:
} }
} }
// if (!nbytes) {
// do_read = true;
// asio::post(std::move(self)); // initiate consequence socket's read operation
// return;
// }
auto start_ptr = static_cast<const char*>(_streamBuffer.data().data());
if constexpr (std::derived_from<socket_t, // auto sr = this->search(std::span(start_ptr, _streamBuffer.size()));
asio::basic_datagram_socket<typename socket_t::protocol_type>> || auto net_pack = this->search(std::span(start_ptr, _streamBuffer.size()));
std::derived_from<socket_t, // if (!std::get<2>(sr)) {
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) { if (net_pack.empty()) {
auto begin_it = asio::buffers_begin(_streamBuffer.data()); do_read = true;
auto end_it = asio::buffers_end(_streamBuffer.data()); asio::post(std::move(self)); // initiate consequence socket's read operation
return;
*s_res = this->search(begin_it, end_it); }
if (!std::get<2>(*s_res)) { // partial or too big packet?!!
// For these types of sockets it is an error!
// ec = std::make_error_code(std::errc::protocol_error);
// self.complete(ec, msg_t());
start = true;
asio::post(std::move(self)); // initiate consequence socket's read operation
return;
}
} // here, the iterators were computed in MatchCondition called by asio::async_read_until
// function!!!
timer->cancel(); // there were no errors in the asynchronous read-operation, so stop timer timer->cancel(); // there were no errors in the asynchronous read-operation, so stop timer
size_t N = std::distance(std::get<0>(*s_res), std::get<1>(*s_res)); // here one has at least a single message
std::span net_pack{&*std::get<0>(*s_res), N}; // size_t N = std::distance(std::get<0>(sr), std::get<1>(sr));
// auto net_pack = std::span{start_ptr, N};
std::ranges::copy(this->fromProto(net_pack), std::back_inserter(msg)); std::ranges::copy(this->fromProto(net_pack), std::back_inserter(msg));
_streamBuffer.consume(net_pack.size()); _streamBuffer.consume(net_pack.size());
while (_streamBuffer.size()) { // search for possible additional session protocol packets while (_streamBuffer.size()) { // search for possible additional session protocol packets
start_ptr = static_cast<const char*>(_streamBuffer.data().data());
auto begin_it = asio::buffers_begin(_streamBuffer.data()); // sr = this->search(std::span(start_ptr, _streamBuffer.size()));
auto end_it = asio::buffers_end(_streamBuffer.data()); net_pack = this->search(std::span(start_ptr, _streamBuffer.size()));
if (!net_pack.empty()) {
// *s_res = this->search(std::span(begin_it, end_it)); // if (std::get<2>(sr)) {
*s_res = this->search(begin_it, end_it); // N = std::distance(std::get<0>(sr), std::get<1>(sr));
if (std::get<2>(*s_res)) { // net_pack = std::span{start_ptr, N};
// net_pack = std::string_view{std::get<0>(*s_res), std::get<1>(*s_res)};
N = std::distance(std::get<0>(*s_res), std::get<1>(*s_res));
net_pack = std::span{&*std::get<0>(*s_res), N};
_receiveQueue.emplace(); _receiveQueue.emplace();
std::ranges::copy(this->fromProto(net_pack), std::back_inserter(_receiveQueue.back())); std::ranges::copy(this->fromProto(net_pack), std::back_inserter(_receiveQueue.back()));
_streamBuffer.consume(net_pack.size()); _streamBuffer.consume(net_pack.size());
} else { } else {
break; break; // exit and hold remaining bytes in stream buffer
} }
} }
} }
@ -579,29 +563,6 @@ protected:
asio::socket_base::shutdown_type _shutdownType = asio::socket_base::shutdown_both; asio::socket_base::shutdown_type _shutdownType = asio::socket_base::shutdown_both;
template <typename T>
auto MatchCondition(asio_streambuff_iter_t begin, asio_streambuff_iter_t end, T& s_res)
{
// if (begin == end) {
// *s_res = this->search(std::span<const char>());
// } else {
// *s_res = this->search(std::span(&*begin, &*end));
// }
*s_res = this->search(begin, end);
// return std::make_pair(std::get<1>(*s_res), std::get<2>(*s_res));
std::pair<asio_streambuff_iter_t, bool> res{end, false};
typename std::iterator_traits<asio_streambuff_iter_t>::difference_type N = 0;
if (std::get<2>(*s_res)) {
N = std::distance(std::get<0>(*s_res), std::get<1>(*s_res));
res = std::make_pair(begin + N, true);
}
return res;
};
template <typename CancelableT, traits::adc_time_duration_c TimeoutT> template <typename CancelableT, traits::adc_time_duration_c TimeoutT>
static std::unique_ptr<asio::steady_timer> getDeadlineTimer(CancelableT& obj, static std::unique_ptr<asio::steady_timer> getDeadlineTimer(CancelableT& obj,

View File

@ -5,7 +5,90 @@
namespace adc::impl namespace adc::impl
{ {
class AdcNetSessionASIO template <typename SessionContextT,
adc_asio_transport_proto_c TRANSPORT_PROTOT,
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
traits::adc_output_char_range RMSGT = std::vector<char>>
class AdcGenericNetSessionASIO : public std::enable_shared_from_this<
AdcGenericNetSessionASIO<SessionContextT, TRANSPORT_PROTOT, SESSION_PROTOT, RMSGT>>
{
public:
typedef std::string netsession_ident_t;
typedef SessionContextT netsession_ctx_t;
typedef AdcNetServiceASIOBase<TRANSPORT_PROTOT, SESSION_PROTOT, RMSGT> netservice_t;
template <traits::adc_input_char_range R, traits::adc_is_callable RECV_MSG_TOKENT>
AdcGenericNetSessionASIO(const R& id, netservice_t netservice, netsession_ctx_t&& context)
: _ident(), _netservice(std::move(netservice)), _sessionContext(std::forward<netsession_ctx_t>(context))
{
if constexpr (std::is_array_v<R>) {
_ident = id;
} else {
_ident = std::string(id.begin(), id.end());
}
}
AdcGenericNetSessionASIO(netservice_t netservice, netsession_ctx_t&& context)
: AdcGenericNetSessionASIO(
std::derived_from<TRANSPORT_PROTOT, asio::ip::tcp> ? "ASIO TCP SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::ip::udp> ? "ASIO UDP SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::local::seq_packet_protocol> ? "ASIO UNIX SEQPACKET SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::local::stream_protocol> ? "ASIO UNIX STREAM SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::local::datagram_protocol> ? "ASIO UNIX DATAGRAM SESSION"
: "ASIO UNKNOWN",
std::move(netservice),
std::forward<netsession_ctx_t>(context))
{
}
virtual ~AdcGenericNetSessionASIO()
{
stop();
}
netsession_ident_t ident() const
{
return _ident;
}
virtual void start() = 0;
virtual void stop()
{
_netservice->close();
}
template <traits::adc_time_duration_c TimeoutT>
AdcGenericNetSessionASIO& setDefaultTimeouts(const TimeoutT& send_timeout, const TimeoutT& recv_timeout)
{
_sendTimeout = send_timeout;
_recvTimeout = recv_timeout;
return *this;
}
protected:
netsession_ident_t _ident;
std::shared_ptr<netservice_t> _netservice;
netsession_ctx_t _sessionContext;
std::chrono::duration<std::chrono::seconds::rep, std::chrono::seconds::period> _recvTimeout =
std::chrono::seconds::max();
std::chrono::duration<std::chrono::seconds::rep, std::chrono::seconds::period> _sendTimeout =
std::chrono::seconds(5);
};
/*
class AdcGenericNetSessionASIO
{ {
public: public:
typedef std::string netsession_ident_t; typedef std::string netsession_ident_t;
@ -15,7 +98,7 @@ public:
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT, interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
traits::adc_output_char_range RMSGT = std::vector<char>, traits::adc_output_char_range RMSGT = std::vector<char>,
traits::adc_is_callable RECV_MSG_TOKENT> traits::adc_is_callable RECV_MSG_TOKENT>
AdcNetSessionASIO(const R& id, AdcGenericNetSessionASIO(const R& id,
std::shared_ptr<AdcNetServiceASIOBase<TRANSPORT_PROTOT, SESSION_PROTOT, RMSGT>> netservice, std::shared_ptr<AdcNetServiceASIOBase<TRANSPORT_PROTOT, SESSION_PROTOT, RMSGT>> netservice,
RECV_MSG_TOKENT&& recv_msg_token) RECV_MSG_TOKENT&& recv_msg_token)
: _ident(id.begin(), id.end()) : _ident(id.begin(), id.end())
@ -52,21 +135,19 @@ public:
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT, interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
traits::adc_output_char_range RMSGT = std::vector<char>, traits::adc_output_char_range RMSGT = std::vector<char>,
traits::adc_is_callable RECV_MSG_TOKENT> traits::adc_is_callable RECV_MSG_TOKENT>
AdcNetSessionASIO(std::shared_ptr<AdcNetServiceASIOBase<TRANSPORT_PROTOT, SESSION_PROTOT, RMSGT>> netservice, AdcGenericNetSessionASIO(std::shared_ptr<AdcNetServiceASIOBase<TRANSPORT_PROTOT, SESSION_PROTOT, RMSGT>> netservice,
RECV_MSG_TOKENT&& recv_msg_token) RECV_MSG_TOKENT&& recv_msg_token)
: AdcNetSessionASIO(std::derived_from<TRANSPORT_PROTOT, asio::ip::tcp> ? "TCP SESSION" : AdcGenericNetSessionASIO(std::derived_from<TRANSPORT_PROTOT, asio::ip::tcp> ? "TCP SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::ip::udp> ? "UDP SESSION" : std::derived_from<TRANSPORT_PROTOT, asio::ip::udp> ? "UDP SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::local::seq_packet_protocol> : std::derived_from<TRANSPORT_PROTOT, asio::local::seq_packet_protocol>
? "UNIX SEQPACKET SESSION" ? "UNIX SEQPACKET SESSION"
: std::derived_from<TRANSPORT_PROTOT, asio::local::stream_protocol> ? "UNIX STREAM SESSION" : std::derived_from<TRANSPORT_PROTOT, asio::local::stream_protocol> ? "UNIX STREAM
: "UNKNOWN", SESSION" : "UNKNOWN", std::move(netservice), std::forward<RECV_MSG_TOKENT>(recv_msg_token))
std::move(netservice),
std::forward<RECV_MSG_TOKENT>(recv_msg_token))
{ {
} }
virtual ~AdcNetSessionASIO() virtual ~AdcGenericNetSessionASIO()
{ {
stop(); stop();
} }
@ -90,7 +171,7 @@ public:
template <traits::adc_time_duration_c TimeoutT> template <traits::adc_time_duration_c TimeoutT>
AdcNetSessionASIO& setDefaultTimeouts(const TimeoutT& send_timeout, const TimeoutT& recv_timeout) AdcGenericNetSessionASIO& setDefaultTimeouts(const TimeoutT& send_timeout, const TimeoutT& recv_timeout)
{ {
_sendTimeout = send_timeout; _sendTimeout = send_timeout;
_recvTimeout = recv_timeout; _recvTimeout = recv_timeout;
@ -111,4 +192,6 @@ protected:
std::chrono::seconds(5); std::chrono::seconds(5);
}; };
*/
} // namespace adc::impl } // namespace adc::impl