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