Author: cazfi
Date: Thu Aug 21 00:17:02 2014
New Revision: 25968

URL: http://svn.gna.org/viewcvs/freeciv?rev=25968&view=rev
Log:
Made find_next_free_port() criteria for acceptable port to match what server 
considers
acceptable when it actually binds the port. This should greatly reduce the 
cases where
client launches server with a port it cannot use.

See bug #22463

Modified:
    branches/S2_5/client/connectdlg_common.c
    branches/S2_5/server/sernet.c
    branches/S2_5/utility/netintf.c
    branches/S2_5/utility/netintf.h

Modified: branches/S2_5/client/connectdlg_common.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/client/connectdlg_common.c?rev=25968&r1=25967&r2=25968&view=diff
==============================================================================
--- branches/S2_5/client/connectdlg_common.c    (original)
+++ branches/S2_5/client/connectdlg_common.c    Thu Aug 21 00:17:02 2014
@@ -203,12 +203,7 @@
 # endif /* WIN32_NATIVE */
 
 #ifdef IPV6_SUPPORT
-  /* We want port that is free in IPv4 even if we (the client) have
-   * IPv6 support. In the unlikely case that local server is IPv4-only
-   * (meaning that it has to be from different build than client) we
-   * have to give port that it can use. IPv6-enabled client would first
-   * try same port in IPv6 and if that fails, fallback to IPv4 too. */
-  enum fc_addr_family family = FC_ADDR_IPV4;
+  enum fc_addr_family family = FC_ADDR_ANY;
 #else
   enum fc_addr_family family = FC_ADDR_IPV4;
 #endif /* IPV6_SUPPORT */
@@ -224,7 +219,7 @@
    * used by standalone server on Windows where this is known to be buggy
    * by not starting from DEFAULT_SOCK_PORT but from one higher. */
   internal_server_port = find_next_free_port(DEFAULT_SOCK_PORT + 1,
-                                             family, "localhost");
+                                             family, "localhost", TRUE);
 
   if (internal_server_port < 0) {
     output_window_append(ftc_client, _("Couldn't start the server."));

Modified: branches/S2_5/server/sernet.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/server/sernet.c?rev=25968&r1=25967&r2=25968&view=diff
==============================================================================
--- branches/S2_5/server/sernet.c       (original)
+++ branches/S2_5/server/sernet.c       Thu Aug 21 00:17:02 2014
@@ -1128,6 +1128,8 @@
         /* Close only this socket. This address is not available.
          * This can happen with the IPv6 wildcard address if this
          * machine has no IPv6 interfaces. */
+        /* If you change this logic, be sure to make clientside checking
+         * of acceptable port to match. */
         fc_closesocket(s);
         continue;
       } else {

Modified: branches/S2_5/utility/netintf.c
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/utility/netintf.c?rev=25968&r1=25967&r2=25968&view=diff
==============================================================================
--- branches/S2_5/utility/netintf.c     (original)
+++ branches/S2_5/utility/netintf.c     Thu Aug 21 00:17:02 2014
@@ -513,7 +513,7 @@
   Finds the next (lowest) free port.
 **************************************************************************/ 
 int find_next_free_port(int starting_port, enum fc_addr_family family,
-                        char *net_interface)
+                        char *net_interface, bool not_avail_ok)
 {
   int port;
   int s;
@@ -542,8 +542,6 @@
      return -1;
   }
 
-  s = socket(gafamily, SOCK_STREAM, 0);
-
   for (port = starting_port; !found ; port++) {
     /* HAVE_GETADDRINFO implies IPv6 support */
 #ifdef HAVE_GETADDRINFO
@@ -562,19 +560,35 @@
     err = getaddrinfo(net_interface, servname, &hints, &res);
     if (!err) {
       struct addrinfo *current = res;
-
-      while (current != NULL && !found) {
-        if (bind(s, current->ai_addr, current->ai_addrlen) == 0) {
-          found = TRUE;
+      bool unusable = FALSE;
+
+      while (current != NULL && !unusable) {
+        s = socket(current->ai_family, SOCK_STREAM, 0);
+
+        if (s == -1) {
+          log_error("socket(): %s", fc_strerror(fc_get_errno()));
+        } else {
+          if (bind(s, current->ai_addr, current->ai_addrlen) != 0) {
+            if (!not_avail_ok || fc_get_errno() != EADDRNOTAVAIL) {
+              unusable = TRUE;
+            }
+          }
         }
         current = current->ai_next;
+        fc_closesocket(s);
       }
 
       freeaddrinfo(res);
+
+      if (!unusable && res != NULL) {
+        found = TRUE;
+      }
     }
 #else /* HAVE_GETADDRINFO */
     union fc_sockaddr tmp;
     struct sockaddr_in *sock4;
+
+    s = socket(gafamily, SOCK_STREAM, 0);
 
     sock4 = &tmp.saddr_in4;
     memset(&tmp, 0, sizeof(tmp));
@@ -603,14 +617,14 @@
     if (bind(s, &tmp.saddr, sockaddr_size(&tmp)) == 0) {
       found = TRUE;
     }
+
+    fc_closesocket(s);
 #endif /* HAVE_GETADDRINFO */
   }
 
   /* Rollback the last increment from the loop, back to port
    * number found to be free. */
   port--;
-
-  fc_closesocket(s);
   
   return port;
 }

Modified: branches/S2_5/utility/netintf.h
URL: 
http://svn.gna.org/viewcvs/freeciv/branches/S2_5/utility/netintf.h?rev=25968&r1=25967&r2=25968&view=diff
==============================================================================
--- branches/S2_5/utility/netintf.h     (original)
+++ branches/S2_5/utility/netintf.h     Thu Aug 21 00:17:02 2014
@@ -127,7 +127,7 @@
                                            enum fc_addr_family family);
 fz_FILE *fc_querysocket(int sock, void *buf, size_t size);
 int find_next_free_port(int starting_port, enum fc_addr_family family,
-                        char *net_interface);
+                        char *net_interface, bool not_avail_ok);
 
 void sockaddr_debug(union fc_sockaddr *addr);
 int sockaddr_size(union fc_sockaddr *addr);


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to