~cody.smith/ubuntu/precise/freeciv/lp.202327

« back to all changes in this revision

Viewing changes to server/sernet.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams
  • Date: 2010-12-16 20:44:14 UTC
  • mfrom: (1.2.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20101216204414-gcr7omy0o66x5nzo
Tags: 2.2.4-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
TEndpointInfo serv_info;
94
94
EndpointRef serv_ep;
95
95
#else
96
 
static int sock;
 
96
static int *listen_socks;
 
97
static int listen_count;
97
98
static int socklan;
98
99
#endif
99
100
 
245
246
  conn_list_free(game.all_connections);
246
247
  conn_list_free(game.est_connections);
247
248
 
248
 
  fc_closesocket(sock);
 
249
  for (i = 0; i < listen_count; i++) {
 
250
    fc_closesocket(listen_socks[i]);
 
251
  }
249
252
  fc_closesocket(socklan);
250
253
 
251
254
#ifdef HAVE_LIBREADLINE
438
441
*****************************************************************************/
439
442
enum server_events server_sniff_all_input(void)
440
443
{
441
 
  int i;
 
444
  int i, s;
442
445
  int max_desc;
 
446
  bool excepting;
443
447
  fd_set readfs, writefs, exceptfs;
444
448
  struct timeval tv;
445
449
#ifdef SOCKET_ZERO_ISNT_STDIN
500
504
        if (last_noplayers != 0) {
501
505
          if (time(NULL) > last_noplayers + srvarg.quitidle) {
502
506
            save_game_auto("Lost all connections", "quitidle");
503
 
            set_meta_message_string(N_("restarting for lack of players"));
504
 
            freelog(LOG_NORMAL, "%s", Q_(get_meta_message_string()));
 
507
            freelog(LOG_NORMAL, _("Restarting for lack of players."));
 
508
            set_meta_message_string("restarting for lack of players");
505
509
            (void) send_server_info_to_metaserver(META_INFO);
506
510
 
507
511
            set_server_state(S_S_OVER);
591
595
#endif /* SOCKET_ZERO_ISNT_STDIN */
592
596
    }
593
597
 
 
598
    max_desc = 0;
 
599
    for (i = 0; i < listen_count; i++) {
 
600
      FD_SET(listen_socks[i], &readfs);
 
601
      FD_SET(listen_socks[i], &exceptfs);
 
602
      max_desc = MAX(max_desc, listen_socks[i]);
 
603
    }
 
604
 
594
605
    if (with_ggz) {
595
606
#ifdef GGZ_SERVER
596
607
      int ggz_sock = get_ggz_socket();
597
608
 
598
609
      FD_SET(ggz_sock, &readfs);
599
 
      max_desc = MAX(sock, ggz_sock);
 
610
      max_desc = MAX(max_desc, ggz_sock);
600
611
#endif /* GGZ_SERVER */
601
 
    } else {
602
 
      FD_SET(sock, &readfs);
603
 
      FD_SET(sock, &exceptfs);
604
 
      max_desc = sock;
605
612
    }
606
613
 
607
614
    for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
660
667
    }
661
668
 
662
669
    if (!with_ggz) { /* No listening socket when using GGZ. */
663
 
      if (FD_ISSET(sock, &exceptfs)) {       /* handle Ctrl-Z suspend/resume */
 
670
      excepting = FALSE;
 
671
      for (i = 0; i < listen_count; i++) {
 
672
        if (FD_ISSET(listen_socks[i], &exceptfs)) {
 
673
          excepting = TRUE;
 
674
          break;
 
675
        }
 
676
      }
 
677
      if (excepting) {                  /* handle Ctrl-Z suspend/resume */
664
678
        continue;
665
679
      }
666
 
      if (FD_ISSET(sock, &readfs)) {    /* new players connects */
667
 
        freelog(LOG_VERBOSE, "got new connection");
668
 
        if (-1 == server_accept_connection(sock)) {
669
 
          /* There will be a LOG_ERROR message from
670
 
           * server_accept_connection() if something
671
 
           * goes wrong, so no need to make another
672
 
           * error-level message here. */
673
 
          freelog(LOG_VERBOSE, "failed accepting connection");
 
680
      for (i = 0; i < listen_count; i++) {
 
681
        s = listen_socks[i];
 
682
        if (FD_ISSET(s, &readfs)) {     /* new players connects */
 
683
          freelog(LOG_VERBOSE, "got new connection");
 
684
          if (-1 == server_accept_connection(s)) {
 
685
            /* There will be a LOG_ERROR message from
 
686
             * server_accept_connection() if something
 
687
             * goes wrong, so no need to make another
 
688
             * error-level message here. */
 
689
            freelog(LOG_VERBOSE, "failed accepting connection");
 
690
          }
674
691
        }
675
692
      }
676
693
    }
886
903
  }
887
904
 
888
905
#ifdef IPV6_SUPPORT
889
 
  if (!getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
890
 
                   service, NI_MAXSERV, NI_NUMERICSERV)) {
891
 
    nameinfo = TRUE;
892
 
  }
 
906
  nameinfo = (0 == getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
 
907
                               service, NI_MAXSERV, NI_NUMERICSERV)
 
908
              && '\0' != host[0]);
893
909
#else  /* IPv6 support */
894
 
  from =
895
 
    gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
896
 
                  sizeof(fromend.saddr_in4.sin_addr), AF_INET);
897
 
  if (from) {
 
910
  from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
 
911
                       sizeof(fromend.saddr_in4.sin_addr), AF_INET);
 
912
  if (NULL != from && '\0' != from->h_name[0]) {
898
913
    host = from->h_name;
899
914
    nameinfo = TRUE;
900
915
  }
901
916
#endif /* IPv6 support */
902
917
 
903
918
  return server_make_connection(new_sock,
904
 
                                (nameinfo ? host : dst), dst);
 
919
                                (nameinfo ? host : dst), dst);
905
920
}
906
921
 
907
922
/********************************************************************
963
978
int server_open_socket(void)
964
979
{
965
980
  /* setup socket address */
966
 
  union fc_sockaddr src;
 
981
  union fc_sockaddr names[2];
967
982
  union fc_sockaddr addr;
968
983
  struct ip_mreq mreq4;
969
 
  const char *group;
970
 
  int opt;
 
984
  const char *cause, *group;
 
985
  int i, j, name_count, on, s;
971
986
  int lan_family;
972
987
 
973
988
#ifdef IPV6_SUPPORT
974
989
  struct ipv6_mreq mreq6;
975
990
#endif
976
991
 
977
 
  if (!net_lookup_service(srvarg.bind_addr, srvarg.port, &src, FALSE)) {
 
992
  /* Lookup addresses to bind. */
 
993
  if (!net_lookup_service(srvarg.bind_addr, srvarg.port, &names[0], FALSE)) {
978
994
    freelog(LOG_FATAL, _("Server: bad address: <%s:%d>."),
979
995
            srvarg.bind_addr, srvarg.port);
980
996
    exit(EXIT_FAILURE);
981
997
  }
982
 
 
983
 
  /* Create socket for client connections. */
984
 
  if((sock = socket(src.saddr.sa_family, SOCK_STREAM, 0)) == -1) {
985
 
    fc_errno error = fc_get_errno();
986
 
 
987
 
#ifdef IPV6_SUPPORT
988
 
#ifdef EAFNOSUPPORT
989
 
    bool still_error = TRUE;
990
 
 
991
 
    if (error == EAFNOSUPPORT && src.saddr.sa_family == AF_INET6 && srvarg.bind_addr == NULL) {
992
 
      /* Let's try IPv4 socket instead */
993
 
      freelog(LOG_NORMAL, _("Cannot open IPv6 socket, trying IPv4 instead"));
994
 
 
995
 
      if (!net_lookup_service(NULL, srvarg.port, &src, TRUE)) {
996
 
        freelog(LOG_FATAL, _("IPv4 service lookup failed <%d>."),
997
 
                srvarg.port);
998
 
        exit(EXIT_FAILURE);
 
998
  name_count = 1;
 
999
#ifdef IPV6_SUPPORT
 
1000
  if (names[0].saddr.sa_family == AF_INET6) {
 
1001
    /* net_lookup_service() prefers IPv6 address.
 
1002
     * Check if there is also IPv4 address.
 
1003
     * TODO: This would be easier using getaddrinfo() */
 
1004
    if (net_lookup_service(srvarg.bind_addr, srvarg.port,
 
1005
                           &names[1], TRUE /* force IPv4 */)) {
 
1006
      name_count = 2;
 
1007
    }
 
1008
  }
 
1009
#endif
 
1010
 
 
1011
  cause = NULL;
 
1012
  on = 1;
 
1013
 
 
1014
  /* Loop to create sockets, bind, listen. */
 
1015
  listen_socks = fc_calloc(name_count, sizeof(listen_socks[0]));
 
1016
  listen_count = 0;
 
1017
  for (i = 0; i < name_count; i++) {
 
1018
 
 
1019
    /* Create socket for client connections. */
 
1020
    s = socket(names[i].saddr.sa_family, SOCK_STREAM, 0);
 
1021
    if (s == -1) {
 
1022
      /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
 
1023
       * Kernel might have disabled AF_INET6. */
 
1024
      cause = "socket";
 
1025
      continue;
 
1026
    }
 
1027
 
 
1028
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 
 
1029
                   (char *)&on, sizeof(on)) == -1) {
 
1030
      freelog(LOG_ERROR, "setsockopt SO_REUSEADDR failed: %s",
 
1031
              fc_strerror(fc_get_errno()));
 
1032
      sockaddr_debug(&names[i]);
 
1033
    }
 
1034
 
 
1035
    /* AF_INET6 sockets should use IPv6 only,
 
1036
     * without stealing IPv4 from AF_INET sockets. */
 
1037
#ifdef IPV6_SUPPORT
 
1038
    if (names[i].saddr.sa_family == AF_INET6) {
 
1039
#ifdef IPV6_V6ONLY
 
1040
      if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
 
1041
                     (char *)&on, sizeof(on)) == -1) {
 
1042
        freelog(LOG_ERROR, "setsockopt IPV6_V6ONLY failed: %s",
 
1043
                fc_strerror(fc_get_errno()));
 
1044
        sockaddr_debug(&names[i]);
999
1045
      }
1000
 
 
1001
 
      /* Create socket for client connections. */
1002
 
      if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1003
 
        fc_errno error2 = fc_get_errno();
1004
 
        freelog(LOG_ERROR, "Even IPv4 socket failed: %s", fc_strerror(error2));
 
1046
#endif
 
1047
    }
 
1048
#endif
 
1049
 
 
1050
    if (bind(s, &names[i].saddr, sockaddr_size(&names[i])) == -1) {
 
1051
      cause = "bind";
 
1052
 
 
1053
      if (fc_get_errno() == EADDRNOTAVAIL) {
 
1054
        /* Close only this socket. This address is not available.
 
1055
         * This can happen with the IPv6 wildcard address if this
 
1056
         * machine has no IPv6 interfaces. */
 
1057
        fc_closesocket(s);
 
1058
        continue;
1005
1059
      } else {
1006
 
        still_error = FALSE;
 
1060
        /* Close all sockets. Another program might have bound to
 
1061
         * one of our addresses, and might hijack some of our
 
1062
         * connections. */
 
1063
        fc_closesocket(s);
 
1064
        for (j = 0; j < listen_count; j++) {
 
1065
          fc_closesocket(listen_socks[j]);
 
1066
        }
 
1067
        listen_count = 0;
 
1068
        break;
1007
1069
      }
1008
1070
    }
1009
1071
 
1010
 
    if (still_error)
1011
 
#endif /* EAFNOSUPPORT */
1012
 
#endif /* IPv6 support */
1013
 
    {
1014
 
      die("socket failed: %s", fc_strerror(error));
1015
 
    }
1016
 
  }
1017
 
 
1018
 
  opt = 1;
1019
 
  if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 
1020
 
                (char *)&opt, sizeof(opt)) == -1) {
1021
 
    freelog(LOG_ERROR, "SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1022
 
  }
1023
 
 
1024
 
  if(bind(sock, &src.saddr, sockaddr_size(&src)) == -1) {
1025
 
    freelog(LOG_FATAL, "Server bind failed: %s", fc_strerror(fc_get_errno()));
1026
 
    sockaddr_debug(&src);
1027
 
    exit(EXIT_FAILURE);
1028
 
  }
1029
 
 
1030
 
  if(listen(sock, MAX_NUM_CONNECTIONS) == -1) {
1031
 
    freelog(LOG_FATAL, "listen failed: %s", fc_strerror(fc_get_errno()));
 
1072
    if (listen(s, MAX_NUM_CONNECTIONS) == -1) {
 
1073
      cause = "listen";
 
1074
      fc_closesocket(s);
 
1075
      continue;
 
1076
    }
 
1077
 
 
1078
    listen_socks[listen_count] = s;
 
1079
    listen_count++;
 
1080
  }
 
1081
 
 
1082
  if (listen_count == 0) {
 
1083
    freelog(LOG_FATAL, "%s failed: %s", cause, fc_strerror(fc_get_errno()));
 
1084
    for (i = 0; i < name_count; i++) {
 
1085
      sockaddr_debug(&names[i]);
 
1086
    }
1032
1087
    exit(EXIT_FAILURE);
1033
1088
  }
1034
1089
 
1051
1106
  }
1052
1107
 
1053
1108
  if (setsockopt(socklan, SOL_SOCKET, SO_REUSEADDR,
1054
 
                 (char *)&opt, sizeof(opt)) == -1) {
 
1109
                 (char *)&on, sizeof(on)) == -1) {
1055
1110
    freelog(LOG_ERROR, "SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1056
1111
  }
1057
1112