X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclientiface.h;h=3e7ba4793a77352554cca45c1240f23bee554baa;hb=1f39948bc3341af99a1a2dfc39e4b4164ab56f4c;hp=0d2bca1965ce535ce3bed7fb63fe2c2c51e7dbdc;hpb=2c637ce1c26145269b09c62afb451240a8def401;p=dragonfireclient.git diff --git a/src/clientiface.h b/src/clientiface.h index 0d2bca196..3e7ba4793 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -16,20 +16,24 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef _CLIENTIFACE_H_ -#define _CLIENTIFACE_H_ + +#pragma once #include "irr_v3d.h" // for irrlicht datatypes #include "constants.h" #include "serialization.h" // for SER_FMT_VER_INVALID -#include "threading/mutex.h" #include "network/networkpacket.h" +#include "network/networkprotocol.h" +#include "network/address.h" +#include "porting.h" +#include "threading/mutex_auto_lock.h" #include #include -#include #include +#include +#include class MapBlock; class ServerEnvironment; @@ -48,30 +52,30 @@ class EmergeManager; | | \-----------------/ | depending of the incoming packet - +--------------------------------------- - v v -+-----------------------------+ +-----------------------------+ -|IN: | |IN: | -| TOSERVER_INIT_LEGACY |----- | TOSERVER_INIT | invalid playername, -+-----------------------------+ | +-----------------------------+ password (for _LEGACY), - | | | or denied by mod - | Auth ok -------------------+--------------------------------- - v v | -+-----------------------------+ +-----------------------------+ | -|OUT: | |OUT: | | -| TOCLIENT_INIT_LEGACY | | TOCLIENT_HELLO | | -+-----------------------------+ +-----------------------------+ | - | | | - | | | - v v | - /-----------------\ /-----------------\ | - | | | | | - | AwaitingInit2 |<--------- | HelloSent | | - | | | | | | - \-----------------/ | \-----------------/ | - | | | | -+-----------------------------+ | *-----------------------------* Auth fails | -|IN: | | |Authentication, depending on |-----------------+ + ---------------------------------------- + v + +-----------------------------+ + |IN: | + | TOSERVER_INIT | + +-----------------------------+ + | invalid playername + | or denied by mod + v + +-----------------------------+ + |OUT: | + | TOCLIENT_HELLO | + +-----------------------------+ + | + | + v + /-----------------\ /-----------------\ + | | | | + | AwaitingInit2 |<--------- | HelloSent | + | | | | | + \-----------------/ | \-----------------/ + | | | ++-----------------------------+ | *-----------------------------* Auth fails +|IN: | | |Authentication, depending on |------------------ | TOSERVER_INIT2 | | | packet sent by client | | +-----------------------------+ | *-----------------------------* | | | | | @@ -100,18 +104,18 @@ class EmergeManager; | | +-----------------------------+ | | DefinitionsSent | |IN: | | | | | TOSERVER_REQUEST_MEDIA | | - \-----------------/ | TOSERVER_RECEIVED_MEDIA | | + \-----------------/ | | | | +-----------------------------+ | | ^ | | | ----------------------------- | - v | + v v +-----------------------------+ --------------------------------+ -|IN: | | | +|IN: | | ^ | TOSERVER_CLIENT_READY | v | -+-----------------------------+ +-------------------------------+ | - | |OUT: | | - v | TOCLIENT_ACCESS_DENIED_LEGAGY | | -+-----------------------------+ +-------------------------------+ | ++-----------------------------+ +------------------------+ | + | |OUT: | | + v | TOCLIENT_ACCESS_DENIED | | ++-----------------------------+ +------------------------+ | |OUT: | | | | TOCLIENT_MOVE_PLAYER | v | | TOCLIENT_PRIVILEGES | /-----------------\ | @@ -165,7 +169,6 @@ namespace con { class Connection; } -#define CI_ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) // Also make sure to update the ClientInterface::statenames // array when modifying these enums @@ -188,7 +191,6 @@ enum ClientStateEvent { CSE_Hello, CSE_AuthAccept, - CSE_InitLegacy, CSE_GotInit2, CSE_SetDenied, CSE_SetDefinitionsSent, @@ -205,7 +207,7 @@ enum ClientStateEvent */ struct PrioritySortedBlockTransfer { - PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id) + PrioritySortedBlockTransfer(float a_priority, const v3s16 &a_pos, session_t a_peer_id) { priority = a_priority; pos = a_pos; @@ -217,7 +219,7 @@ struct PrioritySortedBlockTransfer } float priority; v3s16 pos; - u16 peer_id; + session_t peer_id; }; class RemoteClient @@ -227,51 +229,29 @@ class RemoteClient // NOTE: If client is made allowed to exist while peer doesn't, // this has to be set to 0 when there is no peer. // Also, the client must be moved to some other container. - u16 peer_id; + session_t peer_id = PEER_ID_INEXISTENT; // The serialization version to use with the client - u8 serialization_version; + u8 serialization_version = SER_FMT_VER_INVALID; // - u16 net_proto_version; + u16 net_proto_version = 0; /* Authentication information */ - std::string enc_pwd; - bool create_player_on_auth_success; - AuthMechanism chosen_mech; - void * auth_data; - u32 allowed_auth_mechs; - u32 allowed_sudo_mechs; + std::string enc_pwd = ""; + bool create_player_on_auth_success = false; + AuthMechanism chosen_mech = AUTH_MECHANISM_NONE; + void *auth_data = nullptr; + u32 allowed_auth_mechs = 0; + u32 allowed_sudo_mechs = 0; + + void resetChosenMech(); bool isSudoMechAllowed(AuthMechanism mech) { return allowed_sudo_mechs & mech; } bool isMechAllowed(AuthMechanism mech) { return allowed_auth_mechs & mech; } - RemoteClient(): - peer_id(PEER_ID_INEXISTENT), - serialization_version(SER_FMT_VER_INVALID), - net_proto_version(0), - create_player_on_auth_success(false), - chosen_mech(AUTH_MECHANISM_NONE), - auth_data(NULL), - m_time_from_building(9999), - m_pending_serialization_version(SER_FMT_VER_INVALID), - m_state(CS_Created), - m_nearest_unsent_d(0), - m_nearest_unsent_reset_timer(0.0), - m_excess_gotblocks(0), - m_nothing_to_send_pause_timer(0.0), - m_name(""), - m_version_major(0), - m_version_minor(0), - m_version_patch(0), - m_full_version("unknown"), - m_deployed_compression(0), - m_connection_time(getTime(PRECISION_SECONDS)) - { - } - ~RemoteClient() - { - } + RemoteClient(); + ~RemoteClient() = default; /* Finds block that should be sent next to the client. @@ -296,9 +276,11 @@ class RemoteClient */ void ResendBlockIfOnWire(v3s16 p); - s32 SendingCount() + u32 getSendingCount() const { return m_blocks_sending.size(); } + + bool isBlockSent(v3s16 p) const { - return m_blocks_sending.size(); + return m_blocks_sent.find(p) != m_blocks_sent.end(); } // Increments timeouts and removes timed-out blocks from list @@ -318,22 +300,18 @@ class RemoteClient } // Time from last placing or removing blocks - float m_time_from_building; + float m_time_from_building = 9999; /* List of active objects that the client knows of. - Value is dummy. */ std::set m_known_objects; - ClientState getState() - { return m_state; } + ClientState getState() const { return m_state; } - std::string getName() - { return m_name; } + std::string getName() const { return m_name; } - void setName(std::string name) - { m_name = name; } + void setName(const std::string &name) { m_name = name; } /* update internal client state */ void notifyEvent(ClientStateEvent event); @@ -349,10 +327,11 @@ class RemoteClient { serialization_version = m_pending_serialization_version; } /* get uptime */ - u32 uptime(); + u64 uptime() const; /* set version information */ - void setVersionInfo(u8 major, u8 minor, u8 patch, std::string full) { + void setVersionInfo(u8 major, u8 minor, u8 patch, const std::string &full) + { m_version_major = major; m_version_minor = minor; m_version_patch = patch; @@ -360,16 +339,29 @@ class RemoteClient } /* read version information */ - u8 getMajor() { return m_version_major; } - u8 getMinor() { return m_version_minor; } - u8 getPatch() { return m_version_patch; } - std::string getVersion() { return m_full_version; } + u8 getMajor() const { return m_version_major; } + u8 getMinor() const { return m_version_minor; } + u8 getPatch() const { return m_version_patch; } + const std::string &getFullVer() const { return m_full_version; } + + void setLangCode(const std::string &code) { m_lang_code = code; } + const std::string &getLangCode() const { return m_lang_code; } + + void setCachedAddress(const Address &addr) { m_addr = addr; } + const Address &getAddress() const { return m_addr; } + private: // Version is stored in here after INIT before INIT2 - u8 m_pending_serialization_version; + u8 m_pending_serialization_version = SER_FMT_VER_INVALID; /* current state of client */ - ClientState m_state; + ClientState m_state = CS_Created; + + // Cached here so retrieval doesn't have to go to connection API + Address m_addr; + + // Client sent language code + std::string m_lang_code; /* Blocks that have been sent to client. @@ -377,13 +369,20 @@ class RemoteClient - A block is cleared from here when client says it has deleted it from it's memory - Key is position, value is dummy. + List of block positions. No MapBlock* is stored here because the blocks can get deleted. */ std::set m_blocks_sent; - s16 m_nearest_unsent_d; + s16 m_nearest_unsent_d = 0; v3s16 m_last_center; - float m_nearest_unsent_reset_timer; + v3f m_last_camera_dir; + + const u16 m_max_simul_sends; + const float m_min_time_from_building; + const s16 m_max_send_distance; + const s16 m_block_optimize_distance; + const s16 m_max_gen_distance; + const bool m_occ_cull; /* Blocks that are currently on the line. @@ -395,6 +394,16 @@ class RemoteClient */ std::map m_blocks_sending; + /* + Blocks that have been modified since blocks were + sent to the client last (getNextBlocks()). + This is used to reset the unsent distance, so that + modified blocks are resent to the client. + + List of block positions. + */ + std::set m_blocks_modified; + /* Count of excess GotBlocks(). There is an excess amount because the client sometimes @@ -402,82 +411,91 @@ class RemoteClient and the client then sends two GOTBLOCKs. This is resetted by PrintInfo() */ - u32 m_excess_gotblocks; + u32 m_excess_gotblocks = 0; // CPU usage optimization - float m_nothing_to_send_pause_timer; + float m_nothing_to_send_pause_timer = 0.0f; /* name of player using this client */ - std::string m_name; + std::string m_name = ""; /* client information - */ - u8 m_version_major; - u8 m_version_minor; - u8 m_version_patch; + */ + u8 m_version_major = 0; + u8 m_version_minor = 0; + u8 m_version_patch = 0; - std::string m_full_version; + std::string m_full_version = "unknown"; - u16 m_deployed_compression; + u16 m_deployed_compression = 0; /* time this client was created */ - const u32 m_connection_time; + const u64 m_connection_time = porting::getTimeS(); }; +typedef std::unordered_map RemoteClientMap; + class ClientInterface { public: friend class Server; - ClientInterface(con::Connection* con); + ClientInterface(const std::shared_ptr &con); ~ClientInterface(); /* run sync step */ void step(float dtime); /* get list of active client id's */ - std::vector getClientIDs(ClientState min_state=CS_Active); + std::vector getClientIDs(ClientState min_state=CS_Active); + + /* mark block as not sent to active client sessions */ + void markBlockposAsNotSent(const v3s16 &pos); + + /* verify is server user limit was reached */ + bool isUserLimitReached(); /* get list of client player names */ - std::vector getPlayerNames(); + const std::vector &getPlayerNames() const { return m_clients_names; } /* send message to client */ - void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable); + void send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable); /* send to all clients */ - void sendToAll(u16 channelnum, NetworkPacket* pkt, bool reliable); + void sendToAll(NetworkPacket *pkt); /* delete a client */ - void DeleteClient(u16 peer_id); + void DeleteClient(session_t peer_id); /* create client */ - void CreateClient(u16 peer_id); + void CreateClient(session_t peer_id); /* get a client by peer_id */ - RemoteClient* getClientNoEx(u16 peer_id, ClientState state_min=CS_Active); + RemoteClient *getClientNoEx(session_t peer_id, ClientState state_min = CS_Active); /* get client by peer_id (make sure you have list lock before!*/ - RemoteClient* lockedGetClientNoEx(u16 peer_id, ClientState state_min=CS_Active); + RemoteClient *lockedGetClientNoEx(session_t peer_id, ClientState state_min = CS_Active); /* get state of client by id*/ - ClientState getClientState(u16 peer_id); + ClientState getClientState(session_t peer_id); /* set client playername */ - void setPlayerName(u16 peer_id,std::string name); + void setPlayerName(session_t peer_id, const std::string &name); /* get protocol version of client */ - u16 getProtocolVersion(u16 peer_id); + u16 getProtocolVersion(session_t peer_id); /* set client version */ - void setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full); + void setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch, + const std::string &full); /* event to update client state */ - void event(u16 peer_id, ClientStateEvent event); + void event(session_t peer_id, ClientStateEvent event); /* Set environment. Do not call this function if environment is already set */ void setEnv(ServerEnvironment *env) @@ -487,33 +505,32 @@ class ClientInterface { } static std::string state2Name(ClientState state); - protected: - //TODO find way to avoid this functions - void lock() { m_clients_mutex.lock(); } - void unlock() { m_clients_mutex.unlock(); } + class AutoLock { + public: + AutoLock(ClientInterface &iface): m_lock(iface.m_clients_mutex) {} + + private: + RecursiveMutexAutoLock m_lock; + }; - std::map& getClientList() - { return m_clients; } + RemoteClientMap& getClientList() { return m_clients; } private: /* update internal player list */ void UpdatePlayerList(); // Connection - con::Connection* m_con; - Mutex m_clients_mutex; + std::shared_ptr m_con; + std::recursive_mutex m_clients_mutex; // Connected clients (behind the con mutex) - std::map m_clients; + RemoteClientMap m_clients; std::vector m_clients_names; //for announcing masterserver // Environment ServerEnvironment *m_env; - Mutex m_env_mutex; float m_print_info_timer; static const char *statenames[]; }; - -#endif