hopefully fixed the privilege problems
[oweals/minetest.git] / src / server.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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 /*
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
22 */
23
24 #ifndef SERVER_HEADER
25 #define SERVER_HEADER
26
27 #include "connection.h"
28 #include "environment.h"
29 #include "common_irrlicht.h"
30 #include <string>
31 #include "utility.h"
32 #include "porting.h"
33 #include "map.h"
34 #include "inventory.h"
35 #include "auth.h"
36
37 /*
38         Some random functions
39 */
40 v3f findSpawnPos(ServerMap &map);
41
42 /*
43         A structure containing the data needed for queueing the fetching
44         of blocks.
45 */
46 struct QueuedBlockEmerge
47 {
48         v3s16 pos;
49         // key = peer_id, value = flags
50         core::map<u16, u8> peer_ids;
51 };
52
53 /*
54         This is a thread-safe class.
55 */
56 class BlockEmergeQueue
57 {
58 public:
59         BlockEmergeQueue()
60         {
61                 m_mutex.Init();
62         }
63
64         ~BlockEmergeQueue()
65         {
66                 JMutexAutoLock lock(m_mutex);
67
68                 core::list<QueuedBlockEmerge*>::Iterator i;
69                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
70                 {
71                         QueuedBlockEmerge *q = *i;
72                         delete q;
73                 }
74         }
75         
76         /*
77                 peer_id=0 adds with nobody to send to
78         */
79         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
80         {
81                 DSTACK(__FUNCTION_NAME);
82         
83                 JMutexAutoLock lock(m_mutex);
84
85                 if(peer_id != 0)
86                 {
87                         /*
88                                 Find if block is already in queue.
89                                 If it is, update the peer to it and quit.
90                         */
91                         core::list<QueuedBlockEmerge*>::Iterator i;
92                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
93                         {
94                                 QueuedBlockEmerge *q = *i;
95                                 if(q->pos == pos)
96                                 {
97                                         q->peer_ids[peer_id] = flags;
98                                         return;
99                                 }
100                         }
101                 }
102                 
103                 /*
104                         Add the block
105                 */
106                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
107                 q->pos = pos;
108                 if(peer_id != 0)
109                         q->peer_ids[peer_id] = flags;
110                 m_queue.push_back(q);
111         }
112
113         // Returned pointer must be deleted
114         // Returns NULL if queue is empty
115         QueuedBlockEmerge * pop()
116         {
117                 JMutexAutoLock lock(m_mutex);
118
119                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
120                 if(i == m_queue.end())
121                         return NULL;
122                 QueuedBlockEmerge *q = *i;
123                 m_queue.erase(i);
124                 return q;
125         }
126
127         u32 size()
128         {
129                 JMutexAutoLock lock(m_mutex);
130                 return m_queue.size();
131         }
132         
133         u32 peerItemCount(u16 peer_id)
134         {
135                 JMutexAutoLock lock(m_mutex);
136
137                 u32 count = 0;
138
139                 core::list<QueuedBlockEmerge*>::Iterator i;
140                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
141                 {
142                         QueuedBlockEmerge *q = *i;
143                         if(q->peer_ids.find(peer_id) != NULL)
144                                 count++;
145                 }
146
147                 return count;
148         }
149
150 private:
151         core::list<QueuedBlockEmerge*> m_queue;
152         JMutex m_mutex;
153 };
154
155 class Server;
156
157 class ServerThread : public SimpleThread
158 {
159         Server *m_server;
160
161 public:
162
163         ServerThread(Server *server):
164                 SimpleThread(),
165                 m_server(server)
166         {
167         }
168
169         void * Thread();
170 };
171
172 class EmergeThread : public SimpleThread
173 {
174         Server *m_server;
175
176 public:
177
178         EmergeThread(Server *server):
179                 SimpleThread(),
180                 m_server(server)
181         {
182         }
183
184         void * Thread();
185
186         void trigger()
187         {
188                 setRun(true);
189                 if(IsRunning() == false)
190                 {
191                         Start();
192                 }
193         }
194 };
195
196 struct PlayerInfo
197 {
198         u16 id;
199         char name[PLAYERNAME_SIZE];
200         v3f position;
201         Address address;
202         float avg_rtt;
203
204         PlayerInfo();
205         void PrintLine(std::ostream *s);
206 };
207
208 u32 PIChecksum(core::list<PlayerInfo> &l);
209
210 /*
211         Used for queueing and sorting block transfers in containers
212         
213         Lower priority number means higher priority.
214 */
215 struct PrioritySortedBlockTransfer
216 {
217         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
218         {
219                 priority = a_priority;
220                 pos = a_pos;
221                 peer_id = a_peer_id;
222         }
223         bool operator < (PrioritySortedBlockTransfer &other)
224         {
225                 return priority < other.priority;
226         }
227         float priority;
228         v3s16 pos;
229         u16 peer_id;
230 };
231
232 class RemoteClient
233 {
234 public:
235         // peer_id=0 means this client has no associated peer
236         // NOTE: If client is made allowed to exist while peer doesn't,
237         //       this has to be set to 0 when there is no peer.
238         //       Also, the client must be moved to some other container.
239         u16 peer_id;
240         // The serialization version to use with the client
241         u8 serialization_version;
242         // Version is stored in here after INIT before INIT2
243         u8 pending_serialization_version;
244
245         RemoteClient():
246                 m_time_from_building(9999),
247                 m_excess_gotblocks(0)
248         {
249                 peer_id = 0;
250                 serialization_version = SER_FMT_VER_INVALID;
251                 pending_serialization_version = SER_FMT_VER_INVALID;
252                 m_nearest_unsent_d = 0;
253                 m_nearest_unsent_reset_timer = 0.0;
254                 m_nothing_to_send_counter = 0;
255                 m_nothing_to_send_pause_timer = 0;
256         }
257         ~RemoteClient()
258         {
259         }
260         
261         /*
262                 Finds block that should be sent next to the client.
263                 Environment should be locked when this is called.
264                 dtime is used for resetting send radius at slow interval
265         */
266         void GetNextBlocks(Server *server, float dtime,
267                         core::array<PrioritySortedBlockTransfer> &dest);
268
269         /*
270                 Connection and environment should be locked when this is called.
271                 steps() objects of blocks not found in active_blocks, then
272                 adds those blocks to active_blocks
273         */
274         void SendObjectData(
275                         Server *server,
276                         float dtime,
277                         core::map<v3s16, bool> &stepped_blocks
278                 );
279
280         void GotBlock(v3s16 p);
281
282         void SentBlock(v3s16 p);
283
284         void SetBlockNotSent(v3s16 p);
285         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
286
287         s32 SendingCount()
288         {
289                 return m_blocks_sending.size();
290         }
291         
292         // Increments timeouts and removes timed-out blocks from list
293         // NOTE: This doesn't fix the server-not-sending-block bug
294         //       because it is related to emerging, not sending.
295         //void RunSendingTimeouts(float dtime, float timeout);
296
297         void PrintInfo(std::ostream &o)
298         {
299                 o<<"RemoteClient "<<peer_id<<": "
300                                 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
301                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
302                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
303                                 <<", m_excess_gotblocks="<<m_excess_gotblocks
304                                 <<std::endl;
305                 m_excess_gotblocks = 0;
306         }
307
308         // Time from last placing or removing blocks
309         float m_time_from_building;
310         
311         /*JMutex m_dig_mutex;
312         float m_dig_time_remaining;
313         // -1 = not digging
314         s16 m_dig_tool_item;
315         v3s16 m_dig_position;*/
316         
317         /*
318                 List of active objects that the client knows of.
319                 Value is dummy.
320         */
321         core::map<u16, bool> m_known_objects;
322
323 private:
324         /*
325                 Blocks that have been sent to client.
326                 - These don't have to be sent again.
327                 - A block is cleared from here when client says it has
328                   deleted it from it's memory
329                 
330                 Key is position, value is dummy.
331                 No MapBlock* is stored here because the blocks can get deleted.
332         */
333         core::map<v3s16, bool> m_blocks_sent;
334         s16 m_nearest_unsent_d;
335         v3s16 m_last_center;
336         float m_nearest_unsent_reset_timer;
337         
338         /*
339                 Blocks that are currently on the line.
340                 This is used for throttling the sending of blocks.
341                 - The size of this list is limited to some value
342                 Block is added when it is sent with BLOCKDATA.
343                 Block is removed when GOTBLOCKS is received.
344                 Value is time from sending. (not used at the moment)
345         */
346         core::map<v3s16, float> m_blocks_sending;
347
348         /*
349                 Count of excess GotBlocks().
350                 There is an excess amount because the client sometimes
351                 gets a block so late that the server sends it again,
352                 and the client then sends two GOTBLOCKs.
353                 This is resetted by PrintInfo()
354         */
355         u32 m_excess_gotblocks;
356         
357         // CPU usage optimization
358         u32 m_nothing_to_send_counter;
359         float m_nothing_to_send_pause_timer;
360 };
361
362 class Server : public con::PeerHandler, public MapEventReceiver,
363                 public InventoryManager
364 {
365 public:
366         /*
367                 NOTE: Every public method should be thread-safe
368         */
369
370         Server(
371                 std::string mapsavedir
372         );
373         ~Server();
374         void start(unsigned short port);
375         void stop();
376         // This is mainly a way to pass the time to the server.
377         // Actual processing is done in an another thread.
378         void step(float dtime);
379         // This is run by ServerThread and does the actual processing
380         void AsyncRunStep();
381         void Receive();
382         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
383
384         core::list<PlayerInfo> getPlayerInfo();
385
386         /*u32 getDayNightRatio()
387         {
388                 return time_to_daynight_ratio(m_time_of_day.get());
389         }*/
390         
391         // Environment must be locked when called
392         void setTimeOfDay(u32 time)
393         {
394                 m_env.setTimeOfDay(time);
395                 m_time_of_day_send_timer = 0;
396         }
397
398         bool getShutdownRequested()
399         {
400                 return m_shutdown_requested;
401         }
402         
403         /*
404                 Shall be called with the environment locked.
405                 This is accessed by the map, which is inside the environment,
406                 so it shouldn't be a problem.
407         */
408         void onMapEditEvent(MapEditEvent *event);
409
410         /*
411                 Shall be called with the environment and the connection locked.
412         */
413         Inventory* getInventory(InventoryContext *c, std::string id);
414         void inventoryModified(InventoryContext *c, std::string id);
415
416         // Connection must be locked when called
417         std::wstring getStatusString();
418
419         void requestShutdown(void)
420         {
421                 m_shutdown_requested = true;
422         }
423
424
425         // Envlock and conlock should be locked when calling this
426         void SendMovePlayer(Player *player);
427         
428         u64 getPlayerAuthPrivs(const std::string &name)
429         {
430                 try{
431                         return m_authmanager.getPrivs(name);
432                 }
433                 catch(AuthNotFoundException &e)
434                 {
435                         dstream<<"WARNING: Auth not found for "<<name<<std::endl;
436                         return 0;
437                 }
438         }
439
440         void setPlayerAuthPrivs(const std::string &name, u64 privs)
441         {
442                 try{
443                         return m_authmanager.setPrivs(name, privs);
444                 }
445                 catch(AuthNotFoundException &e)
446                 {
447                         dstream<<"WARNING: Auth not found for "<<name<<std::endl;
448                 }
449         }
450
451 private:
452
453         // con::PeerHandler implementation.
454         // These queue stuff to be processed by handlePeerChanges().
455         // As of now, these create and remove clients and players.
456         void peerAdded(con::Peer *peer);
457         void deletingPeer(con::Peer *peer, bool timeout);
458         
459         /*
460                 Static send methods
461         */
462         
463         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
464         static void SendAccessDenied(con::Connection &con, u16 peer_id,
465                         const std::wstring &reason);
466         
467         /*
468                 Non-static send methods
469         */
470
471         // Envlock and conlock should be locked when calling these
472         void SendObjectData(float dtime);
473         void SendPlayerInfos();
474         void SendInventory(u16 peer_id);
475         void SendChatMessage(u16 peer_id, const std::wstring &message);
476         void BroadcastChatMessage(const std::wstring &message);
477         void SendPlayerHP(Player *player);
478         /*
479                 Send a node removal/addition event to all clients except ignore_id.
480                 Additionally, if far_players!=NULL, players further away than
481                 far_d_nodes are ignored and their peer_ids are added to far_players
482         */
483         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
484                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
485         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
486                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
487         
488         // Environment and Connection must be locked when called
489         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
490         
491         // Sends blocks to clients
492         void SendBlocks(float dtime);
493
494         /*
495                 Something random
496         */
497         
498         void UpdateCrafting(u16 peer_id);
499         
500         // When called, connection mutex should be locked
501         RemoteClient* getClient(u16 peer_id);
502         
503         /*
504                 Get a player from memory or creates one.
505                 If player is already connected, return NULL
506                 The password is not checked here - it is only used to
507                 set the password if a new player is created.
508
509                 Call with env and con locked.
510         */
511         Player *emergePlayer(const char *name, const char *password, u16 peer_id);
512         
513         // Locks environment and connection by its own
514         struct PeerChange;
515         void handlePeerChange(PeerChange &c);
516         void handlePeerChanges();
517
518         u64 getPlayerPrivs(Player *player);
519
520         /*
521                 Variables
522         */
523         
524         // Some timers
525         float m_liquid_transform_timer;
526         float m_print_info_timer;
527         float m_objectdata_timer;
528         float m_emergethread_trigger_timer;
529         float m_savemap_timer;
530         
531         // NOTE: If connection and environment are both to be locked,
532         // environment shall be locked first.
533
534         // Environment
535         ServerEnvironment m_env;
536         JMutex m_env_mutex;
537         
538         // Connection
539         con::Connection m_con;
540         JMutex m_con_mutex;
541         // Connected clients (behind the con mutex)
542         core::map<u16, RemoteClient*> m_clients;
543
544         // User authentication
545         AuthManager m_authmanager;
546         
547         /*
548                 Threads
549         */
550         
551         // A buffer for time steps
552         // step() increments and AsyncRunStep() run by m_thread reads it.
553         float m_step_dtime;
554         JMutex m_step_dtime_mutex;
555
556         // The server mainly operates in this thread
557         ServerThread m_thread;
558         // This thread fetches and generates map
559         EmergeThread m_emergethread;
560         // Queue of block coordinates to be processed by the emerge thread
561         BlockEmergeQueue m_emerge_queue;
562         
563         /*
564                 Time related stuff
565         */
566
567         // 0-23999
568         //MutexedVariable<u32> m_time_of_day;
569         // Used to buffer dtime for adding to m_time_of_day
570         float m_time_counter;
571         // Timer for sending time of day over network
572         float m_time_of_day_send_timer;
573         // Uptime of server in seconds
574         MutexedVariable<double> m_uptime;
575         
576         /*
577                 Peer change queue.
578                 Queues stuff from peerAdded() and deletingPeer() to
579                 handlePeerChanges()
580         */
581         enum PeerChangeType
582         {
583                 PEER_ADDED,
584                 PEER_REMOVED
585         };
586         struct PeerChange
587         {
588                 PeerChangeType type;
589                 u16 peer_id;
590                 bool timeout;
591         };
592         Queue<PeerChange> m_peer_change_queue;
593
594         /*
595                 Random stuff
596         */
597
598         // Map directory
599         std::string m_mapsavedir;
600
601         bool m_shutdown_requested;
602         
603         /*
604                 Map edit event queue. Automatically receives all map edits.
605                 The constructor of this class registers us to receive them through
606                 onMapEditEvent
607
608                 NOTE: Should these be moved to actually be members of
609                 ServerEnvironment?
610         */
611
612         /*
613                 Queue of map edits from the environment for sending to the clients
614                 This is behind m_env_mutex
615         */
616         Queue<MapEditEvent*> m_unsent_map_edit_queue;
617         /*
618                 Set to true when the server itself is modifying the map and does
619                 all sending of information by itself.
620                 This is behind m_env_mutex
621         */
622         bool m_ignore_map_edit_events;
623         /*
624                 If set to !=0, the incoming MapEditEvents are modified to have
625                 this peed id as the disabled recipient
626                 This is behind m_env_mutex
627         */
628         u16 m_ignore_map_edit_events_peer_id;
629
630         friend class EmergeThread;
631         friend class RemoteClient;
632 };
633
634 /*
635         Runs a simple dedicated server loop.
636
637         Shuts down when run is set to false.
638 */
639 void dedicated_server_loop(Server &server, bool &run);
640
641 #endif
642