12 #include <battlefield/player.h>
13 #include <battlefield/gamestat.h>
15 #include <gamestats/client.h>
19 static std::map<std::string, RequestActionFunc> mRequestActions =
41 bool isDisconnected =
false;
44 this->requestChallenge();
46 while(!isDisconnected)
48 std::vector<unsigned char> combined_buffer;
49 std::string last_seven_chars =
"";
53 std::vector<unsigned char> buffer(16384, 0);
55 int v = read(this->_socket, &(buffer[0]), 16384);
60 isDisconnected =
true;
67 this->UpdateLastRecievedTime();
77 combined_buffer.insert(combined_buffer.end(), buffer.begin(), buffer.end());
79 if(combined_buffer.size() > 7)
81 last_seven_chars.assign(combined_buffer.end() - 7, combined_buffer.end());
83 }
while (last_seven_chars !=
"\\final\\" && combined_buffer.size() < 32768);
85 if(combined_buffer.size() > 7)
87 std::string request = Decrypt(combined_buffer);
89 this->_LogTransaction(
"-->", request);
91 this->onRequest(request);
109 GameSpy::Parameter parameter = GameSpy::Request2Parameter(request);
112 std::string action = parameter[0];
114 auto it = mRequestActions.find(action);
115 if (it != mRequestActions.end())
118 RequestActionFunc func = it->second;
121 (this->*(func))(parameter);
125 Logger::warning(
"action \"" + action +
"\" not implemented!", Server::Type::GameStats);
138 std::string challenge = Util::generateRandomChallenge();
140 Logger::info(this->GetAddress() +
" --> Challenge", Server::Type::GameStats);
142 std::string response = GameSpy::Parameter2Response({
144 "challenge", challenge,
149 this->Send(Encrypt(response));
151 this->_LogTransaction(
"<--", response);
163 Logger::info(this->GetAddress() +
" --> Auth", Server::Type::GameStats);
165 std::string response = GameSpy::Parameter2Response({
167 "sesskey",
"1687554231",
173 this->Send(Encrypt(response));
175 this->_LogTransaction(
"<--", response);
185 Logger::info(this->GetAddress() +
" --> NewGame", Server::Type::GameStats);
208 std::string key, value;
213 game_server.SetIp(this->GetIP());
218 if(!game_server.isVerified())
220 Logger::warning(
"Server is not verified. Go to the database and verify the server.");
224 Logger::info(this->GetAddress() +
" --> UpdateGame", Server::Type::GameStats);
227 while(parameter.size() > offset + 1)
229 key = parameter[offset];
230 value = parameter[offset + 1];
232 if (key.find(
"auth_") != std::string::npos)
236 auto it = Battlefield::GameStat::SetterMap.find(key);
237 if (it != Battlefield::GameStat::SetterMap.end()) {
238 (game_stat.*(it->second))(value);
252 while(parameter.size() > offset + 1)
258 this->_GetKeyAndPlayerIndex(parameter[offset], key, player_index);
261 int previous_player_index = player_index;
266 while(parameter.size() > offset + 1)
269 this->_GetKeyAndPlayerIndex(parameter[offset], key, player_index);
272 value = parameter[offset + 1];
275 if (previous_player_index != player_index)
279 auto it = Battlefield::GameStatPlayer::SetterMap.find(key);
280 if (it != Battlefield::GameStatPlayer::SetterMap.end()) {
281 (gsplayer.*(it->second))(value);
290 game_stat.AddPlayer(gsplayer);
293 previous_player_index = player_index;
303 gsplayer.UpdatePlayerStats(game_stat);
310 if(game_stat.GetTeam1ClanId() != 0 && game_stat.GetTeam2ClanId() != 0)
312 game_stat.UpdateClanStats();
322 std::shared_lock<std::shared_mutex> guard2(g_settings_mutex);
324 if ((g_logger_mode & Logger::Mode::Development) == 0)
329 bool show_console = (g_settings[
"gamestats"][
"show_requests"].asBool() && direction ==
"-->") ||
330 (g_settings[
"gamestats"][
"show_responses"].asBool() && direction ==
"<--");
332 Logger::info(this->GetAddress() +
" " + direction +
" " + response,
333 Server::Type::GameStats, show_console);
341 size_t pos = input.rfind(
'_');
342 if (pos == std::string::npos)
349 key = input.substr(0, pos);
350 player_index = std::stoi(input.substr(pos + 1));
368 std::this_thread::sleep_for (std::chrono::seconds(60));
370 for(std::shared_ptr<Net::Socket> client : g_gamestats_server->
GetClients())
372 std::shared_ptr<GameStats::Client> gamestats_client = std::dynamic_pointer_cast<GameStats::Client>(client);
374 std::string response = GameSpy::Parameter2Response({
379 gamestats_client.get()->Send(Encrypt(response));
381 gamestats_client.get()->_LogTransaction(
"<--", response);
389 const char key[10] =
"GameSpy3D";
391 for(
int i = 0; i < static_cast<int>(request.size()) - 7; i++)
393 char v = key[(i % 9)] ^ request[i];
395 if(v > 0x20 && v < 0x7F)
408 std::vector<unsigned char> enc_response;
409 const char key[10] =
"GameSpy3D";
411 for(
int i = 0; i < response.size() - 7; i++)
413 enc_response.push_back(key[(i % 9)] ^ response[i]);
417 enc_response.push_back(0x5c);
418 enc_response.push_back(0x66);
419 enc_response.push_back(0x69);
420 enc_response.push_back(0x6e);
421 enc_response.push_back(0x61);
422 enc_response.push_back(0x6c);
423 enc_response.push_back(0x5c);
Class representing game server information.
Represents a player's statistics in a game.
Represents game statistics.
bool queryGameServerByIp(Battlefield::GameServer &game_server)
Queries a game server by its IP address.
bool insertGameStat(Battlefield::GameStat &game_stat)
Inserts a game statistic into the database.
bool createLeaderboards()
Creates leaderboard tables with ranked players.
Represents a client for game statistics.
~Client()
Destructor for Game Statistics Client.
void requestUpdateGame(const GameSpy::Parameter ¶meter)
Request to update an existing game with provided parameters.
void onRequest(const std::string &request)
Handle incoming requests from the client.
void Listen()
Start listening for client requests.
static std::vector< unsigned char > Encrypt(const std::string &response)
Encrypts a response message.
void Disconnect()
Disconnect the client.
static void Heartbeat()
Heartbeat function to manage client connections.
void requestAuth(const GameSpy::Parameter ¶meter)
Request authentication with provided parameters.
void _LogTransaction(const std::string &direction, const std::string &response) const
Log a transaction with direction and response.
void requestNewGame(const GameSpy::Parameter ¶meter)
Request to create a new game with provided parameters.
static std::string Decrypt(const std::vector< unsigned char > &request)
Decrypts a request message.
void requestChallenge()
Request a challenge from the client.
Client(int socket, struct sockaddr_in address)
Constructor for Game Statistics Client.
bool _GetKeyAndPlayerIndex(const std::string &input, std::string &key, int &player_index)
Get the key and the player index from string input.
void UpdateLastRecievedTime()
Updates the last received time to the current system time.
struct sockaddr_in _address
std::vector< std::shared_ptr< Net::Socket > > GetClients()
Get the vector of client sockets connected to this server.
void onClientDisconnect(const Net::Socket &client)
Called when a client disconnects from the server.