X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclientiface.h;h=cc5292b71bf96fb5b2c8d9063921fc8ff18c7f15;hb=ce0d81a8255886495f5b04ea385b9e37c554db57;hp=95f8bd30531241f25c80887b589ce98c216a3060;hpb=7cdbb805d9f230b2cf00150884dc3fa4fbcde16f;p=dragonfireclient.git diff --git a/src/clientiface.h b/src/clientiface.h index 95f8bd305..cc5292b71 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -16,19 +16,22 @@ 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 "jthread/jmutex.h" +#include "network/networkpacket.h" +#include "network/networkprotocol.h" +#include "network/address.h" +#include "porting.h" #include #include -#include #include +#include class MapBlock; class ServerEnvironment; @@ -46,132 +49,153 @@ class EmergeManager; | Created | | | \-----------------/ - | - | -+-----------------------------+ invalid playername, password -|IN: | or denied by mod -| TOSERVER_INIT |------------------------------ -+-----------------------------+ | - | | - | Auth ok | - | | -+-----------------------------+ | -|OUT: | | -| TOCLIENT_INIT | | -+-----------------------------+ | - | | - v | - /-----------------\ | - | | | - | InitSent | | - | | | - \-----------------/ +------------------ - | | | -+-----------------------------+ +-----------------------------+ | -|IN: | |OUT: | | -| TOSERVER_INIT2 | | TOCLIENT_ACCESS_DENIED | | -+-----------------------------+ +-----------------------------+ | - | | | - v v | - /-----------------\ /-----------------\ | - | | | | | - | InitDone | | Denied | | - | | | | | - \-----------------/ \-----------------/ | - | | -+-----------------------------+ | -|OUT: | | -| TOCLIENT_MOVEMENT | | -| TOCLIENT_ITEMDEF | | -| TOCLIENT_NODEDEF | | -| TOCLIENT_ANNOUNCE_MEDIA | | -| TOCLIENT_DETACHED_INVENTORY | | -| TOCLIENT_TIME_OF_DAY | | -+-----------------------------+ | - | | - | | - | ----------------------------------- | - v | | | - /-----------------\ v | - | | +-----------------------------+ | - | DefinitionsSent | |IN: | | - | | | TOSERVER_REQUEST_MEDIA | | - \-----------------/ | TOSERVER_RECEIVED_MEDIA | | - | +-----------------------------+ | - | ^ | | - | ----------------------------------- | - | | -+-----------------------------+ | -|IN: | | -| TOSERVER_CLIENT_READY | | -+-----------------------------+ | - | async | - v mod action | -+-----------------------------+ (ban,kick) | -|OUT: | | -| TOCLIENT_MOVE_PLAYER | | -| TOCLIENT_PRIVILEGES | | -| TOCLIENT_INVENTORY_FORMSPEC | | -| UpdateCrafting | | -| TOCLIENT_INVENTORY | | -| TOCLIENT_HP (opt) | | -| TOCLIENT_BREATH | | -| TOCLIENT_DEATHSCREEN | | -+-----------------------------+ | - | | - v | - /-----------------\ | - | |------------------------------------------------------ - | Active | - | |---------------------------------- - \-----------------/ timeout | - | +-----------------------------+ - | |OUT: | - | | TOCLIENT_DISCONNECT | - | +-----------------------------+ - | | - | v -+-----------------------------+ /-----------------\ -|IN: | | | -| TOSERVER_DISCONNECT |------------------->| Disconnecting | -+-----------------------------+ | | - \-----------------/ + | depending of the incoming packet + ---------------------------------------- + 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 | | ++-----------------------------+ | *-----------------------------* | + | | | | + | | | Authentication | + v | | successful | + /-----------------\ | v | + | | | +-----------------------------+ | + | InitDone | | |OUT: | | + | | | | TOCLIENT_AUTH_ACCEPT | | + \-----------------/ | +-----------------------------+ | + | | | | ++-----------------------------+ --------------------- | +|OUT: | | +| TOCLIENT_MOVEMENT | | +| TOCLIENT_ITEMDEF | | +| TOCLIENT_NODEDEF | | +| TOCLIENT_ANNOUNCE_MEDIA | | +| TOCLIENT_DETACHED_INVENTORY | | +| TOCLIENT_TIME_OF_DAY | | ++-----------------------------+ | + | | + | | + | ----------------------------- | + v | | | + /-----------------\ v | + | | +-----------------------------+ | + | DefinitionsSent | |IN: | | + | | | TOSERVER_REQUEST_MEDIA | | + \-----------------/ | | | + | +-----------------------------+ | + | ^ | | + | ----------------------------- | + v v ++-----------------------------+ --------------------------------+ +|IN: | | ^ +| TOSERVER_CLIENT_READY | v | ++-----------------------------+ +------------------------+ | + | |OUT: | | + v | TOCLIENT_ACCESS_DENIED | | ++-----------------------------+ +------------------------+ | +|OUT: | | | +| TOCLIENT_MOVE_PLAYER | v | +| TOCLIENT_PRIVILEGES | /-----------------\ | +| TOCLIENT_INVENTORY_FORMSPEC | | | | +| UpdateCrafting | | Denied | | +| TOCLIENT_INVENTORY | | | | +| TOCLIENT_HP (opt) | \-----------------/ | +| TOCLIENT_BREATH | | +| TOCLIENT_DEATHSCREEN | | ++-----------------------------+ | + | | + v | + /-----------------\ async mod action (ban, kick) | + | |--------------------------------------------------------------- + ---->| Active | + | | |---------------------------------------------- + | \-----------------/ timeout v + | | | +-----------------------------+ + | | | |OUT: | + | | | | TOCLIENT_DISCONNECT | + | | | +-----------------------------+ + | | | | + | | v v + | | +-----------------------------+ /-----------------\ + | | |IN: | | | + | | | TOSERVER_DISCONNECT |------------------->| Disconnecting | + | | +-----------------------------+ | | + | | \-----------------/ + | | any auth packet which was + | | allowed in TOCLIENT_AUTH_ACCEPT + | v + | *-----------------------------* Auth +-------------------------------+ + | |Authentication, depending on | succeeds |OUT: | + | | packet sent by client |---------->| TOCLIENT_ACCEPT_SUDO_MODE | + | *-----------------------------* +-------------------------------+ + | | | + | | Auth fails /-----------------\ + | v | | + | +-------------------------------+ | SudoMode | + | |OUT: | | | + | | TOCLIENT_DENY_SUDO_MODE | \-----------------/ + | +-------------------------------+ | + | | v + | | +-----------------------------+ + | | sets password accordingly |IN: | + -------------------+-------------------------------| TOSERVER_FIRST_SRP | + +-----------------------------+ + */ namespace con { class Connection; } + +// Also make sure to update the ClientInterface::statenames +// array when modifying these enums + enum ClientState { - Invalid, - Disconnecting, - Denied, - Created, - InitSent, - InitDone, - DefinitionsSent, - Active -}; - -static const char* statenames[] = { - "Invalid", - "Disconnecting", - "Denied", - "Created", - "InitSent", - "InitDone", - "DefinitionsSent", - "Active" + CS_Invalid, + CS_Disconnecting, + CS_Denied, + CS_Created, + CS_AwaitingInit2, + CS_HelloSent, + CS_InitDone, + CS_DefinitionsSent, + CS_Active, + CS_SudoMode }; enum ClientStateEvent { - Init, - GotInit2, - SetDenied, - SetDefinitionsSent, - SetClientReady, - Disconnect + CSE_Hello, + CSE_AuthAccept, + CSE_GotInit2, + CSE_SetDenied, + CSE_SetDefinitionsSent, + CSE_SetClientReady, + CSE_SudoSuccess, + CSE_SudoLeave, + CSE_Disconnect }; /* @@ -181,7 +205,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; @@ -193,7 +217,7 @@ struct PrioritySortedBlockTransfer } float priority; v3s16 pos; - u16 peer_id; + session_t peer_id; }; class RemoteClient @@ -203,35 +227,27 @@ 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; - - RemoteClient(): - peer_id(PEER_ID_INEXISTENT), - serialization_version(SER_FMT_VER_INVALID), - net_proto_version(0), - m_time_from_building(9999), - m_pending_serialization_version(SER_FMT_VER_INVALID), - m_state(Created), - m_nearest_unsent_d(0), - m_nearest_unsent_reset_timer(0.0), - m_excess_gotblocks(0), - m_nothing_to_send_counter(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_connection_time(getTime(PRECISION_SECONDS)) - { - } - ~RemoteClient() - { - } + u16 net_proto_version = 0; + + /* Authentication information */ + 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; + + bool isSudoMechAllowed(AuthMechanism mech) + { return allowed_sudo_mechs & mech; } + bool isMechAllowed(AuthMechanism mech) + { return allowed_auth_mechs & mech; } + + RemoteClient(); + ~RemoteClient() = default; /* Finds block that should be sent next to the client. @@ -248,9 +264,19 @@ class RemoteClient void SetBlockNotSent(v3s16 p); void SetBlocksNotSent(std::map &blocks); - s32 SendingCount() + /** + * tell client about this block being modified right now. + * this information is required to requeue the block in case it's "on wire" + * while modification is processed by server + * @param p position of modified block + */ + void ResendBlockIfOnWire(v3s16 p); + + 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 @@ -270,22 +296,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); @@ -294,15 +316,18 @@ class RemoteClient void setPendingSerializationVersion(u8 version) { m_pending_serialization_version = version; } + void setDeployedCompressionMode(u16 byteFlag) + { m_deployed_compression = byteFlag; } + void confirmSerializationVersion() { 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; @@ -310,16 +335,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. @@ -327,13 +365,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. @@ -345,6 +390,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 @@ -352,117 +407,123 @@ 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 - u32 m_nothing_to_send_counter; - 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 = "unknown"; - std::string m_full_version; + 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::list getClientIDs(ClientState min_state=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, SharedBuffer data, bool reliable); + void send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable); /* send to all clients */ - void sendToAll(u16 channelnum, SharedBuffer data, bool reliable); + void sendToAll(NetworkPacket *pkt); + void sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt, u16 min_proto_ver); /* 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=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=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 */ - void setEnv(ServerEnvironment* env) - { assert(m_env == 0); m_env = env; } - - static std::string state2Name(ClientState state) { - assert(state < sizeof(statenames)); - return statenames[state]; + /* Set environment. Do not call this function if environment is already set */ + void setEnv(ServerEnvironment *env) + { + assert(m_env == NULL); // pre-condition + m_env = env; } + 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(); } + void lock() { m_clients_mutex.lock(); } + void unlock() { m_clients_mutex.unlock(); } - std::map& getClientList() - { return m_clients; } + RemoteClientMap& getClientList() { return m_clients; } private: /* update internal player list */ void UpdatePlayerList(); // Connection - con::Connection* m_con; - JMutex 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; - JMutex m_env_mutex; float m_print_info_timer; -}; -#endif + static const char *statenames[]; +};