1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/ipc_helper.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <alloca.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <log/log.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <poll.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/inotify.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/param.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/socket.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <algorithm>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/utility.h>
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
21d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenkonamespace {
22d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
23d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// Default implementations of Send/Receive interfaces to use standard socket
24d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// send/sendmsg/recv/recvmsg functions.
25d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenkoclass SocketSender : public SendInterface {
26d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko public:
27d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t Send(int socket_fd, const void* data, size_t size,
28d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko               int flags) override {
29d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return send(socket_fd, data, size, flags);
30d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
31d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) override {
32d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return sendmsg(socket_fd, msg, flags);
33d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
34d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko} g_socket_sender;
35d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
36d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenkoclass SocketReceiver : public RecvInterface {
37d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko public:
38d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t Receive(int socket_fd, void* data, size_t size, int flags) override {
39d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return recv(socket_fd, data, size, flags);
40d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
41d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) override {
42d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return recvmsg(socket_fd, msg, flags);
43d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
44d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko} g_socket_receiver;
45d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
46d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko}  // anonymous namespace
47d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
48d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// Helper wrappers around send()/sendmsg() which repeat send() calls on data
49d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// that was not sent with the initial call to send/sendmsg. This is important to
50d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// handle transmissions interrupted by signals.
51d618b567630d347be0929ea25ce6c68921005ed6Alex VakulenkoStatus<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd,
52d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko                     const void* data, size_t size) {
53d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  Status<void> ret;
54d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  const uint8_t* ptr = static_cast<const uint8_t*>(data);
55d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  while (size > 0) {
56d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ssize_t size_written =
57d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko        RETRY_EINTR(sender->Send(socket_fd.Get(), ptr, size, MSG_NOSIGNAL));
58d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    if (size_written < 0) {
59d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ret.SetError(errno);
60d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ALOGE("SendAll: Failed to send data over socket: %s",
61d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko            ret.GetErrorMessage().c_str());
62d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      break;
63d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    }
64d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    size -= size_written;
65d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ptr += size_written;
66d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
67d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return ret;
68d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko}
69d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
70d618b567630d347be0929ea25ce6c68921005ed6Alex VakulenkoStatus<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd,
71d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko                        const msghdr* msg) {
72d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  Status<void> ret;
73d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t sent_size =
74d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      RETRY_EINTR(sender->SendMessage(socket_fd.Get(), msg, MSG_NOSIGNAL));
75d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  if (sent_size < 0) {
76d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ret.SetError(errno);
77d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ALOGE("SendMsgAll: Failed to send data over socket: %s",
78d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko          ret.GetErrorMessage().c_str());
79d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
80d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
81d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
82d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t chunk_start_offset = 0;
83d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  for (size_t i = 0; i < msg->msg_iovlen; i++) {
84d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ssize_t chunk_end_offset = chunk_start_offset + msg->msg_iov[i].iov_len;
85d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    if (sent_size < chunk_end_offset) {
86d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      size_t offset_within_chunk = sent_size - chunk_start_offset;
87d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      size_t data_size = msg->msg_iov[i].iov_len - offset_within_chunk;
88d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      const uint8_t* chunk_base =
89d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko          static_cast<const uint8_t*>(msg->msg_iov[i].iov_base);
90d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ret = SendAll(sender, socket_fd, chunk_base + offset_within_chunk,
91d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko                    data_size);
92d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      if (!ret)
93d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko        break;
94d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      sent_size += data_size;
95d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    }
96d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    chunk_start_offset = chunk_end_offset;
97d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
98d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return ret;
99d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko}
100d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
101d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// Helper wrappers around recv()/recvmsg() which repeat recv() calls on data
102d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// that was not received with the initial call to recvmsg(). This is important
103d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// to handle transmissions interrupted by signals as well as the case when
104d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// initial data did not arrive in a single chunk over the socket (e.g. socket
105d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// buffer was full at the time of transmission, and only portion of initial
106d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// message was sent and the rest was blocked until the buffer was cleared by the
107d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko// receiving side).
108d618b567630d347be0929ea25ce6c68921005ed6Alex VakulenkoStatus<void> RecvMsgAll(RecvInterface* receiver,
109d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko                        const BorrowedHandle& socket_fd, msghdr* msg) {
110d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  Status<void> ret;
111d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t size_read = RETRY_EINTR(receiver->ReceiveMessage(
112d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      socket_fd.Get(), msg, MSG_WAITALL | MSG_CMSG_CLOEXEC));
113d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  if (size_read < 0) {
114d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ret.SetError(errno);
115d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ALOGE("RecvMsgAll: Failed to receive data from socket: %s",
116d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko          ret.GetErrorMessage().c_str());
117d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
118d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  } else if (size_read == 0) {
119d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ret.SetError(ESHUTDOWN);
120d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ALOGW("RecvMsgAll: Socket has been shut down");
121d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
122d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
123d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
124d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ssize_t chunk_start_offset = 0;
125d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  for (size_t i = 0; i < msg->msg_iovlen; i++) {
126d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ssize_t chunk_end_offset = chunk_start_offset + msg->msg_iov[i].iov_len;
127d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    if (size_read < chunk_end_offset) {
128d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      size_t offset_within_chunk = size_read - chunk_start_offset;
129d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      size_t data_size = msg->msg_iov[i].iov_len - offset_within_chunk;
130d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      uint8_t* chunk_base = static_cast<uint8_t*>(msg->msg_iov[i].iov_base);
131d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ret = RecvAll(receiver, socket_fd, chunk_base + offset_within_chunk,
132d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko                    data_size);
133d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      if (!ret)
134d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko        break;
135d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      size_read += data_size;
136d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    }
137d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    chunk_start_offset = chunk_end_offset;
138d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
139d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return ret;
140d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko}
141d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
142d618b567630d347be0929ea25ce6c68921005ed6Alex VakulenkoStatus<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd,
143d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko                     void* data, size_t size) {
144d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  Status<void> ret;
145d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  uint8_t* ptr = static_cast<uint8_t*>(data);
146d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  while (size > 0) {
147d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ssize_t size_read = RETRY_EINTR(receiver->Receive(
148d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko        socket_fd.Get(), ptr, size, MSG_WAITALL | MSG_CMSG_CLOEXEC));
149d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    if (size_read < 0) {
150d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ret.SetError(errno);
151d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ALOGE("RecvAll: Failed to receive data from socket: %s",
152d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko            ret.GetErrorMessage().c_str());
153d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      break;
154d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    } else if (size_read == 0) {
155d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ret.SetError(ESHUTDOWN);
156d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      ALOGW("RecvAll: Socket has been shut down");
157d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko      break;
158d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    }
159d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    size -= size_read;
160d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ptr += size_read;
161d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
162d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return ret;
163d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko}
164d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkouint32_t kMagicPreamble = 0x7564736d;  // 'udsm'.
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct MessagePreamble {
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t magic{0};
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t data_size{0};
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t fd_count{0};
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17309aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendPayload::Send(const BorrowedHandle& socket_fd) {
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return Send(socket_fd, nullptr);
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17709aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendPayload::Send(const BorrowedHandle& socket_fd,
17809aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                               const ucred* cred) {
179d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  SendInterface* sender = sender_ ? sender_ : &g_socket_sender;
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  MessagePreamble preamble;
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  preamble.magic = kMagicPreamble;
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  preamble.data_size = buffer_.size();
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  preamble.fd_count = file_handles_.size();
184d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  Status<void> ret = SendAll(sender, socket_fd, &preamble, sizeof(preamble));
185d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  if (!ret)
186d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iovec recv_vect = {buffer_.data(), buffer_.size()};
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = &recv_vect;
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = 1;
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (cred || !file_handles_.empty()) {
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const size_t fd_bytes = file_handles_.size() * sizeof(int);
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_controllen = (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                         (fd_bytes == 0 ? 0 : CMSG_SPACE(fd_bytes));
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_control = alloca(msg.msg_controllen);
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    cmsghdr* control = CMSG_FIRSTHDR(&msg);
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (cred) {
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_level = SOL_SOCKET;
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_type = SCM_CREDENTIALS;
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_len = CMSG_LEN(sizeof(ucred));
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(CMSG_DATA(control), cred, sizeof(ucred));
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control = CMSG_NXTHDR(&msg, control);
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (fd_bytes) {
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_level = SOL_SOCKET;
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_type = SCM_RIGHTS;
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_len = CMSG_LEN(fd_bytes);
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(CMSG_DATA(control), file_handles_.data(), fd_bytes);
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
216d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return SendMsgAll(sender, socket_fd, &msg);
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// MessageWriter
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* SendPayload::GetNextWriteBufferSection(size_t size) {
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return buffer_.grow_by(size);
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoOutputResourceMapper* SendPayload::GetOutputResourceMapper() { return this; }
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// OutputResourceMapper
227f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> SendPayload::PushFileHandle(const LocalHandle& handle) {
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (handle) {
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int ref = file_handles_.size();
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    file_handles_.push_back(handle.Get());
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ref;
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
237f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> SendPayload::PushFileHandle(
238f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const BorrowedHandle& handle) {
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (handle) {
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int ref = file_handles_.size();
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    file_handles_.push_back(handle.Get());
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ref;
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
248f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> SendPayload::PushFileHandle(const RemoteHandle& handle) {
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle.Get();
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
252f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> SendPayload::PushChannelHandle(
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const LocalChannelHandle& /*handle*/) {
254f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EOPNOTSUPP};
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
256f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> SendPayload::PushChannelHandle(
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const BorrowedChannelHandle& /*handle*/) {
258f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EOPNOTSUPP};
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
260f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> SendPayload::PushChannelHandle(
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const RemoteChannelHandle& /*handle*/) {
262f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EOPNOTSUPP};
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
26509aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd) {
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return Receive(socket_fd, nullptr);
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
26909aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd,
27009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                                     ucred* cred) {
271d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  RecvInterface* receiver = receiver_ ? receiver_ : &g_socket_receiver;
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  MessagePreamble preamble;
273d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  Status<void> ret = RecvAll(receiver, socket_fd, &preamble, sizeof(preamble));
274d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  if (!ret)
275d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
276d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko
277d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  if (preamble.magic != kMagicPreamble) {
2786eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko    ALOGE("ReceivePayload::Receive: Message header is invalid");
279d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ret.SetError(EIO);
280d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
281d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  }
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  buffer_.resize(preamble.data_size);
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  file_handles_.clear();
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  read_pos_ = 0;
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iovec recv_vect = {buffer_.data(), buffer_.size()};
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = &recv_vect;
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = 1;
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (cred || preamble.fd_count) {
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const size_t receive_fd_bytes = preamble.fd_count * sizeof(int);
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_controllen =
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        (receive_fd_bytes == 0 ? 0 : CMSG_SPACE(receive_fd_bytes));
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_control = alloca(msg.msg_controllen);
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
300d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  ret = RecvMsgAll(receiver, socket_fd, &msg);
301d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  if (!ret)
302d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    return ret;
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool cred_available = false;
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  file_handles_.reserve(preamble.fd_count);
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (cmsg) {
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS &&
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        cred && cmsg->cmsg_len == CMSG_LEN(sizeof(ucred))) {
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      cred_available = true;
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(cred, CMSG_DATA(cmsg), sizeof(ucred));
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (cmsg->cmsg_level == SOL_SOCKET &&
313e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               cmsg->cmsg_type == SCM_RIGHTS) {
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      socklen_t payload_len = cmsg->cmsg_len - CMSG_LEN(0);
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int* fds = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_t fd_count = payload_len / sizeof(int);
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      std::transform(fds, fds + fd_count, std::back_inserter(file_handles_),
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     [](int fd) { return LocalHandle{fd}; });
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    cmsg = CMSG_NXTHDR(&msg, cmsg);
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3236eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko  if (cred && !cred_available) {
3246eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko    ALOGE("ReceivePayload::Receive: Failed to obtain message credentials");
325d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko    ret.SetError(EIO);
3266eefa42d33bdddc3603211634f98937b00abc532Alex Vakulenko  }
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
328d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return ret;
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// MessageReader
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessageReader::BufferSection ReceivePayload::GetNextReadBufferSection() {
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {buffer_.data() + read_pos_, &*buffer_.end()};
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ReceivePayload::ConsumeReadBufferSectionData(const void* new_start) {
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  read_pos_ = PointerDistance(new_start, buffer_.data());
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoInputResourceMapper* ReceivePayload::GetInputResourceMapper() { return this; }
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// InputResourceMapper
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ReceivePayload::GetFileHandle(FileReference ref, LocalHandle* handle) {
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ref < 0) {
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = LocalHandle{ref};
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (static_cast<size_t>(ref) > file_handles_.size())
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return false;
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  *handle = std::move(file_handles_[ref]);
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return true;
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
354e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ReceivePayload::GetChannelHandle(ChannelReference /*ref*/,
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                      LocalChannelHandle* /*handle*/) {
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return false;
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
35909aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendData(const BorrowedHandle& socket_fd, const void* data,
36009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                      size_t size) {
361d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return SendAll(&g_socket_sender, socket_fd, data, size);
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
363e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
36409aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
36509aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                            size_t count) {
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = const_cast<iovec*>(data);
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = count;
369d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return SendMsgAll(&g_socket_sender, socket_fd, &msg);
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
37209aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
37309aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         size_t size) {
374d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return RecvAll(&g_socket_receiver, socket_fd, data, size);
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
37709aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
37809aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                               const iovec* data, size_t count) {
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = const_cast<iovec*>(data);
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = count;
382d618b567630d347be0929ea25ce6c68921005ed6Alex Vakulenko  return RecvMsgAll(&g_socket_receiver, socket_fd, &msg);
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
384e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
385e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkosize_t CountVectorSize(const iovec* vector, size_t count) {
386e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::accumulate(
387e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      vector, vector + count, size_t{0},
388e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      [](size_t size, const iovec& vec) { return size + vec.iov_len; });
389e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
391e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 int opcode, uint32_t send_len, uint32_t max_recv_len,
393e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 bool is_impulse) {
394e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->op = opcode;
395e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->cred.pid = getpid();
396e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->cred.uid = geteuid();
397e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->cred.gid = getegid();
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->send_len = send_len;
399e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->max_recv_len = max_recv_len;
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->is_impulse = is_impulse;
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> WaitForEndpoint(const std::string& endpoint_path,
404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             int64_t timeout_ms) {
405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Endpoint path must be absolute.
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (endpoint_path.empty() || endpoint_path.front() != '/')
407e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EINVAL);
408e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create inotify fd.
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle fd{inotify_init()};
411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!fd)
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set the inotify fd to non-blocking.
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int ret = fcntl(fd.Get(), F_GETFL);
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  fcntl(fd.Get(), F_SETFL, ret | O_NONBLOCK);
417e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
418e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Setup the pollfd.
419e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pollfd pfd = {fd.Get(), POLLIN, 0};
420e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
421e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Find locations of each path separator.
422e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<size_t> separators{0};  // The path is absolute, so '/' is at #0.
423e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t pos = endpoint_path.find('/', 1);
424e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (pos != std::string::npos) {
425e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    separators.push_back(pos);
426e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    pos = endpoint_path.find('/', pos + 1);
427e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
428e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  separators.push_back(endpoint_path.size());
429e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
430e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Walk down the path, checking for existence and waiting if needed.
431e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pos = 1;
432e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t links = 0;
433e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string current;
434e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (pos < separators.size() && links <= MAXSYMLINKS) {
435e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::string previous = current;
436e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    current = endpoint_path.substr(0, separators[pos]);
437e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
438e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Check for existence; proceed to setup a watch if not.
439e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (access(current.c_str(), F_OK) < 0) {
440e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (errno != ENOENT)
441e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return ErrorStatus(errno);
442e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
443e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Extract the name of the path component to wait for.
444e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      std::string next = current.substr(
445e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          separators[pos - 1] + 1, separators[pos] - separators[pos - 1] - 1);
446e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
447e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Add a watch on the last existing directory we reach.
448e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      int wd = inotify_add_watch(
449e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          fd.Get(), previous.c_str(),
450e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF | IN_MOVED_TO);
451e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (wd < 0) {
452e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (errno != ENOENT)
453e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          return ErrorStatus(errno);
454e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        // Restart at the beginning if previous was deleted.
455e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        links = 0;
456e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        current.clear();
457e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        pos = 1;
458e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        continue;
459e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
460e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
461e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Make sure current didn't get created before the watch was added.
462e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = access(current.c_str(), F_OK);
463e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0) {
464e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (errno != ENOENT)
465e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          return ErrorStatus(errno);
466e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
467e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        bool exit_poll = false;
468e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        while (!exit_poll) {
469e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          // Wait for an event or timeout.
470e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          ret = poll(&pfd, 1, timeout_ms);
471e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          if (ret <= 0)
472e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            return ErrorStatus(ret == 0 ? ETIMEDOUT : errno);
473e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
474e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          // Read events.
475e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          char buffer[sizeof(inotify_event) + NAME_MAX + 1];
476e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
477e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          ret = read(fd.Get(), buffer, sizeof(buffer));
478e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          if (ret < 0) {
479e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            if (errno == EAGAIN || errno == EWOULDBLOCK)
480e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              continue;
481e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            else
482e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              return ErrorStatus(errno);
483e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          } else if (static_cast<size_t>(ret) < sizeof(struct inotify_event)) {
484e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            return ErrorStatus(EIO);
485e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          }
486e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
487e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          auto* event = reinterpret_cast<const inotify_event*>(buffer);
488e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          auto* end = reinterpret_cast<const inotify_event*>(buffer + ret);
489e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          while (event < end) {
490e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            std::string event_for;
491e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            if (event->len > 0)
492e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              event_for = event->name;
493e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
494e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
495e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              // See if this is the droid we're looking for.
496e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              if (next == event_for) {
497e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                exit_poll = true;
498e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                break;
499e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              }
500e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            } else if (event->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) {
501e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              // Restart at the beginning if our watch dir is deleted.
502e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              links = 0;
503e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              current.clear();
504e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              pos = 0;
505e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              exit_poll = true;
506e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              break;
507e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            }
508e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
509e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            event = reinterpret_cast<const inotify_event*>(AdvancePointer(
510e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                event, sizeof(struct inotify_event) + event->len));
511e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          }  // while (event < end)
512e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        }    // while (!exit_poll)
513e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }      // Current dir doesn't exist.
514e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = inotify_rm_watch(fd.Get(), wd);
515e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0 && errno != EINVAL)
516e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return ErrorStatus(errno);
517e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }  // if (access(current.c_str(), F_OK) < 0)
518e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
519e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Check for symbolic link and update link count.
520e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    struct stat stat_buf;
521e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ret = lstat(current.c_str(), &stat_buf);
522e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (ret < 0 && errno != ENOENT)
523e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ErrorStatus(errno);
524e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else if (ret == 0 && S_ISLNK(stat_buf.st_mode))
525e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      links++;
526e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    pos++;
527e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }  // while (pos < separators.size() && links <= MAXSYMLINKS)
528e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
529e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
530e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
531e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
532e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
533e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
534e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
535