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(
3652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          std::move(channel_info.data_fd),
3752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          std::move(channel_info.pollin_event_fd),
3852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          std::move(channel_info.pollhup_event_fd));
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  FileReference PushFileHandle(BorrowedHandle handle) {
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    request.file_descriptors.push_back(std::move(handle));
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return request.file_descriptors.size() - 1;
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
556890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
566890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (auto* channel_data =
576890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka            ChannelManager::Get().GetChannelData(handle.value())) {
5852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      ChannelInfo<BorrowedHandle> channel_info{
5952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          channel_data->data_fd(), channel_data->pollin_event_fd(),
6052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          channel_data->pollhup_event_fd()};
616890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      request.channels.push_back(std::move(channel_info));
626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return request.channels.size() - 1;
636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
646890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return -1;
656890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  RequestHeader<BorrowedHandle> request;
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ResponseHeader<LocalHandle> response;
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
7209aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (size > 0) {
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // If there is more data to read in the message than the buffers provided
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // by the caller, read and discard the extra data from the socket.
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    char buffer[1024];
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_to_read = std::min(sizeof(buffer), size);
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = ReceiveData(socket_fd, buffer, size_to_read);
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status)
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return status;
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size -= size_to_read;
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // We still want to return EIO error to the caller in case we had unexpected
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // data in the socket stream.
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ErrorStatus(EIO);
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8809aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendRequest(const BorrowedHandle& socket_fd,
8909aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         TransactionState* transaction_state, int opcode,
9009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         const iovec* send_vector, size_t send_count,
9109aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         size_t max_recv_len) {
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t send_len = CountVectorSize(send_vector, send_count);
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              false);
95adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko  if (send_len == 0) {
96adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko    send_vector = nullptr;
97adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko    send_count = 0;
98adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko  }
99adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko  return SendData(socket_fd, transaction_state->request, send_vector,
100adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko                  send_count);
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
10309aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceiveResponse(const BorrowedHandle& socket_fd,
10409aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                             TransactionState* transaction_state,
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             const iovec* receive_vector, size_t receive_count,
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             size_t max_recv_len) {
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveData(socket_fd, &transaction_state->response);
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status)
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (transaction_state->response.recv_len > 0) {
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::vector<iovec> read_buffers;
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_remaining = 0;
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (transaction_state->response.recv_len != max_recv_len) {
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // If the receive buffer not exactly the size of data available, recreate
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // the vector list to consume the data exactly since ReceiveDataVector()
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // validates that the number of bytes received equals the number of bytes
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // requested.
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_remaining = transaction_state->response.recv_len;
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      for (size_t i = 0; i < receive_count && size_remaining > 0; i++) {
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        read_buffers.push_back(receive_vector[i]);
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        iovec& last_vec = read_buffers.back();
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (last_vec.iov_len > size_remaining)
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          last_vec.iov_len = size_remaining;
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        size_remaining -= last_vec.iov_len;
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      receive_vector = read_buffers.data();
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      receive_count = read_buffers.size();
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReceiveDataVector(socket_fd, receive_vector, receive_count);
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (status && size_remaining > 0)
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      status = ReadAndDiscardData(socket_fd, size_remaining);
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannel::ClientChannel(LocalChannelHandle channel_handle)
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : channel_handle_{std::move(channel_handle)} {
1416890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<pdx::ClientChannel> ClientChannel::Create(
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    LocalChannelHandle channel_handle) {
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::unique_ptr<pdx::ClientChannel>{
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      new ClientChannel{std::move(channel_handle)}};
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannel::~ClientChannel() {
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_handle_)
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    shutdown(channel_handle_.value(), SHUT_WR);
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* ClientChannel::AllocateTransactionState() { return new TransactionState; }
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ClientChannel::FreeTransactionState(void* state) {
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  delete static_cast<TransactionState*>(state);
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                        size_t length) {
163fd22b3e5ad1aae1fc3de54801f33466db3c9b3feAlex Vakulenko  std::unique_lock<std::mutex> lock(socket_mutex_);
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<void> status;
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::RequestHeader<BorrowedHandle> request;
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (length > request.impulse_payload.size() ||
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      (buffer == nullptr && length != 0)) {
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InitRequest(&request, opcode, length, 0, true);
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  memcpy(request.impulse_payload.data(), buffer, length);
17409aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko  return SendData(BorrowedHandle{channel_handle_.value()}, request);
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          const iovec* send_vector,
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          size_t send_count,
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          const iovec* receive_vector,
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          size_t receive_count) {
182fd22b3e5ad1aae1fc3de54801f33466db3c9b3feAlex Vakulenko  std::unique_lock<std::mutex> lock(socket_mutex_);
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> result;
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if ((send_vector == nullptr && send_count != 0) ||
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      (receive_vector == nullptr && receive_count != 0)) {
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    result.SetError(EINVAL);
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return result;
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
19309aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko  auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
19409aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                            opcode, send_vector, send_count, max_recv_len);
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status) {
19609aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko    status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
19709aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                             receive_vector, receive_count, max_recv_len);
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!result.PropagateError(status)) {
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int return_code = state->response.ret_code;
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (return_code >= 0)
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      result.SetValue(return_code);
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      result.SetError(-return_code);
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return result;
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> ClientChannel::SendWithInt(void* transaction_state, int opcode,
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const iovec* send_vector,
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       size_t send_count,
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const iovec* receive_vector,
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       size_t receive_count) {
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return SendAndReceive(transaction_state, opcode, send_vector, send_count,
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        receive_vector, receive_count);
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<LocalHandle> ClientChannel::SendWithFileHandle(
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, int opcode, const iovec* send_vector,
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t send_count, const iovec* receive_vector, size_t receive_count) {
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> int_status =
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      SendAndReceive(transaction_state, opcode, send_vector, send_count,
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     receive_vector, receive_count);
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalHandle> status;
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status.PropagateError(int_status))
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle handle;
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (state->GetLocalFileHandle(int_status.get(), &handle)) {
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetValue(std::move(handle));
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<LocalChannelHandle> ClientChannel::SendWithChannelHandle(
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, int opcode, const iovec* send_vector,
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t send_count, const iovec* receive_vector, size_t receive_count) {
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> int_status =
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      SendAndReceive(transaction_state, opcode, send_vector, send_count,
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     receive_vector, receive_count);
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalChannelHandle> status;
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status.PropagateError(int_status))
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalChannelHandle handle;
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (state->GetLocalChannelHandle(int_status.get(), &handle)) {
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetValue(std::move(handle));
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference ClientChannel::PushFileHandle(void* transaction_state,
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                            const LocalHandle& handle) {
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Borrow());
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference ClientChannel::PushFileHandle(void* transaction_state,
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                            const BorrowedHandle& handle) {
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Duplicate());
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference ClientChannel::PushChannelHandle(
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, const LocalChannelHandle& handle) {
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Borrow());
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference ClientChannel::PushChannelHandle(
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, const BorrowedChannelHandle& handle) {
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Duplicate());
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref,
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  LocalHandle* handle) const {
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->GetLocalFileHandle(ref, handle);
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ClientChannel::GetChannelHandle(void* transaction_state,
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     ChannelReference ref,
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     LocalChannelHandle* handle) const {
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->GetLocalChannelHandle(ref, handle);
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
298