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