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