Return bound port number from grpc_server_add_http2_port.

Allows tests to bind to port 0 and still have clients connect to them.
	Change on 2015/01/12 by ctiller <ctiller@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=83800669
diff --git a/src/core/iomgr/sockaddr_utils.c b/src/core/iomgr/sockaddr_utils.c
index f709d35..eca14a4 100644
--- a/src/core/iomgr/sockaddr_utils.c
+++ b/src/core/iomgr/sockaddr_utils.c
@@ -153,3 +153,31 @@
   errno = save_errno;
   return ret;
 }
+
+int grpc_sockaddr_get_port(const struct sockaddr *addr) {
+  switch (addr->sa_family) {
+    case AF_INET:
+      return ntohs(((struct sockaddr_in *)addr)->sin_port);
+    case AF_INET6:
+      return ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
+    default:
+      gpr_log(GPR_ERROR, "Unknown socket family %d in %s", addr->sa_family,
+              __FUNCTION__);
+      return 0;
+  }
+}
+
+int grpc_sockaddr_set_port(const struct sockaddr *addr, int port) {
+  switch (addr->sa_family) {
+    case AF_INET:
+      ((struct sockaddr_in *)addr)->sin_port = htons(port);
+      return 1;
+    case AF_INET6:
+      ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
+      return 1;
+    default:
+      gpr_log(GPR_ERROR, "Unknown socket family %d in %s", addr->sa_family,
+              __FUNCTION__);
+      return 0;
+  }
+}
diff --git a/src/core/iomgr/sockaddr_utils.h b/src/core/iomgr/sockaddr_utils.h
index 753d0c8..3f5b770 100644
--- a/src/core/iomgr/sockaddr_utils.h
+++ b/src/core/iomgr/sockaddr_utils.h
@@ -57,6 +57,12 @@
 void grpc_sockaddr_make_wildcards(int port, struct sockaddr_in *wild4_out,
                                   struct sockaddr_in6 *wild6_out);
 
+/* Return the IP port number of a sockaddr */
+int grpc_sockaddr_get_port(const struct sockaddr *addr);
+
+/* Set IP port number of a sockaddr */
+int grpc_sockaddr_set_port(const struct sockaddr *addr, int port);
+
 /* Converts a sockaddr into a newly-allocated human-readable string.
 
    Currently, only the AF_INET and AF_INET6 families are recognized.
diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h
index 1968246..d881e14 100644
--- a/src/core/iomgr/tcp_server.h
+++ b/src/core/iomgr/tcp_server.h
@@ -52,7 +52,8 @@
 void grpc_tcp_server_start(grpc_tcp_server *server, grpc_pollset *pollset,
                            grpc_tcp_server_cb cb, void *cb_arg);
 
-/* Add a port to the server, returning true on success, or false otherwise.
+/* Add a port to the server, returning port number on success, or negative
+   on failure.
 
    The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
    both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
@@ -60,6 +61,8 @@
    but not dualstack sockets.
 
    For raw access to the underlying sockets, see grpc_tcp_server_get_fd(). */
+/* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
+                  all of the multiple socket port matching logic in one place */
 int grpc_tcp_server_add_port(grpc_tcp_server *s, const struct sockaddr *addr,
                              int addr_len);
 
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
index 5ed5177..753e24c 100644
--- a/src/core/iomgr/tcp_server_posix.c
+++ b/src/core/iomgr/tcp_server_posix.c
@@ -154,6 +154,9 @@
 
 /* Prepare a recently-created socket for listening. */
 static int prepare_socket(int fd, const struct sockaddr *addr, int addr_len) {
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
+
   if (fd < 0) {
     goto error;
   }
@@ -179,13 +182,18 @@
     goto error;
   }
 
-  return 1;
+  sockname_len = sizeof(sockname_temp);
+  if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
+    goto error;
+  }
+
+  return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
 
 error:
   if (fd >= 0) {
     close(fd);
   }
-  return 0;
+  return -1;
 }
 
 /* event manager callback when reads are ready */
@@ -234,39 +242,64 @@
 static int add_socket_to_server(grpc_tcp_server *s, int fd,
                                 const struct sockaddr *addr, int addr_len) {
   server_port *sp;
+  int port;
 
-  if (!prepare_socket(fd, addr, addr_len)) {
-    return 0;
+  port = prepare_socket(fd, addr, addr_len);
+  if (port >= 0) {
+    gpr_mu_lock(&s->mu);
+    GPR_ASSERT(!s->cb && "must add ports before starting server");
+    /* append it to the list under a lock */
+    if (s->nports == s->port_capacity) {
+      s->port_capacity *= 2;
+      s->ports =
+          gpr_realloc(s->ports, sizeof(server_port *) * s->port_capacity);
+    }
+    sp = &s->ports[s->nports++];
+    sp->server = s;
+    sp->fd = fd;
+    sp->emfd = grpc_fd_create(fd);
+    GPR_ASSERT(sp->emfd);
+    gpr_mu_unlock(&s->mu);
   }
 
-  gpr_mu_lock(&s->mu);
-  GPR_ASSERT(!s->cb && "must add ports before starting server");
-  /* append it to the list under a lock */
-  if (s->nports == s->port_capacity) {
-    s->port_capacity *= 2;
-    s->ports = gpr_realloc(s->ports, sizeof(server_port *) * s->port_capacity);
-  }
-  sp = &s->ports[s->nports++];
-  sp->server = s;
-  sp->fd = fd;
-  sp->emfd = grpc_fd_create(fd);
-  GPR_ASSERT(sp->emfd);
-  gpr_mu_unlock(&s->mu);
-
-  return 1;
+  return port;
 }
 
 int grpc_tcp_server_add_port(grpc_tcp_server *s, const struct sockaddr *addr,
                              int addr_len) {
-  int ok = 0;
+  int allocated_port1 = -1;
+  int allocated_port2 = -1;
+  int i;
   int fd;
   grpc_dualstack_mode dsmode;
   struct sockaddr_in6 addr6_v4mapped;
   struct sockaddr_in wild4;
   struct sockaddr_in6 wild6;
   struct sockaddr_in addr4_copy;
+  struct sockaddr *allocated_addr = NULL;
+  struct sockaddr_storage sockname_temp;
+  socklen_t sockname_len;
   int port;
 
+  /* Check if this is a wildcard port, and if so, try to keep the port the same
+     as some previously created listener. */
+  if (grpc_sockaddr_get_port(addr) == 0) {
+    for (i = 0; i < s->nports; i++) {
+      sockname_len = sizeof(sockname_temp);
+      if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
+                           &sockname_len)) {
+        port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
+        if (port > 0) {
+          allocated_addr = malloc(addr_len);
+          memcpy(allocated_addr, addr, addr_len);
+          grpc_sockaddr_set_port(allocated_addr, port);
+          addr = allocated_addr;
+          break;
+        }
+      }
+    }
+  }
+
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
     addr = (const struct sockaddr *)&addr6_v4mapped;
     addr_len = sizeof(addr6_v4mapped);
@@ -280,12 +313,15 @@
     addr = (struct sockaddr *)&wild6;
     addr_len = sizeof(wild6);
     fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-    ok |= add_socket_to_server(s, fd, addr, addr_len);
+    allocated_port1 = add_socket_to_server(s, fd, addr, addr_len);
     if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-      return ok;
+      goto done;
     }
 
     /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
+    if (port == 0 && allocated_port1 > 0) {
+      grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
+    }
     addr = (struct sockaddr *)&wild4;
     addr_len = sizeof(wild4);
   }
@@ -299,8 +335,11 @@
     addr = (struct sockaddr *)&addr4_copy;
     addr_len = sizeof(addr4_copy);
   }
-  ok |= add_socket_to_server(s, fd, addr, addr_len);
-  return ok;
+  allocated_port2 = add_socket_to_server(s, fd, addr, addr_len);
+
+done:
+  gpr_free(allocated_addr);
+  return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
 }
 
 int grpc_tcp_server_get_fd(grpc_tcp_server *s, int index) {