#ifndef ANDROID_PDX_UDS_IPC_HELPER_H_ #define ANDROID_PDX_UDS_IPC_HELPER_H_ #include #include #include #include #include #include #include namespace android { namespace pdx { namespace uds { // Test interfaces used for unit-testing payload sending/receiving over sockets. class SendInterface { public: virtual ssize_t Send(int socket_fd, const void* data, size_t size, int flags) = 0; virtual ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) = 0; protected: virtual ~SendInterface() = default; }; class RecvInterface { public: virtual ssize_t Receive(int socket_fd, void* data, size_t size, int flags) = 0; virtual ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) = 0; protected: virtual ~RecvInterface() = default; }; // Helper methods that allow to send/receive data through abstract interfaces. // Useful for mocking out the underlying socket I/O. Status SendAll(SendInterface* sender, const BorrowedHandle& socket_fd, const void* data, size_t size); Status SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd, const msghdr* msg); Status RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd, void* data, size_t size); Status RecvMsgAll(RecvInterface* receiver, const BorrowedHandle& socket_fd, msghdr* msg); #define RETRY_EINTR(fnc_call) \ ([&]() -> decltype(fnc_call) { \ decltype(fnc_call) result; \ do { \ result = (fnc_call); \ } while (result == -1 && errno == EINTR); \ return result; \ })() class SendPayload : public MessageWriter, public OutputResourceMapper { public: explicit SendPayload(SendInterface* sender = nullptr) : sender_{sender} {} Status Send(const BorrowedHandle& socket_fd); Status Send(const BorrowedHandle& socket_fd, const ucred* cred, const iovec* data_vec = nullptr, size_t vec_count = 0); // MessageWriter void* GetNextWriteBufferSection(size_t size) override; OutputResourceMapper* GetOutputResourceMapper() override; // OutputResourceMapper Status PushFileHandle(const LocalHandle& handle) override; Status PushFileHandle(const BorrowedHandle& handle) override; Status PushFileHandle(const RemoteHandle& handle) override; Status PushChannelHandle( const LocalChannelHandle& handle) override; Status PushChannelHandle( const BorrowedChannelHandle& handle) override; Status PushChannelHandle( const RemoteChannelHandle& handle) override; private: SendInterface* sender_; ByteBuffer buffer_; std::vector file_handles_; }; class ReceivePayload : public MessageReader, public InputResourceMapper { public: explicit ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {} Status Receive(const BorrowedHandle& socket_fd); Status Receive(const BorrowedHandle& socket_fd, ucred* cred); // MessageReader BufferSection GetNextReadBufferSection() override; void ConsumeReadBufferSectionData(const void* new_start) override; InputResourceMapper* GetInputResourceMapper() override; // InputResourceMapper bool GetFileHandle(FileReference ref, LocalHandle* handle) override; bool GetChannelHandle(ChannelReference ref, LocalChannelHandle* handle) override; private: RecvInterface* receiver_; ByteBuffer buffer_; std::vector file_handles_; size_t read_pos_{0}; }; template class ChannelInfo { public: FileHandleType data_fd; FileHandleType pollin_event_fd; FileHandleType pollhup_event_fd; private: PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, pollin_event_fd, pollhup_event_fd); }; template class ChannelConnectionInfo { public: FileHandleType channel_fd; private: PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd); }; template class RequestHeader { public: int32_t op{0}; ucred cred; uint32_t send_len{0}; uint32_t max_recv_len{0}; std::vector file_descriptors; std::vector> channels; std::array impulse_payload; bool is_impulse{false}; private: PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len, file_descriptors, channels, impulse_payload, is_impulse); }; template class ResponseHeader { public: int32_t ret_code{0}; uint32_t recv_len{0}; std::vector file_descriptors; std::vector> channels; private: PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors, channels); }; template inline Status SendData(const BorrowedHandle& socket_fd, const T& data, const iovec* data_vec = nullptr, size_t vec_count = 0) { SendPayload payload; rpc::Serialize(data, &payload); return payload.Send(socket_fd, nullptr, data_vec, vec_count); } template inline Status SendData(const BorrowedHandle& socket_fd, const RequestHeader& request, const iovec* data_vec = nullptr, size_t vec_count = 0) { SendPayload payload; rpc::Serialize(request, &payload); return payload.Send(socket_fd, &request.cred, data_vec, vec_count); } Status SendData(const BorrowedHandle& socket_fd, const void* data, size_t size); Status SendDataVector(const BorrowedHandle& socket_fd, const iovec* data, size_t count); template inline Status ReceiveData(const BorrowedHandle& socket_fd, T* data) { ReceivePayload payload; Status status = payload.Receive(socket_fd); if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR) status.SetError(EIO); return status; } template inline Status ReceiveData(const BorrowedHandle& socket_fd, RequestHeader* request) { ReceivePayload payload; Status status = payload.Receive(socket_fd, &request->cred); if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR) status.SetError(EIO); return status; } Status ReceiveData(const BorrowedHandle& socket_fd, void* data, size_t size); Status ReceiveDataVector(const BorrowedHandle& socket_fd, const iovec* data, size_t count); size_t CountVectorSize(const iovec* data, size_t count); void InitRequest(android::pdx::uds::RequestHeader* request, int opcode, uint32_t send_len, uint32_t max_recv_len, bool is_impulse); Status WaitForEndpoint(const std::string& endpoint_path, int64_t timeout_ms); } // namespace uds } // namespace pdx } // namespace android #endif // ANDROID_PDX_UDS_IPC_HELPER_H_