6f5a9a4ce1c0e2ec99b09ec610e1ae922de7405e
[rocksndiamonds.git] / src / netserv.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  network.c                                               *
12 ***********************************************************/
13
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <sys/time.h>
17 #include <signal.h>
18 #include <sys/socket.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <arpa/inet.h>
24 #include <netdb.h>
25
26 #include "netserv.h"
27 #include "misc.h"
28
29 static int clients = 0;
30 static int onceonly = 0;
31 static int is_daemon = 0;
32
33 struct NetworkServerPlayerInfo
34 {
35   int fd;
36   unsigned char player_name[16];
37   unsigned char number;
38   struct NetworkServerPlayerInfo *next;
39   char active;
40   char introduced;
41   unsigned char readbuf[MAX_BUFFER_SIZE];
42   unsigned char writbuf[MAX_BUFFER_SIZE];
43   int nread, nwrite;
44   byte action;
45   boolean action_received;
46 };
47
48 static struct NetworkServerPlayerInfo *user0 = NULL;
49
50 #define NEXT(u) ((u)->next ? (u)->next : user0)
51
52 static struct sockaddr_in saddr;
53 static int lfd;
54 static unsigned char realbuf[512], *buf = realbuf + 4;
55
56 static int interrupt;
57 static int tcp = -1;
58
59 static unsigned long ServerFrameCounter = 0;
60
61 static fd_set fds;
62
63 static void syserr(char *s)
64 {
65   if (!is_daemon)
66     fprintf(stderr, "fatal: %s failed.\n", s);
67   exit(1);
68 }
69
70 static void addtobuffer(struct NetworkServerPlayerInfo *u,
71                         unsigned char *b, int len)
72 {
73   if (u->nwrite + len >= MAX_BUFFER_SIZE)
74     Error(ERR_EXIT, "internal error: network send buffer overflow");
75
76   memcpy(u->writbuf + u->nwrite, b, len);
77   u->nwrite += len;
78 }
79
80 static void flushuser(struct NetworkServerPlayerInfo *u)
81 {
82   if (u->nwrite)
83   {
84     write(u->fd, u->writbuf, u->nwrite);
85     u->nwrite = 0;
86   }
87 }
88
89 static void broadcast(struct NetworkServerPlayerInfo *except,
90                       int len, int activeonly)
91 {
92   struct NetworkServerPlayerInfo *u;
93
94   realbuf[0] = realbuf[1] = realbuf[2] = 0;
95   realbuf[3] = (unsigned char)len;
96   for (u=user0; u; u=u->next)
97     if (u != except && (u->active || !activeonly) && u->introduced)
98       addtobuffer(u, realbuf, 4 + len);
99 }
100
101 static void sendtoone(struct NetworkServerPlayerInfo *to, int len)
102 {
103   realbuf[0] = realbuf[1] = realbuf[2] = 0;
104   realbuf[3] = (unsigned char)len;
105   addtobuffer(to, realbuf, 4 + len);
106 }
107
108 static void dropuser(struct NetworkServerPlayerInfo *u)
109 {
110   struct NetworkServerPlayerInfo *v;
111   
112   if (options.verbose)
113     Error(ERR_NETWORK_SERVER, "dropping client %d (%s)",
114           u->number, u->player_name);
115
116   if (u == user0)
117     user0 = u->next;
118   else
119   {
120     for (v=user0; v; v=v->next)
121     {
122       if (v->next && v->next == u)
123       {
124         v->next = u->next;
125         break;
126       }
127     }
128   }
129   close(u->fd);
130
131   if (u->introduced)
132   {
133     buf[0] = u->number;
134     buf[1] = OP_PLAYER_DISCONNECTED;
135     broadcast(u, 2, 0);
136   }
137
138   free(u);
139   clients--;
140
141   if (onceonly && clients == 0)
142   {
143     if (options.verbose)
144     {
145       Error(ERR_NETWORK_SERVER, "no clients left");
146       Error(ERR_NETWORK_SERVER, "aborting");
147     }
148     exit(0);
149   }
150 }
151
152 static void new_connect(int fd)
153 {
154   struct NetworkServerPlayerInfo *u, *v;
155   unsigned char nxn;
156
157   u = checked_malloc(sizeof (struct NetworkServerPlayerInfo));
158
159   u->fd = fd;
160   u->player_name[0] = 0;
161   u->next = user0;
162   u->active = 0;
163   u->nread = 0;
164   u->nwrite = 0;
165   u->introduced = 0;
166   u->action = 0;
167   u->action_received = FALSE;
168
169   user0 = u;
170
171   nxn = 1;
172
173  again:
174   v = u->next;
175   while(v)
176   {
177     if (v->number == nxn)
178     {
179       nxn++;
180       goto again;
181     }
182     v = v->next;
183   }
184
185   u->number = nxn;
186   if (options.verbose)
187     Error(ERR_NETWORK_SERVER, "client %d connecting from %s",
188           nxn, inet_ntoa(saddr.sin_addr));
189   clients++;
190
191   buf[0] = 0;
192   buf[1] = OP_YOUR_NUMBER;
193   buf[2] = u->number;
194   sendtoone(u, 3);
195 }
196
197 static void Handle_OP_PROTOCOL_VERSION(struct NetworkServerPlayerInfo *u,
198                                        unsigned int len)
199 {
200   if (len != 5 || buf[2] != PROTOCOL_VERSION_1 || buf[3] != PROTOCOL_VERSION_2)
201   {
202     if (options.verbose)
203       Error(ERR_NETWORK_SERVER,
204             "client %d (%s) has wrong protocol version %d.%d.%d",
205             u->number, u->player_name, buf[2], buf[3], buf[4]);
206
207     buf[0] = 0;
208     buf[1] = OP_BAD_PROTOCOL_VERSION;
209     buf[2] = PROTOCOL_VERSION_1;
210     buf[3] = PROTOCOL_VERSION_2;
211     buf[4] = PROTOCOL_VERSION_3;
212     sendtoone(u, 5);
213     flushuser(u);
214
215     dropuser(u);
216     interrupt = 1;
217   }
218   else
219   {
220     if (options.verbose)
221       Error(ERR_NETWORK_SERVER,
222             "client %d (%s) uses protocol version %d.%d.%d",
223             u->number, u->player_name, buf[2], buf[3], buf[4]);
224   }
225 }
226
227 static void Handle_OP_NUMBER_WANTED(struct NetworkServerPlayerInfo *u)
228 {
229   struct NetworkServerPlayerInfo *v;
230   int client_nr = u->number;
231   int nr_wanted = buf[2];
232   int nr_is_free = 1;
233
234   if (options.verbose)
235       Error(ERR_NETWORK_SERVER, "client %d (%s) wants to switch to # %d",
236             u->number, u->player_name, nr_wanted);
237
238   for (v=user0; v; v=v->next)
239   {
240     if (v->number == nr_wanted)
241     {
242       nr_is_free = 0;
243       break;
244     }
245   }
246
247   if (options.verbose)
248   {
249     if (nr_is_free)
250       Error(ERR_NETWORK_SERVER, "client %d (%s) switches to # %d",
251             u->number, u->player_name, nr_wanted);
252     else if (u->number == nr_wanted)
253       Error(ERR_NETWORK_SERVER, "client %d (%s) still has # %d",
254             u->number, u->player_name, nr_wanted);
255     else
256       Error(ERR_NETWORK_SERVER,
257             "client %d (%s) cannot switch (client %d still exists)",
258             u->number, u->player_name, nr_wanted);
259   }
260
261   if (nr_is_free)
262     u->number = nr_wanted;
263
264   buf[0] = client_nr;
265   buf[1] = OP_NUMBER_WANTED;
266   buf[2] = nr_wanted;
267   buf[3] = u->number;
268
269   /*
270   sendtoone(u, 4);
271   */
272
273   broadcast(NULL, 4, 0);
274 }
275
276 static void Handle_OP_PLAYER_NAME(struct NetworkServerPlayerInfo *u,
277                                   unsigned int len)
278 {
279   struct NetworkServerPlayerInfo *v;
280   int i;
281
282   if (len>16)
283     len=16;
284   memcpy(u->player_name, &buf[2], len-2);
285   u->player_name[len-2] = 0;
286   for (i=0; i<len-2; i++)
287   {
288     if (u->player_name[i] < ' ' || 
289         (u->player_name[i] > 0x7e && u->player_name[i] <= 0xa0))
290     {
291       u->player_name[i] = 0;
292       break;
293     }
294   }
295
296   if (!u->introduced)
297   {
298     buf[0] = u->number;
299     buf[1] = OP_PLAYER_CONNECTED;
300     broadcast(u, 2, 0);
301   }
302               
303   if (options.verbose)
304     Error(ERR_NETWORK_SERVER, "client %d calls itself \"%s\"",
305           u->number, u->player_name);
306   buf[1] = OP_PLAYER_NAME;
307   broadcast(u, len, 0);
308
309   if (!u->introduced)
310   {
311     for (v=user0; v; v=v->next)
312     {
313       if (v != u && v->introduced)
314       {
315         buf[0] = v->number;
316         buf[1] = OP_PLAYER_CONNECTED;
317         sendtoone(u, 2);
318         buf[1] = OP_PLAYER_NAME;
319         memcpy(&buf[2], v->player_name, 14);
320         sendtoone(u, 2+strlen(v->player_name));
321       }
322     }
323   }
324
325   u->introduced = 1;
326 }
327
328 static void Handle_OP_START_PLAYING(struct NetworkServerPlayerInfo *u)
329 {
330   struct NetworkServerPlayerInfo *v, *w;
331
332   if (options.verbose)
333     Error(ERR_NETWORK_SERVER,
334           "client %d (%s) starts game [level %d from levedir %d (%s)]",
335           u->number, u->player_name,
336           (buf[2] << 8) + buf[3],
337           (buf[4] << 8) + buf[5],
338           &buf[6]);
339
340   for (w=user0; w; w=w->next)
341     if (w->introduced)
342       w->active = 1;
343
344   /* reset frame counter */
345   ServerFrameCounter = 0;
346
347   /* reset player actions */
348   for (v=user0; v; v=v->next)
349   {
350     v->action = 0;
351     v->action_received = FALSE;
352   }
353
354   broadcast(NULL, 10 + strlen(&buf[10])+1, 0);
355 }
356
357 static void Handle_OP_PAUSE_PLAYING(struct NetworkServerPlayerInfo *u)
358 {
359   if (options.verbose)
360     Error(ERR_NETWORK_SERVER, "client %d (%s) pauses game",
361           u->number, u->player_name);
362   broadcast(NULL, 2, 0);
363 }
364
365 static void Handle_OP_CONTINUE_PLAYING(struct NetworkServerPlayerInfo *u)
366 {
367   if (options.verbose)
368     Error(ERR_NETWORK_SERVER, "client %d (%s) continues game",
369           u->number, u->player_name);
370   broadcast(NULL, 2, 0);
371 }
372
373 static void Handle_OP_STOP_PLAYING(struct NetworkServerPlayerInfo *u)
374 {
375   if (options.verbose)
376     Error(ERR_NETWORK_SERVER, "client %d (%s) stops game",
377           u->number, u->player_name);
378   broadcast(NULL, 2, 0);
379 }
380
381 static void Handle_OP_MOVE_FIGURE(struct NetworkServerPlayerInfo *u)
382 {
383   struct NetworkServerPlayerInfo *v;
384   int last_client_nr = 0;
385   int i;
386
387   /* store player action */
388   for (v=user0; v; v=v->next)
389   {
390     if (v->number == u->number)
391     {
392       v->action = buf[2];
393       v->action_received = TRUE;
394     }
395   }
396
397   /* check if server received action from each player */
398   for (v=user0; v; v=v->next)
399   {
400     if (!v->action_received)
401       return;
402
403     if (v->number > last_client_nr)
404       last_client_nr = v->number;
405   }
406
407   /* initialize all player actions to zero */
408   for (i=0; i<last_client_nr; i++)
409     buf[6 + i] = 0;
410
411   /* broadcast actions of all players to all players */
412   for (v=user0; v; v=v->next)
413   {
414     buf[6 + v->number-1] = v->action;
415     v->action = 0;
416     v->action_received = FALSE;
417   }
418
419   buf[2] = (unsigned char)((ServerFrameCounter >> 24) & 0xff);
420   buf[3] = (unsigned char)((ServerFrameCounter >> 16) & 0xff);
421   buf[4] = (unsigned char)((ServerFrameCounter >>  8) & 0xff);
422   buf[5] = (unsigned char)((ServerFrameCounter >>  0) & 0xff);
423
424   broadcast(NULL, 6 + last_client_nr, 0);
425
426   ServerFrameCounter++;
427 }
428
429 void NetworkServer(int port, int serveronly)
430 {
431   int i, sl, on;
432   struct NetworkServerPlayerInfo *u;
433   int mfd;
434   int r; 
435   unsigned int len;
436   struct protoent *tcpproto;
437   struct timeval tv;
438   int is_daemon = 0;
439
440 #ifndef NeXT
441   struct sigaction sact;
442 #endif
443
444   if (port == 0)
445     port = DEFAULT_SERVER_PORT;
446
447   if (!serveronly)
448     onceonly = 1;
449
450   if ((tcpproto = getprotobyname("tcp")) != NULL)
451     tcp = tcpproto->p_proto;
452
453 #ifdef NeXT
454   signal(SIGPIPE, SIG_IGN);
455 #else
456   sact.sa_handler = SIG_IGN;
457   sigemptyset(&sact.sa_mask);
458   sact.sa_flags = 0;
459   sigaction(SIGPIPE, &sact, NULL);
460 #endif
461
462
463   lfd = socket(PF_INET, SOCK_STREAM, 0);
464   saddr.sin_family = AF_INET;
465   saddr.sin_addr.s_addr = htonl(INADDR_ANY);
466   saddr.sin_port = htons(port);
467
468   if (lfd < 0)
469     syserr("socket");
470   on = 1;
471
472   setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int));
473   if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
474     syserr("bind");
475
476   listen(lfd, 5);
477
478   if (is_daemon)
479   {
480     /* become a daemon, breaking all ties with the controlling terminal */
481     options.verbose = 0;
482     for (i=0; i<255; i++)
483     {
484       if (i != lfd)
485         close(i);
486     }
487
488     if (fork())
489       exit(0);
490     setsid();
491     if (fork())
492       exit(0);
493     chdir("/");
494
495     /* open a fake stdin, stdout, stderr, just in case */
496     open("/dev/null", O_RDONLY);
497     open("/dev/null", O_WRONLY);
498     open("/dev/null", O_WRONLY);
499   }
500
501   if (options.verbose)
502   {
503     Error(ERR_NETWORK_SERVER, "started up, listening on port %d", port);
504     Error(ERR_NETWORK_SERVER, "using protocol version %d.%d.%d",
505           PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, PROTOCOL_VERSION_3);
506   }
507
508   while(1)
509   {
510     interrupt = 0;
511
512     for (u=user0; u; u=u->next)
513       flushuser(u);
514
515     FD_ZERO(&fds);
516     mfd = lfd;
517     u = user0;
518     while (u)
519     {
520       FD_SET(u->fd, &fds);
521       if (u->fd > mfd)
522         mfd = u->fd;
523       u = u->next;
524     }
525     FD_SET(lfd, &fds);
526     tv.tv_sec = 0;
527     tv.tv_usec = 500000;
528     if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
529     {
530       if (errno != EINTR)
531         syserr("select");
532       else
533         continue;
534     }
535
536     if (sl < 0)
537       continue;
538     
539     if (sl == 0)
540       continue;
541
542     if (FD_ISSET(lfd, &fds))
543     {
544       int newfd, slen;
545
546       slen = sizeof(saddr);
547       newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
548       if (newfd < 0)
549       {
550         if (errno != EINTR)
551           syserr("accept");
552       }
553       else
554       {
555         if (tcp != -1)
556         {
557           on = 1;
558           setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
559         }
560         new_connect(newfd);
561       }
562       continue;
563     }
564
565     u = user0;
566
567     do
568     {
569       if (FD_ISSET(u->fd, &fds))
570       {
571         r = read(u->fd, u->readbuf + u->nread, MAX_BUFFER_SIZE - u->nread);
572         if (r <= 0)
573         {
574           if (options.verbose)
575             Error(ERR_NETWORK_SERVER, "EOF from client %d (%s)",
576                   u->number, u->player_name);
577           dropuser(u);
578           interrupt = 1;
579           break;
580         }
581         u->nread += r;
582         while (u->nread >= 4 && u->nread >= 4 + u->readbuf[3])
583         {
584           len = u->readbuf[3];
585           if (u->readbuf[0] || u->readbuf[1] || u->readbuf[2])
586           {
587             if (options.verbose)
588               Error(ERR_NETWORK_SERVER, "crap from client %d (%s)",
589                     u->number, u->player_name);
590             write(u->fd, "\033]50;kanji24\007\033#8\033(0", 19);
591             dropuser(u);
592             interrupt = 1;
593             break;
594           }
595           memcpy(buf, &u->readbuf[4], len);
596           u->nread -= 4 + len;
597           memmove(u->readbuf, u->readbuf + 4 + len, u->nread);
598
599           buf[0] = u->number;
600           if (!u->introduced && buf[1] != OP_PLAYER_NAME)
601           {
602             if (options.verbose)
603               Error(ERR_NETWORK_SERVER, "!(client %d)->introduced && buf[1]==%d (expected OP_PLAYER_NAME)", buf[0], buf[1]);
604
605             dropuser(u);
606             interrupt = 1;
607             break;
608           }
609
610           switch(buf[1])
611           {
612             case OP_PLAYER_NAME:
613               Handle_OP_PLAYER_NAME(u, len);
614               break;
615
616             case OP_PROTOCOL_VERSION:
617               Handle_OP_PROTOCOL_VERSION(u, len);
618               break;
619
620             case OP_NUMBER_WANTED:
621               Handle_OP_NUMBER_WANTED(u);
622               break;
623
624             case OP_START_PLAYING:
625               Handle_OP_START_PLAYING(u);
626               break;
627
628             case OP_PAUSE_PLAYING:
629               Handle_OP_PAUSE_PLAYING(u);
630               break;
631
632             case OP_CONTINUE_PLAYING:
633               Handle_OP_CONTINUE_PLAYING(u);
634               break;
635
636             case OP_STOP_PLAYING:
637               Handle_OP_STOP_PLAYING(u);
638               break;
639
640             case OP_MOVE_FIGURE:
641               Handle_OP_MOVE_FIGURE(u);
642               break;
643
644             case OP_BROADCAST_MESSAGE:
645               buf[len] = '\0';
646               if (options.verbose)
647                 Error(ERR_NETWORK_SERVER, "client %d (%s) sends message: %s",
648                       u->number, u->player_name, &buf[2]);
649               broadcast(u, len, 0);
650               break;
651             
652             default:
653               if (options.verbose)
654                 Error(ERR_NETWORK_SERVER,
655                       "unknown opcode %d from client %d (%s)",
656                       buf[0], u->number, u->player_name);
657           }
658         }
659       }
660
661       if (u && !interrupt)
662         u = u->next;
663     }
664     while (u && !interrupt);
665   }
666 }