From fae819296598100e41646e0bebc7d0bce45614f7 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Wed, 10 Jun 2020 11:22:29 +0200 Subject: Add initial systemd integration --- server.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 113 insertions(+), 21 deletions(-) (limited to 'server.c') diff --git a/server.c b/server.c index 7ec0804..ee93a24 100644 --- a/server.c +++ b/server.c @@ -18,6 +18,7 @@ #include "utils.h" #include "idle.h" #include "rcon.h" +#include "systemd.h" struct server_local { struct sockaddr_in46 addr; @@ -67,6 +68,8 @@ server_free(struct uring_task *task) free(scfg->pretty_name); free(scfg->start_exec); free(scfg->stop_exec); + free(scfg->systemd_service); + free(scfg->systemd_obj); free(scfg->name); free(scfg); } @@ -323,6 +326,9 @@ server_start(struct cfg *cfg, struct server *scfg) case SERVER_START_METHOD_EXEC: return server_exec(cfg, scfg, scfg->start_exec); + case SERVER_START_METHOD_SYSTEMD: + return systemd_service_start(cfg, scfg); + case SERVER_START_METHOD_UNDEFINED: default: break; @@ -342,6 +348,9 @@ server_stop(struct cfg *cfg, struct server *scfg) case SERVER_STOP_METHOD_EXEC: return server_exec(cfg, scfg, scfg->stop_exec); + case SERVER_STOP_METHOD_SYSTEMD: + return systemd_service_stop(cfg, scfg); + case SERVER_STOP_METHOD_RCON: rcon_init(cfg, scfg); return true; @@ -360,65 +369,112 @@ server_commit(struct cfg *cfg, struct server *scfg) struct server_local *local; uint16_t port; - if (!scfg || !scfg->name) + if (!scfg || !scfg->name) { + fprintf(stderr, "%s: called with invalid parameters\n", __func__); return false; + } - if (!list_empty(&scfg->proxys)) + if (!list_empty(&scfg->proxys)) { + fprintf(stderr, "%s(%s): proxys not empty?\n", __func__, scfg->name); return false; + } /* FIXME: running? */ if (scfg->stop_method == SERVER_STOP_METHOD_RCON && - (list_empty(&scfg->rcons) || !scfg->rcon_password)) + (list_empty(&scfg->rcons) || !scfg->rcon_password)) { + fprintf(stderr, "%s(%s): rcon stop method but missing rcon password\n", __func__, scfg->name); + return false; + } + + if ((scfg->start_method == SERVER_START_METHOD_SYSTEMD || + scfg->stop_method == SERVER_STOP_METHOD_SYSTEMD) && + !scfg->systemd_service) { + fprintf(stderr, "%s(%s): systemd start/stop method but missing systemd service\n", __func__, scfg->name); + return false; + } + + if (scfg->systemd_service && !scfg->systemd_obj) { + scfg->systemd_obj = systemd_service_object_path(cfg, + scfg->systemd_service); + if (!scfg->systemd_obj) { + fprintf(stderr, "%s(%s): failed to create systemd object path (%s)\n", __func__, scfg->name, scfg->systemd_service); + return false; + } + } + + if (scfg->idle_timeout > 0 && + scfg->stop_method == SERVER_STOP_METHOD_UNDEFINED) { + fprintf(stderr, "%s(%s): idle_timeout set but missing stop method\n", __func__, scfg->name); return false; + } switch (scfg->type) { case SERVER_TYPE_ANNOUNCE: - if (scfg->announce_port < 1) + if (scfg->announce_port < 1) { + fprintf(stderr, "%s(%s): missing announce port\n", __func__, scfg->name); return false; - if (scfg->idle_timeout > 0 && - scfg->stop_method == SERVER_STOP_METHOD_UNDEFINED) - return false; - if (scfg->start_method != SERVER_START_METHOD_UNDEFINED) + } + + if (scfg->start_method != SERVER_START_METHOD_UNDEFINED) { + fprintf(stderr, "%s(%s): can't set start_method for announce server\n", __func__, scfg->name); return false; - if (!list_empty(&scfg->locals)) + } + + if (!list_empty(&scfg->locals)) { + fprintf(stderr, "%s(%s): can't set local addresses for announce server\n", __func__, scfg->name); return false; - if (!list_empty(&scfg->remotes)) + } + + if (!list_empty(&scfg->remotes)) { + fprintf(stderr, "%s(%s): can't set remote addresses for announce server\n", __func__, scfg->name); return false; + } + break; case SERVER_TYPE_PROXY: - if (scfg->announce_port >= 1) + if (scfg->announce_port >= 1) { + fprintf(stderr, "%s(%s): can't set announce port for proxy server\n", __func__, scfg->name); return false; - if (scfg->idle_timeout > 0 && - scfg->stop_method == SERVER_STOP_METHOD_UNDEFINED) - return false; - if (list_empty(&scfg->locals)) + } + + if (list_empty(&scfg->locals)) { + fprintf(stderr, "%s(%s): missing local addresses for proxy server\n", __func__, scfg->name); return false; - if (list_empty(&scfg->remotes)) + } + + if (list_empty(&scfg->remotes)) { + fprintf(stderr, "%s(%s): missing remote addresses for proxy server\n", __func__, scfg->name); return false; + } list_for_each_entry(local, &scfg->locals, list) { port = sockaddr_port(&local->addr); - if (port == 0) + if (port == 0) { + fprintf(stderr, "%s(%s): invalid local port\n", __func__, scfg->name); return false; + } if (scfg->announce_port < 1) scfg->announce_port = port; if (scfg->announce_port != port) { - fprintf(stderr, "Multiple announce ports!?\n"); + fprintf(stderr, "%s(%s): multiple local ports\n", __func__, scfg->name); return false; } } - if (scfg->announce_port < 1) + if (scfg->announce_port < 1) { + fprintf(stderr, "%s(%s): can't determine which port to announce\n", __func__, scfg->name); return false; + } break; default: + fprintf(stderr, "%s(%s): can't determine server type\n", __func__, scfg->name); return false; } @@ -426,12 +482,16 @@ server_commit(struct cfg *cfg, struct server *scfg) char *suffix; suffix = strrchr(scfg->name, '.'); - if (!suffix || suffix == scfg->name) + if (!suffix || suffix == scfg->name) { + fprintf(stderr, "%s(%s): invalid server name\n", __func__, scfg->name); return false; + } scfg->pretty_name = strndup(scfg->name, suffix - scfg->name); - if (!scfg->pretty_name) + if (!scfg->pretty_name) { + fprintf(stderr, "%s(%s): failed to create display name\n", __func__, scfg->name); return false; + } } /* FIXME: config, dont reread config if server running, make sure fd is available before this is called */ @@ -443,6 +503,11 @@ server_commit(struct cfg *cfg, struct server *scfg) idle_init(cfg, scfg); + if (scfg->systemd_service) { + fprintf(stderr, "Checking if systemd service is running\n"); + systemd_service_running(cfg, scfg); + } + return true; } @@ -496,6 +561,33 @@ server_set_rcon_password(struct cfg *cfg, struct server *scfg, return set_property(cfg, scfg, &scfg->rcon_password, password); } +bool +server_set_systemd_service(struct cfg *cfg, struct server *scfg, + const char *service) +{ + const char *suffix; + char *tmp; + + if (!cfg || !scfg || empty_str(service) || scfg->systemd_service) + return false; + + suffix = strrchr(service, '.'); + if (!suffix || strcmp(suffix, ".service")) { + tmp = malloc(strlen(service) + strlen(".service") + 1); + if (tmp) + sprintf(tmp, "%s.service", service); + } else + tmp = strdup(service); + + if (!tmp) { + perror("malloc/strdup"); + return false; + } + + scfg->systemd_service = tmp; + return true; +} + bool server_set_stop_method(struct cfg *cfg, struct server *scfg, enum server_stop_method stop_method) -- cgit v1.2.3