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