|
@@ -1,6 +1,7 @@
|
|
|
#include "core/Network.h"
|
|
|
|
|
|
#define ENET_IMPLEMENTATION
|
|
|
+#include <core/HashMap.h>
|
|
|
#include <core/Logger.h>
|
|
|
#include <core/Utility.h>
|
|
|
#include <enet.h>
|
|
@@ -220,7 +221,7 @@ bool coreClientStart(void) {
|
|
|
CORE_LOG_WARNING("Client already started");
|
|
|
return true;
|
|
|
} else if(addENet()) {
|
|
|
- CORE_LOG_WARNING("Client cannot initialize enet");
|
|
|
+ CORE_LOG_ERROR("Client cannot initialize enet");
|
|
|
return true;
|
|
|
}
|
|
|
client.client = enet_host_create(nullptr, 1, 2, 0, 0);
|
|
@@ -241,8 +242,8 @@ void coreClientStop(void) {
|
|
|
if(client.client != nullptr) {
|
|
|
enet_host_destroy(client.client);
|
|
|
client.client = nullptr;
|
|
|
- removeENet();
|
|
|
}
|
|
|
+ removeENet();
|
|
|
client.connectTicks = 0;
|
|
|
client.disconnectTicks = 0;
|
|
|
}
|
|
@@ -280,7 +281,7 @@ void coreClientDisconnect(int timeoutTicks) {
|
|
|
client.disconnectTimeoutTicks = timeoutTicks;
|
|
|
}
|
|
|
|
|
|
-void coreClientSend(OutPacket* p, CorePacketSendMode mode) {
|
|
|
+void coreClientSend(const OutPacket* p, CorePacketSendMode mode) {
|
|
|
if(client.client != nullptr || client.connection != nullptr ||
|
|
|
client.connectTicks >= 0) {
|
|
|
return;
|
|
@@ -361,162 +362,173 @@ bool coreClientIsConnected(void) {
|
|
|
return client.connectTicks < 0;
|
|
|
}
|
|
|
|
|
|
-/*static_assert(sizeof(enet_uint16) == sizeof(Server::Port),
|
|
|
- "client port has wrong type");
|
|
|
+static void voidClientDummy(CoreClient) {
|
|
|
+}
|
|
|
|
|
|
-static ENetHost* server;
|
|
|
-static HashMap<Server::Client, ENetPeer*> clients;
|
|
|
-static Server::Client idCounter = 1;
|
|
|
-static Server::OnConnect onConnect = [](Server::Client) {};
|
|
|
-static Server::OnDisconnect onDisconnect = [](Server::Client) {};
|
|
|
-static Server::OnPacket onPacket = [](Server::Client, InPacket&) {};
|
|
|
+static void voidClientInPacketDummy(CoreClient, CoreInPacket*) {
|
|
|
+}
|
|
|
|
|
|
-Error Server::start(Port port, int maxClients) {
|
|
|
+typedef struct {
|
|
|
+ ENetHost* server;
|
|
|
+ CoreHashMap clients; // CoreClient -> ENetPeer*
|
|
|
+ CoreClient idCounter;
|
|
|
+ CoreServerOnConnect onConnect;
|
|
|
+ CoreServerOnDisconnect onDisconnect;
|
|
|
+ CoreServerOnPacket onPacket;
|
|
|
+} Server;
|
|
|
+
|
|
|
+static Server server = {
|
|
|
+ nullptr, {0}, 1, voidClientDummy, voidClientDummy, voidClientInPacketDummy};
|
|
|
+
|
|
|
+bool coreServerStart(CorePort port, size_t maxClients) {
|
|
|
if(maxClients <= 0) {
|
|
|
- return {"invalid max client amount"};
|
|
|
- } else if(server != nullptr) {
|
|
|
- return {"already started"};
|
|
|
- } else if(ENet::add()) {
|
|
|
- return {"cannot initialize enet"};
|
|
|
+ CORE_LOG_ERROR("Invalid max client amount");
|
|
|
+ return true;
|
|
|
+ } else if(server.server != nullptr) {
|
|
|
+ CORE_LOG_WARNING("Server already started");
|
|
|
+ return true;
|
|
|
+ } else if(addENet()) {
|
|
|
+ CORE_LOG_ERROR("Server cannot initialize enet");
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- ENetAddress address;
|
|
|
- memset(&address, 0, sizeof(ENetAddress));
|
|
|
- address.host = ENET_HOST_ANY;
|
|
|
- address.port = port;
|
|
|
-
|
|
|
- server = enet_host_create(&address, static_cast<unsigned
|
|
|
-int>(maxClients), 3, 0, 0); if(server == nullptr) { ENet::remove(); return
|
|
|
-{"cannot create enet server host"};
|
|
|
+ ENetAddress address = {.host = ENET_HOST_ANY, .port = port};
|
|
|
+ server.server = enet_host_create(&address, maxClients, 3, 0, 0);
|
|
|
+ if(server.server == nullptr) {
|
|
|
+ coreServerStop();
|
|
|
+ CORE_LOG_ERROR("Cannot create enet server host");
|
|
|
+ return true;
|
|
|
}
|
|
|
- return {};
|
|
|
+ coreInitHashMap(&server.clients, sizeof(CoreClient), sizeof(ENetPeer*));
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
-void Server::stop() {
|
|
|
- if(server == nullptr) {
|
|
|
- return;
|
|
|
- }
|
|
|
- for(ENetPeer* peer : clients.values()) {
|
|
|
- enet_peer_reset(peer);
|
|
|
+void coreServerStop(void) {
|
|
|
+ if(server.server != nullptr) {
|
|
|
+ CoreHashMapIterator i;
|
|
|
+ coreInitHashMapIterator(&i, &server.clients);
|
|
|
+ while(coreHashMapHasNext(&i)) {
|
|
|
+ CoreHashMapNode* n = coreHashMapNext(&i);
|
|
|
+ enet_peer_reset(coreHashMapValue(n, ENetPeer*));
|
|
|
+ }
|
|
|
+ enet_host_destroy(server.server);
|
|
|
+ server.server = nullptr;
|
|
|
+ coreDestroyHashMap(&server.clients);
|
|
|
}
|
|
|
- enet_host_destroy(server);
|
|
|
- server = nullptr;
|
|
|
- ENet::remove();
|
|
|
+ removeENet();
|
|
|
}
|
|
|
|
|
|
-static void writeId(ENetPeer* peer, Server::Client id) {
|
|
|
+static void writeId(ENetPeer* peer, CoreClient id) {
|
|
|
static_assert(sizeof(peer->data) >= sizeof(id),
|
|
|
"private data not big enough for id");
|
|
|
memcpy(&(peer->data), &id, sizeof(id));
|
|
|
}
|
|
|
|
|
|
-static Server::Client getId(ENetPeer* peer) {
|
|
|
- Server::Client id = -1;
|
|
|
+static CoreClient getId(ENetPeer* peer) {
|
|
|
+ CoreClient id = -1;
|
|
|
memcpy(&id, &(peer->data), sizeof(id));
|
|
|
return id;
|
|
|
}
|
|
|
|
|
|
-static void handleConnect(ENetEvent& e) {
|
|
|
- Server::Client id = idCounter++;
|
|
|
- if(clients.tryEmplace(id, e.peer)) {
|
|
|
- LOG_WARNING("id is connected twice");
|
|
|
+static void handleConnect(ENetEvent* e) {
|
|
|
+ CoreClient id = server.idCounter++;
|
|
|
+ if(coreHashMapContains(&server.clients, CoreClient, id)) {
|
|
|
+ CORE_LOG_WARNING("Id is connected twice");
|
|
|
return;
|
|
|
}
|
|
|
- writeId(e.peer, id);
|
|
|
- onConnect(id);
|
|
|
+ coreHashMapPut(&server.clients, CoreClient, id, ENetPeer*, e->peer);
|
|
|
+ writeId(e->peer, id);
|
|
|
+ server.onConnect(id);
|
|
|
}
|
|
|
|
|
|
-static void handlePacket(ENetEvent& e) {
|
|
|
- if(e.peer->data == nullptr) {
|
|
|
- LOG_WARNING("client without data sent package");
|
|
|
+static void handlePacket(ENetEvent* e) {
|
|
|
+ if(e->peer->data == nullptr) {
|
|
|
+ CORE_LOG_WARNING("Client without data sent package");
|
|
|
return;
|
|
|
}
|
|
|
- Server::Client id = getId(e.peer);
|
|
|
- InPacket in(e.packet->data, static_cast<int>(e.packet->dataLength));
|
|
|
- onPacket(id, in);
|
|
|
+ CoreClient id = getId(e->peer);
|
|
|
+ CoreInPacket in;
|
|
|
+ coreInitInPacket(&in, e->packet->data, e->packet->dataLength);
|
|
|
+ server.onPacket(id, &in);
|
|
|
}
|
|
|
|
|
|
-static void handleDisconnect(ENetEvent& e) {
|
|
|
- if(e.peer->data == nullptr) {
|
|
|
- LOG_WARNING("client without data disconnected");
|
|
|
+static void handleDisconnect(ENetEvent* e) {
|
|
|
+ if(e->peer->data == nullptr) {
|
|
|
+ CORE_LOG_WARNING("Client without data disconnected");
|
|
|
return;
|
|
|
}
|
|
|
- Server::Client id = getId(e.peer);
|
|
|
- onDisconnect(id);
|
|
|
- if(clients.remove(id)) {
|
|
|
- LOG_WARNING("removed non existing client");
|
|
|
+ CoreClient id = getId(e->peer);
|
|
|
+ server.onDisconnect(id);
|
|
|
+ if(!coreHashMapRemove(&server.clients, CoreClient, id)) {
|
|
|
+ CORE_LOG_WARNING("Removed non existing client");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Server::tick() {
|
|
|
- if(server == nullptr) {
|
|
|
+void coreServerTick(void) {
|
|
|
+ if(server.server == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
ENetEvent e;
|
|
|
- while(enet_host_service(server, &e, 0) > 0) {
|
|
|
+ while(enet_host_service(server.server, &e, 0) > 0) {
|
|
|
switch(e.type) {
|
|
|
- case ENET_EVENT_TYPE_CONNECT: handleConnect(e); break;
|
|
|
+ case ENET_EVENT_TYPE_CONNECT: handleConnect(&e); break;
|
|
|
case ENET_EVENT_TYPE_RECEIVE:
|
|
|
- handlePacket(e);
|
|
|
+ handlePacket(&e);
|
|
|
enet_packet_destroy(e.packet);
|
|
|
break;
|
|
|
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
|
|
|
- case ENET_EVENT_TYPE_DISCONNECT: handleDisconnect(e); break;
|
|
|
+ case ENET_EVENT_TYPE_DISCONNECT: handleDisconnect(&e); break;
|
|
|
case ENET_EVENT_TYPE_NONE: return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static ENetPacket* fromBuffer(const Buffer& buffer, int index) {
|
|
|
- constexpr enet_uint32 flags[] = {ENET_PACKET_FLAG_RELIABLE, 0,
|
|
|
- ENET_PACKET_FLAG_UNSEQUENCED};
|
|
|
- return enet_packet_create(
|
|
|
- buffer, static_cast<unsigned int>(buffer.getLength()),
|
|
|
-flags[index]);
|
|
|
+static ENetPacket* fromBuffer(const CoreBuffer* buffer, enet_uint8 index) {
|
|
|
+ static const enet_uint32 flags[] = {ENET_PACKET_FLAG_RELIABLE, 0,
|
|
|
+ ENET_PACKET_FLAG_UNSEQUENCED};
|
|
|
+ return enet_packet_create(buffer->buffer, buffer->size, flags[index]);
|
|
|
}
|
|
|
|
|
|
-void Server::send(const OutPacket& p, PacketSendMode mode) {
|
|
|
- if(server != nullptr) {
|
|
|
- int index = static_cast<int>(mode);
|
|
|
- enet_host_broadcast(server, static_cast<enet_uint8>(index),
|
|
|
- fromBuffer(p.buffer, index));
|
|
|
+void coreServerSendAll(const CoreOutPacket* p, CorePacketSendMode mode) {
|
|
|
+ if(server.server != nullptr) {
|
|
|
+ enet_uint8 index = (enet_uint8)mode;
|
|
|
+ enet_host_broadcast(server.server, index, fromBuffer(&p->data, index));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Server::send(Server::Client client, const OutPacket& p,
|
|
|
- PacketSendMode mode) {
|
|
|
- if(server == nullptr) {
|
|
|
+void coreServerSend(CoreClient clientId, const CoreOutPacket* p,
|
|
|
+ CorePacketSendMode mode) {
|
|
|
+ if(server.server == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
- ENetPeer** peer = clients.search(client);
|
|
|
+ ENetPeer** peer = coreHashMapSearchPointer(&server.clients, &clientId);
|
|
|
if(peer != nullptr) {
|
|
|
- int index = static_cast<int>(mode);
|
|
|
- enet_peer_send(*peer, static_cast<enet_uint8>(index),
|
|
|
- fromBuffer(p.buffer, index));
|
|
|
+ enet_uint8 index = (enet_uint8)mode;
|
|
|
+ enet_peer_send(*peer, index, fromBuffer(&p->data, index));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Server::disconnect(Client client) {
|
|
|
- ENetPeer** peer = clients.search(client);
|
|
|
+void coreServerDisconnect(CoreClient clientId) {
|
|
|
+ ENetPeer** peer = coreHashMapSearchPointer(&server.clients, &clientId);
|
|
|
if(peer != nullptr) {
|
|
|
enet_peer_disconnect(*peer, 0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Server::setConnectHandler(OnConnect oc) {
|
|
|
- onConnect = oc;
|
|
|
+void coreServerSetConnectHandler(CoreServerOnConnect oc) {
|
|
|
+ server.onConnect = oc == nullptr ? voidClientDummy : oc;
|
|
|
}
|
|
|
|
|
|
-void Server::setDisconnectHandler(OnDisconnect od) {
|
|
|
- onDisconnect = od;
|
|
|
+void coreServerSetDisconnectHandler(CoreServerOnDisconnect od) {
|
|
|
+ server.onDisconnect = od == nullptr ? voidClientDummy : od;
|
|
|
}
|
|
|
|
|
|
-void Server::setPacketHandler(OnPacket op) {
|
|
|
- onPacket = op;
|
|
|
+void coreServerSetPacketHandler(CoreServerOnPacket op) {
|
|
|
+ server.onPacket = op == nullptr ? voidClientInPacketDummy : op;
|
|
|
}
|
|
|
|
|
|
-void Server::resetHandler() {
|
|
|
- onConnect = [](Server::Client) {};
|
|
|
- onDisconnect = [](Server::Client) {};
|
|
|
- onPacket = [](Server::Client, InPacket&) {};
|
|
|
-}*/
|
|
|
+void coreServerResetHandler(void) {
|
|
|
+ server.onConnect = voidClientDummy;
|
|
|
+ server.onDisconnect = voidClientDummy;
|
|
|
+ server.onPacket = voidClientInPacketDummy;
|
|
|
+}
|