/* * Copyright (C) 2003 Tim Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include /* so strptime gets picked up */ #define _XOPEN_SOURCE #include #include #include #include #include #include #include #include #include #include "map.h" #include "connections.h" #include "protocol.h" #include "senkenconfig.h" #include "main.h" #include "utils.h" #include "game.h" time_t CurrentGameTime; struct timeval lasttime; /* seconds between moving clock */ struct timeval game_speed; extern game_t *game; /* days to move at once */ #define GAME_TIMEQUANTUM 1 /* * Initialize network stuff so we can accept connections */ static int init_network(int port, int *sock) { struct sockaddr_in sin; char hostname[128]; /* xxx max */ int sockoptval = 1; /* get our hostname */ gethostname(hostname, sizeof(hostname)); /* create a socket */ if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("socket"); exit(1); } /* let socket reuse this address and port */ if( setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(int)) != 0 ) { perror( "dblisten(): setsockopt() returned" ); exit(1); } /* create sockaddr_in */ sin.sin_family=AF_INET; sin.sin_port= htons(port); sin.sin_addr.s_addr = INADDR_ANY; /* bind it */ if (bind(*sock,(const struct sockaddr *) &sin, sizeof(sin)) < 0 ) { perror("bind"); exit(1); } if (listen(*sock, 10) < 0) { perror("listen"); exit(1); } /* set non-blocking */ /*fcntl(*sock, F_SETFL, O_NONBLOCK);*/ printf(_("listening on port %i...\n"),port); return 0; } static void give_time(void) { struct timeval curtime; long diff; long speed; gettimeofday(&curtime, NULL); diff = (curtime.tv_sec - lasttime.tv_sec) * 1000000 + (curtime.tv_usec - lasttime.tv_usec); speed = game_speed.tv_sec * 1000000 + game_speed.tv_usec; if ((game_speed.tv_sec >= 0) && (diff >= speed)) { CurrentGameTime += (GAME_TIMEQUANTUM * SECS_IN_DAY); lasttime = curtime; pass_time(CurrentGameTime, 0); connections_send_to_all("* CURTIME %d\r\n", CurrentGameTime); } } static void set_time(int mon, int day, int year) { struct tm tm; memset(&tm, 0, sizeof(struct tm)); tm.tm_mon = mon; tm.tm_mday = day; tm.tm_year = year - 1900; CurrentGameTime = mktime(&tm); gettimeofday(&lasttime, NULL); } extern void set_time_str(char *str) { struct tm tm; strptime(str,"%m/%d/%Y", &tm); set_time(tm.tm_mon, tm.tm_mday, tm.tm_year + 1900); } static int mainloop(int acceptsock) { fd_set readfds; while (1) { struct timeval timeout; int r; /* add file descriptors to read list */ FD_ZERO(&readfds); FD_SET(acceptsock, &readfds); connections_enumerate(&connection_setfd, &readfds); /* need to reset the timeout each time around for linux */ timeout.tv_sec = 0; timeout.tv_usec = 10000; /* main select loop */ r = select(1000, &readfds, NULL, NULL, &timeout); if (r < 0) { perror("select"); } if ((game) && (game->active)) { give_time(); } if (r == 0) { connections_flush_all(); } /* if there is a new connect to accept */ if (FD_ISSET(acceptsock, &readfds)) { struct sockaddr_in sin; int sinsize = sizeof(sin); int newsock; newsock = accept(acceptsock, (struct sockaddr *)&sin, &sinsize); if (newsock < 0) { perror("accept"); } connections_add(newsock); } connections_enumerate(&connection_checkfd, &readfds); } } int main(int argc, char *argv[]) { int acceptsock; int r; srand(time(NULL)); signal(SIGPIPE,SIG_IGN); r = init_network(5000, &acceptsock); if (r) { printf(_("Error initializing network\n")); exit(1); } connections_setlogging("logfile"); set_time(0, 1, 1995); mainloop(acceptsock); return 0; }