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 {
GetLocalFileHandleandroid::pdx::uds::__anon57504a190111::TransactionState19 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
GetLocalChannelHandleandroid::pdx::uds::__anon57504a190111::TransactionState30 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
PushFileHandleandroid::pdx::uds::__anon57504a190111::TransactionState43 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
PushChannelHandleandroid::pdx::uds::__anon57504a190111::TransactionState50 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
ReadAndDiscardData(const BorrowedHandle & socket_fd,size_t size)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
SendRequest(const BorrowedHandle & socket_fd,TransactionState * transaction_state,int opcode,const iovec * send_vector,size_t send_count,size_t max_recv_len)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
ReceiveResponse(const BorrowedHandle & socket_fd,TransactionState * transaction_state,const iovec * receive_vector,size_t receive_count,size_t max_recv_len)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
ClientChannel(LocalChannelHandle channel_handle)135 ClientChannel::ClientChannel(LocalChannelHandle channel_handle)
136 : channel_handle_{std::move(channel_handle)} {
137 channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value());
138 }
139
Create(LocalChannelHandle channel_handle)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
~ClientChannel()146 ClientChannel::~ClientChannel() {
147 if (channel_handle_)
148 shutdown(channel_handle_.value(), SHUT_WR);
149 }
150
AllocateTransactionState()151 void* ClientChannel::AllocateTransactionState() { return new TransactionState; }
152
FreeTransactionState(void * state)153 void ClientChannel::FreeTransactionState(void* state) {
154 delete static_cast<TransactionState*>(state);
155 }
156
SendImpulse(int opcode,const void * buffer,size_t length)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
SendAndReceive(void * transaction_state,int opcode,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)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
SendWithInt(void * transaction_state,int opcode,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)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
SendWithFileHandle(void * transaction_state,int opcode,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)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
SendWithChannelHandle(void * transaction_state,int opcode,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)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
PushFileHandle(void * transaction_state,const LocalHandle & handle)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
PushFileHandle(void * transaction_state,const BorrowedHandle & handle)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
PushChannelHandle(void * transaction_state,const LocalChannelHandle & handle)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
PushChannelHandle(void * transaction_state,const BorrowedChannelHandle & handle)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
GetFileHandle(void * transaction_state,FileReference ref,LocalHandle * handle) const278 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
GetChannelHandle(void * transaction_state,ChannelReference ref,LocalChannelHandle * handle) const284 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
294