diff --git a/src/main.c b/src/main.c index 930fba8..fb49fe4 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include #include #include +#include const char *LOCALHOST = "127.0.0.1"; @@ -22,12 +23,10 @@ typedef struct { int read_env_int(const char *var) { const char* port_str = getenv(var); - if (port_str == NULL) { fprintf(stderr, "error: %s environment variable not set.\n", var); exit(EXIT_FAILURE); } - char* endptr; long val = strtol(port_str, &endptr, 10); if (endptr == port_str || *endptr != '\0') { @@ -52,13 +51,14 @@ int rcon_connect(int port) { if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("connection failed"); + close(sockfd); exit(EXIT_FAILURE); } + printf("connected to rcon server\n"); return sockfd; } - void send_packet(int sockfd, int32_t id, int32_t type, const char *body) { int body_len = strlen(body); int32_t size = 10 + body_len; // 4 (id) + 4 (type) + body + 2 (null terminators) @@ -76,7 +76,6 @@ int recv_packet(int sockfd, rcon_packet_t *packet) { if (recv(sockfd, &packet->id, sizeof(int32_t), 0) <= 0) { return -1; } if (recv(sockfd, &packet->type, sizeof(int32_t), 0) <= 0) { return -1; } - // read body (size - 10 bytes for id, type, and two null terminators) int body_size = packet->size - 10; if (body_size > 0 && body_size < sizeof(packet->body)) { if (recv(sockfd, packet->body, body_size + 2, 0) <= 0) { @@ -108,27 +107,28 @@ int rcon_authenticate(int sockfd, const char *password) { return 0; } -char* rcon_command(int sockfd, const char *command) { - static char result[8192]; +char* rcon_command_multipacket(int sockfd, const char *command) { + static char result[65536]; result[0] = '\0'; - send_packet(sockfd, 2, SERVERDATA_EXECCOMMAND, command); + int cmd_id = 100; + int dummy_id = 101; - // Handle multi-packet responses + send_packet(sockfd, cmd_id, SERVERDATA_EXECCOMMAND, command); + send_packet(sockfd, dummy_id, SERVERDATA_EXECCOMMAND, ""); + + // read packets until we get the dummy response while (1) { rcon_packet_t response; if (recv_packet(sockfd, &response) < 0) { perror("failed to receive command response\n"); return NULL; } - - if (response.type == SERVERDATA_RESPONSE_VALUE) { + if (response.id == dummy_id) { + break; + } + if (response.type == SERVERDATA_RESPONSE_VALUE && response.id == cmd_id) { strncat(result, response.body, sizeof(result) - strlen(result) - 1); - - // Check if response is complete (body length < 4096) - if (strlen(response.body) < 4096) { - break; - } } } @@ -153,10 +153,14 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - // example - char *response = rcon_command(sockfd, "help"); + const char *get_player_positions_cmd = "execute as @a run data get entity @s Pos"; + char *response = rcon_command_multipacket(sockfd, get_player_positions_cmd); + if (response) { - printf("Response:\n%s\n", response); + printf("\n=== player positions ===\n"); + printf("%s\n", response); + } else { + perror("failed to get player positions\n"); } close(sockfd);