init
This commit is contained in:
commit
1a6bc16935
|
@ -0,0 +1 @@
|
||||||
|
mcsrv
|
|
@ -0,0 +1,5 @@
|
||||||
|
all:
|
||||||
|
gcc -Wall -Wextra main.c -o mcsrv
|
||||||
|
|
||||||
|
run: all
|
||||||
|
./mcsrv
|
|
@ -0,0 +1,263 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define PORT 6969
|
||||||
|
#define BUFFER_SIZE 10240
|
||||||
|
|
||||||
|
#define SEGMENT_BITS 0x7F
|
||||||
|
#define CONTINUE_BIT 0x80
|
||||||
|
|
||||||
|
typedef uint8_t byte;
|
||||||
|
|
||||||
|
typedef struct MCString_view {
|
||||||
|
int len;
|
||||||
|
unsigned char* str;
|
||||||
|
} MCString_view;
|
||||||
|
|
||||||
|
typedef struct File {
|
||||||
|
int len;
|
||||||
|
char* data;
|
||||||
|
} File;
|
||||||
|
|
||||||
|
byte buffer[BUFFER_SIZE] = {0};
|
||||||
|
ssize_t bytes_received = 0;
|
||||||
|
int current_byte = 0;
|
||||||
|
|
||||||
|
byte request[BUFFER_SIZE] = {0};
|
||||||
|
int req_current_byte = 0;
|
||||||
|
|
||||||
|
void print_hex(const char *str, int len)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
printf("0x%02x, ", (unsigned int) str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_str(const char *str, int len)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
printf("%c,", (unsigned int) str[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_connection(int client_fd)
|
||||||
|
{
|
||||||
|
bytes_received = 0;
|
||||||
|
current_byte = 0;
|
||||||
|
req_current_byte = 0;
|
||||||
|
close(client_fd);
|
||||||
|
printf("[TCP] connection closed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte read_byte(int client_fd)
|
||||||
|
{
|
||||||
|
if (current_byte >= bytes_received) {
|
||||||
|
bytes_received = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
|
||||||
|
current_byte = 0;
|
||||||
|
|
||||||
|
if (bytes_received > 0) {
|
||||||
|
buffer[bytes_received] = '\0';
|
||||||
|
printf("[TCP] %ld bytes reçu :\n", bytes_received);
|
||||||
|
print_hex((const char*)buffer, bytes_received);
|
||||||
|
// print_str(buffer, bytes_received);
|
||||||
|
printf("\n[TCP] fin %ld bytes\n", bytes_received);
|
||||||
|
}
|
||||||
|
else if (bytes_received < 0) {
|
||||||
|
perror("[ERR] Erreur lors de la réception des données");
|
||||||
|
close_connection(client_fd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("[ERR] Le client s'est déconnecté.\n");
|
||||||
|
close_connection(client_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer[current_byte++];
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_VarInt(int client_fd)
|
||||||
|
{
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
for (int position = 0; position < 32; position += 7) {
|
||||||
|
|
||||||
|
uint8_t current_byte = read_byte(client_fd);
|
||||||
|
value |= (current_byte & SEGMENT_BITS) << position;
|
||||||
|
|
||||||
|
if ((current_byte & CONTINUE_BIT) == 0) break;
|
||||||
|
|
||||||
|
// if (position >= 32) throw new RuntimeException("VarInt is too big");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
MCString_view read_String_view(int client_fd)
|
||||||
|
{
|
||||||
|
MCString_view str = {
|
||||||
|
.len = read_VarInt(client_fd),
|
||||||
|
.str = &buffer[current_byte],
|
||||||
|
};
|
||||||
|
current_byte += str.len;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t read_UShort(int client_fd)
|
||||||
|
{
|
||||||
|
uint8_t var1 = read_byte(client_fd);
|
||||||
|
uint8_t var2 = read_byte(client_fd);
|
||||||
|
|
||||||
|
uint16_t var = (var1 << 8) + var2;
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_byte(int client_fd, int value)
|
||||||
|
{
|
||||||
|
(void) client_fd;
|
||||||
|
request[req_current_byte++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_VarInt(int client_fd, int value)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
if ((value & ~SEGMENT_BITS) == 0) {
|
||||||
|
write_byte(client_fd, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_byte(client_fd, (value & SEGMENT_BITS) | CONTINUE_BIT);
|
||||||
|
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_String(int client_fd, const char* str, int len)
|
||||||
|
{
|
||||||
|
(void) client_fd;
|
||||||
|
write_VarInt(client_fd, len);
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
request[req_current_byte++] = str[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_request(int client_fd)
|
||||||
|
{
|
||||||
|
write(client_fd, request, req_current_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
File read_entire_file(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "r");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long fsize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET); /* same as rewind(f); */
|
||||||
|
|
||||||
|
char *string = malloc(fsize);
|
||||||
|
fread(string, fsize, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return (File) {
|
||||||
|
.len = fsize,
|
||||||
|
.data = string,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_free(File file)
|
||||||
|
{
|
||||||
|
free(file.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int server_fd, client_fd;
|
||||||
|
struct sockaddr_in server_addr, client_addr;
|
||||||
|
socklen_t client_addr_len = sizeof(client_addr);
|
||||||
|
|
||||||
|
// Création de la socket
|
||||||
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||||
|
perror("Erreur lors de la création de la socket");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
int option = 1;
|
||||||
|
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
|
||||||
|
|
||||||
|
// Configuration de l'adresse du serveur
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_addr.s_addr = INADDR_ANY; // Accepter les connexions depuis n'importe quelle adresse IP
|
||||||
|
server_addr.sin_port = htons(PORT);
|
||||||
|
|
||||||
|
// Liaison de la socket à l'adresse et au port
|
||||||
|
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
|
||||||
|
perror("Erreur lors du bind");
|
||||||
|
close(server_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mise en écoute pour accepter des connexions
|
||||||
|
if (listen(server_fd, 5) == -1) { // 5 est le nombre maximum de connexions en file d'attente
|
||||||
|
perror("Erreur lors du listen");
|
||||||
|
close(server_fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[INFO] Serveur en écoute sur le port %d...\n", PORT);
|
||||||
|
|
||||||
|
// Boucle principale pour accepter et gérer les connexions clients
|
||||||
|
while (1) {
|
||||||
|
// Accepter une connexion cliente
|
||||||
|
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
|
||||||
|
if (client_fd == -1) {
|
||||||
|
perror("Erreur lors de l'acceptation de la connexion");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("[TCP] connection %s:%d\n",
|
||||||
|
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
||||||
|
|
||||||
|
int packet_length = read_VarInt(client_fd);
|
||||||
|
int packet_id = read_VarInt(client_fd);
|
||||||
|
printf("[MCPACKET %d] packet length: %d\n", packet_id, packet_length);
|
||||||
|
|
||||||
|
int protocol_version = read_VarInt(client_fd);
|
||||||
|
printf("[INFO] protocol version: %d\n", protocol_version);
|
||||||
|
|
||||||
|
// if (protocol_version != 760 /* mc 1.19.2 */) {
|
||||||
|
// printf("[ERR] protocol version %d non supporter, connection fermer\n", protocol_version);
|
||||||
|
// close_connection(client_fd);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
MCString_view address = read_String_view(client_fd);
|
||||||
|
uint16_t port = read_UShort(client_fd);
|
||||||
|
printf("[INFO] server address from client: %.*s:%hu\n", address.len, address.str, port);
|
||||||
|
|
||||||
|
int next_state = read_VarInt(client_fd);
|
||||||
|
printf("[INFO] next state: %d\n", next_state);
|
||||||
|
|
||||||
|
File status_rep = read_entire_file("status_response.json");
|
||||||
|
|
||||||
|
// TODO: get VarInt byte size from int, for /*str len*/
|
||||||
|
write_VarInt(client_fd, 1 /*packet id*/ + 2 /*str len*/ + status_rep.len); // packet length
|
||||||
|
write_VarInt(client_fd, packet_id);
|
||||||
|
write_String(client_fd, status_rep.data, status_rep.len);
|
||||||
|
|
||||||
|
send_request(client_fd);
|
||||||
|
printf("[INFO] %d byte request sent: ", req_current_byte);
|
||||||
|
print_hex((const char*) request, 10);
|
||||||
|
printf("...\n");
|
||||||
|
|
||||||
|
|
||||||
|
file_free(status_rep);
|
||||||
|
|
||||||
|
close_connection(client_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fermeture de la socket du serveur
|
||||||
|
close(server_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"version": {
|
||||||
|
"name": "1.19.2",
|
||||||
|
"protocol": 760
|
||||||
|
},
|
||||||
|
"players": {
|
||||||
|
"max": 100,
|
||||||
|
"online": 1,
|
||||||
|
"sample": [
|
||||||
|
{
|
||||||
|
"name": "caca player 69 ?",
|
||||||
|
"id": "83e2e372-1df3-485d-a360-d9c4caf8b8c4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"text": "caca serveur minecraft en \u00a72C"
|
||||||
|
},
|
||||||
|
"favicon": "data:image/png;base64,<data>",
|
||||||
|
"enforcesSecureChat": false
|
||||||
|
}
|
Loading…
Reference in New Issue