diff options
-rw-r--r-- | src/core/lib/iomgr/socket_utils_common_posix.cc | 9 | ||||
-rw-r--r-- | src/core/lib/iomgr/tcp_client_posix.cc | 35 | ||||
-rw-r--r-- | src/core/lib/iomgr/unix_sockets_posix.cc | 18 |
3 files changed, 56 insertions, 6 deletions
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 2101651b33..8db2c67c9e 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -431,7 +431,14 @@ grpc_error* grpc_create_dualstack_socket_using_factory( family = AF_INET; } *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE; - *newfd = create_socket(factory, family, type, protocol); + // Special handling for Android Studio Profilers. + // Check whether a connected fd is already provided by the caller of gRPC. + if (family == AF_UNIX && addr->sa_data[0] == '&') { + // Use the provided connected fd directly. + *newfd = atoi(&addr->sa_data[1]); + } else { + *newfd = create_socket(factory, family, type, protocol); + } return error_for_fd(*newfd, resolved_addr); } diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index ad9d7798d0..c50f4bb871 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -28,6 +28,7 @@ #include <netinet/in.h> #include <string.h> #include <unistd.h> +#include <sys/un.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> @@ -295,13 +296,35 @@ void grpc_tcp_client_create_from_prepared_fd( const grpc_channel_args* channel_args, const grpc_resolved_address* addr, grpc_millis deadline, grpc_endpoint** ep) { const int fd = grpc_fd_wrapped_fd(fdobj); - int err; + int err = 0; async_connect* ac; - do { - err = connect(fd, reinterpret_cast<const grpc_sockaddr*>(addr->addr), - addr->len); - } while (err < 0 && errno == EINTR); + // Special handling for Android Studio Profilers. + // Check Unix-specific socket types. + auto* un = reinterpret_cast<const struct sockaddr_un*>(addr->addr); + if (un->sun_path[0] == '&') { + // A connected fd is provided by the caller of gRPC. + // No need to call connect(). Do nothing here. + } else { + // Make a copy of addr so it can be modified to support abstract socket. + grpc_resolved_address addr_copy = *addr; + auto* un_copy = reinterpret_cast<struct sockaddr_un*>(&addr_copy.addr); + if (un_copy->sun_path[0] == '@') { + // This is a Unix abstract domain socket. Set the first char to '\0'. + un_copy->sun_path[0] = '\0'; + // The length includes the leading '\0' but not the terminating '\0'. + // Not including the terminating null byte to make the socket name easy to + // see and type in shell (e.g., adb forward). + addr_copy.len = + 1 + strlen(&un_copy->sun_path[1]) + sizeof(un_copy->sun_family); + } + do { + err = connect(fd, reinterpret_cast<const grpc_sockaddr*>(addr_copy.addr), + addr_copy.len); + } while (err < 0 && errno == EINTR); + } if (err >= 0) { + // Use addr not addr_copy to obtain the string representation as + // grpc_sockaddr_to_uri(..) considers string null-terminated. char* addr_str = grpc_sockaddr_to_uri(addr); *ep = grpc_tcp_client_create_from_fd(fdobj, channel_args, addr_str); gpr_free(addr_str); @@ -321,6 +344,8 @@ void grpc_tcp_client_create_from_prepared_fd( ac->ep = ep; ac->fd = fdobj; ac->interested_parties = interested_parties; + // Use addr not addr_copy to obtain the string representation as + // grpc_sockaddr_to_uri(..) considers strings null-terminated. ac->addr_str = grpc_sockaddr_to_uri(addr); gpr_mu_init(&ac->mu); ac->refs = 2; diff --git a/src/core/lib/iomgr/unix_sockets_posix.cc b/src/core/lib/iomgr/unix_sockets_posix.cc index 22fcaf57fc..213bc1fa55 100644 --- a/src/core/lib/iomgr/unix_sockets_posix.cc +++ b/src/core/lib/iomgr/unix_sockets_posix.cc @@ -63,6 +63,24 @@ grpc_error* grpc_resolve_unix_domain_address(const char* name, strncpy(un->sun_path, name, sizeof(un->sun_path)); (*addrs)->addrs->len = static_cast<socklen_t>(strlen(un->sun_path) + sizeof(un->sun_family) + 1); + // Special handling for Android Studio Profilers. + // Supports Unix abstract domain socket if the input address is a + // unix socket name and the socket name starts with '@'. For example, + // "unix:@AbstractSocketName". The name of the abstract socket doesn't + // include the '@' in "unix:@". + // + // Note the length of address will be reduce by 1. When GRPC handles a Unix + // socket, it assumes it is a pathname socket that "can be bound to a + // null-terminated filesystem pathname using bind(2)". Therefore, the + // length includes the null byte at the end of the sun_path. But for + // abstract sockets null bytes "have no special significance". We choose + // not to include the terminating null byte to make the socket name easy to + // see and type in shell (e.g., adb forward). See more details about lengths + // at http://man7.org/linux/man-pages/man7/unix.7.html . + if (un->sun_path[0] == '@') { + un->sun_path[0] = '\0'; + (*addrs)->addrs->len--; + } return GRPC_ERROR_NONE; } |