service_endpoint.cpp revision 409c6eecdca80e95a110d63bc70b1c2dfcf49100
1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/service_endpoint.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <poll.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/epoll.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/eventfd.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/socket.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/un.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <algorithm>  // std::min
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
10409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko#include <android-base/logging.h>
11409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko#include <android-base/strings.h>
12409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko#include <cutils/sockets.h>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/channel_manager.h>
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/client_channel_factory.h>
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/ipc_helper.h>
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr int kMaxBackLogForSocketListen = 1;
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::BorrowedChannelHandle;
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::BorrowedHandle;
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::ChannelReference;
25f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenkousing android::pdx::ErrorStatus;
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::FileReference;
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalChannelHandle;
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalHandle;
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Status;
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::uds::ChannelInfo;
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::uds::ChannelManager;
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct MessageState {
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalFileHandle(int index, LocalHandle* handle) {
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      handle->Reset(index);
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < request.file_descriptors.size()) {
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = std::move(request.file_descriptors[index]);
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = LocalChannelHandle{nullptr, index};
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < request.channels.size()) {
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      auto& channel_info = request.channels[index];
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = ChannelManager::Get().CreateHandle(
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          std::move(channel_info.data_fd), std::move(channel_info.event_fd));
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
58f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<FileReference> PushFileHandle(BorrowedHandle handle) {
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    response.file_descriptors.push_back(std::move(handle));
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return response.file_descriptors.size() - 1;
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
65f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(BorrowedChannelHandle handle) {
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
686890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
696890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (auto* channel_data =
706890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka            ChannelManager::Get().GetChannelData(handle.value())) {
716890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      ChannelInfo<BorrowedHandle> channel_info;
726890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_info.data_fd.Reset(handle.value());
736890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_info.event_fd = channel_data->event_receiver.event_fd();
746890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      response.channels.push_back(std::move(channel_info));
756890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return response.channels.size() - 1;
766890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
77f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return ErrorStatus{EINVAL};
786890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
81f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> PushChannelHandle(BorrowedHandle data_fd,
82f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                             BorrowedHandle event_fd) {
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!data_fd || !event_fd)
84f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return ErrorStatus{EINVAL};
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ChannelInfo<BorrowedHandle> channel_info;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    channel_info.data_fd = std::move(data_fd);
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    channel_info.event_fd = std::move(event_fd);
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    response.channels.push_back(std::move(channel_info));
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return response.channels.size() - 1;
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
92f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<size_t> WriteData(const iovec* vector, size_t vector_length) {
93f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    size_t size = 0;
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < vector_length; i++) {
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const auto* data = reinterpret_cast<const uint8_t*>(vector[i].iov_base);
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      response_data.insert(response_data.end(), data, data + vector[i].iov_len);
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size += vector[i].iov_len;
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return size;
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
102f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<size_t> ReadData(const iovec* vector, size_t vector_length) {
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_remaining = request_data.size() - request_data_read_pos;
104f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    size_t size = 0;
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < vector_length && size_remaining > 0; i++) {
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_t size_to_copy = std::min(size_remaining, vector[i].iov_len);
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(vector[i].iov_base, request_data.data() + request_data_read_pos,
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             size_to_copy);
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size += size_to_copy;
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      request_data_read_pos += size_to_copy;
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_remaining -= size_to_copy;
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return size;
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::RequestHeader<LocalHandle> request;
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::ResponseHeader<BorrowedHandle> response;
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<LocalHandle> sockets_to_close;
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<uint8_t> request_data;
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t request_data_read_pos{0};
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<uint8_t> response_data;
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds {
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
130409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex VakulenkoEndpoint::Endpoint(const std::string& endpoint_path, bool blocking,
131409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko                   bool use_init_socket_fd)
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : endpoint_path_{ClientChannelFactory::GetEndpointPath(endpoint_path)},
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      is_blocking_{blocking} {
134409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  LocalHandle fd;
135409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  if (use_init_socket_fd) {
136409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    // Cut off the /dev/socket/ prefix from the full socket path and use the
137409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    // resulting "name" to retrieve the file descriptor for the socket created
138409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    // by the init process.
139409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    constexpr char prefix[] = "/dev/socket/";
140409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    CHECK(android::base::StartsWith(endpoint_path_, prefix))
141409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko        << "Endpoint::Endpoint: Socket name '" << endpoint_path_
142409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko        << "' must begin with '" << prefix << "'";
143409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    std::string socket_name = endpoint_path_.substr(sizeof(prefix) - 1);
144409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    fd.Reset(android_get_control_socket(socket_name.c_str()));
145409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    CHECK(fd.IsValid())
146409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko        << "Endpoint::Endpoint: Unable to obtain the control socket fd for '"
147409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko        << socket_name << "'";
148409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    fcntl(fd.Get(), F_SETFD, FD_CLOEXEC);
149409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  } else {
150409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    fd.Reset(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
151409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    CHECK(fd.IsValid()) << "Endpoint::Endpoint: Failed to create socket: "
152409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko                        << strerror(errno);
153409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko
154409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    sockaddr_un local;
155409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    local.sun_family = AF_UNIX;
156409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path));
157409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    local.sun_path[sizeof(local.sun_path) - 1] = '\0';
158409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko
159409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    unlink(local.sun_path);
160409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    int ret =
161409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko        bind(fd.Get(), reinterpret_cast<sockaddr*>(&local), sizeof(local));
162409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko    CHECK_EQ(ret, 0) << "Endpoint::Endpoint: bind error: " << strerror(errno);
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
164409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  CHECK_EQ(listen(fd.Get(), kMaxBackLogForSocketListen), 0)
165409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << "Endpoint::Endpoint: listen error: " << strerror(errno);
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cancel_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
168409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  CHECK(cancel_event_fd_.IsValid())
169409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << "Endpoint::Endpoint: Failed to create event fd: " << strerror(errno);
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
171409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
172409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  CHECK(epoll_fd_.IsValid())
173409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << "Endpoint::Endpoint: Failed to create epoll fd: " << strerror(errno);
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event socket_event;
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  socket_event.data.fd = fd.Get();
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event cancel_event;
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cancel_event.events = EPOLLIN;
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cancel_event.data.fd = cancel_event_fd_.Get();
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
183409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  int ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd.Get(), &socket_event);
184409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  CHECK_EQ(ret, 0)
185409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << "Endpoint::Endpoint: Failed to add socket fd to epoll fd: "
186409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << strerror(errno);
187409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  ret = epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
188409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko                  &cancel_event);
189409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  CHECK_EQ(ret, 0)
190409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << "Endpoint::Endpoint: Failed to add cancel event fd to epoll fd: "
191409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      << strerror(errno);
192409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  socket_fd_ = std::move(fd);
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* Endpoint::AllocateMessageState() { return new MessageState; }
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid Endpoint::FreeMessageState(void* state) {
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  delete static_cast<MessageState*>(state);
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::AcceptConnection(Message* message) {
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  sockaddr_un remote;
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  socklen_t addrlen = sizeof(remote);
204409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  LocalHandle channel_fd{accept4(socket_fd_.Get(),
205409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko                                 reinterpret_cast<sockaddr*>(&remote), &addrlen,
206409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko                                 SOCK_CLOEXEC)};
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!channel_fd) {
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::AcceptConnection: failed to accept connection: %s",
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int optval = 1;
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (setsockopt(channel_fd.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 sizeof(optval)) == -1) {
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::AcceptConnection: Failed to enable the receiving of the "
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "credentials for channel %d: %s",
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        channel_fd.Get(), strerror(errno));
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveMessageForChannel(channel_fd.Get(), message);
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status)
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = OnNewChannel(std::move(channel_fd));
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
229f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::SetService(Service* service) {
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  service_ = service;
231f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return {};
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
234f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::SetChannel(int channel_id, Channel* channel) {
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_data == channels_.end())
238f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_data->second.channel_state = channel;
240f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return {};
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::OnNewChannel(LocalHandle channel_fd) {
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<void> status;
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  status.PropagateError(OnNewChannelLocked(std::move(channel_fd), nullptr));
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<Endpoint::ChannelData*> Endpoint::OnNewChannelLocked(
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    LocalHandle channel_fd, Channel* channel_state) {
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event event;
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.data.fd = channel_fd.Get();
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, channel_fd.Get(), &event) < 0) {
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::OnNewChannelLocked: Failed to add channel to endpoint: %s\n",
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        strerror(errno));
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelData channel_data;
2626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  const int channel_id = channel_fd.Get();
2636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  channel_data.event_set.AddDataFd(channel_fd);
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_data.data_fd = std::move(channel_fd);
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_data.channel_state = channel_state;
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto pair = channels_.emplace(channel_id, std::move(channel_data));
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return &pair.first->second;
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::ReenableEpollEvent(int fd) {
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event event;
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.data.fd = fd;
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd, &event) < 0) {
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::ReenableEpollEvent: Failed to re-enable channel to "
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "endpoint: %s\n",
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        strerror(errno));
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
284f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::CloseChannel(int channel_id) {
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return CloseChannelLocked(channel_id);
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
289f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::CloseChannelLocked(int channel_id) {
2906890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id);
2916890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_data == channels_.end())
294f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
296f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<void> status;
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_id, &dummy) < 0) {
299f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    status.SetError(errno);
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
302e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "%s\n",
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        strerror(errno));
304f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  } else {
305f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    status.SetValue();
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channels_.erase(channel_data);
309f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return status;
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
312f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::ModifyChannelEvents(int channel_id, int clear_mask,
313f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                           int set_mask) {
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3166890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  auto search = channels_.find(channel_id);
3176890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  if (search != channels_.end()) {
3186890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    auto& channel_data = search->second;
3196890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    channel_data.event_set.ModifyEvents(clear_mask, set_mask);
320f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return {};
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
323f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EINVAL};
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<RemoteChannelHandle> Endpoint::PushChannel(Message* message,
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                  int /*flags*/,
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                  Channel* channel,
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                  int* channel_id) {
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_pair[2] = {};
331409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, channel_pair) == -1) {
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::PushChannel: Failed to create a socket pair: %s",
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle local_socket{channel_pair[0]};
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle remote_socket{channel_pair[1]};
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int optval = 1;
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (setsockopt(local_socket.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 sizeof(optval)) == -1) {
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::PushChannel: Failed to enable the receiving of the "
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "credentials for channel %d: %s",
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        local_socket.Get(), strerror(errno));
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  *channel_id = local_socket.Get();
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!channel_data)
354f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return channel_data.error_status();
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Flags are ignored for now.
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // TODO(xiaohuit): Implement those.
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
360f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<ChannelReference> ref = state->PushChannelHandle(
3616890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      remote_socket.Borrow(),
3626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_data.get()->event_set.event_fd().Borrow());
363f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (!ref)
364f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ref.error_status();
365e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->sockets_to_close.push_back(std::move(remote_socket));
366f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return RemoteChannelHandle{ref.get()};
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> Endpoint::CheckChannel(const Message* /*message*/,
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                   ChannelReference /*ref*/,
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                   Channel** /*channel*/) {
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // TODO(xiaohuit): Implement this.
373e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ErrorStatus(EFAULT);
374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannel* Endpoint::GetChannelState(int channel_id) {
377e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return (channel_data != channels_.end()) ? channel_data->second.channel_state
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           : nullptr;
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
382e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::GetChannelSocketFd(int channel_id) {
384e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
385e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
386e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return (channel_data != channels_.end()) ? channel_data->second.data_fd.Get()
387e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           : -1;
388e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
389e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::GetChannelEventFd(int channel_id) {
391e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
3936890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  return (channel_data != channels_.end())
3946890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka             ? channel_data->second.event_set.event_fd().Get()
3956890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka             : -1;
396e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
397e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::ReceiveMessageForChannel(int channel_id,
399e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                Message* message) {
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  RequestHeader<LocalHandle> request;
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveData(channel_id, &request);
402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status) {
4036890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (status.error() == ESHUTDOWN) {
4046890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      BuildCloseMessage(channel_id, message);
4056890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return {};
4066890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
4076890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      CloseChannel(channel_id);
4086890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return status;
4096890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
4116890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  MessageInfo info;
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.pid = request.cred.pid;
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.tid = -1;
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.cid = channel_id;
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.mid = request.is_impulse ? Message::IMPULSE_MESSAGE_ID
417e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                : GetNextAvailableMessageId();
418e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.euid = request.cred.uid;
419e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.egid = request.cred.gid;
420e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.op = request.op;
421e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.flags = 0;
422e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.service = service_;
423e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.channel = GetChannelState(channel_id);
424e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.send_len = request.send_len;
425e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.recv_len = request.max_recv_len;
426e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.fd_count = request.file_descriptors.size();
427e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static_assert(sizeof(info.impulse) == request.impulse_payload.size(),
428e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                "Impulse payload sizes must be the same in RequestHeader and "
429e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                "MessageInfo");
430e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  memcpy(info.impulse, request.impulse_payload.data(),
431e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko         request.impulse_payload.size());
432e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  *message = Message{info};
433e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
434e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->request = std::move(request);
435e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (request.send_len > 0 && !request.is_impulse) {
436e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    state->request_data.resize(request.send_len);
437e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReceiveData(channel_id, state->request_data.data(),
438e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                         state->request_data.size());
439e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
440e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
441e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status && request.is_impulse)
442e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReenableEpollEvent(channel_id);
443e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4446890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  if (!status) {
4456890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (status.error() == ESHUTDOWN) {
4466890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      BuildCloseMessage(channel_id, message);
4476890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return {};
4486890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
4496890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      CloseChannel(channel_id);
4506890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return status;
4516890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
4526890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  }
453e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
454e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
455e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
456e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4576890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabakavoid Endpoint::BuildCloseMessage(int channel_id, Message* message) {
4586890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  ALOGD_IF(TRACE, "Endpoint::BuildCloseMessage: channel_id=%d", channel_id);
4596890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  MessageInfo info;
4606890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.pid = -1;
4616890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.tid = -1;
4626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.cid = channel_id;
4636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.mid = GetNextAvailableMessageId();
4646890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.euid = -1;
4656890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.egid = -1;
4666890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.op = opcodes::CHANNEL_CLOSE;
4676890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.flags = 0;
4686890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.service = service_;
4696890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.channel = GetChannelState(channel_id);
4706890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.send_len = 0;
4716890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.recv_len = 0;
4726890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.fd_count = 0;
4736890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  *message = Message{info};
4746890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka}
475e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
476f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::MessageReceive(Message* message) {
4776890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  // Receive at most one event from the epoll set. This should prevent multiple
4786890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  // dispatch threads from attempting to handle messages on the same socket at
4796890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  // the same time.
480e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event event;
481e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int count = RETRY_EINTR(
482e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      epoll_wait(epoll_fd_.Get(), &event, 1, is_blocking_ ? -1 : 0));
483e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (count < 0) {
484e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::MessageReceive: Failed to wait for epoll events: %s\n",
485e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
486f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{errno};
487e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else if (count == 0) {
488f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ETIMEDOUT};
489e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
490e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
491e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (event.data.fd == cancel_event_fd_.Get()) {
492f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
493e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
494e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
495e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (event.data.fd == socket_fd_.Get()) {
496e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = AcceptConnection(message);
497e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status)
498f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return status;
499f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ReenableEpollEvent(socket_fd_.Get());
500e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
501e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
502e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id = event.data.fd;
5036890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
5046890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    BuildCloseMessage(channel_id, message);
505f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return {};
506e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
507e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
508f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ReceiveMessageForChannel(channel_id, message);
509e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
510e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
511f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::MessageReply(Message* message, int return_code) {
5126890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  const int channel_id = message->GetChannelId();
5136890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  const int channel_socket = GetChannelSocketFd(channel_id);
514e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_socket < 0)
515f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EBADF};
516e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
517e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
518e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  switch (message->GetOp()) {
519e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_CLOSE:
5206890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return CloseChannel(channel_id);
521e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
522e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_OPEN:
523f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      if (return_code < 0) {
5246890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka        return CloseChannel(channel_id);
525f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      } else {
526f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        // Reply with the event fd.
527f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        auto push_status = state->PushFileHandle(
528f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko            BorrowedHandle{GetChannelEventFd(channel_socket)});
529f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        state->response_data.clear();  // Just in case...
530f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        if (!push_status)
531f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          return push_status.error_status();
532f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        return_code = push_status.get();
533f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      }
534e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      break;
535e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
536e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
537e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->response.ret_code = return_code;
538e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->response.recv_len = state->response_data.size();
539e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = SendData(channel_socket, state->response);
540e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status && !state->response_data.empty()) {
541e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = SendData(channel_socket, state->response_data.data(),
542e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      state->response_data.size());
543e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
544e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
545e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status)
546e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReenableEpollEvent(channel_socket);
547e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
548f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return status;
549e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
550e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
551f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::MessageReplyFd(Message* message, unsigned int push_fd) {
552e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
553e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto ref = state->PushFileHandle(BorrowedHandle{static_cast<int>(push_fd)});
554f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (!ref)
555f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ref.error_status();
556f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return MessageReply(message, ref.get());
557e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
558e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
559f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::MessageReplyChannelHandle(
560f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Message* message, const LocalChannelHandle& handle) {
561e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
562e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto ref = state->PushChannelHandle(handle.Borrow());
563f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (!ref)
564f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ref.error_status();
565f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return MessageReply(message, ref.get());
566e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
567e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
568f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::MessageReplyChannelHandle(
569f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Message* message, const BorrowedChannelHandle& handle) {
570e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
571e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto ref = state->PushChannelHandle(handle.Duplicate());
572f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (!ref)
573f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ref.error_status();
574f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return MessageReply(message, ref.get());
575e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
576e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
577f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::MessageReplyChannelHandle(
578f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Message* message, const RemoteChannelHandle& handle) {
579e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return MessageReply(message, handle.value());
580e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
581e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
582f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<size_t> Endpoint::ReadMessageData(Message* message, const iovec* vector,
583f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                         size_t vector_length) {
584e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
585e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->ReadData(vector, vector_length);
586e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
587e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
588f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<size_t> Endpoint::WriteMessageData(Message* message, const iovec* vector,
589f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                          size_t vector_length) {
590e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
591e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->WriteData(vector, vector_length);
592e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
593e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
594f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> Endpoint::PushFileHandle(Message* message,
595f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                               const LocalHandle& handle) {
596e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
597e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Borrow());
598e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
599e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
600f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> Endpoint::PushFileHandle(Message* message,
601f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                               const BorrowedHandle& handle) {
602e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
603e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Duplicate());
604e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
605e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
606f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> Endpoint::PushFileHandle(Message* /*message*/,
607f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                               const RemoteHandle& handle) {
608e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle.Get();
609e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
610e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
611f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> Endpoint::PushChannelHandle(
612f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Message* message, const LocalChannelHandle& handle) {
613e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
614e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Borrow());
615e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
616e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
617f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> Endpoint::PushChannelHandle(
618e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Message* message, const BorrowedChannelHandle& handle) {
619e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
620e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Duplicate());
621e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
622e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
623f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> Endpoint::PushChannelHandle(
624e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Message* /*message*/, const RemoteChannelHandle& handle) {
625e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle.value();
626e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
627e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
628e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoLocalHandle Endpoint::GetFileHandle(Message* message, FileReference ref) const {
629e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle handle;
630e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
631e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->GetLocalFileHandle(ref, &handle);
632e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle;
633e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
634e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
635e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoLocalChannelHandle Endpoint::GetChannelHandle(Message* message,
636e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                              ChannelReference ref) const {
637e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalChannelHandle handle;
638e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
639e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->GetLocalChannelHandle(ref, &handle);
640e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle;
641e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
642e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
643f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Endpoint::Cancel() {
644f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (eventfd_write(cancel_event_fd_.Get(), 1) < 0)
645f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{errno};
646f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return {};
647e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
648e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
649e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<Endpoint> Endpoint::Create(const std::string& endpoint_path,
650e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           mode_t /*unused_mode*/,
651e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           bool blocking) {
652e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::unique_ptr<Endpoint>(new Endpoint(endpoint_path, blocking));
653e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
654e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
655f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenkostd::unique_ptr<Endpoint> Endpoint::CreateAndBindSocket(
656f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const std::string& endpoint_path, bool blocking) {
657409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko  return std::unique_ptr<Endpoint>(
658409c6eecdca80e95a110d63bc70b1c2dfcf49100Alex Vakulenko      new Endpoint(endpoint_path, blocking, false));
659f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko}
660f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko
661e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
662e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
663e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
664