#pragma once #include #include #include #include #include #include #include #include "ByteStream.hpp" #include "NetLibrary.hpp" class NetServer : public std::enable_shared_from_this { public: struct ClientData; typedef std::function, cereal::PortableBinaryInputArchive&)> NetServerRecvCallback; typedef std::function)> NetServerConnectCallback; typedef std::function)> NetServerDisconnectCallback; struct ClientData : public std::enable_shared_from_this { std::unordered_map>> messages; std::unordered_map pfm; MessageOrder nextMessageOrderToSend = 0; MessageOrder nextMessageOrderToExpect = 0; std::unordered_map> channels; std::mutex receivedMessagesMutex; struct ReceivedMessage { std::string channel; rtc::binary data; }; std::queue receivedMessages; struct OutgoingMessage { MessageOrder order; std::shared_ptr ss; }; std::unordered_map> messageQueues; uint64_t customID; void send_queued_messages(NetServer& server); void parse_received_messages(NetServer& server); void send_str_as_bytes(std::shared_ptr channel, const std::string& str); NetLibrary::DownloadProgress get_progress_into_fragmented_message(const std::string& channel) const; std::atomic setToDisconnect = false; std::chrono::steady_clock::time_point lastMessageTime; friend class NetServer; friend class NetClient; }; NetServer(const std::string& serverLocalID); ~NetServer(); void update(); template void send_items_to_client(const std::shared_ptr& client, const std::string& channel, Args&&... items) { send_string_stream_to_client(client, channel, get_string_stream_from_items(items...)); } template void send_items_to_all_clients(const std::string& channel, Args&&... items) { send_string_stream_to_all_clients(channel, get_string_stream_from_items(items...)); } template void send_items_to_all_clients_except(const std::shared_ptr& client, const std::string& channel, Args&&... items) { send_string_stream_to_all_clients_except(client, channel, get_string_stream_from_items(items...)); } template void send_items_to_client_if(std::function&)> clientChecker, const std::string& channel, Args&&... items) { send_string_stream_to_client_if(clientChecker, channel, get_string_stream_from_items(items...)); } template std::shared_ptr get_string_stream_from_items(Args&&... items) { auto ss(std::make_shared()); { cereal::PortableBinaryOutputArchive m(*ss); (m(items), ...); } return ss; } void send_string_stream_to_client(const std::shared_ptr& client, const std::string& channel, const std::shared_ptr& ss); void send_string_stream_to_all_clients(const std::string& channel, const std::shared_ptr& ss); void send_string_stream_to_all_clients_except(const std::shared_ptr& client, const std::string& channel, const std::shared_ptr& ss); void send_string_stream_to_client_if(std::function&)> clientChecker, const std::string& channel, const std::shared_ptr& ss); bool is_disconnected() const; void add_recv_callback(MessageCommandType commandID, const NetServerRecvCallback& callback); void add_disconnect_callback(const NetServerDisconnectCallback& callback); const std::vector> get_client_list() const; private: void parse_received_messages(); void send_queued_messages(); void client_connected(std::shared_ptr connection, const std::string& clientLocalID); std::atomic isDisconnected = false; std::string localID; std::vector> clients; // Adding an add list, because i dont want to block the entire clients vector with a mutex std::mutex clientsToAddMutex; std::vector> clientsToAdd; std::unordered_map recvCallbacks; NetServerDisconnectCallback disconnectCallback; NetClient* directConnectClient = nullptr; std::shared_ptr directConnectClientData; friend class NetLibrary; friend class NetClient; };