UnixSocket: support the vsock address family

This change adds the support of vsock family to UnixSocket. A vsock
socket name is in the format of vsock://$CID:$PORT.

For example:
`PERFETTO_PRODUCER_SOCK_NAME=vsock://-1:10000 traced` starts traced with
the producer socket listening on the "ANY" CID and port 10000.
See vsock(7) for special CID values that may be used for vsock.

Bug: 284258446
Change-Id: Ie6f8e4a9f55c0550dba48818e6e26642763fad8d
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 7dfce6b..e8db554 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -144,6 +144,9 @@
     if (is_win && perfetto_build_standalone) {
       libs = [ "Ws2_32.lib" ]
     }
+    if (is_linux || is_android) {
+      sources += [ "vm_sockets.h" ]
+    }
   }
 }
 
diff --git a/src/base/unix_socket.cc b/src/base/unix_socket.cc
index 6968e36..4092d79 100644
--- a/src/base/unix_socket.cc
+++ b/src/base/unix_socket.cc
@@ -23,6 +23,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include "perfetto/base/compiler.h"
+#include "perfetto/ext/base/string_utils.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 // The include order matters on these three Windows header groups.
@@ -56,6 +57,12 @@
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/utils.h"
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+// Use a local stripped copy of vm_sockets.h from UAPI.
+#include "src/base/vm_sockets.h"
+#endif
+
 namespace perfetto {
 namespace base {
 
@@ -75,6 +82,11 @@
 using CBufLenType = socklen_t;
 #endif
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+constexpr char kVsockNamePrefix[] = "vsock://";
+#endif
+
 // A wrapper around variable-size sockaddr structs.
 // This is solving the following problem: when calling connect() or bind(), the
 // caller needs to take care to allocate the right struct (sockaddr_un for
@@ -103,6 +115,12 @@
       return AF_INET;
     case SockFamily::kInet6:
       return AF_INET6;
+    case SockFamily::kVsock:
+#ifdef AF_VSOCK
+      return AF_VSOCK;
+#else
+      return AF_UNSPEC;  // Return AF_UNSPEC on unsupported platforms.
+#endif
     case SockFamily::kUnspec:
       return AF_UNSPEC;
   }
@@ -191,6 +209,25 @@
       freeaddrinfo(addr_info);
       return res;
     }
+    case SockFamily::kVsock: {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+      PERFETTO_CHECK(StartsWith(socket_name, kVsockNamePrefix));
+      auto address_port = StripPrefix(socket_name, kVsockNamePrefix);
+      auto parts = SplitString(address_port, ":");
+      PERFETTO_CHECK(parts.size() == 2);
+      sockaddr_vm addr;
+      memset(&addr, 0, sizeof(addr));
+      addr.svm_family = AF_VSOCK;
+      addr.svm_cid = *base::StringToUInt32(parts[0]);
+      addr.svm_port = *base::StringToUInt32(parts[1]);
+      SockaddrAny res(&addr, sizeof(addr));
+      return res;
+#else
+      errno = ENOTSOCK;
+      return SockAddrAny{};
+#endif
+    }
     case SockFamily::kUnspec:
       errno = ENOTSOCK;
       return SockaddrAny();
@@ -224,6 +261,13 @@
   if (addr[0] == '@')
     return SockFamily::kUnix;  // Abstract AF_UNIX sockets.
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  // Vsock address starts with vsock://.
+  if (strncmp(addr, kVsockNamePrefix, strlen(kVsockNamePrefix)) == 0)
+    return SockFamily::kVsock;
+#endif
+
   // If `addr` ends in :NNNN it's either a kInet or kInet6 socket.
   const char* col = strrchr(addr, ':');
   if (col && CStringToInt32(col + 1).has_value()) {
@@ -296,14 +340,18 @@
   setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe));
 #endif
 
-  if (family == SockFamily::kInet || family == SockFamily::kInet6) {
+  if (family == SockFamily::kInet || family == SockFamily::kInet6 ||
+      family == SockFamily::kVsock) {
     int flag = 1;
     // The reinterpret_cast<const char*> is needed for Windows, where the 4th
     // arg is a const char* (on other POSIX system is a const void*).
     PERFETTO_CHECK(!setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR,
                                reinterpret_cast<const char*>(&flag),
                                sizeof(flag)));
-    flag = 1;
+  }
+
+  if (family == SockFamily::kInet || family == SockFamily::kInet6) {
+    int flag = 1;
     // Disable Nagle's algorithm, optimize for low-latency.
     // See https://github.com/google/perfetto/issues/70.
     setsockopt(*fd_, IPPROTO_TCP, TCP_NODELAY,
diff --git a/src/base/unix_socket_unittest.cc b/src/base/unix_socket_unittest.cc
index 3210c49..6ed65d5 100644
--- a/src/base/unix_socket_unittest.cc
+++ b/src/base/unix_socket_unittest.cc
@@ -1014,6 +1014,57 @@
   ASSERT_EQ(0, connect(cli.fd(), reinterpret_cast<struct sockaddr*>(&addr),
                        addr_len));
 }
+
+bool VsockLoopBackAddrSupported() {
+  auto sock =
+      UnixSocketRaw::CreateMayFail(SockFamily::kVsock, SockType::kStream);
+  return sock.Bind("vsock://1:10000");
+}
+
+TEST_F(UnixSocketTest, VSockStream) {
+  if (!VsockLoopBackAddrSupported())
+    GTEST_SKIP() << "vsock testing skipped: loopback address unsupported";
+
+  // Use the loopback CID (1) and a random unprileged port number.
+  StackString<128> sock_name("vsock://1:%d", 1024 + rand() % 10000);
+
+  // Set up the server.
+  auto srv =
+      UnixSocket::Listen(sock_name.ToStdString(), &event_listener_,
+                         &task_runner_, SockFamily::kVsock, SockType::kStream);
+  ASSERT_TRUE(srv && srv->is_listening());
+
+  std::unique_ptr<UnixSocket> prod;
+  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
+      .WillOnce(Invoke([&](UnixSocket*, UnixSocket* s) {
+        // OnDisconnect() might spuriously happen depending on the dtor order.
+        EXPECT_CALL(event_listener_, OnDisconnect(s)).Times(AtLeast(0));
+        EXPECT_CALL(event_listener_, OnDataAvailable(s))
+            .WillRepeatedly(Invoke([](UnixSocket* prod_sock) {
+              prod_sock->ReceiveString();  // Read connection EOF;
+            }));
+        ASSERT_TRUE(s->SendStr("welcome"));
+      }));
+
+  // Set up the client.
+  prod =
+      UnixSocket::Connect(sock_name.ToStdString(), &event_listener_,
+                          &task_runner_, SockFamily::kVsock, SockType::kStream);
+  auto checkpoint = task_runner_.CreateCheckpoint("prod_connected");
+  EXPECT_CALL(event_listener_, OnDisconnect(prod.get())).Times(AtLeast(0));
+  EXPECT_CALL(event_listener_, OnConnect(prod.get(), true));
+  EXPECT_CALL(event_listener_, OnDataAvailable(prod.get()))
+      .WillRepeatedly(Invoke([checkpoint](UnixSocket* s) {
+        auto str = s->ReceiveString();
+        if (str == "")
+          return;  // Connection EOF.
+        ASSERT_EQ("welcome", str);
+        checkpoint();
+      }));
+
+  task_runner_.RunUntilCheckpoint("prod_connected");
+  ASSERT_TRUE(Mock::VerifyAndClearExpectations(prod.get()));
+}
 #endif  // OS_LINUX || OS_ANDROID
 
 TEST_F(UnixSocketTest, GetSockFamily) {
@@ -1025,6 +1076,10 @@
   ASSERT_EQ(GetSockFamily("127.0.0.1:80"), SockFamily::kInet);
   ASSERT_EQ(GetSockFamily("[effe::acca]:1234"), SockFamily::kInet6);
   ASSERT_EQ(GetSockFamily("[::1]:123456"), SockFamily::kInet6);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  ASSERT_EQ(GetSockFamily("vsock://-1:10000"), SockFamily::kVsock);
+#endif
 }
 
 }  // namespace
diff --git a/src/base/vm_sockets.h b/src/base/vm_sockets.h
new file mode 100644
index 0000000..af5b917
--- /dev/null
+++ b/src/base/vm_sockets.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_BASE_VM_SOCKETS_H_
+#define SRC_BASE_VM_SOCKETS_H_
+
+#include <sys/socket.h>
+
+#ifdef AF_VSOCK
+// Use system vm_socket.h if avaialbe.
+#include <linux/vm_sockets.h>
+#else
+// Fallback and use the stripped copy from the UAPI vm_sockets.h.
+
+#include <stdint.h>  // For uint8_t.
+
+#define AF_VSOCK 40
+
+struct sockaddr_vm {
+  sa_family_t svm_family;
+  unsigned short svm_reserved1;
+  unsigned int svm_port;
+  unsigned int svm_cid;
+  uint8_t svm_flags;
+  unsigned char svm_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) -
+                         sizeof(unsigned short) - sizeof(unsigned int) -
+                         sizeof(unsigned int) - sizeof(uint8_t)];
+};
+
+#endif
+
+#endif  // SRC_BASE_VM_SOCKETS_H_