diff --git a/include/globals.h b/include/globals.h index efc8f6f..69a951b 100644 --- a/include/globals.h +++ b/include/globals.h @@ -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) diff --git a/include/packets.h b/include/packets.h index 0a3eebf..d9882f4 100644 --- a/include/packets.h +++ b/include/packets.h @@ -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); diff --git a/src/globals.c b/src/globals.c index 583d74a..e1ca985 100644 --- a/src/globals.c +++ b/src/globals.c @@ -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]; diff --git a/src/main.c b/src/main.c index 3c881e0..1510577 100644 --- a/src/main.c +++ b/src/main.c @@ -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; diff --git a/src/packets.c b/src/packets.c index 57f85b6..95dfa4b 100644 --- a/src/packets.c +++ b/src/packets.c @@ -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