summaryrefslogtreecommitdiff
path: root/minecctl
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
parenta87e894ba3f3a8915389f651fb034f0d1835630c (diff)
Create a shared mc protocol implementation and use it in the proxy and cmd line tool
Diffstat (limited to 'minecctl')
-rw-r--r--minecctl/mc-commands.c77
-rw-r--r--minecctl/mc-commands.h6
-rw-r--r--minecctl/meson.build1
-rw-r--r--minecctl/misc-commands.c15
-rw-r--r--minecctl/misc-commands.h2
-rw-r--r--minecctl/misc.c9
-rw-r--r--minecctl/rcon-commands.c19
-rw-r--r--minecctl/rcon-commands.h2
8 files changed, 118 insertions, 13 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;
+}
+
diff --git a/minecctl/mc-commands.h b/minecctl/mc-commands.h
new file mode 100644
index 0000000..3140a73
--- /dev/null
+++ b/minecctl/mc-commands.h
@@ -0,0 +1,6 @@
+#ifndef foomccommandshfoo
+#define foomccomanndshfoo
+
+bool do_mc_pcount(struct cfg *cfg, unsigned *online, unsigned *max);
+
+#endif
diff --git a/minecctl/meson.build b/minecctl/meson.build
index e3bddcc..7a41203 100644
--- a/minecctl/meson.build
+++ b/minecctl/meson.build
@@ -2,6 +2,7 @@ minecctl_sources = [
'minecctl.c',
'server.c',
'rcon-commands.c',
+ 'mc-commands.c',
'misc-commands.c',
'misc.c',
]
diff --git a/minecctl/misc-commands.c b/minecctl/misc-commands.c
index 6b70c55..c64a005 100644
--- a/minecctl/misc-commands.c
+++ b/minecctl/misc-commands.c
@@ -2,6 +2,8 @@
#include "minecctl.h"
#include "server.h"
#include "misc-commands.h"
+#include "rcon-commands.h"
+#include "mc-commands.h"
bool
do_list(struct cfg *cfg)
@@ -16,3 +18,16 @@ do_list(struct cfg *cfg)
return true;
}
+bool
+do_pcount(struct cfg *cfg)
+{
+ unsigned x, y;
+
+ if (do_rcon_pcount(cfg, &y, &x))
+ error("Rcon says %u/%u", y, x);
+
+ if (do_mc_pcount(cfg, &y, &x))
+ error("MC says %u/%u", y, x);
+
+ return true;
+}
diff --git a/minecctl/misc-commands.h b/minecctl/misc-commands.h
index e0dc675..8270601 100644
--- a/minecctl/misc-commands.h
+++ b/minecctl/misc-commands.h
@@ -3,5 +3,7 @@
bool do_list(struct cfg *cfg);
+bool do_pcount(struct cfg *cfg);
+
#endif
diff --git a/minecctl/misc.c b/minecctl/misc.c
index bb33161..72eb03c 100644
--- a/minecctl/misc.c
+++ b/minecctl/misc.c
@@ -68,8 +68,13 @@ connect_any(struct list_head *addrs, bool may_fail)
bool connected = false;
int sfd;
- if (list_empty(addrs))
- die("No address to connect to");
+ /* FIXME: check callers and coordinate debug msg */
+ if (list_empty(addrs)) {
+ if (may_fail)
+ return -1;
+ else
+ die("No address to connect to");
+ }
list_for_each_entry(saddr, addrs, list) {
verbose("Attempting connection to %s", saddr->addrstr);
diff --git a/minecctl/rcon-commands.c b/minecctl/rcon-commands.c
index 02b970f..cf43c5e 100644
--- a/minecctl/rcon-commands.c
+++ b/minecctl/rcon-commands.c
@@ -387,23 +387,22 @@ do_stop_all(struct cfg *cfg) {
}
bool
-do_pcount(struct cfg *cfg) {
- int fd;
- unsigned current, max;
+do_rcon_pcount(struct cfg *cfg, unsigned *online, unsigned *max)
+{
struct server *server;
+ bool rv;
+ int fd;
server = server_get_default(cfg);
fd = rcon_login(cfg, server);
if (fd < 0)
return false;
- if (get_player_count(fd, &current, &max)) {
- info("Players: %u/%u", current, max);
- return true;
- } else {
- die("Failed to get player count");
- return false;
- }
+ rv = get_player_count(fd, online, max);
+
+ close(fd);
+
+ return rv;
}
bool
diff --git a/minecctl/rcon-commands.h b/minecctl/rcon-commands.h
index 5366bf9..1714dd5 100644
--- a/minecctl/rcon-commands.h
+++ b/minecctl/rcon-commands.h
@@ -9,7 +9,7 @@ bool do_stop(struct cfg *cfg);
bool do_stop_all(struct cfg *cfg);
-bool do_pcount(struct cfg *cfg);
+bool do_rcon_pcount(struct cfg *cfg, unsigned *online, unsigned *max);
bool do_console(struct cfg *cfg);