#pragma once #include #include #include #include #include #include "Client.hh" #include "ServerState.hh" class Server : public std::enable_shared_from_this { public: Server() = delete; Server(const Server&) = delete; Server(Server&&) = delete; Server(std::shared_ptr base, std::shared_ptr state); virtual ~Server() = default; void listen(const std::string& addr_str, const std::string& socket_path, GameVersion version, ServerBehavior initial_state); void listen(const std::string& addr_str, const std::string& addr, int port, GameVersion version, ServerBehavior initial_state); void listen(const std::string& addr_str, int port, GameVersion version, ServerBehavior initial_state); void add_socket(const std::string& addr_str, int fd, GameVersion version, ServerBehavior initial_state); void connect_client(struct bufferevent* bev, uint32_t address, uint16_t client_port, uint16_t server_port, GameVersion version, ServerBehavior initial_state); void disconnect_client(std::shared_ptr c); std::shared_ptr get_client() const; std::vector> get_clients_by_identifier( const std::string& ident) const; std::shared_ptr get_base() const; inline std::shared_ptr get_state() const { return this->state; } private: std::shared_ptr base; std::shared_ptr destroy_clients_ev; struct ListeningSocket { std::string addr_str; int fd; GameVersion version; ServerBehavior behavior; std::unique_ptr listener; ListeningSocket( Server* s, const std::string& name, int fd, GameVersion version, ServerBehavior behavior); }; std::unordered_map listening_sockets; std::unordered_set> clients_to_destroy; std::shared_ptr state; void enqueue_destroy_clients(); static void dispatch_destroy_clients(evutil_socket_t, short, void* ctx); void destroy_clients(); static void dispatch_on_listen_accept(struct evconnlistener* listener, evutil_socket_t fd, struct sockaddr* address, int socklen, void* ctx); static void dispatch_on_listen_error(struct evconnlistener* listener, void* ctx); void on_listen_accept(struct evconnlistener* listener, evutil_socket_t fd, struct sockaddr* address, int socklen); void on_listen_error(struct evconnlistener* listener); static void on_client_input(Channel& ch, uint16_t command, uint32_t flag, std::string& data); static void on_client_error(Channel& ch, short events); };