From 7e728d971b95f115c7e9c2def21815034d9bde54 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Wed, 1 Jul 2020 21:29:06 +0200 Subject: Reduce some rcon duplication by using a common function --- minecctl/rcon-commands.c | 34 ++++++++++++---------------------- minecproxy/server-rcon.c | 36 +++++++++++------------------------- shared/rcon-protocol.c | 29 +++++++++++++++++++++++++++++ shared/rcon-protocol.h | 16 ++++++++++------ 4 files changed, 62 insertions(+), 53 deletions(-) diff --git a/minecctl/rcon-commands.c b/minecctl/rcon-commands.c index dfe8647..be18bba 100644 --- a/minecctl/rcon-commands.c +++ b/minecctl/rcon-commands.c @@ -69,10 +69,11 @@ static void read_packet(int sfd, char *buf, size_t len, int32_t *id, } static void send_msg(int sfd, char *buf, size_t len, enum rcon_packet_type type, - const char *msg, enum rcon_packet_type *rtype, + const char *msg, int32_t *rtype, const char **reply) { static uint32_t rcon_packet_id = 1; + const char *error; size_t plen; int32_t id; @@ -84,25 +85,17 @@ static void send_msg(int sfd, char *buf, size_t len, enum rcon_packet_type type, read_packet(sfd, buf, len, &id, rtype, reply); - /* FIXME: this should be shared */ - if (type == RCON_PACKET_LOGIN) { - if (*rtype != RCON_PACKET_LOGIN_OK) - die("Invalid reply id"); - - if (id == RCON_PACKET_LOGIN_FAIL) - *rtype = RCON_PACKET_LOGIN_FAIL; - else if (id != rcon_packet_id) - die("Invalid reply id"); - } else { - if (id != rcon_packet_id) - die("Invalid reply"); - } + /* FIXME: Shouldn't die */ + if (!rcon_protocol_verify_response(rcon_packet_id, id, type, + *rtype, &error)) + die("Invalid response: %s", error); rcon_packet_id++; } static int rcon_login(struct cfg *cfg, struct server *server) { + const char *error; char buf[4096]; int32_t rtype; const char *reply; @@ -135,15 +128,12 @@ static int rcon_login(struct cfg *cfg, struct server *server) explicit_bzero(buf, sizeof(buf)); free_password(&server->scfg.rcon_password); - if (rtype == RCON_PACKET_LOGIN_OK) - verbose("%s: login ok", server->name); - else if (rtype == RCON_PACKET_LOGIN_FAIL) { - info("%s: login failure, invalid password?", server->name); + if (!rcon_protocol_verify_response(1, 1, RCON_PACKET_LOGIN, + rtype, &error)) { + error("%s: invalid response - %s", server->name, error); goto error; - } else { - error("%s: invalid return code: %" PRIi32, server->name, rtype); - goto error; - } + } else + verbose("%s: login ok", server->name); return fd; diff --git a/minecproxy/server-rcon.c b/minecproxy/server-rcon.c index 1f3acfa..4c9da48 100644 --- a/minecproxy/server-rcon.c +++ b/minecproxy/server-rcon.c @@ -55,7 +55,7 @@ static void rcon_stop_reply(struct uring_task *task, int res) struct server *server = container_of(task, struct server, rcon_task); int32_t id; int32_t type; - const char *msg; + const char *msg, *error; assert_return(task); assert_task_alive(DBG_RCON, task); @@ -63,19 +63,13 @@ static void rcon_stop_reply(struct uring_task *task, int res) if (!rcon_check_reply(task, res, &id, &type, &msg)) return; - if (id != 2) { - error("rcon(%s): stop cmd failed, reply id (%" PRIi32 ")", - server->name, id); - goto out; - } else if (type != RCON_PACKET_RESPONSE) { - error("rcon(%s): stop cmd failed, reply type (%" PRIi32 ")", - server->name, type); - goto out; - } - - verbose("rcon(%s): stop command sent, reply: %s", server->name, msg); + if (!rcon_protocol_verify_response(2, id, RCON_PACKET_COMMAND, type, + &error)) + error("rcon(%s): stop cmd failed - %s", server->name, error); + else + verbose("rcon(%s): stop command sent, reply: %s", + server->name, msg); -out: uring_task_close_fd(task); } @@ -102,7 +96,7 @@ static void rcon_login_reply(struct uring_task *task, int res) struct server *server = container_of(task, struct server, rcon_task); int32_t id; int32_t type; - const char *msg; + const char *msg, *error; assert_return(task); assert_task_alive(DBG_RCON, task); @@ -110,17 +104,9 @@ static void rcon_login_reply(struct uring_task *task, int res) if (!rcon_check_reply(task, res, &id, &type, &msg)) return; - if (id != 1) { - error("rcon(%s): login failed, reply id (%" PRIi32 ")", - server->name, id); - goto error; - } else if (type == RCON_PACKET_LOGIN_FAIL) { - error("rcon(%s): login failed, incorrect password", - server->name); - goto error; - } else if (type != RCON_PACKET_LOGIN_OK) { - error("rcon(%s): login failed, reply type (%" PRIi32 ")", - server->name, type); + if (!rcon_protocol_verify_response(1, id, RCON_PACKET_LOGIN, type, + &error)) { + error("rcon(%s): login failed - %s", server->name, error); goto error; } diff --git a/shared/rcon-protocol.c b/shared/rcon-protocol.c index 0cf73fc..1941662 100644 --- a/shared/rcon-protocol.c +++ b/shared/rcon-protocol.c @@ -75,6 +75,35 @@ static void write_end(char **pos, size_t *len) *len += RCON_END_LEN; } +bool rcon_protocol_verify_response(int32_t id_sent, int32_t id_recv, + enum rcon_packet_type t_sent, + enum rcon_packet_type t_recv, + const char **error) +{ + if (t_sent == RCON_PACKET_LOGIN) { + if (t_recv != RCON_PACKET_LOGIN_RESPONSE) { + *error = "invalid reply id"; + return false; + } else if (id_recv == RCON_PACKET_LOGIN_FAIL_ID) { + *error = "login failure"; + return false; + } else if (id_recv != id_sent) { + *error = "invalid reply id"; + return false; + } + } else { + if (t_recv != RCON_PACKET_RESPONSE) { + *error = "invalid reply type"; + return false; + } else if (id_recv != id_sent) { + *error = "invalid reply id"; + return false; + } + } + + return true; +} + bool rcon_protocol_create_packet(char *buf, size_t len, size_t *rlen, int32_t reqid, enum rcon_packet_type type, const char *msg) diff --git a/shared/rcon-protocol.h b/shared/rcon-protocol.h index b3aea98..593a43f 100644 --- a/shared/rcon-protocol.h +++ b/shared/rcon-protocol.h @@ -4,14 +4,13 @@ #include #include -/* FIXME: FAIL is an id, not type, LOGIN_OK should be LOGIN_RESPONSE */ /* clang-format off */ +#define RCON_PACKET_LOGIN_FAIL_ID -1 enum rcon_packet_type { - RCON_PACKET_LOGIN = 3, - RCON_PACKET_LOGIN_OK = 2, - RCON_PACKET_LOGIN_FAIL = -1, - RCON_PACKET_COMMAND = 2, - RCON_PACKET_RESPONSE = 0, + RCON_PACKET_LOGIN = 3, + RCON_PACKET_LOGIN_RESPONSE = 2, + RCON_PACKET_COMMAND = 2, + RCON_PACKET_RESPONSE = 0, }; /* clang-format on */ @@ -30,6 +29,11 @@ static inline size_t rcon_protocol_packet_len(size_t msglen) return (RCON_PKT_MIN_LEN + msglen); } +bool rcon_protocol_verify_response(int32_t id_sent, int32_t id_recv, + enum rcon_packet_type t_sent, + enum rcon_packet_type t_recv, + const char **error); + bool rcon_protocol_create_packet(char *buf, size_t len, size_t *rlen, int32_t reqid, enum rcon_packet_type type, const char *msg); -- cgit v1.2.3