home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / spiele / FreeCiv / src / freeciv-1.7.0 / server / sernet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  6.3 KB  |  258 lines

  1. /********************************************************************** 
  2.  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2, or (at your option)
  6.    any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12. ***********************************************************************/
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15.  
  16. #include <sys/signal.h>
  17. #include <sys/types.h>
  18. #include <time.h>
  19. #include <sys/time.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <pwd.h>
  23. #include <string.h>
  24.  
  25. #if defined(AIX) || defined(__EMX__)
  26. #include <sys/select.h>
  27. #endif
  28.  
  29. #include <signal.h>
  30.  
  31. #include <sys/socket.h>
  32. #include <netdb.h>
  33. #include <sys/uio.h>
  34. #include <netinet/in.h>
  35. #include <arpa/inet.h>
  36.  
  37. #include <log.h>
  38. #include <sernet.h>
  39. #include <shared.h>
  40. #include <civserver.h>
  41. #include <packets.h>
  42.  
  43. #define MY_FD_ZERO(p) memset((void *)(p), 0, sizeof(*(p)))
  44.  
  45. struct connection connections[MAX_CONNECTIONS];
  46. int no_active_connections;
  47. int sock;
  48. extern int errno;
  49. extern int port;
  50. extern int force_end_of_sniff;
  51.  
  52. extern enum server_states server_state;
  53.  
  54.  
  55.  
  56. /*****************************************************************************/
  57. void close_connection(struct connection *pconn)
  58. {
  59.   close(pconn->sock);
  60.   pconn->used=0;
  61. }
  62.  
  63. /*****************************************************************************/
  64. void close_connections_and_socket(void)
  65. {
  66.   int i;
  67.   for(i=0; i<MAX_CONNECTIONS; i++)
  68.     if(connections[i].used) {
  69.       close(connections[i].sock);
  70.       connections[i].used=0;
  71.       close(sock);
  72.     }
  73. }
  74.  
  75. /*****************************************************************************/
  76. int sniff_packets(void)
  77. {
  78.   int i;
  79.   int max_desc;
  80.   fd_set readfs;
  81.   struct timeval tv;
  82.   static time_t time_at_turn_end;
  83.   static int year;
  84.   
  85.   if(year!=game.year) {
  86.     time_at_turn_end = time(NULL) + game.timeout;
  87.     year=game.year;
  88.   }
  89.   
  90.   while(1) {
  91.     if(force_end_of_sniff) {
  92.       force_end_of_sniff=0;
  93.       return 2;
  94.     }
  95.     
  96.     tv.tv_sec=1; tv.tv_usec=0;
  97.     
  98.     MY_FD_ZERO(&readfs);
  99.     FD_SET(0, &readfs);    
  100.     FD_SET(sock, &readfs);
  101.     max_desc=sock;
  102.     
  103.     for(i=0; i<MAX_CONNECTIONS; i++) {
  104.       if(connections[i].used) {
  105.     FD_SET(connections[i].sock, &readfs);
  106.       }
  107.       max_desc=MAX(connections[i].sock, max_desc);
  108.     }
  109.     
  110.     if(select(max_desc+1, &readfs, NULL, NULL, &tv)==0) { /* timeout */
  111.       send_server_info_to_metaserver(0);
  112.       if(game.timeout && time(NULL)>time_at_turn_end) {
  113.     return 0;
  114.       }
  115.       continue;
  116.     }
  117.   
  118.     if(FD_ISSET(sock, &readfs)) {         /* new players connects */
  119.       log(LOG_DEBUG, "got new connection");
  120.       if(server_accept_connection(sock)==-1)
  121.     log(LOG_NORMAL, "failed accepting connection");
  122.     }
  123.     else if(FD_ISSET(0, &readfs)) {    /* input from server operator */
  124.       int didget;
  125.       char buf[BUF_SIZE+1];
  126.       
  127.       if((didget=read(0, buf, BUF_SIZE))==-1) {
  128.     log(LOG_FATAL, "read from stdin failed");
  129.     exit(1);
  130.       }
  131.       *(buf+didget)='\0';
  132.       handle_stdin_input(buf);
  133.     }
  134.     else {                             /* input from a player */
  135.       for(i=0; i<MAX_CONNECTIONS; i++)
  136.     if(connections[i].used && FD_ISSET(connections[i].sock, &readfs)) {
  137.       if(read_socket_data(connections[i].sock, 
  138.                   &connections[i].buffer)>0) {
  139.         char *packet;
  140.         int type;
  141.         while((packet=get_packet_from_connection(&connections[i], &type)))
  142.           handle_packet_input(&connections[i], packet, type);
  143.       }
  144.       else {
  145.         lost_connection_to_player(&connections[i]);
  146.         connections[i].used=0;
  147.         close(connections[i].sock);
  148.         
  149.       }
  150.     }
  151.     }
  152.     break;
  153.   }
  154.   if(game.timeout && time(NULL)>time_at_turn_end) return 0;
  155.   return 1;
  156. }
  157.   
  158.   
  159. /********************************************************************
  160.  server accepts connections from client
  161. ********************************************************************/
  162. int server_accept_connection(int sockfd)
  163. {
  164.   int fromlen;
  165.   int new_sock;
  166.   struct sockaddr_in fromend;
  167.   struct hostent *from;
  168.  
  169.   fromlen = sizeof fromend;
  170.  
  171.   new_sock = accept(sockfd, (struct sockaddr *) &fromend, &fromlen);
  172.  
  173.   from=gethostbyaddr((char*)&fromend.sin_addr, sizeof(sizeof(fromend.sin_addr)), 
  174.              AF_INET);
  175.  
  176.   if(new_sock!=-1) {
  177.     int i;
  178.     for(i=0; i<MAX_CONNECTIONS; i++)
  179.       if(!connections[i].used) {
  180.     connections[i].used=1;
  181.     connections[i].sock=new_sock;
  182.     connections[i].player=NULL;
  183.     connections[i].buffer.ndata=0;
  184.  
  185.     if(from) {
  186.       strncpy(connections[i].addr, from->h_name, ADDR_LENGTH);
  187.       connections[i].addr[ADDR_LENGTH-1]='\0';
  188.     }
  189.     else
  190.        strcpy(connections[i].addr, "unknown");
  191.  
  192.     return 0;
  193.       }
  194.     log(LOG_FATAL, "maximum number of connections reached");
  195.     return -1;
  196.   }
  197.  
  198.   return -1;
  199. }
  200.  
  201.  
  202.  
  203. /********************************************************************
  204.  open server socket to be used to accept client connections
  205. ********************************************************************/
  206. int server_open_socket(void)
  207. {
  208.   /* setup socket address */
  209.   struct sockaddr_in src;
  210.   int opt;
  211.  
  212.   src.sin_addr.s_addr = INADDR_ANY;
  213.   src.sin_family = AF_INET;
  214.   src.sin_port = htons(port);
  215.  
  216.  
  217.   /* broken pipes are ignored. */
  218.   signal (SIGPIPE, SIG_IGN);
  219.   
  220.   if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  221.     log(LOG_FATAL, "socket failed: %s", strerror(errno));
  222.     exit(1);
  223.   }
  224.  
  225.   opt=1; 
  226.   if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 
  227.         (char*)&opt, sizeof(opt))) {
  228. /*        (const char*)&opt, sizeof(opt))) {      gave me warnings -- Syela */
  229.     log(LOG_FATAL, "setsockopt failed: %s", strerror(errno));
  230.   }
  231.  
  232.   if(bind(sock, (struct sockaddr *) &src, sizeof (src)) < 0) {
  233.     log(LOG_FATAL, "bind failed: %s", strerror(errno));
  234.     exit(1);
  235.   }
  236.  
  237.   if(listen(sock, MAX_CONNECTIONS) < 0) {
  238.     log(LOG_FATAL, "listen failed: %s", strerror(errno));
  239.     exit(1);
  240.   }
  241.  
  242.   return 0;
  243. }
  244.  
  245.  
  246. /********************************************************************
  247. ...
  248. ********************************************************************/
  249. void init_connections(void)
  250. {
  251.   int i;
  252.   for(i=0; i<MAX_CONNECTIONS; i++) { 
  253.     connections[i].used=0;
  254.     connections[i].buffer.ndata=0;
  255.   }
  256.   no_active_connections=0;
  257. }
  258.