diff --git a/PlayerTracker b/PlayerTracker index b4bf780..c06afbe 100755 Binary files a/PlayerTracker and b/PlayerTracker differ diff --git a/include/file.cpp b/include/file.cpp new file mode 100644 index 0000000..a40f1ce --- /dev/null +++ b/include/file.cpp @@ -0,0 +1,56 @@ +#include "file.hpp" + +vector read_file(const char *filePath) { + ifstream file(filePath); + if (!file.is_open()) { + return vector(); + } + + vector lines; + string line; + + while (getline(file, line)) { + lines.push_back(line); + } + + file.close(); + return lines; +} + +app_info parce_args(int argc, char *argv[]) { + // example + // ./player_tracker 130 12000 13000 + // -id -serverin -serverout + app_info __processed_info; + + if (argc <= 1) { + throw invalid_argument("No argc provided"); + } + + __processed_info.app_id = (u_int16_t)atoi(argv[1]); + __processed_info.app_port_in = (u_int16_t)atoi(argv[2]); + __processed_info.app_port_out = (u_int16_t)atoi(argv[3]); + + // Parce .env + vector __read_lines = read_file("./.env"); + map __env_args; + + for (size_t i = 0; i < __read_lines.size() - 1; i++) { + string token = __read_lines[i].substr(0, __read_lines[i].find(" = ")); + + __read_lines[i].erase(0, __read_lines[i].find(" = ") + 3); + + __env_args[token] = __read_lines[i]; + } + + // DEBUG + // for (const auto& [key, value] : __env_args) { + // std::cout << '[' << key << "] = " << value << "; "; + // } + + __processed_info.app_api_socket_path = __env_args["API_SOCKET_PATH"].c_str(); + __processed_info.max_players = (u_int16_t)atoi(__env_args["MAX_PLAYERS"].c_str()); + __processed_info.app_server_out_ip = __env_args["SERVER_OUT_IP"].c_str(); + + return __processed_info; +} diff --git a/include/file.hpp b/include/file.hpp new file mode 100644 index 0000000..80b0a25 --- /dev/null +++ b/include/file.hpp @@ -0,0 +1,18 @@ +#ifndef FILE_H +#define FILE_H + +#include +#include +#include +#include +#include +#include + +#include "server_structs.h" + +using namespace std; + +vector read_file(const char *filePath); +app_info parce_args(int argc, char *argv[]); + +#endif diff --git a/include/net.cpp b/include/net.cpp new file mode 100644 index 0000000..e69de29 diff --git a/include/net.hpp b/include/net.hpp new file mode 100644 index 0000000..abe5691 --- /dev/null +++ b/include/net.hpp @@ -0,0 +1,33 @@ +#ifndef NET_HPP +#define NET_HPP + +#include +#include +#include +#include +#include +#include + +#include "server_structs.h" + +using namespace std; + +class Socket { + private: + // Socket file descriptor + int sock; + struct sockaddr_in server_addr; + // Socket Data + api_packet packet_data; + + + public: + Socket(); + ~Socket(); + + void connect(const char *ip, uint16_t port); + void send(); + void send(const api_packet &data); +}; + +#endif // NET_HPP diff --git a/include/server_structs.h b/include/server_structs.h index 2d175af..5e8ac4e 100644 --- a/include/server_structs.h +++ b/include/server_structs.h @@ -4,6 +4,18 @@ #include #include +typedef struct app_info { + // From args + u_int16_t app_id; + u_int16_t app_port_in; + u_int16_t app_port_out; + + // From .env + const char *app_api_socket_path; + u_int16_t max_players; + const char *app_server_out_ip; +} __attribute__((packed)) app_info; + typedef struct handshake { // [not used in the current Remote Telemtry version by AC] // In future versions it will identify the platform type of the client. diff --git a/source/main.cpp b/source/main.cpp index 6aba801..a4523ff 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,801 +1,18 @@ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include -#include "parcer.h" -#include "server_structs.h" -#include "socket.h" +#include "file.hpp" // for parce_args +#include "net.hpp" // for socket operations -#define DEBUG_CAR_INFO 1 - -const char *API_SOCKET_PATH = "/tmp/ACplayer_socket"; - -const int MAX_PLAYERS = 64; -const char *SERVER_OUT_IP = "127.0.0.1"; - -u_int8_t SERVER_ID; -api_packet current_packet; -u_int8_t apiSent = 0; - -// INFO: This assumes Players pointer to be the same size of MAX_PLAYERS -void update_api_packet(trackAtributes trackInfo, carAtributes *players) { - current_packet.tracker_id = SERVER_ID; - - // Update track info - current_packet.track_info.protocol_version = trackInfo.protocol_version; - current_packet.track_info.session_index = trackInfo.session_index; - current_packet.track_info.current_session_index = trackInfo.current_session_index; - current_packet.track_info.session_count = trackInfo.session_count; - current_packet.track_info.session_type = trackInfo.session_type; - strncpy(current_packet.track_info.server_name, trackInfo.server_name, sizeof(current_packet.track_info.server_name) - 1); - strncpy(current_packet.track_info.track, trackInfo.track, sizeof(current_packet.track_info.track) - 1); - strncpy(current_packet.track_info.track_config, trackInfo.track_config, sizeof(current_packet.track_info.track_config) - 1); - strncpy(current_packet.track_info.session_name, trackInfo.session_name, sizeof(current_packet.track_info.session_name) - 1); - current_packet.track_info.typ = trackInfo.typ; - current_packet.track_info.time = trackInfo.time; - current_packet.track_info.laps = trackInfo.laps; - current_packet.track_info.wait_time = trackInfo.wait_time; - current_packet.track_info.ambient_temp = trackInfo.ambient_temp; - current_packet.track_info.road_temp = trackInfo.road_temp; - strncpy(current_packet.track_info.weather_graphics, trackInfo.weather_graphics, sizeof(current_packet.track_info.weather_graphics) - 1); - current_packet.track_info.elapsed_ms = trackInfo.elapsed_ms; - - // Update car INFO - for (int i = 0; i < MAX_PLAYERS; i++) { - current_packet.cars[i].isConnected = players[i].isConnected; - current_packet.cars[i].isLoading = players[i].isLoading; - - strncpy(current_packet.cars[i].car_model, players[i].car_model, sizeof(current_packet.cars[i].car_model) - 1); - strncpy(current_packet.cars[i].driver_GUID, players[i].driver_GUID, sizeof(current_packet.cars[i].driver_GUID) - 1); - strncpy(current_packet.cars[i].car_skin, players[i].car_skin, sizeof(current_packet.cars[i].car_skin) - 1); - strncpy(current_packet.cars[i].driver_name, players[i].driver_name, sizeof(current_packet.cars[i].driver_name) - 1); - strncpy(current_packet.cars[i].driver_team, players[i].driver_team, sizeof(current_packet.cars[i].driver_team) - 1); - - current_packet.cars[i].carID = players[i].carID; - - current_packet.cars[i].position = players[i].position; - current_packet.cars[i].velocity = players[i].velocity; - - current_packet.cars[i].carGear = players[i].carGear; - current_packet.cars[i].carRPM = players[i].carRPM; - current_packet.cars[i].lap_time = players[i].lap_time; - current_packet.cars[i].cuts = players[i].cuts; - current_packet.cars[i].total_cuts = players[i].total_cuts; - current_packet.cars[i].total_cuts_alltime = players[i].total_cuts_alltime; - - current_packet.cars[i].total_laps_completed = players[i].total_laps_completed; - current_packet.cars[i].contacts = players[i].contacts; - current_packet.cars[i].total_contacts = players[i].total_contacts; - - current_packet.cars[i].normalizedSplinePos = players[i].normalizedSplinePos; - } - - apiSent = 0; -} - -void *send_to_api_socket(void *arg) { - int sock_fd; - struct sockaddr_un addr; - - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, API_SOCKET_PATH); - - // --- Connect loop --- - while (1) { - sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock_fd < 0) { - usleep(500000); - continue; - } - - if (connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - close(sock_fd); - usleep(500000); - continue; - } - break; // connected - } - - printf("[+] Connected to API socket at %s\n", API_SOCKET_PATH); - - // Handshake - api_packet handshake; - - handshake.tracker_id = 65; - send(sock_fd, &handshake, sizeof(api_packet), MSG_NOSIGNAL); - - while (1) { - if (current_packet.tracker_id == (u_int8_t)-1) { - usleep(10000); - apiSent = 0; - continue; - } - - if (apiSent) { - usleep(10000); - continue; - } - - ssize_t sent_bytes = send(sock_fd, ¤t_packet, sizeof(api_packet), MSG_NOSIGNAL); - if (sent_bytes < 0) { - fprintf(stderr, "[!] Failed to send data to API socket, reconnecting...\n"); - close(sock_fd); - - // Reconnect loop - while (1) { - sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock_fd < 0) { - usleep(500000); - continue; - } - - if (connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - close(sock_fd); - usleep(500000); - continue; - } - break; // connected - } - - printf("[+] Reconnected to API socket at %s\n", API_SOCKET_PATH); - } - - apiSent = 1; - - usleep(10000); // 10ms - } - - return NULL; -} - -void init_carupdate(carAtributes *car) { - car->isConnected = 0; - car->isLoading = 0; - - car->car_model = (char *)malloc(64); - car->driver_GUID = (char *)malloc(64); - car->car_skin = (char *)malloc(64); - car->driver_name = (char *)malloc(64); - car->driver_team = (char *)malloc(64); - - strcpy(car->car_model, ""); - strcpy(car->driver_GUID, ""); - strcpy(car->car_skin, ""); - strcpy(car->driver_name, ""); - strcpy(car->driver_team, ""); - - car->carID = 0; - - car->position.x = 0.0f; - car->position.y = 0.0f; - car->position.z = 0.0f; - - car->velocity.x = 0.0f; - car->velocity.y = 0.0f; - car->velocity.z = 0.0f; - - car->carGear = 0; - car->carRPM = 0; - car->lap_time = 0; - car->cuts = 0; - car->total_cuts = 0; - car->total_cuts_alltime = 0; // TODO: SQL querry to get total cuts of all time; TAG:1 - - car->total_laps_completed = 0; - car->contacts = 0; - car->total_contacts = 0; // TODO: SQL querry to get total contacts of all time; TAG:2 - - car->normalizedSplinePos = 0.0f; -} +using namespace std; int main(int argc, char *argv[]) { + app_info app = parce_args(argc, argv); - // Parse command-line arguments - if (argc != 4) { - fprintf(stderr, "Usage: %s \n", argv[0]); - fprintf(stderr, "Example: %s 131 11001 12001\n", argv[0]); - return EXIT_FAILURE; - } - SERVER_ID = (u_int8_t)atoi(argv[1]); - u_int16_t SERVER_IN_PORT = (u_int16_t)atoi(argv[2]); - u_int16_t SERVER_OUT_PORT = (u_int16_t)atoi(argv[3]); - - printf("[+] Starting server...\n"); - printf("[+] Server listening on port %d\n", SERVER_IN_PORT); - printf("[+] Server sending to %s:%d\n\n", SERVER_OUT_IP, SERVER_OUT_PORT); - - current_packet.tracker_id = (u_int8_t)-1; // Mark as uninitialized - - int send_sock_fd = connect_udp_socket(SERVER_OUT_IP, SERVER_IN_PORT); // SEND requests to Server - int recv_sock_fd = create_bound_udp_socket("0.0.0.0", SERVER_OUT_PORT); // 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; - } - - unsigned long offset = 0; - int ok = 1; - char buffer[1024]; - - // Start thread to send data to API socket - pthread_t api_thread; - if (pthread_create(&api_thread, NULL, send_to_api_socket, NULL) != 0) { - fprintf(stderr, "[!] Failed to create API socket thread\n"); - return EXIT_FAILURE; - } - - pthread_detach(api_thread); - - trackAtributes trackInfo; - carAtributes players[MAX_PLAYERS]; - - current_packet.connected_players = 0; - carAtributes update; - - // Basically a contrutor for carAtributes (because all strings in carAtributes are pointers) - for (int i = 0; i < MAX_PLAYERS; i++) { - init_carupdate(&players[i]); - } - - init_carupdate(&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 - - printf("\n"); - while (1) { - offset = 0; - u_int8_t str_len_8 = 0; - memset(buffer, 0, sizeof(buffer)); - - // FIX: Its not garanted to receive a full packet in one recvfrom call, but the error -1 is not handled by a unsigned size_t - size_t recv_bytes = (size_t)recvfrom(recv_sock_fd, buffer, sizeof(buffer), 0, NULL, NULL); - - // Convert buffer to utf-8 string and print it -#if DEBUG_CAR_INFO - printf("[+] Received %zd bytes from client\n", recv_bytes); -#endif - - current_packet.message_type = (u_char)buffer[0]; - // The first byte of the messages is always an ACSP_MessageType - switch ((u_char)buffer[0]) { - // ============================ - // SERVER → CLIENT MESSAGES - // ============================ - case ACSP_SESSION_INFO: - printf("[+] Message Type: ACSP_SESSION_INFO\n"); - goto skip_message; - case ACSP_NEW_SESSION: // DONE: - printf("[+] Message Type: ACSP_NEW_SESSION\n"); - skip_message: - 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); - - trackInfo.session_type = (SessionType)trackInfo.session_index; // FOR BACKWARD COMPATIBILITY - - 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); - - // FIX: elapsed_ms was/is incorrectly read - // TEST: Verify with actual server - trackInfo.elapsed_ms = read_uint32((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 (%2d:%2d:%2d)\n\n", trackInfo.elapsed_ms, trackInfo.elapsed_ms / 60000, (trackInfo.elapsed_ms % 60000) / 1000, - (trackInfo.elapsed_ms % 60000) % 1000); - - update_api_packet(trackInfo, players); - break; - - case ACSP_NEW_CONNECTION: // DONE: - printf("[+] Message Type: ACSP_NEW_CONNECTION\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, update.driver_name, str_len_8, &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, update.driver_GUID, str_len_8, &ok); - - update.carID = 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, update.car_model, 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, update.car_skin, str_len_8, &ok); - - if (!ok) { - fprintf(stderr, "[-] Error parsing NEW_CONNECTION packet (offset=%zu)\n", offset); - break; - } - - update.isConnected = 1; // Mark as connected - update.isLoading = 1; // Mark as Loading - current_packet.connected_players++; - - printf("\tDriver Name: \"%s\"\n", update.driver_name); - printf("\tDriver GUID: \"%s\"\n", update.driver_GUID); - printf("\tCar ID: %d\n", update.carID); - printf("\tCar Model: \"%s\"\n", update.car_model); - printf("\tCar Skin: \"%s\"\n\n", update.car_skin); - - // Store player player into the respective Index - if (update.carID < MAX_PLAYERS) { - players[update.carID].isConnected = update.isConnected; - players[update.carID].isLoading = update.isLoading; - players[update.carID].carID = update.carID; - - strncpy(players[update.carID].driver_GUID, update.driver_GUID, 63); - strncpy(players[update.carID].driver_name, update.driver_name, 63); - strncpy(players[update.carID].driver_team, update.driver_team, 63); - strncpy(players[update.carID].car_model, update.car_model, 63); - strncpy(players[update.carID].car_skin, update.car_skin, 63); - - players[update.carID].driver_GUID[63] = '\0'; - players[update.carID].driver_name[63] = '\0'; - players[update.carID].driver_team[63] = '\0'; - players[update.carID].car_model[63] = '\0'; - players[update.carID].car_skin[63] = '\0'; - } - update_api_packet(trackInfo, players); - break; - - case ACSP_CONNECTION_CLOSED: // DONE: - printf("[+] Message Type: ACSP_CONNECTION_CLOSED\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, update.driver_name, str_len_8, &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, update.driver_GUID, str_len_8, &ok); - - update.carID = 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, update.car_model, 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, update.car_skin, str_len_8, &ok); - - if (!ok) { - fprintf(stderr, "[-] Error parsing NEW_CONNECTION packet (offset=%zu)\n", offset); - break; - } - - update.isConnected = 0; // Mark as disconnected - current_packet.connected_players--; - if (current_packet.connected_players > MAX_PLAYERS) { - current_packet.connected_players = 0; - } - - printf("\tDriver Name: \"%s\"\n", update.driver_name); - printf("\tDriver GUID: \"%s\"\n", update.driver_GUID); - printf("\tCar ID: %d\n", update.carID); - printf("\tCar Model: \"%s\"\n", update.car_model); - printf("\tCar Skin: \"%s\"\n\n", update.car_skin); - - // Store player player into the respective Index - if (update.carID < MAX_PLAYERS) { - players[update.carID].isConnected = 0; // Mark disconnected - players[update.carID].isLoading = 0; - } - update_api_packet(trackInfo, players); - break; - - case ACSP_CAR_UPDATE: // DONE: -#if DEBUG_CAR_INFO - printf("[+] Message Type: ACSP_CAR_UPDATE\n"); -#endif - offset = 1; - - memcpy(&update.carID, buffer + offset, 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); - -#if DEBUG_CAR_INFO - 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); -#endif - - // Store player player into the respective Index - if (update.carID < MAX_PLAYERS) { - players[update.carID].position = update.position; - players[update.carID].velocity = update.velocity; - players[update.carID].carGear = update.carGear; - players[update.carID].carRPM = update.carRPM; - players[update.carID].normalizedSplinePos = update.normalizedSplinePos; - - players[update.carID].isConnected = update.isConnected; - players[update.carID].isLoading = update.isLoading; - players[update.carID].carID = update.carID; - } - - update_api_packet(trackInfo, players); - break; - - case ACSP_CAR_INFO: // DONE: - printf("[+] Message Type: ACSP_CAR_INFO\n"); - offset = 1; // Reset offset to 1 to read after message types; - - update.carID = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - update.isConnected = 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, update.car_model, str_len_8, &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, update.car_skin, str_len_8, &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, update.driver_name, str_len_8, &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, update.driver_team, str_len_8, &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, update.driver_GUID, str_len_8, &ok); - - if (!ok) { - fprintf(stderr, "[-] Error parsing CAR_INFO packet (offset=%zu)\n", offset); - } - - printf("\tCar ID: %d\n", update.carID); - printf("\tIs Connected: %d\n", update.isConnected); - printf("\tCar Model: \"%s\"\n", update.car_model); - printf("\tCar Skin: \"%s\"\n", update.car_skin); - printf("\tDriver Name: \"%s\"\n", update.driver_name); - printf("\tDriver Team: \"%s\"\n", update.driver_team); - printf("\tDriver GUID: \"%s\"\n\n", update.driver_GUID); - - // Store player player into the respective Index - if (update.carID < MAX_PLAYERS) { - - players[update.carID].isConnected = update.isConnected; - players[update.carID].isLoading = update.isLoading; - players[update.carID].carID = update.carID; - - strncpy(players[update.carID].driver_GUID, update.driver_GUID, 63); - strncpy(players[update.carID].driver_name, update.driver_name, 63); - strncpy(players[update.carID].driver_team, update.driver_team, 63); - strncpy(players[update.carID].car_model, update.car_model, 63); - strncpy(players[update.carID].car_skin, update.car_skin, 63); - - players[update.carID].driver_GUID[63] = '\0'; - players[update.carID].driver_name[63] = '\0'; - players[update.carID].driver_team[63] = '\0'; - players[update.carID].car_model[63] = '\0'; - players[update.carID].car_skin[63] = '\0'; - } - - update_api_packet(trackInfo, players); - break; - - case ACSP_END_SESSION: // DONE: (only session type cycling) - printf("[+] Message Type: ACSP_END_SESSION\n"); - // Advance session_type to the next in the enum; - - trackInfo.session_type = (SessionType)((trackInfo.session_type + 1) % 3); - - if (trackInfo.session_type == 0) { - memcpy(trackInfo.session_name, "Practice", 9); - } else if (trackInfo.session_type == 1) { - memcpy(trackInfo.session_name, "Race", 5); - } else if (trackInfo.session_type == 2) { - memcpy(trackInfo.session_name, "Qualify", 8); - } - - printf("\tNext Session Name: %s\n", trackInfo.session_name); - printf("\tNext Session Type: %d\n\n", trackInfo.session_type); - - update_api_packet(trackInfo, players); - break; - - case ACSP_VERSION: // DONE: - printf("[+] Message Type: ACSP_VERSION\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); - - printf("\tProtocol Version: %d\n\n", trackInfo.protocol_version); - - update_api_packet(trackInfo, players); - break; - - case ACSP_CHAT: // DONE: Receive chat messages - printf("[+] Message Type: ACSP_CHAT\n"); - offset = 1; // Reset offset to 1 to read after message types - - update.carID = 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, message, str_len_8, &ok); - - printf("\tCar ID: %d (%s)\n", update.carID, players[update.carID].driver_name); - printf("\tMessage: \"%s\"\n\n", message); - - update_api_packet(trackInfo, players); - break; - - case ACSP_CLIENT_LOADED: // DONE: Check for client loaded status - printf("[+] Message Type: ACSP_CLIENT_LOADED\n"); - offset = 1; // Reset offset to 1 to read after message types - - update.carID = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - - players[update.carID].isLoading = 0; - printf("\tCar ID: %d (%s) Finished Loading into the session\n\n", update.carID, players[update.carID].driver_name); - - update_api_packet(trackInfo, players); - break; - - case ACSP_ERROR: // DONE: Simple error message from server - 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\n", message); - break; - - case ACSP_LAP_COMPLETED: // DONE: Handle lap completed events - printf("[+] Message Type: ACSP_LAP_COMPLETED\n"); - offset = 1; // Reset offset to 1 to read after message types - - update.carID = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - - // TEST: Possiblity of lap_time not behing correct - // TODO: Verify with actual serve - // SOLUTION: Server sends all times, lap_times and lap counts in big-endian format - update.lap_time = read_uint32((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - update.cuts = read_uint32((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - - update.total_cuts = read_uint32((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - - printf("\tCar ID: %d (%s)\n", update.carID, players[update.carID].driver_name); - printf("\tLap Time: %5d ms\n", update.lap_time); - printf("\tCuts this lap: %d\n", update.cuts); - printf("\tTotal Cuts (this session): %d\n\n", update.total_cuts); - - update_api_packet(trackInfo, players); - break; - - // ============================ - // EVENTS - // ============================ - case ACSP_CLIENT_EVENT: { - printf("[+] Message Type: ACSP_CLIENT_EVENT\n"); - offset = 1; // Reset offset to 1 to read after message types - - u_int8_t event_type = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - - update.carID = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - u_int8_t event_car_id = 255; // If event doesnt involve another car, set to 255 - - switch (event_type) { - // ============================ - // EVENT TYPES - // ============================ - case ACSP_CE_COLLISION_WITH_CAR: { - printf("[+] Event Type: ACSP_CE_COLLISION_WITH_CAR\n"); - event_car_id = read_uint8((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - - printf("Car ID: %d (%s) collided with Car ID: %d (%s)\n", update.carID, players[update.carID].driver_name, event_car_id, players[event_car_id].driver_name); - - players[update.carID].contacts++; - players[event_car_id].contacts++; - - // TODO: Update total contacts for both players in the database - // TAG:2 Update total contacts for both players - - update_api_packet(trackInfo, players); - } break; - - case ACSP_CE_COLLISION_WITH_ENV: { - printf("[+] Event Type: ACSP_CE_COLLISION_WITH_ENV\n"); - - printf("Car ID: %d (%s) collided with the environment\n", update.carID, players[update.carID].driver_name); - - players[update.carID].contacts++; - - // TODO: Update total contacts for the player in the database - // TAG:2 Update total contacts for the player - - update_api_packet(trackInfo, players); - } break; - } - - // TODO: possible iRacing style impact severity system - // With X velues and (e.g >5 m/s = 0x, >10 m/s = 2x, >15 m/s = 4x) && Blackflag limits (e.g x17 = DQ) - - // FIX: read_float doesnt work, but memcpy does... weird... - float impact_speed = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - postion world_pos = {0, 0, 0}; - /* world_pos.x = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - world_pos.y = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - world_pos.z = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - */ - - memcpy(&world_pos.x, buffer + offset, sizeof(float)); - offset += sizeof(float); - memcpy(&world_pos.y, buffer + offset, sizeof(float)); - offset += sizeof(float); - memcpy(&world_pos.z, buffer + offset, sizeof(float)); - offset += sizeof(float); - - postion rel_pos = {0, 0, 0}; - /* - rel_pos.x = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - rel_pos.y = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - rel_pos.z = read_float((const u_int8_t *)buffer, recv_bytes, &offset, &ok); - */ - - memcpy(&rel_pos.x, buffer + offset, sizeof(float)); - offset += sizeof(float); - memcpy(&rel_pos.y, buffer + offset, sizeof(float)); - offset += sizeof(float); - memcpy(&rel_pos.z, buffer + offset, sizeof(float)); - offset += sizeof(float); - - printf("\tImpact Speed: %.2f m/s\n", impact_speed); - printf("\tWorld Position: X: %.2f Y: %.2f Z: %.2f\n", world_pos.x, world_pos.y, world_pos.z); - printf("\tRelative Position: X: %.2f Y: %.2f Z: %.2f\n\n", rel_pos.x, rel_pos.y, rel_pos.z); - - } break; - - // TODO: Add for ranking system - // OPTIMIZE: Make sure DB queries are optimized for speed has there can be more that 30 players querying at the same time - // - // ============================ - // CLIENT → SERVER COMMANDS - // NOTE: These are not meant to be here, these are comands to SEND to the server - // ============================ - 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: { // DONE: - printf("[+] Command: ACSP_ADMIN_COMMAND\n"); - char *__buffer = (char *)malloc(256); - char command[256] = "/settime 19:00"; // TEST: - - __buffer[0] = (char)ACSP_ADMIN_COMMAND; - for (int i = 1; i <= strlen(command); i++) { - buffer[i] = command[i - 1]; - } - - sendto(send_sock_fd, buffer, strlen(command) + 1, 0, NULL, 0); - printf("\tSent Admin Command: %s\n\n", command); - free(__buffer); - } break; - - // ============================ - // DEFAULT HANDLER - // ============================ - default: - printf("[!] Unknown Message Type: %d\n\n", buffer[0]); - break; - } - - // OPTIMIZE: This should be done inside each case where data is updated otherwise we lose performance - usleep(10000); // Sleep for 10ms - } - close(send_sock_fd); - close(recv_sock_fd); - - // Free allocated memory - free(update.car_model); - free(update.driver_GUID); - free(update.car_skin); - free(update.driver_name); - free(update.driver_team); - - for (int i = 0; i < MAX_PLAYERS; i++) { - free(players[i].car_model); - free(players[i].driver_GUID); - free(players[i].car_skin); - free(players[i].driver_name); - free(players[i].driver_team); - } - - free(trackInfo.server_name); - free(trackInfo.track); - free(trackInfo.track_config); - free(trackInfo.weather_graphics); - free(trackInfo.session_name); return 0; } +