#include #include #include #include #include #include #include #include #include #include "app.hpp" // for app_info struct #include "file.hpp" // for parce_args #include "log.h" // for logging #include "net.hpp" // for socket operations #include "server_structs.h" // for api_packet and ACSP_MessageType #include "session.hpp" // for SessionManager #include "mapper.hpp" // for Mapper const u_int8_t UPDATE_INTERVAL = 120; // in milliseconds using namespace std; volatile bool STOP_PROGRAM = false; void signal_handler(int signum) { if (signum == SIGINT || signum == SIGTERM) { STOP_PROGRAM = true; } } int main(int argc, char *argv[]) { app_info app = parce_args(argc, argv); api_packet packet; Socket sock; SessionManager session_manager(app.app_id); uint8_t buffer[1028]; Mapper map(buffer, 1028); trackAtributes track; track.server_name = new char[256]; track.track = new char[64]; track.track_config = new char[64]; track.session_name = new char[64]; track.weather_graphics = new char[64]; try { // Connect socket to API // sock.connect_unix(app.app_api_socket_path.c_str(), app.app_port_out); // Connect socket to Server sock.connect_server(app.app_server_out_ip.c_str(), app.app_port_in); sock.bind_server("127.0.0.1", app.app_port_out); // Await server for initial data sock.receive_server(buffer, sizeof(buffer)); log_info("Connected to server, awaiting version confirmation...\n"); if (buffer[0] == ACSP_VERSION) { log_info("Server version confirmed. Sending update rate request @ %ums\n", UPDATE_INTERVAL); } else { throw runtime_error("Did not receive version confirmation from server."); } char request[516] = {0}; request[0] = ACSP_REALTIMEPOS_INTERVAL; request[1] = UPDATE_INTERVAL; sock.send_server(request, sizeof(request)); log_debug("Info:\n"); log_debug("\t\tApp ID: %d\n", app.app_id); log_debug("\t\tAPI Socket Path: %s\n", app.app_api_socket_path.c_str()); log_debug("\t\tServer Out IP: %s\n", app.app_server_out_ip.c_str()); log_debug("\t\tApp Port In: %d\n", app.app_port_in); log_debug("\t\tApp Port Out: %d\n", app.app_port_out); } catch (const runtime_error &e) { cerr << "Error: " << e.what() << endl; return 1; } // TODO: Implement Cache // TAG: Because sometimes the parser doesnt have the name of the server because it started after the server init // we can cache it and reuse it to avoid NULL names in the DB while (STOP_PROGRAM == false) { // Receive data from server ssize_t received = sock.receive_server(buffer, sizeof(buffer)); if (received > 0) { map.update_buffer(buffer, static_cast(received)); switch (map.get_message_type()) { // DONE: case ACSP_VERSION: { log_warn("Received Version Again? (Probably server restart) Resending Update Request @ %ums\n", UPDATE_INTERVAL); char request[516] = {0}; request[0] = ACSP_REALTIMEPOS_INTERVAL; request[1] = UPDATE_INTERVAL; sock.send_server(request, sizeof(request)); break; } // TODO: case ACSP_CAR_UPDATE: { // log_info("Received car update.\n"); break; } // TODO: case ACSP_NEW_SESSION: { log_info("New session started.\n"); map.parse_new_session(track); if (map.is_ok()) { session_manager.on_new_session(track); } else { log_error("Failed to parse new session data.\n"); } // TESTING: Print track info log_info("Track Info:\n"); log_info("\t\tServer Name: %s\n", track.server_name); log_info("\t\tTrack: %s\n", track.track); log_info("\t\tTrack Config: %s\n", track.track_config); log_info("\t\tSession Name: %s\n", track.session_name); log_info("\t\tWeather Graphics: %s\n", track.weather_graphics); log_info("\t\tSession Type: %d\n", track.session_type); log_info("\t\tLaps: %d\n", track.laps); log_info("\t\tTime: %d\n", track.time); log_info("\t\tAmbient Temp: %d\n", track.ambient_temp); log_info("\t\tRoad Temp: %d\n", track.road_temp); log_info("\t\tElapsed MS: %u\n", track.elapsed_ms); break; } default: { break; } } } } delete[] track.server_name; delete[] track.track; delete[] track.track_config; delete[] track.session_name; delete[] track.weather_graphics; return 0; }