1 #ifndef ANDROID_PDX_UDS_IPC_HELPER_H_
2 #define ANDROID_PDX_UDS_IPC_HELPER_H_
4 #include <sys/socket.h>
8 #include <pdx/rpc/serializable.h>
9 #include <pdx/rpc/serialization.h>
10 #include <pdx/status.h>
11 #include <pdx/utility.h>
17 // Test interfaces used for unit-testing payload sending/receiving over sockets.
20 virtual ssize_t Send(int socket_fd, const void* data, size_t size,
22 virtual ssize_t SendMessage(int socket_fd, const msghdr* msg, int flags) = 0;
25 virtual ~SendInterface() = default;
30 virtual ssize_t Receive(int socket_fd, void* data, size_t size,
32 virtual ssize_t ReceiveMessage(int socket_fd, msghdr* msg, int flags) = 0;
35 virtual ~RecvInterface() = default;
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,
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);
49 #define RETRY_EINTR(fnc_call) \
50 ([&]() -> decltype(fnc_call) { \
51 decltype(fnc_call) result; \
53 result = (fnc_call); \
54 } while (result == -1 && errno == EINTR); \
58 class SendPayload : public MessageWriter, public OutputResourceMapper {
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);
66 void* GetNextWriteBufferSection(size_t size) override;
67 OutputResourceMapper* GetOutputResourceMapper() override;
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;
81 SendInterface* sender_;
83 std::vector<int> file_handles_;
86 class ReceivePayload : public MessageReader, public InputResourceMapper {
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);
93 BufferSection GetNextReadBufferSection() override;
94 void ConsumeReadBufferSectionData(const void* new_start) override;
95 InputResourceMapper* GetInputResourceMapper() override;
97 // InputResourceMapper
98 bool GetFileHandle(FileReference ref, LocalHandle* handle) override;
99 bool GetChannelHandle(ChannelReference ref,
100 LocalChannelHandle* handle) override;
103 RecvInterface* receiver_;
105 std::vector<LocalHandle> file_handles_;
109 template <typename FileHandleType>
112 FileHandleType data_fd;
113 FileHandleType event_fd;
116 PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd);
119 template <typename FileHandleType>
120 class ChannelConnectionInfo {
122 FileHandleType channel_fd;
125 PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd);
128 template <typename FileHandleType>
129 class RequestHeader {
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};
141 PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len,
142 file_descriptors, channels, impulse_payload,
146 template <typename FileHandleType>
147 class ResponseHeader {
150 uint32_t recv_len{0};
151 std::vector<FileHandleType> file_descriptors;
152 std::vector<ChannelInfo<FileHandleType>> channels;
155 PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors,
159 template <typename T>
160 inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data,
161 const iovec* data_vec = nullptr,
162 size_t vec_count = 0) {
164 rpc::Serialize(data, &payload);
165 return payload.Send(socket_fd, nullptr, data_vec, vec_count);
168 template <typename FileHandleType>
169 inline Status<void> SendData(const BorrowedHandle& socket_fd,
170 const RequestHeader<FileHandleType>& request,
171 const iovec* data_vec = nullptr,
172 size_t vec_count = 0) {
174 rpc::Serialize(request, &payload);
175 return payload.Send(socket_fd, &request.cred, data_vec, vec_count);
178 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
180 Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
183 template <typename T>
184 inline 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);
192 template <typename FileHandleType>
193 inline 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);
202 Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
204 Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
205 const iovec* data, size_t count);
207 size_t CountVectorSize(const iovec* data, size_t count);
208 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
209 int opcode, uint32_t send_len, uint32_t max_recv_len,
212 Status<void> WaitForEndpoint(const std::string& endpoint_path,
217 } // namespace android
219 #endif // ANDROID_PDX_UDS_IPC_HELPER_H_