Home | History | Annotate | Download | only in base
      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