#include "ehs/io/socket/EHC.h" #include "ehs/io/socket/ehc/NetEnc.h" #include "ehs/io/socket/ehc/NetServerCh.h" #include "ehs/io/socket/ehc/NetClientCh.h" #include "ehs/io/socket/ehc/NetSys.h" #include "ehs/io/socket/ehc/NetEnd.h" #include "ehs/PRNG.h" namespace ehs { const Version EHC::version(1, 0, 0); EHC::~EHC() { Release(); } EHC::EHC(const IP version) : udp(version), buffer(nullptr), bufferSize(0), lastTSC(0), delta(0.0f) { } EHC::EHC(EHC &&sock) noexcept : udp((UDP&&)sock.udp), buffer(sock.buffer), bufferSize(sock.bufferSize), lastTSC(sock.lastTSC), delta(sock.delta), encryptions((Array &&)sock.encryptions), servers((Array &&)sock.servers), clients((Array &&)sock.clients) { for (UInt_64 i = 0; i < servers.Size(); i++) servers[i]->owner = this; for (UInt_64 i = 0; i < clients.Size(); i++) clients[i]->owner = this; sock.buffer = nullptr; sock.bufferSize = 0; sock.lastTSC = 0; sock.delta = 0.0f; } EHC::EHC(const EHC &sock) : udp(sock.udp), buffer(nullptr), bufferSize(0), lastTSC(CPU::GetTSC()), delta(0.0f), encryptions(sock.encryptions), servers(sock.servers), clients(sock.clients) { for (UInt_64 i = 0; i < servers.Size(); i++) servers[i]->owner = this; for (UInt_64 i = 0; i < clients.Size(); i++) clients[i]->owner = this; Initialize(); } EHC &EHC::operator=(EHC &&sock) noexcept { if (this == &sock) return *this; udp = (UDP &&)sock.udp; delete[] buffer; buffer = sock.buffer; bufferSize = sock.bufferSize; lastTSC = sock.lastTSC; delta = sock.delta; for (UInt_64 i = 0; i < encryptions.Size(); i++) delete encryptions[i]; encryptions = (Array &&)sock.encryptions; for (UInt_64 i = 0; i < servers.Size(); i++) delete servers[i]; servers = (Array &&)sock.servers; for (UInt_64 i = 0; i < servers.Size(); i++) servers[i]->owner = this; for (UInt_64 i = 0; i < clients.Size(); i++) delete clients[i]; clients = (Array &&)sock.clients; for (UInt_64 i = 0; i < clients.Size(); i++) clients[i]->owner = this; sock.buffer = nullptr; sock.bufferSize = 0; sock.lastTSC = 0; sock.delta = 0.0f; return *this; } EHC &EHC::operator=(const EHC &sock) { if (this == &sock) return *this; udp = sock.udp; delete[] buffer; buffer = nullptr; bufferSize = 0; lastTSC = 0; delta = 0.0f; for (UInt_64 i = 0; i < encryptions.Size(); i++) delete encryptions[i]; encryptions = sock.encryptions; for (UInt_64 i = 0; i < servers.Size(); i++) delete servers[i]; servers = sock.servers; for (UInt_64 i = 0; i < servers.Size(); i++) servers[i]->owner = this; for (UInt_64 i = 0; i < clients.Size(); i++) delete clients[i]; clients = sock.clients; for (UInt_64 i = 0; i < clients.Size(); i++) clients[i]->owner = this; Initialize(); return *this; } void EHC::Initialize() { if (!udp.IsValid()) return; udp.SetBlocking(false); if (udp.GetLocalEndpoint().version == IP::V4) { buffer = new Byte[EHS_IPV4_UDP_PAYLOAD]; bufferSize = EHS_IPV4_UDP_PAYLOAD; } else if (udp.GetLocalEndpoint().version == IP::V6) { buffer = new Byte[EHS_IPV6_UDP_PAYLOAD]; bufferSize = EHS_IPV6_UDP_PAYLOAD; } } void EHC::Release() { if (!udp.IsValid()) return; delete[] buffer; buffer = nullptr; bufferSize = 0; for (UInt_64 i = 0; i < encryptions.Size(); i++) delete encryptions[i]; encryptions.Clear(); for (UInt_64 i = 0; i < servers.Size(); i++) delete servers[i]; servers.Clear(); for (UInt_64 i = 0; i < clients.Size(); i++) delete clients[i]; clients.Clear(); udp.Release(); } void EHC::Bind(const Endpoint &endpoint) { udp.Bind(endpoint); } void EHC::Poll() { if (!udp.IsValid()) return; UInt_64 newTSC = CPU::GetTSC(); delta = (float)(newTSC - lastTSC) / (float)CPU::GetTSC_Freq(); lastTSC = newTSC; Endpoint remoteEndpoint; UInt_16 received; while ((received = udp.Receive(&remoteEndpoint, buffer, bufferSize))) { Serializer payload(Endianness::LE, buffer, received); Version remoteVer = payload.ReadVersion(); if (remoteVer != version) continue; UInt_64 encId = payload.Read(); if (encId) { Version remoteEncVersion = payload.ReadVersion(); NetEnc* enc = GetEncryption(encId); if (!enc || enc->GetVersion() != remoteEncVersion) continue; enc->Decrypt(&payload[payload.GetOffset()], payload.Size() - payload.GetOffset()); } payload.SetOffset(0); Header header = ReadHeader(payload); if (!header.channelId) continue; if (header.channelType == NetChannelType::SERVER) { NetServerCh *server = GetServer(header.channelId); if (!server) continue; server->Process(delta, remoteEndpoint, header, payload); } else if (header.channelType == NetChannelType::CLIENT) { NetClientCh *client = GetClient(header.channelId); if (!client) continue; client->Process(delta, remoteEndpoint, header, payload); } } for (UInt_64 i = 0; i < servers.Size(); ++i) servers[i]->Poll(delta); for (UInt_64 i = 0; i < clients.Size(); ++i) clients[i]->Poll(delta); } bool EHC::IsInitialized() const { return udp.IsValid(); } Endpoint EHC::GetLocalEndpoint() const { return udp.GetLocalEndpoint(); } bool EHC::IsBound() const { return udp.IsBound(); } Version EHC::GetVersion() { return version; } bool EHC::AddEncryption(NetEnc* enc) { if (HasEncryption(enc->GetId())) return false; encryptions.Push(enc); return true; } bool EHC::HasServer(const UInt_64 serverId) const { for (UInt_64 i = 0; i < servers.Size(); ++i) if (servers[i]->GetId() == serverId) return true; return false; } bool EHC::HasServer(const Str_8 &serverName) const { return HasServer(serverName.Hash_64()); } bool EHC::AddServer(NetServerCh *server) { if (HasServer(server->GetId())) return false; server->owner = this; servers.Push(server); return true; } NetServerCh *EHC::GetServer(const UInt_64 serverId) const { for (UInt_64 i = 0; i < servers.Size(); ++i) if (servers[i]->GetId() == serverId) return servers[i]; return nullptr; } NetServerCh *EHC::GetServer(const Str_8 &serverName) const { return GetServer(serverName.Hash_64()); } bool EHC::HasClient(const UInt_64 clientId) const { for (UInt_64 i = 0; i < clients.Size(); ++i) if (clients[i]->GetId() == clientId) return true; return false; } bool EHC::HasClient(const Str_8 &clientName) const { return HasClient(clientName.Hash_64()); } bool EHC::AddClient(NetClientCh *client) { if (HasServer(client->GetId())) return false; client->owner = this; clients.Push(client); return true; } NetClientCh *EHC::GetClient(const UInt_64 clientId) const { for (UInt_64 i = 0; i < clients.Size(); ++i) if (clients[i]->GetId() == clientId) return clients[i]; return nullptr; } NetClientCh *EHC::GetClient(const Str_8 &clientName) const { return GetClient(clientName.Hash_64()); } bool EHC::HasEncryption(UInt_64 encId) const { for (UInt_64 i = 0; i < encryptions.Size(); ++i) if (encryptions[i]->GetId() == encId) return true; return false; } bool EHC::HasEncryption(const Str_8& encName) const { return HasEncryption(encName.Hash_64()); } NetEnc* EHC::GetEncryption(UInt_64 encId) const { for (UInt_64 i = 0; i < encryptions.Size(); ++i) if (encryptions[i]->GetId() == encId) return encryptions[i]; return nullptr; } NetEnc* EHC::GetEncryption(const Str_8& encName) const { return GetEncryption(encName.Hash_64()); } }