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/base/unix_socket.h" 18 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <sys/socket.h> 24 #include <sys/stat.h> 25 #include <sys/types.h> 26 #include <sys/un.h> 27 #include <unistd.h> 28 29 #include <algorithm> 30 #include <memory> 31 32 #include "perfetto/base/build_config.h" 33 #include "perfetto/base/logging.h" 34 #include "perfetto/base/task_runner.h" 35 #include "perfetto/base/utils.h" 36 37 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) 38 #include <sys/ucred.h> 39 #endif 40 41 namespace perfetto { 42 namespace base { 43 44 // The CMSG_* macros use NULL instead of nullptr. 45 #pragma GCC diagnostic push 46 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) 47 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" 48 #endif 49 50 namespace { 51 // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is 52 // created with SO_NOSIGPIPE (See InitializeSocket()). 53 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) 54 constexpr int kNoSigPipe = 0; 55 #else 56 constexpr int kNoSigPipe = MSG_NOSIGNAL; 57 #endif 58 59 // Android takes an int instead of socklen_t for the control buffer size. 60 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 61 using CBufLenType = size_t; 62 #else 63 using CBufLenType = socklen_t; 64 #endif 65 66 inline int GetUnixSockType(SockType type) { 67 switch (type) { 68 case SockType::kStream: 69 return SOCK_STREAM; 70 case SockType::kDgram: 71 return SOCK_DGRAM; 72 case SockType::kSeqPacket: 73 return SOCK_SEQPACKET; 74 } 75 PERFETTO_CHECK(false); 76 } 77 78 bool MakeSockAddr(const std::string& socket_name, 79 sockaddr_un* addr, 80 socklen_t* addr_size) { 81 memset(addr, 0, sizeof(*addr)); 82 const size_t name_len = socket_name.size(); 83 if (name_len >= sizeof(addr->sun_path)) { 84 errno = ENAMETOOLONG; 85 return false; 86 } 87 memcpy(addr->sun_path, socket_name.data(), name_len); 88 if (addr->sun_path[0] == '@') 89 addr->sun_path[0] = '\0'; 90 addr->sun_family = AF_UNIX; 91 *addr_size = static_cast<socklen_t>( 92 __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1); 93 return true; 94 } 95 96 } // namespace 97 98 // +-----------------------+ 99 // | UnixSocketRaw methods | 100 // +-----------------------+ 101 102 // static 103 void UnixSocketRaw::ShiftMsgHdr(size_t n, struct msghdr* msg) { 104 using LenType = decltype(msg->msg_iovlen); // Mac and Linux don't agree. 105 for (LenType i = 0; i < msg->msg_iovlen; ++i) { 106 struct iovec* vec = &msg->msg_iov[i]; 107 if (n < vec->iov_len) { 108 // We sent a part of this iovec. 109 vec->iov_base = reinterpret_cast<char*>(vec->iov_base) + n; 110 vec->iov_len -= n; 111 msg->msg_iov = vec; 112 msg->msg_iovlen -= i; 113 return; 114 } 115 // We sent the whole iovec. 116 n -= vec->iov_len; 117 } 118 // We sent all the iovecs. 119 PERFETTO_CHECK(n == 0); 120 msg->msg_iovlen = 0; 121 msg->msg_iov = nullptr; 122 } 123 124 // static 125 std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePair(SockType t) { 126 int fds[2]; 127 if (socketpair(AF_UNIX, GetUnixSockType(t), 0, fds) != 0) 128 return std::make_pair(UnixSocketRaw(), UnixSocketRaw()); 129 130 return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), t), 131 UnixSocketRaw(ScopedFile(fds[1]), t)); 132 } 133 134 UnixSocketRaw::UnixSocketRaw() = default; 135 136 UnixSocketRaw::UnixSocketRaw(SockType type) 137 : UnixSocketRaw(ScopedFile(socket(AF_UNIX, GetUnixSockType(type), 0)), 138 type) {} 139 140 UnixSocketRaw::UnixSocketRaw(ScopedFile fd, SockType type) 141 : fd_(std::move(fd)), type_(type) { 142 PERFETTO_CHECK(fd_); 143 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) 144 const int no_sigpipe = 1; 145 setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe)); 146 #endif 147 148 // There is no reason why a socket should outlive the process in case of 149 // exec() by default, this is just working around a broken unix design. 150 int fcntl_res = fcntl(*fd_, F_SETFD, FD_CLOEXEC); 151 PERFETTO_CHECK(fcntl_res == 0); 152 } 153 154 void UnixSocketRaw::SetBlocking(bool is_blocking) { 155 PERFETTO_DCHECK(fd_); 156 int flags = fcntl(*fd_, F_GETFL, 0); 157 if (!is_blocking) { 158 flags |= O_NONBLOCK; 159 } else { 160 flags &= ~static_cast<int>(O_NONBLOCK); 161 } 162 bool fcntl_res = fcntl(*fd_, F_SETFL, flags); 163 PERFETTO_CHECK(fcntl_res == 0); 164 } 165 166 void UnixSocketRaw::RetainOnExec() { 167 PERFETTO_DCHECK(fd_); 168 int flags = fcntl(*fd_, F_GETFD, 0); 169 flags &= ~static_cast<int>(FD_CLOEXEC); 170 bool fcntl_res = fcntl(*fd_, F_SETFD, flags); 171 PERFETTO_CHECK(fcntl_res == 0); 172 } 173 174 bool UnixSocketRaw::IsBlocking() const { 175 PERFETTO_DCHECK(fd_); 176 return (fcntl(*fd_, F_GETFL, 0) & O_NONBLOCK) == 0; 177 } 178 179 bool UnixSocketRaw::Bind(const std::string& socket_name) { 180 PERFETTO_DCHECK(fd_); 181 sockaddr_un addr; 182 socklen_t addr_size; 183 if (!MakeSockAddr(socket_name, &addr, &addr_size)) 184 return false; 185 186 if (bind(*fd_, reinterpret_cast<sockaddr*>(&addr), addr_size)) { 187 PERFETTO_DPLOG("bind(%s)", socket_name.c_str()); 188 return false; 189 } 190 191 return true; 192 } 193 194 bool UnixSocketRaw::Listen() { 195 PERFETTO_DCHECK(fd_); 196 PERFETTO_DCHECK(type_ == SockType::kStream || type_ == SockType::kSeqPacket); 197 return listen(*fd_, SOMAXCONN) == 0; 198 } 199 200 bool UnixSocketRaw::Connect(const std::string& socket_name) { 201 PERFETTO_DCHECK(fd_); 202 sockaddr_un addr; 203 socklen_t addr_size; 204 if (!MakeSockAddr(socket_name, &addr, &addr_size)) 205 return false; 206 207 int res = PERFETTO_EINTR( 208 connect(*fd_, reinterpret_cast<sockaddr*>(&addr), addr_size)); 209 if (res && errno != EINPROGRESS) 210 return false; 211 212 return true; 213 } 214 215 void UnixSocketRaw::Shutdown() { 216 shutdown(*fd_, SHUT_RDWR); 217 fd_.reset(); 218 } 219 220 // For the interested reader, Linux kernel dive to verify this is not only a 221 // theoretical possibility: sock_stream_sendmsg, if sock_alloc_send_pskb returns 222 // NULL [1] (which it does when it gets interrupted [2]), returns early with the 223 // amount of bytes already sent. 224 // 225 // [1]: 226 // https://elixir.bootlin.com/linux/v4.18.10/source/net/unix/af_unix.c#L1872 227 // [2]: https://elixir.bootlin.com/linux/v4.18.10/source/net/core/sock.c#L2101 228 ssize_t UnixSocketRaw::SendMsgAll(struct msghdr* msg) { 229 // This does not make sense on non-blocking sockets. 230 PERFETTO_DCHECK(fd_); 231 232 ssize_t total_sent = 0; 233 while (msg->msg_iov) { 234 ssize_t sent = PERFETTO_EINTR(sendmsg(*fd_, msg, kNoSigPipe)); 235 if (sent <= 0) { 236 if (sent == -1 && IsAgain(errno)) 237 return total_sent; 238 return sent; 239 } 240 total_sent += sent; 241 ShiftMsgHdr(static_cast<size_t>(sent), msg); 242 // Only send the ancillary data with the first sendmsg call. 243 msg->msg_control = nullptr; 244 msg->msg_controllen = 0; 245 } 246 return total_sent; 247 } 248 249 ssize_t UnixSocketRaw::Send(const void* msg, 250 size_t len, 251 const int* send_fds, 252 size_t num_fds) { 253 PERFETTO_DCHECK(fd_); 254 msghdr msg_hdr = {}; 255 iovec iov = {const_cast<void*>(msg), len}; 256 msg_hdr.msg_iov = &iov; 257 msg_hdr.msg_iovlen = 1; 258 alignas(cmsghdr) char control_buf[256]; 259 260 if (num_fds > 0) { 261 const auto raw_ctl_data_sz = num_fds * sizeof(int); 262 const CBufLenType control_buf_len = 263 static_cast<CBufLenType>(CMSG_SPACE(raw_ctl_data_sz)); 264 PERFETTO_CHECK(control_buf_len <= sizeof(control_buf)); 265 memset(control_buf, 0, sizeof(control_buf)); 266 msg_hdr.msg_control = control_buf; 267 msg_hdr.msg_controllen = control_buf_len; // used by CMSG_FIRSTHDR 268 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr); 269 cmsg->cmsg_level = SOL_SOCKET; 270 cmsg->cmsg_type = SCM_RIGHTS; 271 cmsg->cmsg_len = static_cast<CBufLenType>(CMSG_LEN(raw_ctl_data_sz)); 272 memcpy(CMSG_DATA(cmsg), send_fds, num_fds * sizeof(int)); 273 // note: if we were to send multiple cmsghdr structures, then 274 // msg_hdr.msg_controllen would need to be adjusted, see "man 3 cmsg". 275 } 276 277 return SendMsgAll(&msg_hdr); 278 } 279 280 ssize_t UnixSocketRaw::Receive(void* msg, 281 size_t len, 282 ScopedFile* fd_vec, 283 size_t max_files) { 284 PERFETTO_DCHECK(fd_); 285 msghdr msg_hdr = {}; 286 iovec iov = {msg, len}; 287 msg_hdr.msg_iov = &iov; 288 msg_hdr.msg_iovlen = 1; 289 alignas(cmsghdr) char control_buf[256]; 290 291 if (max_files > 0) { 292 msg_hdr.msg_control = control_buf; 293 msg_hdr.msg_controllen = 294 static_cast<CBufLenType>(CMSG_SPACE(max_files * sizeof(int))); 295 PERFETTO_CHECK(msg_hdr.msg_controllen <= sizeof(control_buf)); 296 } 297 const ssize_t sz = PERFETTO_EINTR(recvmsg(*fd_, &msg_hdr, 0)); 298 if (sz <= 0) { 299 return sz; 300 } 301 PERFETTO_CHECK(static_cast<size_t>(sz) <= len); 302 303 int* fds = nullptr; 304 uint32_t fds_len = 0; 305 306 if (max_files > 0) { 307 for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg_hdr); cmsg; 308 cmsg = CMSG_NXTHDR(&msg_hdr, cmsg)) { 309 const size_t payload_len = cmsg->cmsg_len - CMSG_LEN(0); 310 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { 311 PERFETTO_DCHECK(payload_len % sizeof(int) == 0u); 312 PERFETTO_CHECK(fds == nullptr); 313 fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); 314 fds_len = static_cast<uint32_t>(payload_len / sizeof(int)); 315 } 316 } 317 } 318 319 if (msg_hdr.msg_flags & MSG_TRUNC || msg_hdr.msg_flags & MSG_CTRUNC) { 320 for (size_t i = 0; fds && i < fds_len; ++i) 321 close(fds[i]); 322 errno = EMSGSIZE; 323 return -1; 324 } 325 326 for (size_t i = 0; fds && i < fds_len; ++i) { 327 if (i < max_files) 328 fd_vec[i].reset(fds[i]); 329 else 330 close(fds[i]); 331 } 332 333 return sz; 334 } 335 336 bool UnixSocketRaw::SetTxTimeout(uint32_t timeout_ms) { 337 PERFETTO_DCHECK(fd_); 338 struct timeval timeout {}; 339 uint32_t timeout_sec = timeout_ms / 1000; 340 timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec); 341 timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>( 342 (timeout_ms - (timeout_sec * 1000)) * 1000); 343 344 return setsockopt(*fd_, SOL_SOCKET, SO_SNDTIMEO, 345 reinterpret_cast<const char*>(&timeout), 346 sizeof(timeout)) == 0; 347 } 348 349 bool UnixSocketRaw::SetRxTimeout(uint32_t timeout_ms) { 350 PERFETTO_DCHECK(fd_); 351 struct timeval timeout {}; 352 uint32_t timeout_sec = timeout_ms / 1000; 353 timeout.tv_sec = static_cast<decltype(timeout.tv_sec)>(timeout_sec); 354 timeout.tv_usec = static_cast<decltype(timeout.tv_usec)>( 355 (timeout_ms - (timeout_sec * 1000)) * 1000); 356 357 return setsockopt(*fd_, SOL_SOCKET, SO_RCVTIMEO, 358 reinterpret_cast<const char*>(&timeout), 359 sizeof(timeout)) == 0; 360 } 361 362 #pragma GCC diagnostic pop 363 364 // +--------------------+ 365 // | UnixSocket methods | 366 // +--------------------+ 367 368 // TODO(primiano): Add ThreadChecker to methods of this class. 369 370 // static 371 std::unique_ptr<UnixSocket> UnixSocket::Listen(const std::string& socket_name, 372 EventListener* event_listener, 373 TaskRunner* task_runner, 374 SockType sock_type) { 375 auto sock_raw = UnixSocketRaw::CreateMayFail(sock_type); 376 if (!sock_raw || !sock_raw.Bind(socket_name)) 377 return nullptr; 378 379 // Forward the call to the Listen() overload below. 380 return Listen(sock_raw.ReleaseFd(), event_listener, task_runner, sock_type); 381 } 382 383 // static 384 std::unique_ptr<UnixSocket> UnixSocket::Listen(ScopedFile fd, 385 EventListener* event_listener, 386 TaskRunner* task_runner, 387 SockType sock_type) { 388 return std::unique_ptr<UnixSocket>( 389 new UnixSocket(event_listener, task_runner, std::move(fd), 390 State::kListening, sock_type)); 391 } 392 393 // static 394 std::unique_ptr<UnixSocket> UnixSocket::Connect(const std::string& socket_name, 395 EventListener* event_listener, 396 TaskRunner* task_runner, 397 SockType sock_type) { 398 std::unique_ptr<UnixSocket> sock( 399 new UnixSocket(event_listener, task_runner, sock_type)); 400 sock->DoConnect(socket_name); 401 return sock; 402 } 403 404 // static 405 std::unique_ptr<UnixSocket> UnixSocket::AdoptConnected( 406 ScopedFile fd, 407 EventListener* event_listener, 408 TaskRunner* task_runner, 409 SockType sock_type) { 410 return std::unique_ptr<UnixSocket>( 411 new UnixSocket(event_listener, task_runner, std::move(fd), 412 State::kConnected, sock_type)); 413 } 414 415 UnixSocket::UnixSocket(EventListener* event_listener, 416 TaskRunner* task_runner, 417 SockType sock_type) 418 : UnixSocket(event_listener, 419 task_runner, 420 ScopedFile(), 421 State::kDisconnected, 422 sock_type) {} 423 424 UnixSocket::UnixSocket(EventListener* event_listener, 425 TaskRunner* task_runner, 426 ScopedFile adopt_fd, 427 State adopt_state, 428 SockType sock_type) 429 : event_listener_(event_listener), 430 task_runner_(task_runner), 431 weak_ptr_factory_(this) { 432 state_ = State::kDisconnected; 433 if (adopt_state == State::kDisconnected) { 434 PERFETTO_DCHECK(!adopt_fd); 435 sock_raw_ = UnixSocketRaw::CreateMayFail(sock_type); 436 if (!sock_raw_) { 437 last_error_ = errno; 438 return; 439 } 440 } else if (adopt_state == State::kConnected) { 441 PERFETTO_DCHECK(adopt_fd); 442 sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_type); 443 state_ = State::kConnected; 444 ReadPeerCredentials(); 445 } else if (adopt_state == State::kListening) { 446 // We get here from Listen(). 447 448 // |adopt_fd| might genuinely be invalid if the bind() failed. 449 if (!adopt_fd) { 450 last_error_ = errno; 451 return; 452 } 453 454 sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_type); 455 if (!sock_raw_.Listen()) { 456 last_error_ = errno; 457 PERFETTO_DPLOG("listen()"); 458 return; 459 } 460 state_ = State::kListening; 461 } else { 462 PERFETTO_FATAL("Unexpected adopt_state"); // Unfeasible. 463 } 464 465 PERFETTO_CHECK(sock_raw_); 466 last_error_ = 0; 467 468 sock_raw_.SetBlocking(false); 469 470 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr(); 471 task_runner_->AddFileDescriptorWatch(sock_raw_.fd(), [weak_ptr] { 472 if (weak_ptr) 473 weak_ptr->OnEvent(); 474 }); 475 } 476 477 UnixSocket::~UnixSocket() { 478 // The implicit dtor of |weak_ptr_factory_| will no-op pending callbacks. 479 Shutdown(true); 480 } 481 482 UnixSocketRaw UnixSocket::ReleaseSocket() { 483 // This will invalidate any pending calls to OnEvent. 484 state_ = State::kDisconnected; 485 if (sock_raw_) 486 task_runner_->RemoveFileDescriptorWatch(sock_raw_.fd()); 487 488 return std::move(sock_raw_); 489 } 490 491 // Called only by the Connect() static constructor. 492 void UnixSocket::DoConnect(const std::string& socket_name) { 493 PERFETTO_DCHECK(state_ == State::kDisconnected); 494 495 // This is the only thing that can gracefully fail in the ctor. 496 if (!sock_raw_) 497 return NotifyConnectionState(false); 498 499 if (!sock_raw_.Connect(socket_name)) { 500 last_error_ = errno; 501 return NotifyConnectionState(false); 502 } 503 504 // At this point either connect() succeeded or started asynchronously 505 // (errno = EINPROGRESS). 506 last_error_ = 0; 507 state_ = State::kConnecting; 508 509 // Even if the socket is non-blocking, connecting to a UNIX socket can be 510 // acknowledged straight away rather than returning EINPROGRESS. 511 // The decision here is to deal with the two cases uniformly, at the cost of 512 // delaying the straight-away-connect() case by one task, to avoid depending 513 // on implementation details of UNIX socket on the various OSes. 514 // Posting the OnEvent() below emulates a wakeup of the FD watch. OnEvent(), 515 // which knows how to deal with spurious wakeups, will poll the SO_ERROR and 516 // evolve, if necessary, the state into either kConnected or kDisconnected. 517 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr(); 518 task_runner_->PostTask([weak_ptr] { 519 if (weak_ptr) 520 weak_ptr->OnEvent(); 521 }); 522 } 523 524 void UnixSocket::ReadPeerCredentials() { 525 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 526 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) 527 struct ucred user_cred; 528 socklen_t len = sizeof(user_cred); 529 int fd = sock_raw_.fd(); 530 int res = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &user_cred, &len); 531 PERFETTO_CHECK(res == 0); 532 peer_uid_ = user_cred.uid; 533 peer_pid_ = user_cred.pid; 534 #else 535 struct xucred user_cred; 536 socklen_t len = sizeof(user_cred); 537 int res = getsockopt(sock_raw_.fd(), 0, LOCAL_PEERCRED, &user_cred, &len); 538 PERFETTO_CHECK(res == 0 && user_cred.cr_version == XUCRED_VERSION); 539 peer_uid_ = static_cast<uid_t>(user_cred.cr_uid); 540 // There is no pid in the LOCAL_PEERCREDS for MacOS / FreeBSD. 541 #endif 542 } 543 544 void UnixSocket::OnEvent() { 545 if (state_ == State::kDisconnected) 546 return; // Some spurious event, typically queued just before Shutdown(). 547 548 if (state_ == State::kConnected) 549 return event_listener_->OnDataAvailable(this); 550 551 if (state_ == State::kConnecting) { 552 PERFETTO_DCHECK(sock_raw_); 553 int sock_err = EINVAL; 554 socklen_t err_len = sizeof(sock_err); 555 int res = 556 getsockopt(sock_raw_.fd(), SOL_SOCKET, SO_ERROR, &sock_err, &err_len); 557 if (res == 0 && sock_err == EINPROGRESS) 558 return; // Not connected yet, just a spurious FD watch wakeup. 559 if (res == 0 && sock_err == 0) { 560 ReadPeerCredentials(); 561 state_ = State::kConnected; 562 return event_listener_->OnConnect(this, true /* connected */); 563 } 564 last_error_ = sock_err; 565 Shutdown(false); 566 return event_listener_->OnConnect(this, false /* connected */); 567 } 568 569 // New incoming connection. 570 if (state_ == State::kListening) { 571 // There could be more than one incoming connection behind each FD watch 572 // notification. Drain'em all. 573 for (;;) { 574 sockaddr_un cli_addr = {}; 575 socklen_t size = sizeof(cli_addr); 576 ScopedFile new_fd(PERFETTO_EINTR(accept( 577 sock_raw_.fd(), reinterpret_cast<sockaddr*>(&cli_addr), &size))); 578 if (!new_fd) 579 return; 580 std::unique_ptr<UnixSocket> new_sock( 581 new UnixSocket(event_listener_, task_runner_, std::move(new_fd), 582 State::kConnected, sock_raw_.type())); 583 event_listener_->OnNewIncomingConnection(this, std::move(new_sock)); 584 } 585 } 586 } 587 588 bool UnixSocket::Send(const void* msg, 589 size_t len, 590 const int* send_fds, 591 size_t num_fds, 592 BlockingMode blocking_mode) { 593 // TODO(b/117139237): Non-blocking sends are broken because we do not 594 // properly handle partial sends. 595 PERFETTO_DCHECK(blocking_mode == BlockingMode::kBlocking); 596 597 if (state_ != State::kConnected) { 598 errno = last_error_ = ENOTCONN; 599 return false; 600 } 601 602 if (blocking_mode == BlockingMode::kBlocking) 603 sock_raw_.SetBlocking(true); 604 const ssize_t sz = sock_raw_.Send(msg, len, send_fds, num_fds); 605 int saved_errno = errno; 606 if (blocking_mode == BlockingMode::kBlocking) 607 sock_raw_.SetBlocking(false); 608 609 if (sz == static_cast<ssize_t>(len)) { 610 last_error_ = 0; 611 return true; 612 } 613 614 // If sendmsg() succeds but the returned size is < |len| it means that the 615 // endpoint disconnected in the middle of the read, and we managed to send 616 // only a portion of the buffer. In this case we should just give up. 617 618 if (sz < 0 && (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK)) { 619 // A genuine out-of-buffer. The client should retry or give up. 620 // Man pages specify that EAGAIN and EWOULDBLOCK have the same semantic here 621 // and clients should check for both. 622 last_error_ = EAGAIN; 623 return false; 624 } 625 626 // Either the the other endpoint disconnect (ECONNRESET) or some other error 627 // happened. 628 last_error_ = saved_errno; 629 PERFETTO_DPLOG("sendmsg() failed"); 630 Shutdown(true); 631 return false; 632 } 633 634 void UnixSocket::Shutdown(bool notify) { 635 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr(); 636 if (notify) { 637 if (state_ == State::kConnected) { 638 task_runner_->PostTask([weak_ptr] { 639 if (weak_ptr) 640 weak_ptr->event_listener_->OnDisconnect(weak_ptr.get()); 641 }); 642 } else if (state_ == State::kConnecting) { 643 task_runner_->PostTask([weak_ptr] { 644 if (weak_ptr) 645 weak_ptr->event_listener_->OnConnect(weak_ptr.get(), false); 646 }); 647 } 648 } 649 650 if (sock_raw_) { 651 task_runner_->RemoveFileDescriptorWatch(sock_raw_.fd()); 652 sock_raw_.Shutdown(); 653 } 654 state_ = State::kDisconnected; 655 } 656 657 size_t UnixSocket::Receive(void* msg, 658 size_t len, 659 ScopedFile* fd_vec, 660 size_t max_files) { 661 if (state_ != State::kConnected) { 662 last_error_ = ENOTCONN; 663 return 0; 664 } 665 666 const ssize_t sz = sock_raw_.Receive(msg, len, fd_vec, max_files); 667 if (sz < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { 668 last_error_ = EAGAIN; 669 return 0; 670 } 671 if (sz <= 0) { 672 last_error_ = errno; 673 Shutdown(true); 674 return 0; 675 } 676 PERFETTO_CHECK(static_cast<size_t>(sz) <= len); 677 return static_cast<size_t>(sz); 678 } 679 680 std::string UnixSocket::ReceiveString(size_t max_length) { 681 std::unique_ptr<char[]> buf(new char[max_length + 1]); 682 size_t rsize = Receive(buf.get(), max_length); 683 PERFETTO_CHECK(static_cast<size_t>(rsize) <= max_length); 684 buf[static_cast<size_t>(rsize)] = '\0'; 685 return std::string(buf.get()); 686 } 687 688 void UnixSocket::NotifyConnectionState(bool success) { 689 if (!success) 690 Shutdown(false); 691 692 WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr(); 693 task_runner_->PostTask([weak_ptr, success] { 694 if (weak_ptr) 695 weak_ptr->event_listener_->OnConnect(weak_ptr.get(), success); 696 }); 697 } 698 699 UnixSocket::EventListener::~EventListener() {} 700 void UnixSocket::EventListener::OnNewIncomingConnection( 701 UnixSocket*, 702 std::unique_ptr<UnixSocket>) {} 703 void UnixSocket::EventListener::OnConnect(UnixSocket*, bool) {} 704 void UnixSocket::EventListener::OnDisconnect(UnixSocket*) {} 705 void UnixSocket::EventListener::OnDataAvailable(UnixSocket*) {} 706 707 } // namespace base 708 } // namespace perfetto 709