4b846f9da413425db5e86999fd149111f34ea77c
[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 clients = 0;
24 static int onceonly = 0;
25
26 struct NetworkServerPlayerInfo
27 {
28   TCPsocket fd;
29   char player_name[16];
30   unsigned char number;
31   struct NetworkServerPlayerInfo *next;
32   char active;
33   char introduced;
34   unsigned char readbuffer[MAX_BUFFER_SIZE];
35   unsigned char writbuffer[MAX_BUFFER_SIZE];
36   int nread, nwrite;
37   byte action;
38   boolean action_received;
39 };
40
41 static struct NetworkServerPlayerInfo *first_player = NULL;
42
43 #define NEXT(player) ((player)->next ? (player)->next : first_player)
44
45 /* TODO: peer address */
46 static TCPsocket lfd;           /* listening TCP socket */
47 static UDPsocket udp;           /* listening UDP socket */
48 static SDLNet_SocketSet fds;    /* socket set */
49
50 static unsigned char realbuffer[512], *buffer = realbuffer + 4;
51
52 static int interrupt;
53
54 static unsigned int ServerFrameCounter = 0;
55
56 static void addtobuffer(struct NetworkServerPlayerInfo *player,
57                         unsigned char *b, int len)
58 {
59   if (player->nwrite + len >= MAX_BUFFER_SIZE)
60     Error(ERR_EXIT_NETWORK_SERVER,
61           "internal error: network send buffer overflow");
62
63   memcpy(player->writbuffer + player->nwrite, b, len);
64   player->nwrite += len;
65 }
66
67 static void flushuser(struct NetworkServerPlayerInfo *player)
68 {
69   if (player->nwrite)
70   {
71     SDLNet_TCP_Send(player->fd, player->writbuffer, player->nwrite);
72
73     player->nwrite = 0;
74   }
75 }
76
77 static void broadcast(struct NetworkServerPlayerInfo *except,
78                       int len, int activeonly)
79 {
80   struct NetworkServerPlayerInfo *player;
81
82   realbuffer[0] = realbuffer[1] = realbuffer[2] = 0;
83   realbuffer[3] = (unsigned char)len;
84   for (player = first_player; player; player = player->next)
85     if (player != except && player->introduced &&
86         (player->active || !activeonly))
87       addtobuffer(player, realbuffer, 4 + len);
88 }
89
90 static void sendtoone(struct NetworkServerPlayerInfo *to, int len)
91 {
92   realbuffer[0] = realbuffer[1] = realbuffer[2] = 0;
93   realbuffer[3] = (unsigned char)len;
94   addtobuffer(to, realbuffer, 4 + len);
95 }
96
97 static void RemovePlayer(struct NetworkServerPlayerInfo *player)
98 {
99   struct NetworkServerPlayerInfo *v;
100   
101   if (options.verbose)
102     Error(ERR_NETWORK_SERVER, "dropping client %d (%s)",
103           player->number, player->player_name);
104
105   if (player == first_player)
106     first_player = player->next;
107   else
108   {
109     for (v = first_player; v; v = v->next)
110     {
111       if (v->next && v->next == player)
112       {
113         v->next = player->next;
114         break;
115       }
116     }
117   }
118
119   SDLNet_TCP_DelSocket(fds, player->fd);
120   SDLNet_TCP_Close(player->fd);
121
122   if (player->introduced)
123   {
124     buffer[0] = player->number;
125     buffer[1] = OP_PLAYER_DISCONNECTED;
126     broadcast(player, 2, 0);
127   }
128
129   free(player);
130   clients--;
131
132 #if 0   /* do not terminate network server if last player disconnected */
133   if (onceonly && clients == 0)
134   {
135     if (options.verbose)
136     {
137       Error(ERR_NETWORK_SERVER, "no clients left");
138       Error(ERR_NETWORK_SERVER, "aborting");
139     }
140     exit(0);
141   }
142 #endif
143 }
144
145 static void AddPlayer(TCPsocket fd)
146 {
147   struct NetworkServerPlayerInfo *player, *v;
148   unsigned char nxn;
149   boolean again = TRUE;
150
151   player = checked_malloc(sizeof (struct NetworkServerPlayerInfo));
152
153   player->fd = fd;
154   player->player_name[0] = 0;
155   player->next = first_player;
156   player->active = 0;
157   player->nread = 0;
158   player->nwrite = 0;
159   player->introduced = 0;
160   player->action = 0;
161   player->action_received = FALSE;
162
163   SDLNet_TCP_AddSocket(fds, fd);
164
165   first_player = player;
166
167   nxn = 1;
168
169   while (again)
170   {
171     again = FALSE;
172     v = player->next;
173
174     while (v)
175     {
176       if (v->number == nxn)
177       {
178         nxn++;
179
180         again = TRUE;
181         break;
182       }
183       v = v->next;
184     }
185   }
186
187   player->number = nxn;
188   clients++;
189
190   buffer[0] = 0;
191   buffer[1] = OP_YOUR_NUMBER;
192   buffer[2] = player->number;
193   sendtoone(player, 3);
194 }
195
196 static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *player,
197                                        unsigned int len)
198 {
199   if (len != 5 ||
200       buffer[2] != PROTOCOL_VERSION_1 ||
201       buffer[3] != PROTOCOL_VERSION_2)
202   {
203     if (options.verbose)
204       Error(ERR_NETWORK_SERVER,
205             "client %d (%s) has wrong protocol version %d.%d.%d",
206             player->number, player->player_name, buffer[2], buffer[3], buffer[4]);
207
208     buffer[0] = 0;
209     buffer[1] = OP_BAD_PROTOCOL_VERSION;
210     buffer[2] = PROTOCOL_VERSION_1;
211     buffer[3] = PROTOCOL_VERSION_2;
212     buffer[4] = PROTOCOL_VERSION_3;
213     sendtoone(player, 5);
214     flushuser(player);
215
216     RemovePlayer(player);
217     interrupt = 1;
218   }
219   else
220   {
221     if (options.verbose)
222       Error(ERR_NETWORK_SERVER,
223             "client %d (%s) uses protocol version %d.%d.%d",
224             player->number, player->player_name, buffer[2], buffer[3], buffer[4]);
225   }
226 }
227
228 static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *player)
229 {
230   struct NetworkServerPlayerInfo *v;
231   int client_nr = player->number;
232   int nr_wanted = buffer[2];
233   int nr_is_free = 1;
234
235   if (options.verbose)
236       Error(ERR_NETWORK_SERVER, "client %d (%s) wants to switch to # %d",
237             player->number, player->player_name, nr_wanted);
238
239   for (v = first_player; v; v = v->next)
240   {
241     if (v->number == nr_wanted)
242     {
243       nr_is_free = 0;
244       break;
245     }
246   }
247
248   if (options.verbose)
249   {
250     if (nr_is_free)
251       Error(ERR_NETWORK_SERVER, "client %d (%s) switches to # %d",
252             player->number, player->player_name, nr_wanted);
253     else if (player->number == nr_wanted)
254       Error(ERR_NETWORK_SERVER, "client %d (%s) already has # %d",
255             player->number, player->player_name, nr_wanted);
256     else
257       Error(ERR_NETWORK_SERVER,
258             "client %d (%s) cannot switch (client %d already exists)",
259             player->number, player->player_name, nr_wanted);
260   }
261
262   if (nr_is_free)
263     player->number = nr_wanted;
264
265   buffer[0] = client_nr;
266   buffer[1] = OP_NUMBER_WANTED;
267   buffer[2] = nr_wanted;
268   buffer[3] = player->number;
269
270   /*
271   sendtoone(player, 4);
272   */
273
274   broadcast(NULL, 4, 0);
275 }
276
277 static void Handle_OP_PLAYER_NAME(struct NetworkServerPlayerInfo *player,
278                                   unsigned int len)
279 {
280   struct NetworkServerPlayerInfo *v;
281   int i;
282
283   if (len>16)
284     len=16;
285   memcpy(player->player_name, &buffer[2], len-2);
286   player->player_name[len-2] = 0;
287   for (i = 0; i < len - 2; i++)
288   {
289     if (player->player_name[i] < ' ' || 
290         ((unsigned char)(player->player_name[i]) > 0x7e &&
291          (unsigned char)(player->player_name[i]) <= 0xa0))
292     {
293       player->player_name[i] = 0;
294       break;
295     }
296   }
297
298   if (!player->introduced)
299   {
300     buffer[0] = player->number;
301     buffer[1] = OP_PLAYER_CONNECTED;
302     broadcast(player, 2, 0);
303   }
304               
305   if (options.verbose)
306     Error(ERR_NETWORK_SERVER, "client %d calls itself \"%s\"",
307           player->number, player->player_name);
308   buffer[1] = OP_PLAYER_NAME;
309   broadcast(player, len, 0);
310
311   if (!player->introduced)
312   {
313     for (v = first_player; v; v = v->next)
314     {
315       if (v != player && v->introduced)
316       {
317         buffer[0] = v->number;
318         buffer[1] = OP_PLAYER_CONNECTED;
319         sendtoone(player, 2);
320         buffer[1] = OP_PLAYER_NAME;
321         memcpy(&buffer[2], v->player_name, 14);
322         sendtoone(player, 2+strlen(v->player_name));
323       }
324     }
325   }
326
327   player->introduced = 1;
328 }
329
330 static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *player)
331 {
332   struct NetworkServerPlayerInfo *v, *w;
333
334   if (options.verbose)
335     Error(ERR_NETWORK_SERVER,
336           "client %d (%s) starts game [level %d from leveldir %d (%s)]",
337           player->number, player->player_name,
338           (buffer[2] << 8) + buffer[3],
339           (buffer[4] << 8) + buffer[5],
340           &buffer[10]);
341
342   for (w = first_player; w; w = w->next)
343     if (w->introduced)
344       w->active = 1;
345
346   /* reset frame counter */
347   ServerFrameCounter = 0;
348
349   Error(ERR_NETWORK_SERVER, "resetting ServerFrameCounter to 0");
350
351   /* reset player actions */
352   for (v = first_player; v; v = v->next)
353   {
354     v->action = 0;
355     v->action_received = FALSE;
356   }
357
358   broadcast(NULL, 10 + strlen((char *)&buffer[10])+1, 0);
359 }
360
361 static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *player)
362 {
363   if (options.verbose)
364     Error(ERR_NETWORK_SERVER, "client %d (%s) pauses game",
365           player->number, player->player_name);
366   broadcast(NULL, 2, 0);
367 }
368
369 static void Handle_OP_CONTINUE_PLAYING(struct NetworkServerPlayerInfo *player)
370 {
371   if (options.verbose)
372     Error(ERR_NETWORK_SERVER, "client %d (%s) continues game",
373           player->number, player->player_name);
374   broadcast(NULL, 2, 0);
375 }
376
377 static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *player)
378 {
379   int cause_for_stopping = buffer[2];
380
381   if (options.verbose)
382     Error(ERR_NETWORK_SERVER, "client %d (%s) stops game [%d]",
383           player->number, player->player_name, cause_for_stopping);
384   broadcast(NULL, 3, 0);
385 }
386
387 static void Handle_OP_MOVE_PLAYER(struct NetworkServerPlayerInfo *player)
388 {
389   struct NetworkServerPlayerInfo *v;
390   int last_client_nr = 0;
391   int i;
392
393   /* store player action */
394   for (v = first_player; v; v = v->next)
395   {
396     if (v->number == player->number)
397     {
398       v->action = buffer[2];
399       v->action_received = TRUE;
400     }
401   }
402
403   /* check if server received action from each player */
404   for (v = first_player; v; v = v->next)
405   {
406     if (!v->action_received)
407       return;
408
409     if (v->number > last_client_nr)
410       last_client_nr = v->number;
411   }
412
413   /* initialize all player actions to zero */
414   for (i = 0; i < last_client_nr; i++)
415     buffer[6 + i] = 0;
416
417   /* broadcast actions of all players to all players */
418   for (v = first_player; v; v = v->next)
419   {
420     buffer[6 + v->number-1] = v->action;
421     v->action = 0;
422     v->action_received = FALSE;
423   }
424
425   buffer[2] = (unsigned char)((ServerFrameCounter >> 24) & 0xff);
426   buffer[3] = (unsigned char)((ServerFrameCounter >> 16) & 0xff);
427   buffer[4] = (unsigned char)((ServerFrameCounter >>  8) & 0xff);
428   buffer[5] = (unsigned char)((ServerFrameCounter >>  0) & 0xff);
429
430   broadcast(NULL, 6 + last_client_nr, 0);
431
432   ServerFrameCounter++;
433 }
434
435 void ExitNetworkServer(int exit_value)
436 {
437   Error(ERR_NETWORK_SERVER, "exiting network server");
438
439   exit(exit_value);
440 }
441
442 /* the following is not used for a standalone server;
443    the pointer points to an integer containing the port-number */
444 int NetworkServerThread(void *ptr)
445 {
446   NetworkServer(*((int *) ptr), 0);
447
448   /* should never be reached */
449   return 0;
450 }
451
452 void NetworkServer(int port, int serveronly)
453 {
454   struct NetworkServerPlayerInfo *player;
455   int r; 
456   unsigned int len;
457   IPaddress ip;
458
459 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_NEXT)
460   struct sigaction sact;
461 #endif
462
463   if (port == 0)
464     port = DEFAULT_SERVER_PORT;
465
466   // if only running the network server, exit on Ctrl-C
467   if (serveronly)
468     signal(SIGINT, ExitNetworkServer);
469
470   if (!serveronly)
471     onceonly = 1;
472
473 #if defined(PLATFORM_UNIX)
474 #if defined(PLATFORM_NEXT)
475   signal(SIGPIPE, SIG_IGN);
476 #else
477   sact.sa_handler = SIG_IGN;
478   sigemptyset(&sact.sa_mask);
479   sact.sa_flags = 0;
480   sigaction(SIGPIPE, &sact, NULL);
481 #endif
482 #endif
483
484   if (SDLNet_ResolveHost(&ip, NULL, port) == -1)
485     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_ResolveHost() failed: %s",
486           SDLNet_GetError());
487
488   if ((fds = SDLNet_AllocSocketSet(MAX_PLAYERS + 1 + 1)) == NULL)
489     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_AllocSocketSet() failed: %s"),
490       SDLNet_GetError();
491
492   if ((lfd = SDLNet_TCP_Open(&ip)) == NULL)
493     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_Open() failed: %s"),
494       SDLNet_GetError();
495
496   if (SDLNet_TCP_AddSocket(fds, lfd) == -1)
497     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
498       SDLNet_GetError();
499
500   if ((udp = SDLNet_UDP_Open(port)) == NULL)
501     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_UDP_Open() failed: %s",
502           SDLNet_GetError());
503
504   if (SDLNet_UDP_AddSocket(fds, udp) == -1)
505     Error(ERR_EXIT_NETWORK_SERVER, "SDLNet_TCP_AddSocket() failed: %s"),
506       SDLNet_GetError();
507
508   if (options.verbose)
509   {
510     Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port);
511     Error(ERR_NETWORK_SERVER, "using protocol version %d.%d.%d",
512           PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, PROTOCOL_VERSION_3);
513   }
514
515   while (1)
516   {
517     interrupt = 0;
518
519     for (player = first_player; player; player = player->next)
520       flushuser(player);
521
522     // wait for 100 ms for activity on open network sockets
523     if (SDLNet_CheckSockets(fds, 100) < 1)
524       continue;
525
526     /* accept incoming TCP connections */
527     if (SDLNet_SocketReady(lfd))
528     {
529       Error(ERR_DEBUG, "got TCP packet");
530
531       TCPsocket newsock;
532
533       newsock = SDLNet_TCP_Accept(lfd);
534
535       if (newsock)
536         AddPlayer(newsock);
537     }
538
539     /* accept incoming UDP packets */
540     if (SDLNet_SocketReady(udp))
541     {
542       Error(ERR_DEBUG, "got UDP packet");
543
544       static UDPpacket packet;
545
546       int num_packets = SDLNet_UDP_Recv(udp, &packet);
547
548       if (num_packets == 1)
549       {
550         // bounce packet
551         SDLNet_UDP_Send(udp, -1, &packet);
552       }
553     }
554
555     player = first_player;
556
557     while (player && !interrupt)
558     {
559       if (SDLNet_SocketReady(player->fd))
560       {
561         /* read only 1 byte, because SDLNet blocks when we want more than is
562            in the buffer */
563         r = SDLNet_TCP_Recv(player->fd, player->readbuffer + player->nread, 1);
564
565         if (r <= 0)
566         {
567           if (options.verbose)
568             Error(ERR_NETWORK_SERVER, "EOF from client %d (%s)",
569                   player->number, player->player_name);
570           RemovePlayer(player);
571           interrupt = 1;
572           break;
573         }
574         player->nread += r;
575         while (player->nread >= 4 && player->nread >= 4 + player->readbuffer[3])
576         {
577           len = player->readbuffer[3];
578           if (player->readbuffer[0] || player->readbuffer[1] || player->readbuffer[2])
579           {
580             if (options.verbose)
581               Error(ERR_NETWORK_SERVER, "crap from client %d (%s)",
582                     player->number, player->player_name);
583             RemovePlayer(player);
584             interrupt = 1;
585             break;
586           }
587           memcpy(buffer, &player->readbuffer[4], len);
588           player->nread -= 4 + len;
589           memmove(player->readbuffer, player->readbuffer + 4 + len, player->nread);
590
591           buffer[0] = player->number;
592           if (!player->introduced &&
593               buffer[1] != OP_PLAYER_NAME &&
594               buffer[1] != OP_PROTOCOL_VERSION)
595           {
596             if (options.verbose)
597               Error(ERR_NETWORK_SERVER, "!(client %d)->introduced && buffer[1]==%d (expected OP_PLAYER_NAME or OP_PROTOCOL_VERSION)", buffer[0], buffer[1]);
598
599             RemovePlayer(player);
600             interrupt = 1;
601             break;
602           }
603
604           switch (buffer[1])
605           {
606             case OP_PLAYER_NAME:
607               Handle_OP_PLAYER_NAME(player, len);
608               break;
609
610             case OP_PROTOCOL_VERSION:
611               Handle_OP_PROTOCOL_VERSION(player, len);
612               break;
613
614             case OP_NUMBER_WANTED:
615               Handle_OP_NUMBER_WANTED(player);
616               break;
617
618             case OP_START_PLAYING:
619               Handle_OP_START_PLAYING(player);
620               break;
621
622             case OP_PAUSE_PLAYING:
623               Handle_OP_PAUSE_PLAYING(player);
624               break;
625
626             case OP_CONTINUE_PLAYING:
627               Handle_OP_CONTINUE_PLAYING(player);
628               break;
629
630             case OP_STOP_PLAYING:
631               Handle_OP_STOP_PLAYING(player);
632               break;
633
634             case OP_MOVE_PLAYER:
635               Handle_OP_MOVE_PLAYER(player);
636               break;
637
638             case OP_BROADCAST_MESSAGE:
639               buffer[len] = '\0';
640               if (options.verbose)
641                 Error(ERR_NETWORK_SERVER, "client %d (%s) sends message: %s",
642                       player->number, player->player_name, &buffer[2]);
643               broadcast(player, len, 0);
644               break;
645             
646             default:
647               if (options.verbose)
648                 Error(ERR_NETWORK_SERVER,
649                       "unknown opcode %d from client %d (%s)",
650                       buffer[0], player->number, player->player_name);
651           }
652         }
653       }
654
655       if (player && !interrupt)
656         player = player->next;
657     }
658   }
659 }