1 #include "uds/client_channel.h"
6 #include <sys/socket.h>
8 #include <pdx/client.h>
9 #include <pdx/service_endpoint.h>
10 #include <uds/ipc_helper.h>
18 struct TransactionState {
19 bool GetLocalFileHandle(int index, LocalHandle* handle) {
22 } else if (static_cast<size_t>(index) < response.file_descriptors.size()) {
23 *handle = std::move(response.file_descriptors[index]);
30 bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
32 *handle = LocalChannelHandle{nullptr, index};
33 } else if (static_cast<size_t>(index) < response.channels.size()) {
34 auto& channel_info = response.channels[index];
35 *handle = ChannelManager::Get().CreateHandle(
36 std::move(channel_info.data_fd), std::move(channel_info.event_fd));
43 FileReference PushFileHandle(BorrowedHandle handle) {
46 request.file_descriptors.push_back(std::move(handle));
47 return request.file_descriptors.size() - 1;
50 ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
52 return handle.value();
54 if (auto* channel_data =
55 ChannelManager::Get().GetChannelData(handle.value())) {
56 ChannelInfo<BorrowedHandle> channel_info;
57 channel_info.data_fd.Reset(handle.value());
58 channel_info.event_fd = channel_data->event_receiver.event_fd();
59 request.channels.push_back(std::move(channel_info));
60 return request.channels.size() - 1;
66 RequestHeader<BorrowedHandle> request;
67 ResponseHeader<LocalHandle> response;
70 Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
72 // If there is more data to read in the message than the buffers provided
73 // by the caller, read and discard the extra data from the socket.
75 size_t size_to_read = std::min(sizeof(buffer), size);
76 auto status = ReceiveData(socket_fd, buffer, size_to_read);
81 // We still want to return EIO error to the caller in case we had unexpected
82 // data in the socket stream.
83 return ErrorStatus(EIO);
86 Status<void> SendRequest(const BorrowedHandle& socket_fd,
87 TransactionState* transaction_state, int opcode,
88 const iovec* send_vector, size_t send_count,
89 size_t max_recv_len) {
90 size_t send_len = CountVectorSize(send_vector, send_count);
91 InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
94 send_vector = nullptr;
97 return SendData(socket_fd, transaction_state->request, send_vector,
101 Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
102 TransactionState* transaction_state,
103 const iovec* receive_vector, size_t receive_count,
104 size_t max_recv_len) {
105 auto status = ReceiveData(socket_fd, &transaction_state->response);
109 if (transaction_state->response.recv_len > 0) {
110 std::vector<iovec> read_buffers;
111 size_t size_remaining = 0;
112 if (transaction_state->response.recv_len != max_recv_len) {
113 // If the receive buffer not exactly the size of data available, recreate
114 // the vector list to consume the data exactly since ReceiveDataVector()
115 // validates that the number of bytes received equals the number of bytes
117 size_remaining = transaction_state->response.recv_len;
118 for (size_t i = 0; i < receive_count && size_remaining > 0; i++) {
119 read_buffers.push_back(receive_vector[i]);
120 iovec& last_vec = read_buffers.back();
121 if (last_vec.iov_len > size_remaining)
122 last_vec.iov_len = size_remaining;
123 size_remaining -= last_vec.iov_len;
125 receive_vector = read_buffers.data();
126 receive_count = read_buffers.size();
128 status = ReceiveDataVector(socket_fd, receive_vector, receive_count);
129 if (status && size_remaining > 0)
130 status = ReadAndDiscardData(socket_fd, size_remaining);
135 } // anonymous namespace
137 ClientChannel::ClientChannel(LocalChannelHandle channel_handle)
138 : channel_handle_{std::move(channel_handle)} {
139 channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
142 std::unique_ptr<pdx::ClientChannel> ClientChannel::Create(
143 LocalChannelHandle channel_handle) {
144 return std::unique_ptr<pdx::ClientChannel>{
145 new ClientChannel{std::move(channel_handle)}};
148 ClientChannel::~ClientChannel() {
150 shutdown(channel_handle_.value(), SHUT_WR);
153 void* ClientChannel::AllocateTransactionState() { return new TransactionState; }
155 void ClientChannel::FreeTransactionState(void* state) {
156 delete static_cast<TransactionState*>(state);
159 Status<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
161 std::unique_lock<std::mutex> lock(socket_mutex_);
163 android::pdx::uds::RequestHeader<BorrowedHandle> request;
164 if (length > request.impulse_payload.size() ||
165 (buffer == nullptr && length != 0)) {
166 status.SetError(EINVAL);
170 InitRequest(&request, opcode, length, 0, true);
171 memcpy(request.impulse_payload.data(), buffer, length);
172 return SendData(BorrowedHandle{channel_handle_.value()}, request);
175 Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
176 const iovec* send_vector,
178 const iovec* receive_vector,
179 size_t receive_count) {
180 std::unique_lock<std::mutex> lock(socket_mutex_);
182 if ((send_vector == nullptr && send_count != 0) ||
183 (receive_vector == nullptr && receive_count != 0)) {
184 result.SetError(EINVAL);
188 auto* state = static_cast<TransactionState*>(transaction_state);
189 size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
191 auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
192 opcode, send_vector, send_count, max_recv_len);
194 status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
195 receive_vector, receive_count, max_recv_len);
197 if (!result.PropagateError(status)) {
198 const int return_code = state->response.ret_code;
199 if (return_code >= 0)
200 result.SetValue(return_code);
202 result.SetError(-return_code);
207 Status<int> ClientChannel::SendWithInt(void* transaction_state, int opcode,
208 const iovec* send_vector,
210 const iovec* receive_vector,
211 size_t receive_count) {
212 return SendAndReceive(transaction_state, opcode, send_vector, send_count,
213 receive_vector, receive_count);
216 Status<LocalHandle> ClientChannel::SendWithFileHandle(
217 void* transaction_state, int opcode, const iovec* send_vector,
218 size_t send_count, const iovec* receive_vector, size_t receive_count) {
219 Status<int> int_status =
220 SendAndReceive(transaction_state, opcode, send_vector, send_count,
221 receive_vector, receive_count);
222 Status<LocalHandle> status;
223 if (status.PropagateError(int_status))
226 auto* state = static_cast<TransactionState*>(transaction_state);
228 if (state->GetLocalFileHandle(int_status.get(), &handle)) {
229 status.SetValue(std::move(handle));
231 status.SetError(EINVAL);
236 Status<LocalChannelHandle> ClientChannel::SendWithChannelHandle(
237 void* transaction_state, int opcode, const iovec* send_vector,
238 size_t send_count, const iovec* receive_vector, size_t receive_count) {
239 Status<int> int_status =
240 SendAndReceive(transaction_state, opcode, send_vector, send_count,
241 receive_vector, receive_count);
242 Status<LocalChannelHandle> status;
243 if (status.PropagateError(int_status))
246 auto* state = static_cast<TransactionState*>(transaction_state);
247 LocalChannelHandle handle;
248 if (state->GetLocalChannelHandle(int_status.get(), &handle)) {
249 status.SetValue(std::move(handle));
251 status.SetError(EINVAL);
256 FileReference ClientChannel::PushFileHandle(void* transaction_state,
257 const LocalHandle& handle) {
258 auto* state = static_cast<TransactionState*>(transaction_state);
259 return state->PushFileHandle(handle.Borrow());
262 FileReference ClientChannel::PushFileHandle(void* transaction_state,
263 const BorrowedHandle& handle) {
264 auto* state = static_cast<TransactionState*>(transaction_state);
265 return state->PushFileHandle(handle.Duplicate());
268 ChannelReference ClientChannel::PushChannelHandle(
269 void* transaction_state, const LocalChannelHandle& handle) {
270 auto* state = static_cast<TransactionState*>(transaction_state);
271 return state->PushChannelHandle(handle.Borrow());
274 ChannelReference ClientChannel::PushChannelHandle(
275 void* transaction_state, const BorrowedChannelHandle& handle) {
276 auto* state = static_cast<TransactionState*>(transaction_state);
277 return state->PushChannelHandle(handle.Duplicate());
280 bool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref,
281 LocalHandle* handle) const {
282 auto* state = static_cast<TransactionState*>(transaction_state);
283 return state->GetLocalFileHandle(ref, handle);
286 bool ClientChannel::GetChannelHandle(void* transaction_state,
287 ChannelReference ref,
288 LocalChannelHandle* handle) const {
289 auto* state = static_cast<TransactionState*>(transaction_state);
290 return state->GetLocalChannelHandle(ref, handle);
295 } // namespace android