123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- #include "core/Network.h"
- #define ENET_IMPLEMENTATION
- #include <enet.h>
- #include <string.h>
- typedef CoreOutPacket OutPacket;
- void coreInitInPacket(CoreInPacket* in, const void* data, size_t n) {
- in->data = data;
- in->size = n;
- in->index = 0;
- }
- bool coreInPacketReadU8(CoreInPacket* in, u8* u) {
- return coreInPacketRead(in, u, sizeof(*u));
- }
- bool coreInPacketReadU16(CoreInPacket* in, u16* u) {
- if(coreInPacketRead(in, u, sizeof(*u))) {
- return true;
- }
- *u = ntohs(*u);
- return false;
- }
- bool coreInPacketReadU32(CoreInPacket* in, u32* u) {
- if(coreInPacketRead(in, u, sizeof(*u))) {
- return true;
- }
- *u = ntohl(*u);
- return false;
- }
- bool coreInPacketReadI8(CoreInPacket* in, i8* i) {
- u8 u;
- if(coreInPacketReadU8(in, &u)) {
- return true;
- }
- *i = (i8)((i32)u - (i32)128);
- return false;
- }
- bool coreInPacketReadI16(CoreInPacket* in, i16* i) {
- u16 u;
- if(coreInPacketReadU16(in, &u)) {
- return true;
- }
- *i = (i16)((i32)u - (i32)32768);
- return false;
- }
- bool coreInPacketReadI32(CoreInPacket* in, i32* i) {
- u32 u;
- if(coreInPacketReadU32(in, &u)) {
- return true;
- }
- if(u < 2147483648) {
- *i = (i32)((i32)u - (i32)2147483648);
- } else {
- *i = (i32)(u - (u32)2147483648);
- }
- return false;
- }
- bool coreInPacketReadFloat(CoreInPacket* in, float* f) {
- u32 u;
- static_assert(sizeof(u) == sizeof(*f), "float and u32 size do not match");
- if(coreInPacketReadU32(in, &u)) {
- return true;
- }
- memcpy(f, &u, sizeof(float));
- return false;
- }
- size_t coreInPacketReadString(CoreInPacket* in, char* buffer, size_t n) {
- if(n == 0) {
- return 0;
- }
- u16 size;
- if(coreInPacketReadU16(in, &size)) {
- return 0;
- }
- size_t end = size;
- char* bufferStart = buffer;
- n--;
- while(n-- > 0 && end-- > 0) {
- u8 u;
- if(coreInPacketReadU8(in, &u)) {
- *bufferStart = '\0';
- break;
- }
- *(buffer++) = (char)u;
- }
- while(end-- > 0 && !coreInPacketReadU8(in, &(u8){0})) {}
- *buffer = '\0';
- return size;
- }
- bool coreInPacketRead(CoreInPacket* in, void* buffer, size_t n) {
- if(in->index + n > in->size) {
- return true;
- }
- memcpy(buffer, in->data + in->index, n);
- in->index += n;
- return false;
- }
- void coreInitOutPacket(OutPacket* out) {
- coreInitBuffer(&out->data);
- }
- void coreDestroyOutPacket(OutPacket* out) {
- coreDestroyBuffer(&out->data);
- }
- OutPacket* coreOutPacketWriteU8(OutPacket* out, u8 u) {
- coreAddSizedBufferData(&out->data, &u, sizeof(u));
- return out;
- }
- OutPacket* coreOutPacketWriteU16(OutPacket* out, u16 u) {
- u = htons(u);
- coreAddSizedBufferData(&out->data, &u, sizeof(u));
- return out;
- }
- OutPacket* coreOutPacketWriteU32(OutPacket* out, u32 u) {
- u = htonl(u);
- coreAddSizedBufferData(&out->data, &u, sizeof(u));
- return out;
- }
- OutPacket* coreOutPacketWriteI8(OutPacket* out, i8 i) {
- if(i < 0) {
- return coreOutPacketWriteU8(out, (u8)((i32)i + (i32)128));
- }
- return coreOutPacketWriteU8(out, (u8)((u32)i + (u32)128));
- }
- OutPacket* coreOutPacketWriteI16(OutPacket* out, i16 i) {
- if(i < 0) {
- return coreOutPacketWriteU16(out, (u16)((i32)i + (i32)32768));
- }
- return coreOutPacketWriteU16(out, (u16)((u32)i + (u32)32768));
- }
- OutPacket* coreOutPacketWriteI32(OutPacket* out, i32 i) {
- if(i < 0) {
- return coreOutPacketWriteU32(out, (u32)(i + (i32)2147483648));
- }
- return coreOutPacketWriteU32(out, (u32)((u32)i + (u32)2147483648));
- }
- OutPacket* coreOutPacketWriteFloat(OutPacket* out, float f) {
- u32 u;
- static_assert(sizeof(u) == sizeof(f), "float and u32 size do not match");
- memcpy(&u, &f, sizeof(float));
- return coreOutPacketWriteU32(out, u);
- }
- OutPacket* coreOutPacketWriteString(OutPacket* out, const char* s, size_t n) {
- size_t end = n > 65535 ? 65535 : n;
- coreOutPacketWriteU16(out, (u16)end);
- for(size_t i = 0; i < end; i++) {
- coreOutPacketWriteU8(out, (u8)(*(s++)));
- }
- return out;
- }
- OutPacket* coreOutPacketWrite(OutPacket* out, const void* buffer, size_t n) {
- coreAddSizedBufferData(&out->data, buffer, n);
- return out;
- }
- /*static int enetCounter = 0;
- bool ENet::add() {
- if(enetCounter == 0 && enet_initialize() != 0) {
- return true;
- }
- enetCounter++;
- return false;
- }
- void ENet::remove() {
- if(enetCounter > 0 && --enetCounter == 0) {
- enet_deinitialize();
- }
- }
- static_assert(sizeof(enet_uint16) == sizeof(Client::Port),
- "client port has wrong type");
- static ENetHost* client = nullptr;
- static ENetPeer* connection = nullptr;
- static int connectTicks = 0;
- static int connectTimeoutTicks = 0;
- static int disconnectTicks = 0;
- static int disconnectTimeoutTicks = 0;
- static Client::OnConnect onConnect = []() {};
- static Client::OnDisconnect onDisconnect = []() {};
- static Client::OnPacket onPacket = [](InPacket&) {};
- Error Client::start() {
- if(client != nullptr) {
- return {"already started"};
- } else if(ENet::add()) {
- return {"cannot initialize enet"};
- }
- client = enet_host_create(nullptr, 1, 2, 0, 0);
- if(client == nullptr) {
- ENet::remove();
- return {"cannot create enet client host"};
- }
- return {};
- }
- void Client::stop() {
- if(connection != nullptr) {
- onDisconnect();
- enet_peer_disconnect_now(connection, 0);
- connection = nullptr;
- }
- if(client != nullptr) {
- enet_host_destroy(client);
- ENet::remove();
- client = nullptr;
- }
- connectTicks = 0;
- disconnectTicks = 0;
- }
- Error Client::connect(const char* server, Port port, int timeoutTicks) {
- if(client == nullptr) {
- return {"client not started"};
- } else if(connection != nullptr) {
- return {"connection already exists"};
- }
- ENetAddress address;
- memset(&address, 0, sizeof(ENetAddress));
- enet_address_set_host(&address, server);
- address.port = port;
- connection = enet_host_connect(client, &address, 3, 0);
- if(connection == nullptr) {
- return {"cannot create connection"};
- }
- connectTicks = 1;
- connectTimeoutTicks = timeoutTicks;
- return {};
- }
- void Client::disconnect(int timeoutTicks) {
- if(connection == nullptr) {
- return;
- }
- connectTicks = 0;
- enet_peer_disconnect(connection, 0);
- disconnectTicks = 1;
- disconnectTimeoutTicks = timeoutTicks;
- }
- void Client::send(OutPacket& p, PacketSendMode mode) {
- if(client != nullptr && connection != nullptr && connectTicks < 0) {
- constexpr enet_uint32 flags[] = {ENET_PACKET_FLAG_RELIABLE, 0,
- ENET_PACKET_FLAG_UNSEQUENCED};
- enet_uint8 index = static_cast<enet_uint8>(mode);
- enet_peer_send(connection, index,
- enet_packet_create(
- p.buffer,
- static_cast<size_t>(p.buffer.getLength()), flags[index]));
- }
- }
- void Client::tick() {
- if(client == nullptr) {
- return;
- }
- ENetEvent e;
- while(enet_host_service(client, &e, 0) > 0) {
- switch(e.type) {
- case ENET_EVENT_TYPE_CONNECT:
- connectTicks = -1;
- onConnect();
- break;
- case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
- case ENET_EVENT_TYPE_DISCONNECT:
- disconnectTicks = 0;
- onDisconnect();
- connection = nullptr;
- break;
- case ENET_EVENT_TYPE_NONE: return;
- case ENET_EVENT_TYPE_RECEIVE:
- InPacket in(e.packet->data,
- static_cast<int>(e.packet->dataLength));
- onPacket(in);
- enet_packet_destroy(e.packet);
- break;
- }
- }
- if(connectTicks >= 1 && ++connectTicks > connectTimeoutTicks) {
- connectTicks = 0;
- disconnect(connectTimeoutTicks);
- }
- if(disconnectTicks >= 1 && ++disconnectTicks > disconnectTimeoutTicks) {
- disconnectTicks = 0;
- onDisconnect();
- if(connection != nullptr) {
- enet_peer_reset(connection);
- connection = nullptr;
- }
- }
- }
- void Client::setConnectHandler(OnConnect oc) {
- onConnect = oc;
- }
- void Client::setDisconnectHandler(OnDisconnect od) {
- onDisconnect = od;
- }
- void Client::setPacketHandler(OnPacket op) {
- onPacket = op;
- }
- void Client::resetHandler() {
- onConnect = []() {};
- onDisconnect = []() {};
- onPacket = [](InPacket&) {};
- }
- bool Client::isConnecting() {
- return connectTicks >= 1;
- }
- bool Client::isConnected() {
- return connectTicks < 0;
- }
- 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&) {};
- }*/
|