/* $Id: input.c,v 1.1 2005/03/21 05:23:43 jerub Exp $ */ #include "copyright.h" #include #include #include #ifdef SCO #include #else #include #endif #include #include #include #include #include #include #include "defs.h" #include INC_SYS_SELECT #include "struct.h" #include "data.h" #include "proto.h" #include "sigpipe.h" #include "packets.h" #include "slotmaint.h" #define GHOSTTIME (ghostbust_timer * 1000000 / UPDATE) /* 30 secs */ static int sendflag=0; static int do_update =1; extern int living; static void setflag() { if (!living) return; if (do_update) intrupt(); else sendflag=1; if (me->p_updates > delay) { me->p_flags &= ~(PFWAR); } if (me->p_updates > rdelay) { me->p_flags &= ~(PFREFITTING); } #ifdef PING /* this will ghostbust a player if the number of missing pings from the client exceeds the ghostbust interval */ if (ping_allow_ghostbust && me->p_status == PALIVE && ping_ghostbust > ping_ghostbust_interval) { /* ghostbusted */ me->p_ghostbuster = GHOSTTIME; ping_ghostbust = 0; ERROR(2,("%s: ghostbusted by ping loss\n", me->p_mapchars)); fflush(stderr); } #endif /*PING*/ } static void gamedown(why) { struct badversion_spacket packet; memset(&packet, 0, sizeof(struct badversion_spacket)); packet.type = SP_BADVERSION; packet.why = why; sendClientPacket(&packet); flushSockBuf(); } static void panic(int why) { gamedown(why); freeslot(me); exit(0); } void input(void) { fd_set readfds; static struct timeval poll = {2, 0}; int rv, afd, nfds; sigpipe_create(); sigpipe_assign(SIGALRM); afd = sigpipe_fd(); /* Idea: read from client often, send to client not so often */ while (living) { if (isClientDead()) { freeslot(me); exit(0); } if (!(status -> gameup & GU_GAMEOK)) panic(BADVERSION_DOWN); if (me->p_disconnect) panic(me->p_disconnect); /* wait for activity on network socket or next daemon update */ while (1) { FD_ZERO(&readfds); nfds = 0; FD_SET(afd, &readfds); if (nfds < afd) nfds = afd; FD_SET(sock, &readfds); if (nfds < sock) nfds = sock; if (udpSock >= 0) { FD_SET(udpSock, &readfds); if (nfds < udpSock) nfds = udpSock; } poll.tv_sec = 5; poll.tv_usec = 0; rv = select(nfds+1, &readfds, 0, 0, &poll); if (rv > 0) break; if (rv == 0) { panic(BADVERSION_SILENCE); /* daemon timeout */ } if (errno == EINTR) continue; perror("select"); panic(BADVERSION_SELECT); } /* if daemon signalled us, perform the update only */ if (FD_ISSET(afd, &readfds)) { if (sigpipe_read() == SIGALRM) setflag(); continue; } /* otherwise handle input from client */ do_update = 0; #ifdef PING /* reset this here also */ ping_ghostbust = 0; #endif if (me->p_updates > delay) { me->p_flags &= ~(PFWAR); } if (me->p_updates > rdelay) { me->p_flags &= ~(PFREFITTING); } readFromClient(); me->p_ghostbuster = 0; if (sendflag) { intrupt(); sendflag=0; } do_update = 1; } sigpipe_suspend(SIGALRM); sigpipe_close(); }