summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--idle.c112
-rw-r--r--idle.h7
-rw-r--r--main.c5
-rw-r--r--main.h1
-rw-r--r--server.c94
-rw-r--r--server.h9
6 files changed, 135 insertions, 93 deletions
diff --git a/idle.c b/idle.c
index bfb8fc8..0ced98d 100644
--- a/idle.c
+++ b/idle.c
@@ -15,25 +15,10 @@
#include "idle.h"
struct idle {
- struct server *server;
-
struct uring_task task;
uint64_t value;
-
- struct uring_task idlecheck;
- struct connection conn;
- struct uring_task_buf tbuf;
};
-static void
-idle_check_free(struct uring_task *task)
-{
- struct idle *idle = container_of(task, struct idle, idlecheck);
-
- assert_return(task && idle);
- debug(DBG_IDLE, "task %p, idle %p", task, idle);
-}
-
static inline void
write_byte(char **pos, char byte)
{
@@ -209,12 +194,12 @@ get_player_count(struct cfg *cfg, const char *pos, size_t remain)
static void
idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res)
{
- struct idle *idle = container_of(task, struct idle, idlecheck);
+ struct server *server = container_of(task, struct server, idle_task);
int32_t mclen;
int32_t jsonlen;
char *pos;
size_t remain;
- int player_count;
+ int player_count = -1;
int r;
assert_return(cfg && task);
@@ -231,8 +216,8 @@ idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res)
fprintf(stderr, "n");
*/
- remain = idle->tbuf.len;
- pos = idle->tbuf.buf;
+ remain = server->idle_buf.len;
+ pos = server->idle_buf.buf;
r = read_varint(&pos, &remain, &mclen);
if (r <= 0 || mclen < 2 || mclen < remain) {
@@ -273,34 +258,16 @@ idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res)
*/
player_count = get_player_count(cfg, pos, remain);
- if (player_count < 0)
- goto out;
-
- idle->server->state = SERVER_STATE_RUNNING;
-
- debug(DBG_IDLE, "%s: currently %i active players",
- idle->server->name, player_count);
-
- if (player_count > 0)
- idle->server->idle_count = 0;
- else if (player_count == 0)
- idle->server->idle_count++;
-
- if (idle->server->idle_count > idle->server->idle_timeout) {
- verbose("stopping idle server %s", idle->server->name);
- server_stop(cfg, idle->server);
- }
out:
uring_task_close_fd(cfg, task);
+ server_set_active_players(cfg, server, player_count);
return;
}
static void
idle_check_handshake_sent(struct cfg *cfg, struct uring_task *task, int res)
{
- struct idle *idle = container_of(task, struct idle, idlecheck);
-
assert_return(cfg && task);
assert_task_alive(DBG_IDLE, task);
@@ -310,34 +277,22 @@ idle_check_handshake_sent(struct cfg *cfg, struct uring_task *task, int res)
return;
}
- uring_tbuf_read_until(cfg, &idle->idlecheck,
+ uring_tbuf_read_until(cfg, task,
idle_check_handshake_complete,
idle_check_handshake_reply);
}
-static void
-idle_check_connected_cb(struct cfg *cfg, struct connection *conn, bool connected)
+void
+idle_check_get_player_count(struct cfg *cfg, struct server *server,
+ struct connection *conn)
{
- struct idle *idle = container_of(conn, struct idle, conn);
char buf[1024];
char *pos;
- char *cmdbuf = idle->tbuf.buf;
+ char *cmdbuf = server->idle_buf.buf;
uint16_t port;
char hostname[INET6_ADDRSTRLEN];
- assert_return(cfg && conn);
- assert_task_alive(DBG_IDLE, &idle->idlecheck);
-
- if (!connected) {
- debug(DBG_IDLE,
- "idle check connection to remote server (%s) failed",
- idle->server->name);
- idle->server->idle_count = 0;
- idle->server->state = SERVER_STATE_STOPPED;
- return;
- }
-
- debug(DBG_IDLE, "connected to remote %s", idle->conn.remote.addrstr);
+ assert_return(cfg && server && conn && server->idle_task.priv);
port = saddr_port(&conn->remote);
saddr_addr(&conn->remote, hostname, sizeof(hostname));
@@ -355,16 +310,17 @@ idle_check_connected_cb(struct cfg *cfg, struct connection *conn, bool connected
write_byte(&pos, MC_GET_STATUS);
write_cmd(&cmdbuf, buf, pos);
- idle->tbuf.len = (cmdbuf - idle->tbuf.buf);
- debug(DBG_IDLE, "sending MC message (%zu bytes)", idle->tbuf.len);
+ server->idle_buf.len = (cmdbuf - server->idle_buf.buf);
+ debug(DBG_IDLE, "sending MC message (%zu bytes)", server->idle_buf.len);
- uring_tbuf_write(cfg, &idle->idlecheck, idle_check_handshake_sent);
+ uring_tbuf_write(cfg, &server->idle_task, idle_check_handshake_sent);
}
static void
idle_cb(struct cfg *cfg, struct uring_task *task, int res)
{
struct idle *idle = container_of(task, struct idle, task);
+ struct server *server;
assert_return(cfg && task);
assert_task_alive(DBG_IDLE, task);
@@ -376,11 +332,8 @@ idle_cb(struct cfg *cfg, struct uring_task *task, int res)
debug(DBG_IDLE, "timer fired (value: %" PRIu64 ")", idle->value);
- if (!list_empty(&idle->server->proxys))
- idle->server->idle_count = 0;
- else
- connect_any(cfg, &idle->idlecheck, &idle->server->remotes,
- &idle->conn, idle_check_connected_cb);
+ list_for_each_entry(server, &cfg->servers, list)
+ server_idle_check(cfg, server);
uring_read(cfg, &idle->task, &idle->value, sizeof(idle->value), idle_cb);
}
@@ -401,26 +354,21 @@ idle_refdump(struct idle *idle)
assert_return_silent(idle);
uring_task_refdump(&idle->task);
- uring_task_refdump(&idle->idlecheck);
}
void
-idle_delete(struct cfg *cfg, struct server *server)
+idle_delete(struct cfg *cfg)
{
- struct idle *idle;
+ assert_return(cfg);
+ assert_return_silent(cfg->idle);
- assert_return(cfg && server);
- assert_return_silent(server->idle);
-
- idle = server->idle;
- debug(DBG_IDLE, "closing fd %i", idle->task.fd);
- uring_task_destroy(cfg, &idle->idlecheck);
- uring_task_destroy(cfg, &idle->task);
- server->idle = NULL;
+ debug(DBG_IDLE, "closing fd %i", cfg->idle->task.fd);
+ uring_task_destroy(cfg, &cfg->idle->task);
+ cfg->idle = NULL;
}
void
-idle_init(struct cfg *cfg, struct server *server)
+idle_init(struct cfg *cfg)
{
struct idle *idle;
int ifd;
@@ -436,10 +384,7 @@ idle_init(struct cfg *cfg, struct server *server)
}
};
- assert_return(cfg && server);
-
- if (server->idle_timeout < 1)
- return;
+ assert_return(cfg);
idle = zmalloc(sizeof(*idle));
if (!idle)
@@ -452,12 +397,9 @@ idle_init(struct cfg *cfg, struct server *server)
if (timerfd_settime(ifd, 0, &tspec, NULL) != 0)
die("timerfd_settime: %m");
- uring_task_init(cfg, &idle->task, "idle", &server->task, idle_free);
+ uring_task_init(cfg, &idle->task, "idle", uring_parent(cfg), idle_free);
uring_task_set_fd(&idle->task, ifd);
- uring_task_init(cfg, &idle->idlecheck, "idlecheck", &idle->task, idle_check_free);
- uring_task_set_buf(&idle->idlecheck, &idle->tbuf);
- idle->server = server;
- server->idle = idle;
+ cfg->idle = idle;
uring_read(cfg, &idle->task, &idle->value, sizeof(idle->value), idle_cb);
}
diff --git a/idle.h b/idle.h
index d15ee9b..a0bf5c2 100644
--- a/idle.h
+++ b/idle.h
@@ -1,10 +1,13 @@
#ifndef fooidlehfoo
#define fooidlehfoo
+void idle_check_get_player_count(struct cfg *cfg, struct server *server,
+ struct connection *conn);
+
void idle_refdump(struct idle *idle);
-void idle_delete(struct cfg *cfg, struct server *server);
+void idle_delete(struct cfg *cfg);
-void idle_init(struct cfg *cfg, struct server *server);
+void idle_init(struct cfg *cfg);
#endif
diff --git a/main.c b/main.c
index 1887a5d..df1f958 100644
--- a/main.c
+++ b/main.c
@@ -26,6 +26,7 @@
#include "announce.h"
#include "systemd.h"
#include "igmp.h"
+#include "idle.h"
#define DEFAULT_HOMEDIR_PATH "/home/david/intest"
#define DEFAULT_MAIN_CONFIG_FILE_PATH "./mcproxy.conf"
@@ -577,6 +578,7 @@ dump_tree(struct cfg *cfg)
debug(DBG_REF, "============");
uring_task_refdump(&cfg->task);
uring_refdump(cfg->uev);
+ idle_refdump(cfg->idle);
if (cfg->sev)
uring_task_refdump(&cfg->sev->task);
igmp_refdump(cfg->igmp);
@@ -614,6 +616,7 @@ signalfd_read(struct cfg *cfg, struct uring_task *task, int res)
uring_task_put(cfg, &sev->task);
igmp_delete(cfg);
announce_delete(cfg);
+ idle_delete(cfg);
cfgdir_delete(cfg);
list_for_each_entry_safe(server, stmp, &cfg->servers, list)
server_delete(cfg, server);
@@ -774,6 +777,8 @@ main(int argc, char **argv)
announce_start(cfg->aev);
+ idle_init(cfg);
+
uring_task_put(cfg, &cfg->task);
server_count = 0;
diff --git a/main.h b/main.h
index 5dff164..e418f38 100644
--- a/main.h
+++ b/main.h
@@ -150,6 +150,7 @@ struct cfg {
struct signalfd_ev *sev;
struct announce *aev;
struct igmp *igmp;
+ struct idle *idle;
struct sd_bus *sd_bus;
bool sd_bus_failed;
struct uring_task task;
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;
diff --git a/server.h b/server.h
index 46fac3f..b104ef1 100644
--- a/server.h
+++ b/server.h
@@ -62,7 +62,9 @@ struct server {
struct uring_task_buf ann_buf;
/* For checking idle status */
- struct idle *idle;
+ struct uring_task idle_task;
+ struct connection idle_conn;
+ struct uring_task_buf idle_buf;
unsigned idle_timeout;
unsigned idle_count;
@@ -83,6 +85,11 @@ bool server_start(struct cfg *cfg, struct server *server);
bool server_stop(struct cfg *cfg, struct server *server);
+void server_set_active_players(struct cfg *cfg, struct server *server,
+ int count);
+
+bool server_idle_check(struct cfg *cfg, struct server *server);
+
bool server_announce(struct cfg *cfg, struct server *server, int fd);
bool server_commit(struct cfg *cfg, struct server *server);