jenkins-promote-staging-trunk-libmemcached-7
[m6w6/libmemcached] / libtest / port.cc
index c1f2f94551cad8bdb24fc2a742c331141dc03053..fefb6a6d394ada0c72b0c480b61b7b38c140a406 100644 (file)
@@ -19,6 +19,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <config.h>
 #include <libtest/common.h>
 
 #include <cassert>
 
 using namespace libtest;
 
+struct socket_st {
+  std::vector<int> fd;
+
+  ~socket_st()
+  {
+    for(std::vector<int>::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;