ipc_helper.h revision adfc42ead3921f94339372ffb561bc3e8d7f3c86
1#ifndef ANDROID_PDX_UDS_IPC_HELPER_H_ 2#define ANDROID_PDX_UDS_IPC_HELPER_H_ 3 4#include <sys/socket.h> 5#include <utility> 6#include <vector> 7 8#include <pdx/rpc/serializable.h> 9#include <pdx/rpc/serialization.h> 10#include <pdx/status.h> 11#include <pdx/utility.h> 12 13namespace android { 14namespace pdx { 15namespace uds { 16 17// Test interfaces used for unit-testing payload sending/receiving over sockets. 18class SendInterface { 19 public: 20 virtual ssize_t Send(int socket_fd, const void* data, size_t size, 21 int flags) = 0; 22 virtual ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) = 0; 23 24 protected: 25 virtual ~SendInterface() = default; 26}; 27 28class RecvInterface { 29 public: 30 virtual ssize_t Receive(int socket_fd, void* data, size_t size, 31 int flags) = 0; 32 virtual ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) = 0; 33 34 protected: 35 virtual ~RecvInterface() = default; 36}; 37 38// Helper methods that allow to send/receive data through abstract interfaces. 39// Useful for mocking out the underlying socket I/O. 40Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd, 41 const void* data, size_t size); 42Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd, 43 const msghdr* msg); 44Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd, 45 void* data, size_t size); 46Status<void> RecvMsgAll(RecvInterface* receiver, 47 const BorrowedHandle& socket_fd, msghdr* msg); 48 49#define RETRY_EINTR(fnc_call) \ 50 ([&]() -> decltype(fnc_call) { \ 51 decltype(fnc_call) result; \ 52 do { \ 53 result = (fnc_call); \ 54 } while (result == -1 && errno == EINTR); \ 55 return result; \ 56 })() 57 58class SendPayload : public MessageWriter, public OutputResourceMapper { 59 public: 60 SendPayload(SendInterface* sender = nullptr) : sender_{sender} {} 61 Status<void> Send(const BorrowedHandle& socket_fd); 62 Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred, 63 const iovec* data_vec = nullptr, size_t vec_count = 0); 64 65 // MessageWriter 66 void* GetNextWriteBufferSection(size_t size) override; 67 OutputResourceMapper* GetOutputResourceMapper() override; 68 69 // OutputResourceMapper 70 Status<FileReference> PushFileHandle(const LocalHandle& handle) override; 71 Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override; 72 Status<FileReference> PushFileHandle(const RemoteHandle& handle) override; 73 Status<ChannelReference> PushChannelHandle( 74 const LocalChannelHandle& handle) override; 75 Status<ChannelReference> PushChannelHandle( 76 const BorrowedChannelHandle& handle) override; 77 Status<ChannelReference> PushChannelHandle( 78 const RemoteChannelHandle& handle) override; 79 80 private: 81 SendInterface* sender_; 82 ByteBuffer buffer_; 83 std::vector<int> file_handles_; 84}; 85 86class ReceivePayload : public MessageReader, public InputResourceMapper { 87 public: 88 ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {} 89 Status<void> Receive(const BorrowedHandle& socket_fd); 90 Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred); 91 92 // MessageReader 93 BufferSection GetNextReadBufferSection() override; 94 void ConsumeReadBufferSectionData(const void* new_start) override; 95 InputResourceMapper* GetInputResourceMapper() override; 96 97 // InputResourceMapper 98 bool GetFileHandle(FileReference ref, LocalHandle* handle) override; 99 bool GetChannelHandle(ChannelReference ref, 100 LocalChannelHandle* handle) override; 101 102 private: 103 RecvInterface* receiver_; 104 ByteBuffer buffer_; 105 std::vector<LocalHandle> file_handles_; 106 size_t read_pos_{0}; 107}; 108 109template <typename FileHandleType> 110class ChannelInfo { 111 public: 112 FileHandleType data_fd; 113 FileHandleType event_fd; 114 115 private: 116 PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd); 117}; 118 119template <typename FileHandleType> 120class ChannelConnectionInfo { 121 public: 122 FileHandleType channel_fd; 123 124 private: 125 PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd); 126}; 127 128template <typename FileHandleType> 129class RequestHeader { 130 public: 131 int32_t op{0}; 132 ucred cred; 133 uint32_t send_len{0}; 134 uint32_t max_recv_len{0}; 135 std::vector<FileHandleType> file_descriptors; 136 std::vector<ChannelInfo<FileHandleType>> channels; 137 std::array<uint8_t, 32> impulse_payload; 138 bool is_impulse{false}; 139 140 private: 141 PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len, 142 file_descriptors, channels, impulse_payload, 143 is_impulse); 144}; 145 146template <typename FileHandleType> 147class ResponseHeader { 148 public: 149 int32_t ret_code{0}; 150 uint32_t recv_len{0}; 151 std::vector<FileHandleType> file_descriptors; 152 std::vector<ChannelInfo<FileHandleType>> channels; 153 154 private: 155 PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors, 156 channels); 157}; 158 159template <typename T> 160inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data, 161 const iovec* data_vec = nullptr, 162 size_t vec_count = 0) { 163 SendPayload payload; 164 rpc::Serialize(data, &payload); 165 return payload.Send(socket_fd, nullptr, data_vec, vec_count); 166} 167 168template <typename FileHandleType> 169inline Status<void> SendData(const BorrowedHandle& socket_fd, 170 const RequestHeader<FileHandleType>& request, 171 const iovec* data_vec = nullptr, 172 size_t vec_count = 0) { 173 SendPayload payload; 174 rpc::Serialize(request, &payload); 175 return payload.Send(socket_fd, &request.cred, data_vec, vec_count); 176} 177 178Status<void> SendData(const BorrowedHandle& socket_fd, const void* data, 179 size_t size); 180Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data, 181 size_t count); 182 183template <typename T> 184inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) { 185 ReceivePayload payload; 186 Status<void> status = payload.Receive(socket_fd); 187 if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR) 188 status.SetError(EIO); 189 return status; 190} 191 192template <typename FileHandleType> 193inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, 194 RequestHeader<FileHandleType>* request) { 195 ReceivePayload payload; 196 Status<void> status = payload.Receive(socket_fd, &request->cred); 197 if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR) 198 status.SetError(EIO); 199 return status; 200} 201 202Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data, 203 size_t size); 204Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd, 205 const iovec* data, size_t count); 206 207size_t CountVectorSize(const iovec* data, size_t count); 208void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request, 209 int opcode, uint32_t send_len, uint32_t max_recv_len, 210 bool is_impulse); 211 212Status<void> WaitForEndpoint(const std::string& endpoint_path, 213 int64_t timeout_ms); 214 215} // namespace uds 216} // namespace pdx 217} // namespace android 218 219#endif // ANDROID_PDX_UDS_IPC_HELPER_H_ 220