added function to dump network message buffer (for debugging)
[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 //                  http://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()
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 (nb->pos + num_bytes > nb->max_size)
191     increaseNetworkBuffer(nb, num_bytes);
192
193   int result = SDLNet_TCP_Recv(socket, &nb->buffer[nb->pos], num_bytes);
194
195   if (result != num_bytes)
196     return result;
197
198   nb->pos += num_bytes;
199   nb->size = nb->pos;
200
201   return num_bytes;
202 }
203
204 int receiveNetworkBufferPacket(struct NetworkBuffer *nb, TCPsocket socket)
205 {
206   int num_bytes, num_bytes_head, num_bytes_body;
207
208   num_bytes_head = 4;
209   num_bytes = receiveNetworkBufferBytes(nb, socket, num_bytes_head);
210
211   if (num_bytes != num_bytes_head)
212     return num_bytes;
213
214   num_bytes_body = getNetwork32BitInteger(nb->buffer);
215   num_bytes = receiveNetworkBufferBytes(nb, socket, num_bytes_body);
216
217   return num_bytes;
218 }
219
220 int getNetworkBuffer8BitInteger(struct NetworkBuffer *nb)
221 {
222   int num_bytes = 1;
223
224   if (nb->pos + num_bytes > nb->size)
225     return 0;
226
227   int value = getNetwork8BitInteger(&nb->buffer[nb->pos]);
228
229   nb->pos += num_bytes;
230
231   return value;
232 }
233
234 void putNetworkBuffer8BitInteger(struct NetworkBuffer *nb, int value)
235 {
236   int num_bytes = 1;
237
238   if (nb->pos + num_bytes > nb->max_size)
239     increaseNetworkBuffer(nb, num_bytes);
240
241   nb->pos += putNetwork8BitInteger(&nb->buffer[nb->pos], value);
242   nb->size = nb->pos;
243 }
244
245 int getNetworkBuffer16BitInteger(struct NetworkBuffer *nb)
246 {
247   int num_bytes = 2;
248
249   if (nb->pos + num_bytes > nb->size)
250     return 0;
251
252   int value = getNetwork16BitInteger(&nb->buffer[nb->pos]);
253
254   nb->pos += num_bytes;
255
256   return value;
257 }
258
259 void putNetworkBuffer16BitInteger(struct NetworkBuffer *nb, int value)
260 {
261   int num_bytes = 2;
262
263   if (nb->pos + num_bytes > nb->max_size)
264     increaseNetworkBuffer(nb, num_bytes);
265
266   nb->pos += putNetwork16BitInteger(&nb->buffer[nb->pos], value);
267   nb->size = nb->pos;
268 }
269
270 int getNetworkBuffer32BitInteger(struct NetworkBuffer *nb)
271 {
272   int num_bytes = 4;
273
274   if (nb->pos + num_bytes > nb->size)
275     return 0;
276
277   int value = getNetwork32BitInteger(&nb->buffer[nb->pos]);
278
279   nb->pos += num_bytes;
280
281   return value;
282 }
283
284 void putNetworkBuffer32BitInteger(struct NetworkBuffer *nb, int value)
285 {
286   int num_bytes = 4;
287
288   if (nb->pos + num_bytes > nb->max_size)
289     increaseNetworkBuffer(nb, num_bytes);
290
291   nb->pos += putNetwork32BitInteger(&nb->buffer[nb->pos], value);
292   nb->size = nb->pos;
293 }
294
295 char *getNetworkBufferString(struct NetworkBuffer *nb)
296 {
297   char *s = getNetworkString(&nb->buffer[nb->pos]);
298
299   nb->pos += strlen(s) + 1;
300
301   return s;
302 }
303
304 void putNetworkBufferString(struct NetworkBuffer *nb, char *s)
305 {
306   int num_bytes = strlen(s) + 1;
307
308   if (nb->pos + num_bytes > nb->max_size)
309     increaseNetworkBuffer(nb, num_bytes);
310
311   nb->pos += putNetworkString(&nb->buffer[nb->pos], s);
312   nb->size = nb->pos;
313 }
314
315 void dumpNetworkBuffer(struct NetworkBuffer *nb)
316 {
317   int i;
318
319   printf("::: network buffer maximum size: %d\n", nb->max_size);
320   printf("::: network buffer size:         %d\n", nb->size);
321   printf("::: network buffer position    : %d\n", nb->pos);
322
323   for (i = 0; i < nb->size; i++)
324   {
325     if ((i % 16) == 0)
326       printf("\n::: ");
327
328     printf("%02x ", nb->buffer[i]);
329   }
330
331   printf("\n");
332 }
333
334 static void SendNetworkBufferToAllButOne(struct NetworkBuffer *nb,
335                                          struct NetworkServerPlayerInfo *except)
336 {
337   struct NetworkServerPlayerInfo *player;
338
339   /* set message length header */
340   putNetwork32BitInteger(nb->buffer, nb->size - 4);
341
342   for (player = first_player; player != NULL; player = player->next)
343   {
344     if (player != except && player->introduced)
345     {
346       /* directly send the buffer to the network client */
347       SDLNet_TCP_Send(player->fd, nb->buffer, nb->size);
348     }
349   }
350 }
351
352 static void SendNetworkBufferToAll(struct NetworkBuffer *nb)
353 {
354   SendNetworkBufferToAllButOne(nb, NULL);
355 }
356
357 static void SendNetworkBufferToClient(struct NetworkBuffer *nb,
358                                       struct NetworkServerPlayerInfo *player)
359 {
360   /* set message length header */
361   putNetwork32BitInteger(nb->buffer, nb->size - 4);
362
363   /* directly send the buffer to the network client */
364   SDLNet_TCP_Send(player->fd, nb->buffer, nb->size);
365 }
366
367 static void RemovePlayer(struct NetworkServerPlayerInfo *player)
368 {
369   if (options.verbose)
370     Error(ERR_NETWORK_SERVER, "dropping client %d (%s)",
371           player->number, player->player_name);
372
373   SDLNet_TCP_DelSocket(fds, player->fd);
374   SDLNet_TCP_Close(player->fd);
375
376   if (player == first_player)
377   {
378     first_player = player->next;
379   }
380   else
381   {
382     struct NetworkServerPlayerInfo *p;
383
384     for (p = first_player; p != NULL; p = p->next)
385     {
386       if (p->next && p->next == player)
387       {
388         p->next = player->next;
389
390         break;
391       }
392     }
393   }
394
395   if (player->introduced)
396   {
397     initNetworkBufferForWriting(write_buffer, OP_PLAYER_DISCONNECTED,
398                                 player->number);
399
400     SendNetworkBufferToAllButOne(write_buffer, player);
401   }
402
403   free(player);
404   num_clients--;
405
406 #if 0   /* do not terminate network server if last player disconnected */
407   if (run_server_only_once && num_clients == 0)
408   {
409     if (options.verbose)
410     {
411       Error(ERR_NETWORK_SERVER, "no clients left");
412       Error(ERR_NETWORK_SERVER, "aborting");
413     }
414
415     exit(0);
416   }
417 #endif
418 }
419
420 static void AddPlayer(TCPsocket fd)
421 {
422   struct NetworkServerPlayerInfo *player, *p;
423   int number = 1;
424   boolean again = TRUE;
425
426   SDLNet_TCP_AddSocket(fds, fd);
427
428   player = checked_calloc(sizeof(struct NetworkServerPlayerInfo));
429
430   player->fd = fd;
431   player->player_name[0] = 0;
432   player->active = FALSE;
433   player->introduced = FALSE;
434   player->action = 0;
435   player->action_received = FALSE;
436   player->next = first_player;
437
438   first_player = player;
439
440   while (again)
441   {
442     again = FALSE;
443     p = player->next;
444
445     while (p)
446     {
447       if (p->number == number)
448       {
449         number++;
450
451         again = TRUE;
452
453         break;
454       }
455
456       p = p->next;
457     }
458   }
459
460   player->number = number;
461   num_clients++;
462
463   initNetworkBufferForWriting(write_buffer, OP_YOUR_NUMBER, 0);
464
465   putNetworkBuffer8BitInteger(write_buffer, player->number);
466
467   SendNetworkBufferToClient(write_buffer, player);
468 }
469
470 static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *player)
471 {
472   int protocol_version_major = getNetworkBuffer8BitInteger(read_buffer);
473   int protocol_version_minor = getNetworkBuffer8BitInteger(read_buffer);
474   int protocol_version_patch = getNetworkBuffer8BitInteger(read_buffer);
475
476   if (protocol_version_major != PROTOCOL_VERSION_MAJOR ||
477       protocol_version_minor != PROTOCOL_VERSION_MINOR)
478   {
479     if (options.verbose)
480       Error(ERR_NETWORK_SERVER,
481             "client %d (%s) has wrong protocol version %d.%d.%d",
482             player->number, player->player_name,
483             protocol_version_major,
484             protocol_version_minor,
485             protocol_version_patch);
486
487     initNetworkBufferForWriting(write_buffer, OP_BAD_PROTOCOL_VERSION, 0);
488
489     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_MAJOR);
490     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_MINOR);
491     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_PATCH);
492
493     SendNetworkBufferToClient(write_buffer, player);
494
495     RemovePlayer(player);
496   }
497   else
498   {
499     if (options.verbose)
500       Error(ERR_NETWORK_SERVER,
501             "client %d (%s) uses protocol version %d.%d.%d",
502             player->number, player->player_name,
503             protocol_version_major,
504             protocol_version_minor,
505             protocol_version_patch);
506   }
507 }
508
509 static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *player)
510 {
511   int nr_wanted = getNetworkBuffer8BitInteger(read_buffer);
512   int client_nr = player->number;
513   boolean nr_is_free = TRUE;
514   struct NetworkServerPlayerInfo *p;
515
516   if (options.verbose)
517       Error(ERR_NETWORK_SERVER, "client %d (%s) wants to switch to # %d",
518             player->number, player->player_name, nr_wanted);
519
520   for (p = first_player; p != NULL; p = p->next)
521   {
522     if (p->number == nr_wanted)
523     {
524       nr_is_free = FALSE;
525
526       break;
527     }
528   }
529
530   if (options.verbose)
531   {
532     if (nr_is_free)
533       Error(ERR_NETWORK_SERVER, "client %d (%s) switches to # %d",
534             player->number, player->player_name, nr_wanted);
535     else if (player->number == nr_wanted)
536       Error(ERR_NETWORK_SERVER, "client %d (%s) already has # %d",
537             player->number, player->player_name, nr_wanted);
538     else
539       Error(ERR_NETWORK_SERVER,
540             "client %d (%s) cannot switch (client %d already exists)",
541             player->number, player->player_name, nr_wanted);
542   }
543
544   if (nr_is_free)
545     player->number = nr_wanted;
546
547   initNetworkBufferForWriting(write_buffer, OP_NUMBER_WANTED, client_nr);
548
549   putNetworkBuffer8BitInteger(write_buffer, nr_wanted);
550   putNetworkBuffer8BitInteger(write_buffer, player->number);
551
552   SendNetworkBufferToAll(write_buffer);
553 }
554
555 static void Handle_OP_PLAYER_NAME(struct NetworkServerPlayerInfo *player)
556 {
557   char *player_name = getNetworkBufferString(read_buffer);
558   int i;
559
560   strncpy(player->player_name, player_name, MAX_PLAYER_NAME_LEN);
561   player->player_name[MAX_PLAYER_NAME_LEN] = '\0';
562
563   for (i = 0; i < MAX_PLAYER_NAME_LEN; i++)
564   {
565     if (player->player_name[i] < ' ' ||
566         ((unsigned char)(player->player_name[i]) > 0x7e &&
567          (unsigned char)(player->player_name[i]) <= 0xa0))
568     {
569       player->player_name[i] = 0;
570
571       break;
572     }
573   }
574
575   if (!player->introduced)
576   {
577     initNetworkBufferForWriting(write_buffer, OP_PLAYER_CONNECTED,
578                                 player->number);
579
580     SendNetworkBufferToAllButOne(write_buffer, player);
581   }
582               
583   if (options.verbose)
584     Error(ERR_NETWORK_SERVER, "client %d calls itself \"%s\"",
585           player->number, player->player_name);
586
587   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
588
589   SendNetworkBufferToAllButOne(write_buffer, player);
590
591   if (!player->introduced)
592   {
593     struct NetworkServerPlayerInfo *p;
594
595     for (p = first_player; p != NULL; p = p->next)
596     {
597       if (p != player && p->introduced)
598       {
599         initNetworkBufferForWriting(write_buffer, OP_PLAYER_CONNECTED,
600                                     p->number);
601
602         SendNetworkBufferToClient(write_buffer, player);
603
604         initNetworkBufferForWriting(write_buffer, OP_PLAYER_NAME, p->number);
605
606         putNetworkBufferString(write_buffer, p->player_name);
607
608         SendNetworkBufferToClient(write_buffer, player);
609       }
610     }
611   }
612
613   player->introduced = TRUE;
614 }
615
616 static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *player)
617 {
618   char *new_leveldir_identifier = getNetworkBufferString(read_buffer);
619   int level_nr = getNetworkBuffer16BitInteger(read_buffer);
620
621   if (options.verbose)
622     Error(ERR_NETWORK_SERVER,
623           "client %d (%s) starts game [level %d from level set '%s']",
624           player->number, player->player_name, level_nr,
625           new_leveldir_identifier);
626
627   struct NetworkServerPlayerInfo *p;
628
629   /* reset frame counter */
630   ServerFrameCounter = 0;
631
632   Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0");
633
634   /* reset player actions */
635   for (p = first_player; p != NULL; p = p->next)
636   {
637     p->action = 0;
638     p->action_received = FALSE;
639
640     if (p->introduced)
641       p->active = TRUE;
642   }
643
644   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
645
646   SendNetworkBufferToAll(write_buffer);
647 }
648
649 static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *player)
650 {
651   if (options.verbose)
652     Error(ERR_NETWORK_SERVER, "client %d (%s) pauses game",
653           player->number, player->player_name);
654
655   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
656
657   SendNetworkBufferToAll(write_buffer);
658 }
659
660 static void Handle_OP_CONTINUE_PLAYING(struct NetworkServerPlayerInfo *player)
661 {
662   if (options.verbose)
663     Error(ERR_NETWORK_SERVER, "client %d (%s) continues game",
664           player->number, player->player_name);
665
666   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
667
668   SendNetworkBufferToAll(write_buffer);
669 }
670
671 static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
672 {
673   int cause_for_stopping = getNetworkBuffer8BitInteger(read_buffer);
674
675   if (options.verbose)
676     Error(ERR_NETWORK_SERVER, "client %d (%s) stops game [%d]",
677           player->number, player->player_name, cause_for_stopping);
678
679   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
680
681   SendNetworkBufferToAll(write_buffer);
682 }
683
684 static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
685 {
686   int player_action = getNetworkBuffer8BitInteger(read_buffer);
687   int last_client_nr = 0;
688   struct NetworkServerPlayerInfo *p;
689   int i;
690
691   /* store player action */
692   for (p = first_player; p != NULL; p = p->next)
693   {
694     if (p->number == player->number)
695     {
696       p->action = player_action;
697       p->action_received = TRUE;
698     }
699   }
700
701   /* check if server received action from each player */
702   for (p = first_player; p != NULL; p = p->next)
703   {
704     if (!p->action_received)
705       return;
706
707     if (p->number > last_client_nr)
708       last_client_nr = p->number;
709   }
710
711   int player_action_all[last_client_nr];
712
713   /* initialize all player actions to zero */
714   for (i = 0; i < last_client_nr; i++)
715     player_action_all[i] = 0;
716
717   /* broadcast actions of all players to all players */
718   for (p = first_player; p != NULL; p = p->next)
719   {
720     player_action_all[p->number - 1] = p->action;
721
722     p->action = 0;
723     p->action_received = FALSE;
724   }
725
726   initNetworkBufferForWriting(write_buffer, OP_MOVE_PLAYER, player->number);
727
728   putNetworkBuffer32BitInteger(write_buffer, ServerFrameCounter);
729
730   for (i = 0; i < last_client_nr; i++)
731     putNetworkBuffer8BitInteger(write_buffer, player_action_all[i]);
732
733   SendNetworkBufferToAll(write_buffer);
734
735   ServerFrameCounter++;
736 }
737
738 static void Handle_OP_BROADCAST_MESSAGE(struct NetworkServerPlayerInfo *player)
739 {
740   char *message = getNetworkBufferString(read_buffer);
741
742   if (options.verbose)
743     Error(ERR_NETWORK_SERVER, "client %d (%s) sends message: %s",
744           player->number, player->player_name, message);
745
746   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
747
748   SendNetworkBufferToAllButOne(write_buffer, player);
749 }
750
751 void ExitNetworkServer(int exit_value)
752 {
753   Error(ERR_NETWORK_SERVER, "exiting network server");
754
755   exit(exit_value);
756 }
757
758 /* the following is not used for a standalone server;
759    the pointer points to an integer containing the port-number */
760 int NetworkServerThread(void *ptr)
761 {
762   NetworkServer(*((int *) ptr), 0);
763
764   /* should never be reached */
765   return 0;
766 }
767
768 void NetworkServer(int port, int serveronly)
769 {
770   struct NetworkServerPlayerInfo *player;
771   IPaddress ip;
772
773 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
774   struct sigaction sact;
775 #endif
776
777   if (read_buffer == NULL)
778     read_buffer = newNetworkBuffer();
779
780   if (write_buffer == NULL)
781     write_buffer = newNetworkBuffer();
782
783   if (port == 0)
784     port = DEFAULT_SERVER_PORT;
785
786   // if only running the network server, exit on Ctrl-C
787   if (serveronly)
788     signal(SIGINT, ExitNetworkServer);
789
790   if (!serveronly)
791     run_server_only_once = TRUE;
792
793 #if defined(PLATFORM_UNIX)
794 #if defined(PLATFORM_NEXT)
795   signal(SIGPIPE, SIG_IGN);
796 #else
797   sact.sa_handler = SIG_IGN;
798   sigemptyset(&sact.sa_mask);
799   sact.sa_flags = 0;
800   sigaction(SIGPIPE, &sact, NULL);
801 #endif
802 #endif
803
804   if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
805     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed: %s",
806           SDLNet_GetError());
807
808   if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL)
809     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_AllocSocketSet() failed: %s"),
810       SDLNet_GetError();
811
812   if ((lfd = SDLNet_TCP_Open(&ip)) == NULL)
813     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed: %s"),
814       SDLNet_GetError();
815
816   if (SDLNet_TCP_AddSocket(fds, lfd) == -1)
817     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
818       SDLNet_GetError();
819
820   if ((udp = SDLNet_UDP_Open(port)) == NULL)
821     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_UDP_Open() failed: %s",
822           SDLNet_GetError());
823
824   if (SDLNet_UDP_AddSocket(fds, udp) == -1)
825     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
826       SDLNet_GetError();
827
828   if (options.verbose)
829   {
830     Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port);
831     Error(ERR_NETWORK_SERVER, "using protocol version %d.%d.%d",
832           PROTOCOL_VERSION_MAJOR,
833           PROTOCOL_VERSION_MINOR,
834           PROTOCOL_VERSION_PATCH);
835   }
836
837   while (1)
838   {
839     // wait for 100 ms for activity on open network sockets
840     if (SDLNet_CheckSockets(fds, 100) < 1)
841       continue;
842
843     /* accept incoming TCP connections */
844     if (SDLNet_SocketReady(lfd))
845     {
846       Error(ERR_DEBUG, "got TCP packet");
847
848       TCPsocket newsock;
849
850       newsock = SDLNet_TCP_Accept(lfd);
851
852       if (newsock)
853         AddPlayer(newsock);
854     }
855
856     /* accept incoming UDP packets */
857     if (SDLNet_SocketReady(udp))
858     {
859       Error(ERR_DEBUG, "got UDP packet");
860
861       static UDPpacket packet;
862
863       int num_packets = SDLNet_UDP_Recv(udp, &packet);
864
865       if (num_packets == 1)
866       {
867         // bounce packet
868         SDLNet_UDP_Send(udp, -1, &packet);
869       }
870     }
871
872     for (player = first_player; player != NULL; player = player->next)
873     {
874       if (!SDLNet_SocketReady(player->fd))
875         continue;
876
877       initNetworkBufferForReceiving(read_buffer);
878
879       int num_bytes = receiveNetworkBufferPacket(read_buffer, player->fd);
880
881       if (num_bytes <= 0)
882       {
883         if (options.verbose)
884           Error(ERR_NETWORK_SERVER, "EOF from client %d (%s)",
885                 player->number, player->player_name);
886
887         RemovePlayer(player);
888
889         break;
890       }
891
892       initNetworkBufferForReading(read_buffer);
893
894       int message_type = getNetworkBuffer8BitInteger(read_buffer);
895
896       /* skip player number */
897       getNetworkBuffer8BitInteger(read_buffer);
898
899       if (!player->introduced &&
900           message_type != OP_PLAYER_NAME &&
901           message_type != OP_PROTOCOL_VERSION)
902       {
903         if (options.verbose)
904           Error(ERR_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);
905
906         RemovePlayer(player);
907
908         break;
909       }
910
911       switch (message_type)
912       {
913         case OP_PROTOCOL_VERSION:
914           Handle_OP_PROTOCOL_VERSION(player);
915           break;
916
917         case OP_NUMBER_WANTED:
918           Handle_OP_NUMBER_WANTED(player);
919           break;
920
921         case OP_PLAYER_NAME:
922           Handle_OP_PLAYER_NAME(player);
923           break;
924
925         case OP_START_PLAYING:
926           Handle_OP_START_PLAYING(player);
927           break;
928
929         case OP_PAUSE_PLAYING:
930           Handle_OP_PAUSE_PLAYING(player);
931           break;
932
933         case OP_CONTINUE_PLAYING:
934           Handle_OP_CONTINUE_PLAYING(player);
935           break;
936
937         case OP_STOP_PLAYING:
938           Handle_OP_STOP_PLAYING(player);
939           break;
940
941         case OP_MOVE_PLAYER:
942           Handle_OP_MOVE_PLAYER(player);
943           break;
944
945         case OP_BROADCAST_MESSAGE:
946           Handle_OP_BROADCAST_MESSAGE(player);
947           break;
948
949         default:
950           if (options.verbose)
951             Error(ERR_NETWORK_SERVER,
952                   "unknown opcode %d from client %d (%s)",
953                   message_type, player->number, player->player_name);
954       }
955     }
956   }
957 }