127 lines
4.7 KiB
C++
127 lines
4.7 KiB
C++
#pragma once
|
|
|
|
#include <asio/io_context.hpp>
|
|
#include <asio/ip/tcp.hpp>
|
|
#include <asio/ip/udp.hpp>
|
|
#include <asio/local/seq_packet_protocol.hpp>
|
|
#include <asio/local/stream_protocol.hpp>
|
|
#include <asio/signal_set.hpp>
|
|
|
|
#include "../adc_device_netserver.h"
|
|
#include "../adc_endpoint.h"
|
|
#include "adc_netservice_asio.h"
|
|
|
|
namespace adc::impl
|
|
{
|
|
|
|
class AdcDeviceNetServerASIO : public AdcDeviceNetServer
|
|
{
|
|
public:
|
|
template <traits::adc_input_char_range R>
|
|
AdcDeviceNetServerASIO(const R& id, asio::io_context& io_context)
|
|
: AdcDeviceNetServer(id), _ioContext(io_context), _stopSignal(io_context), _restartSignal(io_context)
|
|
{
|
|
}
|
|
|
|
|
|
template <interfaces::adc_netsession_proto_c SessProtoT, std::derived_from<AdcEndpointParser> EptT>
|
|
#ifdef USE_OPENSSL_WITH_ASIO
|
|
void start(const EptT& endpoint,
|
|
asio::ssl::context tls_context = asio::ssl::context(asio::ssl::context::tlsv13_server),
|
|
asio::ssl::verify_mode tls_verify_mode = asio::ssl::context_base::verify_peer)
|
|
#else
|
|
void start(const EptT& endpoint)
|
|
#endif
|
|
{
|
|
if (!endpoint.isValid()) {
|
|
return;
|
|
}
|
|
|
|
|
|
// may throw here!
|
|
#ifdef USE_OPENSSL_WITH_ASIO
|
|
if (endpoint.isTCP() || endpoint.isTLS()) {
|
|
asio::ip::tcp::endpoint ept(asio::ip::make_address(endpoint.host()), endpoint.port());
|
|
if (endpoint.isTCP()) {
|
|
using srv_t = AdcNetServiceASIO<asio::ip::tcp, SessProtoT>;
|
|
AdcGenericNetServer::start<Session<srv_t>>("TCP", this, _ioContext, ept);
|
|
|
|
} else {
|
|
using srv_t = AdcNetServiceASIOTLS<asio::ip::tcp, SessProtoT>;
|
|
AdcGenericNetServer::start<Session<srv_t>>("TLS", this, _ioContext, ept, std::move(tls_context),
|
|
tls_verify_mode);
|
|
}
|
|
#else
|
|
if (endpoint.isTCP()) {
|
|
asio::ip::tcp::endpoint ept(asio::ip::make_address(endpoint.host()), endpoint.port());
|
|
using srv_t = AdcNetServiceASIO<asio::ip::tcp, AdcStopSeqSessionProto<>>;
|
|
AdcDeviceNetServer::start<Session<srv_t>>("TCP", this, _ioContext, ept);
|
|
#endif
|
|
} else if (endpoint.isLocal()) {
|
|
if (endpoint.isLocalStream()) {
|
|
asio::local::stream_protocol::endpoint ept(endpoint.template path<std::string>());
|
|
using srv_t = AdcNetServiceASIO<asio::local::stream_protocol, SessProtoT>;
|
|
AdcGenericNetServer::start<Session<srv_t>>("LOCAL STREAM", this, _ioContext, ept);
|
|
// } else if (endpoint.isLocalDatagram()) {
|
|
// asio::local::datagram_protocol::endpoint ept(endpoint.template path<std::string>());
|
|
// using srv_t = AdcNetServiceASIO<asio::local::datagram_protocol, SessProtoT>;
|
|
// AdcDeviceNetServer::start<Session<srv_t>>("LOCAL DGRAM", this, _ioContext, ept);
|
|
} else if (endpoint.isLocalSeqpacket()) {
|
|
asio::local::seq_packet_protocol::endpoint ept(endpoint.template path<std::string>());
|
|
using srv_t = AdcNetServiceASIO<asio::local::seq_packet_protocol, SessProtoT>;
|
|
AdcGenericNetServer::start<Session<srv_t>>("LOCAL SEQPACK", this, _ioContext, ept);
|
|
}
|
|
} else {
|
|
throw std::system_error(std::make_error_code(std::errc::protocol_not_supported));
|
|
}
|
|
}
|
|
|
|
// some default endpoint?!!
|
|
void start() {}
|
|
|
|
template <std::ranges::range RST = std::vector<int>, std::ranges::range RRT = std::vector<int>>
|
|
void setupSignals(const RST& stop_sig_num = std::vector<int>{SIGINT, SIGTERM},
|
|
const RRT& restart_sig_num = std::vector<int>{SIGUSR1})
|
|
requires(std::convertible_to<std::ranges::range_value_t<RST>, int> &&
|
|
std::convertible_to<std::ranges::range_value_t<RRT>, int>)
|
|
{
|
|
for (const int sig : stop_sig_num) {
|
|
_stopSignal.add(sig);
|
|
}
|
|
|
|
_stopSignal.async_wait([this](std::error_code ec, int signo) {
|
|
signalReceived(ec, signo);
|
|
this->stopAllSessions();
|
|
});
|
|
|
|
for (const int sig : restart_sig_num) {
|
|
_restartSignal.add(sig);
|
|
}
|
|
|
|
_restartSignal.async_wait([this](std::error_code ec, int signo) {
|
|
signalReceived(ec, signo);
|
|
// ?!!!!!!!
|
|
});
|
|
}
|
|
|
|
protected:
|
|
asio::io_context& _ioContext;
|
|
|
|
asio::signal_set _stopSignal, _restartSignal;
|
|
|
|
// demonizing ASIO-related methods
|
|
virtual void daemonizePrepare()
|
|
{
|
|
_ioContext.notify_fork(asio::execution_context::fork_prepare);
|
|
}
|
|
|
|
virtual void daemonizeFinalize()
|
|
{
|
|
_ioContext.notify_fork(asio::io_context::fork_child);
|
|
}
|
|
|
|
virtual void signalReceived(std::error_code, int signo) {};
|
|
};
|
|
|
|
} // namespace adc::impl
|