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