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 13 namespace android { 14 namespace pdx { 15 namespace uds { 16 17 // Test interfaces used for unit-testing payload sending/receiving over sockets. 18 class 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 28 class 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. 40 Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd, 41 const void* data, size_t size); 42 Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd, 43 const msghdr* msg); 44 Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd, 45 void* data, size_t size); 46 Status<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 58 class SendPayload : public MessageWriter, public OutputResourceMapper { 59 public: 60 explicit 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 86 class ReceivePayload : public MessageReader, public InputResourceMapper { 87 public: 88 explicit ReceivePayload(RecvInterface* receiver = nullptr) 89 : receiver_{receiver} {} 90 Status<void> Receive(const BorrowedHandle& socket_fd); 91 Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred); 92 93 // MessageReader 94 BufferSection GetNextReadBufferSection() override; 95 void ConsumeReadBufferSectionData(const void* new_start) override; 96 InputResourceMapper* GetInputResourceMapper() override; 97 98 // InputResourceMapper 99 bool GetFileHandle(FileReference ref, LocalHandle* handle) override; 100 bool GetChannelHandle(ChannelReference ref, 101 LocalChannelHandle* handle) override; 102 103 private: 104 RecvInterface* receiver_; 105 ByteBuffer buffer_; 106 std::vector<LocalHandle> file_handles_; 107 size_t read_pos_{0}; 108 }; 109 110 template <typename FileHandleType> 111 class ChannelInfo { 112 public: 113 FileHandleType data_fd; 114 FileHandleType pollin_event_fd; 115 FileHandleType pollhup_event_fd; 116 117 private: 118 PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, pollin_event_fd, 119 pollhup_event_fd); 120 }; 121 122 template <typename FileHandleType> 123 class ChannelConnectionInfo { 124 public: 125 FileHandleType channel_fd; 126 127 private: 128 PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd); 129 }; 130 131 template <typename FileHandleType> 132 class RequestHeader { 133 public: 134 int32_t op{0}; 135 ucred cred; 136 uint32_t send_len{0}; 137 uint32_t max_recv_len{0}; 138 std::vector<FileHandleType> file_descriptors; 139 std::vector<ChannelInfo<FileHandleType>> channels; 140 std::array<uint8_t, 32> impulse_payload; 141 bool is_impulse{false}; 142 143 private: 144 PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len, 145 file_descriptors, channels, impulse_payload, 146 is_impulse); 147 }; 148 149 template <typename FileHandleType> 150 class ResponseHeader { 151 public: 152 int32_t ret_code{0}; 153 uint32_t recv_len{0}; 154 std::vector<FileHandleType> file_descriptors; 155 std::vector<ChannelInfo<FileHandleType>> channels; 156 157 private: 158 PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors, 159 channels); 160 }; 161 162 template <typename T> 163 inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data, 164 const iovec* data_vec = nullptr, 165 size_t vec_count = 0) { 166 SendPayload payload; 167 rpc::Serialize(data, &payload); 168 return payload.Send(socket_fd, nullptr, data_vec, vec_count); 169 } 170 171 template <typename FileHandleType> 172 inline Status<void> SendData(const BorrowedHandle& socket_fd, 173 const RequestHeader<FileHandleType>& request, 174 const iovec* data_vec = nullptr, 175 size_t vec_count = 0) { 176 SendPayload payload; 177 rpc::Serialize(request, &payload); 178 return payload.Send(socket_fd, &request.cred, data_vec, vec_count); 179 } 180 181 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data, 182 size_t size); 183 Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data, 184 size_t count); 185 186 template <typename T> 187 inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) { 188 ReceivePayload payload; 189 Status<void> status = payload.Receive(socket_fd); 190 if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR) 191 status.SetError(EIO); 192 return status; 193 } 194 195 template <typename FileHandleType> 196 inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, 197 RequestHeader<FileHandleType>* request) { 198 ReceivePayload payload; 199 Status<void> status = payload.Receive(socket_fd, &request->cred); 200 if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR) 201 status.SetError(EIO); 202 return status; 203 } 204 205 Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data, 206 size_t size); 207 Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd, 208 const iovec* data, size_t count); 209 210 size_t CountVectorSize(const iovec* data, size_t count); 211 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request, 212 int opcode, uint32_t send_len, uint32_t max_recv_len, 213 bool is_impulse); 214 215 Status<void> WaitForEndpoint(const std::string& endpoint_path, 216 int64_t timeout_ms); 217 218 } // namespace uds 219 } // namespace pdx 220 } // namespace android 221 222 #endif // ANDROID_PDX_UDS_IPC_HELPER_H_ 223