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