summaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'server.c')
-rw-r--r--server.c94
1 files changed, 89 insertions, 5 deletions
diff --git a/server.c b/server.c
index 4a45b53..145bcf9 100644
--- a/server.c
+++ b/server.c
@@ -56,11 +56,11 @@ server_refdump(struct server *server)
uring_task_refdump(&server->task);
uring_task_refdump(&server->exec_task);
uring_task_refdump(&server->ann_task);
+ uring_task_refdump(&server->idle_task);
list_for_each_entry(local, &server->locals, list)
uring_task_refdump(&local->task);
list_for_each_entry(proxy, &server->proxys, list)
proxy_refdump(proxy);
- idle_refdump(server->idle);
rcon_refdump(server->rcon);
}
@@ -98,7 +98,6 @@ server_delete(struct cfg *cfg, struct server *server)
verbose("Removing server %s", server->name);
server->state = SERVER_STATE_DEAD;
- idle_delete(cfg, server);
rcon_delete(cfg, server);
list_for_each_entry_safe(local, ltmp, &server->locals, list)
@@ -120,6 +119,7 @@ server_delete(struct cfg *cfg, struct server *server)
list_for_each_entry_safe(dns, dtmp, &server->dnslookups, list)
gai_cancel(&dns->gcb);
+ uring_task_destroy(cfg, &server->idle_task);
uring_poll_cancel(cfg, &server->exec_task);
uring_task_put(cfg, &server->exec_task);
uring_task_destroy(cfg, &server->task);
@@ -363,7 +363,7 @@ server_exec(struct cfg *cfg, struct server *server, const char *cmd)
CLONE_VM | CLONE_VFORK | CLONE_PIDFD | SIGCHLD,
(void *)cmd, &pidfd);
if (r != 0) {
- error("clone: %m");
+ error("clone: %m: %i", r);
return false;
}
@@ -457,6 +457,84 @@ server_stop(struct cfg *cfg, struct server *server)
}
static void
+server_idle_free(struct uring_task *task)
+{
+ assert_return(task);
+
+ debug(DBG_ANN, "called");
+}
+
+void
+server_set_active_players(struct cfg *cfg, struct server *server, int count)
+{
+ assert_return(cfg && server);
+ assert_task_alive(DBG_IDLE, &server->idle_task);
+
+ debug(DBG_IDLE, "%s: currently %i active players",
+ server->name, count);
+
+ if (count < 0)
+ return;
+
+ server->state = SERVER_STATE_RUNNING;
+ if (count > 0)
+ server->idle_count = 0;
+ else if (count == 0)
+ server->idle_count++;
+
+ if (server->idle_count > server->idle_timeout) {
+ verbose("stopping idle server %s", server->name);
+ server_stop(cfg, server);
+ }
+}
+
+static void
+server_idle_connected_cb(struct cfg *cfg, struct connection *conn, bool connected)
+{
+ struct server *server = container_of(conn, struct server, idle_conn);
+
+ assert_return(cfg && conn);
+ assert_task_alive(DBG_IDLE, &server->idle_task);
+
+ if (!connected) {
+ debug(DBG_IDLE,
+ "idle check connection to remote server (%s) failed",
+ server->name);
+ server->idle_count = 0;
+ server->state = SERVER_STATE_STOPPED;
+ return;
+ }
+
+ debug(DBG_IDLE, "connected to remote %s\n", conn->remote.addrstr);
+ idle_check_get_player_count(cfg, server, conn);
+}
+
+bool
+server_idle_check(struct cfg *cfg, struct server *server)
+{
+ assert_return(cfg && server, false);
+
+ if (server->state == SERVER_STATE_INIT ||
+ server->state == SERVER_STATE_DEAD)
+ return false;
+
+ if (server->idle_timeout < 1)
+ return false;
+
+ if (list_empty(&server->remotes))
+ return false;
+
+ if (!list_empty(&server->proxys)) {
+ server->idle_count = 0;
+ return true;
+ }
+
+ connect_any(cfg, &server->idle_task, &server->remotes,
+ &server->idle_conn, server_idle_connected_cb);
+ return true;
+}
+
+static void
server_announce_free(struct uring_task *task)
{
assert_return(task);
@@ -658,7 +736,6 @@ server_commit(struct cfg *cfg, struct server *server)
server_local_open(cfg, server, local);
}
- idle_init(cfg, server);
server->state = SERVER_STATE_CFG_OK;
server_check_running(cfg, server);
@@ -856,18 +933,25 @@ server_new(struct cfg *cfg, const char *name)
server->name = xstrdup(name);
server->stop_method = SERVER_STOP_METHOD_UNDEFINED;
server->start_method = SERVER_START_METHOD_UNDEFINED;
+ server->idle_timeout = 0;
+
uring_task_init(cfg, &server->task, "server", uring_parent(cfg), server_free);
uring_task_set_buf(&server->task, &server->tbuf);
+
uring_task_init(cfg, &server->ann_task, "announce", &server->task, server_announce_free);
uring_task_set_buf(&server->ann_task, &server->ann_buf);
saddr_set_ipv4(&server->ann_task.saddr, cinet_addr(224,0,2,60), htons(4445));
+
uring_task_init(cfg, &server->exec_task, "exec", &server->task, server_exec_free);
+
+ uring_task_init(cfg, &server->idle_task, "idle", &server->task, server_idle_free);
+ uring_task_set_buf(&server->idle_task, &server->idle_buf);
+
list_init(&server->remotes);
list_init(&server->locals);
list_init(&server->proxys);
list_init(&server->rcons);
list_init(&server->dnslookups);
- server->idle_timeout = 0;
list_add(&server->list, &cfg->servers);
return server;