summaryrefslogtreecommitdiff
path: root/idle.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-10 14:14:24 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-10 14:14:24 +0200
commit06edc57d49547c2d5981467550043660c1f5f282 (patch)
tree58d30e4f3771df582db6f7566cf1e53d3d86564d /idle.c
parent9daf6a0e6b461c6c2a16f810f722b9d10504bf90 (diff)
Convert idle to use tbuf
Diffstat (limited to 'idle.c')
-rw-r--r--idle.c189
1 files changed, 104 insertions, 85 deletions
diff --git a/idle.c b/idle.c
index fc6be9b..ce0dfc4 100644
--- a/idle.c
+++ b/idle.c
@@ -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;