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