aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShukang Zhou <shukang@google.com>2019-08-12 15:31:47 -0700
committerShukang Zhou <shukang@google.com>2019-08-13 00:10:10 +0000
commita5a763290cf4c4510bba6a290eee964f5f6465bb (patch)
tree4ed3f0c1bef9090f5166ab2151dcbcdaaa046518
parent716718820f547216112fe0d37b9a0fbcab74b19f (diff)
downloadgrpc-grpc-a5a763290cf4c4510bba6a290eee964f5f6465bb.tar.gz
[GRPC] Support abstract socket and an connected fd
This CL is an re-implementation of commit 35dd92ca0c464fea9cf41ba7e49e9ab34f361366 while gRPC is being upgraded to 1.22.0. This CL adds special handling for Android Studio Profilers and Transport Pipeline in general. (1) Supports Unix abstract domain socket if the input address starts with prefix "unix:@". For example, "unix:@hidden" indicates an abstract socket of name 'hidden'. Note the name of the abstract socket doesn't include the '@' immediately after "unix:". Abstract socket supports both server and client modes. (2) Supports a GRPC client to use an existing socket if the file descriptor as an integer is provided in the format of "unix:&FD". For example, "unix:&123" indicates a socket of file descriptor '123' exists and is going to be used. Existing socket's file descriptor is supported only in clients. Bug: 138846475 Test: will add unit tests in a follow up CL Change-Id: I433df6eae990253b713b10f42d5acfe920e102f1
-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;
}