blob: e3dfdd84e4bc2212cf818dfe6193199b7ed43535 [file] [log] [blame] [edit]
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);