#include "game/server/ServerConnexion.h" #include "protocol/PacketDispatcher.h" #include "protocol/PacketFactory.h" #include "game/server/Server.h" #include "misc/Time.h" #include "misc/Random.h" #include #define KEEP_ALIVE_TIMEOUT 10 * 1000 // 10s namespace td{ namespace server{ /* NEVER TRUST USER INPUT */ ServerConnexion::ServerConnexion(): m_Player(0){ } ServerConnexion::ServerConnexion(network::TCPSocket& socket, std::uint8_t id) : Connexion::Connexion(&m_Dispatcher, socket), m_ID(id), m_Player(0){ Connexion::updateSocket(); } ServerConnexion::ServerConnexion(ServerConnexion&& move) : Connexion::Connexion(std::move(move)), m_Server(move.m_Server), m_ID(move.m_ID), m_KeepAlive(move.m_KeepAlive), m_Player(move.m_Player){ move.m_Server = nullptr; registerHandlers(); } void ServerConnexion::registerHandlers(){ GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLogin, this); GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this); GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this); GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this); } bool ServerConnexion::updateSocket(){ checkKeepAlive(); return Connexion::updateSocket(); } void ServerConnexion::checkKeepAlive(){ std::uint64_t time = utils::getTime(); if (time - m_KeepAlive.sendTime > KEEP_ALIVE_TIMEOUT){ if (m_KeepAlive.recievedResponse){ sendKeepAlive(); } else{ protocol::DisconnectPacket packet("Time out"); sendPacket(&packet); closeConnection(); } } } void ServerConnexion::sendKeepAlive(){ m_KeepAlive.keepAliveID = utils::getRandomNumber(UINT64_MAX); m_KeepAlive.recievedResponse = false; protocol::KeepAlivePacket keepAlivePacket(m_KeepAlive.keepAliveID); sendPacket(&keepAlivePacket); std::uint64_t time = utils::getTime(); m_KeepAlive.sendTime = time; } void ServerConnexion::HandlePacket(protocol::PlayerLoginPacket* packet){ if (m_Player->getName().empty() && !packet->getPlayerName().empty()){ m_Player->setName(packet->getPlayerName()); protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->getName()); m_Server->broadcastPacket(&joinPacket); std::map playerNames; for (const auto& pair : m_Server->getPlayers()){ const game::Player& player = pair.second; if (!player.getName().empty()){ protocol::PlayerInfo playerInfo; playerInfo.name = player.getName(); playerInfo.team = player.getTeamColor(); playerNames.insert({player.getID(), playerInfo}); } } protocol::PlayerListPacket listPacket(playerNames); sendPacket(&listPacket); } } void ServerConnexion::HandlePacket(protocol::SelectTeamPacket* packet){ if(m_Server->getGame().getGameState() != game::GameState::Lobby) return; if((std::int8_t) packet->getSelectedTeam() >= -1 || (std::int8_t) packet->getSelectedTeam() <= 1){ //m_Player->setTeamColor(packet->getSelectedTeam()); if(m_Player->getTeamColor() == game::TeamColor::None){ //join a team m_Server->getGame().getTeam(packet->getSelectedTeam()).addPlayer(m_Player); }else if(packet->getSelectedTeam() == game::TeamColor::None){ // leave a team m_Server->getGame().getTeam(m_Player->getTeamColor()).removePlayer(m_Player); m_Player->setTeamColor(game::TeamColor::None); }else{ // change team m_Server->getGame().getTeam(m_Player->getTeamColor()).removePlayer(m_Player); m_Server->getGame().getTeam(packet->getSelectedTeam()).addPlayer(m_Player); } protocol::UpdatePlayerTeamPacket updateTeamPacket(m_ID, packet->getSelectedTeam()); m_Server->broadcastPacket(&updateTeamPacket); } } void ServerConnexion::HandlePacket(protocol::KeepAlivePacket* packet){ if(packet->getAliveID() == m_KeepAlive.keepAliveID) m_KeepAlive.recievedResponse = true; } void ServerConnexion::HandlePacket(protocol::DisconnectPacket* packet){ closeConnection(); } void ServerConnexion::setServer(Server* server){ m_Server = server; m_Player = &m_Server->getPlayers().at(m_ID); initConnection(); sendKeepAlive(); } void ServerConnexion::initConnection(){ protocol::UpdateGameStatePacket statePacket(m_Server->getGame().getGameState()); sendPacket(&statePacket); protocol::ConnexionInfoPacket conPacket(m_ID); sendPacket(&conPacket); if (m_Server->getGame().getGameState() == game::GameState::Game){ protocol::WorldBeginDataPacket headerDataPacket(m_Server->getGame().getWorld()); protocol::WorldBeginDataPacket dataPacket(m_Server->getGame().getWorld()); sendPacket(&headerDataPacket); sendPacket(&dataPacket); } } ServerConnexion::~ServerConnexion(){ if (GetDispatcher() != nullptr) GetDispatcher()->UnregisterHandler(this); } } // namespace server } // namespace td