rewrite SESSION_PROTO.search
rewrite ASIO NETSERVICE.asyncReceive rewrite ASIO NETSESSION
This commit is contained in:
parent
242a0571e0
commit
8aef1a7c25
@ -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
|
||||
|
||||
@ -93,45 +93,46 @@ concept adc_async_callback_t = traits::adc_is_callable<T> && traits::adc_func_tr
|
||||
|
||||
}
|
||||
*/
|
||||
template <typename SRVT,
|
||||
typename SMSGT = std::vector<char>, // sending message type
|
||||
typename RMSGT = std::vector<char>, // receiving message 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;
|
||||
template <typename SRVT>
|
||||
concept adc_netservice_c = std::movable<SRVT> && requires(SRVT srv, const SRVT srv_const) {
|
||||
typename SRVT::netservice_ident_t; // service identificator type
|
||||
|
||||
// netservice_ident_t ident() const
|
||||
{ srv_const.ident() } -> std::same_as<typename SRVT::netservice_ident_t>;
|
||||
typename SRVT::send_msg_t; // sending message type
|
||||
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;
|
||||
typename SRVT::endpoint_t; // a type representing endpoint of the network service
|
||||
// underlying protocol
|
||||
|
||||
// asynchronous (non-blocking) operations
|
||||
srv.asyncAccept(std::declval<const typename SRVT::endpoint_t&>(),
|
||||
std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
|
||||
// netservice_ident_t ident() const
|
||||
{ srv_const.ident() } -> std::same_as<typename SRVT::netservice_ident_t>;
|
||||
|
||||
srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(),
|
||||
std::declval<typename SRVT::async_call_ctx_t&>(), std::declval<const DURT&>());
|
||||
typename SRVT::async_call_ctx_t;
|
||||
|
||||
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.accept(std::declval<const typename SRVT::endpoint_t&>(), std::declval<const DURT&>());
|
||||
srv.asyncConnect(std::declval<const typename SRVT::endpoint_t&>(), std::declval<typename SRVT::async_call_ctx_t&>(),
|
||||
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 */
|
||||
@ -140,6 +141,7 @@ template <typename SESST>
|
||||
concept adc_netsession_c =
|
||||
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_ctx_t;
|
||||
|
||||
// netsession_ident_t ident() const
|
||||
{ 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
|
||||
{
|
||||
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
|
||||
|
||||
@ -41,52 +41,67 @@ struct AdcStopSeqSessionProto {
|
||||
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>
|
||||
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 <std::input_iterator IT>
|
||||
auto search(IT begin, IT end)
|
||||
{
|
||||
std::tuple<IT, IT, bool> res{begin, end, false};
|
||||
|
||||
if (begin == end) {
|
||||
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
|
||||
if (!found.empty()) {
|
||||
std::copy(r.begin(), found.end(), std::back_inserter(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>
|
||||
auto toProto(const R& r)
|
||||
{
|
||||
|
||||
@ -25,7 +25,6 @@ namespace adc
|
||||
{
|
||||
|
||||
|
||||
|
||||
class AdcNetServer
|
||||
{
|
||||
protected:
|
||||
@ -41,10 +40,28 @@ public:
|
||||
return _serverIdent;
|
||||
}
|
||||
|
||||
template <interfaces::adc_netservice_c SRVT>
|
||||
void start(SRVT&& netservice, const typename SRVT::endpoint_t& endpoint) {};
|
||||
template <interfaces::adc_netsession_c SessionT, typename... NetsrvCtorArgTs>
|
||||
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)
|
||||
|
||||
@ -8,8 +8,10 @@
|
||||
#include <asio/deferred.hpp>
|
||||
#include <asio/ip/tcp.hpp>
|
||||
#include <asio/ip/udp.hpp>
|
||||
#include <asio/local/datagram_protocol.hpp>
|
||||
#include <asio/local/seq_packet_protocol.hpp>
|
||||
#include <asio/local/stream_protocol.hpp>
|
||||
#include <asio/read.hpp>
|
||||
#include <asio/read_until.hpp>
|
||||
#include <asio/steady_timer.hpp>
|
||||
#include <asio/strand.hpp>
|
||||
@ -46,7 +48,8 @@ using asio_matchcond_result_t = std::pair<asio_streambuff_iter_t, bool>;
|
||||
template <typename T>
|
||||
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::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>
|
||||
@ -90,23 +93,33 @@ concept adc_asio_special_comp_token_c =
|
||||
|
||||
template <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>>
|
||||
traits::adc_output_char_range RMSGT =
|
||||
std::vector<char>> // used only for inner storing of message byte sequence
|
||||
class AdcNetServiceASIOBase : public SESSION_PROTOT
|
||||
{
|
||||
public:
|
||||
// typedefs to satisfy 'adc_netservice_c' concept
|
||||
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;
|
||||
|
||||
// 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 =
|
||||
std::conditional_t<std::derived_from<socket_t, asio::basic_datagram_socket<typename socket_t::protocol_type>>,
|
||||
std::nullptr_t, // there is no 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
|
||||
@ -361,59 +374,35 @@ public:
|
||||
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>>>;
|
||||
|
||||
// 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 timer = getDeadlineTimer(_socket, timeout);
|
||||
|
||||
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 = {},
|
||||
size_t = 0) mutable {
|
||||
RMSGT msg;
|
||||
[out_flags, do_read = true, timer = std::move(timer), this](auto& self, asio::error_code ec = {},
|
||||
size_t nbytes = 0) mutable {
|
||||
// RMSGT msg;
|
||||
msg_t msg;
|
||||
|
||||
if (!ec) {
|
||||
if (start) {
|
||||
start = false;
|
||||
if (do_read) {
|
||||
do_read = false;
|
||||
if (_receiveQueue.size()) { // return message from queue
|
||||
timer->cancel();
|
||||
msg = _receiveQueue.front();
|
||||
auto imsg = _receiveQueue.front();
|
||||
_receiveQueue.pop();
|
||||
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 {
|
||||
// msg_t user_msg{msg.begin(), msg.end()};
|
||||
self.complete(std::error_code(), {msg.begin(), msg.end()});
|
||||
self.complete(std::error_code(), {imsg.begin(), imsg.end()});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (std::derived_from<socket_t,
|
||||
asio::basic_stream_socket<typename socket_t::protocol_type>>) {
|
||||
// adapt to ASIO's MatchCondition
|
||||
auto match_func =
|
||||
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));
|
||||
|
||||
return asio::async_read(_socket, _streamBuffer, asio::transfer_at_least(1),
|
||||
std::move(self));
|
||||
} else if constexpr (std::derived_from<socket_t, asio::basic_datagram_socket<
|
||||
typename socket_t::protocol_type>>) {
|
||||
// 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,
|
||||
asio::basic_datagram_socket<typename socket_t::protocol_type>> ||
|
||||
std::derived_from<socket_t,
|
||||
asio::basic_seq_packet_socket<typename socket_t::protocol_type>>) {
|
||||
auto begin_it = asio::buffers_begin(_streamBuffer.data());
|
||||
auto end_it = asio::buffers_end(_streamBuffer.data());
|
||||
|
||||
*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!!!
|
||||
// auto sr = this->search(std::span(start_ptr, _streamBuffer.size()));
|
||||
auto net_pack = this->search(std::span(start_ptr, _streamBuffer.size()));
|
||||
// if (!std::get<2>(sr)) {
|
||||
if (net_pack.empty()) {
|
||||
do_read = true;
|
||||
asio::post(std::move(self)); // initiate consequence socket's read operation
|
||||
return;
|
||||
}
|
||||
|
||||
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));
|
||||
std::span net_pack{&*std::get<0>(*s_res), N};
|
||||
// here one has at least a single message
|
||||
// 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));
|
||||
_streamBuffer.consume(net_pack.size());
|
||||
|
||||
|
||||
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());
|
||||
auto end_it = asio::buffers_end(_streamBuffer.data());
|
||||
// sr = this->search(std::span(start_ptr, _streamBuffer.size()));
|
||||
net_pack = this->search(std::span(start_ptr, _streamBuffer.size()));
|
||||
|
||||
|
||||
// *s_res = this->search(std::span(begin_it, end_it));
|
||||
*s_res = this->search(begin_it, end_it);
|
||||
if (std::get<2>(*s_res)) {
|
||||
// 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};
|
||||
if (!net_pack.empty()) {
|
||||
// if (std::get<2>(sr)) {
|
||||
// N = std::distance(std::get<0>(sr), std::get<1>(sr));
|
||||
// net_pack = std::span{start_ptr, N};
|
||||
|
||||
_receiveQueue.emplace();
|
||||
std::ranges::copy(this->fromProto(net_pack), std::back_inserter(_receiveQueue.back()));
|
||||
_streamBuffer.consume(net_pack.size());
|
||||
} 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;
|
||||
|
||||
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>
|
||||
static std::unique_ptr<asio::steady_timer> getDeadlineTimer(CancelableT& obj,
|
||||
|
||||
@ -5,7 +5,90 @@
|
||||
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:
|
||||
typedef std::string netsession_ident_t;
|
||||
@ -15,7 +98,7 @@ public:
|
||||
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
|
||||
traits::adc_output_char_range RMSGT = std::vector<char>,
|
||||
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,
|
||||
RECV_MSG_TOKENT&& recv_msg_token)
|
||||
: _ident(id.begin(), id.end())
|
||||
@ -52,21 +135,19 @@ public:
|
||||
interfaces::adc_netsession_proto_c<std::string_view> SESSION_PROTOT,
|
||||
traits::adc_output_char_range RMSGT = std::vector<char>,
|
||||
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)
|
||||
: 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::local::seq_packet_protocol>
|
||||
? "UNIX SEQPACKET SESSION"
|
||||
: std::derived_from<TRANSPORT_PROTOT, asio::local::stream_protocol> ? "UNIX STREAM SESSION"
|
||||
: "UNKNOWN",
|
||||
std::move(netservice),
|
||||
std::forward<RECV_MSG_TOKENT>(recv_msg_token))
|
||||
: std::derived_from<TRANSPORT_PROTOT, asio::local::stream_protocol> ? "UNIX STREAM
|
||||
SESSION" : "UNKNOWN", std::move(netservice), std::forward<RECV_MSG_TOKENT>(recv_msg_token))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~AdcNetSessionASIO()
|
||||
virtual ~AdcGenericNetSessionASIO()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
@ -90,7 +171,7 @@ public:
|
||||
|
||||
|
||||
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;
|
||||
_recvTimeout = recv_timeout;
|
||||
@ -111,4 +192,6 @@ protected:
|
||||
std::chrono::seconds(5);
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
} // namespace adc::impl
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user