summaryrefslogtreecommitdiff
path: root/minecctl/mc-commands.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-27 15:18:45 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-27 15:18:45 +0200
commit99b2c70137fef05a5a18f439b9010ddba455f5cb (patch)
treeb0c08cfce14019cd634e6b4b84d0cf0f6e8eee6a /minecctl/mc-commands.c
parenta87e894ba3f3a8915389f651fb034f0d1835630c (diff)
Create a shared mc protocol implementation and use it in the proxy and cmd line tool
Diffstat (limited to 'minecctl/mc-commands.c')
-rw-r--r--minecctl/mc-commands.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/minecctl/mc-commands.c b/minecctl/mc-commands.c
new file mode 100644
index 0000000..0ac20d0
--- /dev/null
+++ b/minecctl/mc-commands.c
@@ -0,0 +1,77 @@
+#include <unistd.h>
+
+#include "utils.h"
+#include "minecctl.h"
+#include "server.h"
+#include "mc-commands.h"
+#include "misc.h"
+#include "mc-protocol.h"
+
+bool
+do_mc_pcount(struct cfg *cfg, unsigned *online, unsigned *max)
+{
+ struct server *server;
+ struct saddr *saddr;
+ char buf[4096];
+ size_t plen, off;
+ ssize_t r;
+ bool rv = false;
+ int fd;
+
+ server = server_get_default(cfg);
+
+ fd = connect_any(&server->mc_addrs, true);
+ if (fd < 0) {
+ error("%s: unable to connect", server->name);
+ return false;
+ }
+
+ /* FIXME: connect_any needs to indicate the address it used */
+ saddr = list_first_entry(&server->mc_addrs, struct saddr, list);
+ if (!saddr) {
+ error("No saddr");
+ goto out;
+ }
+
+ if (!mc_protocol_create_status_request(buf, sizeof(buf), &plen, saddr)) {
+ error("Failed to create req");
+ goto out;
+ }
+
+ /* FIXME: do proper checks for EINTR etc */
+ off = 0;
+ while (off < plen) {
+ r = write(fd, buf + off, plen - off);
+ if (r <= 0) {
+ error("write failed: %zi (%m)", r);
+ goto out;
+ }
+ off += r;
+ }
+
+ off = 0;
+ while (off < sizeof(buf)) {
+ r = read(fd, buf + off, sizeof(buf) - off);
+ if (r <= 0) {
+ error("Read failed %zi: %m", r);
+ goto out;
+ }
+
+ off += r;
+
+ if (mc_is_handshake_complete(buf, off)) {
+ rv = true;
+ break;
+ }
+ }
+
+ if (!mc_protocol_parse_status_reply(buf, off, online, max)) {
+ error("Failed to get player count");
+ return false;
+ }
+
+out:
+ close(fd);
+ return rv;
+}
+