diff options
author | David Härdeman <david@hardeman.nu> | 2020-06-27 15:18:45 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2020-06-27 15:18:45 +0200 |
commit | 99b2c70137fef05a5a18f439b9010ddba455f5cb (patch) | |
tree | b0c08cfce14019cd634e6b4b84d0cf0f6e8eee6a /minecctl | |
parent | a87e894ba3f3a8915389f651fb034f0d1835630c (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.c | 77 | ||||
-rw-r--r-- | minecctl/mc-commands.h | 6 | ||||
-rw-r--r-- | minecctl/meson.build | 1 | ||||
-rw-r--r-- | minecctl/misc-commands.c | 15 | ||||
-rw-r--r-- | minecctl/misc-commands.h | 2 | ||||
-rw-r--r-- | minecctl/misc.c | 9 | ||||
-rw-r--r-- | minecctl/rcon-commands.c | 19 | ||||
-rw-r--r-- | minecctl/rcon-commands.h | 2 |
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, ¤t, &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); |