This commit is contained in:
Timur A. Fatkhullin
2025-02-20 23:56:25 +03:00
parent b6161ed03f
commit aca8a6523e
4 changed files with 117 additions and 24 deletions

View File

@@ -19,6 +19,15 @@
#include <spdlog/sinks/null_sink.h>
#include <spdlog/spdlog.h>
#if __has_include(<unistd.h>) // POSIX
#define FORK_EXISTS 1
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno>
#endif
#include "comm_server_endpoint.h"
#include "control_proto.h"
#include "mount.h"
@@ -38,25 +47,29 @@ concept mcc_endpoint_c = std::derived_from<T, asio::serial_port> || std::derived
template <typename T>
static constexpr bool is_serial_proto = std::derived_from<T, asio::serial_port>;
template <typename T>
static constexpr bool is_tcp_proto = std::derived_from<typename T::protocol_type, asio::ip::tcp>;
template <typename T>
static constexpr bool is_local_stream_proto =
std::derived_from<typename T::protocol_type, asio::local::stream_protocol>;
template <typename T>
static constexpr bool is_local_seqpack_proto =
std::derived_from<typename T::protocol_type, asio::local::seq_packet_protocol>;
// template <typename T>
// static constexpr bool is_tcp_proto = std::derived_from<typename T::protocol_type, asio::ip::tcp>;
// template <typename T>
// static constexpr bool is_tcp_proto = std::derived_from<T, asio::ip::tcp::endpoint>;
// static constexpr bool is_local_stream_proto =
// std::derived_from<typename T::protocol_type, asio::local::stream_protocol>;
// template <typename T>
// static constexpr bool is_local_stream_proto = std::derived_from<T, asio::local::stream_protocol::endpoint>;
// static constexpr bool is_local_seqpack_proto =
// std::derived_from<typename T::protocol_type, asio::local::seq_packet_protocol>;
// template <typename T>
// static constexpr bool is_local_seqpack_proto = std::derived_from<T, asio::local::seq_packet_protocol::endpoint>;
template <typename T>
static constexpr bool is_tcp_proto =
std::derived_from<T, asio::ip::tcp::endpoint> || std::derived_from<T, asio::ip::tcp::socket>;
template <typename T>
static constexpr bool is_local_stream_proto = std::derived_from<T, asio::local::stream_protocol::endpoint> ||
std::derived_from<T, asio::local::stream_protocol::socket>;
template <typename T>
static constexpr bool is_local_seqpack_proto = std::derived_from<T, asio::local::seq_packet_protocol::endpoint> ||
std::derived_from<T, asio::local::seq_packet_protocol::socket>;
template <typename T>
@@ -148,8 +161,8 @@ public:
try {
// std::stringstream st;
_serverLogger->debug("Create connection acceptor for endpoint <{}> ...",
epn.address().to_string());
// _serverLogger->debug("Create connection acceptor for endpoint <{}> ...",
// epn.address().to_string());
acc = asio::ip::tcp::acceptor(_asioContext, epn);
// st << acc.local_endpoint();
exit_flag = true;
@@ -208,7 +221,7 @@ public:
st << endpoint;
_serverLogger->debug("Create connection acceptor for endpoint <{}> ...", st.str());
auto acc = epn_t::protocol_type::acceptor(_asioContext, endpoint);
auto acc = typename epn_t::protocol_type::acceptor(_asioContext, endpoint);
st.str("");
st << acc.local_endpoint();
@@ -240,6 +253,8 @@ public:
} else {
static_assert(false, "INVALID ENDPOINT!!!");
}
co_return;
}
@@ -247,7 +262,6 @@ public:
void stopListening()
{
std::error_code ec;
size_t N = 0, M = 0;
_serverLogger->info("Close all listening endpoints ...");
@@ -291,6 +305,70 @@ public:
void disconnectClients() {}
void daemonize()
{
#ifdef FORK_EXISTS
_serverLogger->info("Daemonize the server ...");
_asioContext.notify_fork(asio::execution_context::fork_prepare);
auto tmp_path = std::filesystem::temp_directory_path();
if (tmp_path.empty()) {
tmp_path = std::filesystem::current_path().root_path();
}
if (pid_t pid = fork()) {
if (pid > 0) {
exit(0);
} else {
// throw std::system_error(errno, std::generic_category(), "CANNOT FORK 1-STAGE");
_serverLogger->error("CANNOT FORK 1-STAGE! The server was not daemonized!");
return;
}
}
if (setsid() == -1) {
// throw std::system_error(errno, std::generic_category(), "CANNOT FORK SETSID");
_serverLogger->error("CANNOT FORK SETSID! The server was not daemonized!");
return;
}
_serverLogger->info("Try to set the daemon current path to '{}' ...", tmp_path.string());
std::error_code ec{};
std::filesystem::current_path(tmp_path, ec);
if (!ec) {
_serverLogger->warn("Cannot change current path to '{}'! Ignore!", tmp_path.string());
}
umask(0);
if (pid_t pid = fork()) {
if (pid > 0) {
exit(0);
} else {
// throw std::system_error(errno, std::generic_category(), "CANNOT FORK 2-STAGE");
_serverLogger->error("CANNOT FORK 2-STAGE! The server was not daemonized!");
return;
}
}
// stdin, stdout, stderr
close(0);
close(1);
close(2);
_asioContext.notify_fork(asio::io_context::fork_child);
_serverLogger->info("The server was daemonized successfully!");
#else
_serverLogger->warn("Host platform is not POSIX one, so cannot daemonize the server!");
#endif
}
private:
asio::io_context& _asioContext;
std::shared_ptr<spdlog::logger> _serverLogger;
@@ -345,10 +423,11 @@ private:
}
template <traits::mcc_time_duration_c RCVT, traits::mcc_time_duration_c SNDT>
template <traits::mcc_time_duration_c RCVT = decltype(DEFAULT_RCV_TIMEOUT),
traits::mcc_time_duration_c SNDT = decltype(DEFAULT_SND_TIMEOUT)>
asio::awaitable<void> startSession(auto socket,
RCVT&& rcv_timeout = DEFAULT_RCV_TIMEOUT,
SNDT&& snd_timeout = DEFAULT_SND_TIMEOUT)
const RCVT& rcv_timeout = DEFAULT_RCV_TIMEOUT,
const SNDT& snd_timeout = DEFAULT_SND_TIMEOUT)
{
using namespace asio::experimental::awaitable_operators;
@@ -431,7 +510,7 @@ private:
if constexpr (traits::is_local_seqpack_proto<sock_t>) {
asio::socket_base::message_flags oflags;
// nbytes = co_await socket.async_receive(buff, &oflags, asio::use_awaitable);
nbytes = co_await (socket.async_receive(buff, &oflags, asio::use_awaitable) &&
nbytes = co_await (socket.async_receive(buff, oflags, asio::use_awaitable) &&
watchdog(std::chrono::steady_clock::now() + rcv_timeout));
if (!nbytes) { // EOF!