handle server list ping

This commit is contained in:
p2r3
2025-08-27 14:50:17 +03:00
parent 71737380d5
commit b46f5927a2
5 changed files with 56 additions and 5 deletions

View File

@@ -62,6 +62,9 @@ extern uint32_t rng_seed;
extern uint16_t world_time;
extern char motd[];
extern uint8_t motd_len;
extern uint16_t client_count;
#pragma pack(push, 1)

View File

@@ -23,6 +23,7 @@ int cs_playerInput (int client_fd);
int cs_playerCommand (int client_fd);
// Clientbound packets
int sc_statusResponse (int client_fd);
int sc_loginSuccess (int client_fd, uint8_t *uuid, char *name);
int sc_knownPacks (int client_fd);
int sc_finishConfiguration (int client_fd);

View File

@@ -31,6 +31,9 @@ uint32_t rng_seed = 0xE2B9419;
uint16_t world_time = 0;
char motd[] = { "A bareiron server" };
uint8_t motd_len = sizeof(motd) - 1;
uint16_t client_count;
BlockChange block_changes[20000];

View File

@@ -32,9 +32,8 @@
#include "registries.h"
#include "procedures.h"
void handlePacket (int client_fd, int length, int packet_id) {
void handlePacket (int client_fd, int length, int packet_id, int state) {
int state = getClientState(client_fd);
uint64_t bytes_received_start = total_bytes_received;
switch (packet_id) {
@@ -42,7 +41,9 @@ void handlePacket (int client_fd, int length, int packet_id) {
case 0x00:
if (state == STATE_NONE) {
if (cs_handshake(client_fd)) break;
} else if (state == STATE_LOGIN) {
} else if (state == STATE_STATUS) {
if (sc_statusResponse(client_fd)) break;
} if (state == STATE_LOGIN) {
uint8_t uuid[16];
char name[16];
if (cs_loginStart(client_fd, uuid, name)) break;
@@ -55,6 +56,19 @@ void handlePacket (int client_fd, int length, int packet_id) {
}
break;
case 0x01:
// Handle status ping
if (state == STATE_STATUS) {
// No need for a packet handler, just echo back the long verbatim
writeByte(client_fd, 9);
writeByte(client_fd, 0x01);
writeUint64(client_fd, readUint64(client_fd));
// Close connection after this
recv_count = 0;
return;
}
break;
case 0x02:
if (state == STATE_CONFIGURATION) cs_pluginMessage(client_fd);
break;
@@ -526,7 +540,7 @@ int main () {
int client_fd = clients[client_index];
// Check if at least 2 bytes are available for reading
ssize_t recv_count = recv(client_fd, &recv_buffer, 2, MSG_PEEK);
recv_count = recv(client_fd, &recv_buffer, 2, MSG_PEEK);
if (recv_count < 2) {
if (recv_count == 0 || (recv_count < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) {
disconnectClient(&clients[client_index], 1);
@@ -546,8 +560,15 @@ int main () {
disconnectClient(&clients[client_index], 3);
continue;
}
// Get client connection state
int state = getClientState(client_fd);
// Disconnect on legacy server list ping
if (state == STATE_NONE && length == 254 && packet_id == 122) {
disconnectClient(&clients[client_index], 5);
continue;
}
// Handle packet data
handlePacket(client_fd, length - sizeVarInt(packet_id), packet_id);
handlePacket(client_fd, length - sizeVarInt(packet_id), packet_id, state);
if (recv_count == 0 || (recv_count == -1 && errno != EAGAIN && errno != EWOULDBLOCK)) {
disconnectClient(&clients[client_index], 4);
continue;

View File

@@ -20,6 +20,28 @@
#include "procedures.h"
#include "packets.h"
// S->C Status Response (server list ping)
int sc_statusResponse (int client_fd) {
char header[] = "{"
"\"version\":{\"name\":\"1.21.8\",\"protocol\":772},"
"\"enforcesSecureChat\":false,"
"\"description\":{\"text\":\"";
char footer[] = "\"}}";
uint16_t string_len = sizeof(header) + sizeof(footer) + motd_len - 2;
writeVarInt(client_fd, 1 + string_len + sizeVarInt(string_len));
writeByte(client_fd, 0x00);
writeVarInt(client_fd, string_len);
send_all(client_fd, header, sizeof(header) - 1);
send_all(client_fd, motd, motd_len);
send_all(client_fd, footer, sizeof(footer) - 1);
return 0;
}
// C->S Handshake
int cs_handshake (int client_fd) {
printf("Received Handshake:\n");
@@ -1071,6 +1093,7 @@ int cs_playerInput (int client_fd) {
return 0;
}
// C->S Player Command
int cs_playerCommand (int client_fd) {
readVarInt(client_fd); // Ignore entity ID