#pragma once #include #include #include #include #include #include #include "../adc_device_netserver.h" #include "../adc_endpoint.h" #include "adc_netservice_asio.h" namespace adc::impl { template class AdcDeviceNetServerASIO : public AdcDeviceNetServer { typedef AdcDeviceNetServer base_t; public: using typename base_t::server_ident_t; typedef std::string session_ident_t; template using Session = typename base_t::template Session; AdcDeviceNetServerASIO(const server_ident_t& id, asio::io_context& io_context) : base_t(id), _ioContext(io_context), _stopSignal(io_context), _restartSignal(io_context) { } template 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! if (endpoint.isTCP()) { asio::ip::tcp::endpoint ept(asio::ip::make_address(endpoint.host()), endpoint.port()); using srv_t = AdcNetServiceASIO; base_t::template start>("TCP", this, _ioContext, ept); #ifdef USE_OPENSSL_WITH_ASIO } else if (endpoint.isTLS()) { asio::ip::tcp::endpoint ept(asio::ip::make_address(endpoint.host()), endpoint.port()); using srv_t = AdcNetServiceASIOTLS; base_t::template start>("TLS", this, _ioContext, ept, std::move(tls_context), tls_verify_mode); #endif } else if (endpoint.isLocal()) { if (endpoint.isLocalStream()) { asio::local::stream_protocol::endpoint ept(endpoint.template path()); using srv_t = AdcNetServiceASIO; base_t::template start>("LOCAL STREAM", this, _ioContext, ept); // } else if (endpoint.isLocalDatagram()) { // asio::local::datagram_protocol::endpoint ept(endpoint.template path()); // using srv_t = AdcNetServiceASIO; // base_t::template start>("LOCAL DGRAM", this, _ioContext, ept); } else if (endpoint.isLocalSeqpacket()) { asio::local::seq_packet_protocol::endpoint ept(endpoint.template path()); using srv_t = AdcNetServiceASIO; base_t::template start>("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 RRT = std::vector> void setupSignals(const RST& stop_sig_num = {SIGINT, SIGTERM}, const RRT& restart_sig_num = {SIGUSR1}) requires(std::convertible_to, int> && std::convertible_to, 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->stop(); }); for (const int sig : restart_sig_num) { _restartSignal.add(sig); } _restartSignal.async_wait([this](std::error_code ec, int signo) { signalReceived(ec, signo); restart(); }); } 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) { std::cout << "SIGNAL: " << signo << "\n"; }; virtual void restart() { this->stopAllSessions(); _restartSignal.async_wait([this](std::error_code ec, int signo) { signalReceived(ec, signo); restart(); }); } }; } // namespace adc::impl