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