aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/lib/iomgr/socket_utils_common_posix.cc9
-rw-r--r--src/core/lib/iomgr/tcp_client_posix.cc35
-rw-r--r--src/core/lib/iomgr/unix_sockets_posix.cc18
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;
}