rnd-19981016-1
[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 is_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 (!is_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 client_nr = u->number;
274   int nr_wanted = buf[2];
275   int nr_is_free = 1;
276
277   if (verbose)
278     printf("RND_SERVER: client %d (%s) wants to switch to # %d\n",
279            u->number, u->nick, nr_wanted);
280
281   for (v=user0; v; v=v->next)
282   {
283     if (v->number == nr_wanted)
284     {
285       nr_is_free = 0;
286       break;
287     }
288   }
289
290   if (verbose)
291   {
292     if (nr_is_free)
293       printf("RND_SERVER: client %d (%s) switches to # %d\n",
294              u->number, u->nick, nr_wanted);
295     else if (u->number == nr_wanted)
296       printf("RND_SERVER: client %d (%s) still has # %d\n",
297              u->number, u->nick, nr_wanted);
298     else
299       printf("RND_SERVER: client %d (%s) cannot switch (client %d still exists)\n",
300              u->number, u->nick, nr_wanted);
301   }
302
303   if (nr_is_free)
304     u->number = nr_wanted;
305
306   buf[0] = client_nr;
307   buf[1] = OP_NUMBER_WANTED;
308   buf[2] = nr_wanted;
309   buf[3] = u->number;
310
311   /*
312   sendtoone(u, 4);
313   */
314
315   broadcast(NULL, 4, 0);
316 }
317
318 static void Handle_OP_NICKNAME(struct user *u, unsigned int len)
319 {
320   struct user *v;
321   int i;
322
323   if (len>16)
324     len=16;
325   memcpy(u->nick, &buf[2], len-2);
326   u->nick[len-2] = 0;
327   for (i=0; i<len-2; i++)
328   {
329     if (u->nick[i] < ' ' || 
330         (u->nick[i] > 0x7e && u->nick[i] <= 0xa0))
331     {
332       u->nick[i] = 0;
333       break;
334     }
335   }
336
337   if (!u->introduced)
338   {
339     buf[0] = u->number;
340     buf[1] = OP_PLAYER_CONNECTED;
341     broadcast(u, 2, 0);
342   }
343               
344   if (verbose)
345     printf("RND_SERVER: client %d calls itself \"%s\"\n", u->number, u->nick);
346   buf[1] = OP_NICKNAME;
347   broadcast(u, len, 0);
348
349   if (!u->introduced)
350   {
351     for (v=user0; v; v=v->next)
352     {
353       if (v != u && v->introduced)
354       {
355         buf[0] = v->number;
356         buf[1] = OP_PLAYER_CONNECTED;
357         buf[2] = (v->games >> 8);
358         buf[3] = (v->games & 0xff);
359         sendtoone(u, 4);
360         buf[1] = OP_NICKNAME;
361         memcpy(&buf[2], v->nick, 14);
362         sendtoone(u, 2+strlen(v->nick));
363       }
364     }
365     if (level != 5)
366     {
367       buf[0] = 0;
368       buf[1] = OP_LEVEL;
369       buf[2] = level;
370       sendtoone(u, 3);
371     }
372     if (mode >= 0)
373     {
374       buf[1] = OP_MODE;
375       buf[2] = mode;
376       sendtoone(u, 3);
377     }
378   }
379
380   u->introduced = 1;
381 }
382
383 static void Handle_OP_START_PLAYING(struct user *u)
384 {
385   struct user *v, *w;
386
387   if (verbose)
388     printf("RND_SERVER: client %d (%s) starts game [level %d from levedir %d (%s)]\n",
389            u->number, u->nick,
390            (buf[2] << 8) + buf[3],
391            (buf[4] << 8) + buf[5],
392            &buf[6]);
393   timetoplay = 0;
394
395   for (w=user0; w; w=w->next)
396   {
397     if (w->introduced)
398     {
399       w->active = 1;
400       w->playing = 1;
401       w->lines = 0;
402       w->nextvictim = NULL;
403       for (v=NEXT(w); v!=w; v=NEXT(v))
404       {
405         if (v->introduced)
406         {
407           w->nextvictim = v;
408           break;
409         }
410       }
411     }
412   }
413
414   /*
415   if (paused)
416   {
417     paused = 0;
418     buf[1] = OP_CONT;
419     broadcast(NULL, 2, 0);
420   }
421   buf[1] = OP_START_PLAYING;
422   broadcast(NULL, 2, 0);
423   */
424
425   /* reset frame counter */
426   frame_counter = 0;
427
428   /* reset player actions */
429   for (v=user0; v; v=v->next)
430   {
431     v->action = 0;
432     v->action_received = 0;
433   }
434
435   broadcast(NULL, 10 + strlen(&buf[10])+1, 0);
436 }
437
438 static void Handle_OP_PAUSE_PLAYING(struct user *u)
439 {
440   if (verbose)
441     printf("RND_SERVER: client %d (%s) pauses game\n", u->number, u->nick);
442   broadcast(NULL, 2, 0);
443   paused = 1;
444 }
445
446 static void Handle_OP_CONTINUE_PLAYING(struct user *u)
447 {
448   if (verbose)
449     printf("RND_SERVER: client %d (%s) continues game\n", u->number, u->nick);
450   broadcast(NULL, 2, 0);
451   paused = 0;
452 }
453
454 static void Handle_OP_STOP_PLAYING(struct user *u)
455 {
456   if (verbose)
457     printf("RND_SERVER: client %d (%s) stops game\n", u->number, u->nick);
458   broadcast(NULL, 2, 0);
459 }
460
461 static void Handle_OP_MOVE_FIGURE(struct user *u)
462 {
463   struct user *v;
464   int last_client_nr = 0;
465   int i;
466
467   /* store player action */
468   for (v=user0; v; v=v->next)
469   {
470     if (v->number == u->number)
471     {
472       v->action = buf[2];
473       v->action_received = 1;
474     }
475   }
476
477   /* check if server received action from each player */
478   for (v=user0; v; v=v->next)
479   {
480     if (!v->action_received)
481       return;
482
483     if (v->number > last_client_nr)
484       last_client_nr = v->number;
485   }
486
487   /* initialize all player actions to zero */
488   for (i=0; i<last_client_nr; i++)
489     buf[6 + i] = 0;
490
491   /* broadcast actions of all players to all players */
492   for (v=user0; v; v=v->next)
493   {
494     buf[6 + v->number-1] = v->action;
495     v->action = 0;
496     v->action_received = 0;
497   }
498
499   buf[2] = (unsigned char)((frame_counter >> 24) & 0xff);
500   buf[3] = (unsigned char)((frame_counter >> 16) & 0xff);
501   buf[4] = (unsigned char)((frame_counter >>  8) & 0xff);
502   buf[5] = (unsigned char)((frame_counter >>  0) & 0xff);
503
504   broadcast(NULL, 6 + last_client_nr, 0);
505
506   frame_counter++;
507
508   /*
509     if (verbose)
510     printf("RND_SERVER: frame %d: client %d (%s) moves player [0x%02x]\n",
511     frame_counter,
512     u->number, u->nick, buf[2]);
513   */
514 }
515
516 void NetworkServer(int port, int serveronly)
517 {
518   int i, sl, on;
519   struct user *u, *v, *w;
520   int mfd;
521   int r; 
522   unsigned int len;
523   struct protoent *tcpproto;
524   struct timeval tv;
525   int is_daemon = 0;
526
527 #ifndef NeXT
528   struct sigaction sact;
529 #endif
530
531   if (port == 0)
532     port = DEFAULTPORT;
533
534   if (!serveronly)
535     onceonly = 1;
536
537   if ((tcpproto = getprotobyname("tcp")) != NULL)
538     tcp = tcpproto->p_proto;
539
540 #ifdef NeXT
541   signal(SIGPIPE, SIG_IGN);
542 #else
543   sact.sa_handler = SIG_IGN;
544   sigemptyset(&sact.sa_mask);
545   sact.sa_flags = 0;
546   sigaction(SIGPIPE, &sact, NULL);
547 #endif
548
549
550   lfd = socket(PF_INET, SOCK_STREAM, 0);
551   saddr.sin_family = AF_INET;
552   saddr.sin_addr.s_addr = htonl(INADDR_ANY);
553   saddr.sin_port = htons(port);
554
555   if (lfd < 0)
556     syserr("socket");
557   on = 1;
558
559   setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int));
560   if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
561     syserr("bind");
562
563   listen(lfd, 5);
564
565   if (is_daemon)
566   {
567     /* become a daemon, breaking all ties with the controlling terminal */
568     verbose = 0;
569     for (i=0; i<255; i++)
570     {
571       if (i != lfd)
572         close(i);
573     }
574
575     if (fork())
576       exit(0);
577     setsid();
578     if (fork())
579       exit(0);
580     chdir("/");
581
582     /* open a fake stdin, stdout, stderr, just in case */
583     open("/dev/null", O_RDONLY);
584     open("/dev/null", O_WRONLY);
585     open("/dev/null", O_WRONLY);
586   }
587
588   if (verbose)
589   {
590     printf("rocksndiamonds network server: started up, listening on port %d\n",
591            port);
592     printf("rocksndiamonds network server: using protocol version %d.%d.%d\n",
593            PROT_VERS_1, PROT_VERS_2, PROT_VERS_3);
594   }
595
596   while(1)
597   {
598     interrupt = 0;
599
600     /*
601     if (timetoplay && time(NULL) >= timetoplay)
602     {
603       buf[0] = 0;
604       do_play();
605       if (verbose)
606         printf("RND_SERVER: everyone lost... restarting game\n");
607       timetoplay = 0;
608     }
609     */
610
611     for (u=user0; u; u=u->next)
612       flushuser(u);
613
614     FD_ZERO(&fds);
615     mfd = lfd;
616     u = user0;
617     while (u)
618     {
619       FD_SET(u->fd, &fds);
620       if (u->fd > mfd)
621         mfd = u->fd;
622       u = u->next;
623     }
624     FD_SET(lfd, &fds);
625     tv.tv_sec = 0;
626     tv.tv_usec = 500000;
627     if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
628       if (errno != EINTR)
629         syserr("select");
630       else continue;
631     
632     if (sl < 0)
633       continue;
634
635     if (clients > 0 && clients == bots)
636     {
637       if (verbose)
638         printf("RND_SERVER: only bots left... dropping all bots\n");
639       while (user0)
640         dropuser(user0);
641       continue;
642     }
643     
644     if (sl == 0)
645       continue;
646
647     if (FD_ISSET(lfd, &fds))
648     {
649       int newfd, slen;
650
651       slen = sizeof(saddr);
652       newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
653       if (newfd < 0)
654       {
655         if (errno != EINTR)
656           syserr("accept");
657       }
658       else
659       {
660         if (tcp != -1)
661         {
662           on = 1;
663           setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
664         }
665         new_connect(newfd);
666       }
667       continue;
668     }
669
670     u = user0;
671
672     do
673     {
674       if (FD_ISSET(u->fd, &fds))
675       {
676         r = read(u->fd, u->readbuf + u->nread, MAX_BUFFER_SIZE - u->nread);
677         if (r <= 0)
678         {
679           if (verbose)
680             printf("RND_SERVER: EOF from client %d (%s)\n", u->number, u->nick);
681           dropuser(u);
682           interrupt = 1;
683           break;
684         }
685         u->nread += r;
686         while (u->nread >= 4 && u->nread >= 4 + u->readbuf[3])
687         {
688           len = u->readbuf[3];
689           if (u->readbuf[0] || u->readbuf[1] || u->readbuf[2])
690           {
691             if (verbose)
692               printf("RND_SERVER: crap from client %d (%s)\n", u->number, u->nick);
693             write(u->fd, "\033]50;kanji24\007\033#8\033(0", 19);
694             dropuser(u);
695             interrupt = 1;
696             break;
697           }
698           memcpy(buf, &u->readbuf[4], len);
699           u->nread -= 4 + len;
700           copydown(u->readbuf, u->readbuf + 4 + len, u->nread);
701
702           buf[0] = u->number;
703           if (!u->introduced && buf[1] != OP_NICKNAME)
704           {
705             if (verbose)
706               printf("RND_SERVER: !(client %d)->introduced && buf[1]==%d (expected OP_NICKNAME)\n", buf[0], buf[1]);
707
708             dropuser(u);
709             interrupt = 1;
710             break;
711           }
712
713           switch(buf[1])
714           {
715             case OP_NICKNAME:
716               Handle_OP_NICKNAME(u, len);
717               break;
718
719             case OP_PROTOCOL_VERSION:
720               Handle_OP_PROTOCOL_VERSION(u, len);
721               break;
722
723             case OP_NUMBER_WANTED:
724               Handle_OP_NUMBER_WANTED(u);
725               break;
726
727             case OP_START_PLAYING:
728               Handle_OP_START_PLAYING(u);
729               break;
730
731             case OP_PAUSE_PLAYING:
732               Handle_OP_PAUSE_PLAYING(u);
733               break;
734
735             case OP_CONTINUE_PLAYING:
736               Handle_OP_CONTINUE_PLAYING(u);
737               break;
738
739             case OP_STOP_PLAYING:
740               Handle_OP_STOP_PLAYING(u);
741               break;
742
743             case OP_MOVE_FIGURE:
744               Handle_OP_MOVE_FIGURE(u);
745               break;
746
747             case OP_KILL:
748               for (v=user0; v; v=v->next)
749               {
750                 if (v->number == buf[2])
751                   break;
752               }
753               if (v)
754               {
755                 if (v->isbot)
756                 {
757                   if (verbose)
758                     printf("RND_SERVER: client %d (%s) kills bot %d (%s)\n", u->number, u->nick, v->number, v->nick);
759
760                   dropuser(v);
761                   interrupt = 1;
762                   break;
763                 }
764                 else
765                 {
766                   if (verbose)
767                     printf("RND_SERVER: client %d (%s) attempting to kill non-bot %d (%s)\n", u->number, u->nick, v->number, v->nick);
768                 }
769               }
770               break;
771
772             case OP_MODE:
773               mode = buf[2];
774               if (verbose)
775                 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"));
776               broadcast(NULL, 3, 0);
777               break;
778
779             case OP_BOT:
780               if (!u->isbot)
781                 bots++;
782               u->isbot = 1;
783               if (verbose)
784                 printf("RND_SERVER: client %d (%s) declares itself to be a bot\n", u->number, u->nick);
785               break;
786             
787             case OP_LEVEL:
788               level = buf[2];
789               if (verbose)
790                 printf("RND_SERVER: client %d (%s) sets level %d\n", u->number, u->nick, buf[2]);
791               broadcast(NULL, 3, 0);
792               break;
793
794             case OP_LOST:
795               {
796                 struct user *won = NULL;
797
798                 if (verbose)
799                   printf("RND_SERVER: client %d (%s) has lost\n", u->number, u->nick);
800                 u->playing = 0;
801                 broadcast(u, 2, 1);
802                 i = 0;
803                 for (v=user0; v; v=v->next)
804                 {
805                   if (v->nextvictim == u)
806                   {
807                     for (w=NEXT(v); w!=v; w=NEXT(w))
808                     {
809                       if (w->active && w->playing)
810                       {
811                         v->nextvictim = w;
812                         break;
813                       }
814                     }
815                     if (v->nextvictim == u)
816                       v->nextvictim = NULL;
817                   }
818                 }
819                 for (v=user0; v; v=v->next)
820                 {
821                   if (v->playing)
822                   {
823                     i++;
824                     won = v;
825                   }
826                 }
827                 if (i == 1)
828                 {
829                   buf[0] = won->number;
830                   buf[1] = OP_WON;
831                   won->games++;
832                   broadcast(NULL, 2, 0);
833                 }
834                 else if (i == 0)
835                 {
836                   buf[0] = u->number;
837                   buf[1] = OP_WON;
838                   u->games++;
839                   broadcast(NULL, 2, 0);
840                 }
841                 if (i < 2 && clients > 1)
842                   timetoplay = time(NULL) + 4;
843               }
844               break;
845             
846             case OP_ZERO:
847               broadcast(NULL, 2, 0);
848               if (verbose)
849                 printf("RND_SERVER: client %d (%s) resets the game counters\n", u->number, u->nick);
850               for (v=user0; v; v=v->next)
851                 v->games = 0;
852               break;
853
854             case OP_CLEAR:
855             case OP_GROW:
856               broadcast(u, 2, 1);
857               break;
858
859             case OP_MSG:
860               buf[len] = '\0';
861               if (verbose)
862                 printf("RND_SERVER: client %d (%s) sends message: %s\n", u->number, u->nick, &buf[2]);
863               broadcast(u, len, 0);
864               break;
865
866             case OP_LINES:
867               if (len != 3)
868               {
869                 if (verbose)
870                   printf("RND_SERVER: client %d (%s) sends crap for an OP_LINES\n", u->number, u->nick);
871
872                 dropuser(u);
873                 interrupt = 1;
874                 break;
875               }
876               if (u->nextvictim)
877               {
878                 if (verbose)
879                   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);
880                 sendtoone(u->nextvictim, 3);
881                 buf[3] = u->nextvictim->number;
882                 buf[1] = OP_LINESTO;
883                 broadcast(u->nextvictim, 4, 1);
884                 for (v=NEXT(u->nextvictim); v!=u->nextvictim; v=NEXT(v))
885                 {
886                   if (v->active && v != u && v->playing)
887                   {
888                     u->nextvictim = v;
889                     break;
890                   }
891                 }
892               }
893               else if (verbose)
894                 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");
895               break;
896             
897             default:
898               if (verbose)
899                 printf("RND_SERVER: opcode %d from client %d (%s) not understood\n", buf[0], u->number, u->nick);
900           }
901         }
902       }
903
904       if (u && !interrupt)
905         u = u->next;
906     }
907     while (u && !interrupt);
908   }
909 }