123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- #ifndef SERVER_H
- #define SERVER_H
- #include "network/ENet.h"
- #include "network/Packet.h"
- #include "utils/HashMap.h"
- #include "utils/StringBuffer.h"
- #include "utils/Types.h"
- struct Server final {
- typedef enet_uint16 Port;
- typedef StringBuffer<256> Error;
- class Client final {
- friend class Server;
- ENetPeer* peer;
- int id;
- friend HashMap<int, Client>;
- Client(ENetPeer* peer, int id);
- Client(const Client&) = delete;
- Client(Client&& other);
- Client& operator=(const Client&) = delete;
- Client& operator=(Client&& other);
- public:
- ~Client();
- int getId() const;
- void send(OutPacket& p);
- };
- private:
- ENetHost* server;
- Error error;
- HashMap<int, Client> clients;
- int idCounter;
- public:
- Server(Port port, int maxClients);
- Server(const Server&) = delete;
- Server(Server&&) = delete;
- ~Server();
- Server& operator=(const Server&) = delete;
- Server& operator=(Server&&) = delete;
- bool hasError() const;
- const Error& getError() const;
- template<typename T>
- void consumeEvents(T& consumer) {
- ENetEvent e;
- while(!hasError() && enet_host_service(server, &e, 0) > 0) {
- switch(e.type) {
- case ENET_EVENT_TYPE_CONNECT: onConnect(e, consumer); break;
- case ENET_EVENT_TYPE_RECEIVE:
- onPacket(e, consumer);
- enet_packet_destroy(e.packet);
- break;
- case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
- case ENET_EVENT_TYPE_DISCONNECT:
- onDisconnect(e, consumer);
- break;
- case ENET_EVENT_TYPE_NONE: return;
- }
- }
- }
- void send(OutPacket& p);
- void disconnect(Client& client);
- private:
- template<typename T>
- void onConnect(ENetEvent& e, T& consumer) {
- int id = idCounter++;
- if(clients.tryEmplace(id, e.peer, id)) {
- error.clear().append("id is connected twice");
- return;
- }
- static_assert(sizeof(e.peer->data) >= sizeof(id),
- "private data not big enough for id");
- memcpy(&(e.peer->data), &id, sizeof(id));
- Client* client = clients.search(id);
- if(client != nullptr) {
- consumer.onConnect(*client);
- } else {
- error.clear().append("cannot find added client");
- }
- }
- template<typename T>
- void onPacket(ENetEvent& e, T& consumer) {
- if(e.peer->data == nullptr) {
- error.clear().append("client without data sent package");
- return;
- }
- int id = -1;
- memcpy(&id, &(e.peer->data), sizeof(id));
- Client* client = clients.search(id);
- if(client != nullptr) {
- InPacket in(e.packet);
- consumer.onPacket(*client, in);
- } else {
- error.clear().append("client with invalid id sent package");
- }
- }
- template<typename T>
- void onDisconnect(ENetEvent& e, T& consumer) {
- if(e.peer->data == nullptr) {
- error.clear().append("client without data disconnected");
- return;
- }
- int id = -1;
- memcpy(&id, &(e.peer->data), sizeof(id));
- Client* client = clients.search(id);
- if(client != nullptr) {
- consumer.onDisconnect(*client);
- clients.remove(id);
- } else {
- error.clear().append("client has invalid id");
- }
- }
- };
- #endif
|