From f134206509de8417f3f568e8b599290c1b955e1f Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Sun, 12 Mar 2017 22:39:11 -0700 Subject: [PATCH 1/4] Fix android build --- src/core/lib/iomgr/port.h | 4 ++++ src/core/lib/iomgr/tcp_server_posix.c | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index f1897bb91f2..94a454c0b7c 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -39,6 +39,7 @@ #if defined(GRPC_UV) // Do nothing #elif defined(GPR_MANYLINUX1) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 @@ -65,6 +66,7 @@ #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_LINUX) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_IP_PKTINFO 1 #define GRPC_HAVE_MSG_NOSIGNAL 1 @@ -90,6 +92,7 @@ #define GRPC_POSIX_SOCKETUTILS #endif #elif defined(GPR_APPLE) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_SO_NOSIGPIPE 1 #define GRPC_HAVE_UNIX_SOCKET 1 #define GRPC_MSG_IOVLEN_TYPE int @@ -100,6 +103,7 @@ #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #elif defined(GPR_FREEBSD) +#define GRPC_HAVE_IFADDRS 1 #define GRPC_HAVE_IPV6_RECVPKTINFO 1 #define GRPC_HAVE_SO_NOSIGPIPE 1 #define GRPC_HAVE_UNIX_SOCKET 1 diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 5f286a6723c..7cc44fabe7e 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -42,9 +42,12 @@ #include "src/core/lib/iomgr/tcp_server.h" +#ifdef GRPC_HAVE_IFADDRS +#include +#endif /* GRPC_HAVE_IFADDRS */ + #include #include -#include #include #include #include @@ -598,6 +601,7 @@ static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port) { +#ifdef GRPC_HAVE_IFADDRS struct ifaddrs *ifa = NULL; struct ifaddrs *ifa_it; unsigned fd_index = 0; @@ -685,6 +689,9 @@ static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s, *out_port = sp->port; return GRPC_ERROR_NONE; } +#else /* GRPC_HAVE_IFADDRS */ + return GRPC_ERROR_NONE; +#endif /* GRPC_HAVE_IFADDRS */ } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ From ca294650ba9613044c89635b91d6d5ed603d14c5 Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Mon, 13 Mar 2017 14:50:34 -0700 Subject: [PATCH 2/4] Change macros --- src/core/lib/iomgr/tcp_server_posix.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 7cc44fabe7e..61ffb02a716 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -601,7 +601,9 @@ static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port) { -#ifdef GRPC_HAVE_IFADDRS +#ifndef GRPC_HAVE_IFADDRS + return GRPC_ERROR_CREATE("no ifaddrs available"); +#else /* ifndef GRPC_HAVE_IFADDRS */ struct ifaddrs *ifa = NULL; struct ifaddrs *ifa_it; unsigned fd_index = 0; @@ -689,9 +691,7 @@ static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s, *out_port = sp->port; return GRPC_ERROR_NONE; } -#else /* GRPC_HAVE_IFADDRS */ - return GRPC_ERROR_NONE; -#endif /* GRPC_HAVE_IFADDRS */ +#endif /* ifndef GRPC_HAVE_IFADDRS */ } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ @@ -708,10 +708,14 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, grpc_error *v6_err = GRPC_ERROR_NONE; grpc_error *v4_err = GRPC_ERROR_NONE; *out_port = -1; + +#ifdef GRPC_HAVE_IFADDRS if (s->expand_wildcard_addrs) { return add_all_local_addrs_to_server(s, port_index, requested_port, out_port); } +#endif /* GRPC_HAVE_IFADDRS */ + grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6); /* Try listening on IPv6 first. */ if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode, From 47155ed254e7d798cd42797eea1533d5264c565c Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Mon, 13 Mar 2017 17:18:07 -0700 Subject: [PATCH 3/4] Split ifaddr related functions out into a separate file --- BUILD | 3 + CMakeLists.txt | 10 + Makefile | 10 + binding.gyp | 2 + build.yaml | 3 + config.m4 | 2 + gRPC-Core.podspec | 4 + grpc.gemspec | 3 + package.xml | 3 + src/core/lib/iomgr/tcp_server_posix.c | 192 ++---------------- src/core/lib/iomgr/tcp_server_utils_posix.h | 89 ++++++++ .../iomgr/tcp_server_utils_posix_ifaddrs.c | 178 ++++++++++++++++ .../iomgr/tcp_server_utils_posix_noifaddrs.c | 49 +++++ src/python/grpcio/grpc_core_dependencies.py | 2 + tools/doxygen/Doxyfile.core.internal | 3 + .../generated/sources_and_headers.json | 4 + vsprojects/vcxproj/grpc/grpc.vcxproj | 5 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 9 + .../grpc_test_util/grpc_test_util.vcxproj | 5 + .../grpc_test_util.vcxproj.filters | 9 + .../grpc_unsecure/grpc_unsecure.vcxproj | 5 + .../grpc_unsecure.vcxproj.filters | 9 + 22 files changed, 423 insertions(+), 176 deletions(-) create mode 100644 src/core/lib/iomgr/tcp_server_utils_posix.h create mode 100644 src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c create mode 100644 src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c diff --git a/BUILD b/BUILD index ca0a1c56076..dc6431484e3 100644 --- a/BUILD +++ b/BUILD @@ -481,6 +481,8 @@ grpc_cc_library( "src/core/lib/iomgr/tcp_client_windows.c", "src/core/lib/iomgr/tcp_posix.c", "src/core/lib/iomgr/tcp_server_posix.c", + "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", + "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", "src/core/lib/iomgr/tcp_server_uv.c", "src/core/lib/iomgr/tcp_server_windows.c", "src/core/lib/iomgr/tcp_uv.c", @@ -599,6 +601,7 @@ grpc_cc_library( "src/core/lib/iomgr/tcp_client_posix.h", "src/core/lib/iomgr/tcp_posix.h", "src/core/lib/iomgr/tcp_server.h", + "src/core/lib/iomgr/tcp_server_utils_posix.h", "src/core/lib/iomgr/tcp_uv.h", "src/core/lib/iomgr/tcp_windows.h", "src/core/lib/iomgr/time_averaged_stats.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index d0a65b44932..cfc4555834a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -914,6 +914,8 @@ add_library(grpc src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c @@ -1223,6 +1225,8 @@ add_library(grpc_cronet src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c @@ -1523,6 +1527,8 @@ add_library(grpc_test_util src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c @@ -1769,6 +1775,8 @@ add_library(grpc_unsecure src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c @@ -2376,6 +2384,8 @@ add_library(grpc++_cronet src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c src/core/lib/iomgr/tcp_server_windows.c src/core/lib/iomgr/tcp_uv.c diff --git a/Makefile b/Makefile index a9242dddbdd..14c5a36c957 100644 --- a/Makefile +++ b/Makefile @@ -2799,6 +2799,8 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ @@ -3111,6 +3113,8 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ @@ -3414,6 +3418,8 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ @@ -3640,6 +3646,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ @@ -4249,6 +4257,8 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ diff --git a/binding.gyp b/binding.gyp index c521a27c300..ec21a97806f 100644 --- a/binding.gyp +++ b/binding.gyp @@ -667,6 +667,8 @@ 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', diff --git a/build.yaml b/build.yaml index a32a8a06d34..36817a55067 100644 --- a/build.yaml +++ b/build.yaml @@ -228,6 +228,7 @@ filegroups: - src/core/lib/iomgr/tcp_client_posix.h - src/core/lib/iomgr/tcp_posix.h - src/core/lib/iomgr/tcp_server.h + - src/core/lib/iomgr/tcp_server_utils_posix.h - src/core/lib/iomgr/tcp_uv.h - src/core/lib/iomgr/tcp_windows.h - src/core/lib/iomgr/time_averaged_stats.h @@ -337,6 +338,8 @@ filegroups: - src/core/lib/iomgr/tcp_client_windows.c - src/core/lib/iomgr/tcp_posix.c - src/core/lib/iomgr/tcp_server_posix.c + - src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c + - src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c - src/core/lib/iomgr/tcp_server_uv.c - src/core/lib/iomgr/tcp_server_windows.c - src/core/lib/iomgr/tcp_uv.c diff --git a/config.m4 b/config.m4 index 90536e503ed..181e44c52c8 100644 --- a/config.m4 +++ b/config.m4 @@ -140,6 +140,8 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ + src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 027babcda46..1d002247d4b 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -309,6 +309,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/tcp_client_posix.h', 'src/core/lib/iomgr/tcp_posix.h', 'src/core/lib/iomgr/tcp_server.h', + 'src/core/lib/iomgr/tcp_server_utils_posix.h', 'src/core/lib/iomgr/tcp_uv.h', 'src/core/lib/iomgr/tcp_windows.h', 'src/core/lib/iomgr/time_averaged_stats.h', @@ -508,6 +509,8 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', @@ -744,6 +747,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/tcp_client_posix.h', 'src/core/lib/iomgr/tcp_posix.h', 'src/core/lib/iomgr/tcp_server.h', + 'src/core/lib/iomgr/tcp_server_utils_posix.h', 'src/core/lib/iomgr/tcp_uv.h', 'src/core/lib/iomgr/tcp_windows.h', 'src/core/lib/iomgr/time_averaged_stats.h', diff --git a/grpc.gemspec b/grpc.gemspec index 8d5b7b2ab1c..edc08cb9b9a 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -226,6 +226,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/tcp_client_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_server.h ) + s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_uv.h ) s.files += %w( src/core/lib/iomgr/tcp_windows.h ) s.files += %w( src/core/lib/iomgr/time_averaged_stats.h ) @@ -425,6 +426,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/tcp_client_windows.c ) s.files += %w( src/core/lib/iomgr/tcp_posix.c ) s.files += %w( src/core/lib/iomgr/tcp_server_posix.c ) + s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c ) + s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c ) s.files += %w( src/core/lib/iomgr/tcp_server_uv.c ) s.files += %w( src/core/lib/iomgr/tcp_server_windows.c ) s.files += %w( src/core/lib/iomgr/tcp_uv.c ) diff --git a/package.xml b/package.xml index 4167bef26e3..21eeee4d3ef 100644 --- a/package.xml +++ b/package.xml @@ -235,6 +235,7 @@ + @@ -434,6 +435,8 @@ + + diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 61ffb02a716..1e9e854d6b5 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -42,10 +42,6 @@ #include "src/core/lib/iomgr/tcp_server.h" -#ifdef GRPC_HAVE_IFADDRS -#include -#endif /* GRPC_HAVE_IFADDRS */ - #include #include #include @@ -70,6 +66,7 @@ #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" @@ -78,29 +75,6 @@ static gpr_once s_init_max_accept_queue_size; static int s_max_accept_queue_size; -/* one listening port */ -typedef struct grpc_tcp_listener grpc_tcp_listener; -struct grpc_tcp_listener { - int fd; - grpc_fd *emfd; - grpc_tcp_server *server; - grpc_resolved_address addr; - int port; - unsigned port_index; - unsigned fd_index; - grpc_closure read_closure; - grpc_closure destroyed_closure; - struct grpc_tcp_listener *next; - /* sibling is a linked list of all listeners for a given port. add_port and - clone_port place all new listeners in the same sibling list. A member of - the 'sibling' list is also a member of the 'next' list. The head of each - sibling list has is_sibling==0, and subsequent members of sibling lists - have is_sibling==1. is_sibling allows separate sibling lists to be - identified while iterating through 'next'. */ - struct grpc_tcp_listener *sibling; - int is_sibling; -}; - /* the overall server */ struct grpc_tcp_server { gpr_refcount refs; @@ -526,11 +500,11 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd, /* If successful, add a listener to s for addr, set *dsmode for the socket, and return the *listener. */ -static grpc_error *add_addr_to_server(grpc_tcp_server *s, - const grpc_resolved_address *addr, - unsigned port_index, unsigned fd_index, - grpc_dualstack_mode *dsmode, - grpc_tcp_listener **listener) { +grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_dualstack_mode *dsmode, + grpc_tcp_listener **listener) { grpc_resolved_address addr4_copy; int fd; grpc_error *err = @@ -545,39 +519,9 @@ static grpc_error *add_addr_to_server(grpc_tcp_server *s, return add_socket_to_server(s, fd, addr, port_index, fd_index, listener); } -/* Bind to "::" to get a port number not used by any address. */ -static grpc_error *get_unused_port(int *port) { - grpc_resolved_address wild; - grpc_sockaddr_make_wildcard6(0, &wild); - grpc_dualstack_mode dsmode; - int fd; - grpc_error *err = - grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd); - if (err != GRPC_ERROR_NONE) { - return err; - } - if (dsmode == GRPC_DSMODE_IPV4) { - grpc_sockaddr_make_wildcard4(0, &wild); - } - if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) { - err = GRPC_OS_ERROR(errno, "bind"); - close(fd); - return err; - } - if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) != - 0) { - err = GRPC_OS_ERROR(errno, "getsockname"); - close(fd); - return err; - } - close(fd); - *port = grpc_sockaddr_get_port(&wild); - return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE; -} - /* Return the listener in s with address addr or NULL. */ -static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s, - grpc_resolved_address *addr) { +grpc_tcp_listener *grpc_tcp_server_find_listener_with_addr( + grpc_tcp_server *s, grpc_resolved_address *addr) { grpc_tcp_listener *l; gpr_mu_lock(&s->mu); for (l = s->head; l != NULL; l = l->next) { @@ -592,108 +536,6 @@ static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s, return l; } -/* Get all addresses assigned to network interfaces on the machine and create a - listener for each. requested_port is the port to use for every listener, or 0 - to select one random port that will be used for every listener. Set *out_port - to the port selected. Return GRPC_ERROR_NONE only if all listeners were - added. */ -static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s, - unsigned port_index, - int requested_port, - int *out_port) { -#ifndef GRPC_HAVE_IFADDRS - return GRPC_ERROR_CREATE("no ifaddrs available"); -#else /* ifndef GRPC_HAVE_IFADDRS */ - struct ifaddrs *ifa = NULL; - struct ifaddrs *ifa_it; - unsigned fd_index = 0; - grpc_tcp_listener *sp = NULL; - grpc_error *err = GRPC_ERROR_NONE; - if (requested_port == 0) { - /* Note: There could be a race where some local addrs can listen on the - selected port and some can't. The sane way to handle this would be to - retry by recreating the whole grpc_tcp_server. Backing out individual - listeners and orphaning the FDs looks like too much trouble. */ - if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) { - return err; - } else if (requested_port <= 0) { - return GRPC_ERROR_CREATE("Bad get_unused_port()"); - } - gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port); - } - if (getifaddrs(&ifa) != 0 || ifa == NULL) { - return GRPC_OS_ERROR(errno, "getifaddrs"); - } - for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) { - grpc_resolved_address addr; - char *addr_str = NULL; - grpc_dualstack_mode dsmode; - grpc_tcp_listener *new_sp = NULL; - const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : ""); - if (ifa_it->ifa_addr == NULL) { - continue; - } else if (ifa_it->ifa_addr->sa_family == AF_INET) { - addr.len = sizeof(struct sockaddr_in); - } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { - addr.len = sizeof(struct sockaddr_in6); - } else { - continue; - } - memcpy(addr.addr, ifa_it->ifa_addr, addr.len); - if (!grpc_sockaddr_set_port(&addr, requested_port)) { - /* Should never happen, because we check sa_family above. */ - err = GRPC_ERROR_CREATE("Failed to set port"); - break; - } - if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) { - addr_str = gpr_strdup(""); - } - gpr_log(GPR_DEBUG, - "Adding local addr from interface %s flags 0x%x to server: %s", - ifa_name, ifa_it->ifa_flags, addr_str); - /* We could have multiple interfaces with the same address (e.g., bonding), - so look for duplicates. */ - if (find_listener_with_addr(s, &addr) != NULL) { - gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, - ifa_name); - gpr_free(addr_str); - continue; - } - if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode, - &new_sp)) != GRPC_ERROR_NONE) { - char *err_str = NULL; - grpc_error *root_err; - if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) { - err_str = gpr_strdup("Failed to add listener"); - } - root_err = GRPC_ERROR_CREATE(err_str); - gpr_free(err_str); - gpr_free(addr_str); - err = grpc_error_add_child(root_err, err); - break; - } else { - GPR_ASSERT(requested_port == new_sp->port); - ++fd_index; - if (sp != NULL) { - new_sp->is_sibling = 1; - sp->sibling = new_sp; - } - sp = new_sp; - } - gpr_free(addr_str); - } - freeifaddrs(ifa); - if (err != GRPC_ERROR_NONE) { - return err; - } else if (sp == NULL) { - return GRPC_ERROR_CREATE("No local addresses"); - } else { - *out_port = sp->port; - return GRPC_ERROR_NONE; - } -#endif /* ifndef GRPC_HAVE_IFADDRS */ -} - /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, unsigned port_index, @@ -709,17 +551,15 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, grpc_error *v4_err = GRPC_ERROR_NONE; *out_port = -1; -#ifdef GRPC_HAVE_IFADDRS - if (s->expand_wildcard_addrs) { - return add_all_local_addrs_to_server(s, port_index, requested_port, - out_port); + if (grpc_tcp_server_have_ifaddrs() && s->expand_wildcard_addrs) { + return grpc_tcp_server_add_all_local_addrs(s, port_index, requested_port, + out_port); } -#endif /* GRPC_HAVE_IFADDRS */ grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6); /* Try listening on IPv6 first. */ - if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode, - &sp)) == GRPC_ERROR_NONE) { + if ((v6_err = grpc_tcp_server_add_addr(s, &wild6, port_index, fd_index, + &dsmode, &sp)) == GRPC_ERROR_NONE) { ++fd_index; requested_port = *out_port = sp->port; if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) { @@ -728,8 +568,8 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, } /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */ grpc_sockaddr_set_port(&wild4, requested_port); - if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode, - &sp2)) == GRPC_ERROR_NONE) { + if ((v4_err = grpc_tcp_server_add_addr(s, &wild4, port_index, fd_index, + &dsmode, &sp2)) == GRPC_ERROR_NONE) { *out_port = sp2->port; if (sp != NULL) { sp2->is_sibling = 1; @@ -839,7 +679,7 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { addr = &addr6_v4mapped; } - if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) == + if ((err = grpc_tcp_server_add_addr(s, addr, port_index, 0, &dsmode, &sp)) == GRPC_ERROR_NONE) { *out_port = sp->port; } diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h new file mode 100644 index 00000000000..d39f9085fda --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix.h @@ -0,0 +1,89 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H +#define GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "src/core/lib/iomgr/tcp_server.h" + +/* one listening port */ +typedef struct grpc_tcp_listener { + int fd; + grpc_fd *emfd; + grpc_tcp_server *server; + grpc_resolved_address addr; + int port; + unsigned port_index; + unsigned fd_index; + grpc_closure read_closure; + grpc_closure destroyed_closure; + struct grpc_tcp_listener *next; + /* sibling is a linked list of all listeners for a given port. add_port and + clone_port place all new listeners in the same sibling list. A member of + the 'sibling' list is also a member of the 'next' list. The head of each + sibling list has is_sibling==0, and subsequent members of sibling lists + have is_sibling==1. is_sibling allows separate sibling lists to be + identified while iterating through 'next'. */ + struct grpc_tcp_listener *sibling; + int is_sibling; +} grpc_tcp_listener; + +/* If successful, add a listener to \a s for \a addr, set \a dsmode for the + socket, and return the \a listener. */ +grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_dualstack_mode *dsmode, + grpc_tcp_listener **listener); + +/* Return the listener in \a s with address \a addr or NULL. */ +grpc_tcp_listener *grpc_tcp_server_find_listener_with_addr( + grpc_tcp_server *s, grpc_resolved_address *addr); + +/* Get all addresses assigned to network interfaces on the machine and create a + listener for each. requested_port is the port to use for every listener, or 0 + to select one random port that will be used for every listener. Set *out_port + to the port selected. Return GRPC_ERROR_NONE only if all listeners were + added. */ +grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, + unsigned port_index, + int requested_port, + int *out_port); + +/* Ruturn true if the platform supports ifaddrs */ +bool grpc_tcp_server_have_ifaddrs(void); + +#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H */ diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c new file mode 100644 index 00000000000..05eb96f73ed --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c @@ -0,0 +1,178 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_HAVE_IFADDRS + +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" + +/* Bind to "::" to get a port number not used by any address. */ +static grpc_error *get_unused_port(int *port) { + grpc_resolved_address wild; + grpc_sockaddr_make_wildcard6(0, &wild); + grpc_dualstack_mode dsmode; + int fd; + grpc_error *err = + grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd); + if (err != GRPC_ERROR_NONE) { + return err; + } + if (dsmode == GRPC_DSMODE_IPV4) { + grpc_sockaddr_make_wildcard4(0, &wild); + } + if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) { + err = GRPC_OS_ERROR(errno, "bind"); + close(fd); + return err; + } + if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) != + 0) { + err = GRPC_OS_ERROR(errno, "getsockname"); + close(fd); + return err; + } + close(fd); + *port = grpc_sockaddr_get_port(&wild); + return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE; +} + +grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, + unsigned port_index, + int requested_port, + int *out_port) { + struct ifaddrs *ifa = NULL; + struct ifaddrs *ifa_it; + unsigned fd_index = 0; + grpc_tcp_listener *sp = NULL; + grpc_error *err = GRPC_ERROR_NONE; + if (requested_port == 0) { + /* Note: There could be a race where some local addrs can listen on the + selected port and some can't. The sane way to handle this would be to + retry by recreating the whole grpc_tcp_server. Backing out individual + listeners and orphaning the FDs looks like too much trouble. */ + if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) { + return err; + } else if (requested_port <= 0) { + return GRPC_ERROR_CREATE("Bad get_unused_port()"); + } + gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port); + } + if (getifaddrs(&ifa) != 0 || ifa == NULL) { + return GRPC_OS_ERROR(errno, "getifaddrs"); + } + for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) { + grpc_resolved_address addr; + char *addr_str = NULL; + grpc_dualstack_mode dsmode; + grpc_tcp_listener *new_sp = NULL; + const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : ""); + if (ifa_it->ifa_addr == NULL) { + continue; + } else if (ifa_it->ifa_addr->sa_family == AF_INET) { + addr.len = sizeof(struct sockaddr_in); + } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { + addr.len = sizeof(struct sockaddr_in6); + } else { + continue; + } + memcpy(addr.addr, ifa_it->ifa_addr, addr.len); + if (!grpc_sockaddr_set_port(&addr, requested_port)) { + /* Should never happen, because we check sa_family above. */ + err = GRPC_ERROR_CREATE("Failed to set port"); + break; + } + if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) { + addr_str = gpr_strdup(""); + } + gpr_log(GPR_DEBUG, + "Adding local addr from interface %s flags 0x%x to server: %s", + ifa_name, ifa_it->ifa_flags, addr_str); + /* We could have multiple interfaces with the same address (e.g., bonding), + so look for duplicates. */ + if (grpc_tcp_server_find_listener_with_addr(s, &addr) != NULL) { + gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, + ifa_name); + gpr_free(addr_str); + continue; + } + if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode, + &new_sp)) != GRPC_ERROR_NONE) { + char *err_str = NULL; + grpc_error *root_err; + if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) { + err_str = gpr_strdup("Failed to add listener"); + } + root_err = GRPC_ERROR_CREATE(err_str); + gpr_free(err_str); + gpr_free(addr_str); + err = grpc_error_add_child(root_err, err); + break; + } else { + GPR_ASSERT(requested_port == new_sp->port); + ++fd_index; + if (sp != NULL) { + new_sp->is_sibling = 1; + sp->sibling = new_sp; + } + sp = new_sp; + } + gpr_free(addr_str); + } + freeifaddrs(ifa); + if (err != GRPC_ERROR_NONE) { + return err; + } else if (sp == NULL) { + return GRPC_ERROR_CREATE("No local addresses"); + } else { + *out_port = sp->port; + return GRPC_ERROR_NONE; + } +} + +bool grpc_tcp_server_have_ifaddrs(void) { return true; } + +#endif /* GRPC_HAVE_IFADDRS */ diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c new file mode 100644 index 00000000000..fb21d62d053 --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c @@ -0,0 +1,49 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#ifndef GRPC_HAVE_IFADDRS + +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" + +grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, + unsigned port_index, + int requested_port, + int *out_port) { + return GRPC_ERROR_CREATE("no ifaddrs available"); +} + +bool grpc_tcp_server_have_ifaddrs(void) { return false; } + +#endif /* ifndef GRPC_HAVE_IFADDRS */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index a9f20e6d2a8..00b2b8f9026 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -134,6 +134,8 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', 'src/core/lib/iomgr/tcp_server_windows.c', 'src/core/lib/iomgr/tcp_uv.c', diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 131a0134519..f9e4775b738 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1130,6 +1130,9 @@ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_posix.h \ src/core/lib/iomgr/tcp_server.h \ src/core/lib/iomgr/tcp_server_posix.c \ +src/core/lib/iomgr/tcp_server_utils_posix.h \ +src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ +src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ src/core/lib/iomgr/tcp_server_windows.c \ src/core/lib/iomgr/tcp_uv.c \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 767c2b2e368..38fe87ac463 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -7456,6 +7456,7 @@ "src/core/lib/iomgr/tcp_client_posix.h", "src/core/lib/iomgr/tcp_posix.h", "src/core/lib/iomgr/tcp_server.h", + "src/core/lib/iomgr/tcp_server_utils_posix.h", "src/core/lib/iomgr/tcp_uv.h", "src/core/lib/iomgr/tcp_windows.h", "src/core/lib/iomgr/time_averaged_stats.h", @@ -7636,6 +7637,9 @@ "src/core/lib/iomgr/tcp_posix.h", "src/core/lib/iomgr/tcp_server.h", "src/core/lib/iomgr/tcp_server_posix.c", + "src/core/lib/iomgr/tcp_server_utils_posix.h", + "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", + "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", "src/core/lib/iomgr/tcp_server_uv.c", "src/core/lib/iomgr/tcp_server_windows.c", "src/core/lib/iomgr/tcp_uv.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index fde60be3e20..7b48dfbf597 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -357,6 +357,7 @@ + @@ -618,6 +619,10 @@ + + + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 8edbbc22bed..8ba8a4f8fb9 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -181,6 +181,12 @@ src\core\lib\iomgr + + src\core\lib\iomgr + + + src\core\lib\iomgr + src\core\lib\iomgr @@ -944,6 +950,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index e7c9fb71f33..d078db1c3c7 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -252,6 +252,7 @@ + @@ -461,6 +462,10 @@ + + + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 3d36948aaef..9e2d817143e 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -238,6 +238,12 @@ src\core\lib\iomgr + + src\core\lib\iomgr + + + src\core\lib\iomgr + src\core\lib\iomgr @@ -728,6 +734,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 22f4740b8fa..b6f10b3d7c1 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -347,6 +347,7 @@ + @@ -585,6 +586,10 @@ + + + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 5021cb47d8d..03662d4044c 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -184,6 +184,12 @@ src\core\lib\iomgr + + src\core\lib\iomgr + + + src\core\lib\iomgr + src\core\lib\iomgr @@ -854,6 +860,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr From 68745bbf8a0193a8a2c2691281365a1e9d488863 Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Tue, 14 Mar 2017 17:51:07 -0700 Subject: [PATCH 4/4] Resolve dependency issues --- BUILD | 1 + CMakeLists.txt | 5 + Makefile | 5 + binding.gyp | 1 + build.yaml | 1 + config.m4 | 1 + gRPC-Core.podspec | 1 + grpc.gemspec | 1 + package.xml | 1 + src/core/lib/iomgr/tcp_server_posix.c | 229 +----------------- src/core/lib/iomgr/tcp_server_utils_posix.h | 53 +++- .../lib/iomgr/tcp_server_utils_posix_common.c | 220 +++++++++++++++++ .../iomgr/tcp_server_utils_posix_ifaddrs.c | 19 +- .../iomgr/tcp_server_utils_posix_noifaddrs.c | 4 +- src/python/grpcio/grpc_core_dependencies.py | 1 + tools/doxygen/Doxyfile.core.internal | 1 + .../generated/sources_and_headers.json | 1 + vsprojects/vcxproj/grpc/grpc.vcxproj | 2 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 + .../grpc_test_util/grpc_test_util.vcxproj | 2 + .../grpc_test_util.vcxproj.filters | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj | 2 + .../grpc_unsecure.vcxproj.filters | 3 + 23 files changed, 325 insertions(+), 235 deletions(-) create mode 100644 src/core/lib/iomgr/tcp_server_utils_posix_common.c diff --git a/BUILD b/BUILD index dc6431484e3..371ab200d22 100644 --- a/BUILD +++ b/BUILD @@ -481,6 +481,7 @@ grpc_cc_library( "src/core/lib/iomgr/tcp_client_windows.c", "src/core/lib/iomgr/tcp_posix.c", "src/core/lib/iomgr/tcp_server_posix.c", + "src/core/lib/iomgr/tcp_server_utils_posix_common.c", "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", "src/core/lib/iomgr/tcp_server_uv.c", diff --git a/CMakeLists.txt b/CMakeLists.txt index cfc4555834a..c7001aa721c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -914,6 +914,7 @@ add_library(grpc src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c @@ -1225,6 +1226,7 @@ add_library(grpc_cronet src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c @@ -1527,6 +1529,7 @@ add_library(grpc_test_util src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c @@ -1775,6 +1778,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c @@ -2384,6 +2388,7 @@ add_library(grpc++_cronet src/core/lib/iomgr/tcp_client_windows.c src/core/lib/iomgr/tcp_posix.c src/core/lib/iomgr/tcp_server_posix.c + src/core/lib/iomgr/tcp_server_utils_posix_common.c src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c src/core/lib/iomgr/tcp_server_uv.c diff --git a/Makefile b/Makefile index 14c5a36c957..e31b7514e1d 100644 --- a/Makefile +++ b/Makefile @@ -2799,6 +2799,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ @@ -3113,6 +3114,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ @@ -3418,6 +3420,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ @@ -3646,6 +3649,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ @@ -4257,6 +4261,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ diff --git a/binding.gyp b/binding.gyp index ec21a97806f..96843c0d6b7 100644 --- a/binding.gyp +++ b/binding.gyp @@ -667,6 +667,7 @@ 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', diff --git a/build.yaml b/build.yaml index 36817a55067..75bacbde632 100644 --- a/build.yaml +++ b/build.yaml @@ -338,6 +338,7 @@ filegroups: - src/core/lib/iomgr/tcp_client_windows.c - src/core/lib/iomgr/tcp_posix.c - src/core/lib/iomgr/tcp_server_posix.c + - src/core/lib/iomgr/tcp_server_utils_posix_common.c - src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c - src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c - src/core/lib/iomgr/tcp_server_uv.c diff --git a/config.m4 b/config.m4 index 181e44c52c8..6d6f9419cd1 100644 --- a/config.m4 +++ b/config.m4 @@ -140,6 +140,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/tcp_client_windows.c \ src/core/lib/iomgr/tcp_posix.c \ src/core/lib/iomgr/tcp_server_posix.c \ + src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 1d002247d4b..16c17c2bf6e 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -509,6 +509,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', diff --git a/grpc.gemspec b/grpc.gemspec index edc08cb9b9a..da9535ff469 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -426,6 +426,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/tcp_client_windows.c ) s.files += %w( src/core/lib/iomgr/tcp_posix.c ) s.files += %w( src/core/lib/iomgr/tcp_server_posix.c ) + s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_common.c ) s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c ) s.files += %w( src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c ) s.files += %w( src/core/lib/iomgr/tcp_server_uv.c ) diff --git a/package.xml b/package.xml index 21eeee4d3ef..aeeb0d59867 100644 --- a/package.xml +++ b/package.xml @@ -435,6 +435,7 @@ + diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 1e9e854d6b5..b3644518f54 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -44,10 +44,8 @@ #include #include -#include #include #include -#include #include #include #include @@ -70,56 +68,6 @@ #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" -#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 - -static gpr_once s_init_max_accept_queue_size; -static int s_max_accept_queue_size; - -/* the overall server */ -struct grpc_tcp_server { - gpr_refcount refs; - /* Called whenever accept() succeeds on a server port. */ - grpc_tcp_server_cb on_accept_cb; - void *on_accept_cb_arg; - - gpr_mu mu; - - /* active port count: how many ports are actually still listening */ - size_t active_ports; - /* destroyed port count: how many ports are completely destroyed */ - size_t destroyed_ports; - - /* is this server shutting down? */ - bool shutdown; - /* have listeners been shutdown? */ - bool shutdown_listeners; - /* use SO_REUSEPORT */ - bool so_reuseport; - /* expand wildcard addresses to a list of all local addresses */ - bool expand_wildcard_addrs; - - /* linked list of server ports */ - grpc_tcp_listener *head; - grpc_tcp_listener *tail; - unsigned nports; - - /* List of closures passed to shutdown_starting_add(). */ - grpc_closure_list shutdown_starting; - - /* shutdown callback */ - grpc_closure *shutdown_complete; - - /* all pollsets interested in new connections */ - grpc_pollset **pollsets; - /* number of pollsets in the pollsets array */ - size_t pollset_count; - - /* next pollset to assign a channel to */ - gpr_atm next_pollset_to_assign; - - grpc_resource_quota *resource_quota; -}; - static gpr_once check_init = GPR_ONCE_INIT; static bool has_so_reuseport = false; @@ -278,99 +226,6 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { } } -/* get max listen queue size on linux */ -static void init_max_accept_queue_size(void) { - int n = SOMAXCONN; - char buf[64]; - FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r"); - if (fp == NULL) { - /* 2.4 kernel. */ - s_max_accept_queue_size = SOMAXCONN; - return; - } - if (fgets(buf, sizeof buf, fp)) { - char *end; - long i = strtol(buf, &end, 10); - if (i > 0 && i <= INT_MAX && end && *end == 0) { - n = (int)i; - } - } - fclose(fp); - s_max_accept_queue_size = n; - - if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) { - gpr_log(GPR_INFO, - "Suspiciously small accept queue (%d) will probably lead to " - "connection drops", - s_max_accept_queue_size); - } -} - -static int get_max_accept_queue_size(void) { - gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size); - return s_max_accept_queue_size; -} - -/* Prepare a recently-created socket for listening. */ -static grpc_error *prepare_socket(int fd, const grpc_resolved_address *addr, - bool so_reuseport, int *port) { - grpc_resolved_address sockname_temp; - grpc_error *err = GRPC_ERROR_NONE; - - GPR_ASSERT(fd >= 0); - - if (so_reuseport && !grpc_is_unix_socket(addr)) { - err = grpc_set_socket_reuse_port(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - } - - err = grpc_set_socket_nonblocking(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_cloexec(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - if (!grpc_is_unix_socket(addr)) { - err = grpc_set_socket_low_latency(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_reuse_addr(fd, 1); - if (err != GRPC_ERROR_NONE) goto error; - } - err = grpc_set_socket_no_sigpipe_if_possible(fd); - if (err != GRPC_ERROR_NONE) goto error; - - GPR_ASSERT(addr->len < ~(socklen_t)0); - if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) { - err = GRPC_OS_ERROR(errno, "bind"); - goto error; - } - - if (listen(fd, get_max_accept_queue_size()) < 0) { - err = GRPC_OS_ERROR(errno, "listen"); - goto error; - } - - sockname_temp.len = sizeof(struct sockaddr_storage); - - if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, - (socklen_t *)&sockname_temp.len) < 0) { - err = GRPC_OS_ERROR(errno, "getsockname"); - goto error; - } - - *port = grpc_sockaddr_get_port(&sockname_temp); - return GRPC_ERROR_NONE; - -error: - GPR_ASSERT(err != GRPC_ERROR_NONE); - if (fd >= 0) { - close(fd); - } - grpc_error *ret = grpc_error_set_int( - GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1), - GRPC_ERROR_INT_FD, fd); - GRPC_ERROR_UNREF(err); - return ret; -} - /* event manager callback when reads are ready */ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { grpc_tcp_listener *sp = arg; @@ -454,88 +309,6 @@ error: } } -static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd, - const grpc_resolved_address *addr, - unsigned port_index, unsigned fd_index, - grpc_tcp_listener **listener) { - grpc_tcp_listener *sp = NULL; - int port = -1; - char *addr_str; - char *name; - - grpc_error *err = prepare_socket(fd, addr, s->so_reuseport, &port); - if (err == GRPC_ERROR_NONE) { - GPR_ASSERT(port > 0); - grpc_sockaddr_to_string(&addr_str, addr, 1); - gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); - gpr_mu_lock(&s->mu); - s->nports++; - GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); - sp = gpr_malloc(sizeof(grpc_tcp_listener)); - sp->next = NULL; - if (s->head == NULL) { - s->head = sp; - } else { - s->tail->next = sp; - } - s->tail = sp; - sp->server = s; - sp->fd = fd; - sp->emfd = grpc_fd_create(fd, name); - memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); - sp->port = port; - sp->port_index = port_index; - sp->fd_index = fd_index; - sp->is_sibling = 0; - sp->sibling = NULL; - GPR_ASSERT(sp->emfd); - gpr_mu_unlock(&s->mu); - gpr_free(addr_str); - gpr_free(name); - } - - *listener = sp; - return err; -} - -/* If successful, add a listener to s for addr, set *dsmode for the socket, and - return the *listener. */ -grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, - const grpc_resolved_address *addr, - unsigned port_index, unsigned fd_index, - grpc_dualstack_mode *dsmode, - grpc_tcp_listener **listener) { - grpc_resolved_address addr4_copy; - int fd; - grpc_error *err = - grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd); - if (err != GRPC_ERROR_NONE) { - return err; - } - if (*dsmode == GRPC_DSMODE_IPV4 && - grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { - addr = &addr4_copy; - } - return add_socket_to_server(s, fd, addr, port_index, fd_index, listener); -} - -/* Return the listener in s with address addr or NULL. */ -grpc_tcp_listener *grpc_tcp_server_find_listener_with_addr( - grpc_tcp_server *s, grpc_resolved_address *addr) { - grpc_tcp_listener *l; - gpr_mu_lock(&s->mu); - for (l = s->head; l != NULL; l = l->next) { - if (l->addr.len != addr->len) { - continue; - } - if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) { - break; - } - } - gpr_mu_unlock(&s->mu); - return l; -} - /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, unsigned port_index, @@ -607,7 +380,7 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) { err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode, &fd); if (err != GRPC_ERROR_NONE) return err; - err = prepare_socket(fd, &listener->addr, true, &port); + err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port); if (err != GRPC_ERROR_NONE) return err; listener->server->nports++; grpc_sockaddr_to_string(&addr_str, &listener->addr, 1); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h index d39f9085fda..f5dc8532f9f 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix.h +++ b/src/core/lib/iomgr/tcp_server_utils_posix.h @@ -61,6 +61,51 @@ typedef struct grpc_tcp_listener { int is_sibling; } grpc_tcp_listener; +/* the overall server */ +struct grpc_tcp_server { + gpr_refcount refs; + /* Called whenever accept() succeeds on a server port. */ + grpc_tcp_server_cb on_accept_cb; + void *on_accept_cb_arg; + + gpr_mu mu; + + /* active port count: how many ports are actually still listening */ + size_t active_ports; + /* destroyed port count: how many ports are completely destroyed */ + size_t destroyed_ports; + + /* is this server shutting down? */ + bool shutdown; + /* have listeners been shutdown? */ + bool shutdown_listeners; + /* use SO_REUSEPORT */ + bool so_reuseport; + /* expand wildcard addresses to a list of all local addresses */ + bool expand_wildcard_addrs; + + /* linked list of server ports */ + grpc_tcp_listener *head; + grpc_tcp_listener *tail; + unsigned nports; + + /* List of closures passed to shutdown_starting_add(). */ + grpc_closure_list shutdown_starting; + + /* shutdown callback */ + grpc_closure *shutdown_complete; + + /* all pollsets interested in new connections */ + grpc_pollset **pollsets; + /* number of pollsets in the pollsets array */ + size_t pollset_count; + + /* next pollset to assign a channel to */ + gpr_atm next_pollset_to_assign; + + grpc_resource_quota *resource_quota; +}; + /* If successful, add a listener to \a s for \a addr, set \a dsmode for the socket, and return the \a listener. */ grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, @@ -69,10 +114,6 @@ grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, grpc_dualstack_mode *dsmode, grpc_tcp_listener **listener); -/* Return the listener in \a s with address \a addr or NULL. */ -grpc_tcp_listener *grpc_tcp_server_find_listener_with_addr( - grpc_tcp_server *s, grpc_resolved_address *addr); - /* Get all addresses assigned to network interfaces on the machine and create a listener for each. requested_port is the port to use for every listener, or 0 to select one random port that will be used for every listener. Set *out_port @@ -83,6 +124,10 @@ grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, int requested_port, int *out_port); +/* Prepare a recently-created socket for listening. */ +grpc_error *grpc_tcp_server_prepare_socket(int fd, + const grpc_resolved_address *addr, + bool so_reuseport, int *port); /* Ruturn true if the platform supports ifaddrs */ bool grpc_tcp_server_have_ifaddrs(void); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.c b/src/core/lib/iomgr/tcp_server_utils_posix_common.c new file mode 100644 index 00000000000..e45e27d5ab6 --- /dev/null +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.c @@ -0,0 +1,220 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_HAVE_IFADDRS + +#include "src/core/lib/iomgr/tcp_server_utils_posix.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/unix_sockets_posix.h" + +#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 + +static gpr_once s_init_max_accept_queue_size; +static int s_max_accept_queue_size; + +/* get max listen queue size on linux */ +static void init_max_accept_queue_size(void) { + int n = SOMAXCONN; + char buf[64]; + FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r"); + if (fp == NULL) { + /* 2.4 kernel. */ + s_max_accept_queue_size = SOMAXCONN; + return; + } + if (fgets(buf, sizeof buf, fp)) { + char *end; + long i = strtol(buf, &end, 10); + if (i > 0 && i <= INT_MAX && end && *end == 0) { + n = (int)i; + } + } + fclose(fp); + s_max_accept_queue_size = n; + + if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) { + gpr_log(GPR_INFO, + "Suspiciously small accept queue (%d) will probably lead to " + "connection drops", + s_max_accept_queue_size); + } +} + +static int get_max_accept_queue_size(void) { + gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size); + return s_max_accept_queue_size; +} + +static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_tcp_listener **listener) { + grpc_tcp_listener *sp = NULL; + int port = -1; + char *addr_str; + char *name; + + grpc_error *err = + grpc_tcp_server_prepare_socket(fd, addr, s->so_reuseport, &port); + if (err == GRPC_ERROR_NONE) { + GPR_ASSERT(port > 0); + grpc_sockaddr_to_string(&addr_str, addr, 1); + gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); + gpr_mu_lock(&s->mu); + s->nports++; + GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server"); + sp = gpr_malloc(sizeof(grpc_tcp_listener)); + sp->next = NULL; + if (s->head == NULL) { + s->head = sp; + } else { + s->tail->next = sp; + } + s->tail = sp; + sp->server = s; + sp->fd = fd; + sp->emfd = grpc_fd_create(fd, name); + memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); + sp->port = port; + sp->port_index = port_index; + sp->fd_index = fd_index; + sp->is_sibling = 0; + sp->sibling = NULL; + GPR_ASSERT(sp->emfd); + gpr_mu_unlock(&s->mu); + gpr_free(addr_str); + gpr_free(name); + } + + *listener = sp; + return err; +} + +/* If successful, add a listener to s for addr, set *dsmode for the socket, and + return the *listener. */ +grpc_error *grpc_tcp_server_add_addr(grpc_tcp_server *s, + const grpc_resolved_address *addr, + unsigned port_index, unsigned fd_index, + grpc_dualstack_mode *dsmode, + grpc_tcp_listener **listener) { + grpc_resolved_address addr4_copy; + int fd; + grpc_error *err = + grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd); + if (err != GRPC_ERROR_NONE) { + return err; + } + if (*dsmode == GRPC_DSMODE_IPV4 && + grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) { + addr = &addr4_copy; + } + return add_socket_to_server(s, fd, addr, port_index, fd_index, listener); +} + +/* Prepare a recently-created socket for listening. */ +grpc_error *grpc_tcp_server_prepare_socket(int fd, + const grpc_resolved_address *addr, + bool so_reuseport, int *port) { + grpc_resolved_address sockname_temp; + grpc_error *err = GRPC_ERROR_NONE; + + GPR_ASSERT(fd >= 0); + + if (so_reuseport && !grpc_is_unix_socket(addr)) { + err = grpc_set_socket_reuse_port(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + } + + err = grpc_set_socket_nonblocking(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_cloexec(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + if (!grpc_is_unix_socket(addr)) { + err = grpc_set_socket_low_latency(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_reuse_addr(fd, 1); + if (err != GRPC_ERROR_NONE) goto error; + } + err = grpc_set_socket_no_sigpipe_if_possible(fd); + if (err != GRPC_ERROR_NONE) goto error; + + GPR_ASSERT(addr->len < ~(socklen_t)0); + if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) { + err = GRPC_OS_ERROR(errno, "bind"); + goto error; + } + + if (listen(fd, get_max_accept_queue_size()) < 0) { + err = GRPC_OS_ERROR(errno, "listen"); + goto error; + } + + sockname_temp.len = sizeof(struct sockaddr_storage); + + if (getsockname(fd, (struct sockaddr *)sockname_temp.addr, + (socklen_t *)&sockname_temp.len) < 0) { + err = GRPC_OS_ERROR(errno, "getsockname"); + goto error; + } + + *port = grpc_sockaddr_get_port(&sockname_temp); + return GRPC_ERROR_NONE; + +error: + GPR_ASSERT(err != GRPC_ERROR_NONE); + if (fd >= 0) { + close(fd); + } + grpc_error *ret = grpc_error_set_int( + GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1), + GRPC_ERROR_INT_FD, fd); + GRPC_ERROR_UNREF(err); + return ret; +} + +#endif /* GRPC_HAVE_IFADDRS */ diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c index 05eb96f73ed..6354a6bdc10 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c +++ b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c @@ -50,6 +50,23 @@ #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" +/* Return the listener in s with address addr or NULL. */ +static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s, + grpc_resolved_address *addr) { + grpc_tcp_listener *l; + gpr_mu_lock(&s->mu); + for (l = s->head; l != NULL; l = l->next) { + if (l->addr.len != addr->len) { + continue; + } + if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) { + break; + } + } + gpr_mu_unlock(&s->mu); + return l; +} + /* Bind to "::" to get a port number not used by any address. */ static grpc_error *get_unused_port(int *port) { grpc_resolved_address wild; @@ -133,7 +150,7 @@ grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, ifa_name, ifa_it->ifa_flags, addr_str); /* We could have multiple interfaces with the same address (e.g., bonding), so look for duplicates. */ - if (grpc_tcp_server_find_listener_with_addr(s, &addr) != NULL) { + if (find_listener_with_addr(s, &addr) != NULL) { gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, ifa_name); gpr_free(addr_str); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c index fb21d62d053..95c3198be6f 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c +++ b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c @@ -33,7 +33,7 @@ #include "src/core/lib/iomgr/port.h" -#ifndef GRPC_HAVE_IFADDRS +#if defined(GRPC_POSIX_SOCKET) && !defined(GRPC_HAVE_IFADDRS) #include "src/core/lib/iomgr/tcp_server_utils_posix.h" @@ -46,4 +46,4 @@ grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, bool grpc_tcp_server_have_ifaddrs(void) { return false; } -#endif /* ifndef GRPC_HAVE_IFADDRS */ +#endif /* defined(GRPC_POSIX_SOCKET) && !defined(GRPC_HAVE_IFADDRS) */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 00b2b8f9026..ea3a51be13d 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -134,6 +134,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/tcp_client_windows.c', 'src/core/lib/iomgr/tcp_posix.c', 'src/core/lib/iomgr/tcp_server_posix.c', + 'src/core/lib/iomgr/tcp_server_utils_posix_common.c', 'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c', 'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c', 'src/core/lib/iomgr/tcp_server_uv.c', diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index f9e4775b738..a1287cd8942 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1131,6 +1131,7 @@ src/core/lib/iomgr/tcp_posix.h \ src/core/lib/iomgr/tcp_server.h \ src/core/lib/iomgr/tcp_server_posix.c \ src/core/lib/iomgr/tcp_server_utils_posix.h \ +src/core/lib/iomgr/tcp_server_utils_posix_common.c \ src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \ src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \ src/core/lib/iomgr/tcp_server_uv.c \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 38fe87ac463..9ab9836c4bb 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -7638,6 +7638,7 @@ "src/core/lib/iomgr/tcp_server.h", "src/core/lib/iomgr/tcp_server_posix.c", "src/core/lib/iomgr/tcp_server_utils_posix.h", + "src/core/lib/iomgr/tcp_server_utils_posix_common.c", "src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c", "src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c", "src/core/lib/iomgr/tcp_server_uv.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 7b48dfbf597..5e3b027663d 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -619,6 +619,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 8ba8a4f8fb9..d75ca766c0d 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -181,6 +181,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index d078db1c3c7..62969e31acf 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -462,6 +462,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 9e2d817143e..30088101f5f 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -238,6 +238,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index b6f10b3d7c1..11ac8bd4b2b 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -586,6 +586,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 03662d4044c..414e2a50b89 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -184,6 +184,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr