removed library dependency to glib-2.0
[rocksndiamonds.git] / src / netserv.c
1 // ============================================================================
2 // Rocks'n'Diamonds - McDuffin Strikes Back!
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  https://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // netserv.c
10 // ============================================================================
11
12 #include <fcntl.h>
13 #include <sys/time.h>
14 #include <signal.h>
15 #include <errno.h>
16
17 #include "libgame/libgame.h"
18
19 #include "netserv.h"
20 #include "main.h"
21
22
23 static int num_clients = 0;
24 static boolean run_server_only_once = FALSE;
25
26 struct NetworkServerPlayerInfo
27 {
28   TCPsocket fd;
29   char player_name[MAX_PLAYER_NAME_LEN + 1];
30   int number;
31   boolean active;
32   boolean introduced;
33   byte action;
34   boolean action_received;
35
36   struct NetworkServerPlayerInfo *next;
37 };
38
39 static struct NetworkServerPlayerInfo *first_player = NULL;
40
41 #define NEXT(player) ((player)->next ? (player)->next : first_player)
42
43 // TODO: peer address
44 static TCPsocket lfd;           // listening TCP socket
45 static UDPsocket udp;           // listening UDP socket
46 static SDLNet_SocketSet fds;    // socket set
47
48 static struct NetworkBuffer *read_buffer = NULL;
49 static struct NetworkBuffer *write_buffer = NULL;
50
51 static unsigned int ServerFrameCounter = 0;
52
53
54 int getNetwork8BitInteger(byte *ptr)
55 {
56   return ptr[0];
57 }
58
59 int putNetwork8BitInteger(byte *ptr, int value)
60 {
61   ptr[0] = value;
62
63   return 1;
64 }
65
66 int getNetwork16BitInteger(byte *ptr)
67 {
68   return ((ptr[0] << 8) |
69           (ptr[1] << 0));
70 }
71
72 int putNetwork16BitInteger(byte *ptr, int value)
73 {
74   ptr[0] = (value >> 8) & 0xff;
75   ptr[1] = (value >> 0) & 0xff;
76
77   return 2;
78 }
79
80 int getNetwork32BitInteger(byte *ptr)
81 {
82   return ((ptr[0] << 24) |
83           (ptr[1] << 16) |
84           (ptr[2] <<  8) |
85           (ptr[3] <<  0));
86 }
87
88 int putNetwork32BitInteger(byte *ptr, int value)
89 {
90   ptr[0] = (value >> 24) & 0xff;
91   ptr[1] = (value >> 16) & 0xff;
92   ptr[2] = (value >>  8) & 0xff;
93   ptr[3] = (value >>  0) & 0xff;
94
95   return 4;
96 }
97
98 char *getNetworkString(byte *ptr)
99 {
100   return (char *)ptr;
101 }
102
103 int putNetworkString(byte *ptr, char *s)
104 {
105   strcpy((char *)ptr, s);
106
107   return strlen(s) + 1;
108 }
109
110 struct NetworkBuffer *newNetworkBuffer(void)
111 {
112   struct NetworkBuffer *new = checked_calloc(sizeof(struct NetworkBuffer));
113
114   new->max_size = MAX_BUFFER_SIZE;
115   new->size = 0;
116   new->pos = 0;
117
118   new->buffer = checked_calloc(new->max_size);
119
120   return new;
121 }
122
123 static void resetNetworkBufferForReading(struct NetworkBuffer *nb)
124 {
125   nb->pos = 0;
126 }
127
128 static void resetNetworkBufferForWriting(struct NetworkBuffer *nb)
129 {
130   nb->size = 0;
131   nb->pos = 0;
132 }
133
134 void initNetworkBufferForReceiving(struct NetworkBuffer *nb)
135 {
136   resetNetworkBufferForWriting(nb);
137 }
138
139 void initNetworkBufferForReading(struct NetworkBuffer *nb)
140 {
141   resetNetworkBufferForReading(nb);
142
143   // skip message length header
144   getNetworkBuffer32BitInteger(nb);
145 }
146
147 void initNetworkBufferForWriting(struct NetworkBuffer *nb, int message_type,
148                                  int player_nr)
149 {
150   resetNetworkBufferForWriting(nb);
151
152   // will be replaced with message length before sending
153   putNetworkBuffer32BitInteger(nb, 0);
154
155   putNetworkBuffer8BitInteger(nb, message_type);
156   putNetworkBuffer8BitInteger(nb, player_nr);
157 }
158
159 static void copyNetworkBufferForWriting(struct NetworkBuffer *nb_from,
160                                         struct NetworkBuffer *nb_to,
161                                         int player_nr)
162 {
163   initNetworkBufferForReading(nb_from);
164
165   int message_type = getNetworkBuffer8BitInteger(nb_from);
166
167   // skip player number
168   getNetworkBuffer8BitInteger(nb_from);
169
170   initNetworkBufferForWriting(nb_to, message_type, player_nr);
171
172   while (nb_from->pos < nb_from->size)
173   {
174     int b = getNetworkBuffer8BitInteger(nb_from);
175
176     putNetworkBuffer8BitInteger(nb_to, b);
177   }
178 }
179
180 static void increaseNetworkBuffer(struct NetworkBuffer *nb, int additional_size)
181 {
182   // add some more buffer size than is really required this time
183   nb->max_size += additional_size + MAX_BUFFER_SIZE;
184   nb->buffer = checked_realloc(nb->buffer, nb->max_size);
185 }
186
187 int receiveNetworkBufferBytes(struct NetworkBuffer *nb, TCPsocket socket,
188                              int num_bytes)
189 {
190   if (num_bytes > MAX_PACKET_SIZE)
191   {
192     Debug("network:server", "protocol error: invalid packet size %d",
193           num_bytes);
194
195     return -1;
196   }
197
198   if (nb->pos + num_bytes > nb->max_size)
199     increaseNetworkBuffer(nb, num_bytes);
200
201   int result = SDLNet_TCP_Recv(socket, &nb->buffer[nb->pos], num_bytes);
202
203   if (result != num_bytes)
204     return result;
205
206   nb->pos += num_bytes;
207   nb->size = nb->pos;
208
209   return num_bytes;
210 }
211
212 int receiveNetworkBufferPacket(struct NetworkBuffer *nb, TCPsocket socket)
213 {
214   int num_bytes, num_bytes_head, num_bytes_body;
215
216   num_bytes_head = 4;
217   num_bytes = receiveNetworkBufferBytes(nb, socket, num_bytes_head);
218
219   if (num_bytes != num_bytes_head)
220     return num_bytes;
221
222   num_bytes_body = getNetwork32BitInteger(nb->buffer);
223   num_bytes = receiveNetworkBufferBytes(nb, socket, num_bytes_body);
224
225   return num_bytes;
226 }
227
228 int getNetworkBuffer8BitInteger(struct NetworkBuffer *nb)
229 {
230   int num_bytes = 1;
231
232   if (nb->pos + num_bytes > nb->size)
233     return 0;
234
235   int value = getNetwork8BitInteger(&nb->buffer[nb->pos]);
236
237   nb->pos += num_bytes;
238
239   return value;
240 }
241
242 void putNetworkBuffer8BitInteger(struct NetworkBuffer *nb, int value)
243 {
244   int num_bytes = 1;
245
246   if (nb->pos + num_bytes > nb->max_size)
247     increaseNetworkBuffer(nb, num_bytes);
248
249   nb->pos += putNetwork8BitInteger(&nb->buffer[nb->pos], value);
250   nb->size = nb->pos;
251 }
252
253 int getNetworkBuffer16BitInteger(struct NetworkBuffer *nb)
254 {
255   int num_bytes = 2;
256
257   if (nb->pos + num_bytes > nb->size)
258     return 0;
259
260   int value = getNetwork16BitInteger(&nb->buffer[nb->pos]);
261
262   nb->pos += num_bytes;
263
264   return value;
265 }
266
267 void putNetworkBuffer16BitInteger(struct NetworkBuffer *nb, int value)
268 {
269   int num_bytes = 2;
270
271   if (nb->pos + num_bytes > nb->max_size)
272     increaseNetworkBuffer(nb, num_bytes);
273
274   nb->pos += putNetwork16BitInteger(&nb->buffer[nb->pos], value);
275   nb->size = nb->pos;
276 }
277
278 int getNetworkBuffer32BitInteger(struct NetworkBuffer *nb)
279 {
280   int num_bytes = 4;
281
282   if (nb->pos + num_bytes > nb->size)
283     return 0;
284
285   int value = getNetwork32BitInteger(&nb->buffer[nb->pos]);
286
287   nb->pos += num_bytes;
288
289   return value;
290 }
291
292 void putNetworkBuffer32BitInteger(struct NetworkBuffer *nb, int value)
293 {
294   int num_bytes = 4;
295
296   if (nb->pos + num_bytes > nb->max_size)
297     increaseNetworkBuffer(nb, num_bytes);
298
299   nb->pos += putNetwork32BitInteger(&nb->buffer[nb->pos], value);
300   nb->size = nb->pos;
301 }
302
303 char *getNetworkBufferString(struct NetworkBuffer *nb)
304 {
305   char *s = getNetworkString(&nb->buffer[nb->pos]);
306
307   nb->pos += strlen(s) + 1;
308
309   return s;
310 }
311
312 void putNetworkBufferString(struct NetworkBuffer *nb, char *s)
313 {
314   int num_bytes = strlen(s) + 1;
315
316   if (nb->pos + num_bytes > nb->max_size)
317     increaseNetworkBuffer(nb, num_bytes);
318
319   nb->pos += putNetworkString(&nb->buffer[nb->pos], s);
320   nb->size = nb->pos;
321 }
322
323 int getNetworkBufferFile(struct NetworkBuffer *nb, char *filename)
324 {
325   FILE *file;
326   int num_bytes = getNetworkBuffer32BitInteger(nb);
327   int i;
328
329   if (!(file = fopen(filename, MODE_WRITE)))
330   {
331     Warn("cannot write file '%s' from network buffer", filename);
332
333     return 0;
334   }
335
336   for (i = 0; i < num_bytes; i++)
337   {
338     int b = getNetworkBuffer8BitInteger(nb);
339
340     putFile8Bit(file, b);
341   }
342
343   fclose(file);
344
345   return num_bytes;
346 }
347
348 int putNetworkBufferFile(struct NetworkBuffer *nb, char *filename)
349 {
350   File *file;
351   int filesize_pos = nb->pos;
352   int num_bytes = 0;
353
354   // will be replaced with file size
355   putNetworkBuffer32BitInteger(nb, 0);
356
357   if (!(file = openFile(filename, MODE_READ)))
358   {
359     Warn("cannot read file '%s' to network buffer", filename);
360
361     return 0;
362   }
363
364   while (1)
365   {
366     int b = getFile8Bit(file);
367
368     if (checkEndOfFile(file))
369       break;
370
371     putNetworkBuffer8BitInteger(nb, b);
372
373     num_bytes++;
374   }
375
376   closeFile(file);
377
378   // set file size
379   putNetwork32BitInteger(&nb->buffer[filesize_pos], num_bytes);
380
381   return num_bytes;
382 }
383
384 void dumpNetworkBuffer(struct NetworkBuffer *nb)
385 {
386   int i;
387
388   Debug("network:buffer", "network buffer maximum size: %d\n", nb->max_size);
389   Debug("network:buffer", "network buffer size:         %d\n", nb->size);
390   Debug("network:buffer", "network buffer position    : %d\n", nb->pos);
391
392   for (i = 0; i < nb->size; i++)
393   {
394     if ((i % 16) == 0)
395       DebugContinued("network:buffer", "\n");
396
397     DebugContinued("", "%02x ", nb->buffer[i]);
398   }
399
400   DebugContinued("network:buffer", "\n");
401 }
402
403 static void SendNetworkBufferToAllButOne(struct NetworkBuffer *nb,
404                                          struct NetworkServerPlayerInfo *except)
405 {
406   struct NetworkServerPlayerInfo *player;
407
408   // set message length header
409   putNetwork32BitInteger(nb->buffer, nb->size - 4);
410
411   for (player = first_player; player != NULL; player = player->next)
412   {
413     if (player != except && player->introduced)
414     {
415       // directly send the buffer to the network client
416       SDLNet_TCP_Send(player->fd, nb->buffer, nb->size);
417     }
418   }
419 }
420
421 static void SendNetworkBufferToAll(struct NetworkBuffer *nb)
422 {
423   SendNetworkBufferToAllButOne(nb, NULL);
424 }
425
426 static void SendNetworkBufferToClient(struct NetworkBuffer *nb,
427                                       struct NetworkServerPlayerInfo *player)
428 {
429   // set message length header
430   putNetwork32BitInteger(nb->buffer, nb->size - 4);
431
432   // directly send the buffer to the network client
433   SDLNet_TCP_Send(player->fd, nb->buffer, nb->size);
434 }
435
436 static void RemovePlayer(struct NetworkServerPlayerInfo *player)
437 {
438   Debug("network:server", "dropping client %d (%s)",
439         player->number, player->player_name);
440
441   SDLNet_TCP_DelSocket(fds, player->fd);
442   SDLNet_TCP_Close(player->fd);
443
444   if (player == first_player)
445   {
446     first_player = player->next;
447   }
448   else
449   {
450     struct NetworkServerPlayerInfo *p;
451
452     for (p = first_player; p != NULL; p = p->next)
453     {
454       if (p->next && p->next == player)
455       {
456         p->next = player->next;
457
458         break;
459       }
460     }
461   }
462
463   if (player->introduced)
464   {
465     initNetworkBufferForWriting(write_buffer, OP_PLAYER_DISCONNECTED,
466                                 player->number);
467
468     SendNetworkBufferToAllButOne(write_buffer, player);
469   }
470
471   free(player);
472   num_clients--;
473
474 #if 0   // do not terminate network server if last player disconnected
475   if (run_server_only_once && num_clients == 0)
476   {
477     Debug("network:server", "no clients left");
478     Debug("network:server", "aborting");
479
480     exit(0);
481   }
482 #endif
483 }
484
485 static void AddPlayer(TCPsocket fd)
486 {
487   struct NetworkServerPlayerInfo *player, *p;
488   int number = 1;
489   boolean again = TRUE;
490
491   SDLNet_TCP_AddSocket(fds, fd);
492
493   player = checked_calloc(sizeof(struct NetworkServerPlayerInfo));
494
495   player->fd = fd;
496   player->player_name[0] = 0;
497   player->active = FALSE;
498   player->introduced = FALSE;
499   player->action = 0;
500   player->action_received = FALSE;
501   player->next = first_player;
502
503   first_player = player;
504
505   while (again)
506   {
507     again = FALSE;
508     p = player->next;
509
510     while (p)
511     {
512       if (p->number == number)
513       {
514         number++;
515
516         again = TRUE;
517
518         break;
519       }
520
521       p = p->next;
522     }
523   }
524
525   player->number = number;
526   num_clients++;
527
528   initNetworkBufferForWriting(write_buffer, OP_YOUR_NUMBER, 0);
529
530   putNetworkBuffer8BitInteger(write_buffer, player->number);
531
532   SendNetworkBufferToClient(write_buffer, player);
533 }
534
535 static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *player)
536 {
537   int protocol_version_major = getNetworkBuffer8BitInteger(read_buffer);
538   int protocol_version_minor = getNetworkBuffer8BitInteger(read_buffer);
539   int protocol_version_patch = getNetworkBuffer8BitInteger(read_buffer);
540
541   if (protocol_version_major != PROTOCOL_VERSION_MAJOR ||
542       protocol_version_minor != PROTOCOL_VERSION_MINOR)
543   {
544     Debug("network:server",
545           "client %d (%s) has wrong protocol version %d.%d.%d",
546           player->number, player->player_name,
547           protocol_version_major,
548           protocol_version_minor,
549           protocol_version_patch);
550
551     initNetworkBufferForWriting(write_buffer, OP_BAD_PROTOCOL_VERSION, 0);
552
553     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_MAJOR);
554     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_MINOR);
555     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_PATCH);
556
557     SendNetworkBufferToClient(write_buffer, player);
558
559     RemovePlayer(player);
560   }
561   else
562   {
563     Debug("network:server",
564           "client %d (%s) uses protocol version %d.%d.%d",
565           player->number, player->player_name,
566           protocol_version_major,
567           protocol_version_minor,
568           protocol_version_patch);
569   }
570 }
571
572 static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *player)
573 {
574   int nr_wanted = getNetworkBuffer8BitInteger(read_buffer);
575   int client_nr = player->number;
576   boolean nr_is_free = TRUE;
577   struct NetworkServerPlayerInfo *p;
578
579   Debug("network:server", "client %d (%s) wants to switch to # %d",
580         player->number, player->player_name, nr_wanted);
581
582   for (p = first_player; p != NULL; p = p->next)
583   {
584     if (p->number == nr_wanted)
585     {
586       nr_is_free = FALSE;
587
588       break;
589     }
590   }
591
592   if (nr_is_free)
593     Debug("network:server", "client %d (%s) switches to # %d",
594           player->number, player->player_name, nr_wanted);
595   else if (player->number == nr_wanted)
596     Debug("network:server", "client %d (%s) already has # %d",
597           player->number, player->player_name, nr_wanted);
598   else
599     Debug("network:server",
600           "client %d (%s) cannot switch (client %d already exists)",
601           player->number, player->player_name, nr_wanted);
602
603   if (nr_is_free)
604     player->number = nr_wanted;
605
606   initNetworkBufferForWriting(write_buffer, OP_NUMBER_WANTED, client_nr);
607
608   putNetworkBuffer8BitInteger(write_buffer, nr_wanted);
609   putNetworkBuffer8BitInteger(write_buffer, player->number);
610
611   SendNetworkBufferToAll(write_buffer);
612 }
613
614 static void Handle_OP_PLAYER_NAME(struct NetworkServerPlayerInfo *player)
615 {
616   char *player_name = getNetworkBufferString(read_buffer);
617   int i;
618
619   strncpy(player->player_name, player_name, MAX_PLAYER_NAME_LEN);
620   player->player_name[MAX_PLAYER_NAME_LEN] = '\0';
621
622   for (i = 0; i < MAX_PLAYER_NAME_LEN; i++)
623   {
624     if (player->player_name[i] < ' ' ||
625         ((unsigned char)(player->player_name[i]) > 0x7e &&
626          (unsigned char)(player->player_name[i]) <= 0xa0))
627     {
628       player->player_name[i] = 0;
629
630       break;
631     }
632   }
633
634   if (!player->introduced)
635   {
636     initNetworkBufferForWriting(write_buffer, OP_PLAYER_CONNECTED,
637                                 player->number);
638
639     SendNetworkBufferToAllButOne(write_buffer, player);
640   }
641               
642   Debug("network:server", "client %d calls itself \"%s\"",
643         player->number, player->player_name);
644
645   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
646
647   SendNetworkBufferToAllButOne(write_buffer, player);
648
649   if (!player->introduced)
650   {
651     struct NetworkServerPlayerInfo *p;
652
653     for (p = first_player; p != NULL; p = p->next)
654     {
655       if (p != player && p->introduced)
656       {
657         initNetworkBufferForWriting(write_buffer, OP_PLAYER_CONNECTED,
658                                     p->number);
659
660         SendNetworkBufferToClient(write_buffer, player);
661
662         initNetworkBufferForWriting(write_buffer, OP_PLAYER_NAME, p->number);
663
664         putNetworkBufferString(write_buffer, p->player_name);
665
666         SendNetworkBufferToClient(write_buffer, player);
667       }
668     }
669   }
670
671   player->introduced = TRUE;
672 }
673
674 static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *player)
675 {
676   char *new_leveldir_identifier = getNetworkBufferString(read_buffer);
677   int level_nr = getNetworkBuffer16BitInteger(read_buffer);
678
679   Debug("network:server",
680         "client %d (%s) starts game [level %d from level set '%s']",
681         player->number, player->player_name, level_nr,
682         new_leveldir_identifier);
683
684   struct NetworkServerPlayerInfo *p;
685
686   // reset frame counter
687   ServerFrameCounter = 0;
688
689   Debug("network:server", "resetting ServerFrameCounter to 0");
690
691   // reset player actions
692   for (p = first_player; p != NULL; p = p->next)
693   {
694     p->action = 0;
695     p->action_received = FALSE;
696
697     if (p->introduced)
698       p->active = TRUE;
699   }
700
701   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
702
703   SendNetworkBufferToAll(write_buffer);
704 }
705
706 static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *player)
707 {
708   Debug("network:server", "client %d (%s) pauses game",
709         player->number, player->player_name);
710
711   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
712
713   SendNetworkBufferToAll(write_buffer);
714 }
715
716 static void Handle_OP_CONTINUE_PLAYING(struct NetworkServerPlayerInfo *player)
717 {
718   Debug("network:server", "client %d (%s) continues game",
719         player->number, player->player_name);
720
721   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
722
723   SendNetworkBufferToAll(write_buffer);
724 }
725
726 static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
727 {
728   int cause_for_stopping = getNetworkBuffer8BitInteger(read_buffer);
729
730   Debug("network:server", "client %d (%s) stops game [%d]",
731         player->number, player->player_name, cause_for_stopping);
732
733   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
734
735   SendNetworkBufferToAll(write_buffer);
736 }
737
738 static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
739 {
740   int player_action = getNetworkBuffer8BitInteger(read_buffer);
741   int last_client_nr = 0;
742   struct NetworkServerPlayerInfo *p;
743   int i;
744
745   // store player action
746   for (p = first_player; p != NULL; p = p->next)
747   {
748     if (p->number == player->number)
749     {
750       p->action = player_action;
751       p->action_received = TRUE;
752     }
753   }
754
755   // check if server received action from each player
756   for (p = first_player; p != NULL; p = p->next)
757   {
758     if (!p->action_received)
759       return;
760
761     if (p->number > last_client_nr)
762       last_client_nr = p->number;
763   }
764
765   int player_action_all[last_client_nr];
766
767   // initialize all player actions to zero
768   for (i = 0; i < last_client_nr; i++)
769     player_action_all[i] = 0;
770
771   // broadcast actions of all players to all players
772   for (p = first_player; p != NULL; p = p->next)
773   {
774     player_action_all[p->number - 1] = p->action;
775
776     p->action = 0;
777     p->action_received = FALSE;
778   }
779
780   initNetworkBufferForWriting(write_buffer, OP_MOVE_PLAYER, player->number);
781
782   putNetworkBuffer32BitInteger(write_buffer, ServerFrameCounter);
783
784   for (i = 0; i < last_client_nr; i++)
785     putNetworkBuffer8BitInteger(write_buffer, player_action_all[i]);
786
787   SendNetworkBufferToAll(write_buffer);
788
789   ServerFrameCounter++;
790 }
791
792 static void Handle_OP_BROADCAST_MESSAGE(struct NetworkServerPlayerInfo *player)
793 {
794   char *message = getNetworkBufferString(read_buffer);
795
796   Debug("network:server", "client %d (%s) sends message: %s",
797         player->number, player->player_name, message);
798
799   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
800
801   SendNetworkBufferToAllButOne(write_buffer, player);
802 }
803
804 static void Handle_OP_LEVEL_FILE(struct NetworkServerPlayerInfo *player)
805 {
806   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
807
808   SendNetworkBufferToAllButOne(write_buffer, player);
809 }
810
811 static void ExitNetworkServer(int exit_value)
812 {
813   Debug("network:server", "exiting network server");
814
815   exit(exit_value);
816 }
817
818 // the following is not used for a standalone server;
819 // the pointer points to an integer containing the port-number
820 int NetworkServerThread(void *ptr)
821 {
822   network.is_server_thread = TRUE;
823
824   NetworkServer(*((int *) ptr), 0);
825
826   // should never be reached
827   return 0;
828 }
829
830 void NetworkServer(int port, int serveronly)
831 {
832   struct NetworkServerPlayerInfo *player;
833   IPaddress ip;
834
835 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
836   struct sigaction sact;
837 #endif
838
839   if (read_buffer == NULL)
840     read_buffer = newNetworkBuffer();
841
842   if (write_buffer == NULL)
843     write_buffer = newNetworkBuffer();
844
845   if (port == 0)
846     port = DEFAULT_SERVER_PORT;
847
848   // if only running the network server, exit on Ctrl-C
849   if (serveronly)
850     signal(SIGINT, ExitNetworkServer);
851
852   if (!serveronly)
853     run_server_only_once = TRUE;
854
855 #if defined(PLATFORM_UNIX)
856 #if defined(PLATFORM_NEXT)
857   signal(SIGPIPE, SIG_IGN);
858 #else
859   sact.sa_handler = SIG_IGN;
860   sigemptyset(&sact.sa_mask);
861   sact.sa_flags = 0;
862   sigaction(SIGPIPE, &sact, NULL);
863 #endif
864 #endif
865
866   if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
867     Fail("SDLNet_ResolveHost() failed: %s", SDLNet_GetError());
868
869   if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL)
870     Fail("SDLNet_AllocSocketSet() failed: %s"), SDLNet_GetError();
871
872   if ((lfd = SDLNet_TCP_Open(&ip)) == NULL)
873     Fail("SDLNet_TCP_Open() failed: %s"), SDLNet_GetError();
874
875   if (SDLNet_TCP_AddSocket(fds, lfd) == -1)
876     Fail("SDLNet_TCP_AddSocket() failed: %s"), SDLNet_GetError();
877
878   if ((udp = SDLNet_UDP_Open(port)) == NULL)
879     Fail("SDLNet_UDP_Open() failed: %s", SDLNet_GetError());
880
881   if (SDLNet_UDP_AddSocket(fds, udp) == -1)
882     Fail("SDLNet_TCP_AddSocket() failed: %s"), SDLNet_GetError();
883
884   Debug("network:server", "started up, listening on port %d", port);
885   Debug("network:server", "using protocol version %d.%d.%d",
886         PROTOCOL_VERSION_MAJOR,
887         PROTOCOL_VERSION_MINOR,
888         PROTOCOL_VERSION_PATCH);
889
890   while (1)
891   {
892     // wait for 100 ms for activity on open network sockets
893     if (SDLNet_CheckSockets(fds, 100) < 1)
894       continue;
895
896     // accept incoming TCP connections
897     if (SDLNet_SocketReady(lfd))
898     {
899       Debug("network:server", "got TCP packet");
900
901       TCPsocket newsock;
902
903       newsock = SDLNet_TCP_Accept(lfd);
904
905       if (newsock)
906         AddPlayer(newsock);
907     }
908
909     // accept incoming UDP packets
910     if (SDLNet_SocketReady(udp))
911     {
912       Debug("network:server", "got UDP packet");
913
914       static UDPpacket packet;
915
916       int num_packets = SDLNet_UDP_Recv(udp, &packet);
917
918       if (num_packets == 1)
919       {
920         // bounce packet
921         SDLNet_UDP_Send(udp, -1, &packet);
922       }
923     }
924
925     for (player = first_player; player != NULL; player = player->next)
926     {
927       if (!SDLNet_SocketReady(player->fd))
928         continue;
929
930       initNetworkBufferForReceiving(read_buffer);
931
932       int num_bytes = receiveNetworkBufferPacket(read_buffer, player->fd);
933
934       if (num_bytes <= 0)
935       {
936         Debug("network:server", "EOF from client %d (%s)",
937               player->number, player->player_name);
938
939         RemovePlayer(player);
940
941         break;
942       }
943
944       initNetworkBufferForReading(read_buffer);
945
946       int message_type = getNetworkBuffer8BitInteger(read_buffer);
947
948       // skip player number
949       getNetworkBuffer8BitInteger(read_buffer);
950
951       if (!player->introduced &&
952           message_type != OP_PLAYER_NAME &&
953           message_type != OP_PROTOCOL_VERSION)
954       {
955         Debug("network:server", "got opcode %d for client %d which is not introduced yet (expected OP_PLAYER_NAME or OP_PROTOCOL_VERSION)", message_type, player->number);
956
957         RemovePlayer(player);
958
959         break;
960       }
961
962       switch (message_type)
963       {
964         case OP_PROTOCOL_VERSION:
965           Handle_OP_PROTOCOL_VERSION(player);
966           break;
967
968         case OP_NUMBER_WANTED:
969           Handle_OP_NUMBER_WANTED(player);
970           break;
971
972         case OP_PLAYER_NAME:
973           Handle_OP_PLAYER_NAME(player);
974           break;
975
976         case OP_START_PLAYING:
977           Handle_OP_START_PLAYING(player);
978           break;
979
980         case OP_PAUSE_PLAYING:
981           Handle_OP_PAUSE_PLAYING(player);
982           break;
983
984         case OP_CONTINUE_PLAYING:
985           Handle_OP_CONTINUE_PLAYING(player);
986           break;
987
988         case OP_STOP_PLAYING:
989           Handle_OP_STOP_PLAYING(player);
990           break;
991
992         case OP_MOVE_PLAYER:
993           Handle_OP_MOVE_PLAYER(player);
994           break;
995
996         case OP_BROADCAST_MESSAGE:
997           Handle_OP_BROADCAST_MESSAGE(player);
998           break;
999
1000         case OP_LEVEL_FILE:
1001           Handle_OP_LEVEL_FILE(player);
1002           break;
1003
1004         default:
1005           Debug("network:server", "unknown opcode %d from client %d (%s)",
1006                 message_type, player->number, player->player_name);
1007       }
1008     }
1009   }
1010 }