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