summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-23 12:52:36 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-23 12:52:36 +0200
commita4940279d373dc9b9a5526498e390e31d6a8efec (patch)
tree6babcf0300a561302ba5e6e8a5436ae120dad448
parentfd4f4ace264a91355df46186dd88f566fb451aa5 (diff)
Remove allocations from server-rcon in preparation for splitting out rcon protocol handling
-rw-r--r--server-rcon.c167
-rw-r--r--server-rcon.h4
-rw-r--r--server.c6
-rw-r--r--server.h4
-rw-r--r--uring.c1
5 files changed, 92 insertions, 90 deletions
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);
}
+
diff --git a/server-rcon.h b/server-rcon.h
index 1e4ea24..6625f25 100644
--- a/server-rcon.h
+++ b/server-rcon.h
@@ -1,7 +1,9 @@
#ifndef fooserverrconhfoo
#define fooserverrconhfoo
-void rcon_refdump(struct rcon *rcon);
+void rcon_stop(struct server *server);
+
+void rcon_refdump(struct server *server);
void rcon_delete(struct server *server);
diff --git a/server.c b/server.c
index 9f0baec..de42721 100644
--- a/server.c
+++ b/server.c
@@ -52,7 +52,7 @@ server_refdump(struct server *server)
local_refdump(local);
list_for_each_entry(proxy, &server->proxys, list)
proxy_refdump(proxy);
- rcon_refdump(server->rcon);
+ rcon_refdump(server);
}
static void
@@ -331,7 +331,7 @@ server_stop(struct server *server)
case SERVER_STOP_METHOD_RCON:
verbose("Stopping server %s via rcon", server->name);
- rcon_init(server);
+ rcon_stop(server);
return true;
case SERVER_STOP_METHOD_UNDEFINED:
@@ -824,6 +824,8 @@ server_new(const char *name)
uring_task_init(&server->idle_task, "idle", &server->task, server_idle_free);
uring_task_set_buf(&server->idle_task, &server->idle_buf);
+ rcon_init(server);
+
list_init(&server->remotes);
list_init(&server->locals);
list_init(&server->proxys);
diff --git a/server.h b/server.h
index 223c837..ff4c28e 100644
--- a/server.h
+++ b/server.h
@@ -53,8 +53,10 @@ struct server {
char *systemd_obj;
/* For rcon connections */
- struct rcon *rcon;
char *rcon_password;
+ struct connection rcon_conn;
+ struct uring_task rcon_task;
+ struct uring_task_buf rcon_tbuf;
/* For announce messages */
struct uring_task ann_task;
diff --git a/uring.c b/uring.c
index 3437d7e..e979471 100644
--- a/uring.c
+++ b/uring.c
@@ -97,6 +97,7 @@ void
uring_task_destroy(struct uring_task *task)
{
assert_return(task);
+ assert_return_silent(!task->dead);
debug(DBG_UR, "task %s (%p), fd %i, refcount %u",
task->name, task, task->fd, task->refcount);