X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=libtest%2Fport.cc;h=fefb6a6d394ada0c72b0c480b61b7b38c140a406;hb=5b98081c95814fdc00882787f63ab4d169d6fcc5;hp=36939e147aa9e3903f99e9960da826ceea4bf519;hpb=3645e647825396693c46a4de5d9e45dfde54dabd;p=m6w6%2Flibmemcached diff --git a/libtest/port.cc b/libtest/port.cc index 36939e14..fefb6a6d 100644 --- a/libtest/port.cc +++ b/libtest/port.cc @@ -19,19 +19,21 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include #include @@ -44,34 +46,81 @@ using namespace libtest; +struct socket_st { + std::vector fd; + + ~socket_st() + { + for(std::vector::iterator iter= fd.begin(); iter != fd.end(); iter++) + { + close(*iter); + } + } +}; + +static socket_st all_socket_fd; + static in_port_t global_port= 0; -static in_port_t global_max_port= 0; namespace libtest { in_port_t default_port() { + if (global_port == 0) + { + global_port= get_free_port(); + } + return global_port; } - -void set_default_port(in_port_t port) -{ - global_port= port; -} -in_port_t max_port() +in_port_t get_free_port() { - return global_max_port; -} - -void set_max_port(in_port_t port) -{ - if (port > global_max_port) + in_port_t ret_port= in_port_t(0); + + int retries= 1024; + + while (retries--) + { + int sd; + if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1) + { + int optval= 1; + if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1) + { + struct sockaddr_in sin; + sin.sin_port= 0; + sin.sin_addr.s_addr= 0; + sin.sin_addr.s_addr= INADDR_ANY; + sin.sin_family= AF_INET; + + if (bind(sd, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) != -1) + { + socklen_t addrlen= sizeof(sin); + + if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1) + { + ret_port= sin.sin_port; + } + } + } + + all_socket_fd.fd.push_back(sd); + } + + if (ret_port > 1024) + { + break; + } + } + + // We handle the case where if we max out retries, we still abort. + if (ret_port <= 1024) { - global_max_port= port; + fatal_message("No port could be found"); } - global_max_port= port; + return ret_port; } } // namespace libtest