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