1 
2 /***********************************************************
3 *                      K O U L E S                         *
4 *----------------------------------------------------------*
5 *  C1995 JAHUSOFT                                          *
6 *        Jan Hubicka                                       *
7 *        Dukelskych Bojovniku 1944                         *
8 *        390 03 Tabor                                      *
9 *        Czech Republic                                    *
10 *        Phone: 0041-361-32613                             *
11 *        eMail: hubicka@limax.paru.cas.cz                  *
12 *----------------------------------------------------------*
13 *   Copyright(c)1995,1996 by Jan Hubicka.See README for    *
14 *                    licence details.                      *
15 *----------------------------------------------------------*
16 *  server.c network server routines                        *
17 ***********************************************************/
18 #ifdef AVOID_HPUX_CC_BUG
19 #pragma OPT_LEVEL 1
20 #endif
21 /* Server part of network code..It is bit ugly but - my first network
22    program at all. It use nice and powerfull socklib from xpilot game.
23    Thanks to authors. It use unreiable UDP datagram sockets because
24    stream ones are too slow for as fast game. It needs to transfer packet
25    to every client by every frame= 25*number of clients packets per second.
26    Game packet has folowin format:
27 
28    1 byte header + data. Header is number of function(event).
29 
30    Game packets are buffered and sent in bigger ones every freame.
31    They have following format:
32 
33    2 byte size, Game packet, 2 byte size, Game packet .....4byte number
34    of last reiable packet.
35 
36    I also use special code for reiable packets. (some of events are critical
37    so they must be transfered-as registering of players,changing of game mode,
38    starting new level etc...I use special buffer for them..They are buffered
39    and sent to clients every 5 frames util server will not receive piggyback
40    from client(at the end of normal packet) Reiable packets are transfered as
41    normal game packets using special CREIABLE ans SREIABLE Game function.
42 
43    Logining part of server is not done yet...it hope that all packets
44    are transfered reiably..maybe you will need more tryes to login
45    client...I will make it better later.
46 
47    Code is ugly because koules weren't designed as network game :(
48    But it seems to work very well...I need to improve some thinks
49    before official release..
50 
51    I now trying to minimalize network transfer...it transfers about 1KB
52    to every client per second now..it may work over 9600 serial line but slip
53    adding packet header-40 bytes so it transfer more than 2KB and needs
54    about 15000 baud line :(((
55    I dont know how to make support for slow line and do not slow down
56    unreiable ones yet more...I think there are two 100% different situation
57    serial line-very slow but reiable
58    internet - quite fast(sometimes) but unreiable (sometimes)
59  */
60 #include <stdio.h>
61 #include <sys/time.h>
62 #include <string.h>
63 #include <signal.h>
64 #include <unistd.h>
65 #include <errno.h>
66 #include "sock.h"
67 #include "koules.h"
68 #include "server.h"
69 #include "net.h"
70 #ifdef NETSUPPORT
71 #define  max_connections 5
72 #define STATISTICS
73 #ifdef STATISTICS
74 #define MAXPACKET 12
75 static long     frames = 0, packets = 0, size = 0;
76 static long     ipackets = 0, isize = 0;
77 int             serverstartlevel = 0;
78 int             servergameplan = COOPERATIVE;
79 static long     sizes[MAXPACKET];
80 static long     isizes[MAXPACKET];
81 char            acceled[5];
82 #endif
83 static unsigned char Clientmap[MAXROCKETS];
84 static int      Socket;
85 /*static int      tbreak; */
86 #define BUFFERSIZE 65536
87 static unsigned char buffer[BUFFERSIZE];
88 int             initport = DEFAULTINITPORT;
89 static int      connected;
90 #define WAITTIME 5		/*time for piggybacking in frames(1/25 sec) */
91 unsigned char   ibuffer[BUFFERSIZE];
92 static struct conn
93   {
94     int             socket;	/*socket to client */
95     int             port;	/*port of client */
96     int             version;	/*client's version...not used yet */
97     int             connected;
98     long            magic;	/*magic number */
99     char            hostname[1024];
100     unsigned char   obuffer[BUFFERSIZE];	/*output buffer for unreliable messages */
101     unsigned char   rbuffer[BUFFERSIZE];	/*reliable messages */
102     unsigned char   initmessage[REPLYSIZE];	/*initialization message */
103     int             counter;
104     int             itimeout;	/*timeout for resending initialization packet */
105     int             timeout;
106     int             failed;
107     int             sent;
108     int             opos;	/*possition in output buffer */
109     int             rpos;	/*possition in reliable */
110     int             dispframes;
111     int             sentframes;
112     int             allframes;
113     long            rcount;	/*counter of reiable messages */
114     long            rrcount;	/*counter of reiable messages received from client */
115     long            ircount;	/*counter of reiable messages sent by client */
116     int             ready;	/*is client ready to receive messages? */
117     /*int wpos; *//*want server receive possition informations? */
118   }
119 conn[6]        , *connp;
120 struct s_table
121   {
122     void            (*func) (int client, unsigned char *message, int size);
123   };
124 
125 
126 #define A(c) (*s=c,s++)
127 static char     str[30];
128 static char    *s;
129 void
edisplay(int e,int l,int t)130 edisplay (int e, int l, int t)
131 {				/*Magic routine */
132   A ("(<|]<["[l ? (e >> 4) % 7 : 0]), A ((l ? (t ? "8b8d8|" : ":;:|:8") : "||||||")[(e >> 2) % 6]),
133     A (e > 40 && l ? '=' : "-^"[l ? (e >> 3) % 2 : 0]), A ((l ? (!t ? ")>D)]|(<[|" : ">OQ><(C(P|") : "|"
134 				       "||||||||")[(e >> 1) % 10]), A (' ');
135 }
136 #undef A
137 
138 void
extesions()139 extesions ()
140 {
141   static int      e[5];
142   int             i;
143   if (gamemode != GAME)
144     return;
145   s = str;
146   for (i = 0; i < nrockets; i++)
147     {
148       if (object[i].live)
149 	e[i]++;
150       else
151 	e[i] -= 2;
152       if (e[i] < 0)
153 	e[i] = 0;
154       edisplay (e[i], object[i].live, object[i].thief);
155     }
156   if (nrockets)
157     {
158       *s = 0;
159       printf ("%s\r", str);
160       fflush (stdout);
161     }
162 }
163 void
statistics()164 statistics ()
165 {
166   int             i;
167   if (!packets || !ipackets || !frames)
168     return;
169   printf (" S E R V E R   S T A T I S T I C S\n"
170 	  "==================================\n"
171 	  "output:\n"
172 	  "total packets    :%i\n"
173 	  "total frames     :%i\n"
174 	  "total bytes      :%i\n"
175 	  "bytes per packet :%.2f\n"
176 	  "bytes per frame  :%.2f\n"
177 	  "bytes per second :%.2f\n",
178 	  (int) packets, (int) frames, (int) size, (float) size / packets, (float) size / frames,
179 	  (float) size * 25 / frames);
180   for (i = 0; i < MAXPACKET; i++)
181     printf ("%3i:%3i", (int) i, (int) sizes[i]);
182   printf ("\ninput:\n"
183 	  "total packets    :%i\n"
184 	  "total frames     :%i\n"
185 	  "total bytes      :%i\n"
186 	  "bytes per packet :%.2f\n"
187 	  "bytes per frame  :%.2f\n"
188 	  "bytes per second :%.2f\n",
189 	  (int) ipackets, (int) frames, (int) isize, (float) isize / ipackets, (float) isize / frames,
190 	  (float) isize * 25 / frames);
191 
192   for (i = 0; i < MAXPACKET; i++)
193     printf ("%3i:%3i", (int) i, (int) isizes[i]);
194   printf ("\nTotal bytes transfered:%i\n"
195 	  "Total per second:%.2f\n"
196 	  "Bytes per second over slip line(40 bytes heads):%.2f=%i bps\n",
197 	  (int) (isize + size), (float) (isize + size) * 25 / (frames),
198 	  (float) (isize + size + 40 * (ipackets + packets)) * 25 / frames,
199       (int) ((isize + size + 40 * (ipackets + packets)) * 25 / frames * 8));
200 
201   printf ("\n"
202 	  "=================================\n");
203 }
204 void
sinit(int client,unsigned char * message,int size)205 sinit (int client, unsigned char *message, int size)
206 {
207   GETLONG (message, conn[client].port);
208 #if 0
209   if (SetSocketNonBlocking (conn[client].socket, 0) == -1)
210     {
211       return;
212     }
213   SetTimeout (0, 10 * 1000);
214   if (DgramConnect (conn[client].socket, conn[client].hostname, conn[client].port) == -1)
215     {
216       Quit ("Can't connect to client");
217       return;
218     }
219   GetSocketError (conn[client].socket);
220   SetTimeout (0, 0);
221   if (SetSocketNonBlocking (conn[client].socket, 1) == -1)
222     {
223       return;
224     }
225   conn[client].connected = 1;
226 #endif
227   if (!conn[client].port)
228     {
229       Quit ("client refused connection...strange\n");
230       return;
231     }
232   conn[client].itimeout = 0;
233   printf ("Client at %s connected and initialized!\n", conn[client].hostname);
234 }
235 void
sprint(int client,unsigned char * message,int size)236 sprint (int client, unsigned char *message, int size)
237 {
238   printf ("Client's #%i message:%s\n", client, message);
239 }
240 void
squit(int client,unsigned char * message,int size)241 squit (int client, unsigned char *message, int size)
242 {
243   char            str[400];
244   sprintf (str, "Server received quit message from client %i:", client);
245   strcat (str, (char *) message);
246   Quit (str);
247 }
248 extern int      write_objects (unsigned char *buffer);
249 void
spos(int client,unsigned char * message,int s)250 spos (int client, unsigned char *message, int s)
251 {
252   if (conn[client].ready)
253     {
254       int             x;
255       GETCHAR (message, x);
256       /*conn[client].wpos = 1; */
257       conn[client].dispframes = x * 2;	/*Take some time for transfer next information */
258       conn[client].allframes = 25 * 2;
259       conn[client].sentframes = 0;
260     }
261 }
262 void
sjoystick(int client,unsigned char * message,int s)263 sjoystick (int client, unsigned char *message, int s)
264 {
265   int             p, x;
266   GETCHAR (message + 5, p);
267   controls[p].type = C_JOYSTICK1;
268   GETSHORT (message, x);
269   controls[p].jx = x;
270   GETSHORT (message + 2, x);
271   controls[p].jy = x;
272   GETCHAR (message + 4, controls[p].mask);
273 }
274 void
smouse(int client,unsigned char * message,int s)275 smouse (int client, unsigned char *message, int s)
276 {
277   int             p;
278   GETCHAR (message + 5, p);
279   controls[p].type = C_MOUSE;
280   GETSHORT (message, controls[p].mx);
281   GETSHORT (message + 2, controls[p].my);
282   GETCHAR (message + 4, controls[p].mask);
283 }
284 void
skeys(int client,unsigned char * message,int s)285 skeys (int client, unsigned char *message, int s)
286 {
287   int             p;
288   GETCHAR (message + 1, p);
289   controls[p].type = C_KEYBOARD;
290   GETCHAR (message, controls[p].mask);
291 }
292 void
srot(int client,unsigned char * message,int s)293 srot (int client, unsigned char *message, int s)
294 {
295   int             p;
296   GETCHAR (message + 1, p);
297   controls[p].type = C_RKEYBOARD;
298   GETCHAR (message, controls[p].mask);
299 }
300 void
sready(int client,unsigned char * message,int s)301 sready (int client, unsigned char *message, int s)
302 {
303   conn[client].ready = 1;
304   /*conn[client].wpos = 1; */
305   conn[client].dispframes = 0;	/*Take some time for transfer next information */
306   conn[client].allframes = 0;
307   conn[client].sentframes = 0;
308   /*statistics (); */
309   if (gamemode == PREGAME)
310     {
311       int             i;
312       for (i = 0; i < connected; i++)
313 	if (!conn[client].ready)
314 	  return;
315       gamemode = GAME;
316     }
317 }
318 void
sreg(int client,unsigned char * message,int s)319 sreg (int client, unsigned char *message, int s)
320 {
321   int             n, i;
322   static int      registered = 0;
323   registered++;
324   GETCHAR (message, n)
325     PUTHEAD (CREG);
326   printf ("Client %i trying to register %i players\n", client, n);
327   /*statistics (); */
328   for (i = 0; i < MAXROCKETS; i++)
329     buffer[i + HEADSIZE] = 0;
330   for (i = nrockets; i < nrockets + n && i < MAXROCKETS; i++)
331     {
332       buffer[i + HEADSIZE] = 1;
333       Clientmap[i] = client;
334     }
335   nrockets += n;
336   if (nrockets > MAXROCKETS)
337     nrockets = MAXROCKETS;
338   ssendreliable (client, buffer, HEADSIZE + MAXROCKETS);
339   PUTHEAD (CPLAYERS);
340   PUTCHAR (buffer + 1, nrockets)
341     ssendallreliable (buffer, HEADSIZE + 1);
342   if (registered == connected)
343     {
344       printf ("All clients sucesfully registered. Entering configure mode\n");
345       close (Socket), Socket = -1;
346       PUTHEAD (CMENU2);
347       ssendallreliable (buffer, HEADSIZE);
348     }
349 }
350 void
SEffect(int level,int nos)351 SEffect (int level, int nos)
352 {
353   int             i;
354   printf ("Entering level %i\n", level);
355   /*statistics (); */
356   PUTHEAD (CLEVEL);
357   PUTCHAR (buffer + 1, lastlevel)
358     PUTCHAR (buffer + 2, nos)
359     PUTCHAR (buffer + 3, gameplan)
360     for (i = 0; i < connected; i++)
361     conn[client].ready = 0;
362   ssendallreliable (buffer, HEADSIZE + 3);
363   gamemode = PREGAME;
364 }
365 void
sstart(int client,unsigned char * message,int s)366 sstart (int client, unsigned char *message, int s)
367 {
368   static int      registered = 0;
369   registered++;
370   lastlevel = serverstartlevel;
371   printf ("Client %i registered to game\n", client);
372   /*statistics (); */
373   /*PUTHEAD (CLEVEL);
374      PUTCHAR (buffer+1,lastlevel)
375      PUTCHAR (buffer+2,0)
376      ready[client]=0;
377      ssend ( client,buffer, HEADSIZE+2); */
378   if (registered == connected)
379     {
380       printf ("All clients sucesfully registered. Starting game\n");
381       PUTHEAD (CGAME);
382       ssendallreliable (buffer, HEADSIZE);
383       gamemode = GAME;
384       gameplan = servergameplan;
385       gameplan_init ();
386       init_objects ();
387       gamemode = PREGAME;
388     }
389 }
390 void            sreliable (int i, unsigned char *message, int size);
391 struct s_table  stable[] =
392 {
393   {sprint},
394   {squit},
395   {spos},
396   {sreg},
397   {sstart},
398   {sready},
399   {sjoystick},
400   {smouse},
401   {srot},
402   {skeys},
403   {sreliable},
404   {sinit},
405 };
406 #define error(text) fprintf(stderr,text);
407 void
sreliable(int i,unsigned char * message,int size)408 sreliable (int i, unsigned char *message, int size)
409 {
410   int             pos = 0;
411   while (pos < size)
412     {
413       long            rpos1;
414       int             size;
415       GETLONG ((message + pos), rpos1);
416       if (rpos1 > conn[i].ircount + 1)
417 	{
418 	  printf ("Fatal error in transfering reliable messages!\n"
419 		  "Game may become VERY unstable..please contact author \n");
420 	  return;
421 	}
422       GETSHORT ((message + pos + 4), size);
423       if (rpos1 <= conn[i].ircount)
424 	{
425 	  pos += size;
426 	  continue;
427 	}
428       conn[i].ircount = rpos1;
429       stable[message[pos + 6]].func (i, (message + pos + 7), size - 7);
430       pos += size;
431     }
432 }
433 
434 static void
closeSockets()435 closeSockets ()
436 {
437   int             n;
438   statistics ();
439   SocketClose (Socket);
440   for (n = 0; n < connected; n++)
441     {
442       SocketClose (conn[n].socket);
443     }
444 }
445 
446 void
sflushreliable(int i)447 sflushreliable (int i)
448 {
449   if (conn[i].rpos)
450     {
451       PUTHEAD (CRELIABLE) memcpy (buffer + HEADSIZE, conn[i].rbuffer, conn[i].rpos);
452       ssendbegining (i, buffer, conn[i].rpos + HEADSIZE);
453     }
454 }
455 void
ssendbuffer(int client)456 ssendbuffer (int client)
457 {
458   int             result;
459   GetSocketError (conn[client].socket);
460   if (conn[client].itimeout)
461     {
462       conn[client].itimeout--;
463       if (!conn[client].itimeout)
464 	{
465 	  if ((result = DgramSend (Socket, conn[client].hostname, conn[client].port,
466 				   (char *) conn[client].initmessage, sizeof (conn[client].initmessage))) <= 0)
467 	    {
468 	      if (errno == EWOULDBLOCK || errno == EAGAIN || result >= 0)
469 		{
470 		  GetSocketError (Socket);
471 		  conn[client].itimeout = 1;
472 		}
473 	      else
474 		{
475 		  perror ("Connection error:");
476 		  Quit("Can not send message to client");
477 		}
478 	    }
479 	  else
480 	    conn[client].itimeout = WAITTIME;
481 	}
482       return;
483     }
484   if (conn[client].timeout)
485     {
486       conn[client].timeout--;
487       if (!conn[client].timeout)
488 	{
489 	  sflushreliable (client);
490 	  conn[client].timeout = WAITTIME;
491 	}
492     }
493   if (!conn[client].opos)
494     return;
495   PUTLONG (conn[client].obuffer, conn[client].ircount);
496   /*if (!(rand()%10)) *//*emulate internet..send every 10th packet :))) */
497   conn[client].failed = 0;
498   if ((result = DgramSend (conn[client].socket, conn[client].hostname, conn[client].port,
499 		(char *) conn[client].obuffer, conn[client].opos + 4)) <= 0)
500     {
501       if (errno == EWOULDBLOCK || errno == EAGAIN || result >= 0)
502 	{
503 	  if (conn[client].timeout == WAITTIME)
504 	    conn[client].timeout = 1;
505 	  GetSocketError (conn[client].socket);
506 	  conn[client].failed = 1;
507 	}
508       else
509 	{
510 	  perror ("Socket error");
511 	  Quit ("Server error:can not send message to client ");
512 	}
513     }
514   packets++;
515   size += conn[client].opos;
516   conn[client].opos = 0;
517 }
518 
519 void
ssendbuffers()520 ssendbuffers ()
521 {
522   int             i;
523   for (i = 0; i <
524        connected; i++)
525     ssendbuffer (i);
526 }
527 void
setrrcount(int i,long scount)528 setrrcount (int i, long scount)
529 {
530   int             size, pos = 0, count;
531   if (scount <= conn[i].rrcount)
532     return;			/*Old repeated message */
533   do
534     {
535       GETLONG ((conn[i].rbuffer + pos), count);
536       GETSHORT ((conn[i].rbuffer + pos) + 4, size);
537       pos += size;
538     }
539   while (count < scount);
540   memmove (conn[i].rbuffer, conn[i].rbuffer + pos, conn[i].rpos - pos);
541   conn[i].rpos -= pos;
542   conn[i].rrcount = scount;
543 }
544 void
ssendreliable(int client,unsigned char * message,int size)545 ssendreliable (int client, unsigned char *message, int size)
546 {
547   if (size == 0)
548     return;
549   if (conn[client].rpos + size + 6 > BUFFERSIZE)
550     {
551       Quit ("Connection to client broken too long! Reliable buffer owerfllow\n");
552     }
553 
554   PUTLONG ((conn[client].rbuffer + conn[client].rpos), conn[client].rcount);
555   conn[client].rcount++;
556   PUTSHORT ((conn[client].rbuffer + conn[client].rpos + 4), (size + 6));
557   memcpy (conn[client].rbuffer + conn[client].rpos + 6, message, size);
558   conn[client].rpos += size + 6;
559   sizes[message[0]] += size;
560   conn[client].timeout = 1;
561 }
562 void
ssend(int client,unsigned char * message,int size)563 ssend (int client, unsigned char *message, int size)
564 {
565   if (conn[client].opos + size + 6 > BUFFERSIZE)
566     ssendbuffer (client);
567 
568   PUTSHORT ((conn[client].obuffer + conn[client].opos + 4), size + 2);
569   memcpy (conn[client].obuffer + conn[client].opos + 6, message, size);
570   conn[client].opos += size + 2;
571   sizes[message[0]] += size;
572 
573 }
574 void
ssendbegining(int client,unsigned char * message,int size)575 ssendbegining (int client, unsigned char *message, int size)	/*send at more reliable beggining of packet */
576 {
577   if (conn[client].opos + size + 6 > BUFFERSIZE)
578     ssendbuffer (client);
579 
580   memmove (conn[client].obuffer + size + 6, conn[client].obuffer + 4, conn[client].opos);
581   PUTSHORT ((conn[client].obuffer + 4), size + 2);
582   memcpy (conn[client].obuffer + 6, message, size);
583   conn[client].opos += size + 2;
584   sizes[message[0]] += size;
585 
586 }
587 void
ssendallr(unsigned char * message,int size)588 ssendallr (unsigned char *message, int size)
589 {
590   int             n;
591   for (n = 0; n < connected; n++)
592     {
593       if (conn[client].ready)
594 	ssend (n, message, size);
595     }
596 }
597 void
ssendallreliable(unsigned char * message,int size)598 ssendallreliable (unsigned char *message, int size)
599 {
600   int             n;
601   for (n = 0; n < connected; n++)
602     {
603       ssendreliable (n, message, size);
604     }
605 }
606 void
ssendall(unsigned char * message,int size)607 ssendall (unsigned char *message, int size)
608 {
609   int             n;
610   for (n = 0; n < connected; n++)
611     {
612       ssend (n, message, size);
613     }
614 }
615 void
Quit(char * text)616 Quit (char *text)
617 {
618   static int      quited = 0;
619   static int      n;
620   if (quited)
621     return;
622   quited = 1;
623   PUTHEAD (CQUITS);
624   strcpy ((char *) (buffer + HEADSIZE), text);
625   for (n = 0; n < 5; n++)
626     {				/*repeat quiting messages to make sure that
627 				   all clients received it */
628       ssendall (buffer, strlen (text) + HEADSIZE + 1);
629       ssendbuffers ();
630     }
631   closeSockets ();
632   printf ("Game tarminated.\nReason:%s\n", text);
633   exit (0);
634 }
635 int
PlaySound(int s)636 PlaySound (int s)
637 {
638   PUTHEAD (CSOUND);
639   PUTCHAR ((buffer + HEADSIZE), s);
640   ssendallr (buffer, HEADSIZE + 1);
641   return 0;
642 }
643 void
Explosion(int x,int y,int type,int letter,int n)644 Explosion (int x, int y, int type, int letter, int n)
645 {
646   PUTHEAD (CEXPLOSSION);
647   PUTSHORT ((buffer + HEADSIZE), x);
648   PUTSHORT ((buffer + HEADSIZE + 2), y);
649   PUTCHAR ((buffer + HEADSIZE + 4), type);
650   PUTCHAR ((buffer + HEADSIZE + 5), letter);
651   PUTCHAR ((buffer + HEADSIZE + 6), n);
652   ssendallr (buffer, HEADSIZE + 7);
653 }
654 void
Outro()655 Outro ()
656 {
657   int             i;
658   PUTHEAD (COUTRO);
659   ssendallreliable (buffer, HEADSIZE);
660   for (i = 0; i < connected; i++)
661     conn[client].ready = 0;
662 }
663 void
CreatorsPoints(int radius,int x,int y,int color)664 CreatorsPoints (int radius, int x, int y, int color)
665 {
666   PUTHEAD (CCREATOR);
667   PUTSHORT ((buffer + HEADSIZE), x);
668   PUTSHORT ((buffer + HEADSIZE + 2), y);
669   PUTSHORT ((buffer + HEADSIZE + 4), radius);
670   PUTCHAR ((buffer + HEADSIZE + 6), color);
671   ssendallr (buffer, HEADSIZE + 7);
672 }
673 
674 static int
contact()675 contact ()
676 {
677   int             bytes;
678   int             sock, my_port;
679   int             accept = 1;
680   char           *in_host, version = 1;
681   if (connected >= 6)
682     {
683       printf ("Maximum number of clients reached!\n");
684       return 0;
685     }
686   if ((bytes = DgramReceiveAny (Socket, (char *) buffer, BUFFERSIZE)) <= 3)
687     {
688       if (bytes >= 0
689 	  || errno == EWOULDBLOCK
690 	  || errno == EAGAIN
691 	  || errno == EINTR)
692 	{
693 	  /*
694 	   * This caused some long series of error messages
695 	   * if a player connection crashed violently (SIGKILL, SIGSEGV).
696 	   * error("SocketRead (pack from %s)", DgramLastaddr());
697 	   */
698 	  /*
699 	   * Clear the error condition for the contact socket.
700 	   */
701 	  GetSocketError (Socket);
702 	  return 0;
703 	}
704       /*printf ("******************SERVER CRASH***********************\n"
705          "This port is dangorous-someone attacking me\n"
706          "Try another\nmaybe only internet noise?\n"); */
707       return 0;
708     }
709 /*It is client's connection message? */
710   if (memcmp ("Koules", buffer, 7) || bytes != INITPACKETSIZE)
711     {
712 /*      printf ("****WARNING****WARNING****WARNING****WARNING****\n"
713    "Some saboteur atacked my port!\n"
714    "Transaction can not be completted\n"
715    "Good bye :)\n"); */
716 	return 0;
717     }
718   printf ("Client contacted me!\n");
719   {
720     int             x;
721     GETSHORT (buffer + 8, x);
722     if (x < GAMEWIDTH)
723       accept = 0, printf ("Client does not support %i game width(supports only:%i)\n", x, GAMEWIDTH);
724     GETSHORT (buffer + 10, x);
725     if (x < GAMEHEIGHT)
726       accept = 0, printf ("Client does not support %i game height(supports only:%i)\n", x, GAMEHEIGHT);
727     if (connected >= 5)
728       accept = 0;
729   }
730 /*Is server able to accept it? */
731   in_host = DgramLastaddr ();
732   connp = conn + connected;
733   connp->version = buffer[8];
734   strcpy (connp->hostname, DgramLastaddr ());
735   GETCHAR (buffer + 7, connp->version);
736   /*SetTimeout(1,10000); */
737   GETLONG (buffer + 12, connp->magic);
738   {
739     int             i;
740     for (i = 0; i < connected; i++)
741       {
742 	if (conn[i].magic == connp->magic && !strcmp (conn[i].hostname, connp->hostname))
743 	  return 0;
744 	/* We've received old repeated message */
745       }
746   }
747   connp->rcount = 1;
748   if ((sock = CreateDgramSocket (0)) == -1)
749     {
750       error ("Cannot create datagram socket ");
751       connp--;
752       return 0;
753     }
754 
755   /*if (sock >= MAX_SELECT_FD)
756      {
757      errno = 0;
758      error ("Socket filedescriptor too big");
759      close (sock);
760      connp--;
761      return 0;
762      } */
763   if ((my_port = GetPortNum (sock)) == 0)
764     {
765       error ("Cannot get port from socket");
766       close (sock);
767       connp--;
768       return 0;
769     }
770   if (!accept)
771     my_port = 0;
772   if (SetSocketNonBlocking (sock, 1) == -1)
773     {
774       error ("Cannot make client socket non-blocking");
775       close (sock);
776       connp--;
777       return 0;
778     }
779   if (SetSocketReceiveBufferSize (sock, NETBUFFER) == -1)
780     {
781       printf ("Cannot set receive buffer size to %d", NETBUFFER);
782       connp--;
783       close (sock);
784       return 0;
785     }
786   if (SetSocketSendBufferSize (sock, NETBUFFER) == -1)
787     {
788       printf ("Cannot set send buffer size to %d", NETBUFFER);
789       connp--;
790       close (sock);
791       return 0;
792     }
793   connp->socket = sock;
794   connp->version = version;
795   connp->port = DgramLastport ();
796   connp->itimeout = WAITTIME;
797   printf ("Client #%i:\n", connected);
798   printf ("port:%i\n", my_port);
799   printf ("address:%s\n", connp->hostname);
800   printf ("lastport:%i\n", connp->port);
801   PUTLONG (connp->initmessage, my_port);
802   PUTSHORT ((connp->initmessage) + 4, GAMEWIDTH);
803   PUTSHORT ((connp->initmessage) + 6, GAMEHEIGHT);
804   GetSocketError(sock);
805   if (DgramSend (Socket , DgramLastaddr (), DgramLastport (),
806 	    (char *) connp->initmessage, sizeof (connp->initmessage)) == -1)
807     {
808       if (errno != EWOULDBLOCK && errno != EAGAIN)
809 	{
810 	  error ("Cant contact client\n");
811 	  connp--;
812 	  close (sock);
813 	  return 0;
814 	}
815       GetSocketError (sock);
816     }
817   if (!accept)
818     {
819       printf ("client not accepted. sorry\n");
820       connp--;
821       close (sock);
822       return 0;
823     }
824   connected++;
825   return 1;
826 }
827 static void
client_message(struct conn * c)828 client_message (struct conn *c)
829 {
830   long            scount;
831   int             bytes, pos = 4;
832   GetSocketError (c->socket);
833   if ((bytes = (c->connected ? DgramReceiveConnected (c->socket, (char *) ibuffer, BUFFERSIZE)
834 		: DgramReceiveAny (c->socket, (char *) ibuffer, BUFFERSIZE))
835       ) <= 4)
836     {
837       if (errno == EWOULDBLOCK || errno == EAGAIN || bytes >= 0)
838 	{
839 	  GetSocketError (c->socket);
840 	  return;
841 	}
842       perror ("Socket error");
843       GetSocketError (c->socket);
844       Quit ("Connection to client broken-exiting game\n");
845     }
846   isize += bytes;
847   GETLONG (ibuffer, scount);
848   setrrcount ((int) (c - conn), scount);
849   ipackets++;
850   while (pos + 2 < bytes)
851     {
852       int             size;
853       GETSHORT (ibuffer + pos, size);
854       if (pos + size <= bytes)
855 	{
856 	  isizes[ibuffer[pos + 2]]++;
857 	  stable[ibuffer[pos + 2]].func ((int) (c - conn), (ibuffer + pos + 3), size - 3);
858 	}
859       pos += size;
860     }
861 }
862 void
wposs()863 wposs ()
864 {
865   int             size;
866   int             i;
867   PUTHEAD (CPOS);
868   size = write_objects (buffer + 1);
869   for (i = 0; i < connected; i++)
870     {
871       conn[client].sent = 0;
872       if ( /*conn[client].wpos && */ (conn[client].dispframes >
873 			 conn[client].sentframes && conn[client].ready) || (
874 				  conn[client].failed && conn[client].sent))
875 	{
876 	  conn[client].counter += conn[client].dispframes;
877 	  if ((conn[client].counter > conn[client].allframes) ||
878 	      (conn[client].failed && conn[client].sent))
879 	    {
880 	      conn[client].sent = 1;
881 	      conn[client].sentframes++;
882 	      conn[client].counter -= conn[client].allframes;
883 	      ssend (i, buffer, size + HEADSIZE);
884 	    }
885 	}
886     }
887   for (i = 0; i < 5; i++)
888     acceled[i] = 0;
889 }
890 
891 static void
exitcall()892 exitcall ()
893 {
894   Quit ("Server called exit!");
895 }
896 static void
interrupt(int i)897 interrupt (int i)
898 {
899   char            s[256];
900   sprintf (s, "Server received interrupt %i\n", i);
901   Quit (s);
902 }
903 extern void     server_loop2 (void);
904 
905 void
server_loop()906 server_loop ()
907 {
908   long            VfTime = 0;
909   long            VendSleep = 0;
910   struct timeval  VlastClk;
911   struct timeval  VnewClk;
912   struct conn    *c;
913   int             ecounter = 0;
914   int             wait = 0;
915   server = 1;
916 
917   gettimeofday (&VlastClk, NULL);
918   gettimeofday (&VnewClk, NULL);
919   VendSleep = VlastClk.tv_usec;
920   VfTime = 1000000 / 25;
921   SetTimeout (0, 10 * 1000);
922   printf ("Awaiting clients....\n");
923   while (!SocketReadable (Socket) || !contact ())
924     SetTimeout (0, 10 * 1000);
925   SetTimeout (0, 0);
926   printf ("First client connected-starting setup part of game\n");
927   atexit (exitcall);
928   signal (SIGHUP, interrupt);
929   signal (SIGINT, interrupt);
930   signal (SIGTRAP, interrupt);
931   signal (SIGABRT, interrupt);
932   signal (SIGSEGV, interrupt);
933   signal (SIGQUIT, interrupt);
934   signal (SIGFPE, interrupt);
935   signal (SIGTERM, interrupt);
936   signal (SIGBUS, interrupt);
937   signal (SIGIOT, interrupt);
938   signal (SIGILL, interrupt);
939   nrockets = 0;
940   gamemode = MENU;
941   while (1)
942     {
943       ecounter--;
944       if (ecounter < 0)
945 	{
946 	  ecounter = 15, extesions ();
947 	}
948       frames++;
949       SetTimeout (0, 0);
950       if (Socket != -1)
951 	while (SocketReadable (Socket))
952 	  {
953 	    contact ();
954 	  }
955       for (c = &conn[0]; c <= connp; c++)
956 	{
957 	  while (SocketReadable (c->socket))
958 	    {
959 	      client_message (c);
960 	    }
961 	}
962       gettimeofday (&VnewClk, NULL);
963       if (VnewClk.tv_usec < VendSleep)
964 	VendSleep -= 1000000;
965       wait = (VfTime - VnewClk.tv_usec + VendSleep);
966       /* if (tbreak) */
967       wait = VfTime /*, tbreak = 0 */ ;
968       tbreak = 0;
969       if (gamemode != PREGAME)
970 	server_loop2 ();
971       wposs ();
972       ssendbuffers ();
973       do
974 	{
975 	  gettimeofday (&VnewClk, NULL);
976 	  if (VnewClk.tv_usec < VendSleep)
977 	    VendSleep -= 1000000;
978 	  wait = (VfTime - VnewClk.tv_usec + VendSleep);
979 	  if (tbreak)
980 	    wait = VfTime;
981 	  if (wait > 0)
982 	    usleep (wait);
983 	}
984       while (wait > 10 && !tbreak);
985       VendSleep = VnewClk.tv_usec + wait;
986       gettimeofday (&VlastClk, NULL);
987       if (tbreak)
988 	VendSleep = VlastClk.tv_usec;
989       tbreak = 0;
990 
991     }
992 }
993 void
init_server(void)994 init_server (void)
995 {
996   if ((Socket = CreateDgramSocket (initport)) == -1)
997     {
998       error ("Could not create Dgram socket");
999       exit (-1);
1000     }
1001   printf ("Initializing koules network server at port: %i\n", initport);
1002   if (SetSocketNonBlocking (Socket, 1) == -1)
1003     {
1004       error ("Can't make contact socket non-blocking");
1005       exit (-1);
1006     }
1007 
1008   SetTimeout (0, 0);
1009 }
1010 #endif
1011