send and receive packets

This commit is contained in:
2026-02-07 22:35:41 +01:00
parent 4e0036e5f9
commit 39a943e4cc

View File

@@ -5,6 +5,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdint.h>
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);