xref: /aosp_15_r20/external/perfetto/src/base/unix_socket.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/unix_socket.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <errno.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <fcntl.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <stdlib.h>
22*6dbdd20aSAndroid Build Coastguard Worker #include <string.h>
23*6dbdd20aSAndroid Build Coastguard Worker #include <sys/stat.h>
24*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h>
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/compiler.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker 
28*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
29*6dbdd20aSAndroid Build Coastguard Worker // The include order matters on these three Windows header groups.
30*6dbdd20aSAndroid Build Coastguard Worker #include <Windows.h>
31*6dbdd20aSAndroid Build Coastguard Worker 
32*6dbdd20aSAndroid Build Coastguard Worker #include <WS2tcpip.h>
33*6dbdd20aSAndroid Build Coastguard Worker #include <WinSock2.h>
34*6dbdd20aSAndroid Build Coastguard Worker 
35*6dbdd20aSAndroid Build Coastguard Worker #include <afunix.h>
36*6dbdd20aSAndroid Build Coastguard Worker #else
37*6dbdd20aSAndroid Build Coastguard Worker #include <arpa/inet.h>
38*6dbdd20aSAndroid Build Coastguard Worker #include <netdb.h>
39*6dbdd20aSAndroid Build Coastguard Worker #include <netinet/in.h>
40*6dbdd20aSAndroid Build Coastguard Worker #include <netinet/tcp.h>
41*6dbdd20aSAndroid Build Coastguard Worker #include <poll.h>
42*6dbdd20aSAndroid Build Coastguard Worker #include <sys/socket.h>
43*6dbdd20aSAndroid Build Coastguard Worker #include <sys/un.h>
44*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
45*6dbdd20aSAndroid Build Coastguard Worker #endif
46*6dbdd20aSAndroid Build Coastguard Worker 
47*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
48*6dbdd20aSAndroid Build Coastguard Worker #include <sys/ucred.h>
49*6dbdd20aSAndroid Build Coastguard Worker #endif
50*6dbdd20aSAndroid Build Coastguard Worker 
51*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
52*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
53*6dbdd20aSAndroid Build Coastguard Worker 
54*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
55*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
56*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/task_runner.h"
57*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h"
58*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
59*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
60*6dbdd20aSAndroid Build Coastguard Worker 
61*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
62*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
63*6dbdd20aSAndroid Build Coastguard Worker // Use a local stripped copy of vm_sockets.h from UAPI.
64*6dbdd20aSAndroid Build Coastguard Worker #include "src/base/vm_sockets.h"
65*6dbdd20aSAndroid Build Coastguard Worker #endif
66*6dbdd20aSAndroid Build Coastguard Worker 
67*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
68*6dbdd20aSAndroid Build Coastguard Worker namespace base {
69*6dbdd20aSAndroid Build Coastguard Worker 
70*6dbdd20aSAndroid Build Coastguard Worker // The CMSG_* macros use NULL instead of nullptr.
71*6dbdd20aSAndroid Build Coastguard Worker // Note: MSVC doesn't have #pragma GCC diagnostic, hence the if __GNUC__.
72*6dbdd20aSAndroid Build Coastguard Worker #if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
73*6dbdd20aSAndroid Build Coastguard Worker #pragma GCC diagnostic push
74*6dbdd20aSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
75*6dbdd20aSAndroid Build Coastguard Worker #endif
76*6dbdd20aSAndroid Build Coastguard Worker 
77*6dbdd20aSAndroid Build Coastguard Worker namespace {
78*6dbdd20aSAndroid Build Coastguard Worker 
79*6dbdd20aSAndroid Build Coastguard Worker // Android takes an int instead of socklen_t for the control buffer size.
80*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
81*6dbdd20aSAndroid Build Coastguard Worker using CBufLenType = size_t;
82*6dbdd20aSAndroid Build Coastguard Worker #else
83*6dbdd20aSAndroid Build Coastguard Worker using CBufLenType = socklen_t;
84*6dbdd20aSAndroid Build Coastguard Worker #endif
85*6dbdd20aSAndroid Build Coastguard Worker 
86*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
87*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
88*6dbdd20aSAndroid Build Coastguard Worker constexpr char kVsockNamePrefix[] = "vsock://";
89*6dbdd20aSAndroid Build Coastguard Worker #endif
90*6dbdd20aSAndroid Build Coastguard Worker 
91*6dbdd20aSAndroid Build Coastguard Worker // A wrapper around variable-size sockaddr structs.
92*6dbdd20aSAndroid Build Coastguard Worker // This is solving the following problem: when calling connect() or bind(), the
93*6dbdd20aSAndroid Build Coastguard Worker // caller needs to take care to allocate the right struct (sockaddr_un for
94*6dbdd20aSAndroid Build Coastguard Worker // AF_UNIX, sockaddr_in for AF_INET).   Those structs have different sizes and,
95*6dbdd20aSAndroid Build Coastguard Worker // more importantly, are bigger than the base struct sockaddr.
96*6dbdd20aSAndroid Build Coastguard Worker struct SockaddrAny {
SockaddrAnyperfetto::base::__anonf9031f200111::SockaddrAny97*6dbdd20aSAndroid Build Coastguard Worker   SockaddrAny() : size() {}
SockaddrAnyperfetto::base::__anonf9031f200111::SockaddrAny98*6dbdd20aSAndroid Build Coastguard Worker   SockaddrAny(const void* addr, socklen_t sz)
99*6dbdd20aSAndroid Build Coastguard Worker       : data(new char[static_cast<size_t>(sz)]), size(sz) {
100*6dbdd20aSAndroid Build Coastguard Worker     memcpy(data.get(), addr, static_cast<size_t>(size));
101*6dbdd20aSAndroid Build Coastguard Worker   }
102*6dbdd20aSAndroid Build Coastguard Worker 
addrperfetto::base::__anonf9031f200111::SockaddrAny103*6dbdd20aSAndroid Build Coastguard Worker   const struct sockaddr* addr() const {
104*6dbdd20aSAndroid Build Coastguard Worker     return reinterpret_cast<const struct sockaddr*>(data.get());
105*6dbdd20aSAndroid Build Coastguard Worker   }
106*6dbdd20aSAndroid Build Coastguard Worker 
107*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<char[]> data;
108*6dbdd20aSAndroid Build Coastguard Worker   socklen_t size;
109*6dbdd20aSAndroid Build Coastguard Worker };
110*6dbdd20aSAndroid Build Coastguard Worker 
MkSockFamily(SockFamily family)111*6dbdd20aSAndroid Build Coastguard Worker inline int MkSockFamily(SockFamily family) {
112*6dbdd20aSAndroid Build Coastguard Worker   switch (family) {
113*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kUnix:
114*6dbdd20aSAndroid Build Coastguard Worker       return AF_UNIX;
115*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kInet:
116*6dbdd20aSAndroid Build Coastguard Worker       return AF_INET;
117*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kInet6:
118*6dbdd20aSAndroid Build Coastguard Worker       return AF_INET6;
119*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kVsock:
120*6dbdd20aSAndroid Build Coastguard Worker #ifdef AF_VSOCK
121*6dbdd20aSAndroid Build Coastguard Worker       return AF_VSOCK;
122*6dbdd20aSAndroid Build Coastguard Worker #else
123*6dbdd20aSAndroid Build Coastguard Worker       return AF_UNSPEC;  // Return AF_UNSPEC on unsupported platforms.
124*6dbdd20aSAndroid Build Coastguard Worker #endif
125*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kUnspec:
126*6dbdd20aSAndroid Build Coastguard Worker       return AF_UNSPEC;
127*6dbdd20aSAndroid Build Coastguard Worker   }
128*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(false);  // For GCC.
129*6dbdd20aSAndroid Build Coastguard Worker }
130*6dbdd20aSAndroid Build Coastguard Worker 
MkSockType(SockType type)131*6dbdd20aSAndroid Build Coastguard Worker inline int MkSockType(SockType type) {
132*6dbdd20aSAndroid Build Coastguard Worker #if defined(SOCK_CLOEXEC)
133*6dbdd20aSAndroid Build Coastguard Worker   constexpr int kSockCloExec = SOCK_CLOEXEC;
134*6dbdd20aSAndroid Build Coastguard Worker #else
135*6dbdd20aSAndroid Build Coastguard Worker   constexpr int kSockCloExec = 0;
136*6dbdd20aSAndroid Build Coastguard Worker #endif
137*6dbdd20aSAndroid Build Coastguard Worker   switch (type) {
138*6dbdd20aSAndroid Build Coastguard Worker     case SockType::kStream:
139*6dbdd20aSAndroid Build Coastguard Worker       return SOCK_STREAM | kSockCloExec;
140*6dbdd20aSAndroid Build Coastguard Worker     case SockType::kDgram:
141*6dbdd20aSAndroid Build Coastguard Worker       return SOCK_DGRAM | kSockCloExec;
142*6dbdd20aSAndroid Build Coastguard Worker     case SockType::kSeqPacket:
143*6dbdd20aSAndroid Build Coastguard Worker       return SOCK_SEQPACKET | kSockCloExec;
144*6dbdd20aSAndroid Build Coastguard Worker   }
145*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(false);  // For GCC.
146*6dbdd20aSAndroid Build Coastguard Worker }
147*6dbdd20aSAndroid Build Coastguard Worker 
MakeSockAddr(SockFamily family,const std::string & socket_name)148*6dbdd20aSAndroid Build Coastguard Worker SockaddrAny MakeSockAddr(SockFamily family, const std::string& socket_name) {
149*6dbdd20aSAndroid Build Coastguard Worker   switch (family) {
150*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kUnix: {
151*6dbdd20aSAndroid Build Coastguard Worker       struct sockaddr_un saddr {};
152*6dbdd20aSAndroid Build Coastguard Worker       const size_t name_len = socket_name.size();
153*6dbdd20aSAndroid Build Coastguard Worker       if (name_len + 1 /* for trailing \0 */ >= sizeof(saddr.sun_path)) {
154*6dbdd20aSAndroid Build Coastguard Worker         errno = ENAMETOOLONG;
155*6dbdd20aSAndroid Build Coastguard Worker         return SockaddrAny();
156*6dbdd20aSAndroid Build Coastguard Worker       }
157*6dbdd20aSAndroid Build Coastguard Worker       memcpy(saddr.sun_path, socket_name.data(), name_len);
158*6dbdd20aSAndroid Build Coastguard Worker       if (saddr.sun_path[0] == '@') {
159*6dbdd20aSAndroid Build Coastguard Worker         saddr.sun_path[0] = '\0';
160*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
161*6dbdd20aSAndroid Build Coastguard Worker         // The MSDN blog claims that abstract (non-filesystem based) AF_UNIX
162*6dbdd20aSAndroid Build Coastguard Worker         // socket are supported, but that doesn't seem true.
163*6dbdd20aSAndroid Build Coastguard Worker         PERFETTO_ELOG(
164*6dbdd20aSAndroid Build Coastguard Worker             "Abstract AF_UNIX sockets are not supported on Windows, see "
165*6dbdd20aSAndroid Build Coastguard Worker             "https://github.com/microsoft/WSL/issues/4240");
166*6dbdd20aSAndroid Build Coastguard Worker         return SockaddrAny();
167*6dbdd20aSAndroid Build Coastguard Worker #endif
168*6dbdd20aSAndroid Build Coastguard Worker       }
169*6dbdd20aSAndroid Build Coastguard Worker       saddr.sun_family = AF_UNIX;
170*6dbdd20aSAndroid Build Coastguard Worker       auto size = static_cast<socklen_t>(
171*6dbdd20aSAndroid Build Coastguard Worker           __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
172*6dbdd20aSAndroid Build Coastguard Worker 
173*6dbdd20aSAndroid Build Coastguard Worker       // Abstract sockets do NOT require a trailing null terminator (which is
174*6dbdd20aSAndroid Build Coastguard Worker       // instad mandatory for filesystem sockets). Any byte up to `size`,
175*6dbdd20aSAndroid Build Coastguard Worker       // including '\0' will become part of the socket name.
176*6dbdd20aSAndroid Build Coastguard Worker       if (saddr.sun_path[0] == '\0')
177*6dbdd20aSAndroid Build Coastguard Worker         --size;
178*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(static_cast<size_t>(size) <= sizeof(saddr));
179*6dbdd20aSAndroid Build Coastguard Worker       return SockaddrAny(&saddr, size);
180*6dbdd20aSAndroid Build Coastguard Worker     }
181*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kInet: {
182*6dbdd20aSAndroid Build Coastguard Worker       auto parts = SplitString(socket_name, ":");
183*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(parts.size() == 2);
184*6dbdd20aSAndroid Build Coastguard Worker       struct addrinfo* addr_info = nullptr;
185*6dbdd20aSAndroid Build Coastguard Worker       struct addrinfo hints {};
186*6dbdd20aSAndroid Build Coastguard Worker       hints.ai_family = AF_INET;
187*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(getaddrinfo(parts[0].c_str(), parts[1].c_str(), &hints,
188*6dbdd20aSAndroid Build Coastguard Worker                                  &addr_info) == 0);
189*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(addr_info->ai_family == AF_INET);
190*6dbdd20aSAndroid Build Coastguard Worker       SockaddrAny res(addr_info->ai_addr,
191*6dbdd20aSAndroid Build Coastguard Worker                       static_cast<socklen_t>(addr_info->ai_addrlen));
192*6dbdd20aSAndroid Build Coastguard Worker       freeaddrinfo(addr_info);
193*6dbdd20aSAndroid Build Coastguard Worker       return res;
194*6dbdd20aSAndroid Build Coastguard Worker     }
195*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kInet6: {
196*6dbdd20aSAndroid Build Coastguard Worker       auto parts = SplitString(socket_name, "]");
197*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(parts.size() == 2);
198*6dbdd20aSAndroid Build Coastguard Worker       auto address = SplitString(parts[0], "[");
199*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(address.size() == 1);
200*6dbdd20aSAndroid Build Coastguard Worker       auto port = SplitString(parts[1], ":");
201*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(port.size() == 1);
202*6dbdd20aSAndroid Build Coastguard Worker       struct addrinfo* addr_info = nullptr;
203*6dbdd20aSAndroid Build Coastguard Worker       struct addrinfo hints {};
204*6dbdd20aSAndroid Build Coastguard Worker       hints.ai_family = AF_INET6;
205*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(getaddrinfo(address[0].c_str(), port[0].c_str(), &hints,
206*6dbdd20aSAndroid Build Coastguard Worker                                  &addr_info) == 0);
207*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(addr_info->ai_family == AF_INET6);
208*6dbdd20aSAndroid Build Coastguard Worker       SockaddrAny res(addr_info->ai_addr,
209*6dbdd20aSAndroid Build Coastguard Worker                       static_cast<socklen_t>(addr_info->ai_addrlen));
210*6dbdd20aSAndroid Build Coastguard Worker       freeaddrinfo(addr_info);
211*6dbdd20aSAndroid Build Coastguard Worker       return res;
212*6dbdd20aSAndroid Build Coastguard Worker     }
213*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kVsock: {
214*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
215*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
216*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(StartsWith(socket_name, kVsockNamePrefix));
217*6dbdd20aSAndroid Build Coastguard Worker       auto address_port = StripPrefix(socket_name, kVsockNamePrefix);
218*6dbdd20aSAndroid Build Coastguard Worker       auto parts = SplitString(address_port, ":");
219*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(parts.size() == 2);
220*6dbdd20aSAndroid Build Coastguard Worker       sockaddr_vm addr;
221*6dbdd20aSAndroid Build Coastguard Worker       memset(&addr, 0, sizeof(addr));
222*6dbdd20aSAndroid Build Coastguard Worker       addr.svm_family = AF_VSOCK;
223*6dbdd20aSAndroid Build Coastguard Worker       addr.svm_cid = *base::StringToUInt32(parts[0]);
224*6dbdd20aSAndroid Build Coastguard Worker       addr.svm_port = *base::StringToUInt32(parts[1]);
225*6dbdd20aSAndroid Build Coastguard Worker       SockaddrAny res(&addr, sizeof(addr));
226*6dbdd20aSAndroid Build Coastguard Worker       return res;
227*6dbdd20aSAndroid Build Coastguard Worker #else
228*6dbdd20aSAndroid Build Coastguard Worker       errno = ENOTSOCK;
229*6dbdd20aSAndroid Build Coastguard Worker       return SockaddrAny();
230*6dbdd20aSAndroid Build Coastguard Worker #endif
231*6dbdd20aSAndroid Build Coastguard Worker     }
232*6dbdd20aSAndroid Build Coastguard Worker     case SockFamily::kUnspec:
233*6dbdd20aSAndroid Build Coastguard Worker       errno = ENOTSOCK;
234*6dbdd20aSAndroid Build Coastguard Worker       return SockaddrAny();
235*6dbdd20aSAndroid Build Coastguard Worker   }
236*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(false);  // For GCC.
237*6dbdd20aSAndroid Build Coastguard Worker }
238*6dbdd20aSAndroid Build Coastguard Worker 
CreateSocketHandle(SockFamily family,SockType type)239*6dbdd20aSAndroid Build Coastguard Worker ScopedSocketHandle CreateSocketHandle(SockFamily family, SockType type) {
240*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
241*6dbdd20aSAndroid Build Coastguard Worker   static bool init_winsock_once = [] {
242*6dbdd20aSAndroid Build Coastguard Worker     WSADATA ignored{};
243*6dbdd20aSAndroid Build Coastguard Worker     return WSAStartup(MAKEWORD(2, 2), &ignored) == 0;
244*6dbdd20aSAndroid Build Coastguard Worker   }();
245*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(init_winsock_once);
246*6dbdd20aSAndroid Build Coastguard Worker #endif
247*6dbdd20aSAndroid Build Coastguard Worker   return ScopedSocketHandle(socket(MkSockFamily(family), MkSockType(type), 0));
248*6dbdd20aSAndroid Build Coastguard Worker }
249*6dbdd20aSAndroid Build Coastguard Worker 
250*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
251*6dbdd20aSAndroid Build Coastguard Worker 
252*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
CloseSocket(SocketHandle s)253*6dbdd20aSAndroid Build Coastguard Worker int CloseSocket(SocketHandle s) {
254*6dbdd20aSAndroid Build Coastguard Worker   return ::closesocket(s);
255*6dbdd20aSAndroid Build Coastguard Worker }
256*6dbdd20aSAndroid Build Coastguard Worker #endif
257*6dbdd20aSAndroid Build Coastguard Worker 
GetSockFamily(const char * addr)258*6dbdd20aSAndroid Build Coastguard Worker SockFamily GetSockFamily(const char* addr) {
259*6dbdd20aSAndroid Build Coastguard Worker   if (strlen(addr) == 0)
260*6dbdd20aSAndroid Build Coastguard Worker     return SockFamily::kUnspec;
261*6dbdd20aSAndroid Build Coastguard Worker 
262*6dbdd20aSAndroid Build Coastguard Worker   if (addr[0] == '@')
263*6dbdd20aSAndroid Build Coastguard Worker     return SockFamily::kUnix;  // Abstract AF_UNIX sockets.
264*6dbdd20aSAndroid Build Coastguard Worker 
265*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
266*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
267*6dbdd20aSAndroid Build Coastguard Worker   // Vsock address starts with vsock://.
268*6dbdd20aSAndroid Build Coastguard Worker   if (strncmp(addr, kVsockNamePrefix, strlen(kVsockNamePrefix)) == 0)
269*6dbdd20aSAndroid Build Coastguard Worker     return SockFamily::kVsock;
270*6dbdd20aSAndroid Build Coastguard Worker #endif
271*6dbdd20aSAndroid Build Coastguard Worker 
272*6dbdd20aSAndroid Build Coastguard Worker   // If `addr` ends in :NNNN it's either a kInet or kInet6 socket.
273*6dbdd20aSAndroid Build Coastguard Worker   const char* col = strrchr(addr, ':');
274*6dbdd20aSAndroid Build Coastguard Worker   if (col && CStringToInt32(col + 1).has_value()) {
275*6dbdd20aSAndroid Build Coastguard Worker     return addr[0] == '[' ? SockFamily::kInet6 : SockFamily::kInet;
276*6dbdd20aSAndroid Build Coastguard Worker   }
277*6dbdd20aSAndroid Build Coastguard Worker 
278*6dbdd20aSAndroid Build Coastguard Worker   return SockFamily::kUnix;  // For anything else assume it's a linked AF_UNIX.
279*6dbdd20aSAndroid Build Coastguard Worker }
280*6dbdd20aSAndroid Build Coastguard Worker 
281*6dbdd20aSAndroid Build Coastguard Worker // +-----------------------+
282*6dbdd20aSAndroid Build Coastguard Worker // | UnixSocketRaw methods |
283*6dbdd20aSAndroid Build Coastguard Worker // +-----------------------+
284*6dbdd20aSAndroid Build Coastguard Worker 
285*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
286*6dbdd20aSAndroid Build Coastguard Worker // static
ShiftMsgHdrPosix(size_t n,struct msghdr * msg)287*6dbdd20aSAndroid Build Coastguard Worker void UnixSocketRaw::ShiftMsgHdrPosix(size_t n, struct msghdr* msg) {
288*6dbdd20aSAndroid Build Coastguard Worker   using LenType = decltype(msg->msg_iovlen);  // Mac and Linux don't agree.
289*6dbdd20aSAndroid Build Coastguard Worker   for (LenType i = 0; i < msg->msg_iovlen; ++i) {
290*6dbdd20aSAndroid Build Coastguard Worker     struct iovec* vec = &msg->msg_iov[i];
291*6dbdd20aSAndroid Build Coastguard Worker     if (n < vec->iov_len) {
292*6dbdd20aSAndroid Build Coastguard Worker       // We sent a part of this iovec.
293*6dbdd20aSAndroid Build Coastguard Worker       vec->iov_base = reinterpret_cast<char*>(vec->iov_base) + n;
294*6dbdd20aSAndroid Build Coastguard Worker       vec->iov_len -= n;
295*6dbdd20aSAndroid Build Coastguard Worker       msg->msg_iov = vec;
296*6dbdd20aSAndroid Build Coastguard Worker       msg->msg_iovlen -= i;
297*6dbdd20aSAndroid Build Coastguard Worker       return;
298*6dbdd20aSAndroid Build Coastguard Worker     }
299*6dbdd20aSAndroid Build Coastguard Worker     // We sent the whole iovec.
300*6dbdd20aSAndroid Build Coastguard Worker     n -= vec->iov_len;
301*6dbdd20aSAndroid Build Coastguard Worker   }
302*6dbdd20aSAndroid Build Coastguard Worker   // We sent all the iovecs.
303*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(n == 0);
304*6dbdd20aSAndroid Build Coastguard Worker   msg->msg_iovlen = 0;
305*6dbdd20aSAndroid Build Coastguard Worker   msg->msg_iov = nullptr;
306*6dbdd20aSAndroid Build Coastguard Worker }
307*6dbdd20aSAndroid Build Coastguard Worker 
308*6dbdd20aSAndroid Build Coastguard Worker // static
CreatePairPosix(SockFamily family,SockType type)309*6dbdd20aSAndroid Build Coastguard Worker std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePairPosix(
310*6dbdd20aSAndroid Build Coastguard Worker     SockFamily family,
311*6dbdd20aSAndroid Build Coastguard Worker     SockType type) {
312*6dbdd20aSAndroid Build Coastguard Worker   int fds[2];
313*6dbdd20aSAndroid Build Coastguard Worker   if (socketpair(MkSockFamily(family), MkSockType(type), 0, fds) != 0) {
314*6dbdd20aSAndroid Build Coastguard Worker     return std::make_pair(UnixSocketRaw(), UnixSocketRaw());
315*6dbdd20aSAndroid Build Coastguard Worker   }
316*6dbdd20aSAndroid Build Coastguard Worker   return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), family, type),
317*6dbdd20aSAndroid Build Coastguard Worker                         UnixSocketRaw(ScopedFile(fds[1]), family, type));
318*6dbdd20aSAndroid Build Coastguard Worker }
319*6dbdd20aSAndroid Build Coastguard Worker #endif
320*6dbdd20aSAndroid Build Coastguard Worker 
321*6dbdd20aSAndroid Build Coastguard Worker // static
CreateMayFail(SockFamily family,SockType type)322*6dbdd20aSAndroid Build Coastguard Worker UnixSocketRaw UnixSocketRaw::CreateMayFail(SockFamily family, SockType type) {
323*6dbdd20aSAndroid Build Coastguard Worker   auto fd = CreateSocketHandle(family, type);
324*6dbdd20aSAndroid Build Coastguard Worker   if (!fd)
325*6dbdd20aSAndroid Build Coastguard Worker     return UnixSocketRaw();
326*6dbdd20aSAndroid Build Coastguard Worker   return UnixSocketRaw(std::move(fd), family, type);
327*6dbdd20aSAndroid Build Coastguard Worker }
328*6dbdd20aSAndroid Build Coastguard Worker 
329*6dbdd20aSAndroid Build Coastguard Worker UnixSocketRaw::UnixSocketRaw() = default;
330*6dbdd20aSAndroid Build Coastguard Worker 
UnixSocketRaw(SockFamily family,SockType type)331*6dbdd20aSAndroid Build Coastguard Worker UnixSocketRaw::UnixSocketRaw(SockFamily family, SockType type)
332*6dbdd20aSAndroid Build Coastguard Worker     : UnixSocketRaw(CreateSocketHandle(family, type), family, type) {}
333*6dbdd20aSAndroid Build Coastguard Worker 
UnixSocketRaw(ScopedSocketHandle fd,SockFamily family,SockType type)334*6dbdd20aSAndroid Build Coastguard Worker UnixSocketRaw::UnixSocketRaw(ScopedSocketHandle fd,
335*6dbdd20aSAndroid Build Coastguard Worker                              SockFamily family,
336*6dbdd20aSAndroid Build Coastguard Worker                              SockType type)
337*6dbdd20aSAndroid Build Coastguard Worker     : fd_(std::move(fd)), family_(family), type_(type) {
338*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(fd_);
339*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
340*6dbdd20aSAndroid Build Coastguard Worker   const int no_sigpipe = 1;
341*6dbdd20aSAndroid Build Coastguard Worker   setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe));
342*6dbdd20aSAndroid Build Coastguard Worker #endif
343*6dbdd20aSAndroid Build Coastguard Worker 
344*6dbdd20aSAndroid Build Coastguard Worker   if (family == SockFamily::kInet || family == SockFamily::kInet6 ||
345*6dbdd20aSAndroid Build Coastguard Worker       family == SockFamily::kVsock) {
346*6dbdd20aSAndroid Build Coastguard Worker     int flag = 1;
347*6dbdd20aSAndroid Build Coastguard Worker     // The reinterpret_cast<const char*> is needed for Windows, where the 4th
348*6dbdd20aSAndroid Build Coastguard Worker     // arg is a const char* (on other POSIX system is a const void*).
349*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(!setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR,
350*6dbdd20aSAndroid Build Coastguard Worker                                reinterpret_cast<const char*>(&flag),
351*6dbdd20aSAndroid Build Coastguard Worker                                sizeof(flag)));
352*6dbdd20aSAndroid Build Coastguard Worker   }
353*6dbdd20aSAndroid Build Coastguard Worker 
354*6dbdd20aSAndroid Build Coastguard Worker   if (family == SockFamily::kInet || family == SockFamily::kInet6) {
355*6dbdd20aSAndroid Build Coastguard Worker     int flag = 1;
356*6dbdd20aSAndroid Build Coastguard Worker     // Disable Nagle's algorithm, optimize for low-latency.
357*6dbdd20aSAndroid Build Coastguard Worker     // See https://github.com/google/perfetto/issues/70.
358*6dbdd20aSAndroid Build Coastguard Worker     setsockopt(*fd_, IPPROTO_TCP, TCP_NODELAY,
359*6dbdd20aSAndroid Build Coastguard Worker                reinterpret_cast<const char*>(&flag), sizeof(flag));
360*6dbdd20aSAndroid Build Coastguard Worker   }
361*6dbdd20aSAndroid Build Coastguard Worker 
362*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
363*6dbdd20aSAndroid Build Coastguard Worker   // We use one event handle for all socket events, to stay consistent to what
364*6dbdd20aSAndroid Build Coastguard Worker   // we do on UNIX with the base::TaskRunner's poll().
365*6dbdd20aSAndroid Build Coastguard Worker   event_handle_.reset(WSACreateEvent());
366*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(event_handle_);
367*6dbdd20aSAndroid Build Coastguard Worker #else
368*6dbdd20aSAndroid Build Coastguard Worker   // There is no reason why a socket should outlive the process in case of
369*6dbdd20aSAndroid Build Coastguard Worker   // exec() by default, this is just working around a broken unix design.
370*6dbdd20aSAndroid Build Coastguard Worker   SetRetainOnExec(false);
371*6dbdd20aSAndroid Build Coastguard Worker #endif
372*6dbdd20aSAndroid Build Coastguard Worker }
373*6dbdd20aSAndroid Build Coastguard Worker 
SetBlocking(bool is_blocking)374*6dbdd20aSAndroid Build Coastguard Worker void UnixSocketRaw::SetBlocking(bool is_blocking) {
375*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
376*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
377*6dbdd20aSAndroid Build Coastguard Worker   unsigned long flag = is_blocking ? 0 : 1;  // FIONBIO has reverse logic.
378*6dbdd20aSAndroid Build Coastguard Worker   if (is_blocking) {
379*6dbdd20aSAndroid Build Coastguard Worker     // When switching between non-blocking -> blocking mode, we need to reset
380*6dbdd20aSAndroid Build Coastguard Worker     // the event handle registration, otherwise the call will fail.
381*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(WSAEventSelect(*fd_, *event_handle_, 0) == 0);
382*6dbdd20aSAndroid Build Coastguard Worker   }
383*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ioctlsocket(*fd_, static_cast<long>(FIONBIO), &flag) == 0);
384*6dbdd20aSAndroid Build Coastguard Worker   if (!is_blocking) {
385*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(
386*6dbdd20aSAndroid Build Coastguard Worker         WSAEventSelect(*fd_, *event_handle_,
387*6dbdd20aSAndroid Build Coastguard Worker                        FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE) == 0);
388*6dbdd20aSAndroid Build Coastguard Worker   }
389*6dbdd20aSAndroid Build Coastguard Worker #else
390*6dbdd20aSAndroid Build Coastguard Worker   int flags = fcntl(*fd_, F_GETFL, 0);
391*6dbdd20aSAndroid Build Coastguard Worker   if (!is_blocking) {
392*6dbdd20aSAndroid Build Coastguard Worker     flags |= O_NONBLOCK;
393*6dbdd20aSAndroid Build Coastguard Worker   } else {
394*6dbdd20aSAndroid Build Coastguard Worker     flags &= ~static_cast<int>(O_NONBLOCK);
395*6dbdd20aSAndroid Build Coastguard Worker   }
396*6dbdd20aSAndroid Build Coastguard Worker   int fcntl_res = fcntl(*fd_, F_SETFL, flags);
397*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(fcntl_res == 0);
398*6dbdd20aSAndroid Build Coastguard Worker #endif
399*6dbdd20aSAndroid Build Coastguard Worker }
400*6dbdd20aSAndroid Build Coastguard Worker 
SetRetainOnExec(bool retain)401*6dbdd20aSAndroid Build Coastguard Worker void UnixSocketRaw::SetRetainOnExec(bool retain) {
402*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
403*6dbdd20aSAndroid Build Coastguard Worker     !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
404*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
405*6dbdd20aSAndroid Build Coastguard Worker   int flags = fcntl(*fd_, F_GETFD, 0);
406*6dbdd20aSAndroid Build Coastguard Worker   if (retain) {
407*6dbdd20aSAndroid Build Coastguard Worker     flags &= ~static_cast<int>(FD_CLOEXEC);
408*6dbdd20aSAndroid Build Coastguard Worker   } else {
409*6dbdd20aSAndroid Build Coastguard Worker     flags |= FD_CLOEXEC;
410*6dbdd20aSAndroid Build Coastguard Worker   }
411*6dbdd20aSAndroid Build Coastguard Worker   int fcntl_res = fcntl(*fd_, F_SETFD, flags);
412*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(fcntl_res == 0);
413*6dbdd20aSAndroid Build Coastguard Worker #else
414*6dbdd20aSAndroid Build Coastguard Worker   ignore_result(retain);
415*6dbdd20aSAndroid Build Coastguard Worker #endif
416*6dbdd20aSAndroid Build Coastguard Worker }
417*6dbdd20aSAndroid Build Coastguard Worker 
DcheckIsBlocking(bool expected) const418*6dbdd20aSAndroid Build Coastguard Worker void UnixSocketRaw::DcheckIsBlocking(bool expected) const {
419*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
420*6dbdd20aSAndroid Build Coastguard Worker   ignore_result(expected);
421*6dbdd20aSAndroid Build Coastguard Worker #else
422*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
423*6dbdd20aSAndroid Build Coastguard Worker   bool is_blocking = (fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0;
424*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(is_blocking == expected);
425*6dbdd20aSAndroid Build Coastguard Worker #endif
426*6dbdd20aSAndroid Build Coastguard Worker }
427*6dbdd20aSAndroid Build Coastguard Worker 
Bind(const std::string & socket_name)428*6dbdd20aSAndroid Build Coastguard Worker bool UnixSocketRaw::Bind(const std::string& socket_name) {
429*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
430*6dbdd20aSAndroid Build Coastguard Worker   SockaddrAny addr = MakeSockAddr(family_, socket_name);
431*6dbdd20aSAndroid Build Coastguard Worker   if (addr.size == 0)
432*6dbdd20aSAndroid Build Coastguard Worker     return false;
433*6dbdd20aSAndroid Build Coastguard Worker 
434*6dbdd20aSAndroid Build Coastguard Worker   if (bind(*fd_, addr.addr(), addr.size)) {
435*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DPLOG("bind(%s)", socket_name.c_str());
436*6dbdd20aSAndroid Build Coastguard Worker     return false;
437*6dbdd20aSAndroid Build Coastguard Worker   }
438*6dbdd20aSAndroid Build Coastguard Worker 
439*6dbdd20aSAndroid Build Coastguard Worker   return true;
440*6dbdd20aSAndroid Build Coastguard Worker }
441*6dbdd20aSAndroid Build Coastguard Worker 
Listen()442*6dbdd20aSAndroid Build Coastguard Worker bool UnixSocketRaw::Listen() {
443*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
444*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(type_ == SockType::kStream || type_ == SockType::kSeqPacket);
445*6dbdd20aSAndroid Build Coastguard Worker   return listen(*fd_, SOMAXCONN) == 0;
446*6dbdd20aSAndroid Build Coastguard Worker }
447*6dbdd20aSAndroid Build Coastguard Worker 
Connect(const std::string & socket_name)448*6dbdd20aSAndroid Build Coastguard Worker bool UnixSocketRaw::Connect(const std::string& socket_name) {
449*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
450*6dbdd20aSAndroid Build Coastguard Worker   SockaddrAny addr = MakeSockAddr(family_, socket_name);
451*6dbdd20aSAndroid Build Coastguard Worker   if (addr.size == 0)
452*6dbdd20aSAndroid Build Coastguard Worker     return false;
453*6dbdd20aSAndroid Build Coastguard Worker 
454*6dbdd20aSAndroid Build Coastguard Worker   int res = PERFETTO_EINTR(connect(*fd_, addr.addr(), addr.size));
455*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
456*6dbdd20aSAndroid Build Coastguard Worker   bool continue_async = WSAGetLastError() == WSAEWOULDBLOCK;
457*6dbdd20aSAndroid Build Coastguard Worker #else
458*6dbdd20aSAndroid Build Coastguard Worker   bool continue_async = errno == EINPROGRESS;
459*6dbdd20aSAndroid Build Coastguard Worker #endif
460*6dbdd20aSAndroid Build Coastguard Worker   if (res && !continue_async)
461*6dbdd20aSAndroid Build Coastguard Worker     return false;
462*6dbdd20aSAndroid Build Coastguard Worker 
463*6dbdd20aSAndroid Build Coastguard Worker   return true;
464*6dbdd20aSAndroid Build Coastguard Worker }
465*6dbdd20aSAndroid Build Coastguard Worker 
Shutdown()466*6dbdd20aSAndroid Build Coastguard Worker void UnixSocketRaw::Shutdown() {
467*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
468*6dbdd20aSAndroid Build Coastguard Worker   // Somebody felt very strongly about the naming of this constant.
469*6dbdd20aSAndroid Build Coastguard Worker   shutdown(*fd_, SD_BOTH);
470*6dbdd20aSAndroid Build Coastguard Worker #else
471*6dbdd20aSAndroid Build Coastguard Worker   shutdown(*fd_, SHUT_RDWR);
472*6dbdd20aSAndroid Build Coastguard Worker #endif
473*6dbdd20aSAndroid Build Coastguard Worker   fd_.reset();
474*6dbdd20aSAndroid Build Coastguard Worker }
475*6dbdd20aSAndroid Build Coastguard Worker 
476*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
477*6dbdd20aSAndroid Build Coastguard Worker 
Send(const void * msg,size_t len,const int *,size_t num_fds)478*6dbdd20aSAndroid Build Coastguard Worker ssize_t UnixSocketRaw::Send(const void* msg,
479*6dbdd20aSAndroid Build Coastguard Worker                             size_t len,
480*6dbdd20aSAndroid Build Coastguard Worker                             const int* /*send_fds*/,
481*6dbdd20aSAndroid Build Coastguard Worker                             size_t num_fds) {
482*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(num_fds == 0);
483*6dbdd20aSAndroid Build Coastguard Worker   return sendto(*fd_, static_cast<const char*>(msg), static_cast<int>(len), 0,
484*6dbdd20aSAndroid Build Coastguard Worker                 nullptr, 0);
485*6dbdd20aSAndroid Build Coastguard Worker }
486*6dbdd20aSAndroid Build Coastguard Worker 
Receive(void * msg,size_t len,ScopedFile *,size_t)487*6dbdd20aSAndroid Build Coastguard Worker ssize_t UnixSocketRaw::Receive(void* msg,
488*6dbdd20aSAndroid Build Coastguard Worker                                size_t len,
489*6dbdd20aSAndroid Build Coastguard Worker                                ScopedFile* /*fd_vec*/,
490*6dbdd20aSAndroid Build Coastguard Worker                                size_t /*max_files*/) {
491*6dbdd20aSAndroid Build Coastguard Worker   return recv(*fd_, static_cast<char*>(msg), static_cast<int>(len), 0);
492*6dbdd20aSAndroid Build Coastguard Worker }
493*6dbdd20aSAndroid Build Coastguard Worker 
494*6dbdd20aSAndroid Build Coastguard Worker #else
495*6dbdd20aSAndroid Build Coastguard Worker // For the interested reader, Linux kernel dive to verify this is not only a
496*6dbdd20aSAndroid Build Coastguard Worker // theoretical possibility: sock_stream_sendmsg, if sock_alloc_send_pskb returns
497*6dbdd20aSAndroid Build Coastguard Worker // NULL [1] (which it does when it gets interrupted [2]), returns early with the
498*6dbdd20aSAndroid Build Coastguard Worker // amount of bytes already sent.
499*6dbdd20aSAndroid Build Coastguard Worker //
500*6dbdd20aSAndroid Build Coastguard Worker // [1]:
501*6dbdd20aSAndroid Build Coastguard Worker // https://elixir.bootlin.com/linux/v4.18.10/source/net/unix/af_unix.c#L1872
502*6dbdd20aSAndroid Build Coastguard Worker // [2]: https://elixir.bootlin.com/linux/v4.18.10/source/net/core/sock.c#L2101
SendMsgAllPosix(struct msghdr * msg)503*6dbdd20aSAndroid Build Coastguard Worker ssize_t UnixSocketRaw::SendMsgAllPosix(struct msghdr* msg) {
504*6dbdd20aSAndroid Build Coastguard Worker   // This does not make sense on non-blocking sockets.
505*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
506*6dbdd20aSAndroid Build Coastguard Worker 
507*6dbdd20aSAndroid Build Coastguard Worker   const bool is_blocking_with_timeout =
508*6dbdd20aSAndroid Build Coastguard Worker       tx_timeout_ms_ > 0 && ((fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0);
509*6dbdd20aSAndroid Build Coastguard Worker   const int64_t start_ms = GetWallTimeMs().count();
510*6dbdd20aSAndroid Build Coastguard Worker 
511*6dbdd20aSAndroid Build Coastguard Worker   // Waits until some space is available in the tx buffer.
512*6dbdd20aSAndroid Build Coastguard Worker   // Returns true if some buffer space is available, false if times out.
513*6dbdd20aSAndroid Build Coastguard Worker   auto poll_or_timeout = [&] {
514*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(is_blocking_with_timeout);
515*6dbdd20aSAndroid Build Coastguard Worker     const int64_t deadline = start_ms + tx_timeout_ms_;
516*6dbdd20aSAndroid Build Coastguard Worker     const int64_t now_ms = GetWallTimeMs().count();
517*6dbdd20aSAndroid Build Coastguard Worker     if (now_ms >= deadline)
518*6dbdd20aSAndroid Build Coastguard Worker       return false;  // Timed out
519*6dbdd20aSAndroid Build Coastguard Worker     const int timeout_ms = static_cast<int>(deadline - now_ms);
520*6dbdd20aSAndroid Build Coastguard Worker     pollfd pfd{*fd_, POLLOUT, 0};
521*6dbdd20aSAndroid Build Coastguard Worker     return PERFETTO_EINTR(poll(&pfd, 1, timeout_ms)) > 0;
522*6dbdd20aSAndroid Build Coastguard Worker   };
523*6dbdd20aSAndroid Build Coastguard Worker 
524*6dbdd20aSAndroid Build Coastguard Worker // We implement blocking sends that require a timeout as non-blocking + poll.
525*6dbdd20aSAndroid Build Coastguard Worker // This is because SO_SNDTIMEO doesn't work as expected (b/193234818). On linux
526*6dbdd20aSAndroid Build Coastguard Worker // we can just pass MSG_DONTWAIT to force the send to be non-blocking. On Mac,
527*6dbdd20aSAndroid Build Coastguard Worker // instead we need to flip the O_NONBLOCK flag back and forth.
528*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
529*6dbdd20aSAndroid Build Coastguard Worker   // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is
530*6dbdd20aSAndroid Build Coastguard Worker   // created with SO_NOSIGPIPE (See InitializeSocket()).
531*6dbdd20aSAndroid Build Coastguard Worker   int send_flags = 0;
532*6dbdd20aSAndroid Build Coastguard Worker 
533*6dbdd20aSAndroid Build Coastguard Worker   if (is_blocking_with_timeout)
534*6dbdd20aSAndroid Build Coastguard Worker     SetBlocking(false);
535*6dbdd20aSAndroid Build Coastguard Worker 
536*6dbdd20aSAndroid Build Coastguard Worker   auto reset_nonblock_on_exit = OnScopeExit([&] {
537*6dbdd20aSAndroid Build Coastguard Worker     if (is_blocking_with_timeout)
538*6dbdd20aSAndroid Build Coastguard Worker       SetBlocking(true);
539*6dbdd20aSAndroid Build Coastguard Worker   });
540*6dbdd20aSAndroid Build Coastguard Worker #else
541*6dbdd20aSAndroid Build Coastguard Worker   int send_flags = MSG_NOSIGNAL | (is_blocking_with_timeout ? MSG_DONTWAIT : 0);
542*6dbdd20aSAndroid Build Coastguard Worker #endif
543*6dbdd20aSAndroid Build Coastguard Worker 
544*6dbdd20aSAndroid Build Coastguard Worker   ssize_t total_sent = 0;
545*6dbdd20aSAndroid Build Coastguard Worker   while (msg->msg_iov) {
546*6dbdd20aSAndroid Build Coastguard Worker     ssize_t send_res = PERFETTO_EINTR(sendmsg(*fd_, msg, send_flags));
547*6dbdd20aSAndroid Build Coastguard Worker     if (send_res == -1 && IsAgain(errno)) {
548*6dbdd20aSAndroid Build Coastguard Worker       if (is_blocking_with_timeout && poll_or_timeout()) {
549*6dbdd20aSAndroid Build Coastguard Worker         continue;  // Tx buffer unblocked, repeat the loop.
550*6dbdd20aSAndroid Build Coastguard Worker       }
551*6dbdd20aSAndroid Build Coastguard Worker       return total_sent;
552*6dbdd20aSAndroid Build Coastguard Worker     } else if (send_res <= 0) {
553*6dbdd20aSAndroid Build Coastguard Worker       return send_res;  // An error occurred.
554*6dbdd20aSAndroid Build Coastguard Worker     } else {
555*6dbdd20aSAndroid Build Coastguard Worker       total_sent += send_res;
556*6dbdd20aSAndroid Build Coastguard Worker       ShiftMsgHdrPosix(static_cast<size_t>(send_res), msg);
557*6dbdd20aSAndroid Build Coastguard Worker       // Only send the ancillary data with the first sendmsg call.
558*6dbdd20aSAndroid Build Coastguard Worker       msg->msg_control = nullptr;
559*6dbdd20aSAndroid Build Coastguard Worker       msg->msg_controllen = 0;
560*6dbdd20aSAndroid Build Coastguard Worker     }
561*6dbdd20aSAndroid Build Coastguard Worker   }
562*6dbdd20aSAndroid Build Coastguard Worker   return total_sent;
563*6dbdd20aSAndroid Build Coastguard Worker }
564*6dbdd20aSAndroid Build Coastguard Worker 
Send(const void * msg,size_t len,const int * send_fds,size_t num_fds)565*6dbdd20aSAndroid Build Coastguard Worker ssize_t UnixSocketRaw::Send(const void* msg,
566*6dbdd20aSAndroid Build Coastguard Worker                             size_t len,
567*6dbdd20aSAndroid Build Coastguard Worker                             const int* send_fds,
568*6dbdd20aSAndroid Build Coastguard Worker                             size_t num_fds) {
569*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
570*6dbdd20aSAndroid Build Coastguard Worker   msghdr msg_hdr = {};
571*6dbdd20aSAndroid Build Coastguard Worker   iovec iov = {const_cast<void*>(msg), len};
572*6dbdd20aSAndroid Build Coastguard Worker   msg_hdr.msg_iov = &iov;
573*6dbdd20aSAndroid Build Coastguard Worker   msg_hdr.msg_iovlen = 1;
574*6dbdd20aSAndroid Build Coastguard Worker   alignas(cmsghdr) char control_buf[256];
575*6dbdd20aSAndroid Build Coastguard Worker 
576*6dbdd20aSAndroid Build Coastguard Worker   if (num_fds > 0) {
577*6dbdd20aSAndroid Build Coastguard Worker     const auto raw_ctl_data_sz = num_fds * sizeof(int);
578*6dbdd20aSAndroid Build Coastguard Worker     const CBufLenType control_buf_len =
579*6dbdd20aSAndroid Build Coastguard Worker         static_cast<CBufLenType>(CMSG_SPACE(raw_ctl_data_sz));
580*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(control_buf_len <= sizeof(control_buf));
581*6dbdd20aSAndroid Build Coastguard Worker     memset(control_buf, 0, sizeof(control_buf));
582*6dbdd20aSAndroid Build Coastguard Worker     msg_hdr.msg_control = control_buf;
583*6dbdd20aSAndroid Build Coastguard Worker     msg_hdr.msg_controllen = control_buf_len;  // used by CMSG_FIRSTHDR
584*6dbdd20aSAndroid Build Coastguard Worker     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr);
585*6dbdd20aSAndroid Build Coastguard Worker     cmsg->cmsg_level = SOL_SOCKET;
586*6dbdd20aSAndroid Build Coastguard Worker     cmsg->cmsg_type = SCM_RIGHTS;
587*6dbdd20aSAndroid Build Coastguard Worker     cmsg->cmsg_len = static_cast<CBufLenType>(CMSG_LEN(raw_ctl_data_sz));
588*6dbdd20aSAndroid Build Coastguard Worker     memcpy(CMSG_DATA(cmsg), send_fds, num_fds * sizeof(int));
589*6dbdd20aSAndroid Build Coastguard Worker     // note: if we were to send multiple cmsghdr structures, then
590*6dbdd20aSAndroid Build Coastguard Worker     // msg_hdr.msg_controllen would need to be adjusted, see "man 3 cmsg".
591*6dbdd20aSAndroid Build Coastguard Worker   }
592*6dbdd20aSAndroid Build Coastguard Worker 
593*6dbdd20aSAndroid Build Coastguard Worker   return SendMsgAllPosix(&msg_hdr);
594*6dbdd20aSAndroid Build Coastguard Worker }
595*6dbdd20aSAndroid Build Coastguard Worker 
Receive(void * msg,size_t len,ScopedFile * fd_vec,size_t max_files)596*6dbdd20aSAndroid Build Coastguard Worker ssize_t UnixSocketRaw::Receive(void* msg,
597*6dbdd20aSAndroid Build Coastguard Worker                                size_t len,
598*6dbdd20aSAndroid Build Coastguard Worker                                ScopedFile* fd_vec,
599*6dbdd20aSAndroid Build Coastguard Worker                                size_t max_files) {
600*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
601*6dbdd20aSAndroid Build Coastguard Worker   msghdr msg_hdr = {};
602*6dbdd20aSAndroid Build Coastguard Worker   iovec iov = {msg, len};
603*6dbdd20aSAndroid Build Coastguard Worker   msg_hdr.msg_iov = &iov;
604*6dbdd20aSAndroid Build Coastguard Worker   msg_hdr.msg_iovlen = 1;
605*6dbdd20aSAndroid Build Coastguard Worker   alignas(cmsghdr) char control_buf[256];
606*6dbdd20aSAndroid Build Coastguard Worker 
607*6dbdd20aSAndroid Build Coastguard Worker   if (max_files > 0) {
608*6dbdd20aSAndroid Build Coastguard Worker     msg_hdr.msg_control = control_buf;
609*6dbdd20aSAndroid Build Coastguard Worker     msg_hdr.msg_controllen =
610*6dbdd20aSAndroid Build Coastguard Worker         static_cast<CBufLenType>(CMSG_SPACE(max_files * sizeof(int)));
611*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(msg_hdr.msg_controllen <= sizeof(control_buf));
612*6dbdd20aSAndroid Build Coastguard Worker   }
613*6dbdd20aSAndroid Build Coastguard Worker   const ssize_t sz = PERFETTO_EINTR(recvmsg(*fd_, &msg_hdr, 0));
614*6dbdd20aSAndroid Build Coastguard Worker   if (sz <= 0) {
615*6dbdd20aSAndroid Build Coastguard Worker     return sz;
616*6dbdd20aSAndroid Build Coastguard Worker   }
617*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
618*6dbdd20aSAndroid Build Coastguard Worker 
619*6dbdd20aSAndroid Build Coastguard Worker   int* fds = nullptr;
620*6dbdd20aSAndroid Build Coastguard Worker   uint32_t fds_len = 0;
621*6dbdd20aSAndroid Build Coastguard Worker 
622*6dbdd20aSAndroid Build Coastguard Worker   if (max_files > 0) {
623*6dbdd20aSAndroid Build Coastguard Worker     for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr); cmsg;
624*6dbdd20aSAndroid Build Coastguard Worker          cmsg = CMSG_NXTHDR(&msg_hdr, cmsg)) {
625*6dbdd20aSAndroid Build Coastguard Worker       const size_t payload_len = cmsg->cmsg_len - CMSG_LEN(0);
626*6dbdd20aSAndroid Build Coastguard Worker       if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
627*6dbdd20aSAndroid Build Coastguard Worker         PERFETTO_DCHECK(payload_len % sizeof(int) == 0u);
628*6dbdd20aSAndroid Build Coastguard Worker         PERFETTO_CHECK(fds == nullptr);
629*6dbdd20aSAndroid Build Coastguard Worker         fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
630*6dbdd20aSAndroid Build Coastguard Worker         fds_len = static_cast<uint32_t>(payload_len / sizeof(int));
631*6dbdd20aSAndroid Build Coastguard Worker       }
632*6dbdd20aSAndroid Build Coastguard Worker     }
633*6dbdd20aSAndroid Build Coastguard Worker   }
634*6dbdd20aSAndroid Build Coastguard Worker 
635*6dbdd20aSAndroid Build Coastguard Worker   if (msg_hdr.msg_flags & MSG_TRUNC || msg_hdr.msg_flags & MSG_CTRUNC) {
636*6dbdd20aSAndroid Build Coastguard Worker     for (size_t i = 0; fds && i < fds_len; ++i)
637*6dbdd20aSAndroid Build Coastguard Worker       close(fds[i]);
638*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_ELOG(
639*6dbdd20aSAndroid Build Coastguard Worker         "Socket message truncated. This might be due to a SELinux denial on "
640*6dbdd20aSAndroid Build Coastguard Worker         "fd:use.");
641*6dbdd20aSAndroid Build Coastguard Worker     errno = EMSGSIZE;
642*6dbdd20aSAndroid Build Coastguard Worker     return -1;
643*6dbdd20aSAndroid Build Coastguard Worker   }
644*6dbdd20aSAndroid Build Coastguard Worker 
645*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; fds && i < fds_len; ++i) {
646*6dbdd20aSAndroid Build Coastguard Worker     if (i < max_files)
647*6dbdd20aSAndroid Build Coastguard Worker       fd_vec[i].reset(fds[i]);
648*6dbdd20aSAndroid Build Coastguard Worker     else
649*6dbdd20aSAndroid Build Coastguard Worker       close(fds[i]);
650*6dbdd20aSAndroid Build Coastguard Worker   }
651*6dbdd20aSAndroid Build Coastguard Worker 
652*6dbdd20aSAndroid Build Coastguard Worker   return sz;
653*6dbdd20aSAndroid Build Coastguard Worker }
654*6dbdd20aSAndroid Build Coastguard Worker #endif  // OS_WIN
655*6dbdd20aSAndroid Build Coastguard Worker 
SetTxTimeout(uint32_t timeout_ms)656*6dbdd20aSAndroid Build Coastguard Worker bool UnixSocketRaw::SetTxTimeout(uint32_t timeout_ms) {
657*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
658*6dbdd20aSAndroid Build Coastguard Worker   // On Unix-based systems, SO_SNDTIMEO isn't used for Send() because it's
659*6dbdd20aSAndroid Build Coastguard Worker   // unreliable (b/193234818). Instead we use non-blocking sendmsg() + poll().
660*6dbdd20aSAndroid Build Coastguard Worker   // See SendMsgAllPosix(). We still make the setsockopt call because
661*6dbdd20aSAndroid Build Coastguard Worker   // SO_SNDTIMEO also affects connect().
662*6dbdd20aSAndroid Build Coastguard Worker   tx_timeout_ms_ = timeout_ms;
663*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
664*6dbdd20aSAndroid Build Coastguard Worker   DWORD timeout = timeout_ms;
665*6dbdd20aSAndroid Build Coastguard Worker   ignore_result(tx_timeout_ms_);
666*6dbdd20aSAndroid Build Coastguard Worker #else
667*6dbdd20aSAndroid Build Coastguard Worker   struct timeval timeout {};
668*6dbdd20aSAndroid Build Coastguard Worker   uint32_t timeout_sec = timeout_ms / 1000;
669*6dbdd20aSAndroid Build Coastguard Worker   timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
670*6dbdd20aSAndroid Build Coastguard Worker   timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
671*6dbdd20aSAndroid Build Coastguard Worker       (timeout_ms - (timeout_sec * 1000)) * 1000);
672*6dbdd20aSAndroid Build Coastguard Worker #endif
673*6dbdd20aSAndroid Build Coastguard Worker   return setsockopt(*fd_, SOL_SOCKET, SO_SNDTIMEO,
674*6dbdd20aSAndroid Build Coastguard Worker                     reinterpret_cast<const char*>(&timeout),
675*6dbdd20aSAndroid Build Coastguard Worker                     sizeof(timeout)) == 0;
676*6dbdd20aSAndroid Build Coastguard Worker }
677*6dbdd20aSAndroid Build Coastguard Worker 
SetRxTimeout(uint32_t timeout_ms)678*6dbdd20aSAndroid Build Coastguard Worker bool UnixSocketRaw::SetRxTimeout(uint32_t timeout_ms) {
679*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(fd_);
680*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
681*6dbdd20aSAndroid Build Coastguard Worker   DWORD timeout = timeout_ms;
682*6dbdd20aSAndroid Build Coastguard Worker #else
683*6dbdd20aSAndroid Build Coastguard Worker   struct timeval timeout {};
684*6dbdd20aSAndroid Build Coastguard Worker   uint32_t timeout_sec = timeout_ms / 1000;
685*6dbdd20aSAndroid Build Coastguard Worker   timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec);
686*6dbdd20aSAndroid Build Coastguard Worker   timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>(
687*6dbdd20aSAndroid Build Coastguard Worker       (timeout_ms - (timeout_sec * 1000)) * 1000);
688*6dbdd20aSAndroid Build Coastguard Worker #endif
689*6dbdd20aSAndroid Build Coastguard Worker   return setsockopt(*fd_, SOL_SOCKET, SO_RCVTIMEO,
690*6dbdd20aSAndroid Build Coastguard Worker                     reinterpret_cast<const char*>(&timeout),
691*6dbdd20aSAndroid Build Coastguard Worker                     sizeof(timeout)) == 0;
692*6dbdd20aSAndroid Build Coastguard Worker }
693*6dbdd20aSAndroid Build Coastguard Worker 
GetSockAddr() const694*6dbdd20aSAndroid Build Coastguard Worker std::string UnixSocketRaw::GetSockAddr() const {
695*6dbdd20aSAndroid Build Coastguard Worker   struct sockaddr_storage stg {};
696*6dbdd20aSAndroid Build Coastguard Worker   socklen_t slen = sizeof(stg);
697*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(
698*6dbdd20aSAndroid Build Coastguard Worker       getsockname(*fd_, reinterpret_cast<struct sockaddr*>(&stg), &slen) == 0);
699*6dbdd20aSAndroid Build Coastguard Worker   char addr[255]{};
700*6dbdd20aSAndroid Build Coastguard Worker 
701*6dbdd20aSAndroid Build Coastguard Worker   if (stg.ss_family == AF_UNIX) {
702*6dbdd20aSAndroid Build Coastguard Worker     auto* saddr = reinterpret_cast<struct sockaddr_un*>(&stg);
703*6dbdd20aSAndroid Build Coastguard Worker     static_assert(sizeof(addr) >= sizeof(saddr->sun_path), "addr too small");
704*6dbdd20aSAndroid Build Coastguard Worker     memcpy(addr, saddr->sun_path, sizeof(saddr->sun_path));
705*6dbdd20aSAndroid Build Coastguard Worker     addr[0] = addr[0] == '\0' ? '@' : addr[0];
706*6dbdd20aSAndroid Build Coastguard Worker     addr[sizeof(saddr->sun_path) - 1] = '\0';
707*6dbdd20aSAndroid Build Coastguard Worker     return std::string(addr);
708*6dbdd20aSAndroid Build Coastguard Worker   }
709*6dbdd20aSAndroid Build Coastguard Worker 
710*6dbdd20aSAndroid Build Coastguard Worker   if (stg.ss_family == AF_INET) {
711*6dbdd20aSAndroid Build Coastguard Worker     auto* saddr = reinterpret_cast<struct sockaddr_in*>(&stg);
712*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof(addr)));
713*6dbdd20aSAndroid Build Coastguard Worker     uint16_t port = ntohs(saddr->sin_port);
714*6dbdd20aSAndroid Build Coastguard Worker     base::StackString<255> addr_and_port("%s:%" PRIu16, addr, port);
715*6dbdd20aSAndroid Build Coastguard Worker     return addr_and_port.ToStdString();
716*6dbdd20aSAndroid Build Coastguard Worker   }
717*6dbdd20aSAndroid Build Coastguard Worker 
718*6dbdd20aSAndroid Build Coastguard Worker   if (stg.ss_family == AF_INET6) {
719*6dbdd20aSAndroid Build Coastguard Worker     auto* saddr = reinterpret_cast<struct sockaddr_in6*>(&stg);
720*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(inet_ntop(AF_INET6, &saddr->sin6_addr, addr, sizeof(addr)));
721*6dbdd20aSAndroid Build Coastguard Worker     auto port = ntohs(saddr->sin6_port);
722*6dbdd20aSAndroid Build Coastguard Worker     base::StackString<255> addr_and_port("[%s]:%" PRIu16, addr, port);
723*6dbdd20aSAndroid Build Coastguard Worker     return addr_and_port.ToStdString();
724*6dbdd20aSAndroid Build Coastguard Worker   }
725*6dbdd20aSAndroid Build Coastguard Worker 
726*6dbdd20aSAndroid Build Coastguard Worker #if defined(AF_VSOCK) && (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
727*6dbdd20aSAndroid Build Coastguard Worker                           PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID))
728*6dbdd20aSAndroid Build Coastguard Worker   if (stg.ss_family == AF_VSOCK) {
729*6dbdd20aSAndroid Build Coastguard Worker     auto* saddr = reinterpret_cast<struct sockaddr_vm*>(&stg);
730*6dbdd20aSAndroid Build Coastguard Worker     base::StackString<255> addr_and_port("%s%d:%d", kVsockNamePrefix,
731*6dbdd20aSAndroid Build Coastguard Worker                                          saddr->svm_cid, saddr->svm_port);
732*6dbdd20aSAndroid Build Coastguard Worker     return addr_and_port.ToStdString();
733*6dbdd20aSAndroid Build Coastguard Worker   }
734*6dbdd20aSAndroid Build Coastguard Worker #endif
735*6dbdd20aSAndroid Build Coastguard Worker 
736*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_FATAL("GetSockAddr() unsupported on family %d", stg.ss_family);
737*6dbdd20aSAndroid Build Coastguard Worker }
738*6dbdd20aSAndroid Build Coastguard Worker 
739*6dbdd20aSAndroid Build Coastguard Worker #if defined(__GNUC__) && !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
740*6dbdd20aSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
741*6dbdd20aSAndroid Build Coastguard Worker #endif
742*6dbdd20aSAndroid Build Coastguard Worker 
743*6dbdd20aSAndroid Build Coastguard Worker // +--------------------+
744*6dbdd20aSAndroid Build Coastguard Worker // | UnixSocket methods |
745*6dbdd20aSAndroid Build Coastguard Worker // +--------------------+
746*6dbdd20aSAndroid Build Coastguard Worker 
747*6dbdd20aSAndroid Build Coastguard Worker // TODO(primiano): Add ThreadChecker to methods of this class.
748*6dbdd20aSAndroid Build Coastguard Worker 
749*6dbdd20aSAndroid Build Coastguard Worker // static
Listen(const std::string & socket_name,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type)750*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<UnixSocket> UnixSocket::Listen(const std::string& socket_name,
751*6dbdd20aSAndroid Build Coastguard Worker                                                EventListener* event_listener,
752*6dbdd20aSAndroid Build Coastguard Worker                                                TaskRunner* task_runner,
753*6dbdd20aSAndroid Build Coastguard Worker                                                SockFamily sock_family,
754*6dbdd20aSAndroid Build Coastguard Worker                                                SockType sock_type) {
755*6dbdd20aSAndroid Build Coastguard Worker   auto sock_raw = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
756*6dbdd20aSAndroid Build Coastguard Worker   if (!sock_raw || !sock_raw.Bind(socket_name))
757*6dbdd20aSAndroid Build Coastguard Worker     return nullptr;
758*6dbdd20aSAndroid Build Coastguard Worker 
759*6dbdd20aSAndroid Build Coastguard Worker   // Forward the call to the Listen() overload below.
760*6dbdd20aSAndroid Build Coastguard Worker   return Listen(sock_raw.ReleaseFd(), event_listener, task_runner, sock_family,
761*6dbdd20aSAndroid Build Coastguard Worker                 sock_type);
762*6dbdd20aSAndroid Build Coastguard Worker }
763*6dbdd20aSAndroid Build Coastguard Worker 
764*6dbdd20aSAndroid Build Coastguard Worker // static
Listen(ScopedSocketHandle fd,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type)765*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<UnixSocket> UnixSocket::Listen(ScopedSocketHandle fd,
766*6dbdd20aSAndroid Build Coastguard Worker                                                EventListener* event_listener,
767*6dbdd20aSAndroid Build Coastguard Worker                                                TaskRunner* task_runner,
768*6dbdd20aSAndroid Build Coastguard Worker                                                SockFamily sock_family,
769*6dbdd20aSAndroid Build Coastguard Worker                                                SockType sock_type) {
770*6dbdd20aSAndroid Build Coastguard Worker   return std::unique_ptr<UnixSocket>(new UnixSocket(
771*6dbdd20aSAndroid Build Coastguard Worker       event_listener, task_runner, std::move(fd), State::kListening,
772*6dbdd20aSAndroid Build Coastguard Worker       sock_family, sock_type, SockPeerCredMode::kDefault));
773*6dbdd20aSAndroid Build Coastguard Worker }
774*6dbdd20aSAndroid Build Coastguard Worker 
775*6dbdd20aSAndroid Build Coastguard Worker // static
Connect(const std::string & socket_name,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)776*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<UnixSocket> UnixSocket::Connect(
777*6dbdd20aSAndroid Build Coastguard Worker     const std::string& socket_name,
778*6dbdd20aSAndroid Build Coastguard Worker     EventListener* event_listener,
779*6dbdd20aSAndroid Build Coastguard Worker     TaskRunner* task_runner,
780*6dbdd20aSAndroid Build Coastguard Worker     SockFamily sock_family,
781*6dbdd20aSAndroid Build Coastguard Worker     SockType sock_type,
782*6dbdd20aSAndroid Build Coastguard Worker     SockPeerCredMode peer_cred_mode) {
783*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<UnixSocket> sock(new UnixSocket(
784*6dbdd20aSAndroid Build Coastguard Worker       event_listener, task_runner, sock_family, sock_type, peer_cred_mode));
785*6dbdd20aSAndroid Build Coastguard Worker   sock->DoConnect(socket_name);
786*6dbdd20aSAndroid Build Coastguard Worker   return sock;
787*6dbdd20aSAndroid Build Coastguard Worker }
788*6dbdd20aSAndroid Build Coastguard Worker 
789*6dbdd20aSAndroid Build Coastguard Worker // static
AdoptConnected(ScopedSocketHandle fd,EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)790*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<UnixSocket> UnixSocket::AdoptConnected(
791*6dbdd20aSAndroid Build Coastguard Worker     ScopedSocketHandle fd,
792*6dbdd20aSAndroid Build Coastguard Worker     EventListener* event_listener,
793*6dbdd20aSAndroid Build Coastguard Worker     TaskRunner* task_runner,
794*6dbdd20aSAndroid Build Coastguard Worker     SockFamily sock_family,
795*6dbdd20aSAndroid Build Coastguard Worker     SockType sock_type,
796*6dbdd20aSAndroid Build Coastguard Worker     SockPeerCredMode peer_cred_mode) {
797*6dbdd20aSAndroid Build Coastguard Worker   return std::unique_ptr<UnixSocket>(new UnixSocket(
798*6dbdd20aSAndroid Build Coastguard Worker       event_listener, task_runner, std::move(fd), State::kConnected,
799*6dbdd20aSAndroid Build Coastguard Worker       sock_family, sock_type, peer_cred_mode));
800*6dbdd20aSAndroid Build Coastguard Worker }
801*6dbdd20aSAndroid Build Coastguard Worker 
UnixSocket(EventListener * event_listener,TaskRunner * task_runner,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)802*6dbdd20aSAndroid Build Coastguard Worker UnixSocket::UnixSocket(EventListener* event_listener,
803*6dbdd20aSAndroid Build Coastguard Worker                        TaskRunner* task_runner,
804*6dbdd20aSAndroid Build Coastguard Worker                        SockFamily sock_family,
805*6dbdd20aSAndroid Build Coastguard Worker                        SockType sock_type,
806*6dbdd20aSAndroid Build Coastguard Worker                        SockPeerCredMode peer_cred_mode)
807*6dbdd20aSAndroid Build Coastguard Worker     : UnixSocket(event_listener,
808*6dbdd20aSAndroid Build Coastguard Worker                  task_runner,
809*6dbdd20aSAndroid Build Coastguard Worker                  ScopedSocketHandle(),
810*6dbdd20aSAndroid Build Coastguard Worker                  State::kDisconnected,
811*6dbdd20aSAndroid Build Coastguard Worker                  sock_family,
812*6dbdd20aSAndroid Build Coastguard Worker                  sock_type,
813*6dbdd20aSAndroid Build Coastguard Worker                  peer_cred_mode) {}
814*6dbdd20aSAndroid Build Coastguard Worker 
UnixSocket(EventListener * event_listener,TaskRunner * task_runner,ScopedSocketHandle adopt_fd,State adopt_state,SockFamily sock_family,SockType sock_type,SockPeerCredMode peer_cred_mode)815*6dbdd20aSAndroid Build Coastguard Worker UnixSocket::UnixSocket(EventListener* event_listener,
816*6dbdd20aSAndroid Build Coastguard Worker                        TaskRunner* task_runner,
817*6dbdd20aSAndroid Build Coastguard Worker                        ScopedSocketHandle adopt_fd,
818*6dbdd20aSAndroid Build Coastguard Worker                        State adopt_state,
819*6dbdd20aSAndroid Build Coastguard Worker                        SockFamily sock_family,
820*6dbdd20aSAndroid Build Coastguard Worker                        SockType sock_type,
821*6dbdd20aSAndroid Build Coastguard Worker                        SockPeerCredMode peer_cred_mode)
822*6dbdd20aSAndroid Build Coastguard Worker     : peer_cred_mode_(peer_cred_mode),
823*6dbdd20aSAndroid Build Coastguard Worker       event_listener_(event_listener),
824*6dbdd20aSAndroid Build Coastguard Worker       task_runner_(task_runner),
825*6dbdd20aSAndroid Build Coastguard Worker       weak_ptr_factory_(this) {
826*6dbdd20aSAndroid Build Coastguard Worker   state_ = State::kDisconnected;
827*6dbdd20aSAndroid Build Coastguard Worker   if (adopt_state == State::kDisconnected) {
828*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(!adopt_fd);
829*6dbdd20aSAndroid Build Coastguard Worker     sock_raw_ = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
830*6dbdd20aSAndroid Build Coastguard Worker     if (!sock_raw_)
831*6dbdd20aSAndroid Build Coastguard Worker       return;
832*6dbdd20aSAndroid Build Coastguard Worker   } else if (adopt_state == State::kConnected) {
833*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(adopt_fd);
834*6dbdd20aSAndroid Build Coastguard Worker     sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
835*6dbdd20aSAndroid Build Coastguard Worker     state_ = State::kConnected;
836*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
837*6dbdd20aSAndroid Build Coastguard Worker     if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
838*6dbdd20aSAndroid Build Coastguard Worker       ReadPeerCredentialsPosix();
839*6dbdd20aSAndroid Build Coastguard Worker #endif
840*6dbdd20aSAndroid Build Coastguard Worker   } else if (adopt_state == State::kListening) {
841*6dbdd20aSAndroid Build Coastguard Worker     // We get here from Listen().
842*6dbdd20aSAndroid Build Coastguard Worker 
843*6dbdd20aSAndroid Build Coastguard Worker     // |adopt_fd| might genuinely be invalid if the bind() failed.
844*6dbdd20aSAndroid Build Coastguard Worker     if (!adopt_fd)
845*6dbdd20aSAndroid Build Coastguard Worker       return;
846*6dbdd20aSAndroid Build Coastguard Worker 
847*6dbdd20aSAndroid Build Coastguard Worker     sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
848*6dbdd20aSAndroid Build Coastguard Worker     if (!sock_raw_.Listen()) {
849*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DPLOG("listen() failed");
850*6dbdd20aSAndroid Build Coastguard Worker       return;
851*6dbdd20aSAndroid Build Coastguard Worker     }
852*6dbdd20aSAndroid Build Coastguard Worker     state_ = State::kListening;
853*6dbdd20aSAndroid Build Coastguard Worker   } else {
854*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_FATAL("Unexpected adopt_state");  // Unfeasible.
855*6dbdd20aSAndroid Build Coastguard Worker   }
856*6dbdd20aSAndroid Build Coastguard Worker 
857*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(sock_raw_);
858*6dbdd20aSAndroid Build Coastguard Worker 
859*6dbdd20aSAndroid Build Coastguard Worker   sock_raw_.SetBlocking(false);
860*6dbdd20aSAndroid Build Coastguard Worker 
861*6dbdd20aSAndroid Build Coastguard Worker   WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
862*6dbdd20aSAndroid Build Coastguard Worker 
863*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->AddFileDescriptorWatch(sock_raw_.watch_handle(), [weak_ptr] {
864*6dbdd20aSAndroid Build Coastguard Worker     if (weak_ptr)
865*6dbdd20aSAndroid Build Coastguard Worker       weak_ptr->OnEvent();
866*6dbdd20aSAndroid Build Coastguard Worker   });
867*6dbdd20aSAndroid Build Coastguard Worker }
868*6dbdd20aSAndroid Build Coastguard Worker 
~UnixSocket()869*6dbdd20aSAndroid Build Coastguard Worker UnixSocket::~UnixSocket() {
870*6dbdd20aSAndroid Build Coastguard Worker   // The implicit dtor of |weak_ptr_factory_| will no-op pending callbacks.
871*6dbdd20aSAndroid Build Coastguard Worker   Shutdown(true);
872*6dbdd20aSAndroid Build Coastguard Worker }
873*6dbdd20aSAndroid Build Coastguard Worker 
ReleaseSocket()874*6dbdd20aSAndroid Build Coastguard Worker UnixSocketRaw UnixSocket::ReleaseSocket() {
875*6dbdd20aSAndroid Build Coastguard Worker   // This will invalidate any pending calls to OnEvent.
876*6dbdd20aSAndroid Build Coastguard Worker   state_ = State::kDisconnected;
877*6dbdd20aSAndroid Build Coastguard Worker   if (sock_raw_)
878*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
879*6dbdd20aSAndroid Build Coastguard Worker 
880*6dbdd20aSAndroid Build Coastguard Worker   return std::move(sock_raw_);
881*6dbdd20aSAndroid Build Coastguard Worker }
882*6dbdd20aSAndroid Build Coastguard Worker 
883*6dbdd20aSAndroid Build Coastguard Worker // Called only by the Connect() static constructor.
DoConnect(const std::string & socket_name)884*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::DoConnect(const std::string& socket_name) {
885*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(state_ == State::kDisconnected);
886*6dbdd20aSAndroid Build Coastguard Worker 
887*6dbdd20aSAndroid Build Coastguard Worker   // This is the only thing that can gracefully fail in the ctor.
888*6dbdd20aSAndroid Build Coastguard Worker   if (!sock_raw_)
889*6dbdd20aSAndroid Build Coastguard Worker     return NotifyConnectionState(false);
890*6dbdd20aSAndroid Build Coastguard Worker 
891*6dbdd20aSAndroid Build Coastguard Worker   if (!sock_raw_.Connect(socket_name))
892*6dbdd20aSAndroid Build Coastguard Worker     return NotifyConnectionState(false);
893*6dbdd20aSAndroid Build Coastguard Worker 
894*6dbdd20aSAndroid Build Coastguard Worker   // At this point either connect() succeeded or started asynchronously
895*6dbdd20aSAndroid Build Coastguard Worker   // (errno = EINPROGRESS).
896*6dbdd20aSAndroid Build Coastguard Worker   state_ = State::kConnecting;
897*6dbdd20aSAndroid Build Coastguard Worker 
898*6dbdd20aSAndroid Build Coastguard Worker   // Even if the socket is non-blocking, connecting to a UNIX socket can be
899*6dbdd20aSAndroid Build Coastguard Worker   // acknowledged straight away rather than returning EINPROGRESS.
900*6dbdd20aSAndroid Build Coastguard Worker   // The decision here is to deal with the two cases uniformly, at the cost of
901*6dbdd20aSAndroid Build Coastguard Worker   // delaying the straight-away-connect() case by one task, to avoid depending
902*6dbdd20aSAndroid Build Coastguard Worker   // on implementation details of UNIX socket on the various OSes.
903*6dbdd20aSAndroid Build Coastguard Worker   // Posting the OnEvent() below emulates a wakeup of the FD watch. OnEvent(),
904*6dbdd20aSAndroid Build Coastguard Worker   // which knows how to deal with spurious wakeups, will poll the SO_ERROR and
905*6dbdd20aSAndroid Build Coastguard Worker   // evolve, if necessary, the state into either kConnected or kDisconnected.
906*6dbdd20aSAndroid Build Coastguard Worker   WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
907*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostTask([weak_ptr] {
908*6dbdd20aSAndroid Build Coastguard Worker     if (weak_ptr)
909*6dbdd20aSAndroid Build Coastguard Worker       weak_ptr->OnEvent();
910*6dbdd20aSAndroid Build Coastguard Worker   });
911*6dbdd20aSAndroid Build Coastguard Worker }
912*6dbdd20aSAndroid Build Coastguard Worker 
913*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
ReadPeerCredentialsPosix()914*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::ReadPeerCredentialsPosix() {
915*6dbdd20aSAndroid Build Coastguard Worker   // Peer credentials are supported only on AF_UNIX sockets.
916*6dbdd20aSAndroid Build Coastguard Worker   if (sock_raw_.family() != SockFamily::kUnix)
917*6dbdd20aSAndroid Build Coastguard Worker     return;
918*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(peer_cred_mode_ != SockPeerCredMode::kIgnore);
919*6dbdd20aSAndroid Build Coastguard Worker 
920*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
921*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
922*6dbdd20aSAndroid Build Coastguard Worker   struct ucred user_cred;
923*6dbdd20aSAndroid Build Coastguard Worker   socklen_t len = sizeof(user_cred);
924*6dbdd20aSAndroid Build Coastguard Worker   int fd = sock_raw_.fd();
925*6dbdd20aSAndroid Build Coastguard Worker   int res = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &user_cred, &len);
926*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(res == 0);
927*6dbdd20aSAndroid Build Coastguard Worker   peer_uid_ = user_cred.uid;
928*6dbdd20aSAndroid Build Coastguard Worker   peer_pid_ = user_cred.pid;
929*6dbdd20aSAndroid Build Coastguard Worker #elif PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
930*6dbdd20aSAndroid Build Coastguard Worker   struct xucred user_cred;
931*6dbdd20aSAndroid Build Coastguard Worker   socklen_t len = sizeof(user_cred);
932*6dbdd20aSAndroid Build Coastguard Worker   int res = getsockopt(sock_raw_.fd(), 0, LOCAL_PEERCRED, &user_cred, &len);
933*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(res == 0 && user_cred.cr_version == XUCRED_VERSION);
934*6dbdd20aSAndroid Build Coastguard Worker   peer_uid_ = static_cast<uid_t>(user_cred.cr_uid);
935*6dbdd20aSAndroid Build Coastguard Worker   // There is no pid in the LOCAL_PEERCREDS for MacOS / FreeBSD.
936*6dbdd20aSAndroid Build Coastguard Worker #endif
937*6dbdd20aSAndroid Build Coastguard Worker }
938*6dbdd20aSAndroid Build Coastguard Worker #endif  // !OS_WIN
939*6dbdd20aSAndroid Build Coastguard Worker 
940*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
OnEvent()941*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::OnEvent() {
942*6dbdd20aSAndroid Build Coastguard Worker   WSANETWORKEVENTS evts{};
943*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(WSAEnumNetworkEvents(sock_raw_.fd(), sock_raw_.watch_handle(),
944*6dbdd20aSAndroid Build Coastguard Worker                                       &evts) == 0);
945*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kDisconnected)
946*6dbdd20aSAndroid Build Coastguard Worker     return;  // Some spurious event, typically queued just before Shutdown().
947*6dbdd20aSAndroid Build Coastguard Worker 
948*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kConnecting && (evts.lNetworkEvents & FD_CONNECT)) {
949*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(sock_raw_);
950*6dbdd20aSAndroid Build Coastguard Worker     int err = evts.iErrorCode[FD_CONNECT_BIT];
951*6dbdd20aSAndroid Build Coastguard Worker     if (err) {
952*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DPLOG("Connection error: %d", err);
953*6dbdd20aSAndroid Build Coastguard Worker       Shutdown(false);
954*6dbdd20aSAndroid Build Coastguard Worker       event_listener_->OnConnect(this, false /* connected */);
955*6dbdd20aSAndroid Build Coastguard Worker       return;
956*6dbdd20aSAndroid Build Coastguard Worker     }
957*6dbdd20aSAndroid Build Coastguard Worker 
958*6dbdd20aSAndroid Build Coastguard Worker     // kReadOnConnect is not supported on Windows.
959*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(peer_cred_mode_ != SockPeerCredMode::kReadOnConnect);
960*6dbdd20aSAndroid Build Coastguard Worker     state_ = State::kConnected;
961*6dbdd20aSAndroid Build Coastguard Worker     event_listener_->OnConnect(this, true /* connected */);
962*6dbdd20aSAndroid Build Coastguard Worker   }
963*6dbdd20aSAndroid Build Coastguard Worker 
964*6dbdd20aSAndroid Build Coastguard Worker   // This is deliberately NOT an else-if. When a client socket connects and
965*6dbdd20aSAndroid Build Coastguard Worker   // there is already data queued, the following will happen within the same
966*6dbdd20aSAndroid Build Coastguard Worker   // OnEvent() call:
967*6dbdd20aSAndroid Build Coastguard Worker   // 1. The block above will transition kConnecting -> kConnected.
968*6dbdd20aSAndroid Build Coastguard Worker   // 2. This block will cause an OnDataAvailable() call.
969*6dbdd20aSAndroid Build Coastguard Worker   // Unlike UNIX, where poll() keeps signalling the event until the client
970*6dbdd20aSAndroid Build Coastguard Worker   // does a recv(), Windows is more picky and stops signalling the event until
971*6dbdd20aSAndroid Build Coastguard Worker   // the next call to recv() is made. In other words, in Windows we cannot
972*6dbdd20aSAndroid Build Coastguard Worker   // miss an OnDataAvailable() call or the event pump will stop.
973*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kConnected) {
974*6dbdd20aSAndroid Build Coastguard Worker     if (evts.lNetworkEvents & FD_READ) {
975*6dbdd20aSAndroid Build Coastguard Worker       event_listener_->OnDataAvailable(this);
976*6dbdd20aSAndroid Build Coastguard Worker       // TODO(primiano): I am very conflicted here. Because of the behavior
977*6dbdd20aSAndroid Build Coastguard Worker       // described above, if the event listener doesn't do a Recv() call in
978*6dbdd20aSAndroid Build Coastguard Worker       // the OnDataAvailable() callback, WinSock won't notify the event ever
979*6dbdd20aSAndroid Build Coastguard Worker       // again. On one side, I don't see any reason why a client should decide
980*6dbdd20aSAndroid Build Coastguard Worker       // to not do a Recv() in OnDataAvailable. On the other side, the
981*6dbdd20aSAndroid Build Coastguard Worker       // behavior here diverges from UNIX, where OnDataAvailable() would be
982*6dbdd20aSAndroid Build Coastguard Worker       // re-posted immediately. In both cases, not doing a Recv() in
983*6dbdd20aSAndroid Build Coastguard Worker       // OnDataAvailable, leads to something bad (getting stuck on Windows,
984*6dbdd20aSAndroid Build Coastguard Worker       // getting in a hot loop on Linux), so doesn't feel we should worry too
985*6dbdd20aSAndroid Build Coastguard Worker       // much about this. If we wanted to keep the behavrior consistent, here
986*6dbdd20aSAndroid Build Coastguard Worker       // we should do something like: `if (sock_raw_)
987*6dbdd20aSAndroid Build Coastguard Worker       // sock_raw_.SetBlocking(false)` (Note that the socket might be closed
988*6dbdd20aSAndroid Build Coastguard Worker       // by the time we come back here, hence the if part).
989*6dbdd20aSAndroid Build Coastguard Worker       return;
990*6dbdd20aSAndroid Build Coastguard Worker     }
991*6dbdd20aSAndroid Build Coastguard Worker     // Could read EOF and disconnect here.
992*6dbdd20aSAndroid Build Coastguard Worker     if (evts.lNetworkEvents & FD_CLOSE) {
993*6dbdd20aSAndroid Build Coastguard Worker       Shutdown(true);
994*6dbdd20aSAndroid Build Coastguard Worker       return;
995*6dbdd20aSAndroid Build Coastguard Worker     }
996*6dbdd20aSAndroid Build Coastguard Worker   }
997*6dbdd20aSAndroid Build Coastguard Worker 
998*6dbdd20aSAndroid Build Coastguard Worker   // New incoming connection.
999*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kListening && (evts.lNetworkEvents & FD_ACCEPT)) {
1000*6dbdd20aSAndroid Build Coastguard Worker     // There could be more than one incoming connection behind each FD watch
1001*6dbdd20aSAndroid Build Coastguard Worker     // notification. Drain'em all.
1002*6dbdd20aSAndroid Build Coastguard Worker     for (;;) {
1003*6dbdd20aSAndroid Build Coastguard Worker       // Note: right now we don't need the remote endpoint, hence we pass
1004*6dbdd20aSAndroid Build Coastguard Worker       // nullptr to |addr| and |addrlen|. If we ever need to do so, be
1005*6dbdd20aSAndroid Build Coastguard Worker       // extremely careful. Windows' WinSock API will happily write more than
1006*6dbdd20aSAndroid Build Coastguard Worker       // |addrlen| (hence corrupt the stack) if the |addr| argument passed is
1007*6dbdd20aSAndroid Build Coastguard Worker       // not big enough (e.g. passing a struct sockaddr_in to a AF_UNIX
1008*6dbdd20aSAndroid Build Coastguard Worker       // socket, where sizeof(sockaddr_un) is >> sizef(sockaddr_in)). It seems
1009*6dbdd20aSAndroid Build Coastguard Worker       // a Windows / CRT bug in the AF_UNIX implementation.
1010*6dbdd20aSAndroid Build Coastguard Worker       ScopedSocketHandle new_fd(accept(sock_raw_.fd(), nullptr, nullptr));
1011*6dbdd20aSAndroid Build Coastguard Worker       if (!new_fd)
1012*6dbdd20aSAndroid Build Coastguard Worker         return;
1013*6dbdd20aSAndroid Build Coastguard Worker       std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
1014*6dbdd20aSAndroid Build Coastguard Worker           event_listener_, task_runner_, std::move(new_fd), State::kConnected,
1015*6dbdd20aSAndroid Build Coastguard Worker           sock_raw_.family(), sock_raw_.type(), peer_cred_mode_));
1016*6dbdd20aSAndroid Build Coastguard Worker       event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
1017*6dbdd20aSAndroid Build Coastguard Worker     }
1018*6dbdd20aSAndroid Build Coastguard Worker   }
1019*6dbdd20aSAndroid Build Coastguard Worker }
1020*6dbdd20aSAndroid Build Coastguard Worker #else
OnEvent()1021*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::OnEvent() {
1022*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kDisconnected)
1023*6dbdd20aSAndroid Build Coastguard Worker     return;  // Some spurious event, typically queued just before Shutdown().
1024*6dbdd20aSAndroid Build Coastguard Worker 
1025*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kConnected)
1026*6dbdd20aSAndroid Build Coastguard Worker     return event_listener_->OnDataAvailable(this);
1027*6dbdd20aSAndroid Build Coastguard Worker 
1028*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kConnecting) {
1029*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(sock_raw_);
1030*6dbdd20aSAndroid Build Coastguard Worker     int sock_err = EINVAL;
1031*6dbdd20aSAndroid Build Coastguard Worker     socklen_t err_len = sizeof(sock_err);
1032*6dbdd20aSAndroid Build Coastguard Worker     int res =
1033*6dbdd20aSAndroid Build Coastguard Worker         getsockopt(sock_raw_.fd(), SOL_SOCKET, SO_ERROR, &sock_err, &err_len);
1034*6dbdd20aSAndroid Build Coastguard Worker 
1035*6dbdd20aSAndroid Build Coastguard Worker     if (res == 0 && sock_err == EINPROGRESS)
1036*6dbdd20aSAndroid Build Coastguard Worker       return;  // Not connected yet, just a spurious FD watch wakeup.
1037*6dbdd20aSAndroid Build Coastguard Worker     if (res == 0 && sock_err == 0) {
1038*6dbdd20aSAndroid Build Coastguard Worker       if (peer_cred_mode_ == SockPeerCredMode::kReadOnConnect)
1039*6dbdd20aSAndroid Build Coastguard Worker         ReadPeerCredentialsPosix();
1040*6dbdd20aSAndroid Build Coastguard Worker       state_ = State::kConnected;
1041*6dbdd20aSAndroid Build Coastguard Worker       return event_listener_->OnConnect(this, true /* connected */);
1042*6dbdd20aSAndroid Build Coastguard Worker     }
1043*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("Connection error: %s", strerror(sock_err));
1044*6dbdd20aSAndroid Build Coastguard Worker     Shutdown(false);
1045*6dbdd20aSAndroid Build Coastguard Worker     return event_listener_->OnConnect(this, false /* connected */);
1046*6dbdd20aSAndroid Build Coastguard Worker   }
1047*6dbdd20aSAndroid Build Coastguard Worker 
1048*6dbdd20aSAndroid Build Coastguard Worker   // New incoming connection.
1049*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == State::kListening) {
1050*6dbdd20aSAndroid Build Coastguard Worker     // There could be more than one incoming connection behind each FD watch
1051*6dbdd20aSAndroid Build Coastguard Worker     // notification. Drain'em all.
1052*6dbdd20aSAndroid Build Coastguard Worker     for (;;) {
1053*6dbdd20aSAndroid Build Coastguard Worker       ScopedFile new_fd(
1054*6dbdd20aSAndroid Build Coastguard Worker           PERFETTO_EINTR(accept(sock_raw_.fd(), nullptr, nullptr)));
1055*6dbdd20aSAndroid Build Coastguard Worker       if (!new_fd)
1056*6dbdd20aSAndroid Build Coastguard Worker         return;
1057*6dbdd20aSAndroid Build Coastguard Worker       std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
1058*6dbdd20aSAndroid Build Coastguard Worker           event_listener_, task_runner_, std::move(new_fd), State::kConnected,
1059*6dbdd20aSAndroid Build Coastguard Worker           sock_raw_.family(), sock_raw_.type(), peer_cred_mode_));
1060*6dbdd20aSAndroid Build Coastguard Worker       event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
1061*6dbdd20aSAndroid Build Coastguard Worker     }
1062*6dbdd20aSAndroid Build Coastguard Worker   }
1063*6dbdd20aSAndroid Build Coastguard Worker }
1064*6dbdd20aSAndroid Build Coastguard Worker #endif
1065*6dbdd20aSAndroid Build Coastguard Worker 
Send(const void * msg,size_t len,const int * send_fds,size_t num_fds)1066*6dbdd20aSAndroid Build Coastguard Worker bool UnixSocket::Send(const void* msg,
1067*6dbdd20aSAndroid Build Coastguard Worker                       size_t len,
1068*6dbdd20aSAndroid Build Coastguard Worker                       const int* send_fds,
1069*6dbdd20aSAndroid Build Coastguard Worker                       size_t num_fds) {
1070*6dbdd20aSAndroid Build Coastguard Worker   if (state_ != State::kConnected) {
1071*6dbdd20aSAndroid Build Coastguard Worker     errno = ENOTCONN;
1072*6dbdd20aSAndroid Build Coastguard Worker     return false;
1073*6dbdd20aSAndroid Build Coastguard Worker   }
1074*6dbdd20aSAndroid Build Coastguard Worker 
1075*6dbdd20aSAndroid Build Coastguard Worker   sock_raw_.SetBlocking(true);
1076*6dbdd20aSAndroid Build Coastguard Worker   const ssize_t sz = sock_raw_.Send(msg, len, send_fds, num_fds);
1077*6dbdd20aSAndroid Build Coastguard Worker   sock_raw_.SetBlocking(false);
1078*6dbdd20aSAndroid Build Coastguard Worker 
1079*6dbdd20aSAndroid Build Coastguard Worker   if (sz == static_cast<ssize_t>(len)) {
1080*6dbdd20aSAndroid Build Coastguard Worker     return true;
1081*6dbdd20aSAndroid Build Coastguard Worker   }
1082*6dbdd20aSAndroid Build Coastguard Worker 
1083*6dbdd20aSAndroid Build Coastguard Worker   // If we ever decide to support non-blocking sends again, here we should
1084*6dbdd20aSAndroid Build Coastguard Worker   // watch for both EAGAIN and EWOULDBLOCK (see base::IsAgain()).
1085*6dbdd20aSAndroid Build Coastguard Worker 
1086*6dbdd20aSAndroid Build Coastguard Worker   // If sendmsg() succeeds but the returned size is >= 0 and < |len| it means
1087*6dbdd20aSAndroid Build Coastguard Worker   // that the endpoint disconnected in the middle of the read, and we managed
1088*6dbdd20aSAndroid Build Coastguard Worker   // to send only a portion of the buffer.
1089*6dbdd20aSAndroid Build Coastguard Worker   // If sz < 0, either the other endpoint disconnected (ECONNRESET) or some
1090*6dbdd20aSAndroid Build Coastguard Worker   // other error happened. In both cases we should just give up.
1091*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DPLOG("sendmsg() failed");
1092*6dbdd20aSAndroid Build Coastguard Worker   Shutdown(true);
1093*6dbdd20aSAndroid Build Coastguard Worker   return false;
1094*6dbdd20aSAndroid Build Coastguard Worker }
1095*6dbdd20aSAndroid Build Coastguard Worker 
Shutdown(bool notify)1096*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::Shutdown(bool notify) {
1097*6dbdd20aSAndroid Build Coastguard Worker   WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
1098*6dbdd20aSAndroid Build Coastguard Worker   if (notify) {
1099*6dbdd20aSAndroid Build Coastguard Worker     if (state_ == State::kConnected) {
1100*6dbdd20aSAndroid Build Coastguard Worker       task_runner_->PostTask([weak_ptr] {
1101*6dbdd20aSAndroid Build Coastguard Worker         if (weak_ptr)
1102*6dbdd20aSAndroid Build Coastguard Worker           weak_ptr->event_listener_->OnDisconnect(weak_ptr.get());
1103*6dbdd20aSAndroid Build Coastguard Worker       });
1104*6dbdd20aSAndroid Build Coastguard Worker     } else if (state_ == State::kConnecting) {
1105*6dbdd20aSAndroid Build Coastguard Worker       task_runner_->PostTask([weak_ptr] {
1106*6dbdd20aSAndroid Build Coastguard Worker         if (weak_ptr)
1107*6dbdd20aSAndroid Build Coastguard Worker           weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false);
1108*6dbdd20aSAndroid Build Coastguard Worker       });
1109*6dbdd20aSAndroid Build Coastguard Worker     }
1110*6dbdd20aSAndroid Build Coastguard Worker   }
1111*6dbdd20aSAndroid Build Coastguard Worker 
1112*6dbdd20aSAndroid Build Coastguard Worker   if (sock_raw_) {
1113*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->RemoveFileDescriptorWatch(sock_raw_.watch_handle());
1114*6dbdd20aSAndroid Build Coastguard Worker     sock_raw_.Shutdown();
1115*6dbdd20aSAndroid Build Coastguard Worker   }
1116*6dbdd20aSAndroid Build Coastguard Worker   state_ = State::kDisconnected;
1117*6dbdd20aSAndroid Build Coastguard Worker }
1118*6dbdd20aSAndroid Build Coastguard Worker 
Receive(void * msg,size_t len,ScopedFile * fd_vec,size_t max_files)1119*6dbdd20aSAndroid Build Coastguard Worker size_t UnixSocket::Receive(void* msg,
1120*6dbdd20aSAndroid Build Coastguard Worker                            size_t len,
1121*6dbdd20aSAndroid Build Coastguard Worker                            ScopedFile* fd_vec,
1122*6dbdd20aSAndroid Build Coastguard Worker                            size_t max_files) {
1123*6dbdd20aSAndroid Build Coastguard Worker   if (state_ != State::kConnected)
1124*6dbdd20aSAndroid Build Coastguard Worker     return 0;
1125*6dbdd20aSAndroid Build Coastguard Worker 
1126*6dbdd20aSAndroid Build Coastguard Worker   const ssize_t sz = sock_raw_.Receive(msg, len, fd_vec, max_files);
1127*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
1128*6dbdd20aSAndroid Build Coastguard Worker   bool async_would_block = WSAGetLastError() == WSAEWOULDBLOCK;
1129*6dbdd20aSAndroid Build Coastguard Worker #else
1130*6dbdd20aSAndroid Build Coastguard Worker   bool async_would_block = IsAgain(errno);
1131*6dbdd20aSAndroid Build Coastguard Worker #endif
1132*6dbdd20aSAndroid Build Coastguard Worker   if (sz < 0 && async_would_block)
1133*6dbdd20aSAndroid Build Coastguard Worker     return 0;
1134*6dbdd20aSAndroid Build Coastguard Worker 
1135*6dbdd20aSAndroid Build Coastguard Worker   if (sz <= 0) {
1136*6dbdd20aSAndroid Build Coastguard Worker     Shutdown(true);
1137*6dbdd20aSAndroid Build Coastguard Worker     return 0;
1138*6dbdd20aSAndroid Build Coastguard Worker   }
1139*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(static_cast<size_t>(sz) <= len);
1140*6dbdd20aSAndroid Build Coastguard Worker   return static_cast<size_t>(sz);
1141*6dbdd20aSAndroid Build Coastguard Worker }
1142*6dbdd20aSAndroid Build Coastguard Worker 
ReceiveString(size_t max_length)1143*6dbdd20aSAndroid Build Coastguard Worker std::string UnixSocket::ReceiveString(size_t max_length) {
1144*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<char[]> buf(new char[max_length + 1]);
1145*6dbdd20aSAndroid Build Coastguard Worker   size_t rsize = Receive(buf.get(), max_length);
1146*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(rsize <= max_length);
1147*6dbdd20aSAndroid Build Coastguard Worker   buf[rsize] = '\0';
1148*6dbdd20aSAndroid Build Coastguard Worker   return std::string(buf.get());
1149*6dbdd20aSAndroid Build Coastguard Worker }
1150*6dbdd20aSAndroid Build Coastguard Worker 
NotifyConnectionState(bool success)1151*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::NotifyConnectionState(bool success) {
1152*6dbdd20aSAndroid Build Coastguard Worker   if (!success)
1153*6dbdd20aSAndroid Build Coastguard Worker     Shutdown(false);
1154*6dbdd20aSAndroid Build Coastguard Worker 
1155*6dbdd20aSAndroid Build Coastguard Worker   WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
1156*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostTask([weak_ptr, success] {
1157*6dbdd20aSAndroid Build Coastguard Worker     if (weak_ptr)
1158*6dbdd20aSAndroid Build Coastguard Worker       weak_ptr->event_listener_->OnConnect(weak_ptr.get(), success);
1159*6dbdd20aSAndroid Build Coastguard Worker   });
1160*6dbdd20aSAndroid Build Coastguard Worker }
1161*6dbdd20aSAndroid Build Coastguard Worker 
~EventListener()1162*6dbdd20aSAndroid Build Coastguard Worker UnixSocket::EventListener::~EventListener() {}
OnNewIncomingConnection(UnixSocket *,std::unique_ptr<UnixSocket>)1163*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::EventListener::OnNewIncomingConnection(
1164*6dbdd20aSAndroid Build Coastguard Worker     UnixSocket*,
1165*6dbdd20aSAndroid Build Coastguard Worker     std::unique_ptr<UnixSocket>) {}
OnConnect(UnixSocket *,bool)1166*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {}
OnDisconnect(UnixSocket *)1167*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {}
OnDataAvailable(UnixSocket *)1168*6dbdd20aSAndroid Build Coastguard Worker void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {}
1169*6dbdd20aSAndroid Build Coastguard Worker 
1170*6dbdd20aSAndroid Build Coastguard Worker }  // namespace base
1171*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
1172