generated from AfonsoCMSousa/CPP-Template
Feature: API can now handle write and read to the DB
This commit is contained in:
parent
524405d80d
commit
2d3f52a9a5
7
.clang-format
Normal file
7
.clang-format
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
UseTab: ForIndentation
|
||||||
|
TabWidth: 4
|
||||||
|
ColumnLimit: 180
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
project(CPP_TEMPLATE VERSION 0.1.0 LANGUAGES CXX)
|
project(CPP_TEMPLATE VERSION 0.1.0 LANGUAGES CXX C)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
@ -47,6 +47,10 @@ add_executable(${EXECUTABLE_NAME}
|
|||||||
${PROJECT_HEADERS}
|
${PROJECT_HEADERS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
find_package(PostgreSQL REQUIRED)
|
||||||
|
include_directories(${PostgreSQL_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${EXECUTABLE_NAME} ${PostgreSQL_LIBRARIES})
|
||||||
|
|
||||||
# Set output name property (for consistency)
|
# Set output name property (for consistency)
|
||||||
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_NAME})
|
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_NAME})
|
||||||
|
|
||||||
@ -72,4 +76,4 @@ endif()
|
|||||||
|
|
||||||
# Optionally, enable testing
|
# Optionally, enable testing
|
||||||
# enable_testing()
|
# enable_testing()
|
||||||
# add_subdirectory(tests)
|
# add_subdirectory(tests)
|
||||||
|
|||||||
1
compile_commands.json
Symbolic link
1
compile_commands.json
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
build/compile_commands.json
|
||||||
244
include/server_structs.h
Normal file
244
include/server_structs.h
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
#ifndef SERVER_STRUCTS_H
|
||||||
|
#define SERVER_STRUCTS_H
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
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.
|
||||||
|
// This will be used to adjust a specific behaviour for each platform. (eIPadDevice for now (1))
|
||||||
|
int32_t identifier;
|
||||||
|
|
||||||
|
// [not used in the current Remote Telemtry version by AC]
|
||||||
|
// In future version this field will identify the AC Remote Telemetry version that the device expects to speak with.
|
||||||
|
int32_t version;
|
||||||
|
|
||||||
|
// This is the type of operation required by the client.
|
||||||
|
// The following operations are now available:
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
// HANDSHAKE = 0 :
|
||||||
|
// This operation identifier must be set when the client wants to start the comunication.
|
||||||
|
//
|
||||||
|
// SUBSCRIBE_UPDATE = 1 :
|
||||||
|
// This operation identifier must be set when the client wants to be updated from the specific ACServer.
|
||||||
|
//
|
||||||
|
// SUBSCRIBE_SPOT = 2 :
|
||||||
|
// This operation identifier must be set when the client wants to be updated from the specific ACServer just for SPOT Events (e.g.: the end of a lap).
|
||||||
|
//
|
||||||
|
// DISMISS = 3 :
|
||||||
|
// This operation identifier must be set when the client wants to leave the comunication with ACServer.
|
||||||
|
int32_t operationId;
|
||||||
|
} __attribute__((packed)) handshake;
|
||||||
|
|
||||||
|
typedef struct handshackerResponse {
|
||||||
|
// is the name of the car that the player is driving on the AC Server
|
||||||
|
char carName[50];
|
||||||
|
|
||||||
|
// is the name of the driver running on the AC Server
|
||||||
|
char driverName[50];
|
||||||
|
|
||||||
|
// for now is just 4242, this code will identify different status,
|
||||||
|
// as “NOT AVAILABLE” for connection
|
||||||
|
int32_t identifier;
|
||||||
|
|
||||||
|
// for now is set to 1, this will identify the version running on the AC Server
|
||||||
|
int32_t version;
|
||||||
|
|
||||||
|
// is the name of the track on the AC Server
|
||||||
|
char trackName[50];
|
||||||
|
|
||||||
|
// is the track configuration on the AC Server
|
||||||
|
char trackConfig[50];
|
||||||
|
} __attribute__((packed)) handshackerResponse;
|
||||||
|
|
||||||
|
typedef struct postion {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} __attribute__((packed)) postion;
|
||||||
|
|
||||||
|
typedef enum flag {
|
||||||
|
NO_FLAG = 0,
|
||||||
|
YELLOW_FLAG = 1,
|
||||||
|
BLUE_FLAG = 2,
|
||||||
|
BLACK_FLAG = 3,
|
||||||
|
CHECKERED_FLAG = 4,
|
||||||
|
} __attribute__((packed)) flag;
|
||||||
|
|
||||||
|
typedef struct carAtributes {
|
||||||
|
// Related to ACSP_CAR_INFO
|
||||||
|
u_char isConnected; // 1 = connected, 0 = disconnected
|
||||||
|
u_char isLoading; // 1 = loading, 0 = not isLoading
|
||||||
|
|
||||||
|
char *car_model;
|
||||||
|
char *car_skin;
|
||||||
|
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;
|
||||||
|
u_int32_t lap_time;
|
||||||
|
u_int32_t cuts;
|
||||||
|
u_int32_t total_cuts;
|
||||||
|
u_int32_t total_cuts_alltime;
|
||||||
|
u_int16_t total_laps_completed;
|
||||||
|
u_int16_t contacts;
|
||||||
|
u_int16_t total_contacts;
|
||||||
|
|
||||||
|
flag current_flag; // TODO: implement flag status updates
|
||||||
|
// TAG:3
|
||||||
|
|
||||||
|
float normalizedSplinePos;
|
||||||
|
} __attribute__((packed)) carAtributes;
|
||||||
|
|
||||||
|
typedef struct carAtributesAPI {
|
||||||
|
// Related to ACSP_CAR_INFO
|
||||||
|
u_char isConnected; // 1 = connected, 0 = disconnected
|
||||||
|
u_char isLoading; // 1 = loading, 0 = not isLoading
|
||||||
|
|
||||||
|
char car_model[64];
|
||||||
|
char car_skin[64];
|
||||||
|
char driver_name[64];
|
||||||
|
char driver_team[64];
|
||||||
|
char driver_GUID[64];
|
||||||
|
|
||||||
|
// Related to ACSP_CAR_UPDATE
|
||||||
|
u_int8_t carID;
|
||||||
|
postion position;
|
||||||
|
postion velocity;
|
||||||
|
u_int8_t carGear;
|
||||||
|
u_int16_t carRPM;
|
||||||
|
u_int32_t lap_time;
|
||||||
|
u_int32_t cuts;
|
||||||
|
u_int32_t total_cuts;
|
||||||
|
u_int32_t total_cuts_alltime;
|
||||||
|
u_int16_t total_laps_completed;
|
||||||
|
u_int16_t contacts;
|
||||||
|
u_int16_t total_contacts;
|
||||||
|
|
||||||
|
flag current_flag; // TODO: implement flag status updates
|
||||||
|
// TAG:3
|
||||||
|
|
||||||
|
float normalizedSplinePos;
|
||||||
|
} __attribute__((packed)) carAtributesAPI;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum SessionType {
|
||||||
|
PRACTICE = 0,
|
||||||
|
RACE = 1,
|
||||||
|
QUALIFYING = 2,
|
||||||
|
} __attribute__((packed)) SessionType;
|
||||||
|
|
||||||
|
typedef struct trackAtributes {
|
||||||
|
u_int8_t protocol_version;
|
||||||
|
|
||||||
|
u_int8_t session_index;
|
||||||
|
u_int8_t current_session_index;
|
||||||
|
u_int8_t session_count;
|
||||||
|
SessionType session_type;
|
||||||
|
|
||||||
|
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;
|
||||||
|
u_int32_t elapsed_ms;
|
||||||
|
} __attribute__((packed)) trackAtributes;
|
||||||
|
|
||||||
|
typedef struct trackAtributesAPI {
|
||||||
|
u_int8_t protocol_version;
|
||||||
|
|
||||||
|
u_int8_t session_index;
|
||||||
|
u_int8_t current_session_index;
|
||||||
|
u_int8_t session_count;
|
||||||
|
SessionType session_type;
|
||||||
|
|
||||||
|
char server_name[128];
|
||||||
|
char track[64];
|
||||||
|
char track_config[64];
|
||||||
|
char session_name[64];
|
||||||
|
|
||||||
|
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[64];
|
||||||
|
u_int32_t elapsed_ms;
|
||||||
|
} __attribute__((packed)) trackAtributesAPI;
|
||||||
|
|
||||||
|
typedef struct api_packet {
|
||||||
|
u_int8_t tracker_id;
|
||||||
|
u_int8_t last_updated_carid;
|
||||||
|
u_int8_t connected_cars;
|
||||||
|
|
||||||
|
carAtributesAPI cars[64];
|
||||||
|
trackAtributesAPI track_info;
|
||||||
|
|
||||||
|
} __attribute__((packed)) api_packet;
|
||||||
|
|
||||||
|
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
|
||||||
48
include/stack.cpp
Normal file
48
include/stack.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "stack.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
Stack::Stack(size_t size) {
|
||||||
|
capacity = size;
|
||||||
|
data = new api_packet[capacity];
|
||||||
|
top = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack::~Stack() {
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stack::isEmpty() {
|
||||||
|
return top == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stack::isFull() {
|
||||||
|
return top == capacity - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stack::push(const api_packet &item) {
|
||||||
|
if (isFull()) {
|
||||||
|
return false; // Stack overflow
|
||||||
|
}
|
||||||
|
data[++top] = item;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stack::pop(api_packet &item) {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return false; // Stack underflow
|
||||||
|
}
|
||||||
|
item = data[top--];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Stack::peek(api_packet &item) {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return false; // Stack is empty
|
||||||
|
}
|
||||||
|
item = data[top];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Stack::size() {
|
||||||
|
return top + 1;
|
||||||
|
}
|
||||||
25
include/stack.h
Normal file
25
include/stack.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef STACK_H
|
||||||
|
#define STACK_H // STACK_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "server_structs.h"
|
||||||
|
|
||||||
|
class Stack {
|
||||||
|
private:
|
||||||
|
api_packet *data;
|
||||||
|
size_t capacity;
|
||||||
|
int top;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Stack(size_t size);
|
||||||
|
~Stack();
|
||||||
|
bool isEmpty();
|
||||||
|
bool isFull();
|
||||||
|
bool push(const api_packet &item);
|
||||||
|
bool pop(api_packet &item);
|
||||||
|
bool peek(api_packet &item);
|
||||||
|
size_t size();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STACK_H
|
||||||
262
source/main.cpp
262
source/main.cpp
@ -1,7 +1,257 @@
|
|||||||
#include <iostream>
|
#include <cstdlib>
|
||||||
|
#include <libpq-fe.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
int main()
|
// SERVER STRUCTS
|
||||||
{
|
#include "server_structs.h"
|
||||||
std::cout << "Hello, World!" << std::endl;
|
#include "stack.h"
|
||||||
return 0;
|
|
||||||
}
|
#define SERVER_SOCKET_PATH "/tmp/ACplayer_socket"
|
||||||
|
|
||||||
|
const int STACK_SIZE = 512;
|
||||||
|
|
||||||
|
Stack api_queue(STACK_SIZE);
|
||||||
|
|
||||||
|
void checkConn(PGconn *conn) {
|
||||||
|
if (PQstatus(conn) != CONNECTION_OK) {
|
||||||
|
fprintf(stderr, "[!] Connection to database failed: %s", PQerrorMessage(conn));
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *db_write_thread(void *arg) {
|
||||||
|
|
||||||
|
(void)arg; // Unused parameter
|
||||||
|
|
||||||
|
const char *conninfo = "host=localhost port=5432 dbname=acservers_players user=admin password=123wer789";
|
||||||
|
PGconn *conn = PQconnectdb(conninfo);
|
||||||
|
|
||||||
|
checkConn(conn);
|
||||||
|
if (PQstatus(conn) == CONNECTION_OK) {
|
||||||
|
printf("[+] Database connection established successfully.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
api_packet packet;
|
||||||
|
|
||||||
|
if (api_queue.pop(packet)) {
|
||||||
|
|
||||||
|
printf("[W] Writing packet for Server with tracker ID: %d to database.\tQueue: %u/%d\n", packet.tracker_id, (unsigned int)api_queue.size(), STACK_SIZE);
|
||||||
|
|
||||||
|
const char *query = "INSERT INTO servers ("
|
||||||
|
"server_id, server_name, session_type, session_count, server_track, "
|
||||||
|
"server_config, server_weather_graphics, typ, session_time, session_laps, "
|
||||||
|
"session_wait_time, session_ambient_temp, session_road_temp, session_elapsed_time, connected_players"
|
||||||
|
") "
|
||||||
|
"VALUES ($1, $2, $4, $3, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) "
|
||||||
|
"ON CONFLICT (server_id) DO UPDATE SET "
|
||||||
|
"session_type = EXCLUDED.session_type, "
|
||||||
|
"session_count = EXCLUDED.session_count, "
|
||||||
|
"server_track = EXCLUDED.server_track, "
|
||||||
|
"server_config = EXCLUDED.server_config, "
|
||||||
|
"server_weather_graphics = EXCLUDED.server_weather_graphics, "
|
||||||
|
"typ = EXCLUDED.typ, "
|
||||||
|
"session_time = EXCLUDED.session_time, "
|
||||||
|
"session_laps = EXCLUDED.session_laps, "
|
||||||
|
"session_wait_time = EXCLUDED.session_wait_time, "
|
||||||
|
"session_ambient_temp = EXCLUDED.session_ambient_temp, "
|
||||||
|
"session_road_temp = EXCLUDED.session_road_temp, "
|
||||||
|
"session_elapsed_time = EXCLUDED.session_elapsed_time, "
|
||||||
|
"connected_players = EXCLUDED.connected_players "
|
||||||
|
"RETURNING server_id;";
|
||||||
|
|
||||||
|
const char *server_name = packet.track_info.server_name;
|
||||||
|
const char *server_track = packet.track_info.track;
|
||||||
|
const char *server_config = packet.track_info.track_config;
|
||||||
|
const char *server_weather_graphics = packet.track_info.weather_graphics;
|
||||||
|
|
||||||
|
std::string server_id_str = std::to_string(packet.tracker_id);
|
||||||
|
std::string session_count_s = std::to_string(packet.track_info.session_count);
|
||||||
|
std::string session_type_s = std::to_string(packet.track_info.session_type);
|
||||||
|
std::string typ_s = std::to_string(packet.track_info.typ);
|
||||||
|
std::string session_time_s = std::to_string(packet.track_info.time);
|
||||||
|
std::string session_laps_s = std::to_string(packet.track_info.laps);
|
||||||
|
std::string session_wait_s = std::to_string(packet.track_info.wait_time);
|
||||||
|
std::string ambient_temp_s = std::to_string(packet.track_info.ambient_temp);
|
||||||
|
std::string road_temp_s = std::to_string(packet.track_info.road_temp);
|
||||||
|
std::string elapsed_time_s = std::to_string((u_int16_t)packet.track_info.elapsed_ms);
|
||||||
|
|
||||||
|
std::string connected_players_s = std::to_string(packet.connected_cars);
|
||||||
|
|
||||||
|
const char *paramValues[15] = {server_id_str.c_str(),
|
||||||
|
server_name,
|
||||||
|
session_count_s.c_str(),
|
||||||
|
session_type_s.c_str(),
|
||||||
|
server_track,
|
||||||
|
server_config,
|
||||||
|
server_weather_graphics,
|
||||||
|
typ_s.c_str(),
|
||||||
|
session_time_s.c_str(),
|
||||||
|
session_laps_s.c_str(),
|
||||||
|
session_wait_s.c_str(),
|
||||||
|
ambient_temp_s.c_str(),
|
||||||
|
road_temp_s.c_str(),
|
||||||
|
elapsed_time_s.c_str(),
|
||||||
|
connected_players_s.c_str()};
|
||||||
|
|
||||||
|
PGresult *res = PQexecParams(conn, query, 15, nullptr, paramValues, nullptr, nullptr, 0);
|
||||||
|
|
||||||
|
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
|
||||||
|
printf("[!] Insert failed: %s", PQerrorMessage(conn));
|
||||||
|
PQclear(res);
|
||||||
|
PQfinish(conn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time for users table insert/UPDATE
|
||||||
|
|
||||||
|
if (packet.connected_cars == 0) {
|
||||||
|
PQclear(res);
|
||||||
|
continue; // No connected cars to process
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < packet.connected_cars; i++) {
|
||||||
|
|
||||||
|
if (packet.cars[i].isConnected == 0) {
|
||||||
|
continue; // Skip disconnected cars
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *user_query = "INSERT INTO users ("
|
||||||
|
"driver_guid, driver_name, driver_team, car_model, car_skin, "
|
||||||
|
"cuts_alltime, contacts_alltime, laps_completed, is_connect, is_loading, current_server"
|
||||||
|
") "
|
||||||
|
"VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) "
|
||||||
|
"ON CONFLICT (driver_guid) DO UPDATE SET "
|
||||||
|
"driver_name = EXCLUDED.driver_name, "
|
||||||
|
"driver_team = EXCLUDED.driver_team, "
|
||||||
|
"car_model = EXCLUDED.car_model, "
|
||||||
|
"car_skin = EXCLUDED.car_skin, "
|
||||||
|
"cuts_alltime = EXCLUDED.cuts_alltime, "
|
||||||
|
"contacts_alltime = EXCLUDED.contacts_alltime, "
|
||||||
|
"laps_completed = EXCLUDED.laps_completed, "
|
||||||
|
"is_connect = EXCLUDED.is_connect, "
|
||||||
|
"is_loading = EXCLUDED.is_loading, "
|
||||||
|
"current_server = EXCLUDED.current_server;";
|
||||||
|
|
||||||
|
const char *driver_guid = packet.cars[i].driver_GUID;
|
||||||
|
const char *driver_name = packet.cars[i].driver_name;
|
||||||
|
const char *driver_team = packet.cars[i].driver_team;
|
||||||
|
const char *car_model = packet.cars[i].car_model;
|
||||||
|
const char *car_skin = packet.cars[i].car_skin;
|
||||||
|
|
||||||
|
std::string cuts_alltime_s = std::to_string(packet.cars[i].total_cuts_alltime);
|
||||||
|
std::string contacts_alltime_s = std::to_string(packet.cars[i].total_contacts);
|
||||||
|
std::string laps_completed_s = std::to_string(packet.cars[i].total_laps_completed);
|
||||||
|
std::string is_connect_s = std::to_string(packet.cars[i].isConnected);
|
||||||
|
std::string is_loading_s = std::to_string(packet.cars[i].isLoading);
|
||||||
|
std::string current_server_s = server_id_str;
|
||||||
|
|
||||||
|
const char *user_paramValues[11] = {driver_guid,
|
||||||
|
driver_name,
|
||||||
|
driver_team,
|
||||||
|
car_model,
|
||||||
|
car_skin,
|
||||||
|
cuts_alltime_s.c_str(),
|
||||||
|
contacts_alltime_s.c_str(),
|
||||||
|
laps_completed_s.c_str(),
|
||||||
|
is_connect_s.c_str(),
|
||||||
|
is_loading_s.c_str(),
|
||||||
|
current_server_s.c_str()};
|
||||||
|
PGresult *user_res = PQexecParams(conn, user_query, 11, nullptr, user_paramValues, nullptr, nullptr, 0);
|
||||||
|
|
||||||
|
PQclear(user_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
} else {
|
||||||
|
usleep(1000); // Sleep for 1ms if no packets are available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PQfinish(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
int server_fd, client_fd;
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
socklen_t addr_len;
|
||||||
|
ssize_t n;
|
||||||
|
|
||||||
|
api_packet api_packet_storage;
|
||||||
|
|
||||||
|
// Create socket
|
||||||
|
server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (server_fd < 0) {
|
||||||
|
perror("socket");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
unlink(SERVER_SOCKET_PATH);
|
||||||
|
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strcpy(addr.sun_path, SERVER_SOCKET_PATH);
|
||||||
|
if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (listen(server_fd, 5) < 0) {
|
||||||
|
perror("listen");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start DB write db_write_thread
|
||||||
|
pthread_t db_thread;
|
||||||
|
if (pthread_create(&db_thread, NULL, db_write_thread, NULL) != 0) {
|
||||||
|
perror("pthread create");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// Detach the thread so it cleans up after itself
|
||||||
|
pthread_detach(db_thread);
|
||||||
|
|
||||||
|
printf("[+] Server listening on %s\n", SERVER_SOCKET_PATH);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
client_fd = accept(server_fd, NULL, NULL);
|
||||||
|
if (client_fd < 0) {
|
||||||
|
perror("[!] accept");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[+] Client connected\n");
|
||||||
|
|
||||||
|
while ((n = read(client_fd, &api_packet_storage, sizeof(api_packet))) > 0) {
|
||||||
|
printf("[+] Received %zd bytes\n", n);
|
||||||
|
|
||||||
|
if (api_packet_storage.tracker_id == 65) {
|
||||||
|
printf("[+] Handshake Received from server \"%s\" (%d).\n", api_packet_storage.track_info.server_name, api_packet_storage.tracker_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print info
|
||||||
|
printf("[*] Info: Tracker ID: %d (\"%s\")\tQueue: %u/%d\n", api_packet_storage.tracker_id, api_packet_storage.track_info.server_name, (unsigned int)api_queue.size(),
|
||||||
|
STACK_SIZE);
|
||||||
|
if (!api_queue.push(api_packet_storage)) {
|
||||||
|
printf("[!] API Queue full, dropping packet from Tracker ID: %d\n", api_packet_storage.tracker_id);
|
||||||
|
}
|
||||||
|
usleep(1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
perror("[!] Error on read");
|
||||||
|
else
|
||||||
|
printf("[+] Client disconnected\n");
|
||||||
|
|
||||||
|
close(client_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user