This commit is contained in:
2026-07-01 18:26:09 +03:00
parent 3ae77a4e2c
commit a7bbc6ff8c

View File

@@ -2,7 +2,6 @@
#include <set> #include <set>
#include "../concepts/snplib_concepts.h" #include "../concepts/snplib_concepts.h"
#include "../containers/snplib_hvec.h"
namespace snplib namespace snplib
{ {
@@ -23,6 +22,21 @@ concept snplib_net_endpoint_c = requires(T t, const T t_const) {
}; };
template <typename T>
concept snplib_net_message_c = requires(T t) {
{ t.toBytes() } -> snplib_output_char_range_c;
// can be constructed from contiguous byte range
requires(
requires {
{ T::fromBytes(std::declval<std::span<const char>>()) } -> std::same_as<T>;
} ||
requires {
{ T::fromBytes(std::declval<std::span<char>>()) } -> std::same_as<T>;
});
};
template <typename T> template <typename T>
concept snplib_net_connection_c = requires(T t) { concept snplib_net_connection_c = requires(T t) {
// static constexpr member // static constexpr member
@@ -46,7 +60,8 @@ concept snplib_net_session_c = std::derived_from<T, std::enable_shared_from_this
snplib_net_connection_c<typename T::connection_t>; snplib_net_connection_c<typename T::connection_t>;
{ t.startSession(std::declval<typename T::connection_t>()) } -> snplib_async_retval_c; // { t.startSession(std::declval<typename T::connection_t>()) } -> snplib_async_retval_c;
t.startSession(std::declval<typename T::connection_t>());
t.stopSession(); t.stopSession();
}; };
@@ -58,73 +73,67 @@ concept snplib_net_listener_c = requires(T t) {
std::formattable<decltype(T::id), char>; std::formattable<decltype(T::id), char>;
[]() { [[maybe_unused]] static constexpr auto val = T::id; }(); []() { [[maybe_unused]] static constexpr auto val = T::id; }();
snplib_net_session_c<typename T::session_t>; snplib_net_connection_c<typename T::connection_t>;
{ t.accept() } -> snplib_async_retval_c<typename T::session_t>; { t.accept() } -> snplib_async_retval_c<typename T::connection_t>;
// { t.accept() } -> snplib_expected_c; // must return std::expected<snplib_net_session_c, snplib_error_c> { t.startListen() } -> snplib_error_c;
// snplib_net_session_c<typename std::invoke_result_t<decltype(t.accept)>::value_type>; t.stopListen();
{ t.start() } -> snplib_error_c;
t.stop();
}; };
struct snplib_netserver_iface_t {
virtual ~snplib_netserver_iface_t() = default;
template <std::derived_from<snplib_netserver_iface_t> SelfT, snplib_net_listener_c LT>
auto start(this SelfT&& self, LT&& listener)
{
return std::forward<SelfT>(self).start(std::forward<LT>(listener));
}
protected:
snplib_netserver_iface_t() = default;
};
template <typename T> template <typename T>
concept snplib_netserver_c = std::derived_from<T, snplib_netserver_iface_t> && requires(T t) { concept snplib_netserver_c = requires(T t) {
// static constexpr member // static constexpr member
std::formattable<decltype(T::id), char>; std::formattable<decltype(T::id), char>;
[]() { [[maybe_unused]] static constexpr auto val = T::id; }(); []() { [[maybe_unused]] static constexpr auto val = T::id; }();
// start/stop all listeners // start/stop all listeners
{ t.start() } -> snplib_error_c; t.startServer();
{ t.stop() } -> snplib_error_c; t.stopServer();
{ t.disconnectClients() } -> snplib_error_c; t.disconnectClients();
// { t.startServer() } -> snplib_error_c;
// { t.stopServer() } -> snplib_error_c;
// { t.disconnectClients() } -> snplib_error_c;
}; };
/* SINGLE-PROTO*/ /* SINGLE-PROTO*/
template <snplib_net_listener_c ListenerT> template <snplib_net_listener_c ListenerT, snplib_net_session_c SessionT>
requires std::same_as<typename ListenerT::connection_t, typename SessionT::connection_t>
class snplib_generic_netserver_t class snplib_generic_netserver_t
{ {
public: public:
typedef std::error_code error_t; // typedef std::error_code error_t;
using session_t = typename ListenerT::session_t;
snplib_generic_netserver_t(std::unique_ptr<ListenerT> listener) : _listener(std::move(listener)) {} snplib_generic_netserver_t(std::unique_ptr<ListenerT> listener) : _listener(std::move(listener)) {}
error_t start() auto startServer()
{ {
auto err = _listener->start(); auto err = _listener->start();
if (err) { if (err) {
return snplib_deduced_error(err, std::make_error_code(std::errc::io_error)); co_return std::unexpect(snplib_deduced_error(err, std::make_error_code(std::errc::io_error)));
} }
startListen(); while (true) {
auto connection = co_await _listener->accept();
if (connection) {
auto sptr = std::make_shared<SessionT>();
_sessions.insert(sptr);
sptr->start(std::move(connection.value()));
}
}
} }
error_t stop() error_t stopServer()
{ {
_listener->stop(); _listener->stop();
@@ -133,15 +142,7 @@ public:
protected: protected:
std::unique_ptr<ListenerT> _listener{}; std::unique_ptr<ListenerT> _listener{};
std::set<std::weak_ptr<session_t>> _sessions{}; std::set<std::weak_ptr<SessionT>> _sessions{};
void startListen()
{
auto sess = co_await _listener->accept();
if (sess) {
_sessions.insert(sess);
}
}
}; };