diff --git a/code/apps/client/source/network.c b/code/apps/client/source/network.c index 71cf23c..29c380b 100644 --- a/code/apps/client/source/network.c +++ b/code/apps/client/source/network.c @@ -152,3 +152,16 @@ void network_client_update(void *data) { bool network_client_is_connected() { return peer ? enet_peer_get_state(peer) == ENET_PEER_STATE_CONNECTED : false; } + +static int32_t network_msg_send_raw(uint16_t /* peer_id */, void *data, size_t datalen, uint32_t flags) { + ENetPacket *packet = enet_packet_create(data, datalen, flags); + enet_peer_send(peer, 0, packet); +} + +int32_t network_msg_send(uint16_t /* peer_id */, void *data, size_t datalen) { + network_msg_send_raw(0, data, datalen, ENET_PACKET_FLAG_RELIABLE); +} + +int32_t network_msg_send_unreliable(uint16_t /* peer_id */, void *data, size_t datalen) { + network_msg_send_raw(0, data, datalen, 0); +} diff --git a/code/apps/server/header/network.h b/code/apps/server/header/network.h index b3ef261..58b617e 100644 --- a/code/apps/server/header/network.h +++ b/code/apps/server/header/network.h @@ -10,3 +10,6 @@ void network_server_update(void *data); uint64_t network_client_create(uint16_t peer_id); void network_client_destroy(uint64_t ent_id); + +int32_t network_msg_send(uint16_t peer_id, void *data, size_t datalen); +int32_t network_msg_send_unreliable(uint16_t peer_id, void *data, size_t datalen); diff --git a/code/apps/server/source/network.c b/code/apps/server/source/network.c index ba6cce4..e3a56d8 100644 --- a/code/apps/server/source/network.c +++ b/code/apps/server/source/network.c @@ -70,7 +70,7 @@ int32_t network_server_tick(void) { case ENET_EVENT_TYPE_CONNECT: { zpl_printf("[INFO] A new user %d connected.\n", event.peer->incomingPeerID); uint16_t peer_id = event.peer->incomingPeerID; - uint64_t ent_id = network_client_create(peer_id); + uint64_t ent_id = network_client_create(event.peer); // TODO: Make sure ent_id does not get truncated with large entity numbers. event.peer->data = (void*)((uint32_t)ent_id); } break; @@ -82,6 +82,16 @@ int32_t network_server_tick(void) { } break; case ENET_EVENT_TYPE_RECEIVE: { + pkt_header header = {0}; + pkt_header_decode(&header, event.packet->data, event.packet->dataLength); + + if (header.ok) { + pkt_handlers[header.id].handler(&header); + } else { + // error happened within top level packet flow + } + + // /* handle a newly received event */ // librg_world_read( // world_tracker(), @@ -152,3 +162,26 @@ void network_client_destroy(uint64_t ent_id) { librg_entity_untrack(world_tracker(), ent_id); ecs_delete(world_ecs(), ent_id); } + +static ENetPeer *network_enet_find_by_id(uint16_t peer_id) { + for (size_t i = 0; i < server->peerCount; ++i) { + ENetPeer *peer = &server->peers[i]; + if (enet_peer_get_id(peer) == peer_id) + return peer; + } + + return NULL; +} + +static int32_t network_msg_send_raw(uint16_t peer_id, void *data, size_t datalen, uint32_t flags) { + ENetPacket *packet = enet_packet_create(data, datalen, flags); + enet_peer_send(network_enet_find_by_id(peer_id), 0, packet); +} + +int32_t network_msg_send(uint16_t peer_id, void *data, size_t datalen) { + network_msg_send_raw(peer_id, data, datalen, ENET_PACKET_FLAG_RELIABLE); +} + +int32_t network_msg_send_unreliable(uint16_t peer_id, void *data, size_t datalen) { + network_msg_send_raw(peer_id, data, datalen, 0); +} diff --git a/code/common/packets/packet.c b/code/common/packets/packet.c new file mode 100644 index 0000000..2af9cca --- /dev/null +++ b/code/common/packets/packet.c @@ -0,0 +1,43 @@ +#include "packet.h" + +#define PKT_HEADER_ELEMENTS 2 + +pkt_handler pkt_handlers[] = { + {.id = MSG_ID_01_WELCOME, .handler = pkt_01_welcome_handler}, +}; + +int32_t pkt_header_encode(pkt_header *table) { + return 0; +} + +int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen) { + cw_unpack_context uc = {0}; + cw_unpack_context_init(&uc, data, datalen, 0); + + cw_unpack_next(&uc); + if (uc.item.type != CWP_ITEM_ARRAY || uc.item.as.array.size != PKT_HEADER_ELEMENTS) { + return -1;//todo: error + } + + cw_unpack_next(&uc); + if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER || uc.item.as.u64 > UINT16_MAX) { + return -1; // invalid packet id id + } + + uint16_t pkt_id = (uint16_t)uc.item.as.u64; + + cw_unpack_next(&uc); + const void *packed_blob = uc.item.as.bin.start; + uin32_t packed_size = uc.item.as.bind.length; + + table->id = pkt_id; + table->data = packed_blob; + table->datalen = packed_size; + table->ok = 1; + + if (uc.return_code != CWP_RC_OK) return -1; // unpacking failed somwwhere + cw_unpack_next(&uc); + if (uc.return_code != CWP_RC_END_OF_INPUT) return -1; // not finished yet but should be? + + return 0; +} diff --git a/code/common/packets/packet.h b/code/common/packets/packet.h index e9b6a44..35ba9bb 100644 --- a/code/common/packets/packet.h +++ b/code/common/packets/packet.h @@ -1 +1,35 @@ -// nothing +#pragma once +#include "system.h" + +#define PKT_HANDLER_PROC(name) int32_t name(pkt_header *header) +typedef PKT_HANDLER_PROC(pkt_handler_proc); + +typedef enum { + MSG_ID_01_WELCOME, + MSG_ID_LIBRG_UPDATE, + MSG_ID_FORCE_UINT16 = UINT16_MAX, +} pkt_messages; + +typedef struct { + uint16_t id; + uint16_t sender; + uint8_t *data; + uint32_t datalen; + int8_t ok; +} pkt_header; + +typedef struct { + uint16_t id; + pkt_handler_proc *handler; +} pkt_handler; + +typedef struct { + uint32_t chunk_size; + uint32_t chunk_amount; +} pkt_01_welcome; + +int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen); + +PKT_HANDLER_PROC(pkt_01_welcome_handler); + +extern pkt_handler pkt_handlers[]; diff --git a/code/common/packets/pkt_01_welcome.c b/code/common/packets/pkt_01_welcome.c index 3e30f29..a15b6ea 100644 --- a/code/common/packets/pkt_01_welcome.c +++ b/code/common/packets/pkt_01_welcome.c @@ -2,14 +2,14 @@ // PACKET_GENERATE_ENCODE(1, 2, ) +#include "packet.h" #include "cwpack/cwpack.h" #define PKT_01_WELCOME_ID 1 #define PKT_01_WELCOME_ARGS 2 -size_t PKT_01_welcome_encode(uint32_t chunk_size, uint32_t chunk_amount) { - char buffer[20] = {0}; +size_t pkt_01_welcome_encode(pkt_01_welcome *table) { cw_pack_context pc = {0}; cw_pack_context_init(&pc, buffer, 20, 0); cw_pack_array_size(&pc, 1 + PKT_01_WELCOME_ARGS); @@ -20,3 +20,37 @@ size_t PKT_01_welcome_encode(uint32_t chunk_size, uint32_t chunk_amount) { return pc.current - pc.start; /* length */ } + +int32_t pkt_01_welcome_decode(pkt_01_welcome *table, pkt_header *header) { + cw_unpack_context uc = {0}; + cw_unpack_context_init(&uc, header->data, header->datalen, 0); + + cw_unpack_next(&uc); + if (uc.item.type != CWP_ITEM_ARRAY || uc.item.as.array.size != PKT_01_WELCOME_ARGS) { + return -1;//todo: error + } + + cw_unpack_next(&uc); + if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER) return -1; // expected chunk size + table->chunk_size = uc.item.as.u64; + + cw_unpack_next(&uc); + if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER) return -1; // expected chunk amount + table->chunk_amount = uc.item.as.u64; + + if (uc.return_code != CWP_RC_OK) return -1; // unpacking failed somwwhere + cw_unpack_next(&uc); + if (uc.return_code != CWP_RC_END_OF_INPUT) return -1; // not finished yet but should be? + + return 0; +} + +int32_t pkt_01_handler(pkt_header *header) { + pkt_01_welcome table; + pkt_01_welcome_decode(&table, header); + + zpl_printf("we received: chunk_size: %d and chunk_amount: %d\n", table.chunk_size, table.chunk_amount); + + // do STUFF + return 0; +}