rnd-19981010-2
[rocksndiamonds.git] / src / netserv.c
1 /*
2  *   A server for a multi-player version of Tetris
3  *
4  *   Copyright (C) 1996 Roger Espel Llima <roger.espel.llima@pobox.com>
5  *
6  *   Started: 10 Oct 1996
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation. See the file COPYING for details.
11  *
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <sys/types.h>
19 #include <sys/time.h>
20 #include <signal.h>
21 #include <sys/socket.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <netinet/in.h>
25 #include <netinet/tcp.h>
26 #include <arpa/inet.h>
27 #include <netdb.h>
28
29 #include "netserv.h"
30
31
32
33 extern int verbose;
34
35 extern void copydown(char *, char *, int);
36 extern void fatal(char *);
37
38
39
40 static int clients = 0;
41 static int bots = 0;
42 static int onceonly = 0;
43 static int timetoplay = 0;
44 static int daemon = 0;
45 static int level = 5;
46 static int mode = -1;
47 static int paused = 0;
48
49 struct user
50 {
51   int fd;
52   unsigned char nick[16];
53   unsigned char number;
54   struct user *next, *nextvictim;
55   char active;
56   char introduced;
57   unsigned char readbuf[MAX_BUFFER_SIZE];
58   int nread;
59   unsigned char writbuf[MAX_BUFFER_SIZE];
60   int nwrite;
61   char playing;
62   char isbot;
63   int lines;
64   unsigned int games;
65   unsigned char action;
66   int action_received;
67 };
68
69 static struct user *user0 = NULL;
70
71 #define NEXT(u) ((u)->next ? (u)->next : user0)
72
73 static struct sockaddr_in saddr;
74 static int lfd;
75 static unsigned char realbuf[512], *buf = realbuf + 4;
76
77 static int interrupt;
78 static int tcp = -1;
79
80 static unsigned long frame_counter = 0;
81
82 static fd_set fds;
83
84 static void syserr(char *s)
85 {
86   if (!daemon)
87     fprintf(stderr, "fatal: %s failed.\n", s);
88   exit(1);
89 }
90
91 static void addtobuffer(struct user *u, unsigned char *b, int len)
92 {
93   if (u->nwrite + len >= MAX_BUFFER_SIZE)
94     fatal("Internal error: send buffer overflow");
95   memcpy(u->writbuf + u->nwrite, b, len);
96   u->nwrite += len;
97 }
98
99 static void flushuser(struct user *u)
100 {
101   if (u->nwrite)
102   {
103     write(u->fd, u->writbuf, u->nwrite);
104     u->nwrite = 0;
105   }
106 }
107
108 static void broadcast(struct user *except, int len, int activeonly)
109 {
110   struct user *u;
111
112   realbuf[0] = realbuf[1] = realbuf[2] = 0;
113   realbuf[3] = (unsigned char)len;
114   for (u=user0; u; u=u->next)
115     if (u != except && (u->active || !activeonly) && u->introduced)
116       addtobuffer(u, realbuf, 4 + len);
117 }
118
119 static void sendtoone(struct user *to, int len)
120 {
121   realbuf[0] = realbuf[1] = realbuf[2] = 0;
122   realbuf[3] = (unsigned char)len;
123   addtobuffer(to, realbuf, 4 + len);
124 }
125
126 static void dropuser(struct user *u)
127 {
128   struct user *v, *w;
129   
130   if (verbose)
131     printf("RND_SERVER: dropping client %d (%s)\n", u->number, u->nick);
132
133   if (u == user0)
134     user0 = u->next;
135   else
136   {
137     for (v=user0; v; v=v->next)
138     {
139       if (v->next && v->next == u)
140       {
141         v->next = u->next;
142         break;
143       }
144     }
145   }
146   close(u->fd);
147
148   if (u->introduced)
149   {
150     buf[0] = u->number;
151     buf[1] = OP_PLAYER_DISCONNECTED;
152     broadcast(u, 2, 0);
153   }
154
155   for (v=user0; v; v=v->next)
156   {
157     if (v->nextvictim == u)
158     {
159       for (w=NEXT(v); w!=v; w=NEXT(w))
160       {
161         if (w->active && w->playing)
162         {
163           v->nextvictim = w;
164           break;
165         }
166       }
167       if (v->nextvictim == u)
168         v->nextvictim = NULL;
169     }
170   }
171
172   if (u->isbot)
173     bots--;
174
175   free(u);
176   clients--;
177
178   if (onceonly && clients == bots)
179   {
180     if (verbose)
181     {
182       printf("RND_SERVER: no clients left\n");
183       printf("RND_SERVER: aborting\n");
184     }
185     exit(0);
186   }
187
188   if (clients == 0)
189   {
190     mode = -1;
191     level = 5;
192     timetoplay = 0;
193   }
194 }
195
196 static void new_connect(int fd)
197 {
198   struct user *u, *v;
199   unsigned char nxn;
200
201   u = malloc(sizeof (struct user));
202   if (!u)
203     fatal("Out of memory");
204   u->fd = fd;
205   u->nick[0] = 0;
206   u->next = user0;
207   u->nextvictim = NULL;
208   u->active = 0;
209   u->nread = 0;
210   u->nwrite = 0;
211   u->playing = 0;
212   u->isbot = 0;
213   u->introduced = 0;
214   u->games = 0;
215   u->action = 0;
216   u->action_received = 0;
217
218   user0 = u;
219
220   nxn = 1;
221
222  again:
223   v = u->next;
224   while(v)
225   {
226     if (v->number == nxn)
227     {
228       nxn++;
229       goto again;
230     }
231     v = v->next;
232   }
233
234   u->number = nxn;
235   if (verbose)
236     printf("RND_SERVER: client %d connecting from %s\n", nxn, inet_ntoa(saddr.sin_addr));
237   clients++;
238
239   buf[0] = 0;
240   buf[1] = OP_YOUR_NUMBER;
241   buf[2] = u->number;
242   sendtoone(u, 3);
243 }
244
245 static void Handle_OP_PROTOCOL_VERSION(struct user *u, unsigned int len)
246 {
247   if (len != 5 || buf[2] != PROT_VERS_1 || buf[3] != PROT_VERS_2)
248   {
249     if (verbose)
250       printf("RND_SERVER: client %d (%s) has wrong protocol version %d.%d.%d\n", u->number, u->nick, buf[2], buf[3], buf[4]);
251
252     buf[0] = 0;
253     buf[1] = OP_BADVERS;
254     buf[2] = PROT_VERS_1;
255     buf[3] = PROT_VERS_2;
256     buf[4] = PROT_VERS_3;
257     sendtoone(u, 5);
258     flushuser(u);
259
260     dropuser(u);
261     interrupt = 1;
262   }
263   else
264   {
265     if (verbose)
266       printf("RND_SERVER: client %d (%s) uses protocol version %d.%d.%d\n", u->number, u->nick, buf[2], buf[3], buf[4]);
267   }
268 }
269
270 static void Handle_OP_NUMBER_WANTED(struct user *u)
271 {
272   struct user *v;
273   int nr_wanted = buf[2];
274   int nr_is_free = 1;
275
276   if (verbose)
277     printf("RND_SERVER: client %d (%s) wants to switch to # %d\n",
278            u->number, u->nick, nr_wanted);
279
280   for (v=user0; v; v=v->next)
281   {
282     if (v->number == nr_wanted)
283     {
284       nr_is_free = 0;
285       break;
286     }
287   }
288
289   if (verbose)
290   {
291     if (nr_is_free)
292       printf("RND_SERVER: client %d (%s) switches to # %d\n",
293              u->number, u->nick, nr_wanted);
294     else if (u->number == nr_wanted)
295       printf("RND_SERVER: client %d (%s) still has # %d\n",
296              u->number, u->nick, nr_wanted);
297     else
298       printf("RND_SERVER: client %d (%s) cannot switch (client %d still exists)\n",
299              u->number, u->nick, nr_wanted);
300   }
301
302   if (nr_is_free)
303     u->number = nr_wanted;
304
305   buf[0] = 0;
306   buf[1] = OP_NUMBER_WANTED;
307   buf[2] = nr_wanted;
308   buf[3] = u->number;
309   sendtoone(u, 4);
310 }
311
312 static void Handle_OP_NICKNAME(struct user *u, unsigned int len)
313 {
314   struct user *v;
315   int i;
316
317   if (len>16)
318     len=16;
319   memcpy(u->nick, &buf[2], len-2);
320   u->nick[len-2] = 0;
321   for (i=0; i<len-2; i++)
322   {
323     if (u->nick[i] < ' ' || 
324         (u->nick[i] > 0x7e && u->nick[i] <= 0xa0))
325     {
326       u->nick[i] = 0;
327       break;
328     }
329   }
330
331   if (!u->introduced)
332   {
333     buf[0] = u->number;
334     buf[1] = OP_PLAYER_CONNECTED;
335     broadcast(u, 2, 0);
336   }
337               
338   if (verbose)
339     printf("RND_SERVER: client %d calls itself \"%s\"\n", u->number, u->nick);
340   buf[1] = OP_NICKNAME;
341   broadcast(u, len, 0);
342
343   if (!u->introduced)
344   {
345     for (v=user0; v; v=v->next)
346     {
347       if (v != u && v->introduced)
348       {
349         buf[0] = v->number;
350         buf[1] = OP_PLAYER_CONNECTED;
351         buf[2] = (v->games >> 8);
352         buf[3] = (v->games & 0xff);
353         sendtoone(u, 4);
354         buf[1] = OP_NICKNAME;
355         memcpy(&buf[2], v->nick, 14);
356         sendtoone(u, 2+strlen(v->nick));
357       }
358     }
359     if (level != 5)
360     {
361       buf[0] = 0;
362       buf[1] = OP_LEVEL;
363       buf[2] = level;
364       sendtoone(u, 3);
365     }
366     if (mode >= 0)
367     {
368       buf[1] = OP_MODE;
369       buf[2] = mode;
370       sendtoone(u, 3);
371     }
372   }
373
374   u->introduced = 1;
375 }
376
377 static void Handle_OP_START_PLAYING(struct user *u)
378 {
379   struct user *v, *w;
380
381   if (verbose)
382     printf("RND_SERVER: client %d (%s) starts game [level %d from levedir %d (%s)]\n",
383            u->number, u->nick,
384            (buf[2] << 8) + buf[3],
385            (buf[4] << 8) + buf[5],
386            &buf[6]);
387   timetoplay = 0;
388
389   for (w=user0; w; w=w->next)
390   {
391     if (w->introduced)
392     {
393       w->active = 1;
394       w->playing = 1;
395       w->lines = 0;
396       w->nextvictim = NULL;
397       for (v=NEXT(w); v!=w; v=NEXT(v))
398       {
399         if (v->introduced)
400         {
401           w->nextvictim = v;
402           break;
403         }
404       }
405     }
406   }
407
408   /*
409   if (paused)
410   {
411     paused = 0;
412     buf[1] = OP_CONT;
413     broadcast(NULL, 2, 0);
414   }
415   buf[1] = OP_START_PLAYING;
416   broadcast(NULL, 2, 0);
417   */
418
419   /* reset frame counter */
420   frame_counter = 0;
421
422   /* reset player actions */
423   for (v=user0; v; v=v->next)
424   {
425     v->action = 0;
426     v->action_received = 0;
427   }
428
429   broadcast(NULL, 10 + strlen(&buf[10])+1, 0);
430 }
431
432 static void Handle_OP_PAUSE_PLAYING(struct user *u)
433 {
434   if (verbose)
435     printf("RND_SERVER: client %d (%s) pauses game\n", u->number, u->nick);
436   broadcast(NULL, 2, 0);
437   paused = 1;
438 }
439
440 static void Handle_OP_CONTINUE_PLAYING(struct user *u)
441 {
442   if (verbose)
443     printf("RND_SERVER: client %d (%s) continues game\n", u->number, u->nick);
444   broadcast(NULL, 2, 0);
445   paused = 0;
446 }
447
448 static void Handle_OP_STOP_PLAYING(struct user *u)
449 {
450   if (verbose)
451     printf("RND_SERVER: client %d (%s) stops game\n", u->number, u->nick);
452   broadcast(NULL, 2, 0);
453 }
454
455 static void Handle_OP_MOVE_FIGURE(struct user *u)
456 {
457   struct user *v;
458   int actions_complete = 1;
459   int last_client_nr = 0;
460
461   /* store player action */
462   for (v=user0; v; v=v->next)
463   {
464     if (v->number == u->number)
465     {
466       v->action = buf[2];
467       v->action_received = 1;
468     }
469   }
470
471   /* check if server received action from each player */
472   for (v=user0; v; v=v->next)
473   {
474     if (!v->action_received)
475     {
476       actions_complete = 0;
477       break;
478     }
479   }
480
481   if (!actions_complete)
482     return;
483
484   /* broadcast actions of all players to all players */
485   for (v=user0; v; v=v->next)
486   {
487     buf[6 + v->number-1] = v->action;
488     v->action = 0;
489     v->action_received = 0;
490
491     if (v->number > last_client_nr)
492       last_client_nr = v->number;
493   }
494
495   buf[2] = (unsigned char)((frame_counter >> 24) & 0xff);
496   buf[3] = (unsigned char)((frame_counter >> 16) & 0xff);
497   buf[4] = (unsigned char)((frame_counter >>  8) & 0xff);
498   buf[5] = (unsigned char)((frame_counter >>  0) & 0xff);
499
500   broadcast(NULL, 6 + last_client_nr, 0);
501
502   frame_counter++;
503
504   /*
505     if (verbose)
506     printf("RND_SERVER: frame %d: client %d (%s) moves player [0x%02x]\n",
507     frame_counter,
508     u->number, u->nick, buf[2]);
509   */
510 }
511
512 void NetworkServer(int port, int serveronly)
513 {
514   int i, sl, on;
515   struct user *u, *v, *w;
516   int mfd;
517   int r; 
518   unsigned int len;
519   struct protoent *tcpproto;
520   struct timeval tv;
521   int daemon = 0;
522
523 #ifndef NeXT
524   struct sigaction sact;
525 #endif
526
527   if (port == 0)
528     port = DEFAULTPORT;
529
530   if (!serveronly)
531     onceonly = 1;
532
533   if ((tcpproto = getprotobyname("tcp")) != NULL)
534     tcp = tcpproto->p_proto;
535
536 #ifdef NeXT
537   signal(SIGPIPE, SIG_IGN);
538 #else
539   sact.sa_handler = SIG_IGN;
540   sigemptyset(&sact.sa_mask);
541   sact.sa_flags = 0;
542   sigaction(SIGPIPE, &sact, NULL);
543 #endif
544
545
546   lfd = socket(PF_INET, SOCK_STREAM, 0);
547   saddr.sin_family = AF_INET;
548   saddr.sin_addr.s_addr = htonl(INADDR_ANY);
549   saddr.sin_port = htons(port);
550
551   if (lfd < 0)
552     syserr("socket");
553   on = 1;
554
555   setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int));
556   if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
557     syserr("bind");
558
559   listen(lfd, 5);
560
561   if (daemon)
562   {
563     /* become a daemon, breaking all ties with the controlling terminal */
564     verbose = 0;
565     for (i=0; i<255; i++)
566     {
567       if (i != lfd)
568         close(i);
569     }
570
571     if (fork())
572       exit(0);
573     setsid();
574     if (fork())
575       exit(0);
576     chdir("/");
577
578     /* open a fake stdin, stdout, stderr, just in case */
579     open("/dev/null", O_RDONLY);
580     open("/dev/null", O_WRONLY);
581     open("/dev/null", O_WRONLY);
582   }
583
584   if (verbose)
585   {
586     printf("rocksndiamonds network server: started up, listening on port %d\n",
587            port);
588     printf("rocksndiamonds network server: using protocol version %d.%d.%d\n",
589            PROT_VERS_1, PROT_VERS_2, PROT_VERS_3);
590   }
591
592   while(1)
593   {
594     interrupt = 0;
595
596     /*
597     if (timetoplay && time(NULL) >= timetoplay)
598     {
599       buf[0] = 0;
600       do_play();
601       if (verbose)
602         printf("RND_SERVER: everyone lost... restarting game\n");
603       timetoplay = 0;
604     }
605     */
606
607     for (u=user0; u; u=u->next)
608       flushuser(u);
609
610     FD_ZERO(&fds);
611     mfd = lfd;
612     u = user0;
613     while (u)
614     {
615       FD_SET(u->fd, &fds);
616       if (u->fd > mfd)
617         mfd = u->fd;
618       u = u->next;
619     }
620     FD_SET(lfd, &fds);
621     tv.tv_sec = 0;
622     tv.tv_usec = 500000;
623     if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
624       if (errno != EINTR)
625         syserr("select");
626       else continue;
627     
628     if (sl < 0)
629       continue;
630
631     if (clients > 0 && clients == bots)
632     {
633       if (verbose)
634         printf("RND_SERVER: only bots left... dropping all bots\n");
635       while (user0)
636         dropuser(user0);
637       continue;
638     }
639     
640     if (sl == 0)
641       continue;
642
643     if (FD_ISSET(lfd, &fds))
644     {
645       int newfd, slen;
646
647       slen = sizeof(saddr);
648       newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
649       if (newfd < 0)
650       {
651         if (errno != EINTR)
652           syserr("accept");
653       }
654       else
655       {
656         if (tcp != -1)
657         {
658           on = 1;
659           setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
660         }
661         new_connect(newfd);
662       }
663       continue;
664     }
665
666     u = user0;
667
668     do
669     {
670       if (FD_ISSET(u->fd, &fds))
671       {
672         r = read(u->fd, u->readbuf + u->nread, MAX_BUFFER_SIZE - u->nread);
673         if (r <= 0)
674         {
675           if (verbose)
676             printf("RND_SERVER: EOF from client %d (%s)\n", u->number, u->nick);
677           dropuser(u);
678           interrupt = 1;
679           break;
680         }
681         u->nread += r;
682         while (u->nread >= 4 && u->nread >= 4 + u->readbuf[3])
683         {
684           len = u->readbuf[3];
685           if (u->readbuf[0] || u->readbuf[1] || u->readbuf[2])
686           {
687             if (verbose)
688               printf("RND_SERVER: crap from client %d (%s)\n", u->number, u->nick);
689             write(u->fd, "\033]50;kanji24\007\033#8\033(0", 19);
690             dropuser(u);
691             interrupt = 1;
692             break;
693           }
694           memcpy(buf, &u->readbuf[4], len);
695           u->nread -= 4 + len;
696           copydown(u->readbuf, u->readbuf + 4 + len, u->nread);
697
698           buf[0] = u->number;
699           if (!u->introduced && buf[1] != OP_NICKNAME)
700           {
701             if (verbose)
702               printf("RND_SERVER: !(client %d)->introduced && buf[1]==%d (expected OP_NICKNAME)\n", buf[0], buf[1]);
703
704             dropuser(u);
705             interrupt = 1;
706             break;
707           }
708
709           switch(buf[1])
710           {
711             case OP_NICKNAME:
712               Handle_OP_NICKNAME(u, len);
713               break;
714
715             case OP_PROTOCOL_VERSION:
716               Handle_OP_PROTOCOL_VERSION(u, len);
717               break;
718
719             case OP_NUMBER_WANTED:
720               Handle_OP_NUMBER_WANTED(u);
721               break;
722
723             case OP_START_PLAYING:
724               Handle_OP_START_PLAYING(u);
725               break;
726
727             case OP_PAUSE_PLAYING:
728               Handle_OP_PAUSE_PLAYING(u);
729               break;
730
731             case OP_CONTINUE_PLAYING:
732               Handle_OP_CONTINUE_PLAYING(u);
733               break;
734
735             case OP_STOP_PLAYING:
736               Handle_OP_STOP_PLAYING(u);
737               break;
738
739             case OP_MOVE_FIGURE:
740               Handle_OP_MOVE_FIGURE(u);
741               break;
742
743             case OP_KILL:
744               for (v=user0; v; v=v->next)
745               {
746                 if (v->number == buf[2])
747                   break;
748               }
749               if (v)
750               {
751                 if (v->isbot)
752                 {
753                   if (verbose)
754                     printf("RND_SERVER: client %d (%s) kills bot %d (%s)\n", u->number, u->nick, v->number, v->nick);
755
756                   dropuser(v);
757                   interrupt = 1;
758                   break;
759                 }
760                 else
761                 {
762                   if (verbose)
763                     printf("RND_SERVER: client %d (%s) attempting to kill non-bot %d (%s)\n", u->number, u->nick, v->number, v->nick);
764                 }
765               }
766               break;
767
768             case OP_MODE:
769               mode = buf[2];
770               if (verbose)
771                 printf("RND_SERVER: client %d (%s) sets mode %d (%s)\n", u->number, u->nick, buf[2], buf[2] == 0 ? "normal" : (buf[2] == 1 ? "fun" : "unknown"));
772               broadcast(NULL, 3, 0);
773               break;
774
775             case OP_BOT:
776               if (!u->isbot)
777                 bots++;
778               u->isbot = 1;
779               if (verbose)
780                 printf("RND_SERVER: client %d (%s) declares itself to be a bot\n", u->number, u->nick);
781               break;
782             
783             case OP_LEVEL:
784               level = buf[2];
785               if (verbose)
786                 printf("RND_SERVER: client %d (%s) sets level %d\n", u->number, u->nick, buf[2]);
787               broadcast(NULL, 3, 0);
788               break;
789
790             case OP_LOST:
791               {
792                 struct user *won = NULL;
793
794                 if (verbose)
795                   printf("RND_SERVER: client %d (%s) has lost\n", u->number, u->nick);
796                 u->playing = 0;
797                 broadcast(u, 2, 1);
798                 i = 0;
799                 for (v=user0; v; v=v->next)
800                 {
801                   if (v->nextvictim == u)
802                   {
803                     for (w=NEXT(v); w!=v; w=NEXT(w))
804                     {
805                       if (w->active && w->playing)
806                       {
807                         v->nextvictim = w;
808                         break;
809                       }
810                     }
811                     if (v->nextvictim == u)
812                       v->nextvictim = NULL;
813                   }
814                 }
815                 for (v=user0; v; v=v->next)
816                 {
817                   if (v->playing)
818                   {
819                     i++;
820                     won = v;
821                   }
822                 }
823                 if (i == 1)
824                 {
825                   buf[0] = won->number;
826                   buf[1] = OP_WON;
827                   won->games++;
828                   broadcast(NULL, 2, 0);
829                 }
830                 else if (i == 0)
831                 {
832                   buf[0] = u->number;
833                   buf[1] = OP_WON;
834                   u->games++;
835                   broadcast(NULL, 2, 0);
836                 }
837                 if (i < 2 && clients > 1)
838                   timetoplay = time(NULL) + 4;
839               }
840               break;
841             
842             case OP_ZERO:
843               broadcast(NULL, 2, 0);
844               if (verbose)
845                 printf("RND_SERVER: client %d (%s) resets the game counters\n", u->number, u->nick);
846               for (v=user0; v; v=v->next)
847                 v->games = 0;
848               break;
849
850             case OP_CLEAR:
851             case OP_GROW:
852               broadcast(u, 2, 1);
853               break;
854
855             case OP_MSG:
856               buf[len] = '\0';
857               if (verbose)
858                 printf("RND_SERVER: client %d (%s) sends message: %s\n", u->number, u->nick, &buf[2]);
859               broadcast(u, len, 0);
860               break;
861
862             case OP_LINES:
863               if (len != 3)
864               {
865                 if (verbose)
866                   printf("RND_SERVER: client %d (%s) sends crap for an OP_LINES\n", u->number, u->nick);
867
868                 dropuser(u);
869                 interrupt = 1;
870                 break;
871               }
872               if (u->nextvictim)
873               {
874                 if (verbose)
875                   printf("RND_SERVER: client %d (%s) sends %d %s to client %d (%s)\n", u->number, u->nick, (int)buf[2], buf[2] == 1 ? "line" : "lines", u->nextvictim->number, u->nextvictim->nick);
876                 sendtoone(u->nextvictim, 3);
877                 buf[3] = u->nextvictim->number;
878                 buf[1] = OP_LINESTO;
879                 broadcast(u->nextvictim, 4, 1);
880                 for (v=NEXT(u->nextvictim); v!=u->nextvictim; v=NEXT(v))
881                 {
882                   if (v->active && v != u && v->playing)
883                   {
884                     u->nextvictim = v;
885                     break;
886                   }
887                 }
888               }
889               else if (verbose)
890                 printf("RND_SERVER: client %d (%s) makes %d %s but has no victim\n", u->number, u->nick, (int)buf[2], buf[2] == 1 ? "line" : "lines");
891               break;
892             
893             default:
894               if (verbose)
895                 printf("RND_SERVER: opcode %d from client %d (%s) not understood\n", buf[0], u->number, u->nick);
896           }
897         }
898       }
899
900       if (u && !interrupt)
901         u = u->next;
902     }
903     while (u && !interrupt);
904   }
905 }