grpcio-sys: add vsock support into core grpcio-sys crate
This patch allows rust code to establish GRPC connections over vsock.
Intended for use with resourced and borealis. Patch is targetted
specifically for version grpcio-sys-0.9.1+1.38.0, where 1.38.0
corresponds to the libgrpc version in use.
BUG=b:209841376
TEST=vendor.py; emerge-brya dev-rust/third-party-crates-src; link
custom grpcio-sys with resourced/vm_grpc
Change-Id: I5a65941861a5da47a681a74197238c4e937aed27
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/rust_crates/+/4098236
Auto-Submit: Shah Hossain <shahadath@google.com>
Commit-Queue: Shah Hossain <shahadath@google.com>
Tested-by: Shah Hossain <shahadath@google.com>
Reviewed-by: Allen Webb <allenwebb@google.com>
diff --git a/patches/grpcio-sys-0.9.1+1.38.0/001-grpc-vsock-support.patch b/patches/grpcio-sys-0.9.1+1.38.0/001-grpc-vsock-support.patch
new file mode 100644
index 0000000..b8bcfe0
--- /dev/null
+++ b/patches/grpcio-sys-0.9.1+1.38.0/001-grpc-vsock-support.patch
@@ -0,0 +1,357 @@
+commit c77ea4e57554384f0a2ddb6bd24bb1e7d4e0bdb7
+Author: Shah Hossain <shahadath@google.com>
+Date: Wed Sep 7 23:57:56 2022 +0000
+
+ Add vsock support to grpc library
+
+ Add support for client and server vsock sockets in core grpc library.
+
+TODO(b/262411696): Link grpcio-sys library to system libgrpc instead of building and linking a new version.
+
+diff --git a/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc b/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
+index 46efbb0..b651e06 100644
+--- a/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
++++ b/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
+@@ -140,6 +140,23 @@ class IPv6ResolverFactory : public ResolverFactory {
+ };
+
+ #ifdef GRPC_HAVE_UNIX_SOCKET
++class VsockResolverFactory : public ResolverFactory {
++ public:
++ bool IsValidUri(const URI& uri) const override {
++ return ParseUri(uri, grpc_parse_vsock, nullptr);
++ }
++
++ OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
++ return CreateSockaddrResolver(std::move(args), grpc_parse_vsock);
++ }
++
++ std::string GetDefaultAuthority(const URI& /*uri*/) const override {
++ return "localhost";
++ }
++
++ const char* scheme() const override { return "vsock"; }
++};
++
+ class UnixResolverFactory : public ResolverFactory {
+ public:
+ bool IsValidUri(const URI& uri) const override {
+@@ -185,6 +202,8 @@ void grpc_resolver_sockaddr_init() {
+ grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
+ absl::make_unique<grpc_core::IPv6ResolverFactory>());
+ #ifdef GRPC_HAVE_UNIX_SOCKET
++ grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
++ absl::make_unique<grpc_core::VsockResolverFactory>());
+ grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
+ absl::make_unique<grpc_core::UnixResolverFactory>());
+ grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
+diff --git a/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc b/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc
+index 911af03..ad255db 100644
+--- a/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc
++++ b/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc
+@@ -57,6 +57,7 @@ namespace grpc_core {
+ namespace {
+
+ const char kUnixUriPrefix[] = "unix:";
++const char kVsockPrefix[] = "vsock:";
+ const char kUnixAbstractUriPrefix[] = "unix-abstract:";
+
+ class Chttp2ServerListener : public Server::ListenerInterface {
+@@ -837,6 +838,9 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr,
+ if (absl::StartsWith(addr, kUnixUriPrefix)) {
+ error = grpc_resolve_unix_domain_address(
+ addr + sizeof(kUnixUriPrefix) - 1, &resolved);
++ } else if (absl::StartsWith(addr, kVsockPrefix)) {
++ error = grpc_resolve_vsock_address(addr + sizeof(kVsockPrefix) - 1,
++ &resolved);
+ } else if (absl::StartsWith(addr, kUnixAbstractUriPrefix)) {
+ error = grpc_resolve_unix_abstract_domain_address(
+ addr + sizeof(kUnixAbstractUriPrefix) - 1, &resolved);
+diff --git a/grpc/src/core/lib/address_utils/parse_address.cc b/grpc/src/core/lib/address_utils/parse_address.cc
+index 98dd1bc..e706703 100644
+--- a/grpc/src/core/lib/address_utils/parse_address.cc
++++ b/grpc/src/core/lib/address_utils/parse_address.cc
+@@ -23,6 +23,8 @@
+ #include <stdio.h>
+ #include <string.h>
+ #ifdef GRPC_HAVE_UNIX_SOCKET
++#include <linux/vm_sockets.h>
++#include <sys/socket.h>
+ #include <sys/un.h>
+ #endif
+ #ifdef GRPC_POSIX_SOCKET
+@@ -45,6 +47,23 @@
+
+ #ifdef GRPC_HAVE_UNIX_SOCKET
+
++bool grpc_parse_vsock(const grpc_core::URI& uri,
++ grpc_resolved_address* resolved_addr) {
++ if (uri.scheme() != "vsock") {
++ gpr_log(GPR_ERROR, "Expected 'vsock' scheme, got '%s'",
++ uri.scheme().c_str());
++ return false;
++ }
++ grpc_error_handle error =
++ grpc_core::VsockaddrPopulate(uri.path(), resolved_addr);
++ if (error != GRPC_ERROR_NONE) {
++ gpr_log(GPR_ERROR, "%s", grpc_error_std_string(error).c_str());
++ GRPC_ERROR_UNREF(error);
++ return false;
++ }
++ return true;
++}
++
+ bool grpc_parse_unix(const grpc_core::URI& uri,
+ grpc_resolved_address* resolved_addr) {
+ if (uri.scheme() != "unix") {
+@@ -81,6 +100,30 @@ bool grpc_parse_unix_abstract(const grpc_core::URI& uri,
+
+ namespace grpc_core {
+
++grpc_error_handle VsockaddrPopulate(absl::string_view path,
++ grpc_resolved_address* resolved_addr) {
++ struct sockaddr_vm* vm =
++ reinterpret_cast<struct sockaddr_vm*>(resolved_addr->addr);
++ unsigned int cid;
++ unsigned int port;
++
++ // TODO: `path.data()` is scary, assumes the underlying string is null
++ // terminated. Maybe use `std::string(path).data()` to make a copy.
++ if (sscanf(path.data(), "%u:%u", &cid, &port) != 2) {
++ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
++ "Failed to parse cid:port pair");
++ }
++
++ vm->svm_family = AF_VSOCK;
++ vm->svm_reserved1 = 0;
++ vm->svm_cid = cid;
++ vm->svm_port = port;
++ //vm->svm_flags = 0;
++ memset(vm->svm_zero, '\0', sizeof(vm->svm_zero));
++ resolved_addr->len = static_cast<socklen_t>(sizeof(*vm));
++ return GRPC_ERROR_NONE;
++}
++
+ grpc_error_handle UnixSockaddrPopulate(absl::string_view path,
+ grpc_resolved_address* resolved_addr) {
+ struct sockaddr_un* un =
+@@ -308,6 +351,10 @@ bool grpc_parse_uri(const grpc_core::URI& uri,
+ if (uri.scheme() == "ipv6") {
+ return grpc_parse_ipv6(uri, resolved_addr);
+ }
++ if (uri.scheme() == "vsock") {
++ return grpc_parse_vsock(uri, resolved_addr);
++ }
++
+ gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri.scheme().c_str());
+ return false;
+ }
+diff --git a/grpc/src/core/lib/address_utils/parse_address.h b/grpc/src/core/lib/address_utils/parse_address.h
+index 92409b7..c182fb8 100644
+--- a/grpc/src/core/lib/address_utils/parse_address.h
++++ b/grpc/src/core/lib/address_utils/parse_address.h
+@@ -28,6 +28,11 @@
+ #include "src/core/lib/iomgr/resolve_address.h"
+ #include "src/core/lib/uri/uri_parser.h"
+
++/** Populate \a addr and \a len from \a uri, whose path is expected to contain a
++ * vsock specification. Returns true upon success. */
++bool grpc_parse_vsock(const grpc_core::URI& uri,
++ grpc_resolved_address* resolved_addr);
++
+ /** Populate \a resolved_addr from \a uri, whose path is expected to contain a
+ * unix socket path. Returns true upon success. */
+ bool grpc_parse_unix(const grpc_core::URI& uri,
+@@ -63,6 +68,10 @@ uint16_t grpc_strhtons(const char* port);
+
+ namespace grpc_core {
+
++/** Populate \a resolved_addr to be a vsock socket at |path| */
++grpc_error_handle VsockaddrPopulate(absl::string_view path,
++ grpc_resolved_address* resolved_addr);
++
+ /** Populate \a resolved_addr to be a unix socket at |path| */
+ grpc_error_handle UnixSockaddrPopulate(absl::string_view path,
+ grpc_resolved_address* resolved_addr);
+diff --git a/grpc/src/core/lib/address_utils/sockaddr_utils.cc b/grpc/src/core/lib/address_utils/sockaddr_utils.cc
+index 888cd1a..26d4530 100644
+--- a/grpc/src/core/lib/address_utils/sockaddr_utils.cc
++++ b/grpc/src/core/lib/address_utils/sockaddr_utils.cc
+@@ -226,7 +226,10 @@ std::string grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) {
+ const char* scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
+ if (scheme == nullptr || strcmp("unix", scheme) == 0) {
+ return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
++ } else if (strcmp("vsock", scheme) == 0) {
++ return grpc_sockaddr_to_vsock(resolved_addr);
+ }
++
+ std::string path =
+ grpc_sockaddr_to_string(resolved_addr, false /* normalize */);
+ std::string uri_str;
+@@ -240,6 +243,7 @@ const char* grpc_sockaddr_get_uri_scheme(
+ const grpc_resolved_address* resolved_addr) {
+ const grpc_sockaddr* addr =
+ reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
++
+ switch (addr->sa_family) {
+ case GRPC_AF_INET:
+ return "ipv4";
+@@ -247,6 +251,8 @@ const char* grpc_sockaddr_get_uri_scheme(
+ return "ipv6";
+ case GRPC_AF_UNIX:
+ return "unix";
++ case GRPC_AF_VSOCK:
++ return "vsock";
+ }
+ return nullptr;
+ }
+@@ -268,7 +274,8 @@ int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) {
+ return grpc_ntohs(
+ (reinterpret_cast<const grpc_sockaddr_in6*>(addr))->sin6_port);
+ default:
+- if (grpc_is_unix_socket(resolved_addr)) {
++ if (grpc_is_unix_socket(resolved_addr) ||
++ grpc_is_vsock_socket(resolved_addr)) {
+ return 1;
+ }
+ gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port",
+diff --git a/grpc/src/core/lib/iomgr/sockaddr_posix.h b/grpc/src/core/lib/iomgr/sockaddr_posix.h
+index 3cedd90..549a761 100644
+--- a/grpc/src/core/lib/iomgr/sockaddr_posix.h
++++ b/grpc/src/core/lib/iomgr/sockaddr_posix.h
+@@ -47,6 +47,7 @@ typedef struct in6_addr grpc_in6_addr;
+ #define GRPC_AF_UNIX AF_UNIX
+ #define GRPC_AF_INET AF_INET
+ #define GRPC_AF_INET6 AF_INET6
++#define GRPC_AF_VSOCK AF_VSOCK
+
+ #define GRPC_AI_PASSIVE AI_PASSIVE
+
+diff --git a/grpc/src/core/lib/iomgr/tcp_client_posix.cc b/grpc/src/core/lib/iomgr/tcp_client_posix.cc
+index 741cc6a..9e073b6 100644
+--- a/grpc/src/core/lib/iomgr/tcp_client_posix.cc
++++ b/grpc/src/core/lib/iomgr/tcp_client_posix.cc
+@@ -75,7 +75,7 @@ static grpc_error_handle prepare_socket(const grpc_resolved_address* addr,
+ 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)) {
++ if (!grpc_is_unix_socket(addr) && !grpc_is_vsock_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);
+diff --git a/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
+index 6fdf070..4932334 100644
+--- a/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
++++ b/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
+@@ -153,7 +153,11 @@ grpc_error_handle grpc_tcp_server_prepare_socket(
+
+ GPR_ASSERT(fd >= 0);
+
+- if (so_reuseport && !grpc_is_unix_socket(addr)) {
++ const grpc_sockaddr* cast_addr =
++ reinterpret_cast<const grpc_sockaddr*>(const_cast<char*>(addr->addr));
++
++ if (so_reuseport && !grpc_is_unix_socket(addr) &&
++ !grpc_is_vsock_socket(addr)) {
+ err = grpc_set_socket_reuse_port(fd, 1);
+ if (err != GRPC_ERROR_NONE) goto error;
+ }
+@@ -170,7 +174,7 @@ grpc_error_handle grpc_tcp_server_prepare_socket(
+ 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)) {
++ if (!grpc_is_unix_socket(addr) && !grpc_is_vsock_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);
+diff --git a/grpc/src/core/lib/iomgr/unix_sockets_posix.cc b/grpc/src/core/lib/iomgr/unix_sockets_posix.cc
+index 2b077a3..3fc903d 100644
+--- a/grpc/src/core/lib/iomgr/unix_sockets_posix.cc
++++ b/grpc/src/core/lib/iomgr/unix_sockets_posix.cc
+@@ -23,6 +23,7 @@
+
+ #include "src/core/lib/iomgr/sockaddr.h"
+
++#include <linux/vm_sockets.h>
+ #include <string.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+@@ -52,6 +53,16 @@ grpc_error_handle grpc_resolve_unix_domain_address(
+ return grpc_core::UnixSockaddrPopulate(name, (*addresses)->addrs);
+ }
+
++grpc_error_handle grpc_resolve_vsock_address(
++ const char* name, grpc_resolved_addresses** addresses) {
++ *addresses = static_cast<grpc_resolved_addresses*>(
++ gpr_malloc(sizeof(grpc_resolved_addresses)));
++ (*addresses)->naddrs = 1;
++ (*addresses)->addrs = static_cast<grpc_resolved_address*>(
++ gpr_malloc(sizeof(grpc_resolved_address)));
++ return grpc_core::VsockaddrPopulate(name, (*addresses)->addrs);
++}
++
+ grpc_error_handle grpc_resolve_unix_abstract_domain_address(
+ const absl::string_view name, grpc_resolved_addresses** addresses) {
+ *addresses = static_cast<grpc_resolved_addresses*>(
+@@ -68,10 +79,17 @@ int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr) {
+ return addr->sa_family == AF_UNIX;
+ }
+
++int grpc_is_vsock_socket(const grpc_resolved_address* resolved_addr) {
++ const grpc_sockaddr* addr =
++ reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
++ return addr->sa_family == AF_VSOCK;
++}
++
+ void grpc_unlink_if_unix_domain_socket(
+ const grpc_resolved_address* resolved_addr) {
+ const grpc_sockaddr* addr =
+ reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
++
+ if (addr->sa_family != AF_UNIX) {
+ return;
+ }
+@@ -107,4 +125,14 @@ std::string grpc_sockaddr_to_uri_unix_if_possible(
+ return absl::StrCat("unix:", unix_addr->sun_path);
+ }
+
++std::string grpc_sockaddr_to_vsock(const grpc_resolved_address* resolved_addr) {
++ const grpc_sockaddr* addr =
++ reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
++ if (addr->sa_family != AF_VSOCK) {
++ return "";
++ }
++ const auto* vsock_addr = reinterpret_cast<const struct sockaddr_vm*>(addr);
++ return absl::StrCat("vsock:", vsock_addr->svm_cid, ":", vsock_addr->svm_port);
++}
++
+ #endif
+diff --git a/grpc/src/core/lib/iomgr/unix_sockets_posix.h b/grpc/src/core/lib/iomgr/unix_sockets_posix.h
+index c35423b..939cef9 100644
+--- a/grpc/src/core/lib/iomgr/unix_sockets_posix.h
++++ b/grpc/src/core/lib/iomgr/unix_sockets_posix.h
+@@ -36,15 +36,22 @@ void grpc_create_socketpair_if_unix(int sv[2]);
+ grpc_error_handle grpc_resolve_unix_domain_address(
+ const char* name, grpc_resolved_addresses** addresses);
+
++grpc_error_handle grpc_resolve_vsock_address(
++ const char* name, grpc_resolved_addresses** addresses);
++
+ grpc_error_handle grpc_resolve_unix_abstract_domain_address(
+ absl::string_view name, grpc_resolved_addresses** addresses);
+
+ int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr);
+
++int grpc_is_vsock_socket(const grpc_resolved_address* resolved_addr);
++
+ void grpc_unlink_if_unix_domain_socket(
+ const grpc_resolved_address* resolved_addr);
+
+ std::string grpc_sockaddr_to_uri_unix_if_possible(
+ const grpc_resolved_address* resolved_addr);
+
++std::string grpc_sockaddr_to_vsock(const grpc_resolved_address* resolved_addr);
++
+ #endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */