client_channel.cpp revision fd22b3e5ad1aae1fc3de54801f33466db3c9b3fe
1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/client_channel.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <log/log.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/epoll.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/socket.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service_endpoint.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/ipc_helper.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds {
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct TransactionState {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalFileHandle(int index, LocalHandle* handle) {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      handle->Reset(index);
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < response.file_descriptors.size()) {
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = std::move(response.file_descriptors[index]);
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = LocalChannelHandle{nullptr, index};
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < response.channels.size()) {
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      auto& channel_info = response.channels[index];
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = ChannelManager::Get().CreateHandle(
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          std::move(channel_info.data_fd), std::move(channel_info.event_fd));
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  FileReference PushFileHandle(BorrowedHandle handle) {
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    request.file_descriptors.push_back(std::move(handle));
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return request.file_descriptors.size() - 1;
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
536890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
546890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (auto* channel_data =
556890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka            ChannelManager::Get().GetChannelData(handle.value())) {
566890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      ChannelInfo<BorrowedHandle> channel_info;
576890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_info.data_fd.Reset(handle.value());
586890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      channel_info.event_fd = channel_data->event_receiver.event_fd();
596890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      request.channels.push_back(std::move(channel_info));
606890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return request.channels.size() - 1;
616890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return -1;
636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  RequestHeader<BorrowedHandle> request;
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ResponseHeader<LocalHandle> response;
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
7009aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (size > 0) {
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // If there is more data to read in the message than the buffers provided
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // by the caller, read and discard the extra data from the socket.
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    char buffer[1024];
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_to_read = std::min(sizeof(buffer), size);
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = ReceiveData(socket_fd, buffer, size_to_read);
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status)
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return status;
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size -= size_to_read;
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // We still want to return EIO error to the caller in case we had unexpected
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // data in the socket stream.
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ErrorStatus(EIO);
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8609aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendRequest(const BorrowedHandle& socket_fd,
8709aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         TransactionState* transaction_state, int opcode,
8809aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         const iovec* send_vector, size_t send_count,
8909aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         size_t max_recv_len) {
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t send_len = CountVectorSize(send_vector, send_count);
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              false);
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = SendData(socket_fd, transaction_state->request);
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status && send_len > 0)
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = SendDataVector(socket_fd, send_vector, send_count);
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9909aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceiveResponse(const BorrowedHandle& socket_fd,
10009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                             TransactionState* transaction_state,
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             const iovec* receive_vector, size_t receive_count,
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             size_t max_recv_len) {
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveData(socket_fd, &transaction_state->response);
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status)
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (transaction_state->response.recv_len > 0) {
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::vector<iovec> read_buffers;
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_remaining = 0;
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (transaction_state->response.recv_len != max_recv_len) {
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // If the receive buffer not exactly the size of data available, recreate
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // the vector list to consume the data exactly since ReceiveDataVector()
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // validates that the number of bytes received equals the number of bytes
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // requested.
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_remaining = transaction_state->response.recv_len;
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      for (size_t i = 0; i < receive_count && size_remaining > 0; i++) {
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        read_buffers.push_back(receive_vector[i]);
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        iovec& last_vec = read_buffers.back();
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (last_vec.iov_len > size_remaining)
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          last_vec.iov_len = size_remaining;
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        size_remaining -= last_vec.iov_len;
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      receive_vector = read_buffers.data();
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      receive_count = read_buffers.size();
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReceiveDataVector(socket_fd, receive_vector, receive_count);
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (status && size_remaining > 0)
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      status = ReadAndDiscardData(socket_fd, size_remaining);
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannel::ClientChannel(LocalChannelHandle channel_handle)
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : channel_handle_{std::move(channel_handle)} {
1376890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<pdx::ClientChannel> ClientChannel::Create(
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    LocalChannelHandle channel_handle) {
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::unique_ptr<pdx::ClientChannel>{
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      new ClientChannel{std::move(channel_handle)}};
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannel::~ClientChannel() {
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_handle_)
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    shutdown(channel_handle_.value(), SHUT_WR);
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* ClientChannel::AllocateTransactionState() { return new TransactionState; }
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ClientChannel::FreeTransactionState(void* state) {
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  delete static_cast<TransactionState*>(state);
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                        size_t length) {
159fd22b3e5ad1aae1fc3de54801f33466db3c9b3feAlex Vakulenko  std::unique_lock<std::mutex> lock(socket_mutex_);
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<void> status;
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::RequestHeader<BorrowedHandle> request;
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (length > request.impulse_payload.size() ||
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      (buffer == nullptr && length != 0)) {
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InitRequest(&request, opcode, length, 0, true);
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  memcpy(request.impulse_payload.data(), buffer, length);
17009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko  return SendData(BorrowedHandle{channel_handle_.value()}, request);
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          const iovec* send_vector,
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          size_t send_count,
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          const iovec* receive_vector,
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          size_t receive_count) {
178fd22b3e5ad1aae1fc3de54801f33466db3c9b3feAlex Vakulenko  std::unique_lock<std::mutex> lock(socket_mutex_);
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> result;
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if ((send_vector == nullptr && send_count != 0) ||
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      (receive_vector == nullptr && receive_count != 0)) {
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    result.SetError(EINVAL);
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return result;
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
18909aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko  auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
19009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                            opcode, send_vector, send_count, max_recv_len);
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status) {
19209aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko    status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
19309aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                             receive_vector, receive_count, max_recv_len);
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!result.PropagateError(status)) {
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int return_code = state->response.ret_code;
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (return_code >= 0)
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      result.SetValue(return_code);
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      result.SetError(-return_code);
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return result;
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> ClientChannel::SendWithInt(void* transaction_state, int opcode,
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const iovec* send_vector,
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       size_t send_count,
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const iovec* receive_vector,
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       size_t receive_count) {
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return SendAndReceive(transaction_state, opcode, send_vector, send_count,
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        receive_vector, receive_count);
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<LocalHandle> ClientChannel::SendWithFileHandle(
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, int opcode, const iovec* send_vector,
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t send_count, const iovec* receive_vector, size_t receive_count) {
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> int_status =
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      SendAndReceive(transaction_state, opcode, send_vector, send_count,
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     receive_vector, receive_count);
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalHandle> status;
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status.PropagateError(int_status))
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle handle;
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (state->GetLocalFileHandle(int_status.get(), &handle)) {
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetValue(std::move(handle));
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<LocalChannelHandle> ClientChannel::SendWithChannelHandle(
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, int opcode, const iovec* send_vector,
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t send_count, const iovec* receive_vector, size_t receive_count) {
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> int_status =
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      SendAndReceive(transaction_state, opcode, send_vector, send_count,
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     receive_vector, receive_count);
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalChannelHandle> status;
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status.PropagateError(int_status))
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalChannelHandle handle;
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (state->GetLocalChannelHandle(int_status.get(), &handle)) {
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetValue(std::move(handle));
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference ClientChannel::PushFileHandle(void* transaction_state,
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                            const LocalHandle& handle) {
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Borrow());
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference ClientChannel::PushFileHandle(void* transaction_state,
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                            const BorrowedHandle& handle) {
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Duplicate());
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference ClientChannel::PushChannelHandle(
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, const LocalChannelHandle& handle) {
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Borrow());
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference ClientChannel::PushChannelHandle(
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, const BorrowedChannelHandle& handle) {
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Duplicate());
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref,
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  LocalHandle* handle) const {
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->GetLocalFileHandle(ref, handle);
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ClientChannel::GetChannelHandle(void* transaction_state,
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     ChannelReference ref,
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     LocalChannelHandle* handle) const {
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->GetLocalChannelHandle(ref, handle);
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
294