diff options
author | David Härdeman <david@hardeman.nu> | 2020-06-10 14:14:24 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2020-06-10 14:14:24 +0200 |
commit | 06edc57d49547c2d5981467550043660c1f5f282 (patch) | |
tree | 58d30e4f3771df582db6f7566cf1e53d3d86564d | |
parent | 9daf6a0e6b461c6c2a16f810f722b9d10504bf90 (diff) |
Convert idle to use tbuf
-rw-r--r-- | idle.c | 189 | ||||
-rw-r--r-- | server.c | 3 | ||||
-rw-r--r-- | uring.c | 4 |
3 files changed, 109 insertions, 87 deletions
@@ -6,6 +6,7 @@ #include <arpa/inet.h> #include <string.h> #include <ctype.h> +#include <errno.h> #include "main.h" #include "uring.h" @@ -22,9 +23,8 @@ struct idle { unsigned next_remote; struct sockaddr_in46 remote; char remotestr[ADDRSTRLEN]; - char remotebuf[4096]; - size_t remotebuflen; - size_t remotebufdone; + + struct uring_task_buf tbuf; }; static void @@ -64,8 +64,8 @@ write_varint(char **pos, int32_t orig) /* * return value: - * positive = need more bytes - * zero = value decoded + * positive = varint parsed + * zero = need more bytes * negative = error */ static inline int @@ -86,13 +86,13 @@ read_varint(char **pos, size_t *remain, int32_t *res) } if (consumed > *remain) - return 1; + return 0; else if (consumed > MC_VARINT_MAX_BYTES) return -1; *remain -= consumed; *res = (int32_t)val; - return 0; + return 1; } static inline void @@ -115,7 +115,77 @@ write_cmd(char **pos, const char *begin, const char *end) write_bytes(pos, begin, end - begin); } +static int +idle_check_handshake_complete(struct cfg *cfg, struct uring_task *task, int res) +{ + size_t remain; + char *pos; + int32_t mclen; + int r; + + remain = task->tbuf->len; + pos = task->tbuf->buf; + + r = read_varint(&pos, &remain, &mclen); + if (r < 0) { + fprintf(stderr, "Failed to parse message length\n"); + return -EINVAL; + } else if (r == 0) { + return 0; + } else if (mclen < 2) { + fprintf(stderr, "Short MC message\n"); + return -EINVAL; + } + + fprintf(stderr, "MC message len: %" PRIi32 "\n", mclen); + fprintf(stderr, "Remain: %zu\n", remain); + + if (mclen < remain) + return 0; + + fprintf(stderr, "Complete message\n"); + return 1; +} + #define ONLINE_NEEDLE "\"online\"" +static int +get_player_count(struct cfg *cfg, const char *pos, size_t remain) +{ + /* + * Example JSON (line breaks added): + * {"description":{ + * "text":"A Minecraft Server"}, + * "players":{"max":20,"online":0}, + * "version":{"name":"1.15.2","protocol":578} + * } + */ + char *online; + char *end; + unsigned count; + + online = memmem(pos, remain, ONLINE_NEEDLE, strlen(ONLINE_NEEDLE)); + if (!online) { + fprintf(stderr, "Could not find online count in JSON\n"); + return -1; + } + + remain -= (online - pos); + + end = memchr(online, '}', remain); + if (!end) { + fprintf(stderr, "Could not parse JSON (no end)\n"); + return -1; + } + *end = '\0'; + + if (sscanf(online, ONLINE_NEEDLE " : %u", &count) != 1) { + fprintf(stderr, "Could not parse JSON (online count)\n"); + return -1; + } + + return count; +} + static void idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res) { @@ -124,14 +194,13 @@ idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res) int32_t jsonlen; char *pos; size_t remain; + int player_count; int r; fprintf(stderr, "%s: received %i bytes\n", __func__, res); if (res < 0) goto error; - idle->remotebuflen += res; - /* fprintf(stderr, "Received MC message (%i bytes):\n", res); for (int i = 0; i < res; i++) @@ -139,35 +208,29 @@ idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res) fprintf(stderr, "\n"); */ - remain = idle->remotebuflen; - pos = idle->remotebuf; + remain = idle->tbuf.len; + pos = idle->tbuf.buf; r = read_varint(&pos, &remain, &mclen); - if (r < 0) { - fprintf(stderr, "Failed to parse message length\n"); - goto error; - } else if (r > 0) { - goto read_more; - } else if (mclen < 2) { - fprintf(stderr, "Short MC message\n"); + if (r <= 0 || mclen < 2 || mclen < remain) { + /* Should not happen since the msg has been checked already */ + fprintf(stderr, "Invalid message\n"); goto error; } - fprintf(stderr, "MC message len: %" PRIi32 "\n", mclen); - fprintf(stderr, "Remain: %zu\n", remain); - - if (mclen < remain) - goto read_more; + fprintf(stderr, "%s: MC message len: %" PRIi32 "\n", __func__, mclen); + fprintf(stderr, "%s: Remain: %zu\n", __func__, remain); if (*pos != MC_STATUS_REPLY) { fprintf(stderr, "Unknown server reply\n"); goto error; } + pos++; remain--; r = read_varint(&pos, &remain, &jsonlen); - if (r != 0) { + if (r <= 0) { fprintf(stderr, "Could not read JSON length\n"); goto error; } @@ -185,41 +248,12 @@ idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res) fprintf(stderr, "%c", pos[i]); fprintf(stderr, "\n"); - /* - * Example JSON (line breaks added): - * {"description":{ - * "text":"A Minecraft Server"}, - * "players":{"max":20,"online":0}, - * "version":{"name":"1.15.2","protocol":578} - * } - */ - - char *online; - char *end; - unsigned count; + player_count = get_player_count(cfg, pos, remain); + fprintf(stderr, "We have %i players\n", player_count); - online = memmem(pos, remain, ONLINE_NEEDLE, strlen(ONLINE_NEEDLE)); - if (!online) { - fprintf(stderr, "Could not find online count in JSON\n"); - goto error; - } - - remain -= (online - pos); - - end = memchr(online, '}', remain); - if (!end) { - fprintf(stderr, "Could not parse JSON (no end)\n"); - goto error; - } - *end = '\0'; - - if (sscanf(online, ONLINE_NEEDLE " : %u", &count) != 1) { - fprintf(stderr, "Could not parse JSON (online count)\n"); + if (player_count < 0) goto error; - } - - fprintf(stderr, "We have %u players\n", count); - if (count > 0) + else if (player_count > 0) idle->server->idle_count = 0; else { idle->server->idle_count++; @@ -231,17 +265,8 @@ idle_check_handshake_reply(struct cfg *cfg, struct uring_task *task, int res) return; -read_more: - if (idle->remotebuflen >= sizeof(idle->remotebuflen)) - goto error; - - uring_read(cfg, &idle->idlecheck, idle->remotebuf + idle->remotebuflen, - sizeof(idle->remotebuf) - idle->remotebuflen, - 0, idle_check_handshake_reply); - return; - error: - /* FIXME */ + uring_task_close_fd(cfg, task); return; } @@ -252,19 +277,11 @@ idle_check_handshake_sent(struct cfg *cfg, struct uring_task *task, int res) fprintf(stderr, "%s: sent %i bytes\n", __func__, res); if (res < 0) { + uring_task_close_fd(cfg, task); return; } - idle->remotebufdone += res; - if (idle->remotebufdone < idle->remotebuflen) - uring_write(cfg, &idle->idlecheck, - idle->remotebuf + idle->remotebufdone, - idle->remotebuflen - idle->remotebufdone, - idle_check_handshake_sent); - else { - idle->remotebuflen = 0; - uring_read(cfg, &idle->idlecheck, idle->remotebuf, sizeof(idle->remotebuf), 0, idle_check_handshake_reply); - } + uring_tbuf_read_until(cfg, &idle->idlecheck, idle_check_handshake_complete, idle_check_handshake_reply); } static void idle_check_connect_next_remote(struct cfg *cfg, struct idle *idle); @@ -275,11 +292,13 @@ idle_check_remote_connected(struct cfg *cfg, struct uring_task *task, int res) struct idle *idle = container_of(task, struct idle, idlecheck); char buf[1024]; char *pos; - char *cmdbuf = idle->remotebuf; + char *cmdbuf = idle->tbuf.buf; uint16_t port = 25565; + /* FIXME: Write real remote addr and port */ fprintf(stderr, "%s: connected %i\n", __func__, res); if (res < 0) { + uring_task_close_fd(cfg, task); idle_check_connect_next_remote(cfg, idle); return; } @@ -298,14 +317,13 @@ idle_check_remote_connected(struct cfg *cfg, struct uring_task *task, int res) write_byte(&pos, MC_GET_STATUS); write_cmd(&cmdbuf, buf, pos); - idle->remotebufdone = 0; - idle->remotebuflen = (cmdbuf - idle->remotebuf); - fprintf(stderr, "Sending MC message (%zu bytes):\n", idle->remotebuflen); - for (pos = idle->remotebuf; pos < cmdbuf; pos++) + idle->tbuf.len = (cmdbuf - idle->tbuf.buf); + fprintf(stderr, "Sending MC message (%zu bytes):\n", idle->tbuf.len); + for (pos = idle->tbuf.buf; pos < cmdbuf; pos++) fprintf(stderr, "0x%02hhx ", *pos); fprintf(stderr, "\n"); - uring_write(cfg, &idle->idlecheck, idle->remotebuf, idle->remotebuflen, idle_check_handshake_sent); + uring_tbuf_write(cfg, &idle->idlecheck, idle_check_handshake_sent); } /* FIXME: Parts of this could be shared with proxy.c, probably in server.c */ @@ -329,7 +347,7 @@ again: if (!remote) { fprintf(stderr, "No more remote addresses to attempt\n"); - /* FIXME: put tasks */ + /* FIXME: put tasks? */ return; } @@ -445,8 +463,9 @@ idle_init(struct cfg *cfg, struct server *server) perrordie("timerfd_settime"); uring_task_init(&idle->task, "idle", &server->task, idle_free); - uring_task_init(&idle->idlecheck, "idlecheck", &idle->task, idle_check_free); uring_task_set_fd(&idle->task, ifd); + uring_task_init(&idle->idlecheck, "idlecheck", &idle->task, idle_check_free); + uring_task_set_buf(&idle->idlecheck, &idle->tbuf); idle->server = server; server->idle = idle; @@ -122,7 +122,7 @@ server_dump(struct server *scfg) struct sockaddr_in46 *remote; char abuf[ADDRSTRLEN]; - fprintf(stderr, "Dumping server %s\n", scfg->name); + fprintf(stderr, "\nDumping server %s\n", scfg->name); switch (scfg->type) { case SERVER_TYPE_ANNOUNCE: fprintf(stderr, " * Type: announce\n"); @@ -145,6 +145,7 @@ server_dump(struct server *scfg) fprintf(stderr, " * RCon:\n"); list_for_each_entry(remote, &scfg->rcons, list) fprintf(stderr, " * %s\n", sockaddr_to_str(remote, abuf, sizeof(abuf))); + fprintf(stderr, "\n"); } static void @@ -119,7 +119,9 @@ uring_task_set_fd(struct uring_task *task, int fd) void uring_task_close_fd(struct cfg *cfg, struct uring_task *task) { - fprintf(stderr, "%s called with task 0x%p\n", __func__, task); + fprintf(stderr, "%s: called with task %s (0x%p)\n", + __func__, task->name, task); + if (task->fd < 0) return; |