service_endpoint.cpp revision 6890d95ec8b96970202518b439bfa8ab2d9dbf77
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
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/channel_manager.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/client_channel_factory.h>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/ipc_helper.h>
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr int kMaxBackLogForSocketListen = 1;
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::BorrowedChannelHandle;
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::BorrowedHandle;
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::ChannelReference;
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::FileReference;
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalChannelHandle;
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalHandle;
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Status;
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::uds::ChannelInfo;
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::uds::ChannelManager;
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct MessageState {
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalFileHandle(int index, LocalHandle* handle) {
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      handle->Reset(index);
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < request.file_descriptors.size()) {
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = std::move(request.file_descriptors[index]);
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = LocalChannelHandle{nullptr, index};
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < request.channels.size()) {
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      auto& channel_info = request.channels[index];
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = ChannelManager::Get().CreateHandle(
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          std::move(channel_info.data_fd), std::move(channel_info.event_fd));
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  FileReference PushFileHandle(BorrowedHandle handle) {
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    response.file_descriptors.push_back(std::move(handle));
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return response.file_descriptors.size() - 1;
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
646890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
656890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (auto* channel_data =
666890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka            ChannelManager::Get().GetChannelData(handle.value())) {
676890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      ChannelInfo<BorrowedHandle> channel_info;
686890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_info.data_fd.Reset(handle.value());
696890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_info.event_fd = channel_data->event_receiver.event_fd();
706890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      response.channels.push_back(std::move(channel_info));
716890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return response.channels.size() - 1;
726890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
736890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return -1;
746890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelReference PushChannelHandle(BorrowedHandle data_fd,
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     BorrowedHandle event_fd) {
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!data_fd || !event_fd)
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -1;
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ChannelInfo<BorrowedHandle> channel_info;
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    channel_info.data_fd = std::move(data_fd);
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    channel_info.event_fd = std::move(event_fd);
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    response.channels.push_back(std::move(channel_info));
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return response.channels.size() - 1;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t WriteData(const iovec* vector, size_t vector_length) {
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ssize_t size = 0;
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < vector_length; i++) {
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const auto* data = reinterpret_cast<const uint8_t*>(vector[i].iov_base);
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      response_data.insert(response_data.end(), data, data + vector[i].iov_len);
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size += vector[i].iov_len;
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return size;
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t ReadData(const iovec* vector, size_t vector_length) {
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_remaining = request_data.size() - request_data_read_pos;
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ssize_t size = 0;
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < vector_length && size_remaining > 0; i++) {
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_t size_to_copy = std::min(size_remaining, vector[i].iov_len);
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(vector[i].iov_base, request_data.data() + request_data_read_pos,
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko             size_to_copy);
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size += size_to_copy;
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      request_data_read_pos += size_to_copy;
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_remaining -= size_to_copy;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return size;
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::RequestHeader<LocalHandle> request;
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::ResponseHeader<BorrowedHandle> response;
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<LocalHandle> sockets_to_close;
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<uint8_t> request_data;
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t request_data_read_pos{0};
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<uint8_t> response_data;
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds {
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoEndpoint::Endpoint(const std::string& endpoint_path, bool blocking)
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : endpoint_path_{ClientChannelFactory::GetEndpointPath(endpoint_path)},
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      is_blocking_{blocking} {
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle fd{socket(AF_UNIX, SOCK_STREAM, 0)};
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!fd) {
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::Endpoint: Failed to create socket: %s", strerror(errno));
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  sockaddr_un local;
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  local.sun_family = AF_UNIX;
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  strncpy(local.sun_path, endpoint_path_.c_str(), sizeof(local.sun_path));
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  local.sun_path[sizeof(local.sun_path) - 1] = '\0';
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  unlink(local.sun_path);
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (bind(fd.Get(), (struct sockaddr*)&local, sizeof(local)) == -1) {
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::Endpoint: bind error: %s", strerror(errno));
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (listen(fd.Get(), kMaxBackLogForSocketListen) == -1) {
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::Endpoint: listen error: %s", strerror(errno));
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cancel_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!cancel_event_fd_) {
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::Endpoint: Failed to create event fd: %s\n",
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_fd_.Reset(epoll_create(1));  // Size arg is ignored, but must be > 0.
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!epoll_fd_) {
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::Endpoint: Failed to create epoll fd: %s\n",
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event socket_event;
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  socket_event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  socket_event.data.fd = fd.Get();
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event cancel_event;
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cancel_event.events = EPOLLIN;
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cancel_event.data.fd = cancel_event_fd_.Get();
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd.Get(), &socket_event) < 0 ||
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, cancel_event_fd_.Get(),
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                &cancel_event) < 0) {
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::Endpoint: Failed to add event fd to epoll fd: %s\n",
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    cancel_event_fd_.Close();
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    epoll_fd_.Close();
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    socket_fd_ = std::move(fd);
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* Endpoint::AllocateMessageState() { return new MessageState; }
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid Endpoint::FreeMessageState(void* state) {
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  delete static_cast<MessageState*>(state);
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::AcceptConnection(Message* message) {
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  sockaddr_un remote;
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  socklen_t addrlen = sizeof(remote);
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle channel_fd{
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      accept(socket_fd_.Get(), reinterpret_cast<sockaddr*>(&remote), &addrlen)};
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!channel_fd) {
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::AcceptConnection: failed to accept connection: %s",
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int optval = 1;
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (setsockopt(channel_fd.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 sizeof(optval)) == -1) {
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::AcceptConnection: Failed to enable the receiving of the "
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "credentials for channel %d: %s",
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        channel_fd.Get(), strerror(errno));
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveMessageForChannel(channel_fd.Get(), message);
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status)
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = OnNewChannel(std::move(channel_fd));
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::SetService(Service* service) {
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  service_ = service;
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return 0;
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::SetChannel(int channel_id, Channel* channel) {
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_data == channels_.end())
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -EINVAL;
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_data->second.channel_state = channel;
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return 0;
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::OnNewChannel(LocalHandle channel_fd) {
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<void> status;
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  status.PropagateError(OnNewChannelLocked(std::move(channel_fd), nullptr));
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<Endpoint::ChannelData*> Endpoint::OnNewChannelLocked(
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    LocalHandle channel_fd, Channel* channel_state) {
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event event;
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.data.fd = channel_fd.Get();
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, channel_fd.Get(), &event) < 0) {
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::OnNewChannelLocked: Failed to add channel to endpoint: %s\n",
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        strerror(errno));
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelData channel_data;
2506890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  const int channel_id = channel_fd.Get();
2516890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  channel_data.event_set.AddDataFd(channel_fd);
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_data.data_fd = std::move(channel_fd);
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_data.channel_state = channel_state;
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto pair = channels_.emplace(channel_id, std::move(channel_data));
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return &pair.first->second;
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::ReenableEpollEvent(int fd) {
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event event;
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  event.data.fd = fd;
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd, &event) < 0) {
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::ReenableEpollEvent: Failed to re-enable channel to "
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "endpoint: %s\n",
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        strerror(errno));
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::CloseChannel(int channel_id) {
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return CloseChannelLocked(channel_id);
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::CloseChannelLocked(int channel_id) {
2786890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id);
2796890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_data == channels_.end())
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -EINVAL;
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int ret = 0;
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_id, &dummy) < 0) {
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ret = -errno;
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "%s\n",
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        strerror(errno));
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channels_.erase(channel_data);
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ret;
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::ModifyChannelEvents(int channel_id, int clear_mask,
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  int set_mask) {
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3026890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  auto search = channels_.find(channel_id);
3036890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  if (search != channels_.end()) {
3046890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    auto& channel_data = search->second;
3056890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    channel_data.event_set.ModifyEvents(clear_mask, set_mask);
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3096890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  return -EINVAL;
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<RemoteChannelHandle> Endpoint::PushChannel(Message* message,
313e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                  int /*flags*/,
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                  Channel* channel,
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                  int* channel_id) {
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_pair[2] = {};
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel_pair) == -1) {
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::PushChannel: Failed to create a socket pair: %s",
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle local_socket{channel_pair[0]};
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle remote_socket{channel_pair[1]};
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int optval = 1;
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (setsockopt(local_socket.Get(), SOL_SOCKET, SO_PASSCRED, &optval,
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 sizeof(optval)) == -1) {
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "Endpoint::PushChannel: Failed to enable the receiving of the "
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "credentials for channel %d: %s",
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        local_socket.Get(), strerror(errno));
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  *channel_id = local_socket.Get();
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!channel_data)
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(channel_data.error());
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Flags are ignored for now.
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // TODO(xiaohuit): Implement those.
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelReference ref = state->PushChannelHandle(
3476890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      remote_socket.Borrow(),
3486890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_data.get()->event_set.event_fd().Borrow());
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->sockets_to_close.push_back(std::move(remote_socket));
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return RemoteChannelHandle{ref};
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> Endpoint::CheckChannel(const Message* /*message*/,
354e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                   ChannelReference /*ref*/,
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                   Channel** /*channel*/) {
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // TODO(xiaohuit): Implement this.
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ErrorStatus(EFAULT);
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::DefaultHandleMessage(const MessageInfo& /* info */) {
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ALOGE(
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      "Endpoint::CheckChannel: Not implemented! Endpoint DefaultHandleMessage "
363e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      "does nothing!");
364e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return 0;
365e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannel* Endpoint::GetChannelState(int channel_id) {
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return (channel_data != channels_.end()) ? channel_data->second.channel_state
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           : nullptr;
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
373e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::GetChannelSocketFd(int channel_id) {
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
377e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return (channel_data != channels_.end()) ? channel_data->second.data_fd.Get()
378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           : -1;
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::GetChannelEventFd(int channel_id) {
382e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channel_mutex_);
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto channel_data = channels_.find(channel_id);
3846890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  return (channel_data != channels_.end())
3856890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka             ? channel_data->second.event_set.event_fd().Get()
3866890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka             : -1;
387e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
388e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
389e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> Endpoint::ReceiveMessageForChannel(int channel_id,
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                Message* message) {
391e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  RequestHeader<LocalHandle> request;
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveData(channel_id, &request);
393e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status) {
3946890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (status.error() == ESHUTDOWN) {
3956890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      BuildCloseMessage(channel_id, message);
3966890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return {};
3976890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
3986890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      CloseChannel(channel_id);
3996890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return status;
4006890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
4026890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  MessageInfo info;
404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.pid = request.cred.pid;
405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.tid = -1;
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.cid = channel_id;
407e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.mid = request.is_impulse ? Message::IMPULSE_MESSAGE_ID
408e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                : GetNextAvailableMessageId();
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.euid = request.cred.uid;
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.egid = request.cred.gid;
411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.op = request.op;
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.flags = 0;
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.service = service_;
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.channel = GetChannelState(channel_id);
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.send_len = request.send_len;
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.recv_len = request.max_recv_len;
417e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  info.fd_count = request.file_descriptors.size();
418e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static_assert(sizeof(info.impulse) == request.impulse_payload.size(),
419e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                "Impulse payload sizes must be the same in RequestHeader and "
420e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                "MessageInfo");
421e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  memcpy(info.impulse, request.impulse_payload.data(),
422e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko         request.impulse_payload.size());
423e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  *message = Message{info};
424e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
425e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->request = std::move(request);
426e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (request.send_len > 0 && !request.is_impulse) {
427e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    state->request_data.resize(request.send_len);
428e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReceiveData(channel_id, state->request_data.data(),
429e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                         state->request_data.size());
430e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
431e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
432e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status && request.is_impulse)
433e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReenableEpollEvent(channel_id);
434e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4356890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  if (!status) {
4366890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (status.error() == ESHUTDOWN) {
4376890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      BuildCloseMessage(channel_id, message);
4386890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return {};
4396890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
4406890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      CloseChannel(channel_id);
4416890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return status;
4426890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
4436890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  }
444e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
445e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
446e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
447e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4486890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabakavoid Endpoint::BuildCloseMessage(int channel_id, Message* message) {
4496890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  ALOGD_IF(TRACE, "Endpoint::BuildCloseMessage: channel_id=%d", channel_id);
4506890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  MessageInfo info;
4516890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.pid = -1;
4526890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.tid = -1;
4536890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.cid = channel_id;
4546890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.mid = GetNextAvailableMessageId();
4556890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.euid = -1;
4566890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.egid = -1;
4576890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.op = opcodes::CHANNEL_CLOSE;
4586890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.flags = 0;
4596890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.service = service_;
4606890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.channel = GetChannelState(channel_id);
4616890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.send_len = 0;
4626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.recv_len = 0;
4636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  info.fd_count = 0;
4646890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  *message = Message{info};
4656890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka}
466e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4676890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabakaint Endpoint::MessageReceive(Message* message) {
4686890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  // Receive at most one event from the epoll set. This should prevent multiple
4696890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  // dispatch threads from attempting to handle messages on the same socket at
4706890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  // the same time.
471e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  epoll_event event;
472e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int count = RETRY_EINTR(
473e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      epoll_wait(epoll_fd_.Get(), &event, 1, is_blocking_ ? -1 : 0));
474e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (count < 0) {
475e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Endpoint::MessageReceive: Failed to wait for epoll events: %s\n",
476e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
477e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -errno;
478e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else if (count == 0) {
479e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -ETIMEDOUT;
480e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
481e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
482e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (event.data.fd == cancel_event_fd_.Get()) {
483e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -ESHUTDOWN;
484e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
485e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
486e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (event.data.fd == socket_fd_.Get()) {
487e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = AcceptConnection(message);
488e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status)
489e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -status.error();
490e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReenableEpollEvent(socket_fd_.Get());
491e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status ? 0 : -status.error();
492e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
493e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
494e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id = event.data.fd;
4956890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
4966890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    BuildCloseMessage(channel_id, message);
497e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
498e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
499e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
500e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveMessageForChannel(channel_id, message);
501e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status)
502e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -status.error();
503e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return 0;
504e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
505e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
506e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::MessageReply(Message* message, int return_code) {
5076890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  const int channel_id = message->GetChannelId();
5086890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  const int channel_socket = GetChannelSocketFd(channel_id);
509e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_socket < 0)
510e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -EBADF;
511e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
512e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
513e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  switch (message->GetOp()) {
514e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_CLOSE:
5156890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return CloseChannel(channel_id);
516e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
517e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_OPEN:
518e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (return_code < 0)
5196890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka        return CloseChannel(channel_id);
520e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Reply with the event fd.
521e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return_code = state->PushFileHandle(
522e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          BorrowedHandle{GetChannelEventFd(channel_socket)});
523e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      state->response_data.clear();  // Just in case...
524e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      break;
525e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
526e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
527e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->response.ret_code = return_code;
528e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->response.recv_len = state->response_data.size();
529e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = SendData(channel_socket, state->response);
530e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status && !state->response_data.empty()) {
531e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = SendData(channel_socket, state->response_data.data(),
532e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      state->response_data.size());
533e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
534e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
535e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status)
536e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReenableEpollEvent(channel_socket);
537e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
538e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status ? 0 : -status.error();
539e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
540e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
541e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::MessageReplyFd(Message* message, unsigned int push_fd) {
542e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
543e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto ref = state->PushFileHandle(BorrowedHandle{static_cast<int>(push_fd)});
544e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return MessageReply(message, ref);
545e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
546e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
547e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::MessageReplyChannelHandle(Message* message,
548e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                        const LocalChannelHandle& handle) {
549e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
550e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto ref = state->PushChannelHandle(handle.Borrow());
551e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return MessageReply(message, ref);
552e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
553e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
554e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::MessageReplyChannelHandle(Message* message,
555e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                        const BorrowedChannelHandle& handle) {
556e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
557e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto ref = state->PushChannelHandle(handle.Duplicate());
558e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return MessageReply(message, ref);
559e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
560e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
561e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::MessageReplyChannelHandle(Message* message,
562e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                        const RemoteChannelHandle& handle) {
563e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return MessageReply(message, handle.value());
564e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
565e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
566e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkossize_t Endpoint::ReadMessageData(Message* message, const iovec* vector,
567e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  size_t vector_length) {
568e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
569e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->ReadData(vector, vector_length);
570e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
571e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
572e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkossize_t Endpoint::WriteMessageData(Message* message, const iovec* vector,
573e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                   size_t vector_length) {
574e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
575e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->WriteData(vector, vector_length);
576e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
577e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
578e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference Endpoint::PushFileHandle(Message* message,
579e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const LocalHandle& handle) {
580e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
581e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Borrow());
582e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
583e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
584e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference Endpoint::PushFileHandle(Message* message,
585e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const BorrowedHandle& handle) {
586e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
587e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Duplicate());
588e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
589e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
590e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference Endpoint::PushFileHandle(Message* /*message*/,
591e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const RemoteHandle& handle) {
592e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle.Get();
593e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
594e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
595e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference Endpoint::PushChannelHandle(Message* message,
596e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                             const LocalChannelHandle& handle) {
597e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
598e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Borrow());
599e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
600e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
601e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference Endpoint::PushChannelHandle(
602e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Message* message, const BorrowedChannelHandle& handle) {
603e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
604e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Duplicate());
605e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
606e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
607e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference Endpoint::PushChannelHandle(
608e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Message* /*message*/, const RemoteChannelHandle& handle) {
609e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle.value();
610e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
611e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
612e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoLocalHandle Endpoint::GetFileHandle(Message* message, FileReference ref) const {
613e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle handle;
614e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
615e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->GetLocalFileHandle(ref, &handle);
616e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle;
617e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
618e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
619e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoLocalChannelHandle Endpoint::GetChannelHandle(Message* message,
620e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                              ChannelReference ref) const {
621e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalChannelHandle handle;
622e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<MessageState*>(message->GetState());
623e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state->GetLocalChannelHandle(ref, &handle);
624e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle;
625e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
626e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
627e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Endpoint::Cancel() {
628e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return (eventfd_write(cancel_event_fd_.Get(), 1) < 0) ? -errno : 0;
629e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
630e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
631e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<Endpoint> Endpoint::Create(const std::string& endpoint_path,
632e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           mode_t /*unused_mode*/,
633e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                           bool blocking) {
634e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::unique_ptr<Endpoint>(new Endpoint(endpoint_path, blocking));
635e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
636e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
637e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
638e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
639e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
640