fully implement KeepAlive behavior
This commit is contained in:
70
src/server/Server.cpp
Normal file
70
src/server/Server.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <server/Server.h>
|
||||
|
||||
#include <server/components/EnetConnection.h>
|
||||
#include <server/components/KeepAliveSession.h>
|
||||
#include <server/handlers/KeepAliveHandler.h>
|
||||
#include <server/systems/DisconnectSystem.h>
|
||||
#include <server/systems/KeepAliveSystem.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
Server::Server(std::uint16_t a_Port, std::shared_ptr<Nz::EnttWorld> a_World) : m_NetworkServer(a_Port) {
|
||||
m_World.store(a_World);
|
||||
RegisterSystems();
|
||||
m_NetworkServer.OnClientConnect.Connect(this, &Server::HandleConnect);
|
||||
m_NetworkServer.OnClientDisconnect.Connect(this, &Server::HandleDisconnect);
|
||||
m_NetworkServer.OnClientDisconnectTimeout.Connect(this, &Server::HandleDisconnect);
|
||||
}
|
||||
|
||||
Server::~Server() {}
|
||||
|
||||
void Server::HandleConnect(network::EnetConnection& a_Connection) {
|
||||
Session newSession;
|
||||
newSession.m_Connection = &a_Connection;
|
||||
|
||||
RegisterHandlers(newSession);
|
||||
|
||||
m_Sessions.insert({a_Connection.GetPeerId(), std::move(newSession)});
|
||||
|
||||
CreateEntity(a_Connection);
|
||||
}
|
||||
|
||||
void Server::HandleDisconnect(network::EnetConnection& a_Connection) {
|
||||
m_Sessions.erase(a_Connection.GetPeerId());
|
||||
}
|
||||
|
||||
void Server::CreateEntity(network::EnetConnection& a_Connection) {
|
||||
auto world = m_World.load();
|
||||
|
||||
auto entity = world->CreateEntity();
|
||||
|
||||
entity.emplace<KeepAliveSessionComponent>(a_Connection.GetPeerId(), 69, Nz::GetElapsedMilliseconds(), true);
|
||||
entity.emplace<EnetConnectionComponent>(&a_Connection);
|
||||
}
|
||||
|
||||
void Server::RegisterSystems() {
|
||||
auto world = m_World.load();
|
||||
world->AddSystem<KeepAliveSystem>();
|
||||
world->AddSystem<DisconectSystem>(*this);
|
||||
}
|
||||
|
||||
void Server::RegisterHandlers(Session& session) {
|
||||
session.m_Handlers.push_back(std::make_unique<KeepAliveHandler>(*session.m_Connection, m_World));
|
||||
}
|
||||
|
||||
network::EnetConnection* Server::GetConnection(std::uint16_t a_PeerId) {
|
||||
auto it = m_Sessions.find(a_PeerId);
|
||||
|
||||
if (it == m_Sessions.end())
|
||||
return nullptr;
|
||||
|
||||
return it->second.m_Connection;
|
||||
}
|
||||
|
||||
void Server::CloseConnection(std::uint16_t a_PeerId) {
|
||||
m_NetworkServer.CloseConnection(a_PeerId);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
29
src/server/handlers/KeepAliveHandler.cpp
Normal file
29
src/server/handlers/KeepAliveHandler.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <server/handlers/KeepAliveHandler.h>
|
||||
|
||||
#include <server/components/KeepAliveSession.h>
|
||||
|
||||
#include <Nazara/Core/Time.hpp>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
KeepAliveHandler::KeepAliveHandler(network::EnetConnection& a_Connection, EnttWorld& a_World) :
|
||||
protocol::PacketHandler(a_Connection, a_World) {
|
||||
m_Slot.Connect(a_Connection.OnKeepAlive,
|
||||
[this](const protocol::data::KeepAlive& a_KeepAlive) { Handle(m_Connection.GetPeerId(), a_KeepAlive); });
|
||||
}
|
||||
|
||||
KeepAliveHandler::~KeepAliveHandler() {}
|
||||
|
||||
void KeepAliveHandler::Handle(std::uint16_t a_PeerId, const protocol::data::KeepAlive& a_KeepAlive) {
|
||||
auto world = m_World.load();
|
||||
world->GetRegistry().view<KeepAliveSessionComponent>().each([a_PeerId, &a_KeepAlive](auto& keepAliveSession) {
|
||||
if (keepAliveSession.m_PeerId == a_PeerId && keepAliveSession.m_LastKeepAliveId == a_KeepAlive.m_KeepAliveId) {
|
||||
keepAliveSession.m_LastTime = Nz::GetElapsedMilliseconds();
|
||||
keepAliveSession.m_RecievedResponse = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
25
src/server/systems/DisconnectSystem.cpp
Normal file
25
src/server/systems/DisconnectSystem.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <server/systems/DisconnectSystem.h>
|
||||
|
||||
#include <server/components/Disconnect.h>
|
||||
#include <server/components/EnetConnection.h>
|
||||
|
||||
#include <server/Server.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
DisconectSystem::DisconectSystem(entt::registry& a_Registry, Server& a_Server) : m_Registry(a_Registry), m_Server(a_Server) {}
|
||||
|
||||
void DisconectSystem::Update(Nz::Time elapsedTime) {
|
||||
m_Registry.view<EnetConnectionComponent, DisconnectComponent>().each(
|
||||
[this](auto entity, EnetConnectionComponent& connection, DisconnectComponent disconnect) {
|
||||
m_Server.CloseConnection(connection.m_Connection->GetPeerId());
|
||||
});
|
||||
|
||||
// remove the entities
|
||||
auto it = m_Registry.view<DisconnectComponent>();
|
||||
m_Registry.destroy(it.begin(), it.end());
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
38
src/server/systems/KeepAliveSystem.cpp
Normal file
38
src/server/systems/KeepAliveSystem.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <server/systems/KeepAliveSystem.h>
|
||||
|
||||
#include <server/components/Disconnect.h>
|
||||
#include <server/components/EnetConnection.h>
|
||||
#include <server/components/KeepAliveSession.h>
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
KeepAliveSystem::KeepAliveSystem(entt::registry& a_Registry) : m_Registry(a_Registry) {}
|
||||
|
||||
void KeepAliveSystem::Update(Nz::Time elapsedTime) {
|
||||
m_Registry.view<KeepAliveSessionComponent, EnetConnectionComponent>().each(
|
||||
[this](auto entity, auto& keepAliveSession, auto& connection) {
|
||||
auto duration = Nz::GetElapsedMilliseconds() - keepAliveSession.m_LastTime;
|
||||
if (duration > Nz::Time::Seconds(10)) {
|
||||
if (keepAliveSession.m_RecievedResponse) {
|
||||
keepAliveSession.m_RecievedResponse = false;
|
||||
keepAliveSession.m_LastTime = Nz::GetElapsedMilliseconds();
|
||||
|
||||
std::random_device rd;
|
||||
std::uniform_int_distribution<std::uint64_t> dis(0, std::numeric_limits<std::uint64_t>::max());
|
||||
std::uint64_t keepAliveId = dis(rd);
|
||||
|
||||
keepAliveSession.m_LastKeepAliveId = keepAliveId;
|
||||
connection.m_Connection->SendKeepAlive({keepAliveId});
|
||||
} else {
|
||||
// We kick the player because he's not responding anymore
|
||||
m_Registry.emplace<DisconnectComponent>(entity);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
Reference in New Issue
Block a user