X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=libtest%2Fport.cc;h=fefb6a6d394ada0c72b0c480b61b7b38c140a406;hb=1e8bc3cb173d8b4e206363de7fdabeddb32d0f53;hp=c1f2f94551cad8bdb24fc2a742c331141dc03053;hpb=a18c65b0ee1a4721a4f1298f52f8b3446cf7c600;p=m6w6%2Flibmemcached diff --git a/libtest/port.cc b/libtest/port.cc index c1f2f945..fefb6a6d 100644 --- a/libtest/port.cc +++ b/libtest/port.cc @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include @@ -45,66 +46,78 @@ 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() { - return global_port; -} - -void set_default_port(in_port_t port) -{ - global_port= port; -} - -in_port_t max_port() -{ - return global_max_port; -} - -void set_max_port(in_port_t port) -{ - if (port > global_max_port) + if (global_port == 0) { - global_max_port= port; + global_port= get_free_port(); } - global_max_port= port; + return global_port; } in_port_t get_free_port() { in_port_t ret_port= in_port_t(0); - int sd; - if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1) + + int retries= 1024; + + while (retries--) { - int optval= 1; - if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1) + int sd; + if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -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) + int optval= 1; + if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1) { - socklen_t addrlen= sizeof(sin); + 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 (listen(sd, 100) != -1) + 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; } + } - close(sd); + // We handle the case where if we max out retries, we still abort. + if (ret_port <= 1024) + { + fatal_message("No port could be found"); } return ret_port;