diff --git a/PlayerTracker b/PlayerTracker index 43c2e04..5e98092 100755 Binary files a/PlayerTracker and b/PlayerTracker differ diff --git a/include/parcer.c b/include/parcer.c new file mode 100644 index 0000000..41f3f33 --- /dev/null +++ b/include/parcer.c @@ -0,0 +1,125 @@ +#include "parcer.h" +#include + +int ensure(size_t recv_len, size_t offset, size_t need) { + return (offset + need <= recv_len); +} + +u_int8_t read_uint8(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok) { + if (!ensure(recv_len, *offset, sizeof(uint8_t))) { + *ok = 0; + return 0; + } + u_int8_t v; + memcpy(&v, buf + *offset, sizeof(v)); + *offset += sizeof(v); + return v; +} + +u_int16_t read_uint16(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok) { + if (!ensure(recv_len, *offset, sizeof(uint16_t))) { + *ok = 0; + return 0; + } + u_int16_t v; + memcpy(&v, buf + *offset, sizeof(v)); + *offset += sizeof(v); + return (u_int16_t)ntohs(v); +} + +u_int32_t read_uint32(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok) { + if (!ensure(recv_len, *offset, sizeof(uint32_t))) { + *ok = 0; + return 0; + } + u_int32_t v; + memcpy(&v, buf + *offset, sizeof(v)); + *offset += sizeof(v); + return (u_int32_t)ntohl(v); +} + +int32_t read_int32(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok) { + if (!ensure(recv_len, *offset, sizeof(int32_t))) { + *ok = 0; + return 0; + } + int32_t v; + memcpy(&v, buf + *offset, sizeof(v)); + *offset += sizeof(v); + return (int32_t)ntohl(v); +} + +void read_bytes(const u_int8_t *buf, size_t recv_len, size_t *offset, u_int8_t *out, size_t len, int *ok) { + if (!ensure(recv_len, *offset, len)) { + *ok = 0; + return; + } + memcpy(out, buf + *offset, len); + *offset += len; +} + +void read_utf32le_string(const uint8_t *buffer, size_t buf_size, size_t *offset, char *dest, size_t max_len, int *ok) { + size_t i = *offset; + size_t j = 0; + + while (i + 3 < buf_size && j < max_len) { + uint32_t codeunit = buffer[i] | (buffer[i + 1] << 8) | (buffer[i + 2] << 16) | (buffer[i + 3] << 24); + + if (codeunit == 0) { + i += 4; // termina a string + break; + } + + if (codeunit < 0x80) { + dest[j++] = (char)codeunit; + } else { + dest[j++] = '?'; // substitui caracteres fora de ASCII + } + + i += 4; + } + + dest[j] = '\0'; + *offset = i; + *ok = 1; +} + +void read_utf16le_string(const uint8_t *buffer, size_t buf_size, size_t *offset, char *dest, size_t max_len, int *ok) { + size_t i = *offset; + size_t j = 0; + + while (i + 1 < buf_size && j < max_len - 1) { + uint16_t codeunit = buffer[i] | (buffer[i + 1] << 8); + + if (codeunit == 0) { + i += 2; // termina a string + break; + } + + if (codeunit < 0x80) { + dest[j++] = (char)codeunit; + } else { + dest[j++] = '?'; // substitui caracteres fora de ASCII + } + + i += 2; + } + + dest[j] = '\0'; + *offset = i; + *ok = 1; +} + +void read_string(const u_int8_t *buf, size_t recv_len, size_t *offset, char *out, size_t len, int *ok) { + if (!ensure(recv_len, *offset, len)) { + *ok = 0; + return; + } + + for (size_t i = 0; i <= len; i++) { + out[i] = (char)buf[*offset + i]; + } + out[len] = '\0'; // Ensure null termination + *offset += len; + *ok = 1; +} diff --git a/include/parcer.h b/include/parcer.h new file mode 100644 index 0000000..c8fa4d2 --- /dev/null +++ b/include/parcer.h @@ -0,0 +1,56 @@ +#ifndef PARCER_H +#define PARCER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +// Ensures that there are at least 'need' bytes available in the buffer +// starting from 'offset'. Returns 1 if enough bytes are available, 0 otherwise. +int ensure(size_t recv_len, size_t offset, size_t need); + +// Reads an 8-bit unsigned integer from the buffer. +// Advances the offset by 1 byte. +u_int8_t read_uint8(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok); + +// Reads a 16-bit unsigned integer from the buffer in network byte order. +// Advances the offset by 2 bytes. +u_int16_t read_uint16(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok); + +// Reads a 32-bit unsigned integer from the buffer in network byte order. +// Advances the offset by 4 bytes. +u_int32_t read_uint32(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok); + +// Reads a 32-bit signed integer from the buffer in network byte order. +// Advances the offset by 4 bytes. +int32_t read_int32(const u_int8_t *buf, size_t recv_len, size_t *offset, int *ok); + +// Reads a fixed number of bytes into the output buffer. +// The output buffer must be at least 'len' bytes long. +void read_bytes(const u_int8_t *buf, size_t recv_len, size_t *offset, u_int8_t *out, size_t len, int *ok); + +// Reads a length-prefixed string. The length is a single byte. +// The string is not null-terminated in the buffer, but the function +void read_utf32le_string(const uint8_t *buffer, size_t buf_size, size_t *offset, char *dest, size_t max_len, int *ok); + +// reads up to max_len - 1 characters and null-terminates the destination buffer. +// The string is encoded in UTF-32LE. +void read_utf16le_string(const uint8_t *buffer, size_t buf_size, size_t *offset, char *dest, size_t max_len, int *ok); + +// Reads a null-terminated string from the buffer. +// The string is read into the output buffer, which must be at least max_len bytes long +void read_string(const u_int8_t *buf, size_t recv_len, size_t *offset, char *out, size_t max_len, int *ok); + +#ifdef __cplusplus +} +#endif + +#endif // PARCER_H diff --git a/include/server_structs.h b/include/server_structs.h index 101780a..e766687 100644 --- a/include/server_structs.h +++ b/include/server_structs.h @@ -1,7 +1,10 @@ #ifndef SERVER_STRUCTS_H #define SERVER_STRUCTS_H +#include #include +#include +#include struct handshake { // [not used in the current Remote Telemtry version by AC] // In future versions it will identify the platform type of the client. @@ -50,4 +53,102 @@ struct handshackerResponse{ char trackConfig[50]; } __attribute__((packed)); +struct postion { + float x; + float y; + float z; +} __attribute__((packed)); + +struct carAtributes { + // Related to ACSP_CAR_INFO + u_char isConnected; // 1 = connected, 0 = disconnected + char *carModel; + char *carSkin; + char *driver_name; + char *driver_team; + char *driver_GUID; + + // Related to ACSP_CAR_UPDATE + u_int8_t carID; + postion position; + postion velocity; + u_int8_t carGear; + u_int16_t carRPM; + float_t normalizedSplinePos; + +} __attribute__((packed)); + + +struct trackAtributes { + u_int8_t protocol_version; + u_int8_t session_index; + u_int8_t current_session_index; + u_int8_t session_count; + + char *server_name; + char *track; + char *track_config; + char *session_name; + + u_int8_t typ; + u_int16_t time; + u_int16_t laps; + u_int16_t wait_time; + u_int8_t ambient_temp; + u_int8_t road_temp; + + char *weather_graphics; + int32_t elapsed_ms; +} __attribute__((packed)); + + +enum ACSP_MessageType { + // ============================ + // PROTOCOL VERSION + // ============================ + PROTOCOL_VERSION = 4, + + // ============================ + // SERVER → CLIENT MESSAGES + // ============================ + ACSP_NEW_SESSION = 50, + ACSP_NEW_CONNECTION = 51, + ACSP_CONNECTION_CLOSED = 52, + ACSP_CAR_UPDATE = 53, + ACSP_CAR_INFO = 54, // Response to ACSP_GET_CAR_INFO + ACSP_END_SESSION = 55, + ACSP_VERSION = 56, + ACSP_CHAT = 57, + ACSP_CLIENT_LOADED = 58, + ACSP_SESSION_INFO = 59, + ACSP_ERROR = 60, + ACSP_LAP_COMPLETED = 73, + + // ============================ + // EVENTS + // ============================ + ACSP_CLIENT_EVENT = 130, + + // ============================ + // EVENT TYPES + // ============================ + ACSP_CE_COLLISION_WITH_CAR = 10, + ACSP_CE_COLLISION_WITH_ENV = 11, + + // ============================ + // CLIENT → SERVER COMMANDS + // ============================ + ACSP_REALTIMEPOS_INTERVAL = 200, + ACSP_GET_CAR_INFO = 201, + ACSP_SEND_CHAT = 202, // Sends chat to one car + ACSP_BROADCAST_CHAT = 203, // Sends chat to everybody + ACSP_GET_SESSION_INFO = 204, + ACSP_SET_SESSION_INFO = 205, + ACSP_KICK_USER = 206, + ACSP_NEXT_SESSION = 207, + ACSP_RESTART_SESSION = 208, + ACSP_ADMIN_COMMAND = 209 // Send message plus a string +}; + + #endif // SERVER_STRUCTS_H diff --git a/include/socket.c b/include/socket.c index ff14f1a..baed2dc 100644 --- a/include/socket.c +++ b/include/socket.c @@ -3,62 +3,88 @@ // ========================= // UDP SOCKET FUCNTIONS // ========================= -// @param ip: IP address to connect to -// @param port: Port number to connect to + +// Create a UDP socket // @return: Socket file descriptor, or -1 on error -int connect_udp_socket(const char* ip, uint16_t port) { - int sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) { - perror("socket creation failed"); - return -1; - } - - struct sockaddr_in servaddr; - memset(&servaddr, 0, sizeof(servaddr)); - - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(port); - servaddr.sin_addr.s_addr = inet_addr(ip); - - if (connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { - perror("connection to the server failed"); - close(sockfd); - return -1; - } - - return sockfd; +int create_udp_socket(void) { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("[!] socket() failed"); + return -1; + } + return sockfd; } -int bind_udp_socket(int sockfd, const char* ip, uint16_t port) { - struct sockaddr_in servaddr; - memset(&servaddr, 0, sizeof(servaddr)); +// Create a UDP socket and connect it to a specific IP and port +// Used for sending data (no bind needed) +// @param ip: Destination IP address as a string +// @return: Socket file descriptor, or -1 on error +int connect_udp_socket(const char *ip, uint16_t port) { + int sockfd = create_udp_socket(); + if (sockfd < 0) + return -1; - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = inet_addr(ip); - servaddr.sin_port = htons(port); + struct sockaddr_in servaddr; + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + servaddr.sin_addr.s_addr = inet_addr(ip); - if (bind(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { - perror("bind failed"); - close(sockfd); - return -1; - } + if (connect(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { + perror("[!] connect() failed"); + close(sockfd); + return -1; + } - return 0; + printf("[+] Connected UDP socket to %s:%d\n", ip, port); + return sockfd; } +// Create and bind a UDP socket to a local IP and port +// Used for listening for incoming data +// @param ip: Local IP address to bind to +// @param port: Local port to bind to +// @return: Socket file descriptor, or -1 on error +int create_bound_udp_socket(const char *ip, uint16_t port) { + int sockfd = create_udp_socket(); + if (sockfd < 0) + return -1; + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(ip); + + if (bind(sockfd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("[!] bind() failed"); + close(sockfd); + return -1; + } + + printf("[+] Bound UDP socket on %s:%d\n", ip, port); + return sockfd; +} + +// Send a UDP message to the specified IP and port +// @param sockfd: Socket file descriptor +// @param message: Message to send +// @param dest_ip: Destination IP address as a string +// @param dest_port: Destination port +// @return: Number of bytes sent, or -1 on error ssize_t send_udp_message(int sockfd, const char *message, const char *dest_ip, uint16_t dest_port) { - struct sockaddr_in destaddr; - memset(&destaddr, 0, sizeof(destaddr)); + struct sockaddr_in destaddr; + memset(&destaddr, 0, sizeof(destaddr)); + destaddr.sin_family = AF_INET; + destaddr.sin_port = htons(dest_port); + destaddr.sin_addr.s_addr = inet_addr(dest_ip); - destaddr.sin_family = AF_INET; - destaddr.sin_port = htons(dest_port); - destaddr.sin_addr.s_addr = inet_addr(dest_ip); + ssize_t n = sendto(sockfd, message, strlen(message), 0, (const struct sockaddr *)&destaddr, sizeof(destaddr)); + if (n < 0) { + perror("[!] sendto() failed"); + return -1; + } - ssize_t n = sendto(sockfd, message, strlen(message), 0, (const struct sockaddr*)&destaddr, sizeof(destaddr)); - if (n < 0) { - perror("sendto failed"); - return -1; - } - - return n; + printf("[+] Sent %zd bytes to %s:%d\n", n, dest_ip, dest_port); + return n; } diff --git a/include/socket.h b/include/socket.h index 339feca..499bb2b 100644 --- a/include/socket.h +++ b/include/socket.h @@ -10,12 +10,15 @@ extern "C" { #include #pragma comment(lib, "ws2_32.lib") // link Winsock #else -#include -#include -#include #include -#include +#include +#include +#include +#include #include +#include +#include +#include #endif // ========================= @@ -24,12 +27,13 @@ extern "C" { // Server hosts a UDP socket at 127.0.0.1:12000 // Client sends a message to the server at 11000 +// UDP socket creation & management +int create_udp_socket(void); int connect_udp_socket(const char *ip, uint16_t port); +int create_bound_udp_socket(const char *ip, uint16_t port); -int bind_udp_socket(int sockfd, const char *ip, uint16_t port); - -ssize_t send_udp_message(int sockfd, const char *message, const char *dest_ip, - uint16_t dest_port); +// UDP messaging +ssize_t send_udp_message(int sockfd, const char *message, const char *dest_ip, uint16_t dest_port); #ifdef __cplusplus } diff --git a/source/main.cpp b/source/main.cpp index 52abda1..cf538ca 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,6 +1,5 @@ -#include -#include -#include +#include +#include #include #include #include @@ -8,6 +7,7 @@ #include #include +#include "parcer.h" #include "server_structs.h" #include "socket.h" @@ -18,54 +18,252 @@ const char *SERVER_OUT_IP = "127.0.0.1"; int main(void) { printf("[+] Starting server...\n"); - // Printf information about the server printf("[+] Server listening on port %d\n", SERVER_IN_PORT); - printf("[+] Server sending to %s:%d\n", SERVER_OUT_IP, SERVER_OUT_PORT); + printf("[+] Server sending to %s:%d\n\n", SERVER_OUT_IP, SERVER_OUT_PORT); - // Create UDP socket - int sock_FD = connect_udp_socket(SERVER_OUT_IP, SERVER_OUT_PORT); - if (sock_FD < 0) { - fprintf(stderr, "[-] Failed to create UDP socket\n"); - return -1; + int send_sock_fd = connect_udp_socket("127.0.0.1", 11000); // SEND requests to Server + int recv_sock_fd = create_bound_udp_socket("0.0.0.0", 12000); // LISTEN to server updates + + if (send_sock_fd < 0 || recv_sock_fd < 0) { + fprintf(stderr, "[!] Failed to create sockets (%d)(%d)\n", send_sock_fd, recv_sock_fd); + return EXIT_FAILURE; } - handshake hs; - hs.identifier = 1; - hs.operationId = 1; - hs.version = 0; - // Send handshake message + unsigned long offset = 0; + int ok = 1; + char buffer[1024]; - printf("[+] Sending handshake message...\t"); - ssize_t bytes_sent = send_udp_message((int)sock_FD, (const char *)&hs, SERVER_OUT_IP, uint16_t(SERVER_OUT_PORT)); - if (bytes_sent >= 0) { - printf("OK (%zd bytes)\n", bytes_sent); - } else { - fprintf(stderr, "ERROR. \n"); - close((int)sock_FD); - return -2; + trackAtributes trackInfo; + carAtributes update; + + trackInfo.server_name = (char *)malloc(128); + trackInfo.track = (char *)malloc(128); + trackInfo.track_config = (char *)malloc(64); + trackInfo.weather_graphics = (char *)malloc(64); + trackInfo.session_name = (char *)malloc(64); + + char message[124] = {0}; // just a place to put info messages from the server itself + + while (1) { + offset = 0; + u_int8_t str_len_8 = 0; + memset(buffer, 0, sizeof(buffer)); + + size_t recv_bytes = (size_t)recvfrom(recv_sock_fd, buffer, sizeof(buffer), 0, NULL, NULL); + if (recv_bytes < 0) { + perror("[!] recvfrom() failed"); + close(send_sock_fd); + close(recv_sock_fd); + return EXIT_FAILURE; + } + + // Convert buffer to utf-8 string and print it + printf("[+] Received %zd bytes from client\n", recv_bytes); + + // The first byte of the messages is always an ACSP_MessageType + switch ((int)buffer[0]) { + // ============================ + // SERVER → CLIENT MESSAGES + // ============================ + + case ACSP_NEW_SESSION: + printf("[+] Message Type: ACSP_NEW_SESSION\n"); + offset = 1; // Reset offset to 1 to read after message types + + trackInfo.protocol_version = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.session_index = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.current_session_index = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.session_count = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + + str_len_8 = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + read_utf32le_string((const u_int8_t *)buffer, recv_bytes, &offset, trackInfo.server_name, str_len_8, &ok); + + str_len_8 = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + read_string((const u_int8_t *)buffer, recv_bytes, &offset, trackInfo.track, str_len_8, &ok); + + str_len_8 = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + read_string((const u_int8_t *)buffer, recv_bytes, &offset, trackInfo.track_config, str_len_8, &ok); + + str_len_8 = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + read_string((const u_int8_t *)buffer, recv_bytes, &offset, trackInfo.session_name, str_len_8, &ok); + + trackInfo.typ = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.time = read_uint16((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.laps = read_uint16((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.wait_time = read_uint16((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.ambient_temp = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + trackInfo.road_temp = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + + str_len_8 = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + read_string((const u_int8_t *)buffer, recv_bytes, &offset, trackInfo.weather_graphics, str_len_8, &ok); + + trackInfo.elapsed_ms = read_int32((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + + + if (!ok) { + fprintf(stderr, "[-] Error parsing NEW_SESSION packet (offset=%zu)\n", offset); + break; + } + + printf("\tServer Name: \"%s\"\n", trackInfo.server_name); + printf("\tTrack: \"%s\"\n", trackInfo.track); + printf("\tTrack Config: \"%s\"\n", trackInfo.track_config); + printf("\tSession Name: \"%s\"\n", trackInfo.session_name); + + printf("\tProtocol Version: %d\tSession Index: %d/%d\tCurrent Session Index: %d\n", trackInfo.protocol_version, trackInfo.session_index, trackInfo.session_count, + trackInfo.current_session_index); + + printf("\tType: %d\tTime: %d mins\tLaps: %d\tWait Time: %d secs\n", trackInfo.typ, trackInfo.time, trackInfo.laps, trackInfo.wait_time); + printf("\tAmbient Temp: %d C\tRoad Temp: %d C\n", trackInfo.ambient_temp, trackInfo.road_temp); + printf("\tWeather Graphics: %s\n", trackInfo.weather_graphics); + printf("\tElapsed Time: %d ms\n", trackInfo.elapsed_ms); + + break; + + case ACSP_NEW_CONNECTION: + printf("[+] Message Type: ACSP_NEW_CONNECTION\n"); + break; + + case ACSP_CONNECTION_CLOSED: + printf("[+] Message Type: ACSP_CONNECTION_CLOSED\n"); + break; + + case ACSP_CAR_UPDATE: + printf("[+] Message Type: ACSP_CAR_UPDATE\n"); + + memcpy(&update.carID, buffer + 1, sizeof(uint8_t)); + offset = 1 + sizeof(uint8_t); + memcpy(&update.position, buffer + offset, sizeof(postion)); + offset += sizeof(postion); + memcpy(&update.velocity, buffer + offset, sizeof(postion)); + offset += sizeof(postion); + memcpy(&update.carGear, buffer + offset, sizeof(u_int8_t)); + offset += sizeof(u_int8_t); + memcpy(&update.carRPM, buffer + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + memcpy(&update.normalizedSplinePos, buffer + offset, sizeof(float_t)); + offset += sizeof(float_t); + + printf("\tCar %d Position: X: %.2f Y: %.2f Z: %.2f ", update.carID, update.position.x, update.position.y, update.position.z); + printf("Gear: %d RPM: %d\n", update.carGear, update.carRPM); + break; + + case ACSP_CAR_INFO: + printf("[+] Message Type: ACSP_CAR_INFO\n"); + break; + + case ACSP_END_SESSION: + printf("[+] Message Type: ACSP_END_SESSION\n"); + break; + + case ACSP_VERSION: + printf("[+] Message Type: ACSP_VERSION\n"); + break; + + case ACSP_CHAT: + printf("[+] Message Type: ACSP_CHAT\n"); + break; + + case ACSP_CLIENT_LOADED: + printf("[+] Message Type: ACSP_CLIENT_LOADED\n"); + break; + + case ACSP_SESSION_INFO: + printf("[+] Message Type: ACSP_SESSION_INFO\n"); + break; + + case ACSP_ERROR: + printf("[+] Message Type: ACSP_ERROR\n"); + offset = 1; // Reset offset to 1 to read after message types + + str_len_8 = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); + read_utf32le_string((const u_int8_t *)buffer, recv_bytes, &offset, message, str_len_8, &ok); + + printf("\tServer Message: \"%s\"\n", message); + break; + + case ACSP_LAP_COMPLETED: + printf("[+] Message Type: ACSP_LAP_COMPLETED\n"); + break; + + // ============================ + // EVENTS + // ============================ + case ACSP_CLIENT_EVENT: + printf("[+] Message Type: ACSP_CLIENT_EVENT\n"); + break; + + // ============================ + // EVENT TYPES + // ============================ + case ACSP_CE_COLLISION_WITH_CAR: + printf("[+] Event Type: ACSP_CE_COLLISION_WITH_CAR\n"); + break; + + case ACSP_CE_COLLISION_WITH_ENV: + printf("[+] Event Type: ACSP_CE_COLLISION_WITH_ENV\n"); + break; + + // ============================ + // CLIENT → SERVER COMMANDS + // ============================ + case ACSP_REALTIMEPOS_INTERVAL: + printf("[+] Command: ACSP_REALTIMEPOS_INTERVAL\n"); + break; + + case ACSP_GET_CAR_INFO: + printf("[+] Command: ACSP_GET_CAR_INFO\n"); + break; + + case ACSP_SEND_CHAT: + printf("[+] Command: ACSP_SEND_CHAT\n"); + break; + + case ACSP_BROADCAST_CHAT: + printf("[+] Command: ACSP_BROADCAST_CHAT\n"); + break; + + case ACSP_GET_SESSION_INFO: + printf("[+] Command: ACSP_GET_SESSION_INFO\n"); + break; + + case ACSP_SET_SESSION_INFO: + printf("[+] Command: ACSP_SET_SESSION_INFO\n"); + break; + + case ACSP_KICK_USER: + printf("[+] Command: ACSP_KICK_USER\n"); + break; + + case ACSP_NEXT_SESSION: + printf("[+] Command: ACSP_NEXT_SESSION\n"); + break; + + case ACSP_RESTART_SESSION: + printf("[+] Command: ACSP_RESTART_SESSION\n"); + break; + + case ACSP_ADMIN_COMMAND: + printf("[+] Command: ACSP_ADMIN_COMMAND\n"); + break; + + // ============================ + // DEFAULT HANDLER + // ============================ + default: + printf("[!] Unknown Message Type: %d\n", buffer[0]); + break; + } + + usleep(10000); // Sleep for 10ms } + close(send_sock_fd); + close(recv_sock_fd); - uint8_t buffer[512]; // bigger than struct - ssize_t bytes_received = recv(sock_FD, buffer, sizeof(buffer), 0); - - if (bytes_received >= sizeof(handshackerResponse)) { - handshackerResponse resp; - memcpy(&resp, buffer, sizeof(handshackerResponse)); - - printf("[+] Received handshake response:\n"); - printf(" Car: %0x\n", resp.carName); - printf(" Driver: %0x\n", resp.driverName); - printf(" Identifier: %d\n", resp.identifier); - printf(" Version: %0x\n", resp.version); - printf(" Track: %0x\n", resp.trackName); - printf(" Config: %0x\n", resp.trackConfig); - } else { - printf("[!] Packet too short for handshake response (%zd bytes)\n", bytes_received); - } - - - - - + free(trackInfo.server_name); + free(trackInfo.track); + free(trackInfo.track_config); + free(trackInfo.weather_graphics); + free(trackInfo.session_name); return 0; }