From a4940279d373dc9b9a5526498e390e31d6a8efec Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Tue, 23 Jun 2020 12:52:36 +0200 Subject: Remove allocations from server-rcon in preparation for splitting out rcon protocol handling --- server-rcon.c | 167 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 86 deletions(-) (limited to 'server-rcon.c') diff --git a/server-rcon.c b/server-rcon.c index 5409b48..710d969 100644 --- a/server-rcon.c +++ b/server-rcon.c @@ -15,13 +15,6 @@ #include "server.h" #include "server-rcon.h" -struct rcon { - struct server *server; - struct connection conn; - struct uring_task task; - struct uring_task_buf tbuf; -}; - static int32_t read_int(char **pos, size_t *len) { @@ -104,32 +97,32 @@ enum rcon_packet_type { }; static void -create_packet(struct rcon *rcon, int32_t reqid, - enum rcon_packet_type type, const char *msg) +rcon_create_packet(struct uring_task_buf *tbuf, int32_t reqid, + enum rcon_packet_type type, const char *msg) { char *pos; - assert_return(rcon && !empty_str(msg)); + assert_return(tbuf && !empty_str(msg)); /* Body */ - pos = &rcon->tbuf.buf[4]; - rcon->tbuf.len = 4; - write_int(&pos, &rcon->tbuf.len, reqid); - write_int(&pos, &rcon->tbuf.len, type); - write_str(&pos, &rcon->tbuf.len, msg); - write_end(&pos, &rcon->tbuf.len); + pos = &tbuf->buf[4]; + tbuf->len = 4; + write_int(&pos, &tbuf->len, reqid); + write_int(&pos, &tbuf->len, type); + write_str(&pos, &tbuf->len, msg); + write_end(&pos, &tbuf->len); /* Header (length of body) */ - pos = &rcon->tbuf.buf[0]; - write_int(&pos, NULL, rcon->tbuf.len - 4); + pos = &tbuf->buf[0]; + write_int(&pos, NULL, tbuf->len - 4); debug(DBG_RCON, "created packet (reqid: %" PRIi32 ", type %" PRIi32 ", len %zu, payload: %s)", - reqid, type, rcon->tbuf.len, msg); + reqid, type, tbuf->len, msg); } static int -packet_complete(struct uring_task *task, int res) +rcon_packet_complete(struct uring_task *task, int res) { char *pos; size_t len; @@ -154,17 +147,17 @@ packet_complete(struct uring_task *task, int res) } static bool -rcon_read_packet(struct rcon *rcon, int32_t *id, +rcon_read_packet(struct uring_task_buf *tbuf, int32_t *id, int32_t *type, char **rmsg) { char *pos; size_t len; int32_t plen; - assert_return(rcon && id && type && rmsg, false); + assert_return(tbuf && id && type && rmsg, false); - pos = rcon->tbuf.buf; - len = rcon->tbuf.len; + pos = tbuf->buf; + len = tbuf->len; plen = read_int(&pos, &len); *id = read_int(&pos, &len); *type = read_int(&pos, &len); @@ -201,7 +194,7 @@ rcon_read_packet(struct rcon *rcon, int32_t *id, static void rcon_stop_reply(struct uring_task *task, int res) { - struct rcon *rcon = container_of(task, struct rcon, task); + struct server *server = container_of(task, struct server, rcon_task); int32_t id; int32_t type; char *msg; @@ -210,49 +203,52 @@ rcon_stop_reply(struct uring_task *task, int res) assert_task_alive(DBG_RCON, task); if (res < 0) { - debug(DBG_RCON, "res: %i", res); + error("rcon(%s): reading stop cmd reply failed, res: %i", + server->name, res); goto out; } - debug(DBG_RCON, "packet complete"); - rcon_read_packet(rcon, &id, &type, &msg); + rcon_read_packet(task->tbuf, &id, &type, &msg); if (id != 2) { - error("rcon stop failed - reply id (%" PRIi32 ")", id); + error("rcon(%s): stop cmd failed, reply id (%" PRIi32 ")", + server->name, id); goto out; } else if (type != RCON_PACKET_RESPONSE) { - error("rcon stop failed - reply type (%" PRIi32 ")", type); + error("rcon(%s): stop cmd failed, reply type (%" PRIi32 ")", + server->name, type); goto out; } - verbose("rcon stop successful (%s)", msg); + verbose("rcon(%s): stop command sent, reply: %s", server->name, msg); out: - uring_task_put(&rcon->task); + uring_task_close_fd(task); } static void rcon_stop_sent(struct uring_task *task, int res) { - struct rcon *rcon = container_of(task, struct rcon, task); + struct server *server = container_of(task, struct server, rcon_task); assert_return(task); assert_task_alive(DBG_RCON, task); - if (res < 0) { - debug(DBG_RCON, "res: %i", res); - uring_task_put(&rcon->task); + if (res != task->tbuf->len) { + error("rcon(%s): sending stop cmd failed, res: %i", + server->name, res); + uring_task_close_fd(task); return; } - debug(DBG_RCON, "stop cmd sent"); - uring_tbuf_read_until(&rcon->task, packet_complete, rcon_stop_reply); + debug(DBG_RCON, "rcon(%s): stop cmd sent", server->name); + uring_tbuf_read_until(task, rcon_packet_complete, rcon_stop_reply); } static void rcon_login_reply(struct uring_task *task, int res) { - struct rcon *rcon = container_of(task, struct rcon, task); + struct server *server = container_of(task, struct server, rcon_task); int32_t id; int32_t type; char *msg; @@ -261,115 +257,114 @@ rcon_login_reply(struct uring_task *task, int res) assert_task_alive(DBG_RCON, task); if (res < 0) { - debug(DBG_RCON, "res: %i", res); + error("rcon(%s): reading login reply failed, res: %i", + server->name, res); goto error; } - debug(DBG_RCON, "packet complete"); - rcon_read_packet(rcon, &id, &type, &msg); + rcon_read_packet(task->tbuf, &id, &type, &msg); if (id != 1) { - error("rcon login failed - unexpected reply id (%" PRIi32 ")", id); + error("rcon(%s): login failed, reply id (%" PRIi32 ")", + server->name, id); goto error; } else if (type == RCON_PACKET_LOGIN_FAIL) { - error("rcon login failed - incorrect password"); + error("rcon(%s): login failed, incorrect password", + server->name); goto error; } else if (type != RCON_PACKET_LOGIN_OK) { - error("rcon login failed - unexpected reply type (%" PRIi32 ")", type); + error("rcon(%s): login failed, reply type (%" PRIi32 ")", + server->name, type); goto error; } - debug(DBG_RCON, "rcon login successful"); - create_packet(rcon, 2, RCON_PACKET_COMMAND, "stop"); - uring_tbuf_write(&rcon->task, rcon_stop_sent); + debug(DBG_RCON, "rcon(%s): login successful", server->name); + rcon_create_packet(task->tbuf, 2, RCON_PACKET_COMMAND, "stop"); + uring_tbuf_write(task, rcon_stop_sent); return; error: - uring_task_put(&rcon->task); + uring_task_close_fd(task); } static void rcon_login_sent(struct uring_task *task, int res) { - struct rcon *rcon = container_of(task, struct rcon, task); + struct server *server = container_of(task, struct server, rcon_task); assert_return(task); assert_task_alive(DBG_RCON, task); - if (res < 0) { - debug(DBG_RCON, "res: %i", res); - uring_task_put(&rcon->task); + if (res != task->tbuf->len) { + error("rcon(%s): sending login failed, res: %i", + server->name, res); + uring_task_close_fd(task); return; } - debug(DBG_RCON, "login sent"); - uring_tbuf_read_until(&rcon->task, packet_complete, rcon_login_reply); + debug(DBG_RCON, "rcon(%s): login sent", server->name); + uring_tbuf_read_until(task, rcon_packet_complete, rcon_login_reply); } static void rcon_connected_cb(struct connection *conn, bool connected) { - struct rcon *rcon = container_of(conn, struct rcon, conn); + struct server *server = container_of(conn, struct server, rcon_conn); assert_return(conn); - assert_task_alive(DBG_RCON, &rcon->task); + assert_task_alive(DBG_RCON, &server->rcon_task); if (!connected) { - error("rcon connection to remote server (%s) failed", - rcon->server->name); - uring_task_put(&rcon->task); + error("rcon (%s): connection failed", server->name); return; } - create_packet(rcon, 1, RCON_PACKET_LOGIN, rcon->server->rcon_password); - uring_tbuf_write(&rcon->task, rcon_login_sent); + rcon_create_packet(&server->rcon_tbuf, 1, RCON_PACKET_LOGIN, server->rcon_password); + uring_tbuf_write(&server->rcon_task, rcon_login_sent); } static void rcon_free(struct uring_task *task) { - struct rcon *rcon = container_of(task, struct rcon, task); + struct server *server = container_of(task, struct server, rcon_task); assert_return(task); - debug(DBG_RCON, "task %p, idle %p", task, rcon); - rcon->server->rcon = NULL; - xfree(rcon); + debug(DBG_RCON, "task %p, server %s (%p)", task, server->name, server); } void -rcon_refdump(struct rcon *rcon) +rcon_stop(struct server *server) { - assert_return_silent(rcon); + assert_return(server && !list_empty(&server->rcons) && !empty_str(server->rcon_password)); + assert_task_alive(DBG_RCON, &server->rcon_task); - uring_task_refdump(&rcon->task); + connect_any(&server->rcon_task, &server->rcons, &server->rcon_conn, rcon_connected_cb); } void -rcon_delete(struct server *server) +rcon_refdump(struct server *server) { - assert_return_silent(server->rcon); + assert_return(server); - debug(DBG_RCON, "closing fd %i", server->rcon->task.fd); - uring_task_destroy(&server->rcon->task); - server->rcon = NULL; + uring_task_refdump(&server->rcon_task); } void -rcon_init(struct server *server) +rcon_delete(struct server *server) { - struct rcon *rcon; + assert_return(server); - assert_return(server && !server->rcon && !list_empty(&server->rcons) && !empty_str(server->rcon_password)); - - rcon = zmalloc(sizeof(*rcon)); - if (!rcon) - die("malloc: %m"); + debug(DBG_RCON, "closing fd %i", server->rcon_task.fd); + uring_task_destroy(&server->rcon_task); +} - uring_task_init(&rcon->task, "rcon", &server->task, rcon_free); - uring_task_set_buf(&rcon->task, &rcon->tbuf); - rcon->server = server; - server->rcon = rcon; +void +rcon_init(struct server *server) +{ + assert_return(server); - connect_any(&rcon->task, &server->rcons, &rcon->conn, rcon_connected_cb); + uring_task_init(&server->rcon_task, "rcon", &server->task, rcon_free); + uring_task_set_buf(&server->rcon_task, &server->rcon_tbuf); } + -- cgit v1.2.3