Files
EHS/src/io/socket/EHC.cpp

381 lines
7.6 KiB
C++

#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<NetEnc *> &&)sock.encryptions), servers((Array<NetServerCh *> &&)sock.servers),
clients((Array<NetClientCh *> &&)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<NetEnc *> &&)sock.encryptions;
for (UInt_64 i = 0; i < servers.Size(); i++)
delete servers[i];
servers = (Array<NetServerCh *> &&)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<NetClientCh *> &&)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<UInt_64> payload(Endianness::LE, buffer, received);
Version remoteVer = payload.ReadVersion();
if (remoteVer != version)
continue;
UInt_64 encId = payload.Read<UInt_64>();
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());
}
}