...
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <set>
|
||||
#include "../concepts/snplib_concepts.h"
|
||||
#include "../containers/snplib_hvec.h"
|
||||
|
||||
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>
|
||||
concept snplib_net_connection_c = requires(T t) {
|
||||
// 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>;
|
||||
|
||||
{ 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();
|
||||
};
|
||||
@@ -58,73 +73,67 @@ concept snplib_net_listener_c = requires(T t) {
|
||||
std::formattable<decltype(T::id), char>;
|
||||
[]() { [[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.start() } -> snplib_error_c;
|
||||
|
||||
t.stop();
|
||||
t.stopListen();
|
||||
};
|
||||
|
||||
|
||||
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>
|
||||
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
|
||||
std::formattable<decltype(T::id), char>;
|
||||
[]() { [[maybe_unused]] static constexpr auto val = T::id; }();
|
||||
|
||||
|
||||
// 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*/
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
typedef std::error_code error_t;
|
||||
|
||||
using session_t = typename ListenerT::session_t;
|
||||
// typedef std::error_code error_t;
|
||||
|
||||
snplib_generic_netserver_t(std::unique_ptr<ListenerT> listener) : _listener(std::move(listener)) {}
|
||||
|
||||
error_t start()
|
||||
auto startServer()
|
||||
{
|
||||
auto err = _listener->start();
|
||||
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();
|
||||
|
||||
@@ -133,15 +142,7 @@ public:
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ListenerT> _listener{};
|
||||
std::set<std::weak_ptr<session_t>> _sessions{};
|
||||
|
||||
void startListen()
|
||||
{
|
||||
auto sess = co_await _listener->accept();
|
||||
if (sess) {
|
||||
_sessions.insert(sess);
|
||||
}
|
||||
}
|
||||
std::set<std::weak_ptr<SessionT>> _sessions{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user