#include "constants.h"
#include "serialization.h" // for SER_FMT_VER_INVALID
-#include "jthread/jmutex.h"
+#include "threading/mutex.h"
+#include "network/networkpacket.h"
+#include "util/cpp11_container.h"
+#include "porting.h"
#include <list>
#include <vector>
-#include <map>
#include <set>
class MapBlock;
| 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 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 |-----------------+
+| 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 | |
+ \-----------------/ | TOSERVER_RECEIVED_MEDIA | |
+ | +-----------------------------+ |
+ | ^ | |
+ | ----------------------------- |
+ v |
++-----------------------------+ --------------------------------+
+|IN: | | |
+| TOSERVER_CLIENT_READY | v |
++-----------------------------+ +-------------------------------+ |
+ | |OUT: | |
+ v | TOCLIENT_ACCESS_DENIED_LEGAGY | |
++-----------------------------+ +-------------------------------+ |
+|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 = (const char*[]) {
- "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_InitLegacy,
+ CSE_GotInit2,
+ CSE_SetDenied,
+ CSE_SetDefinitionsSent,
+ CSE_SetClientReady,
+ CSE_SudoSuccess,
+ CSE_SudoLeave,
+ CSE_Disconnect
};
/*
//
u16 net_proto_version;
+ /* 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;
+
+ 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(Created),
+ m_state(CS_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))
+ m_deployed_compression(0),
+ m_connection_time(porting::getTime(PRECISION_SECONDS))
{
}
~RemoteClient()
void SetBlockNotSent(v3s16 p);
void SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks);
+ /**
+ * 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);
+
s32 SendingCount()
{
return m_blocks_sending.size();
/*
List of active objects that the client knows of.
- Value is dummy.
*/
std::set<u16> 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);
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();
-
/* 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;
}
/* 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; }
+ std::string getVersion() const { return m_full_version; }
private:
// Version is stored in here after INIT before INIT2
u8 m_pending_serialization_version;
- 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<v3s16> m_blocks_sent;
*/
std::map<v3s16, float> m_blocks_sending;
+ /*
+ Blocks that have been modified since last sending them.
+ These blocks will not be marked as sent, even if the
+ client reports it has received them to account for blocks
+ that are being modified while on the line.
+
+ List of block positions.
+ */
+ std::set<v3s16> m_blocks_modified;
+
/*
Count of excess GotBlocks().
There is an excess amount because the client sometimes
u32 m_excess_gotblocks;
// CPU usage optimization
- u32 m_nothing_to_send_counter;
float m_nothing_to_send_pause_timer;
/*
std::string m_full_version;
+ u16 m_deployed_compression;
+
/*
time this client was created
*/
void step(float dtime);
/* get list of active client id's */
- std::list<u16> getClientIDs(ClientState min_state=Active);
+ std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
/* get list of client player names */
- std::vector<std::string> getPlayerNames();
+ const std::vector<std::string> &getPlayerNames() const { return m_clients_names; }
/* send message to client */
- void send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
+ void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
/* send to all clients */
- void sendToAll(u16 channelnum, SharedBuffer<u8> data, bool reliable);
+ void sendToAll(NetworkPacket *pkt);
/* delete a client */
void DeleteClient(u16 peer_id);
void CreateClient(u16 peer_id);
/* get a client by peer_id */
- RemoteClient* getClientNoEx(u16 peer_id, ClientState state_min=Active);
+ RemoteClient* getClientNoEx(u16 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(u16 peer_id, ClientState state_min=CS_Active);
/* get state of client by id*/
ClientState getClientState(u16 peer_id);
/* event to update client state */
void event(u16 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<u16, RemoteClient*>& getClientList()
- { return m_clients; }
+ UNORDERED_MAP<u16, RemoteClient*>& getClientList() { return m_clients; }
private:
/* update internal player list */
// Connection
con::Connection* m_con;
- JMutex m_clients_mutex;
+ Mutex m_clients_mutex;
// Connected clients (behind the con mutex)
- std::map<u16, RemoteClient*> m_clients;
+ UNORDERED_MAP<u16, RemoteClient*> m_clients;
std::vector<std::string> m_clients_names; //for announcing masterserver
// Environment
ServerEnvironment *m_env;
- JMutex m_env_mutex;
+ Mutex m_env_mutex;
float m_print_info_timer;
+
+ static const char *statenames[];
};
#endif