1a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai#include "uds/channel_parcelable.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/client_channel.h"
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <log/log.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/epoll.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/socket.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service_endpoint.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/ipc_helper.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct TransactionState {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalFileHandle(int index, LocalHandle* handle) {
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      handle->Reset(index);
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < response.file_descriptors.size()) {
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = std::move(response.file_descriptors[index]);
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (index < 0) {
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = LocalChannelHandle{nullptr, index};
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (static_cast<size_t>(index) < response.channels.size()) {
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      auto& channel_info = response.channels[index];
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *handle = ChannelManager::Get().CreateHandle(
3752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          std::move(channel_info.data_fd),
3852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          std::move(channel_info.pollin_event_fd),
3952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          std::move(channel_info.pollhup_event_fd));
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  FileReference PushFileHandle(BorrowedHandle handle) {
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.Get();
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    request.file_descriptors.push_back(std::move(handle));
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return request.file_descriptors.size() - 1;
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle)
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return handle.value();
566890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka
576890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    if (auto* channel_data =
586890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka            ChannelManager::Get().GetChannelData(handle.value())) {
5952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      ChannelInfo<BorrowedHandle> channel_info{
6052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          channel_data->data_fd(), channel_data->pollin_event_fd(),
6152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          channel_data->pollhup_event_fd()};
626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      request.channels.push_back(std::move(channel_info));
636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return request.channels.size() - 1;
646890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    } else {
656890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka      return -1;
666890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    }
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  RequestHeader<BorrowedHandle> request;
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ResponseHeader<LocalHandle> response;
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
7309aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (size > 0) {
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // If there is more data to read in the message than the buffers provided
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // by the caller, read and discard the extra data from the socket.
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    char buffer[1024];
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_to_read = std::min(sizeof(buffer), size);
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = ReceiveData(socket_fd, buffer, size_to_read);
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!status)
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return status;
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size -= size_to_read;
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // We still want to return EIO error to the caller in case we had unexpected
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // data in the socket stream.
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ErrorStatus(EIO);
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8909aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> SendRequest(const BorrowedHandle& socket_fd,
9009aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         TransactionState* transaction_state, int opcode,
9109aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         const iovec* send_vector, size_t send_count,
9209aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                         size_t max_recv_len) {
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t send_len = CountVectorSize(send_vector, send_count);
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              false);
96adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko  if (send_len == 0) {
97adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko    send_vector = nullptr;
98adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko    send_count = 0;
99adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko  }
100adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko  return SendData(socket_fd, transaction_state->request, send_vector,
101adfc42ead3921f94339372ffb561bc3e8d7f3c86Alex Vakulenko                  send_count);
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
10409aa736ee6136787b18807d7ab459feba23cec04Alex VakulenkoStatus<void> ReceiveResponse(const BorrowedHandle& socket_fd,
10509aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                             TransactionState* transaction_state,
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             const iovec* receive_vector, size_t receive_count,
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             size_t max_recv_len) {
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = ReceiveData(socket_fd, &transaction_state->response);
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status)
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (transaction_state->response.recv_len > 0) {
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::vector<iovec> read_buffers;
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t size_remaining = 0;
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (transaction_state->response.recv_len != max_recv_len) {
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // If the receive buffer not exactly the size of data available, recreate
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // the vector list to consume the data exactly since ReceiveDataVector()
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // validates that the number of bytes received equals the number of bytes
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // requested.
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_remaining = transaction_state->response.recv_len;
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      for (size_t i = 0; i < receive_count && size_remaining > 0; i++) {
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        read_buffers.push_back(receive_vector[i]);
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        iovec& last_vec = read_buffers.back();
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (last_vec.iov_len > size_remaining)
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          last_vec.iov_len = size_remaining;
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        size_remaining -= last_vec.iov_len;
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      receive_vector = read_buffers.data();
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      receive_count = read_buffers.size();
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status = ReceiveDataVector(socket_fd, receive_vector, receive_count);
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (status && size_remaining > 0)
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      status = ReadAndDiscardData(socket_fd, size_remaining);
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannel::ClientChannel(LocalChannelHandle channel_handle)
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : channel_handle_{std::move(channel_handle)} {
1426890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<pdx::ClientChannel> ClientChannel::Create(
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    LocalChannelHandle channel_handle) {
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::unique_ptr<pdx::ClientChannel>{
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      new ClientChannel{std::move(channel_handle)}};
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoClientChannel::~ClientChannel() {
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_handle_)
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    shutdown(channel_handle_.value(), SHUT_WR);
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* ClientChannel::AllocateTransactionState() { return new TransactionState; }
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ClientChannel::FreeTransactionState(void* state) {
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  delete static_cast<TransactionState*>(state);
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                        size_t length) {
164fd22b3e5ad1aae1fc3de54801f33466db3c9b3feAlex Vakulenko  std::unique_lock<std::mutex> lock(socket_mutex_);
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<void> status;
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::uds::RequestHeader<BorrowedHandle> request;
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (length > request.impulse_payload.size() ||
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      (buffer == nullptr && length != 0)) {
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  InitRequest(&request, opcode, length, 0, true);
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  memcpy(request.impulse_payload.data(), buffer, length);
17509aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko  return SendData(BorrowedHandle{channel_handle_.value()}, request);
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          const iovec* send_vector,
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          size_t send_count,
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          const iovec* receive_vector,
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                          size_t receive_count) {
183fd22b3e5ad1aae1fc3de54801f33466db3c9b3feAlex Vakulenko  std::unique_lock<std::mutex> lock(socket_mutex_);
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> result;
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if ((send_vector == nullptr && send_count != 0) ||
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      (receive_vector == nullptr && receive_count != 0)) {
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    result.SetError(EINVAL);
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return result;
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
19409aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko  auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
19509aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                            opcode, send_vector, send_count, max_recv_len);
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status) {
19709aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko    status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
19809aa736ee6136787b18807d7ab459feba23cec04Alex Vakulenko                             receive_vector, receive_count, max_recv_len);
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!result.PropagateError(status)) {
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int return_code = state->response.ret_code;
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (return_code >= 0)
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      result.SetValue(return_code);
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      result.SetError(-return_code);
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return result;
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> ClientChannel::SendWithInt(void* transaction_state, int opcode,
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const iovec* send_vector,
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       size_t send_count,
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       const iovec* receive_vector,
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       size_t receive_count) {
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return SendAndReceive(transaction_state, opcode, send_vector, send_count,
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        receive_vector, receive_count);
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<LocalHandle> ClientChannel::SendWithFileHandle(
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, int opcode, const iovec* send_vector,
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t send_count, const iovec* receive_vector, size_t receive_count) {
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> int_status =
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      SendAndReceive(transaction_state, opcode, send_vector, send_count,
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     receive_vector, receive_count);
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalHandle> status;
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status.PropagateError(int_status))
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle handle;
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (state->GetLocalFileHandle(int_status.get(), &handle)) {
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetValue(std::move(handle));
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<LocalChannelHandle> ClientChannel::SendWithChannelHandle(
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, int opcode, const iovec* send_vector,
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t send_count, const iovec* receive_vector, size_t receive_count) {
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> int_status =
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      SendAndReceive(transaction_state, opcode, send_vector, send_count,
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     receive_vector, receive_count);
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalChannelHandle> status;
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (status.PropagateError(int_status))
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return status;
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalChannelHandle handle;
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (state->GetLocalChannelHandle(int_status.get(), &handle)) {
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetValue(std::move(handle));
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    status.SetError(EINVAL);
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return status;
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference ClientChannel::PushFileHandle(void* transaction_state,
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                            const LocalHandle& handle) {
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Borrow());
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoFileReference ClientChannel::PushFileHandle(void* transaction_state,
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                            const BorrowedHandle& handle) {
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushFileHandle(handle.Duplicate());
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference ClientChannel::PushChannelHandle(
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, const LocalChannelHandle& handle) {
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Borrow());
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoChannelReference ClientChannel::PushChannelHandle(
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    void* transaction_state, const BorrowedChannelHandle& handle) {
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->PushChannelHandle(handle.Duplicate());
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref,
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  LocalHandle* handle) const {
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->GetLocalFileHandle(ref, handle);
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ClientChannel::GetChannelHandle(void* transaction_state,
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     ChannelReference ref,
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                     LocalChannelHandle* handle) const {
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto* state = static_cast<TransactionState*>(transaction_state);
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return state->GetLocalChannelHandle(ref, handle);
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
296a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Caistd::unique_ptr<pdx::ChannelParcelable> ClientChannel::TakeChannelParcelable()
297a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    {
298a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai  if (!channel_handle_)
299a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    return nullptr;
300a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai
301a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai  if (auto* channel_data =
302a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai          ChannelManager::Get().GetChannelData(channel_handle_.value())) {
303a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    auto fds = channel_data->TakeFds();
304a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    auto parcelable = std::make_unique<ChannelParcelable>(
305a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai        std::move(std::get<0>(fds)), std::move(std::get<1>(fds)),
306a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai        std::move(std::get<2>(fds)));
307a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai
308a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    // Here we need to explicitly close the channel handle so that the channel
309a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    // won't get shutdown in the destructor, while the FDs in ChannelParcelable
310a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    // can keep the channel alive so that new client can be created from it
311a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    // later.
312a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    channel_handle_.Close();
313a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    return parcelable;
314a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai  } else {
315a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai    return nullptr;
316a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai  }
317a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai}
318a88e3ee3a33a60e72bd976cfb5b9fc0bd15a1078Jiwen 'Steve' Cai
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
322