client_channel.cpp revision fd22b3e5ad1aae1fc3de54801f33466db3c9b3fe
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 12namespace android { 13namespace pdx { 14namespace uds { 15 16namespace { 17 18struct 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 70Status<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 86Status<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 99Status<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 135ClientChannel::ClientChannel(LocalChannelHandle channel_handle) 136 : channel_handle_{std::move(channel_handle)} { 137 channel_data_ = ChannelManager::Get().GetChannelData(channel_handle_.value()); 138} 139 140std::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 146ClientChannel::~ClientChannel() { 147 if (channel_handle_) 148 shutdown(channel_handle_.value(), SHUT_WR); 149} 150 151void* ClientChannel::AllocateTransactionState() { return new TransactionState; } 152 153void ClientChannel::FreeTransactionState(void* state) { 154 delete static_cast<TransactionState*>(state); 155} 156 157Status<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 173Status<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 205Status<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 214Status<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 234Status<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 254FileReference 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 260FileReference 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 266ChannelReference 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 272ChannelReference 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 278bool 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 284bool 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