11 #include <gpcm/client.h>
15 #include <atomizes.hpp>
16 #include <service/file_system.h>
18 #include <webserver/client.h>
20 typedef void (
Webserver::Client::*RequestActionFunc)(
const atomizes::HTTPMessage&,
const std::string&,
const Util::Url::Variables&);
22 static std::map<std::string, RequestActionFunc> mRequestActions =
171 std::vector<char> buffer(4096, 0);
172 atomizes::HTTPMessageParser http_parser;
173 atomizes::HTTPMessage http_request;
176 int recv_size = read(this->_socket, &(buffer[0]), 4096);
187 buffer.resize(recv_size);
189 this->UpdateLastRecievedTime();
192 http_parser.Parse(&http_request, &(buffer[0]));
195 this->onRequest(http_request);
214 Json::StreamWriterBuilder writer;
215 std::string jsonString = Json::writeString(writer, value);
218 atomizes::HTTPMessage http_response = this->_defaultResponseHeader();
219 http_response.SetStatusCode(200);
220 http_response.SetMessageBody(jsonString);
225 this->Send(http_response);
232 if(http_request.GetMethod() == atomizes::MessageMethod::GET)
234 std::string url_base;
235 Util::Url::Variables url_variables;
237 this->_LogTransaction(
"-->", http_request.GetPath());
240 Util::Url::GetElements(http_request.GetPath(), url_base, url_variables);
242 auto it = mRequestActions.find(url_base);
243 if (it != mRequestActions.end())
246 RequestActionFunc func = it->second;
249 (this->*(func))(http_request, url_base, url_variables);
253 Logger::warning(
"action \"" + url_base +
"\" not implemented!", Server::Type::Webserver);
259 const Util::Url::Variables& url_variables)
261 this->_SendFile(
"../data" + url_base);
265 const Util::Url::Variables& url_variables)
267 atomizes::HTTPMessage http_response = this->_defaultResponseHeader();
269 http_response.SetStatusCode(200);
270 http_response.SetMessageBody(
"\r\n");
272 this->Send(http_response);
274 this->_LogTransaction(
"<--",
"HTTP/1.1 200 OK");
278 const Util::Url::Variables& url_variables)
280 this->_SendFile(
"../data/meme/index.html");
287 std::shared_lock<std::shared_mutex> guard(g_settings_mutex);
294 bool show_console = (g_settings[
"webserver"][
"show_requests"].asBool() && direction ==
"-->") ||
295 (g_settings[
"webserver"][
"show_responses"].asBool() && direction ==
"<--");
297 Logger::info(this->GetAddress() +
" " + direction +
" " + response,
298 Server::Type::Webserver, show_console);
303 atomizes::HTTPMessage http_response;
305 http_response.SetHeader(
"Server",
"BF2MC-Matchmaker");
306 http_response.SetHeader(
"Accept-Ranges",
"bytes");
309 http_response.SetHeader(
"Content-Type",
"text/plain");
311 return http_response;
316 bool finished =
false;
319 if(g_file_system->
GetFile(file_name, data))
332 input.open(file_name, std::ifstream::in | std::ifstream::binary);
336 data.append((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
345 Logger::error(file_name);
356 atomizes::HTTPMessage http_response = this->_defaultResponseHeader(
false);
358 if(this->_readFile(file_name, data) && data.size() != 0)
360 http_response.SetStatusCode(200);
361 http_response.SetMessageBody(data);
365 http_response.SetStatusCode(404);
366 http_response.SetMessageBody(
"\r\n");
369 this->Send(http_response);
371 this->_LogTransaction(
"<--",
"HTTP/1.1 200 OK");
378 auto it = url_variables.find(
"authtoken");
379 if (it != url_variables.end())
381 std::string authtoken = it->second;
386 if(session.profileid != -1)
389 player.SetProfileId(session.profileid);
397 const Util::Url::Variables &url_variables,
bool is_update)
399 for(
const auto &url_variable : url_variables)
401 std::string key = url_variable.first;
402 std::string value = Util::Url::Decode(url_variable.second);
404 if(key ==
"authtoken")
407 if(!Util::isAscii(value) || (key ==
"name" && is_update))
412 auto it = Battlefield::Clan::SetterMap.find(key);
413 if(it == Battlefield::Clan::SetterMap.end() || (clan.*(it->second))(value))
430 std::this_thread::sleep_for (std::chrono::seconds(60));
432 auto target_time = std::chrono::system_clock::now() - std::chrono::minutes(1);
434 for(std::shared_ptr<Net::Socket> client : g_webserver_server->
GetClients())
436 auto last_recieved = client.get()->GetLastRecievedTime();
438 if (last_recieved <= target_time)
440 client.get()->Close();
Represents a clan in the Battlefield game.
Represents a player with extended statistics.
bool queryClanByProfileId(Battlefield::Clan &clan, const Battlefield::Player &player)
Queries a clan by a player's profile ID.
static GPCM::Session findSessionByAuthtoken(const std::string &authtoken)
Finds a session by authentication token.
void Send(const std::string &msg) const
Sends a message over the socket.
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.
bool GetFile(const std::string &file_path, std::string &data)
Retrieves the data of a file from the File_System.
void requestAPIAdminKick(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to kick a client through the API.
void requestAPIClanSimulation(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for clan simulation through the API.
void requestLeaderboard(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to get the leaderboard.
static void Heartbeat()
Heartbeat function to manage client connections.
void requestMeme(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for a meme.
void requestStats(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for player statistics.
void requestAPIAdminMessage(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to send a message to a client through the API.
void requestAPIPlayer(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for a specific player through the API.
Client(int socket, struct sockaddr_in address)
Constructor for Webserver Client.
atomizes::HTTPMessage _defaultResponseHeader(bool isPlainText=true) const
Generate the default HTTP response header.
void onRequest(const atomizes::HTTPMessage &http_request)
Process incoming HTTP request.
void _GetSessionPlayerAndClan(const Util::Url::Variables &url_variables, Battlefield::Clan &clan, Battlefield::Player &player) const
Extract session, player, and clan information from URL variables.
void Disconnect()
Disconnect the client.
void requestAPILeaderboardClan(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for the clan leaderboard through the API.
void requestClanInfo(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to get clan information.
void requestAddMember(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to add a member to a clan.
void requestChangeRank(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to change a member's rank in a clan.
void requestClanMembers(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to get clan members.
void requestAPIAdminClients(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for admin clients through the API.
void requestEmpty(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for a empty response.
void requestFile(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for a specific file.
void requestUpdateClan(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to update a clan.
void requestClanMessage(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for clan messages.
void Send(const atomizes::HTTPMessage &http_response) const
Send an HTTP response.
void requestAPIServersLive(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for live servers through the API.
void requestDeleteMember(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to delete a member from a clan.
void requestAPIGame(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for a specific game through the API.
void _LogTransaction(const std::string &direction, const std::string &response) const
Log a transaction.
void Listen()
Start listening for incoming requests.
void _SendFile(const std::string &file_name) const
Send a file as an HTTP response.
void requestCreateClan(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to create a new clan.
bool _readFile(const std::string &file_name, std::string &data) const
Read a file and store its contents in a string.
bool _updateClanInformation(Battlefield::Clan &clan, const Util::Url::Variables &url_variables, bool is_update=false)
Update clan information based on URL variables.
void requestDisband(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to disband a clan.
~Client()
Destructor for Webserver Client.
void requestAPIClan(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for a specific clan through the API.
void requestAPILeaderboard(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for the leaderboard through the API.
void requestGetPlayerInfo(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to get player information.
void requestAPIGames(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for multiple games through the API.
void requestAPIAdminPlayerStatsRecalc(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handles the API request to recalculate player statistics.
Represents a session with a GPCM client.