.. _program_listing_file_server_server.h: Program Listing for File server.h ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``server/server.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef SERVER_H #define SERVER_H #include #include #include #include #include #include "server_args_parser.h" #include "client/client_manager.h" #include "utils/debug.h" #include "event.h" #define MAP_MAX_SIDE_SIZE 42 #define LIKELY(cond) (__builtin_expect(!!(cond), 1)) #define UNLIKELY(cond) (__builtin_expect(!!(cond), 0)) enum { RES_FOOD, RES_LINEMATE, RES_DERAUMERE, RES_SIBUR, RES_MENDIANE, RES_PHIRAS, RES_THYSTAME, RES_COUNT }; typedef struct pollfd pollfd_t; typedef union { struct { uint32_t food; uint32_t linemate; uint32_t deraumere; uint32_t sibur; uint32_t mendiane; uint32_t phiras; uint32_t thystame; }; uint32_t qnts[RES_COUNT]; } inventory_t; typedef struct { uint32_t hatch; uint8_t team_id; uint8_t id; uint8_t x; uint8_t y; } egg_t; // For the next 3 structures, we use a resizable array pattern // to manage dynamic arrays of client states, eggs, and poll file descriptors. // It requires the following memory layout in order to work: // - buff: pointer to the allocated memory // - nmemb: number of elements currently in the array // - capacity: total capacity of the allocated memory // This allows us to use the same functions for all three types of arrays. typedef struct { client_state_t *buff; size_t nmemb; size_t capacity; } client_state_array_t; typedef struct { egg_t *buff; size_t nmemb; size_t capacity; } egg_array_t; typedef struct { pollfd_t *buff; size_t nmemb; size_t capacity; } pollfd_array_t; typedef struct server_s { int self_fd; volatile bool is_running; egg_array_t eggs; client_manager_t cm; char *team_names[TEAM_COUNT_LIMIT]; uint8_t map_height; uint8_t map_width; inventory_t total_item_in_map; inventory_t map[MAP_MAX_SIDE_SIZE][MAP_MAX_SIDE_SIZE]; event_heap_t events; uint64_t start_time; uint16_t frequency; // reciprocal of time unit uint8_t last_egg_id; } server_t; bool server_run(params_t *p, uint64_t timestamp); void server_handle_events(server_t *srv); void handle_poll(server_t *srv, uint64_t timeout); void handle_fds_revents(server_t *srv); void handle_client_disconnection(server_t *srv); void process_clients_buff(server_t *srv); static constexpr const int MICROSEC_IN_SEC = 1000000; static constexpr const int MILISEC_IN_SEC = 1000; static inline uint64_t get_timestamp(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)((tv.tv_sec * MICROSEC_IN_SEC) + tv.tv_usec); } static inline int32_t compute_timeout(server_t *srv) { int64_t current_time = get_timestamp(); int64_t next_event_time = event_heap_peek(&srv->events)->timestamp; int32_t diff = (next_event_time - current_time); int32_t ms = diff / MILISEC_IN_SEC; if (ms > 0) { DEBUG("Timeout for next event: %u ms; diff µs: %d", ms, diff - (MILISEC_IN_SEC * ms)); } return ms; } #endif