Split off rcon related code into separate source file
Also rename tests and rename some constants, and modify Makefile to handle the new structure.
This commit is contained in:
@@ -7,14 +7,16 @@ CFLAGS_DEBUG = -O0 -ggdb -DDEBUG -fsanitize=address -static-libasan
|
||||
|
||||
TEST_LIBS = -lcmocka
|
||||
TEST_INCLUDES = $(shell pkg-config --cflags cmocka)
|
||||
CFLAGS_TEST = -O0 -ggdb -DTEST -fsanitize=address -static-libasan -fprofile-instr-generate -fcoverage-mapping $(TEST_LIBS) $(TEST_INCLUDES)
|
||||
CFLAGS_TEST = -O0 -ggdb -DTEST -fsanitize=address -static-libasan -fprofile-instr-generate -fcoverage-mapping $(TEST_INCLUDES)
|
||||
LDFLAGS_TEST = $(TEST_LIBS)
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
|
||||
SOURCE_FOLDER = src
|
||||
SOURCE = main.c
|
||||
SOURCES = $(wildcard $(SOURCE_FOLDER)/*.c)
|
||||
APP_SOURCES = $(filter-out $(SOURCE_FOLDER)/main.c,$(SOURCES))
|
||||
TARGET = wamf
|
||||
TARGET_DEBUG = wamf-debug
|
||||
OUTPUT_FOLDER = output
|
||||
@@ -22,7 +24,7 @@ OUTPUT = $(OUTPUT_FOLDER)/$(TARGET)
|
||||
OUTPUT_DEBUG = $(OUTPUT_FOLDER)/$(TARGET_DEBUG)
|
||||
|
||||
TEST_FOLDER = test
|
||||
TEST_SOURCE = test.c
|
||||
TEST_SOURCES = $(wildcard $(TEST_FOLDER)/*.c)
|
||||
TEST_OUTPUT_FOLDER = $(OUTPUT_FOLDER)/test
|
||||
TEST_OUTPUT = $(TEST_OUTPUT_FOLDER)/test
|
||||
|
||||
@@ -36,19 +38,19 @@ REMOTE_PATH = $(REMOTE_USER)@$(REMOTE_HOST):$(REMOTE_DIR)
|
||||
all: $(OUTPUT)
|
||||
|
||||
$(OUTPUT_FOLDER):
|
||||
mkdir $(OUTPUT_FOLDER)
|
||||
mkdir -p $(OUTPUT_FOLDER)
|
||||
|
||||
$(TEST_OUTPUT_FOLDER): $(OUTPUT_FOLDER)
|
||||
mkdir $(TEST_OUTPUT_FOLDER)
|
||||
mkdir -p $(TEST_OUTPUT_FOLDER)
|
||||
|
||||
$(OUTPUT) release: $(SOURCE_FOLDER)/$(SOURCE) $(OUTPUT_FOLDER)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_WARNINGS) $(CFLAGS_RELEASE) -o $(OUTPUT) $(SOURCE_FOLDER)/$(SOURCE)
|
||||
$(OUTPUT) release: $(SOURCES) $(OUTPUT_FOLDER)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_WARNINGS) $(CFLAGS_RELEASE) -o $(OUTPUT) $(SOURCES)
|
||||
|
||||
$(OUTPUT_DEBUG) debug: $(SOURCE_FOLDER)/$(SOURCE) $(OUTPUT_FOLDER)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_WARNINGS) $(CFLAGS_DEBUG) -o $(OUTPUT_DEBUG) $(SOURCE_FOLDER)/$(SOURCE)
|
||||
$(OUTPUT_DEBUG) debug: $(SOURCES) $(OUTPUT_FOLDER)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_WARNINGS) $(CFLAGS_DEBUG) -o $(OUTPUT_DEBUG) $(SOURCES)
|
||||
|
||||
$(TEST_OUTPUT): $(TEST_FOLDER)/$(TEST_SOURCE) $(TEST_OUTPUT_FOLDER)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_WARNINGS) $(CFLAGS_TEST) -o $(TEST_OUTPUT) $(TEST_FOLDER)/$(TEST_SOURCE)
|
||||
$(TEST_OUTPUT): $(APP_SOURCES) $(TEST_SOURCES) $(TEST_OUTPUT_FOLDER)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_WARNINGS) $(CFLAGS_TEST) -o $(TEST_OUTPUT) $(APP_SOURCES) $(TEST_SOURCES) $(LDFLAGS_TEST)
|
||||
|
||||
install: $(OUTPUT)
|
||||
install -Dm755 $(OUTPUT) -t $(bindir)
|
||||
@@ -60,7 +62,7 @@ deploy:
|
||||
@echo "Creating remote directory..."
|
||||
ssh $(REMOTE_USER)@$(REMOTE_HOST) "mkdir -p $(REMOTE_DIR)"
|
||||
@echo "Copying source files to $(REMOTE_HOST)..."
|
||||
scp $(SOURCE_FOLDER)/$(SOURCE) $(REMOTE_PATH)/$(SOURCE_FOLDER)
|
||||
scp $(SOURCE_FOLDER)/* $(REMOTE_PATH)/$(SOURCE_FOLDER)
|
||||
scp Makefile $(REMOTE_PATH)
|
||||
@echo "Files deployed successfully"
|
||||
|
||||
|
||||
+3
-213
@@ -1,39 +1,11 @@
|
||||
#include <endian.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "rcon.h"
|
||||
|
||||
const char *LOCALHOST = "127.0.0.1";
|
||||
|
||||
#define SERVERDATA_AUTH 3
|
||||
#define SERVERDATA_AUTH_RESPONSE 2
|
||||
#define SERVERDATA_EXECCOMMAND 2
|
||||
#define SERVERDATA_RESPONSE_VALUE 0
|
||||
|
||||
typedef struct {
|
||||
// size of the remainder of the packet
|
||||
int32_t size;
|
||||
// packet id (client sets, server echoes, -1 on auth failure)
|
||||
int32_t id;
|
||||
// packet type (see the SERVERDATA_* constants)
|
||||
int32_t type;
|
||||
// null-terminated command string (for auth and exec) or response string (from server)
|
||||
char body[4096];
|
||||
// yet another null byte after the body (required by protocol)
|
||||
uint8_t _padding;
|
||||
} rcon_packet_t;
|
||||
|
||||
// Minimum and maximum values for the `size` field of a valid packet.
|
||||
#define MIN_SIZE (sizeof(int32_t) * 2 + 2)
|
||||
#define MAX_SIZE (sizeof(rcon_packet_t) - sizeof(int32_t))
|
||||
|
||||
int read_env_int(const char *var) {
|
||||
const char* port_str = getenv(var);
|
||||
if (port_str == NULL) {
|
||||
@@ -49,188 +21,6 @@ int read_env_int(const char *var) {
|
||||
return (int)val;
|
||||
}
|
||||
|
||||
int rcon_connect(int port) {
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
perror("socket creation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(port);
|
||||
|
||||
if (inet_pton(AF_INET, LOCALHOST, &server_addr.sin_addr) <= 0) {
|
||||
perror("invalid address");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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) {
|
||||
size_t body_len = strlen(body);
|
||||
|
||||
size_t packet_size = sizeof(int32_t) * 3 + body_len + 2;
|
||||
unsigned char *packet = malloc(packet_size);
|
||||
if (!packet) {
|
||||
perror("malloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t size = htole32(packet_size - sizeof(int32_t));
|
||||
memcpy(packet, &size, sizeof(int32_t));
|
||||
|
||||
int32_t id_ = htole32(id);
|
||||
memcpy(packet + 4, &id_, sizeof(int32_t));
|
||||
|
||||
int32_t type_ = htole32(type);
|
||||
memcpy(packet + 8, &type_, sizeof(int32_t));
|
||||
|
||||
memcpy(packet + 12, body, body_len);
|
||||
packet[3 * sizeof(int32_t) + body_len] = 0;
|
||||
packet[3 * sizeof(int32_t) + body_len + 1] = 0;
|
||||
|
||||
ssize_t sent = send(sockfd, packet, packet_size, 0);
|
||||
if (sent < 0) {
|
||||
perror("send failed");
|
||||
}
|
||||
|
||||
free(packet);
|
||||
}
|
||||
|
||||
int recv_packet(int sockfd, rcon_packet_t *packet) {
|
||||
ssize_t bytes;
|
||||
|
||||
bytes = recv(sockfd, &packet->size, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
if (bytes == 0) {
|
||||
fprintf(stderr, "connection closed by server\n");
|
||||
} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return -2; // Timeout
|
||||
} else {
|
||||
perror("recv size failed");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
packet->size = le32toh(packet->size);
|
||||
|
||||
if (packet->size < (int32_t)MIN_SIZE || packet->size > (int32_t)MAX_SIZE) {
|
||||
fprintf(stderr, "invalid packet size: %d\n", packet->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = recv(sockfd, &packet->id, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv id failed");
|
||||
return -1;
|
||||
}
|
||||
packet->id = le32toh(packet->id);
|
||||
|
||||
bytes = recv(sockfd, &packet->type, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv type failed");
|
||||
return -1;
|
||||
}
|
||||
packet->type = le32toh(packet->type);
|
||||
|
||||
int body_size = packet->size - sizeof(int32_t) * 2 - 2;
|
||||
if (body_size > 0 && body_size < (int)sizeof(packet->body)) {
|
||||
bytes = recv(sockfd, packet->body, body_size, MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv body failed");
|
||||
return -1;
|
||||
}
|
||||
packet->body[body_size] = '\0';
|
||||
|
||||
bytes = recv(sockfd, &packet->_padding, 1, MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv padding failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
packet->size = sizeof(int32_t) * 2 + 2;
|
||||
packet->body[0] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rcon_authenticate(int sockfd, const char *password) {
|
||||
printf("authenticating with password: '%s'\n", password);
|
||||
|
||||
send_packet(sockfd, 1, SERVERDATA_AUTH, password);
|
||||
|
||||
printf("waiting for auth response...\n");
|
||||
|
||||
rcon_packet_t response;
|
||||
if (recv_packet(sockfd, &response) < 0) {
|
||||
fprintf(stderr, "failed to receive auth response\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("received auth packet: id=%d, type=%d\n", response.id, response.type);
|
||||
|
||||
// Check if authentication failed (id == -1)
|
||||
if (response.id == -1) {
|
||||
fprintf(stderr, "authentication failed - invalid password\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Try to read second packet (may timeout, which is OK)
|
||||
rcon_packet_t response2;
|
||||
int result = recv_packet(sockfd, &response2);
|
||||
if (result == 0) {
|
||||
printf("received second auth packet: id=%d, type=%d\n", response2.id, response2.type);
|
||||
} else if (result == -2) {
|
||||
printf("no second packet (timeout - this is normal)\n");
|
||||
}
|
||||
|
||||
printf("authenticated successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* rcon_command_multipacket(int sockfd, const char *command) {
|
||||
static char result[65536];
|
||||
result[0] = '\0';
|
||||
|
||||
int cmd_id = 100;
|
||||
int dummy_id = 101;
|
||||
|
||||
send_packet(sockfd, cmd_id, SERVERDATA_EXECCOMMAND, command);
|
||||
send_packet(sockfd, dummy_id, SERVERDATA_EXECCOMMAND, "");
|
||||
|
||||
while (1) {
|
||||
rcon_packet_t response;
|
||||
if (recv_packet(sockfd, &response) < 0) {
|
||||
fprintf(stderr, "failed to receive command response\n");
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const int PORT_NUM = read_env_int("RCON_PORT_NUMBER");
|
||||
const char *password = getenv("RCON_PASSWORD");
|
||||
@@ -245,7 +35,7 @@ int main(void) {
|
||||
printf("password: '%s'\n", password);
|
||||
printf("==========================\n\n");
|
||||
|
||||
int sockfd = rcon_connect(PORT_NUM);
|
||||
int sockfd = rcon_connect(LOCALHOST, PORT_NUM);
|
||||
|
||||
if (rcon_authenticate(sockfd, password) < 0) {
|
||||
close(sockfd);
|
||||
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "rcon.h"
|
||||
|
||||
int rcon_connect(const char* address, int port) {
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
perror("socket creation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(port);
|
||||
|
||||
if (inet_pton(AF_INET, address, &server_addr.sin_addr) <= 0) {
|
||||
perror("invalid address");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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) {
|
||||
size_t body_len = strlen(body);
|
||||
|
||||
size_t packet_size = sizeof(int32_t) * 3 + body_len + 2;
|
||||
unsigned char *packet = malloc(packet_size);
|
||||
if (!packet) {
|
||||
perror("malloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t size = htole32(packet_size - sizeof(int32_t));
|
||||
memcpy(packet, &size, sizeof(int32_t));
|
||||
|
||||
int32_t id_ = htole32(id);
|
||||
memcpy(packet + 4, &id_, sizeof(int32_t));
|
||||
|
||||
int32_t type_ = htole32(type);
|
||||
memcpy(packet + 8, &type_, sizeof(int32_t));
|
||||
|
||||
memcpy(packet + 12, body, body_len);
|
||||
packet[3 * sizeof(int32_t) + body_len] = 0;
|
||||
packet[3 * sizeof(int32_t) + body_len + 1] = 0;
|
||||
|
||||
ssize_t sent = send(sockfd, packet, packet_size, 0);
|
||||
if (sent < 0) {
|
||||
perror("send failed");
|
||||
}
|
||||
|
||||
free(packet);
|
||||
}
|
||||
|
||||
int recv_packet(int sockfd, rcon_packet_t *packet) {
|
||||
ssize_t bytes;
|
||||
|
||||
bytes = recv(sockfd, &packet->size, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
if (bytes == 0) {
|
||||
fprintf(stderr, "connection closed by server\n");
|
||||
} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return -2; // Timeout
|
||||
} else {
|
||||
perror("recv size failed");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
packet->size = le32toh(packet->size);
|
||||
|
||||
if (packet->size < (int32_t)RCON_PACKET_MIN_SIZE || packet->size > (int32_t)RCON_PACKET_MAX_SIZE) {
|
||||
fprintf(stderr, "invalid packet size: %d\n", packet->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = recv(sockfd, &packet->id, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv id failed");
|
||||
return -1;
|
||||
}
|
||||
packet->id = le32toh(packet->id);
|
||||
|
||||
bytes = recv(sockfd, &packet->type, sizeof(int32_t), MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv type failed");
|
||||
return -1;
|
||||
}
|
||||
packet->type = le32toh(packet->type);
|
||||
|
||||
int body_size = packet->size - sizeof(int32_t) * 2 - 2;
|
||||
if (body_size > 0 && body_size < (int)sizeof(packet->body)) {
|
||||
bytes = recv(sockfd, packet->body, body_size, MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv body failed");
|
||||
return -1;
|
||||
}
|
||||
packet->body[body_size] = '\0';
|
||||
|
||||
bytes = recv(sockfd, &packet->_padding, 1, MSG_WAITALL);
|
||||
if (bytes <= 0) {
|
||||
perror("recv padding failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
packet->size = sizeof(int32_t) * 2 + 2;
|
||||
packet->body[0] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rcon_authenticate(int sockfd, const char *password) {
|
||||
printf("authenticating with password: '%s'\n", password);
|
||||
|
||||
send_packet(sockfd, 1, RCON_SERVERDATA_AUTH, password);
|
||||
|
||||
printf("waiting for auth response...\n");
|
||||
|
||||
rcon_packet_t response;
|
||||
if (recv_packet(sockfd, &response) < 0) {
|
||||
fprintf(stderr, "failed to receive auth response\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("received auth packet: id=%d, type=%d\n", response.id, response.type);
|
||||
|
||||
// Check if authentication failed (id == -1)
|
||||
if (response.id == -1) {
|
||||
fprintf(stderr, "authentication failed - invalid password\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Try to read second packet (may timeout, which is OK)
|
||||
rcon_packet_t response2;
|
||||
int result = recv_packet(sockfd, &response2);
|
||||
if (result == 0) {
|
||||
printf("received second auth packet: id=%d, type=%d\n", response2.id, response2.type);
|
||||
} else if (result == -2) {
|
||||
printf("no second packet (timeout - this is normal)\n");
|
||||
}
|
||||
|
||||
printf("authenticated successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* rcon_command_multipacket(int sockfd, const char *command) {
|
||||
static char result[65536];
|
||||
result[0] = '\0';
|
||||
|
||||
int cmd_id = 100;
|
||||
int dummy_id = 101;
|
||||
|
||||
send_packet(sockfd, cmd_id, RCON_SERVERDATA_EXECCOMMAND, command);
|
||||
send_packet(sockfd, dummy_id, RCON_SERVERDATA_EXECCOMMAND, "");
|
||||
|
||||
while (1) {
|
||||
rcon_packet_t response;
|
||||
if (recv_packet(sockfd, &response) < 0) {
|
||||
fprintf(stderr, "failed to receive command response\n");
|
||||
return NULL;
|
||||
}
|
||||
if (response.id == dummy_id) {
|
||||
break;
|
||||
}
|
||||
if (response.type == RCON_SERVERDATA_RESPONSE_VALUE && response.id == cmd_id) {
|
||||
strncat(result, response.body, sizeof(result) - strlen(result) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define RCON_SERVERDATA_AUTH 3
|
||||
#define RCON_SERVERDATA_AUTH_RESPONSE 2
|
||||
#define RCON_SERVERDATA_EXECCOMMAND 2
|
||||
#define RCON_SERVERDATA_RESPONSE_VALUE 0
|
||||
|
||||
typedef struct {
|
||||
// size of the remainder of the packet
|
||||
int32_t size;
|
||||
// packet id (client sets, server echoes, -1 on auth failure)
|
||||
int32_t id;
|
||||
// packet type (see the SERVERDATA_* constants)
|
||||
int32_t type;
|
||||
// null-terminated command string (for auth and exec) or response string (from server)
|
||||
char body[4096];
|
||||
// yet another null byte after the body (required by protocol)
|
||||
uint8_t _padding;
|
||||
} rcon_packet_t;
|
||||
|
||||
// Minimum and maximum values for the `size` field of a valid packet.
|
||||
#define RCON_PACKET_MIN_SIZE (sizeof(int32_t) * 2 + 2)
|
||||
#define RCON_PACKET_MAX_SIZE (sizeof(rcon_packet_t) - sizeof(int32_t))
|
||||
|
||||
int rcon_connect(const char* address, int port);
|
||||
|
||||
void send_packet(int sockfd, int32_t id, int32_t type, const char *body);
|
||||
|
||||
int recv_packet(int sockfd, rcon_packet_t *packet);
|
||||
|
||||
int rcon_authenticate(int sockfd, const char *password);
|
||||
|
||||
char* rcon_command_multipacket(int sockfd, const char *command);
|
||||
@@ -1,19 +1,9 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmocka.h>
|
||||
|
||||
#define main wamf_main
|
||||
#include "../src/main.c"
|
||||
#undef main
|
||||
#include "../src/rcon.h"
|
||||
|
||||
static void assert_packet_equals(const rcon_packet_t *packet,
|
||||
int32_t expected_id, int32_t expected_type,
|
||||
@@ -33,7 +23,7 @@ static void test_serialization_roundtrip_command_packet(void **state) {
|
||||
assert_int_equal(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
|
||||
const int32_t id = 123;
|
||||
const int32_t type = SERVERDATA_EXECCOMMAND;
|
||||
const int32_t type = RCON_SERVERDATA_EXECCOMMAND;
|
||||
const char *body = "execute as @a run data get entity @s Pos";
|
||||
|
||||
send_packet(sv[0], id, type, body);
|
||||
@@ -53,7 +43,7 @@ static void test_serialization_roundtrip_auth_packet(void **state) {
|
||||
assert_int_equal(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
|
||||
const int32_t id = 1;
|
||||
const int32_t type = SERVERDATA_AUTH;
|
||||
const int32_t type = RCON_SERVERDATA_AUTH;
|
||||
const char *body = "correct horse battery staple";
|
||||
|
||||
send_packet(sv[0], id, type, body);
|
||||
@@ -73,7 +63,7 @@ static void test_serialization_roundtrip_empty_body_packet(void **state) {
|
||||
assert_int_equal(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
|
||||
const int32_t id = 101;
|
||||
const int32_t type = SERVERDATA_EXECCOMMAND;
|
||||
const int32_t type = RCON_SERVERDATA_EXECCOMMAND;
|
||||
const char *body = "";
|
||||
|
||||
send_packet(sv[0], id, type, body);
|
||||
@@ -96,11 +86,11 @@ static void test_serialization_roundtrip_max_supported_body(void **state) {
|
||||
memset(body, 'A', sizeof(body) - 1);
|
||||
body[sizeof(body) - 1] = '\0';
|
||||
|
||||
send_packet(sv[0], 777, SERVERDATA_RESPONSE_VALUE, body);
|
||||
send_packet(sv[0], 777, RCON_SERVERDATA_RESPONSE_VALUE, body);
|
||||
|
||||
rcon_packet_t packet = {0};
|
||||
assert_int_equal(recv_packet(sv[1], &packet), 0);
|
||||
assert_packet_equals(&packet, 777, SERVERDATA_RESPONSE_VALUE, body);
|
||||
assert_packet_equals(&packet, 777, RCON_SERVERDATA_RESPONSE_VALUE, body);
|
||||
|
||||
close(sv[0]);
|
||||
close(sv[1]);
|
||||
Reference in New Issue
Block a user