...
This commit is contained in:
parent
4e3e3ec60e
commit
6a4278c247
@ -155,7 +155,10 @@ if (BUILD_TESTS)
|
|||||||
find_package(cxxopts CONFIG)
|
find_package(cxxopts CONFIG)
|
||||||
set(ASIO_NETSERVER_TEST_APP adc_asio_netserver_test)
|
set(ASIO_NETSERVER_TEST_APP adc_asio_netserver_test)
|
||||||
add_executable(${ASIO_NETSERVER_TEST_APP} tests/adc_asio_netserver_test.cpp)
|
add_executable(${ASIO_NETSERVER_TEST_APP} tests/adc_asio_netserver_test.cpp)
|
||||||
target_link_libraries(${ASIO_NETSERVER_TEST_APP} PUBLIC cxxopts::cxxopts)
|
target_link_libraries(${ASIO_NETSERVER_TEST_APP} PUBLIC Threads::Threads cxxopts::cxxopts)
|
||||||
|
if (OPENSSL_LIBRARY)
|
||||||
|
target_link_libraries(${ASIO_NETSERVER_TEST_APP} PUBLIC OpenSSL::SSL OpenSSL::Crypto)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT doctest_FOUND)
|
if (NOT doctest_FOUND)
|
||||||
|
|||||||
@ -170,14 +170,19 @@ static ValueT AdcFromChars(R&& range)
|
|||||||
static const std::regex AdcIntegerRegex("^ *[+-]?\\d+\\d* *$", std::regex::ECMAScript);
|
static const std::regex AdcIntegerRegex("^ *[+-]?\\d+\\d* *$", std::regex::ECMAScript);
|
||||||
static const std::regex AdcRealRegex("^ *[-+]?\\d+\\d*\\.?\\d*([Ee][-+]?\\d+)? *$", std::regex::ECMAScript);
|
static const std::regex AdcRealRegex("^ *[-+]?\\d+\\d*\\.?\\d*([Ee][-+]?\\d+)? *$", std::regex::ECMAScript);
|
||||||
|
|
||||||
template <typename SerializedT, traits::formattable VT>
|
// template <typename SerializedT, traits::formattable VT>
|
||||||
|
template <typename SerializedT, typename VT>
|
||||||
static SerializedT AdcTrivialSerializer(VT&& value)
|
static SerializedT AdcTrivialSerializer(VT&& value)
|
||||||
{
|
{
|
||||||
using v_t = std::decay_t<VT>;
|
using v_t = std::decay_t<VT>;
|
||||||
|
|
||||||
if constexpr (std::is_convertible_v<v_t, SerializedT>) {
|
if constexpr (std::is_convertible_v<v_t, SerializedT>) {
|
||||||
return static_cast<SerializedT>(std::forward<VT>(value));
|
return static_cast<SerializedT>(std::forward<VT>(value));
|
||||||
} else if constexpr (traits::adc_output_char_range<SerializedT>) {
|
} else if constexpr (traits::adc_output_char_range<SerializedT> && traits::adc_input_char_range<v_t>) {
|
||||||
|
SerializedT s_val;
|
||||||
|
std::ranges::copy(std::forward<VT>(value), std::back_inserter(s_val));
|
||||||
|
return s_val;
|
||||||
|
} else if constexpr (traits::adc_output_char_range<SerializedT> && traits::formattable<v_t>) {
|
||||||
SerializedT s_val;
|
SerializedT s_val;
|
||||||
std::format_to(std::back_inserter(s_val), "{}", std::forward<VT>(value));
|
std::format_to(std::back_inserter(s_val), "{}", std::forward<VT>(value));
|
||||||
return s_val;
|
return s_val;
|
||||||
|
|||||||
@ -496,7 +496,7 @@ public:
|
|||||||
|
|
||||||
void err(const std::error_code& ec)
|
void err(const std::error_code& ec)
|
||||||
{
|
{
|
||||||
base_t::setKeyValue(ERR_KEY, ec.value(), ec.category(), ec.message());
|
base_t::setKeyValue(ERR_KEY, ec.value(), ec.category().name(), ec.message());
|
||||||
|
|
||||||
keyHash();
|
keyHash();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -158,7 +158,7 @@ protected:
|
|||||||
if constexpr (std::same_as<serialized_t, val_t> || std::convertible_to<val_t, serialized_t>) {
|
if constexpr (std::same_as<serialized_t, val_t> || std::convertible_to<val_t, serialized_t>) {
|
||||||
return val;
|
return val;
|
||||||
} else {
|
} else {
|
||||||
// !!!!!!!! TODO: val_t maust be a char range
|
// !!!!!!!! TODO: val_t must be a char range
|
||||||
return serialized_t{val.begin(), val.end()};
|
return serialized_t{val.begin(), val.end()};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -199,7 +199,7 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static DeviceWrapper nullDevice;
|
static inline DeviceWrapper nullDevice{};
|
||||||
|
|
||||||
std::unordered_map<void*, DeviceWrapper> _devices;
|
std::unordered_map<void*, DeviceWrapper> _devices;
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ public:
|
|||||||
attrs = msg.template attrs<attr_vec_t>(0, 1);
|
attrs = msg.template attrs<attr_vec_t>(0, 1);
|
||||||
if (attrs.size()) {
|
if (attrs.size()) {
|
||||||
auto val = _bindDevice.getAttr(get_elem(0));
|
auto val = _bindDevice.getAttr(get_elem(0));
|
||||||
msg.ack(get_elem(0), {val.begin(), val.end()});
|
msg.ack(get_elem(0), serialized_t{val.begin(), val.end()});
|
||||||
} else { // no attr name!
|
} else { // no attr name!
|
||||||
msg.err(std::make_error_code(AdcDeviceNetServerSessionError::ERROR_NO_PROTO_ATTRNAME));
|
msg.err(std::make_error_code(AdcDeviceNetServerSessionError::ERROR_NO_PROTO_ATTRNAME));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,10 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#if __has_include(<unistd.h>) // POSIX
|
#if __has_include(<unistd.h>) // POSIX
|
||||||
#define FORK_EXISTS 1
|
#define FORK_EXISTS 1
|
||||||
@ -139,28 +139,46 @@ protected:
|
|||||||
|
|
||||||
// started sessions weak pointers
|
// started sessions weak pointers
|
||||||
template <interfaces::adc_netsession_c SessionT>
|
template <interfaces::adc_netsession_c SessionT>
|
||||||
static std::unordered_map<const AdcNetSessionManager*, std::unordered_set<std::weak_ptr<SessionT>>> _serverSessions;
|
// static std::unordered_map<const AdcNetSessionManager*, std::unordered_set<std::weak_ptr<SessionT>>>
|
||||||
|
// _serverSessions;
|
||||||
|
static inline std::unordered_map<const AdcNetSessionManager*, std::list<std::weak_ptr<SessionT>>> _serverSessions{};
|
||||||
std::vector<std::function<bool()>> _stopSessionFunc;
|
std::vector<std::function<bool()>> _stopSessionFunc;
|
||||||
std::vector<std::function<void(const AdcNetSessionManager*)>> _moveCtorFunc;
|
std::vector<std::function<void(const AdcNetSessionManager*)>> _moveCtorFunc;
|
||||||
|
|
||||||
template <interfaces::adc_netsession_c SessionT>
|
template <interfaces::adc_netsession_c SessionT>
|
||||||
void startSession(std::shared_ptr<SessionT>& sess_ptr)
|
void startSession(std::shared_ptr<SessionT>& sess_ptr)
|
||||||
{
|
{
|
||||||
auto res = _serverSessions<SessionT>[this].emplace(sess_ptr);
|
auto it = _serverSessions<SessionT>[this].end();
|
||||||
if (res.second) {
|
it = _serverSessions<SessionT>[this].emplace(it, sess_ptr);
|
||||||
sess_ptr->start();
|
sess_ptr->start();
|
||||||
|
|
||||||
_stopSessionFunc.emplace_back([res, this]() {
|
_stopSessionFunc.emplace_back([it, this]() {
|
||||||
if (!res.first->expired()) { // session is still existing
|
if (!it->expired()) { // session is still existing
|
||||||
auto sess = res.first->lock();
|
auto sess = it->lock();
|
||||||
sess->stop();
|
sess->stop();
|
||||||
_serverSessions<SessionT>[this].erase(res.first);
|
_serverSessions<SessionT>[this].erase(it);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
// auto res = _serverSessions<SessionT>[this].emplace(sess_ptr);
|
||||||
|
// if (res.second) {
|
||||||
|
// sess_ptr->start();
|
||||||
|
|
||||||
|
// _stopSessionFunc.emplace_back([res, this]() {
|
||||||
|
// if (!res.first->expired()) { // session is still existing
|
||||||
|
// auto sess = res.first->lock();
|
||||||
|
// sess->stop();
|
||||||
|
// _serverSessions<SessionT>[this].erase(res.first);
|
||||||
|
// return true;
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
// define move-function only once per SessionT!
|
// define move-function only once per SessionT!
|
||||||
if (_serverSessions<SessionT>[this].size() == 1) {
|
if (_serverSessions<SessionT>[this].size() == 1) {
|
||||||
|
|||||||
@ -48,7 +48,8 @@ public:
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
using srv_t = AdcNetServiceASIOTLS<asio::ip::tcp, SessProtoT>;
|
using srv_t = AdcNetServiceASIOTLS<asio::ip::tcp, SessProtoT>;
|
||||||
AdcGenericNetServer::start<Session<srv_t>>("TLS", this, _ioContext, ept, tls_context, tls_verify_mode);
|
AdcGenericNetServer::start<Session<srv_t>>("TLS", this, _ioContext, ept, std::move(tls_context),
|
||||||
|
tls_verify_mode);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (endpoint.isTCP()) {
|
if (endpoint.isTCP()) {
|
||||||
|
|||||||
@ -168,13 +168,39 @@ public:
|
|||||||
typedef std::function<void(std::error_code, netservice_t)> async_accept_callback_t;
|
typedef std::function<void(std::error_code, netservice_t)> async_accept_callback_t;
|
||||||
|
|
||||||
|
|
||||||
acceptor_t(asio::io_context& io_context) : _ioContext(io_context), _acceptor(io_context) {}
|
acceptor_t(asio::io_context& io_context)
|
||||||
|
requires(!netservice_t::isTLS)
|
||||||
|
: _ioContext(io_context), _acceptor(io_context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
acceptor_t(asio::io_context& io_context, const netservice_t::endpoint_t& endpoint)
|
acceptor_t(asio::io_context& io_context, const netservice_t::endpoint_t& endpoint)
|
||||||
|
requires(!netservice_t::isTLS)
|
||||||
: _ioContext(io_context), _acceptor(io_context, endpoint)
|
: _ioContext(io_context), _acceptor(io_context, endpoint)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
|
acceptor_t(asio::io_context& io_context,
|
||||||
|
asio::ssl::context tls_ctx,
|
||||||
|
asio::ssl::verify_mode tls_verify_mode = asio::ssl::context_base::verify_peer)
|
||||||
|
requires netservice_t::isTLS
|
||||||
|
: _ioContext(io_context), _acceptor(io_context), _tlsCtx(std::move(tls_ctx)), _tlsVerMode(tls_verify_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptor_t(asio::io_context& io_context,
|
||||||
|
const netservice_t::endpoint_t& endpoint,
|
||||||
|
asio::ssl::context tls_ctx,
|
||||||
|
asio::ssl::verify_mode tls_verify_mode = asio::ssl::context_base::verify_peer)
|
||||||
|
requires netservice_t::isTLS
|
||||||
|
: _ioContext(io_context),
|
||||||
|
_acceptor(io_context, endpoint),
|
||||||
|
_tlsCtx(std::move(tls_ctx)),
|
||||||
|
_tlsVerMode(tls_verify_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
template <asio::completion_token_for<void(std::error_code, netservice_t)> TokenT,
|
template <asio::completion_token_for<void(std::error_code, netservice_t)> TokenT,
|
||||||
traits::adc_time_duration_c DT = decltype(DEFAULT_ACCEPT_TIMEOUT)>
|
traits::adc_time_duration_c DT = decltype(DEFAULT_ACCEPT_TIMEOUT)>
|
||||||
auto asyncAccept(TokenT&& token, const DT& timeout = DEFAULT_ACCEPT_TIMEOUT)
|
auto asyncAccept(TokenT&& token, const DT& timeout = DEFAULT_ACCEPT_TIMEOUT)
|
||||||
@ -183,10 +209,17 @@ public:
|
|||||||
|
|
||||||
auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout);
|
auto timer = netservice_t::getDeadlineTimer(_acceptor, timeout);
|
||||||
|
|
||||||
// auto srv = std::make_unique<netservice_t>(_ioContext);
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
auto srv = netservice_t::isTLS ? std::make_unique<netservice_t>(_ioContext, srv->_tlsContext)
|
auto srv = [&, this]() {
|
||||||
: std::make_unique<netservice_t>(_ioContext);
|
if constexpr (netservice_t::isTLS) {
|
||||||
|
return std::make_unique<netservice_t>(_ioContext, std::move(_tlsCtx), _tlsVerMode);
|
||||||
|
} else {
|
||||||
|
return std::make_unique<netservice_t>(_ioContext);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
#else
|
||||||
|
auto srv = std::make_unique<netservice_t>(_ioContext);
|
||||||
|
#endif
|
||||||
return asio::async_compose<TokenT, void(std::error_code, netservice_t)>(
|
return asio::async_compose<TokenT, void(std::error_code, netservice_t)>(
|
||||||
[timer = std::move(timer), srv = std::move(srv), state = sock_accept, this](
|
[timer = std::move(timer), srv = std::move(srv), state = sock_accept, this](
|
||||||
auto& self, std::error_code ec = {}) mutable {
|
auto& self, std::error_code ec = {}) mutable {
|
||||||
@ -205,7 +238,7 @@ public:
|
|||||||
#ifdef USE_OPENSSL_WITH_ASIO
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
if constexpr (netservice_t::isTLS) {
|
if constexpr (netservice_t::isTLS) {
|
||||||
srv->_sessSocket =
|
srv->_sessSocket =
|
||||||
netservice_t::session_level_socket_t(srv->_socket, srv->_tlsContext);
|
netservice_t::session_level_socket_t(std::move(srv->_socket), srv->_tlsContext);
|
||||||
return srv->_sessSocket.async_handshake(asio::ssl::stream_base::server,
|
return srv->_sessSocket.async_handshake(asio::ssl::stream_base::server,
|
||||||
std::move(self));
|
std::move(self));
|
||||||
}
|
}
|
||||||
@ -264,6 +297,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
asio::io_context& _ioContext;
|
asio::io_context& _ioContext;
|
||||||
srv_acceptor_t _acceptor;
|
srv_acceptor_t _acceptor;
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
|
asio::ssl::context _tlsCtx{asio::ssl::context_base::tlsv13};
|
||||||
|
asio::ssl::verify_mode _tlsVerMode;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -291,7 +329,7 @@ public:
|
|||||||
|
|
||||||
#ifdef USE_OPENSSL_WITH_ASIO
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
AdcBaseNetServiceASIO(asio::io_context& ctx,
|
AdcBaseNetServiceASIO(asio::io_context& ctx,
|
||||||
const asio::ssl::context& tls_context,
|
asio::ssl::context tls_context,
|
||||||
const asio::ssl::verify_mode& tls_peer_verify_mode = asio::ssl::verify_peer)
|
const asio::ssl::verify_mode& tls_peer_verify_mode = asio::ssl::verify_peer)
|
||||||
requires isTLS
|
requires isTLS
|
||||||
: SESSION_PROTOT(),
|
: SESSION_PROTOT(),
|
||||||
@ -299,8 +337,9 @@ public:
|
|||||||
_receiveStrand(_ioContext),
|
_receiveStrand(_ioContext),
|
||||||
_socket(_ioContext),
|
_socket(_ioContext),
|
||||||
_receiveQueue(),
|
_receiveQueue(),
|
||||||
_tlsContext(tls_context),
|
_tlsContext(std::move(tls_context)),
|
||||||
_tlsPeerVerifyMode(tls_peer_verify_mode)
|
_tlsPeerVerifyMode(tls_peer_verify_mode),
|
||||||
|
_sessSocket(_ioContext, _tlsContext)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -418,7 +457,7 @@ public:
|
|||||||
state = done;
|
state = done;
|
||||||
#ifdef USE_OPENSSL_WITH_ASIO
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
if constexpr (isTLS) {
|
if constexpr (isTLS) {
|
||||||
_sessSocket = session_level_socket_t(_socket, _tlsContext);
|
_sessSocket = session_level_socket_t(std::move(_socket), _tlsContext);
|
||||||
return _sessSocket.async_handshake(session_level_socket_t::client, std::move(self));
|
return _sessSocket.async_handshake(session_level_socket_t::client, std::move(self));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -666,7 +705,7 @@ public:
|
|||||||
|
|
||||||
#ifdef USE_OPENSSL_WITH_ASIO
|
#ifdef USE_OPENSSL_WITH_ASIO
|
||||||
if constexpr (isTLS) {
|
if constexpr (isTLS) {
|
||||||
_sessSocket.shutdown(_shutdownType, ec);
|
_sessSocket.shutdown(ec);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user