]> git.lizzy.rs Git - minetest.git/blob - src/server.h
Fix wctomb use
[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 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 #ifndef SERVER_HEADER
21 #define SERVER_HEADER
22
23 #include "connection.h"
24 #include "environment.h"
25 #include "irrlichttypes_bloated.h"
26 #include <string>
27 #include "porting.h"
28 #include "map.h"
29 #include "inventory.h"
30 #include "ban.h"
31 #include "gamedef.h"
32 #include "serialization.h" // For SER_FMT_VER_INVALID
33 #include "mods.h"
34 #include "inventorymanager.h"
35 #include "subgame.h"
36 #include "sound.h"
37 #include "util/thread.h"
38 #include "util/string.h"
39
40 struct LuaState;
41 typedef struct lua_State lua_State;
42 class IWritableItemDefManager;
43 class IWritableNodeDefManager;
44 class IWritableCraftDefManager;
45 class EventManager;
46 class PlayerSAO;
47
48 class ServerError : public std::exception
49 {
50 public:
51         ServerError(const std::string &s)
52         {
53                 m_s = "ServerError: ";
54                 m_s += s;
55         }
56         virtual ~ServerError() throw()
57         {}
58         virtual const char * what() const throw()
59         {
60                 return m_s.c_str();
61         }
62         std::string m_s;
63 };
64
65 /*
66         Some random functions
67 */
68 v3f findSpawnPos(ServerMap &map);
69
70 /*
71         A structure containing the data needed for queueing the fetching
72         of blocks.
73 */
74 struct QueuedBlockEmerge
75 {
76         v3s16 pos;
77         // key = peer_id, value = flags
78         core::map<u16, u8> peer_ids;
79 };
80
81 /*
82         This is a thread-safe class.
83 */
84 class BlockEmergeQueue
85 {
86 public:
87         BlockEmergeQueue()
88         {
89                 m_mutex.Init();
90         }
91
92         ~BlockEmergeQueue()
93         {
94                 JMutexAutoLock lock(m_mutex);
95
96                 core::list<QueuedBlockEmerge*>::Iterator i;
97                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
98                 {
99                         QueuedBlockEmerge *q = *i;
100                         delete q;
101                 }
102         }
103         
104         /*
105                 peer_id=0 adds with nobody to send to
106         */
107         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
108         {
109                 DSTACK(__FUNCTION_NAME);
110         
111                 JMutexAutoLock lock(m_mutex);
112
113                 if(peer_id != 0)
114                 {
115                         /*
116                                 Find if block is already in queue.
117                                 If it is, update the peer to it and quit.
118                         */
119                         core::list<QueuedBlockEmerge*>::Iterator i;
120                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
121                         {
122                                 QueuedBlockEmerge *q = *i;
123                                 if(q->pos == pos)
124                                 {
125                                         q->peer_ids[peer_id] = flags;
126                                         return;
127                                 }
128                         }
129                 }
130                 
131                 /*
132                         Add the block
133                 */
134                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
135                 q->pos = pos;
136                 if(peer_id != 0)
137                         q->peer_ids[peer_id] = flags;
138                 m_queue.push_back(q);
139         }
140
141         // Returned pointer must be deleted
142         // Returns NULL if queue is empty
143         QueuedBlockEmerge * pop()
144         {
145                 JMutexAutoLock lock(m_mutex);
146
147                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
148                 if(i == m_queue.end())
149                         return NULL;
150                 QueuedBlockEmerge *q = *i;
151                 m_queue.erase(i);
152                 return q;
153         }
154
155         u32 size()
156         {
157                 JMutexAutoLock lock(m_mutex);
158                 return m_queue.size();
159         }
160         
161         u32 peerItemCount(u16 peer_id)
162         {
163                 JMutexAutoLock lock(m_mutex);
164
165                 u32 count = 0;
166
167                 core::list<QueuedBlockEmerge*>::Iterator i;
168                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
169                 {
170                         QueuedBlockEmerge *q = *i;
171                         if(q->peer_ids.find(peer_id) != NULL)
172                                 count++;
173                 }
174
175                 return count;
176         }
177
178 private:
179         core::list<QueuedBlockEmerge*> m_queue;
180         JMutex m_mutex;
181 };
182
183 class Server;
184
185 class ServerThread : public SimpleThread
186 {
187         Server *m_server;
188
189 public:
190
191         ServerThread(Server *server):
192                 SimpleThread(),
193                 m_server(server)
194         {
195         }
196
197         void * Thread();
198 };
199
200 class EmergeThread : public SimpleThread
201 {
202         Server *m_server;
203
204 public:
205
206         EmergeThread(Server *server):
207                 SimpleThread(),
208                 m_server(server)
209         {
210         }
211
212         void * Thread();
213
214         void trigger()
215         {
216                 setRun(true);
217                 if(IsRunning() == false)
218                 {
219                         Start();
220                 }
221         }
222 };
223
224 struct PlayerInfo
225 {
226         u16 id;
227         char name[PLAYERNAME_SIZE];
228         v3f position;
229         Address address;
230         float avg_rtt;
231
232         PlayerInfo();
233         void PrintLine(std::ostream *s);
234 };
235
236 /*
237         Used for queueing and sorting block transfers in containers
238         
239         Lower priority number means higher priority.
240 */
241 struct PrioritySortedBlockTransfer
242 {
243         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
244         {
245                 priority = a_priority;
246                 pos = a_pos;
247                 peer_id = a_peer_id;
248         }
249         bool operator < (PrioritySortedBlockTransfer &other)
250         {
251                 return priority < other.priority;
252         }
253         float priority;
254         v3s16 pos;
255         u16 peer_id;
256 };
257
258 struct MediaRequest
259 {
260         std::string name;
261
262         MediaRequest(const std::string &name_=""):
263                 name(name_)
264         {}
265 };
266
267 struct MediaInfo
268 {
269         std::string path;
270         std::string sha1_digest;
271
272         MediaInfo(const std::string path_="",
273                         const std::string sha1_digest_=""):
274                 path(path_),
275                 sha1_digest(sha1_digest_)
276         {
277         }
278 };
279
280 struct ServerSoundParams
281 {
282         float gain;
283         std::string to_player;
284         enum Type{
285                 SSP_LOCAL=0,
286                 SSP_POSITIONAL=1,
287                 SSP_OBJECT=2
288         } type;
289         v3f pos;
290         u16 object;
291         float max_hear_distance;
292         bool loop;
293
294         ServerSoundParams():
295                 gain(1.0),
296                 to_player(""),
297                 type(SSP_LOCAL),
298                 pos(0,0,0),
299                 object(0),
300                 max_hear_distance(32*BS),
301                 loop(false)
302         {}
303         
304         v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
305 };
306
307 struct ServerPlayingSound
308 {
309         ServerSoundParams params;
310         std::set<u16> clients; // peer ids
311 };
312
313 class RemoteClient
314 {
315 public:
316         // peer_id=0 means this client has no associated peer
317         // NOTE: If client is made allowed to exist while peer doesn't,
318         //       this has to be set to 0 when there is no peer.
319         //       Also, the client must be moved to some other container.
320         u16 peer_id;
321         // The serialization version to use with the client
322         u8 serialization_version;
323         //
324         u16 net_proto_version;
325         // Version is stored in here after INIT before INIT2
326         u8 pending_serialization_version;
327
328         bool definitions_sent;
329
330         RemoteClient():
331                 m_time_from_building(9999),
332                 m_excess_gotblocks(0)
333         {
334                 peer_id = 0;
335                 serialization_version = SER_FMT_VER_INVALID;
336                 net_proto_version = 0;
337                 pending_serialization_version = SER_FMT_VER_INVALID;
338                 definitions_sent = false;
339                 m_nearest_unsent_d = 0;
340                 m_nearest_unsent_reset_timer = 0.0;
341                 m_nothing_to_send_counter = 0;
342                 m_nothing_to_send_pause_timer = 0;
343         }
344         ~RemoteClient()
345         {
346         }
347         
348         /*
349                 Finds block that should be sent next to the client.
350                 Environment should be locked when this is called.
351                 dtime is used for resetting send radius at slow interval
352         */
353         void GetNextBlocks(Server *server, float dtime,
354                         core::array<PrioritySortedBlockTransfer> &dest);
355
356         void GotBlock(v3s16 p);
357
358         void SentBlock(v3s16 p);
359
360         void SetBlockNotSent(v3s16 p);
361         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
362
363         s32 SendingCount()
364         {
365                 return m_blocks_sending.size();
366         }
367         
368         // Increments timeouts and removes timed-out blocks from list
369         // NOTE: This doesn't fix the server-not-sending-block bug
370         //       because it is related to emerging, not sending.
371         //void RunSendingTimeouts(float dtime, float timeout);
372
373         void PrintInfo(std::ostream &o)
374         {
375                 o<<"RemoteClient "<<peer_id<<": "
376                                 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
377                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
378                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
379                                 <<", m_excess_gotblocks="<<m_excess_gotblocks
380                                 <<std::endl;
381                 m_excess_gotblocks = 0;
382         }
383
384         // Time from last placing or removing blocks
385         float m_time_from_building;
386         
387         /*JMutex m_dig_mutex;
388         float m_dig_time_remaining;
389         // -1 = not digging
390         s16 m_dig_tool_item;
391         v3s16 m_dig_position;*/
392         
393         /*
394                 List of active objects that the client knows of.
395                 Value is dummy.
396         */
397         core::map<u16, bool> m_known_objects;
398
399 private:
400         /*
401                 Blocks that have been sent to client.
402                 - These don't have to be sent again.
403                 - A block is cleared from here when client says it has
404                   deleted it from it's memory
405                 
406                 Key is position, value is dummy.
407                 No MapBlock* is stored here because the blocks can get deleted.
408         */
409         core::map<v3s16, bool> m_blocks_sent;
410         s16 m_nearest_unsent_d;
411         v3s16 m_last_center;
412         float m_nearest_unsent_reset_timer;
413         
414         /*
415                 Blocks that are currently on the line.
416                 This is used for throttling the sending of blocks.
417                 - The size of this list is limited to some value
418                 Block is added when it is sent with BLOCKDATA.
419                 Block is removed when GOTBLOCKS is received.
420                 Value is time from sending. (not used at the moment)
421         */
422         core::map<v3s16, float> m_blocks_sending;
423
424         /*
425                 Count of excess GotBlocks().
426                 There is an excess amount because the client sometimes
427                 gets a block so late that the server sends it again,
428                 and the client then sends two GOTBLOCKs.
429                 This is resetted by PrintInfo()
430         */
431         u32 m_excess_gotblocks;
432         
433         // CPU usage optimization
434         u32 m_nothing_to_send_counter;
435         float m_nothing_to_send_pause_timer;
436 };
437
438 class Server : public con::PeerHandler, public MapEventReceiver,
439                 public InventoryManager, public IGameDef,
440                 public IBackgroundBlockEmerger
441 {
442 public:
443         /*
444                 NOTE: Every public method should be thread-safe
445         */
446         
447         Server(
448                 const std::string &path_world,
449                 const std::string &path_config,
450                 const SubgameSpec &gamespec,
451                 bool simple_singleplayer_mode
452         );
453         ~Server();
454         void start(unsigned short port);
455         void stop();
456         // This is mainly a way to pass the time to the server.
457         // Actual processing is done in an another thread.
458         void step(float dtime);
459         // This is run by ServerThread and does the actual processing
460         void AsyncRunStep();
461         void Receive();
462         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
463
464         core::list<PlayerInfo> getPlayerInfo();
465
466         // Environment must be locked when called
467         void setTimeOfDay(u32 time)
468         {
469                 m_env->setTimeOfDay(time);
470                 m_time_of_day_send_timer = 0;
471         }
472
473         bool getShutdownRequested()
474         {
475                 return m_shutdown_requested;
476         }
477         
478         /*
479                 Shall be called with the environment locked.
480                 This is accessed by the map, which is inside the environment,
481                 so it shouldn't be a problem.
482         */
483         void onMapEditEvent(MapEditEvent *event);
484
485         /*
486                 Shall be called with the environment and the connection locked.
487         */
488         Inventory* getInventory(const InventoryLocation &loc);
489         void setInventoryModified(const InventoryLocation &loc);
490
491         // Connection must be locked when called
492         std::wstring getStatusString();
493
494         void requestShutdown(void)
495         {
496                 m_shutdown_requested = true;
497         }
498
499         // Returns -1 if failed, sound handle on success
500         // Envlock + conlock
501         s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
502         void stopSound(s32 handle);
503         
504         // Envlock + conlock
505         std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
506         bool checkPriv(const std::string &name, const std::string &priv);
507         void reportPrivsModified(const std::string &name=""); // ""=all
508         void reportInventoryFormspecModified(const std::string &name);
509
510         // Saves g_settings to configpath given at initialization
511         void saveConfig();
512
513         void setIpBanned(const std::string &ip, const std::string &name)
514         {
515                 m_banmanager.add(ip, name);
516                 return;
517         }
518
519         void unsetIpBanned(const std::string &ip_or_name)
520         {
521                 m_banmanager.remove(ip_or_name);
522                 return;
523         }
524
525         std::string getBanDescription(const std::string &ip_or_name)
526         {
527                 return m_banmanager.getBanDescription(ip_or_name);
528         }
529
530         Address getPeerAddress(u16 peer_id)
531         {
532                 return m_con.GetPeerAddress(peer_id);
533         }
534         
535         // Envlock and conlock should be locked when calling this
536         void notifyPlayer(const char *name, const std::wstring msg);
537         void notifyPlayers(const std::wstring msg);
538
539         void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
540         
541         // Envlock and conlock should be locked when using Lua
542         lua_State *getLua(){ return m_lua; }
543         
544         // IGameDef interface
545         // Under envlock
546         virtual IItemDefManager* getItemDefManager();
547         virtual INodeDefManager* getNodeDefManager();
548         virtual ICraftDefManager* getCraftDefManager();
549         virtual ITextureSource* getTextureSource();
550         virtual u16 allocateUnknownNodeId(const std::string &name);
551         virtual ISoundManager* getSoundManager();
552         virtual MtEventManager* getEventManager();
553         
554         IWritableItemDefManager* getWritableItemDefManager();
555         IWritableNodeDefManager* getWritableNodeDefManager();
556         IWritableCraftDefManager* getWritableCraftDefManager();
557
558         const ModSpec* getModSpec(const std::string &modname);
559         std::string getBuiltinLuaPath();
560         
561         std::string getWorldPath(){ return m_path_world; }
562
563         bool isSingleplayer(){ return m_simple_singleplayer_mode; }
564
565         void setAsyncFatalError(const std::string &error)
566         {
567                 m_async_fatal_error.set(error);
568         }
569
570 private:
571
572         // con::PeerHandler implementation.
573         // These queue stuff to be processed by handlePeerChanges().
574         // As of now, these create and remove clients and players.
575         void peerAdded(con::Peer *peer);
576         void deletingPeer(con::Peer *peer, bool timeout);
577         
578         /*
579                 Static send methods
580         */
581         
582         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
583         static void SendAccessDenied(con::Connection &con, u16 peer_id,
584                         const std::wstring &reason);
585         static void SendDeathscreen(con::Connection &con, u16 peer_id,
586                         bool set_camera_point_target, v3f camera_point_target);
587         static void SendItemDef(con::Connection &con, u16 peer_id,
588                         IItemDefManager *itemdef);
589         static void SendNodeDef(con::Connection &con, u16 peer_id,
590                         INodeDefManager *nodedef);
591         
592         /*
593                 Non-static send methods.
594                 Conlock should be always used.
595                 Envlock usage is documented badly but it's easy to figure out
596                 which ones access the environment.
597         */
598
599         // Envlock and conlock should be locked when calling these
600         void SendInventory(u16 peer_id);
601         void SendChatMessage(u16 peer_id, const std::wstring &message);
602         void BroadcastChatMessage(const std::wstring &message);
603         void SendPlayerHP(u16 peer_id);
604         void SendMovePlayer(u16 peer_id);
605         void SendPlayerPrivileges(u16 peer_id);
606         void SendPlayerInventoryFormspec(u16 peer_id);
607         /*
608                 Send a node removal/addition event to all clients except ignore_id.
609                 Additionally, if far_players!=NULL, players further away than
610                 far_d_nodes are ignored and their peer_ids are added to far_players
611         */
612         // Envlock and conlock should be locked when calling these
613         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
614                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
615         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
616                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
617         void setBlockNotSent(v3s16 p);
618         
619         // Environment and Connection must be locked when called
620         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
621         
622         // Sends blocks to clients (locks env and con on its own)
623         void SendBlocks(float dtime);
624         
625         void fillMediaCache();
626         void sendMediaAnnouncement(u16 peer_id);
627         void sendRequestedMedia(u16 peer_id,
628                         const core::list<MediaRequest> &tosend);
629
630         /*
631                 Something random
632         */
633         
634         void DiePlayer(u16 peer_id);
635         void RespawnPlayer(u16 peer_id);
636         
637         void UpdateCrafting(u16 peer_id);
638         
639         // When called, connection mutex should be locked
640         RemoteClient* getClient(u16 peer_id);
641         
642         // When called, environment mutex should be locked
643         std::string getPlayerName(u16 peer_id)
644         {
645                 Player *player = m_env->getPlayer(peer_id);
646                 if(player == NULL)
647                         return "[id="+itos(peer_id)+"]";
648                 return player->getName();
649         }
650
651         // When called, environment mutex should be locked
652         PlayerSAO* getPlayerSAO(u16 peer_id)
653         {
654                 Player *player = m_env->getPlayer(peer_id);
655                 if(player == NULL)
656                         return NULL;
657                 return player->getPlayerSAO();
658         }
659
660         /*
661                 Get a player from memory or creates one.
662                 If player is already connected, return NULL
663                 Does not verify/modify auth info and password.
664
665                 Call with env and con locked.
666         */
667         PlayerSAO *emergePlayer(const char *name, u16 peer_id);
668         
669         // Locks environment and connection by its own
670         struct PeerChange;
671         void handlePeerChange(PeerChange &c);
672         void handlePeerChanges();
673
674         /*
675                 Variables
676         */
677         
678         // World directory
679         std::string m_path_world;
680         // Path to user's configuration file ("" = no configuration file)
681         std::string m_path_config;
682         // Subgame specification
683         SubgameSpec m_gamespec;
684         // If true, do not allow multiple players and hide some multiplayer
685         // functionality
686         bool m_simple_singleplayer_mode;
687
688         // Thread can set; step() will throw as ServerError
689         MutexedVariable<std::string> m_async_fatal_error;
690         
691         // Some timers
692         float m_liquid_transform_timer;
693         float m_print_info_timer;
694         float m_objectdata_timer;
695         float m_emergethread_trigger_timer;
696         float m_savemap_timer;
697         IntervalLimiter m_map_timer_and_unload_interval;
698         
699         // NOTE: If connection and environment are both to be locked,
700         // environment shall be locked first.
701
702         // Environment
703         ServerEnvironment *m_env;
704         JMutex m_env_mutex;
705         
706         // Connection
707         con::Connection m_con;
708         JMutex m_con_mutex;
709         // Connected clients (behind the con mutex)
710         core::map<u16, RemoteClient*> m_clients;
711
712         // Bann checking
713         BanManager m_banmanager;
714
715         // Scripting
716         // Envlock and conlock should be locked when using Lua
717         lua_State *m_lua;
718
719         // Item definition manager
720         IWritableItemDefManager *m_itemdef;
721         
722         // Node definition manager
723         IWritableNodeDefManager *m_nodedef;
724         
725         // Craft definition manager
726         IWritableCraftDefManager *m_craftdef;
727         
728         // Event manager
729         EventManager *m_event;
730         
731         // Mods
732         core::list<ModSpec> m_mods;
733         
734         /*
735                 Threads
736         */
737         
738         // A buffer for time steps
739         // step() increments and AsyncRunStep() run by m_thread reads it.
740         float m_step_dtime;
741         JMutex m_step_dtime_mutex;
742
743         // The server mainly operates in this thread
744         ServerThread m_thread;
745         // This thread fetches and generates map
746         EmergeThread m_emergethread;
747         // Queue of block coordinates to be processed by the emerge thread
748         BlockEmergeQueue m_emerge_queue;
749         
750         /*
751                 Time related stuff
752         */
753
754         // Timer for sending time of day over network
755         float m_time_of_day_send_timer;
756         // Uptime of server in seconds
757         MutexedVariable<double> m_uptime;
758         
759         /*
760                 Peer change queue.
761                 Queues stuff from peerAdded() and deletingPeer() to
762                 handlePeerChanges()
763         */
764         enum PeerChangeType
765         {
766                 PEER_ADDED,
767                 PEER_REMOVED
768         };
769         struct PeerChange
770         {
771                 PeerChangeType type;
772                 u16 peer_id;
773                 bool timeout;
774         };
775         Queue<PeerChange> m_peer_change_queue;
776
777         /*
778                 Random stuff
779         */
780         
781         // Mod parent directory paths
782         core::list<std::string> m_modspaths;
783
784         bool m_shutdown_requested;
785
786         /*
787                 Map edit event queue. Automatically receives all map edits.
788                 The constructor of this class registers us to receive them through
789                 onMapEditEvent
790
791                 NOTE: Should these be moved to actually be members of
792                 ServerEnvironment?
793         */
794
795         /*
796                 Queue of map edits from the environment for sending to the clients
797                 This is behind m_env_mutex
798         */
799         Queue<MapEditEvent*> m_unsent_map_edit_queue;
800         /*
801                 Set to true when the server itself is modifying the map and does
802                 all sending of information by itself.
803                 This is behind m_env_mutex
804         */
805         bool m_ignore_map_edit_events;
806         /*
807                 If a non-empty area, map edit events contained within are left
808                 unsent. Done at map generation time to speed up editing of the
809                 generated area, as it will be sent anyway.
810                 This is behind m_env_mutex
811         */
812         VoxelArea m_ignore_map_edit_events_area;
813         /*
814                 If set to !=0, the incoming MapEditEvents are modified to have
815                 this peed id as the disabled recipient
816                 This is behind m_env_mutex
817         */
818         u16 m_ignore_map_edit_events_peer_id;
819
820         friend class EmergeThread;
821         friend class RemoteClient;
822
823         std::map<std::string,MediaInfo> m_media;
824
825         /*
826                 Sounds
827         */
828         std::map<s32, ServerPlayingSound> m_playing_sounds;
829         s32 m_next_sound_id;
830 };
831
832 /*
833         Runs a simple dedicated server loop.
834
835         Shuts down when run is set to false.
836 */
837 void dedicated_server_loop(Server &server, bool &run);
838
839 #endif
840