send and receive packets
This commit is contained in:
40
src/main.c
40
src/main.c
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user