OSDN Git Service

Merge "Add thread usage output to lshal." am: 4a3e0a9767 am: 9a130151a2
[android-x86/frameworks-native.git] / libs / vr / libpdx_uds / client_channel.cpp
1 #include "uds/client_channel.h"
2
3 #include <errno.h>
4 #include <log/log.h>
5 #include <sys/epoll.h>
6 #include <sys/socket.h>
7
8 #include <pdx/client.h>
9 #include <pdx/service_endpoint.h>
10 #include <uds/ipc_helper.h>
11
12 namespace android {
13 namespace pdx {
14 namespace uds {
15
16 namespace {
17
18 struct TransactionState {
19   bool GetLocalFileHandle(int index, LocalHandle* handle) {
20     if (index < 0) {
21       handle->Reset(index);
22     } else if (static_cast<size_t>(index) < response.file_descriptors.size()) {
23       *handle = std::move(response.file_descriptors[index]);
24     } else {
25       return false;
26     }
27     return true;
28   }
29
30   bool GetLocalChannelHandle(int index, LocalChannelHandle* handle) {
31     if (index < 0) {
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));
37     } else {
38       return false;
39     }
40     return true;
41   }
42
43   FileReference PushFileHandle(BorrowedHandle handle) {
44     if (!handle)
45       return handle.Get();
46     request.file_descriptors.push_back(std::move(handle));
47     return request.file_descriptors.size() - 1;
48   }
49
50   ChannelReference PushChannelHandle(BorrowedChannelHandle handle) {
51     if (!handle)
52       return handle.value();
53
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;
61     } else {
62       return -1;
63     }
64   }
65
66   RequestHeader<BorrowedHandle> request;
67   ResponseHeader<LocalHandle> response;
68 };
69
70 Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
71   while (size > 0) {
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.
74     char buffer[1024];
75     size_t size_to_read = std::min(sizeof(buffer), size);
76     auto status = ReceiveData(socket_fd, buffer, size_to_read);
77     if (!status)
78       return status;
79     size -= size_to_read;
80   }
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);
84 }
85
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,
92               false);
93   auto status = SendData(socket_fd, transaction_state->request);
94   if (status && send_len > 0)
95     status = SendDataVector(socket_fd, send_vector, send_count);
96   return status;
97 }
98
99 Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
100                              TransactionState* transaction_state,
101                              const iovec* receive_vector, size_t receive_count,
102                              size_t max_recv_len) {
103   auto status = ReceiveData(socket_fd, &transaction_state->response);
104   if (!status)
105     return status;
106
107   if (transaction_state->response.recv_len > 0) {
108     std::vector<iovec> read_buffers;
109     size_t size_remaining = 0;
110     if (transaction_state->response.recv_len != max_recv_len) {
111       // If the receive buffer not exactly the size of data available, recreate
112       // the vector list to consume the data exactly since ReceiveDataVector()
113       // validates that the number of bytes received equals the number of bytes
114       // requested.
115       size_remaining = transaction_state->response.recv_len;
116       for (size_t i = 0; i < receive_count && size_remaining > 0; i++) {
117         read_buffers.push_back(receive_vector[i]);
118         iovec& last_vec = read_buffers.back();
119         if (last_vec.iov_len > size_remaining)
120           last_vec.iov_len = size_remaining;
121         size_remaining -= last_vec.iov_len;
122       }
123       receive_vector = read_buffers.data();
124       receive_count = read_buffers.size();
125     }
126     status = ReceiveDataVector(socket_fd, receive_vector, receive_count);
127     if (status && size_remaining > 0)
128       status = ReadAndDiscardData(socket_fd, size_remaining);
129   }
130   return status;
131 }
132
133 }  // anonymous namespace
134
135 ClientChannel::ClientChannel(LocalChannelHandle channel_handle)
136     : channel_handle_{std::move(channel_handle)} {
137   channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
138 }
139
140 std::unique_ptr<pdx::ClientChannel> ClientChannel::Create(
141     LocalChannelHandle channel_handle) {
142   return std::unique_ptr<pdx::ClientChannel>{
143       new ClientChannel{std::move(channel_handle)}};
144 }
145
146 ClientChannel::~ClientChannel() {
147   if (channel_handle_)
148     shutdown(channel_handle_.value(), SHUT_WR);
149 }
150
151 void* ClientChannel::AllocateTransactionState() { return new TransactionState; }
152
153 void ClientChannel::FreeTransactionState(void* state) {
154   delete static_cast<TransactionState*>(state);
155 }
156
157 Status<void> ClientChannel::SendImpulse(int opcode, const void* buffer,
158                                         size_t length) {
159   std::unique_lock<std::mutex> lock(socket_mutex_);
160   Status<void> status;
161   android::pdx::uds::RequestHeader<BorrowedHandle> request;
162   if (length > request.impulse_payload.size() ||
163       (buffer == nullptr && length != 0)) {
164     status.SetError(EINVAL);
165     return status;
166   }
167
168   InitRequest(&request, opcode, length, 0, true);
169   memcpy(request.impulse_payload.data(), buffer, length);
170   return SendData(BorrowedHandle{channel_handle_.value()}, request);
171 }
172
173 Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
174                                           const iovec* send_vector,
175                                           size_t send_count,
176                                           const iovec* receive_vector,
177                                           size_t receive_count) {
178   std::unique_lock<std::mutex> lock(socket_mutex_);
179   Status<int> result;
180   if ((send_vector == nullptr && send_count != 0) ||
181       (receive_vector == nullptr && receive_count != 0)) {
182     result.SetError(EINVAL);
183     return result;
184   }
185
186   auto* state = static_cast<TransactionState*>(transaction_state);
187   size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
188
189   auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
190                             opcode, send_vector, send_count, max_recv_len);
191   if (status) {
192     status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
193                              receive_vector, receive_count, max_recv_len);
194   }
195   if (!result.PropagateError(status)) {
196     const int return_code = state->response.ret_code;
197     if (return_code >= 0)
198       result.SetValue(return_code);
199     else
200       result.SetError(-return_code);
201   }
202   return result;
203 }
204
205 Status<int> ClientChannel::SendWithInt(void* transaction_state, int opcode,
206                                        const iovec* send_vector,
207                                        size_t send_count,
208                                        const iovec* receive_vector,
209                                        size_t receive_count) {
210   return SendAndReceive(transaction_state, opcode, send_vector, send_count,
211                         receive_vector, receive_count);
212 }
213
214 Status<LocalHandle> ClientChannel::SendWithFileHandle(
215     void* transaction_state, int opcode, const iovec* send_vector,
216     size_t send_count, const iovec* receive_vector, size_t receive_count) {
217   Status<int> int_status =
218       SendAndReceive(transaction_state, opcode, send_vector, send_count,
219                      receive_vector, receive_count);
220   Status<LocalHandle> status;
221   if (status.PropagateError(int_status))
222     return status;
223
224   auto* state = static_cast<TransactionState*>(transaction_state);
225   LocalHandle handle;
226   if (state->GetLocalFileHandle(int_status.get(), &handle)) {
227     status.SetValue(std::move(handle));
228   } else {
229     status.SetError(EINVAL);
230   }
231   return status;
232 }
233
234 Status<LocalChannelHandle> ClientChannel::SendWithChannelHandle(
235     void* transaction_state, int opcode, const iovec* send_vector,
236     size_t send_count, const iovec* receive_vector, size_t receive_count) {
237   Status<int> int_status =
238       SendAndReceive(transaction_state, opcode, send_vector, send_count,
239                      receive_vector, receive_count);
240   Status<LocalChannelHandle> status;
241   if (status.PropagateError(int_status))
242     return status;
243
244   auto* state = static_cast<TransactionState*>(transaction_state);
245   LocalChannelHandle handle;
246   if (state->GetLocalChannelHandle(int_status.get(), &handle)) {
247     status.SetValue(std::move(handle));
248   } else {
249     status.SetError(EINVAL);
250   }
251   return status;
252 }
253
254 FileReference ClientChannel::PushFileHandle(void* transaction_state,
255                                             const LocalHandle& handle) {
256   auto* state = static_cast<TransactionState*>(transaction_state);
257   return state->PushFileHandle(handle.Borrow());
258 }
259
260 FileReference ClientChannel::PushFileHandle(void* transaction_state,
261                                             const BorrowedHandle& handle) {
262   auto* state = static_cast<TransactionState*>(transaction_state);
263   return state->PushFileHandle(handle.Duplicate());
264 }
265
266 ChannelReference ClientChannel::PushChannelHandle(
267     void* transaction_state, const LocalChannelHandle& handle) {
268   auto* state = static_cast<TransactionState*>(transaction_state);
269   return state->PushChannelHandle(handle.Borrow());
270 }
271
272 ChannelReference ClientChannel::PushChannelHandle(
273     void* transaction_state, const BorrowedChannelHandle& handle) {
274   auto* state = static_cast<TransactionState*>(transaction_state);
275   return state->PushChannelHandle(handle.Duplicate());
276 }
277
278 bool ClientChannel::GetFileHandle(void* transaction_state, FileReference ref,
279                                   LocalHandle* handle) const {
280   auto* state = static_cast<TransactionState*>(transaction_state);
281   return state->GetLocalFileHandle(ref, handle);
282 }
283
284 bool ClientChannel::GetChannelHandle(void* transaction_state,
285                                      ChannelReference ref,
286                                      LocalChannelHandle* handle) const {
287   auto* state = static_cast<TransactionState*>(transaction_state);
288   return state->GetLocalChannelHandle(ref, handle);
289 }
290
291 }  // namespace uds
292 }  // namespace pdx
293 }  // namespace android