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