123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- #include "network/Server.h"
- #include "data/HashMap.h"
- #include "network/ENet.h"
- #include "utils/Logger.h"
- static_assert(sizeof(enet_uint16) == sizeof(Server::Port),
- "client port has wrong type");
- 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&) {};
- Error Server::start(Port port, int maxClients) {
- if(maxClients <= 0) {
- return {"invalid max client amount"};
- } else if(server != nullptr) {
- return {"already started"};
- } else if(ENet::add()) {
- return {"cannot initialize enet"};
- }
- 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"};
- }
- return {};
- }
- void Server::stop() {
- if(server == nullptr) {
- return;
- }
- for(ENetPeer* peer : clients.values()) {
- enet_peer_reset(peer);
- }
- enet_host_destroy(server);
- server = nullptr;
- ENet::remove();
- }
- static void writeId(ENetPeer* peer, Server::Client 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;
- 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");
- return;
- }
- writeId(e.peer, id);
- onConnect(id);
- }
- static void handlePacket(ENetEvent& e) {
- if(e.peer->data == nullptr) {
- 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);
- }
- static void handleDisconnect(ENetEvent& e) {
- if(e.peer->data == nullptr) {
- 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");
- }
- }
- void Server::tick() {
- if(server == nullptr) {
- return;
- }
- ENetEvent e;
- while(enet_host_service(server, &e, 0) > 0) {
- switch(e.type) {
- case ENET_EVENT_TYPE_CONNECT: handleConnect(e); break;
- case ENET_EVENT_TYPE_RECEIVE:
- 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_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]);
- }
- 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 Server::send(Server::Client client, const OutPacket& p,
- PacketSendMode mode) {
- if(server == nullptr) {
- return;
- }
- ENetPeer** peer = clients.search(client);
- if(peer != nullptr) {
- int index = static_cast<int>(mode);
- enet_peer_send(*peer, static_cast<enet_uint8>(index),
- fromBuffer(p.buffer, index));
- }
- }
- void Server::disconnect(Client client) {
- ENetPeer** peer = clients.search(client);
- if(peer != nullptr) {
- enet_peer_disconnect(*peer, 0);
- }
- }
- void Server::setConnectHandler(OnConnect oc) {
- onConnect = oc;
- }
- void Server::setDisconnectHandler(OnDisconnect od) {
- onDisconnect = od;
- }
- void Server::setPacketHandler(OnPacket op) {
- onPacket = op;
- }
- void Server::resetHandler() {
- onConnect = [](Server::Client) {};
- onDisconnect = [](Server::Client) {};
- onPacket = [](Server::Client, InPacket&) {};
- }
|