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 { 20 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 31 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 46 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 53 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 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 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 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 140 ClientChannel::ClientChannel(LocalChannelHandle channel_handle) 141 : channel_handle_{std::move(channel_handle)} { 142 channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value()); 143 } 144 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 151 ClientChannel::~ClientChannel() { 152 if (channel_handle_) 153 shutdown(channel_handle_.value(), SHUT_WR); 154 } 155 156 void* ClientChannel::AllocateTransactionState() { return new TransactionState; } 157 158 void ClientChannel::FreeTransactionState(void* state) { 159 delete static_cast<TransactionState*>(state); 160 } 161 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 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 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 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 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 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 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 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 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 283 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 289 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 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