| From 716cb35ab711efbd99a65c599b50f044e4912bd0 Mon Sep 17 00:00:00 2001 |
| From: Chirantan Ekbote <chirantan@google.com> |
| Date: Mon, 10 Jul 2017 13:22:59 -0700 |
| Subject: [PATCH 4/5] grpc-1.3.0: Support vsock |
| |
| Add support for vsock as a transport for client <-> server communication. Has |
| not been sent upstream because upstream has not indicated whether they are |
| interested in adding support for this transport. Also the patch in its current |
| form is probably not upstream-able because it assumes that vsock is always |
| available, which is definitely not the case for all the platforms that upstream |
| supports. |
| |
| Rebased by: Allen Webb <allenwebb@google.com> |
| Rebased on: 2018-12-28 (1.16.1) |
| Rebased again on: 2022-04-08 (1.43.0) and added grpc_is_virtual_socket to fix |
| peer(). |
| diff --git a/src/core/lib/address_utils/parse_address.cc b/src/core/lib/address_utils/parse_address.cc |
| index c254d2eb19..5014d28a5c 100644 |
| --- a/src/core/lib/address_utils/parse_address.cc |
| +++ b/src/core/lib/address_utils/parse_address.cc |
| @@ -24,6 +24,8 @@ |
| #include <string.h> |
| #ifdef GRPC_HAVE_UNIX_SOCKET |
| #include <sys/un.h> |
| +#include <sys/socket.h> |
| +#include <linux/vm_sockets.h> |
| #endif |
| #ifdef GRPC_POSIX_SOCKET |
| #include <errno.h> |
| @@ -79,6 +81,21 @@ bool grpc_parse_unix_abstract(const grpc_core::URI& uri, |
| return true; |
| } |
| |
| +bool grpc_parse_vsock(const grpc_core::URI& uri, |
| + grpc_resolved_address* resolved_addr) { |
| + memset(resolved_addr, 0, sizeof(grpc_resolved_address)); |
| + struct sockaddr_vm *vm = |
| + reinterpret_cast<struct sockaddr_vm *>(resolved_addr->addr); |
| + |
| + if (sscanf(uri.path().c_str(), "%u:%u", &vm->svm_cid, &vm->svm_port) != 2) { |
| + return false; |
| + } |
| + vm->svm_family = AF_VSOCK; |
| + |
| + resolved_addr->len = static_cast<socklen_t>(sizeof(*vm)); |
| + return true; |
| +} |
| + |
| namespace grpc_core { |
| |
| grpc_error_handle UnixSockaddrPopulate(absl::string_view path, |
| @@ -306,6 +323,9 @@ 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/src/core/lib/address_utils/parse_address.h b/src/core/lib/address_utils/parse_address.h |
| index 92409b7e81..50ca4c3f84 100644 |
| --- a/src/core/lib/address_utils/parse_address.h |
| +++ b/src/core/lib/address_utils/parse_address.h |
| @@ -38,6 +38,11 @@ bool grpc_parse_unix(const grpc_core::URI& uri, |
| bool grpc_parse_unix_abstract(const grpc_core::URI& uri, |
| grpc_resolved_address* resolved_addr); |
| |
| +/** 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 an |
| * IPv4 host:port pair. Returns true upon success. */ |
| bool grpc_parse_ipv4(const grpc_core::URI& uri, |
| diff --git a/src/core/lib/address_utils/sockaddr_utils.cc b/src/core/lib/address_utils/sockaddr_utils.cc |
| index 33afba1d72..223bac89a9 100644 |
| --- a/src/core/lib/address_utils/sockaddr_utils.cc |
| +++ b/src/core/lib/address_utils/sockaddr_utils.cc |
| @@ -226,7 +226,8 @@ std::string grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) { |
| resolved_addr = &addr_normalized; |
| } |
| const char* scheme = grpc_sockaddr_get_uri_scheme(resolved_addr); |
| - if (scheme == nullptr || strcmp("unix", scheme) == 0) { |
| + if (scheme == nullptr || strcmp("unix", scheme) == 0 || |
| + strcmp("vsock", scheme) == 0) { |
| return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr); |
| } |
| std::string path = |
| @@ -249,6 +250,8 @@ const char* grpc_sockaddr_get_uri_scheme( |
| return "ipv6"; |
| case GRPC_AF_UNIX: |
| return "unix"; |
| + case AF_VSOCK: |
| + return "vsock"; |
| } |
| return nullptr; |
| } |
| @@ -269,6 +272,9 @@ int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) { |
| case GRPC_AF_INET6: |
| return grpc_ntohs( |
| (reinterpret_cast<const grpc_sockaddr_in6*>(addr))->sin6_port); |
| + case AF_VSOCK: |
| + return static_cast<int>( |
| + (reinterpret_cast<const struct sockaddr_vm *>(addr))->svm_port); |
| default: |
| if (grpc_is_unix_socket(resolved_addr)) { |
| return 1; |
| @@ -292,6 +298,10 @@ int grpc_sockaddr_set_port(grpc_resolved_address* resolved_addr, int port) { |
| (reinterpret_cast<grpc_sockaddr_in6*>(addr))->sin6_port = |
| grpc_htons(static_cast<uint16_t>(port)); |
| return 1; |
| + case AF_VSOCK: |
| + (reinterpret_cast<struct sockaddr_vm *>(addr))->svm_port = |
| + static_cast<unsigned int>(port); |
| + return 1; |
| default: |
| gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_set_port", |
| addr->sa_family); |
| diff --git a/src/core/lib/iomgr/resolve_address_posix.cc b/src/core/lib/iomgr/resolve_address_posix.cc |
| index 1427cbda96..363de7a368 100644 |
| --- a/src/core/lib/iomgr/resolve_address_posix.cc |
| +++ b/src/core/lib/iomgr/resolve_address_posix.cc |
| @@ -50,6 +50,11 @@ static grpc_error_handle posix_blocking_resolve_address( |
| size_t i; |
| grpc_error_handle err; |
| |
| + if (name[0] == 'v' && name[1] == 's' && name[2] == 'o' && name[3] == 'c' && |
| + name[4] == 'k' && name[5] == ':' && name[6] != 0) { |
| + return grpc_resolve_vsock_address(name + 6, addresses); |
| + } |
| + |
| std::string host; |
| std::string port; |
| /* parse name, splitting it into host and port parts */ |
| diff --git a/src/core/lib/iomgr/sockaddr_posix.h b/src/core/lib/iomgr/sockaddr_posix.h |
| index 3cedd9082d..f12f52e4da 100644 |
| --- a/src/core/lib/iomgr/sockaddr_posix.h |
| +++ b/src/core/lib/iomgr/sockaddr_posix.h |
| @@ -50,6 +50,8 @@ typedef struct in6_addr grpc_in6_addr; |
| |
| #define GRPC_AI_PASSIVE AI_PASSIVE |
| |
| -#endif |
| +#endif /* GRPC_POSIX_SOCKET_SOCKADDR */ |
| + |
| +#include <linux/vm_sockets.h> // Needs to come after sys/socket.h |
| |
| #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_POSIX_H */ |
| diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc |
| index 580a1f2cff..dff1f738f9 100644 |
| --- a/src/core/lib/iomgr/tcp_server_posix.cc |
| +++ b/src/core/lib/iomgr/tcp_server_posix.cc |
| @@ -228,7 +228,7 @@ static void on_read(void* arg, grpc_error_handle err) { |
| |
| /* For UNIX sockets, the accept call might not fill up the member sun_path |
| * of sockaddr_un, so explicitly call getsockname to get it. */ |
| - if (grpc_is_unix_socket(&addr)) { |
| + if (!grpc_is_virtual_socket(&addr) && grpc_is_unix_socket(&addr)) { |
| memset(&addr, 0, sizeof(addr)); |
| addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage)); |
| if (getsockname(fd, reinterpret_cast<struct sockaddr*>(addr.addr), |
| diff --git a/src/core/lib/iomgr/unix_sockets_posix.cc b/src/core/lib/iomgr/unix_sockets_posix.cc |
| index dada84a86b..e8a8eabbb2 100644 |
| --- a/src/core/lib/iomgr/unix_sockets_posix.cc |
| +++ b/src/core/lib/iomgr/unix_sockets_posix.cc |
| @@ -21,6 +21,7 @@ |
| |
| #ifdef GRPC_HAVE_UNIX_SOCKET |
| |
| +#include <stdio.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| @@ -60,10 +61,39 @@ grpc_error_handle grpc_resolve_unix_abstract_domain_address( |
| return grpc_core::UnixAbstractSockaddrPopulate(name, (*addresses)->addrs); |
| } |
| |
| +grpc_error* grpc_resolve_vsock_address(const char* name, |
| + grpc_resolved_addresses** addrs) { |
| + struct sockaddr_vm *vm; |
| + unsigned int cid; |
| + unsigned int port; |
| + |
| + if (sscanf(name, "%u:%u", &cid, &port) != 2) { |
| + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse cid:port pair"); |
| + } |
| + |
| + *addrs = static_cast<grpc_resolved_addresses*>( |
| + gpr_malloc(sizeof(grpc_resolved_addresses))); |
| + (*addrs)->naddrs = 1; |
| + (*addrs)->addrs = static_cast<grpc_resolved_address*>( |
| + gpr_zalloc(sizeof(grpc_resolved_address))); |
| + vm = (struct sockaddr_vm *)(*addrs)->addrs->addr; |
| + vm->svm_family = AF_VSOCK; |
| + vm->svm_cid = cid; |
| + vm->svm_port = port; |
| + (*addrs)->addrs->len = sizeof(struct sockaddr_vm); |
| + return GRPC_ERROR_NONE; |
| +} |
| + |
| int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr) { |
| const grpc_sockaddr* addr = |
| reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); |
| - return addr->sa_family == AF_UNIX; |
| + return addr->sa_family == AF_UNIX || addr->sa_family == AF_VSOCK; |
| +} |
| + |
| +int grpc_is_virtual_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( |
| @@ -91,6 +121,13 @@ std::string grpc_sockaddr_to_uri_unix_if_possible( |
| const grpc_resolved_address* resolved_addr) { |
| const grpc_sockaddr* addr = |
| reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); |
| + if (addr->sa_family == AF_VSOCK) { |
| + char *result; |
| + struct sockaddr_vm *vm = (struct sockaddr_vm*)addr; |
| + gpr_asprintf(&result, "vsock:%u:%u", vm->svm_cid, vm->svm_port); |
| + return result; |
| + } |
| + |
| if (addr->sa_family != AF_UNIX) { |
| return ""; |
| } |
| diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h |
| index 823dd83274..de4623ebe3 100644 |
| --- a/src/core/lib/iomgr/unix_sockets_posix.h |
| +++ b/src/core/lib/iomgr/unix_sockets_posix.h |
| @@ -38,8 +38,13 @@ grpc_error_handle grpc_resolve_unix_domain_address( |
| grpc_error_handle grpc_resolve_unix_abstract_domain_address( |
| absl::string_view name, grpc_resolved_addresses** addresses); |
| |
| +grpc_error* grpc_resolve_vsock_address( |
| + const char* name, grpc_resolved_addresses** addrs); |
| + |
| int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr); |
| |
| +int grpc_is_virtual_socket(const grpc_resolved_address* resolved_addr); |
| + |
| void grpc_unlink_if_unix_domain_socket( |
| const grpc_resolved_address* resolved_addr); |