moved drawing program info on startup to separate function
[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(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     Error(ERR_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     Error(ERR_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     Error(ERR_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   printf("::: network buffer maximum size: %d\n", nb->max_size);
389   printf("::: network buffer size:         %d\n", nb->size);
390   printf("::: network buffer position    : %d\n", nb->pos);
391
392   for (i = 0; i < nb->size; i++)
393   {
394     if ((i % 16) == 0)
395       printf("\n::: ");
396
397     printf("%02x ", nb->buffer[i]);
398   }
399
400   printf("\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   if (options.verbose)
439     Error(ERR_NETWORK_SERVER, "dropping client %d (%s)",
440           player->number, player->player_name);
441
442   SDLNet_TCP_DelSocket(fds, player->fd);
443   SDLNet_TCP_Close(player->fd);
444
445   if (player == first_player)
446   {
447     first_player = player->next;
448   }
449   else
450   {
451     struct NetworkServerPlayerInfo *p;
452
453     for (p = first_player; p != NULL; p = p->next)
454     {
455       if (p->next && p->next == player)
456       {
457         p->next = player->next;
458
459         break;
460       }
461     }
462   }
463
464   if (player->introduced)
465   {
466     initNetworkBufferForWriting(write_buffer, OP_PLAYER_DISCONNECTED,
467                                 player->number);
468
469     SendNetworkBufferToAllButOne(write_buffer, player);
470   }
471
472   free(player);
473   num_clients--;
474
475 #if 0   /* do not terminate network server if last player disconnected */
476   if (run_server_only_once && num_clients == 0)
477   {
478     if (options.verbose)
479     {
480       Error(ERR_NETWORK_SERVER, "no clients left");
481       Error(ERR_NETWORK_SERVER, "aborting");
482     }
483
484     exit(0);
485   }
486 #endif
487 }
488
489 static void AddPlayer(TCPsocket fd)
490 {
491   struct NetworkServerPlayerInfo *player, *p;
492   int number = 1;
493   boolean again = TRUE;
494
495   SDLNet_TCP_AddSocket(fds, fd);
496
497   player = checked_calloc(sizeof(struct NetworkServerPlayerInfo));
498
499   player->fd = fd;
500   player->player_name[0] = 0;
501   player->active = FALSE;
502   player->introduced = FALSE;
503   player->action = 0;
504   player->action_received = FALSE;
505   player->next = first_player;
506
507   first_player = player;
508
509   while (again)
510   {
511     again = FALSE;
512     p = player->next;
513
514     while (p)
515     {
516       if (p->number == number)
517       {
518         number++;
519
520         again = TRUE;
521
522         break;
523       }
524
525       p = p->next;
526     }
527   }
528
529   player->number = number;
530   num_clients++;
531
532   initNetworkBufferForWriting(write_buffer, OP_YOUR_NUMBER, 0);
533
534   putNetworkBuffer8BitInteger(write_buffer, player->number);
535
536   SendNetworkBufferToClient(write_buffer, player);
537 }
538
539 static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *player)
540 {
541   int protocol_version_major = getNetworkBuffer8BitInteger(read_buffer);
542   int protocol_version_minor = getNetworkBuffer8BitInteger(read_buffer);
543   int protocol_version_patch = getNetworkBuffer8BitInteger(read_buffer);
544
545   if (protocol_version_major != PROTOCOL_VERSION_MAJOR ||
546       protocol_version_minor != PROTOCOL_VERSION_MINOR)
547   {
548     if (options.verbose)
549       Error(ERR_NETWORK_SERVER,
550             "client %d (%s) has wrong protocol version %d.%d.%d",
551             player->number, player->player_name,
552             protocol_version_major,
553             protocol_version_minor,
554             protocol_version_patch);
555
556     initNetworkBufferForWriting(write_buffer, OP_BAD_PROTOCOL_VERSION, 0);
557
558     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_MAJOR);
559     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_MINOR);
560     putNetworkBuffer8BitInteger(write_buffer, PROTOCOL_VERSION_PATCH);
561
562     SendNetworkBufferToClient(write_buffer, player);
563
564     RemovePlayer(player);
565   }
566   else
567   {
568     if (options.verbose)
569       Error(ERR_NETWORK_SERVER,
570             "client %d (%s) uses protocol version %d.%d.%d",
571             player->number, player->player_name,
572             protocol_version_major,
573             protocol_version_minor,
574             protocol_version_patch);
575   }
576 }
577
578 static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *player)
579 {
580   int nr_wanted = getNetworkBuffer8BitInteger(read_buffer);
581   int client_nr = player->number;
582   boolean nr_is_free = TRUE;
583   struct NetworkServerPlayerInfo *p;
584
585   if (options.verbose)
586       Error(ERR_NETWORK_SERVER, "client %d (%s) wants to switch to # %d",
587             player->number, player->player_name, nr_wanted);
588
589   for (p = first_player; p != NULL; p = p->next)
590   {
591     if (p->number == nr_wanted)
592     {
593       nr_is_free = FALSE;
594
595       break;
596     }
597   }
598
599   if (options.verbose)
600   {
601     if (nr_is_free)
602       Error(ERR_NETWORK_SERVER, "client %d (%s) switches to # %d",
603             player->number, player->player_name, nr_wanted);
604     else if (player->number == nr_wanted)
605       Error(ERR_NETWORK_SERVER, "client %d (%s) already has # %d",
606             player->number, player->player_name, nr_wanted);
607     else
608       Error(ERR_NETWORK_SERVER,
609             "client %d (%s) cannot switch (client %d already exists)",
610             player->number, player->player_name, nr_wanted);
611   }
612
613   if (nr_is_free)
614     player->number = nr_wanted;
615
616   initNetworkBufferForWriting(write_buffer, OP_NUMBER_WANTED, client_nr);
617
618   putNetworkBuffer8BitInteger(write_buffer, nr_wanted);
619   putNetworkBuffer8BitInteger(write_buffer, player->number);
620
621   SendNetworkBufferToAll(write_buffer);
622 }
623
624 static void Handle_OP_PLAYER_NAME(struct NetworkServerPlayerInfo *player)
625 {
626   char *player_name = getNetworkBufferString(read_buffer);
627   int i;
628
629   strncpy(player->player_name, player_name, MAX_PLAYER_NAME_LEN);
630   player->player_name[MAX_PLAYER_NAME_LEN] = '\0';
631
632   for (i = 0; i < MAX_PLAYER_NAME_LEN; i++)
633   {
634     if (player->player_name[i] < ' ' ||
635         ((unsigned char)(player->player_name[i]) > 0x7e &&
636          (unsigned char)(player->player_name[i]) <= 0xa0))
637     {
638       player->player_name[i] = 0;
639
640       break;
641     }
642   }
643
644   if (!player->introduced)
645   {
646     initNetworkBufferForWriting(write_buffer, OP_PLAYER_CONNECTED,
647                                 player->number);
648
649     SendNetworkBufferToAllButOne(write_buffer, player);
650   }
651               
652   if (options.verbose)
653     Error(ERR_NETWORK_SERVER, "client %d calls itself \"%s\"",
654           player->number, player->player_name);
655
656   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
657
658   SendNetworkBufferToAllButOne(write_buffer, player);
659
660   if (!player->introduced)
661   {
662     struct NetworkServerPlayerInfo *p;
663
664     for (p = first_player; p != NULL; p = p->next)
665     {
666       if (p != player && p->introduced)
667       {
668         initNetworkBufferForWriting(write_buffer, OP_PLAYER_CONNECTED,
669                                     p->number);
670
671         SendNetworkBufferToClient(write_buffer, player);
672
673         initNetworkBufferForWriting(write_buffer, OP_PLAYER_NAME, p->number);
674
675         putNetworkBufferString(write_buffer, p->player_name);
676
677         SendNetworkBufferToClient(write_buffer, player);
678       }
679     }
680   }
681
682   player->introduced = TRUE;
683 }
684
685 static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *player)
686 {
687   char *new_leveldir_identifier = getNetworkBufferString(read_buffer);
688   int level_nr = getNetworkBuffer16BitInteger(read_buffer);
689
690   if (options.verbose)
691     Error(ERR_NETWORK_SERVER,
692           "client %d (%s) starts game [level %d from level set '%s']",
693           player->number, player->player_name, level_nr,
694           new_leveldir_identifier);
695
696   struct NetworkServerPlayerInfo *p;
697
698   /* reset frame counter */
699   ServerFrameCounter = 0;
700
701   Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0");
702
703   /* reset player actions */
704   for (p = first_player; p != NULL; p = p->next)
705   {
706     p->action = 0;
707     p->action_received = FALSE;
708
709     if (p->introduced)
710       p->active = TRUE;
711   }
712
713   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
714
715   SendNetworkBufferToAll(write_buffer);
716 }
717
718 static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *player)
719 {
720   if (options.verbose)
721     Error(ERR_NETWORK_SERVER, "client %d (%s) pauses game",
722           player->number, player->player_name);
723
724   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
725
726   SendNetworkBufferToAll(write_buffer);
727 }
728
729 static void Handle_OP_CONTINUE_PLAYING(struct NetworkServerPlayerInfo *player)
730 {
731   if (options.verbose)
732     Error(ERR_NETWORK_SERVER, "client %d (%s) continues game",
733           player->number, player->player_name);
734
735   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
736
737   SendNetworkBufferToAll(write_buffer);
738 }
739
740 static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
741 {
742   int cause_for_stopping = getNetworkBuffer8BitInteger(read_buffer);
743
744   if (options.verbose)
745     Error(ERR_NETWORK_SERVER, "client %d (%s) stops game [%d]",
746           player->number, player->player_name, cause_for_stopping);
747
748   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
749
750   SendNetworkBufferToAll(write_buffer);
751 }
752
753 static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
754 {
755   int player_action = getNetworkBuffer8BitInteger(read_buffer);
756   int last_client_nr = 0;
757   struct NetworkServerPlayerInfo *p;
758   int i;
759
760   /* store player action */
761   for (p = first_player; p != NULL; p = p->next)
762   {
763     if (p->number == player->number)
764     {
765       p->action = player_action;
766       p->action_received = TRUE;
767     }
768   }
769
770   /* check if server received action from each player */
771   for (p = first_player; p != NULL; p = p->next)
772   {
773     if (!p->action_received)
774       return;
775
776     if (p->number > last_client_nr)
777       last_client_nr = p->number;
778   }
779
780   int player_action_all[last_client_nr];
781
782   /* initialize all player actions to zero */
783   for (i = 0; i < last_client_nr; i++)
784     player_action_all[i] = 0;
785
786   /* broadcast actions of all players to all players */
787   for (p = first_player; p != NULL; p = p->next)
788   {
789     player_action_all[p->number - 1] = p->action;
790
791     p->action = 0;
792     p->action_received = FALSE;
793   }
794
795   initNetworkBufferForWriting(write_buffer, OP_MOVE_PLAYER, player->number);
796
797   putNetworkBuffer32BitInteger(write_buffer, ServerFrameCounter);
798
799   for (i = 0; i < last_client_nr; i++)
800     putNetworkBuffer8BitInteger(write_buffer, player_action_all[i]);
801
802   SendNetworkBufferToAll(write_buffer);
803
804   ServerFrameCounter++;
805 }
806
807 static void Handle_OP_BROADCAST_MESSAGE(struct NetworkServerPlayerInfo *player)
808 {
809   char *message = getNetworkBufferString(read_buffer);
810
811   if (options.verbose)
812     Error(ERR_NETWORK_SERVER, "client %d (%s) sends message: %s",
813           player->number, player->player_name, message);
814
815   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
816
817   SendNetworkBufferToAllButOne(write_buffer, player);
818 }
819
820 static void Handle_OP_LEVEL_FILE(struct NetworkServerPlayerInfo *player)
821 {
822   copyNetworkBufferForWriting(read_buffer, write_buffer, player->number);
823
824   SendNetworkBufferToAllButOne(write_buffer, player);
825 }
826
827 static void ExitNetworkServer(int exit_value)
828 {
829   Error(ERR_NETWORK_SERVER, "exiting network server");
830
831   exit(exit_value);
832 }
833
834 /* the following is not used for a standalone server;
835    the pointer points to an integer containing the port-number */
836 int NetworkServerThread(void *ptr)
837 {
838   NetworkServer(*((int *) ptr), 0);
839
840   /* should never be reached */
841   return 0;
842 }
843
844 void NetworkServer(int port, int serveronly)
845 {
846   struct NetworkServerPlayerInfo *player;
847   IPaddress ip;
848
849 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
850   struct sigaction sact;
851 #endif
852
853   if (read_buffer == NULL)
854     read_buffer = newNetworkBuffer();
855
856   if (write_buffer == NULL)
857     write_buffer = newNetworkBuffer();
858
859   if (port == 0)
860     port = DEFAULT_SERVER_PORT;
861
862   // if only running the network server, exit on Ctrl-C
863   if (serveronly)
864     signal(SIGINT, ExitNetworkServer);
865
866   if (!serveronly)
867     run_server_only_once = TRUE;
868
869 #if defined(PLATFORM_UNIX)
870 #if defined(PLATFORM_NEXT)
871   signal(SIGPIPE, SIG_IGN);
872 #else
873   sact.sa_handler = SIG_IGN;
874   sigemptyset(&sact.sa_mask);
875   sact.sa_flags = 0;
876   sigaction(SIGPIPE, &sact, NULL);
877 #endif
878 #endif
879
880   if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
881     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed: %s",
882           SDLNet_GetError());
883
884   if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL)
885     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_AllocSocketSet() failed: %s"),
886       SDLNet_GetError();
887
888   if ((lfd = SDLNet_TCP_Open(&ip)) == NULL)
889     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed: %s"),
890       SDLNet_GetError();
891
892   if (SDLNet_TCP_AddSocket(fds, lfd) == -1)
893     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
894       SDLNet_GetError();
895
896   if ((udp = SDLNet_UDP_Open(port)) == NULL)
897     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_UDP_Open() failed: %s",
898           SDLNet_GetError());
899
900   if (SDLNet_UDP_AddSocket(fds, udp) == -1)
901     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
902       SDLNet_GetError();
903
904   if (options.verbose)
905   {
906     Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port);
907     Error(ERR_NETWORK_SERVER, "using protocol version %d.%d.%d",
908           PROTOCOL_VERSION_MAJOR,
909           PROTOCOL_VERSION_MINOR,
910           PROTOCOL_VERSION_PATCH);
911   }
912
913   while (1)
914   {
915     // wait for 100 ms for activity on open network sockets
916     if (SDLNet_CheckSockets(fds, 100) < 1)
917       continue;
918
919     /* accept incoming TCP connections */
920     if (SDLNet_SocketReady(lfd))
921     {
922       Error(ERR_DEBUG, "got TCP packet");
923
924       TCPsocket newsock;
925
926       newsock = SDLNet_TCP_Accept(lfd);
927
928       if (newsock)
929         AddPlayer(newsock);
930     }
931
932     /* accept incoming UDP packets */
933     if (SDLNet_SocketReady(udp))
934     {
935       Error(ERR_DEBUG, "got UDP packet");
936
937       static UDPpacket packet;
938
939       int num_packets = SDLNet_UDP_Recv(udp, &packet);
940
941       if (num_packets == 1)
942       {
943         // bounce packet
944         SDLNet_UDP_Send(udp, -1, &packet);
945       }
946     }
947
948     for (player = first_player; player != NULL; player = player->next)
949     {
950       if (!SDLNet_SocketReady(player->fd))
951         continue;
952
953       initNetworkBufferForReceiving(read_buffer);
954
955       int num_bytes = receiveNetworkBufferPacket(read_buffer, player->fd);
956
957       if (num_bytes <= 0)
958       {
959         if (options.verbose)
960           Error(ERR_NETWORK_SERVER, "EOF from client %d (%s)",
961                 player->number, player->player_name);
962
963         RemovePlayer(player);
964
965         break;
966       }
967
968       initNetworkBufferForReading(read_buffer);
969
970       int message_type = getNetworkBuffer8BitInteger(read_buffer);
971
972       /* skip player number */
973       getNetworkBuffer8BitInteger(read_buffer);
974
975       if (!player->introduced &&
976           message_type != OP_PLAYER_NAME &&
977           message_type != OP_PROTOCOL_VERSION)
978       {
979         if (options.verbose)
980           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);
981
982         RemovePlayer(player);
983
984         break;
985       }
986
987       switch (message_type)
988       {
989         case OP_PROTOCOL_VERSION:
990           Handle_OP_PROTOCOL_VERSION(player);
991           break;
992
993         case OP_NUMBER_WANTED:
994           Handle_OP_NUMBER_WANTED(player);
995           break;
996
997         case OP_PLAYER_NAME:
998           Handle_OP_PLAYER_NAME(player);
999           break;
1000
1001         case OP_START_PLAYING:
1002           Handle_OP_START_PLAYING(player);
1003           break;
1004
1005         case OP_PAUSE_PLAYING:
1006           Handle_OP_PAUSE_PLAYING(player);
1007           break;
1008
1009         case OP_CONTINUE_PLAYING:
1010           Handle_OP_CONTINUE_PLAYING(player);
1011           break;
1012
1013         case OP_STOP_PLAYING:
1014           Handle_OP_STOP_PLAYING(player);
1015           break;
1016
1017         case OP_MOVE_PLAYER:
1018           Handle_OP_MOVE_PLAYER(player);
1019           break;
1020
1021         case OP_BROADCAST_MESSAGE:
1022           Handle_OP_BROADCAST_MESSAGE(player);
1023           break;
1024
1025         case OP_LEVEL_FILE:
1026           Handle_OP_LEVEL_FILE(player);
1027           break;
1028
1029         default:
1030           if (options.verbose)
1031             Error(ERR_NETWORK_SERVER,
1032                   "unknown opcode %d from client %d (%s)",
1033                   message_type, player->number, player->player_name);
1034       }
1035     }
1036   }
1037 }