generated from AfonsoCMSousa/CPP-Template
527 lines
22 KiB
C++
527 lines
22 KiB
C++
#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>
|
|
|
|
// native webstocket
|
|
|
|
// SERVER STRUCTS
|
|
#include "server_structs.h"
|
|
#include "stack.h"
|
|
#include "telemetry.h"
|
|
|
|
#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 sanitize_utf8(char *str) {
|
|
if (!str)
|
|
return;
|
|
|
|
for (size_t i = 0; str[i] != '\0'; i++) {
|
|
// Replace invalid UTF-8 bytes with '?'
|
|
if ((unsigned char)str[i] > 127) {
|
|
str[i] = '?';
|
|
}
|
|
}
|
|
}
|
|
|
|
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)) {
|
|
|
|
// Check if message was Handshake
|
|
if (packet.tracker_id == 65) {
|
|
printf("[+] Handshake packet received for server \"%s\" (%d), skipping database write.\n", packet.track_info.server_name, packet.tracker_id);
|
|
continue; // Skip database write for handshake packets
|
|
}
|
|
|
|
// Check if it was a crash report
|
|
if (packet.message_type == ACSP_CE_COLLISION_WITH_ENV) {
|
|
printf("[!] Crash report packet received for server \"%s\" (%d), skipping database write.\n", packet.track_info.server_name, packet.tracker_id);
|
|
|
|
printf("[!] Single car collision detected. Car ID: %d\n", packet.cars_colided[0]);
|
|
|
|
// Get current driver_rank for the car
|
|
const char *get_rank_query = "SELECT user_rank FROM users WHERE driver_guid = $1;";
|
|
|
|
const char *driver_guid = packet.cars[packet.cars_colided[0]].driver_GUID;
|
|
const char *get_rank_paramValues[1] = {driver_guid};
|
|
|
|
PGresult *rank_res = PQexecParams(conn, get_rank_query, 1, nullptr, get_rank_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(rank_res) != PGRES_TUPLES_OK) {
|
|
printf("[!] Failed to retrieve driver rank for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
} else {
|
|
|
|
// Get driver contacts_alltime
|
|
const char *get_contacts_query = "SELECT contacts_alltime FROM users WHERE driver_guid = $1;";
|
|
PGresult *contacts_res = PQexecParams(conn, get_contacts_query, 1, nullptr, get_rank_paramValues, nullptr, nullptr, 0);
|
|
int contacts_alltime = 0;
|
|
if (PQresultStatus(contacts_res) == PGRES_TUPLES_OK) {
|
|
if (PQntuples(contacts_res) > 0) {
|
|
char *contacts_str = PQgetvalue(contacts_res, 0, 0);
|
|
contacts_alltime = atoi(contacts_str);
|
|
printf("[*] Driver contacts_alltime for GUID %s is %d\n", driver_guid, contacts_alltime);
|
|
}
|
|
} else {
|
|
printf("[!] Failed to retrieve contacts_alltime for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
}
|
|
PQclear(contacts_res);
|
|
|
|
if (PQntuples(rank_res) > 0) {
|
|
char *rank_str = PQgetvalue(rank_res, 0, 0);
|
|
int driver_rank = atoi(rank_str);
|
|
printf("[*] Driver rank for GUID %s is %d\n", driver_guid, driver_rank);
|
|
|
|
driver_rank -= 10;
|
|
if (driver_rank < 0)
|
|
driver_rank = 0;
|
|
|
|
// Update driver_rank in the database
|
|
const char *update_rank_query = "UPDATE users SET user_rank = $1, contacts_alltime = $2 WHERE driver_guid = $3;";
|
|
std::string new_rank_s = std::to_string(driver_rank);
|
|
std::string contacts_alltime_s = std::to_string(contacts_alltime + 1);
|
|
const char *update_rank_paramValues[3] = {new_rank_s.c_str(), contacts_alltime_s.c_str(), driver_guid};
|
|
|
|
PGresult *update_rank_res = PQexecParams(conn, update_rank_query, 3, nullptr, update_rank_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(update_rank_res) != PGRES_COMMAND_OK) {
|
|
printf("[!] Failed to update driver rank for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
} else {
|
|
printf("[*] Driver rank for GUID %s updated to %d\n", driver_guid, driver_rank);
|
|
}
|
|
PQclear(update_rank_res);
|
|
} else {
|
|
printf("[!] No driver found with GUID %s to retrieve rank.\n", driver_guid);
|
|
}
|
|
}
|
|
PQclear(rank_res);
|
|
continue; // Skip database write for crash report api_packet_storages
|
|
}
|
|
|
|
// Check if it was a crash report
|
|
if (packet.message_type == ACSP_CE_COLLISION_WITH_CAR) {
|
|
printf("[!] Crash report packet received for server \"%s\" (%d), skipping database write.\n", packet.track_info.server_name, packet.tracker_id);
|
|
|
|
printf("[!] Multi-car collision detected. Car IDs: %d and %d\n", packet.cars_colided[0], packet.cars_colided[1]);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
u_int8_t car_id = packet.cars_colided[i];
|
|
const char *driver_guid = packet.cars[car_id].driver_GUID;
|
|
|
|
// Get current driver_rank for the car
|
|
const char *get_rank_query = "SELECT user_rank FROM users WHERE driver_guid = $1;";
|
|
|
|
const char *get_rank_paramValues[1] = {driver_guid};
|
|
|
|
PGresult *rank_res = PQexecParams(conn, get_rank_query, 1, nullptr, get_rank_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(rank_res) != PGRES_TUPLES_OK) {
|
|
printf("[!] Failed to retrieve driver rank for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
} else {
|
|
if (PQntuples(rank_res) > 0) {
|
|
char *rank_str = PQgetvalue(rank_res, 0, 0);
|
|
int driver_rank = atoi(rank_str);
|
|
printf("[*] Driver rank for GUID %s is %d\n", driver_guid, driver_rank);
|
|
|
|
driver_rank -= 5;
|
|
if (driver_rank < 0)
|
|
driver_rank = 0;
|
|
|
|
// Update driver_rank in the database
|
|
const char *update_rank_query = "UPDATE user SET driver_rank = $1 WHERE driver_guid = $2;";
|
|
std::string new_rank_s = std::to_string(driver_rank);
|
|
const char *update_rank_paramValues[2] = {new_rank_s.c_str(), driver_guid};
|
|
|
|
PGresult *update_rank_res = PQexecParams(conn, update_rank_query, 2, nullptr, update_rank_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(update_rank_res) != PGRES_COMMAND_OK) {
|
|
printf("[!] Failed to update driver rank for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
} else {
|
|
printf("[*] Driver rank for GUID %s updated to %d\n", driver_guid, driver_rank);
|
|
}
|
|
PQclear(update_rank_res);
|
|
} else {
|
|
printf("[!] No driver found with GUID %s to retrieve rank.\n", driver_guid);
|
|
}
|
|
}
|
|
PQclear(rank_res);
|
|
}
|
|
continue; // Skip database write for crash report api_packet_storages
|
|
}
|
|
|
|
if (packet.message_type == ACSP_LAP_COMPLETED) {
|
|
printf("[+] Lap completed by (%d).\n", packet.cars_colided[0]);
|
|
|
|
const char *get_rank_query = "UPDATE users SET user_rank = user_rank + $1 WHERE driver_guid = $2;";
|
|
|
|
const char *driver_guid = packet.cars[packet.cars_colided[0]].driver_GUID;
|
|
|
|
char rank_buf[32];
|
|
|
|
// snprintf(rank_buf, sizeof(rank_buf), "%d",
|
|
// (packet.cars[packet.cars_colided[0]].total_laps_completed + 1)
|
|
// / (packet.cars[packet.cars_colided[0]].cuts + 1) * 10
|
|
// );
|
|
|
|
const char *get_rank_paramValues[2];
|
|
get_rank_paramValues[0] = "10";
|
|
get_rank_paramValues[1] = driver_guid;
|
|
|
|
|
|
PGresult *rank_res = PQexecParams(conn, get_rank_query, 2, nullptr, get_rank_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(rank_res) != PGRES_TUPLES_OK) {
|
|
printf("[!] Failed to UPDATE driver Rank for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
} else {
|
|
printf("[+] Increase driver rank\n");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// INFO: Deprecated because packet.car[ID].total_laps_completed was already being updated by the parser alone
|
|
// TAG:4 Might be useful in future for other purposes
|
|
/* if (packet.message_type == ACSP_LAP_COMPLETED) {
|
|
u_int8_t car_id = packet.cars_colided[0]; // In this case, cars_colided[0] holds the carID that completed the lap
|
|
const char *driver_guid = packet.cars[car_id].driver_GUID;
|
|
|
|
// Update laps_completed in the database
|
|
const char *update_laps_query = "UPDATE users SET laps_completed = laps_completed + 1, user_rank = user_rank + 25 WHERE driver_guid = $1;";
|
|
const char *update_laps_paramValues[1] = {driver_guid};
|
|
|
|
PGresult *update_laps_res = PQexecParams(conn, update_laps_query, 1, nullptr, update_laps_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(update_laps_res) != PGRES_COMMAND_OK) {
|
|
printf("[!] Failed to update laps completed for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
} else {
|
|
printf("[*] Laps completed updated for GUID %s\n", driver_guid);
|
|
}
|
|
PQclear(update_laps_res);
|
|
|
|
continue; // Skip database write for lap completed api_packet_storages
|
|
} */
|
|
|
|
/*
|
|
// DEBUG: OUTPUT ALL PACKET DATA
|
|
printf("[D] API Packet Data for Server \"%s\" (ID: %d):\n", packet.track_info.server_name, packet.tracker_id);
|
|
printf(" Session Type: %d\n", packet.track_info.session_type);
|
|
printf(" Session Count: %d\n", packet.track_info.session_count);
|
|
printf(" Track: %s\n", packet.track_info.track);
|
|
printf(" Config: %s\n", packet.track_info.track_config);
|
|
printf(" Weather/Graphics: %s\n", packet.track_info.weather_graphics);
|
|
printf(" Time: %d\n", packet.track_info.time);
|
|
printf(" Laps: %d\n", packet.track_info.laps);
|
|
printf(" Wait Time: %d\n", packet.track_info.wait_time);
|
|
printf(" Ambient Temp: %d\n", packet.track_info.ambient_temp);
|
|
printf(" Road Temp: %d\n", packet.track_info.road_temp);
|
|
printf(" Elapsed Time (ms): %d\n", packet.track_info.elapsed_ms);
|
|
printf(" Connected Players: %d\n", packet.connected_players);
|
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
|
if (packet.cars[i].isConnected) {
|
|
printf(" [D] Car ID: %d\n", packet.cars[i].carID);
|
|
printf(" Driver GUID: %s\n", packet.cars[i].driver_GUID);
|
|
printf(" Driver Name: %s\n", packet.cars[i].driver_name);
|
|
printf(" Driver Team: %s\n", packet.cars[i].driver_team);
|
|
printf(" Car Model: %s\n", packet.cars[i].car_model);
|
|
printf(" Car Skin: %s\n", packet.cars[i].car_skin);
|
|
printf(" Total Cuts Alltime: %d\n", packet.cars[i].total_cuts_alltime);
|
|
printf(" Total Contacts: %d\n", packet.cars[i].total_contacts);
|
|
printf(" Total Laps Completed: %d\n", packet.cars[i].total_laps_completed);
|
|
printf(" Is Connected: %d\n", packet.cars[i].isConnected);
|
|
printf(" Is Loading: %d\n", packet.cars[i].isLoading);
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
broadcast_telemetry(packet);
|
|
|
|
// DEBUG
|
|
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);
|
|
|
|
// Time for servers table insert/UPDATE
|
|
|
|
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_players);
|
|
|
|
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);
|
|
continue;
|
|
}
|
|
|
|
PQclear(res);
|
|
|
|
// Time for users table insert/UPDATE
|
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
if (packet.cars[i].isConnected == 0) {
|
|
if (packet.cars[i].driver_GUID[0] == '\0') {
|
|
continue; // Skip empty slots
|
|
}
|
|
// printf("[D] User disconnected (%d): GUID=%s, Name=%s\n", i, packet.cars[i].driver_GUID, packet.cars[i].driver_name);
|
|
// If the car is not connected, we still need to update its status in the db
|
|
const char *disconnect_query = "UPDATE users SET is_connect = false, current_server = NULL WHERE driver_guid = $1;";
|
|
const char *disconnect_paramValues[1] = {packet.cars[i].driver_GUID};
|
|
|
|
PGresult *disconnect_res = PQexecParams(conn, disconnect_query, 1, nullptr, disconnect_paramValues, nullptr, nullptr, 0);
|
|
if (PQresultStatus(disconnect_res) != PGRES_COMMAND_OK) {
|
|
printf("[!] User disconnect update failed for GUID %s: %s", packet.cars[i].driver_GUID, PQerrorMessage(conn));
|
|
}
|
|
PQclear(disconnect_res);
|
|
continue; // Skip disconnected cars
|
|
}
|
|
u_int8_t car_id = packet.cars[i].carID;
|
|
|
|
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[car_id].driver_GUID;
|
|
const char *driver_name = packet.cars[car_id].driver_name;
|
|
const char *driver_team = packet.cars[car_id].driver_team;
|
|
const char *car_model = packet.cars[car_id].car_model;
|
|
const char *car_skin = packet.cars[car_id].car_skin;
|
|
|
|
std::string cuts_alltime_s = std::to_string(packet.cars[car_id].total_cuts_alltime);
|
|
std::string contacts_alltime_s = std::to_string(packet.cars[car_id].total_contacts);
|
|
std::string laps_completed_s = std::to_string(packet.cars[car_id].total_laps_completed);
|
|
std::string is_connect_s = std::to_string(packet.cars[car_id].isConnected);
|
|
std::string is_loading_s = std::to_string(packet.cars[car_id].isLoading);
|
|
std::string current_server_s = std::to_string(packet.tracker_id);
|
|
|
|
// Debug output for user data being inserted/updated
|
|
printf("[D] Processing user \(%d\): GUID=%s, Name=%s, Team=%s Car Model=%s, Skin=%s, Cuts=%s, Contacts=%s, Laps=%s, IsConnect=%s, IsLoading=%s, CurrentServer=%s\n",
|
|
i, 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());
|
|
printf("[D] Player Position: (X: %.2f, Y: %.2f, Z: %.2f)\n", packet.cars[car_id].position.x, packet.cars[car_id].position.y, packet.cars[car_id].position.z);
|
|
|
|
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);
|
|
if (PQresultStatus(user_res) != PGRES_COMMAND_OK) {
|
|
printf("[!] User insert/update failed for GUID %s: %s", driver_guid, PQerrorMessage(conn));
|
|
PQclear(user_res);
|
|
continue; // Proceed to next user
|
|
}
|
|
|
|
PQclear(user_res);
|
|
}
|
|
|
|
} else {
|
|
usleep(1000); // Sleep for 1ms if no packets are available
|
|
}
|
|
}
|
|
|
|
PQfinish(conn);
|
|
return NULL;
|
|
}
|
|
|
|
void *handle_client(void *arg) {
|
|
int client_fd = *(int *)arg;
|
|
free(arg);
|
|
|
|
api_packet api_packet_storage;
|
|
ssize_t 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;
|
|
}
|
|
|
|
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(),
|
|
(int)api_queue.getCapacity());
|
|
|
|
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 NULL;
|
|
}
|
|
|
|
int main(void) {
|
|
|
|
int server_fd, client_fd;
|
|
struct sockaddr_un addr;
|
|
|
|
// 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;
|
|
strncpy(addr.sun_path, SERVER_SOCKET_PATH, sizeof(addr.sun_path) - 1);
|
|
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; // null-terminate just in case
|
|
|
|
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);
|
|
|
|
pthread_t telemetry_thread;
|
|
if (pthread_create(&telemetry_thread, NULL, telemetry_server_thread, NULL) != 0) {
|
|
perror("[!] Failed to create telemetry server thread");
|
|
return EXIT_FAILURE;
|
|
}
|
|
pthread_detach(telemetry_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");
|
|
|
|
int *client_fd_ptr = (int *)malloc(sizeof(int));
|
|
*client_fd_ptr = client_fd;
|
|
|
|
pthread_t client_thread;
|
|
if (pthread_create(&client_thread, NULL, handle_client, client_fd_ptr) != 0) {
|
|
perror("pthread_create");
|
|
close(client_fd);
|
|
free(client_fd_ptr);
|
|
continue;
|
|
}
|
|
|
|
pthread_detach(client_thread); // no need to join manually
|
|
}
|
|
|
|
return 0;
|
|
}
|