]> git.lizzy.rs Git - dragonfireclient.git/blob - src/clientiface.h
Merge branch 'master' into master
[dragonfireclient.git] / src / clientiface.h
1 /*
2 Minetest
3 Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #pragma once
21
22 #include "irr_v3d.h" // for irrlicht datatypes
23
24 #include "constants.h"
25 #include "serialization.h" // for SER_FMT_VER_INVALID
26 #include "network/networkpacket.h"
27 #include "network/networkprotocol.h"
28 #include "porting.h"
29
30 #include <list>
31 #include <vector>
32 #include <set>
33 #include <mutex>
34
35 class MapBlock;
36 class ServerEnvironment;
37 class EmergeManager;
38
39 /*
40  * State Transitions
41
42       Start
43   (peer connect)
44         |
45         v
46       /-----------------\
47       |                 |
48       |    Created      |
49       |                 |
50       \-----------------/
51                |                  depending of the incoming packet
52                ----------------------------------------
53                                                       v
54                                        +-----------------------------+
55                                        |IN:                          |
56                                        | TOSERVER_INIT               |
57                                        +-----------------------------+
58                                                       | invalid playername
59                                                       | or denied by mod
60                                                       v
61                                        +-----------------------------+
62                                        |OUT:                         |
63                                        | TOCLIENT_HELLO              |
64                                        +-----------------------------+
65                                                       |
66                                                       |
67                                                       v
68       /-----------------\                    /-----------------\
69       |                 |                    |                 |
70       |  AwaitingInit2  |<---------          |    HelloSent    |
71       |                 |         |          |                 |
72       \-----------------/         |          \-----------------/
73                |                  |                   |
74 +-----------------------------+   |    *-----------------------------*     Auth fails
75 |IN:                          |   |    |Authentication, depending on |------------------
76 | TOSERVER_INIT2              |   |    | packet sent by client       |                 |
77 +-----------------------------+   |    *-----------------------------*                 |
78                |                  |                   |                                |
79                |                  |                   | Authentication                 |
80                v                  |                   |  successful                    |
81       /-----------------\         |                   v                                |
82       |                 |         |    +-----------------------------+                 |
83       |    InitDone     |         |    |OUT:                         |                 |
84       |                 |         |    | TOCLIENT_AUTH_ACCEPT        |                 |
85       \-----------------/         |    +-----------------------------+                 |
86                |                  |                   |                                |
87 +-----------------------------+   ---------------------                                |
88 |OUT:                         |                                                        |
89 | TOCLIENT_MOVEMENT           |                                                        |
90 | TOCLIENT_ITEMDEF            |                                                        |
91 | TOCLIENT_NODEDEF            |                                                        |
92 | TOCLIENT_ANNOUNCE_MEDIA     |                                                        |
93 | TOCLIENT_DETACHED_INVENTORY |                                                        |
94 | TOCLIENT_TIME_OF_DAY        |                                                        |
95 +-----------------------------+                                                        |
96                |                                                                       |
97                |                                                                       |
98                |      -----------------------------                                    |
99                v      |                           |                                    |
100       /-----------------\                         v                                    |
101       |                 |             +-----------------------------+                  |
102       | DefinitionsSent |             |IN:                          |                  |
103       |                 |             | TOSERVER_REQUEST_MEDIA      |                  |
104       \-----------------/             |                             |                  |
105                |                      +-----------------------------+                  |
106                |      ^                           |                                    |
107                |      -----------------------------                                    |
108                v                                                                       v
109 +-----------------------------+                        --------------------------------+
110 |IN:                          |                        |                               ^
111 | TOSERVER_CLIENT_READY       |                        v                               |
112 +-----------------------------+            +------------------------+                  |
113                |                           |OUT:                    |                  |
114                v                           | TOCLIENT_ACCESS_DENIED |                  |
115 +-----------------------------+            +------------------------+                  |
116 |OUT:                         |                        |                               |
117 | TOCLIENT_MOVE_PLAYER        |                        v                               |
118 | TOCLIENT_PRIVILEGES         |                /-----------------\                     |
119 | TOCLIENT_INVENTORY_FORMSPEC |                |                 |                     |
120 | UpdateCrafting              |                |     Denied      |                     |
121 | TOCLIENT_INVENTORY          |                |                 |                     |
122 | TOCLIENT_HP (opt)           |                \-----------------/                     |
123 | TOCLIENT_BREATH             |                                                        |
124 | TOCLIENT_DEATHSCREEN        |                                                        |
125 +-----------------------------+                                                        |
126               |                                                                        |
127               v                                                                        |
128       /-----------------\      async mod action (ban, kick)                            |
129       |                 |---------------------------------------------------------------
130  ---->|     Active      |
131  |    |                 |----------------------------------------------
132  |    \-----------------/      timeout                                v
133  |       |           |                                  +-----------------------------+
134  |       |           |                                  |OUT:                         |
135  |       |           |                                  | TOCLIENT_DISCONNECT         |
136  |       |           |                                  +-----------------------------+
137  |       |           |                                                |
138  |       |           v                                                v
139  |       |  +-----------------------------+                    /-----------------\
140  |       |  |IN:                          |                    |                 |
141  |       |  | TOSERVER_DISCONNECT         |------------------->|  Disconnecting  |
142  |       |  +-----------------------------+                    |                 |
143  |       |                                                     \-----------------/
144  |       | any auth packet which was
145  |       | allowed in TOCLIENT_AUTH_ACCEPT
146  |       v
147  |    *-----------------------------* Auth      +-------------------------------+
148  |    |Authentication, depending on | succeeds  |OUT:                           |
149  |    | packet sent by client       |---------->| TOCLIENT_ACCEPT_SUDO_MODE     |
150  |    *-----------------------------*           +-------------------------------+
151  |                  |                                            |
152  |                  | Auth fails                        /-----------------\
153  |                  v                                   |                 |
154  |    +-------------------------------+                 |    SudoMode     |
155  |    |OUT:                           |                 |                 |
156  |    | TOCLIENT_DENY_SUDO_MODE       |                 \-----------------/
157  |    +-------------------------------+                          |
158  |                  |                                            v
159  |                  |                               +-----------------------------+
160  |                  |    sets password accordingly  |IN:                          |
161  -------------------+-------------------------------| TOSERVER_FIRST_SRP          |
162                                                     +-----------------------------+
163
164 */
165 namespace con
166 {
167 class Connection;
168 }
169
170 // Also make sure to update the ClientInterface::statenames
171 // array when modifying these enums
172
173 enum ClientState
174 {
175         CS_Invalid,
176         CS_Disconnecting,
177         CS_Denied,
178         CS_Created,
179         CS_AwaitingInit2,
180         CS_HelloSent,
181         CS_InitDone,
182         CS_DefinitionsSent,
183         CS_Active,
184         CS_SudoMode
185 };
186
187 enum ClientStateEvent
188 {
189         CSE_Hello,
190         CSE_AuthAccept,
191         CSE_InitLegacy,
192         CSE_GotInit2,
193         CSE_SetDenied,
194         CSE_SetDefinitionsSent,
195         CSE_SetClientReady,
196         CSE_SudoSuccess,
197         CSE_SudoLeave,
198         CSE_Disconnect
199 };
200
201 /*
202         Used for queueing and sorting block transfers in containers
203
204         Lower priority number means higher priority.
205 */
206 struct PrioritySortedBlockTransfer
207 {
208         PrioritySortedBlockTransfer(
209                         float a_priority, const v3s16 &a_pos, session_t a_peer_id)
210         {
211                 priority = a_priority;
212                 pos = a_pos;
213                 peer_id = a_peer_id;
214         }
215         bool operator<(const PrioritySortedBlockTransfer &other) const
216         {
217                 return priority < other.priority;
218         }
219         float priority;
220         v3s16 pos;
221         session_t peer_id;
222 };
223
224 class RemoteClient
225 {
226 public:
227         // peer_id=0 means this client has no associated peer
228         // NOTE: If client is made allowed to exist while peer doesn't,
229         //       this has to be set to 0 when there is no peer.
230         //       Also, the client must be moved to some other container.
231         session_t peer_id = PEER_ID_INEXISTENT;
232         // The serialization version to use with the client
233         u8 serialization_version = SER_FMT_VER_INVALID;
234         //
235         u16 net_proto_version = 0;
236
237         /* Authentication information */
238         std::string enc_pwd = "";
239         bool create_player_on_auth_success = false;
240         AuthMechanism chosen_mech = AUTH_MECHANISM_NONE;
241         void *auth_data = nullptr;
242         u32 allowed_auth_mechs = 0;
243         u32 allowed_sudo_mechs = 0;
244
245         bool isSudoMechAllowed(AuthMechanism mech) { return allowed_sudo_mechs & mech; }
246         bool isMechAllowed(AuthMechanism mech) { return allowed_auth_mechs & mech; }
247
248         RemoteClient();
249         ~RemoteClient() = default;
250
251         /*
252                 Finds block that should be sent next to the client.
253                 Environment should be locked when this is called.
254                 dtime is used for resetting send radius at slow interval
255         */
256         void GetNextBlocks(ServerEnvironment *env, EmergeManager *emerge, float dtime,
257                         std::vector<PrioritySortedBlockTransfer> &dest);
258
259         void GotBlock(v3s16 p);
260
261         void SentBlock(v3s16 p);
262
263         void SetBlockNotSent(v3s16 p);
264         void SetBlocksNotSent(std::map<v3s16, MapBlock *> &blocks);
265
266         /**
267          * tell client about this block being modified right now.
268          * this information is required to requeue the block in case it's "on wire"
269          * while modification is processed by server
270          * @param p position of modified block
271          */
272         void ResendBlockIfOnWire(v3s16 p);
273
274         u32 getSendingCount() const { return m_blocks_sending.size(); }
275
276         bool isBlockSent(v3s16 p) const
277         {
278                 return m_blocks_sent.find(p) != m_blocks_sent.end();
279         }
280
281         // Increments timeouts and removes timed-out blocks from list
282         // NOTE: This doesn't fix the server-not-sending-block bug
283         //       because it is related to emerging, not sending.
284         // void RunSendingTimeouts(float dtime, float timeout);
285
286         void PrintInfo(std::ostream &o)
287         {
288                 o << "RemoteClient " << peer_id << ": "
289                   << "m_blocks_sent.size()=" << m_blocks_sent.size()
290                   << ", m_blocks_sending.size()=" << m_blocks_sending.size()
291                   << ", m_nearest_unsent_d=" << m_nearest_unsent_d
292                   << ", m_excess_gotblocks=" << m_excess_gotblocks << std::endl;
293                 m_excess_gotblocks = 0;
294         }
295
296         // Time from last placing or removing blocks
297         float m_time_from_building = 9999;
298
299         /*
300                 List of active objects that the client knows of.
301         */
302         std::set<u16> m_known_objects;
303
304         ClientState getState() const { return m_state; }
305
306         std::string getName() const { return m_name; }
307
308         void setName(const std::string &name) { m_name = name; }
309
310         /* update internal client state */
311         void notifyEvent(ClientStateEvent event);
312
313         /* set expected serialization version */
314         void setPendingSerializationVersion(u8 version)
315         {
316                 m_pending_serialization_version = version;
317         }
318
319         void setDeployedCompressionMode(u16 byteFlag)
320         {
321                 m_deployed_compression = byteFlag;
322         }
323
324         void confirmSerializationVersion()
325         {
326                 serialization_version = m_pending_serialization_version;
327         }
328
329         /* get uptime */
330         u64 uptime() const;
331
332         /* set version information */
333         void setVersionInfo(u8 major, u8 minor, u8 patch, const std::string &full)
334         {
335                 m_version_major = major;
336                 m_version_minor = minor;
337                 m_version_patch = patch;
338                 m_full_version = full;
339         }
340
341         /* read version information */
342         u8 getMajor() const { return m_version_major; }
343         u8 getMinor() const { return m_version_minor; }
344         u8 getPatch() const { return m_version_patch; }
345         const std::string &getFull() const { return m_full_version; }
346
347         void setLangCode(const std::string &code) { m_lang_code = code; }
348         const std::string &getLangCode() const { return m_lang_code; }
349
350 private:
351         // Version is stored in here after INIT before INIT2
352         u8 m_pending_serialization_version = SER_FMT_VER_INVALID;
353
354         /* current state of client */
355         ClientState m_state = CS_Created;
356
357         // Client sent language code
358         std::string m_lang_code;
359
360         /*
361                 Blocks that have been sent to client.
362                 - These don't have to be sent again.
363                 - A block is cleared from here when client says it has
364                   deleted it from it's memory
365
366                 List of block positions.
367                 No MapBlock* is stored here because the blocks can get deleted.
368         */
369         std::set<v3s16> m_blocks_sent;
370         s16 m_nearest_unsent_d = 0;
371         v3s16 m_last_center;
372         float m_nearest_unsent_reset_timer = 0.0f;
373
374         const u16 m_max_simul_sends;
375         const float m_min_time_from_building;
376         const s16 m_max_send_distance;
377         const s16 m_block_optimize_distance;
378         const s16 m_max_gen_distance;
379         const bool m_occ_cull;
380
381         /*
382                 Blocks that are currently on the line.
383                 This is used for throttling the sending of blocks.
384                 - The size of this list is limited to some value
385                 Block is added when it is sent with BLOCKDATA.
386                 Block is removed when GOTBLOCKS is received.
387                 Value is time from sending. (not used at the moment)
388         */
389         std::map<v3s16, float> m_blocks_sending;
390
391         /*
392                 Blocks that have been modified since last sending them.
393                 These blocks will not be marked as sent, even if the
394                 client reports it has received them to account for blocks
395                 that are being modified while on the line.
396
397                 List of block positions.
398         */
399         std::set<v3s16> m_blocks_modified;
400
401         /*
402                 Count of excess GotBlocks().
403                 There is an excess amount because the client sometimes
404                 gets a block so late that the server sends it again,
405                 and the client then sends two GOTBLOCKs.
406                 This is resetted by PrintInfo()
407         */
408         u32 m_excess_gotblocks = 0;
409
410         // CPU usage optimization
411         float m_nothing_to_send_pause_timer = 0.0f;
412
413         /*
414                 name of player using this client
415         */
416         std::string m_name = "";
417
418         /*
419                 client information
420          */
421         u8 m_version_major = 0;
422         u8 m_version_minor = 0;
423         u8 m_version_patch = 0;
424
425         std::string m_full_version = "unknown";
426
427         u16 m_deployed_compression = 0;
428
429         /*
430                 time this client was created
431          */
432         const u64 m_connection_time = porting::getTimeS();
433 };
434
435 typedef std::unordered_map<u16, RemoteClient *> RemoteClientMap;
436
437 class ClientInterface
438 {
439 public:
440         friend class Server;
441
442         ClientInterface(const std::shared_ptr<con::Connection> &con);
443         ~ClientInterface();
444
445         /* run sync step */
446         void step(float dtime);
447
448         /* get list of active client id's */
449         std::vector<session_t> getClientIDs(ClientState min_state = CS_Active);
450
451         /* mark block as not sent to active client sessions */
452         void markBlockposAsNotSent(const v3s16 &pos);
453
454         /* verify is server user limit was reached */
455         bool isUserLimitReached();
456
457         /* get list of client player names */
458         const std::vector<std::string> &getPlayerNames() const { return m_clients_names; }
459
460         /* send message to client */
461         void send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
462
463         /* send to all clients */
464         void sendToAll(NetworkPacket *pkt);
465         void sendToAllCompat(
466                         NetworkPacket *pkt, NetworkPacket *legacypkt, u16 min_proto_ver);
467
468         /* delete a client */
469         void DeleteClient(session_t peer_id);
470
471         /* create client */
472         void CreateClient(session_t peer_id);
473
474         /* get a client by peer_id */
475         RemoteClient *getClientNoEx(session_t peer_id, ClientState state_min = CS_Active);
476
477         /* get client by peer_id (make sure you have list lock before!*/
478         RemoteClient *lockedGetClientNoEx(
479                         session_t peer_id, ClientState state_min = CS_Active);
480
481         /* get state of client by id*/
482         ClientState getClientState(session_t peer_id);
483
484         /* set client playername */
485         void setPlayerName(session_t peer_id, const std::string &name);
486
487         /* get protocol version of client */
488         u16 getProtocolVersion(session_t peer_id);
489
490         /* set client version */
491         void setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
492                         const std::string &full);
493
494         /* event to update client state */
495         void event(session_t peer_id, ClientStateEvent event);
496
497         /* Set environment. Do not call this function if environment is already set */
498         void setEnv(ServerEnvironment *env)
499         {
500                 assert(m_env == NULL); // pre-condition
501                 m_env = env;
502         }
503
504         static std::string state2Name(ClientState state);
505
506 protected:
507         // TODO find way to avoid this functions
508         void lock() { m_clients_mutex.lock(); }
509         void unlock() { m_clients_mutex.unlock(); }
510
511         RemoteClientMap &getClientList() { return m_clients; }
512
513 private:
514         /* update internal player list */
515         void UpdatePlayerList();
516
517         // Connection
518         std::shared_ptr<con::Connection> m_con;
519         std::recursive_mutex m_clients_mutex;
520         // Connected clients (behind the con mutex)
521         RemoteClientMap m_clients;
522         std::vector<std::string> m_clients_names; // for announcing masterserver
523
524         // Environment
525         ServerEnvironment *m_env;
526
527         float m_print_info_timer;
528
529         static const char *statenames[];
530 };