|  | @@ -260,15 +260,36 @@ static void on_connect(uv_stream_t* server, int status) {
 | 
	
		
			
				|  |  |    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error* add_socket_to_server(grpc_tcp_server* s, uv_tcp_t* handle,
 | 
	
		
			
				|  |  | -                                        const grpc_resolved_address* addr,
 | 
	
		
			
				|  |  | -                                        unsigned port_index,
 | 
	
		
			
				|  |  | -                                        grpc_tcp_listener** listener) {
 | 
	
		
			
				|  |  | +static grpc_error* add_addr_to_server(grpc_tcp_server* s,
 | 
	
		
			
				|  |  | +                                      const grpc_resolved_address* addr,
 | 
	
		
			
				|  |  | +                                      unsigned port_index,
 | 
	
		
			
				|  |  | +                                      grpc_tcp_listener** listener) {
 | 
	
		
			
				|  |  |    grpc_tcp_listener* sp = NULL;
 | 
	
		
			
				|  |  |    int port = -1;
 | 
	
		
			
				|  |  |    int status;
 | 
	
		
			
				|  |  |    grpc_error* error;
 | 
	
		
			
				|  |  |    grpc_resolved_address sockname_temp;
 | 
	
		
			
				|  |  | +  uv_tcp_t* handle = (uv_tcp_t*)gpr_malloc(sizeof(uv_tcp_t));
 | 
	
		
			
				|  |  | +  int family = grpc_sockaddr_get_family(addr);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  status = uv_tcp_init_ex(uv_default_loop(), handle, (unsigned int)family);
 | 
	
		
			
				|  |  | +#if defined(GPR_LINUX) && defined(SO_REUSEPORT)
 | 
	
		
			
				|  |  | +  if (family == AF_INET || family == AF_INET6) {
 | 
	
		
			
				|  |  | +    int fd;
 | 
	
		
			
				|  |  | +    uv_fileno((uv_handle_t*)handle, &fd);
 | 
	
		
			
				|  |  | +    int enable = 1;
 | 
	
		
			
				|  |  | +    setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +#endif /* GPR_LINUX && SO_REUSEPORT */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (status != 0) {
 | 
	
		
			
				|  |  | +    error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
 | 
	
		
			
				|  |  | +        "Failed to initialize UV tcp handle");
 | 
	
		
			
				|  |  | +    error =
 | 
	
		
			
				|  |  | +        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
 | 
	
		
			
				|  |  | +                           grpc_slice_from_static_string(uv_strerror(status)));
 | 
	
		
			
				|  |  | +    return error;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // The last argument to uv_tcp_bind is flags
 | 
	
		
			
				|  |  |    status = uv_tcp_bind(handle, (struct sockaddr*)addr->addr, 0);
 | 
	
	
		
			
				|  | @@ -325,20 +346,46 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, uv_tcp_t* handle,
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static grpc_error* add_wildcard_addrs_to_server(grpc_tcp_server* s,
 | 
	
		
			
				|  |  | +                                                unsigned port_index,
 | 
	
		
			
				|  |  | +                                                int requested_port,
 | 
	
		
			
				|  |  | +                                                grpc_tcp_listener **listener) {
 | 
	
		
			
				|  |  | +  grpc_resolved_address wild4;
 | 
	
		
			
				|  |  | +  grpc_resolved_address wild6;
 | 
	
		
			
				|  |  | +  grpc_tcp_listener* sp = nullptr;
 | 
	
		
			
				|  |  | +  grpc_tcp_listener* sp2 = nullptr;
 | 
	
		
			
				|  |  | +  grpc_error* v6_err = GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | +  grpc_error* v4_err = GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
 | 
	
		
			
				|  |  | +  /* Try listening on IPv6 first. */
 | 
	
		
			
				|  |  | +  if ((v6_err = add_addr_to_server(s, &wild6, port_index, &sp)) == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | +    *listener = sp;
 | 
	
		
			
				|  |  | +    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if ((v4_err = add_addr_to_server(s, &wild4, port_index, &sp2)) == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | +    *listener = sp2;
 | 
	
		
			
				|  |  | +    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  grpc_error* root_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
 | 
	
		
			
				|  |  | +      "Failed to add any wildcard listeners");
 | 
	
		
			
				|  |  | +  root_err = grpc_error_add_child(root_err, v6_err);
 | 
	
		
			
				|  |  | +  root_err = grpc_error_add_child(root_err, v4_err);
 | 
	
		
			
				|  |  | +  return root_err;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  grpc_error* grpc_tcp_server_add_port(grpc_tcp_server* s,
 | 
	
		
			
				|  |  |                                       const grpc_resolved_address* addr,
 | 
	
		
			
				|  |  |                                       int* port) {
 | 
	
		
			
				|  |  |    // This function is mostly copied from tcp_server_windows.c
 | 
	
		
			
				|  |  |    grpc_tcp_listener* sp = NULL;
 | 
	
		
			
				|  |  | -  uv_tcp_t* handle;
 | 
	
		
			
				|  |  |    grpc_resolved_address addr6_v4mapped;
 | 
	
		
			
				|  |  | -  grpc_resolved_address wildcard;
 | 
	
		
			
				|  |  |    grpc_resolved_address* allocated_addr = NULL;
 | 
	
		
			
				|  |  |    grpc_resolved_address sockname_temp;
 | 
	
		
			
				|  |  |    unsigned port_index = 0;
 | 
	
		
			
				|  |  | -  int status;
 | 
	
		
			
				|  |  |    grpc_error* error = GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | -  int family;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GRPC_UV_ASSERT_SAME_THREAD();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -367,38 +414,15 @@ grpc_error* grpc_tcp_server_add_port(grpc_tcp_server* s,
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
 | 
	
		
			
				|  |  | -    addr = &addr6_v4mapped;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
 | 
	
		
			
				|  |  |    if (grpc_sockaddr_is_wildcard(addr, port)) {
 | 
	
		
			
				|  |  | -    grpc_sockaddr_make_wildcard6(*port, &wildcard);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    addr = &wildcard;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  handle = (uv_tcp_t*)gpr_malloc(sizeof(uv_tcp_t));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  family = grpc_sockaddr_get_family(addr);
 | 
	
		
			
				|  |  | -  status = uv_tcp_init_ex(uv_default_loop(), handle, (unsigned int)family);
 | 
	
		
			
				|  |  | -#if defined(GPR_LINUX) && defined(SO_REUSEPORT)
 | 
	
		
			
				|  |  | -  if (family == AF_INET || family == AF_INET6) {
 | 
	
		
			
				|  |  | -    int fd;
 | 
	
		
			
				|  |  | -    uv_fileno((uv_handle_t*)handle, &fd);
 | 
	
		
			
				|  |  | -    int enable = 1;
 | 
	
		
			
				|  |  | -    setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#endif /* GPR_LINUX && SO_REUSEPORT */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (status == 0) {
 | 
	
		
			
				|  |  | -    error = add_socket_to_server(s, handle, addr, port_index, &sp);
 | 
	
		
			
				|  |  | +    error = add_wildcard_addrs_to_server(s, port_index, *port, &sp);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
 | 
	
		
			
				|  |  | -        "Failed to initialize UV tcp handle");
 | 
	
		
			
				|  |  | -    error =
 | 
	
		
			
				|  |  | -        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
 | 
	
		
			
				|  |  | -                           grpc_slice_from_static_string(uv_strerror(status)));
 | 
	
		
			
				|  |  | +    if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
 | 
	
		
			
				|  |  | +      addr = &addr6_v4mapped;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    error = add_addr_to_server(s, addr, port_index, &sp);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    gpr_free(allocated_addr);
 |