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 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
64 // MessageWriter
65 void* GetNextWriteBufferSection(size_t size) override;
66 OutputResourceMapper* GetOutputResourceMapper() override;
67
68 // OutputResourceMapper
69 Status<FileReference> PushFileHandle(const LocalHandle& handle) override;
70 Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override;
71 Status<FileReference> PushFileHandle(const RemoteHandle& handle) override;
72 Status<ChannelReference> PushChannelHandle(
73 const LocalChannelHandle& handle) override;
74 Status<ChannelReference> PushChannelHandle(
75 const BorrowedChannelHandle& handle) override;
76 Status<ChannelReference> PushChannelHandle(
77 const RemoteChannelHandle& handle) override;
78
79 private:
80 SendInterface* sender_;
81 ByteBuffer buffer_;
82 std::vector<int> file_handles_;
83 };
84
85 class ReceivePayload : public MessageReader, public InputResourceMapper {
86 public:
87 ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {}
88 Status<void> Receive(const BorrowedHandle& socket_fd);
89 Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
90
91 // MessageReader
92 BufferSection GetNextReadBufferSection() override;
93 void ConsumeReadBufferSectionData(const void* new_start) override;
94 InputResourceMapper* GetInputResourceMapper() override;
95
96 // InputResourceMapper
97 bool GetFileHandle(FileReference ref, LocalHandle* handle) override;
98 bool GetChannelHandle(ChannelReference ref,
99 LocalChannelHandle* handle) override;
100
101 private:
102 RecvInterface* receiver_;
103 ByteBuffer buffer_;
104 std::vector<LocalHandle> file_handles_;
105 size_t read_pos_{0};
106 };
107
108 template <typename FileHandleType>
109 class ChannelInfo {
110 public:
111 FileHandleType data_fd;
112 FileHandleType event_fd;
113
114 private:
115 PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd);
116 };
117
118 template <typename FileHandleType>
119 class ChannelConnectionInfo {
120 public:
121 FileHandleType channel_fd;
122
123 private:
124 PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd);
125 };
126
127 template <typename FileHandleType>
128 class RequestHeader {
129 public:
130 int32_t op{0};
131 ucred cred;
132 uint32_t send_len{0};
133 uint32_t max_recv_len{0};
134 std::vector<FileHandleType> file_descriptors;
135 std::vector<ChannelInfo<FileHandleType>> channels;
136 std::array<uint8_t, 32> impulse_payload;
137 bool is_impulse{false};
138
139 private:
140 PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len,
141 file_descriptors, channels, impulse_payload,
142 is_impulse);
143 };
144
145 template <typename FileHandleType>
146 class ResponseHeader {
147 public:
148 int32_t ret_code{0};
149 uint32_t recv_len{0};
150 std::vector<FileHandleType> file_descriptors;
151 std::vector<ChannelInfo<FileHandleType>> channels;
152
153 private:
154 PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors,
155 channels);
156 };
157
158 template <typename T>
SendData(const BorrowedHandle & socket_fd,const T & data)159 inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
160 SendPayload payload;
161 rpc::Serialize(data, &payload);
162 return payload.Send(socket_fd);
163 }
164
165 template <typename FileHandleType>
SendData(const BorrowedHandle & socket_fd,const RequestHeader<FileHandleType> & request)166 inline Status<void> SendData(const BorrowedHandle& socket_fd,
167 const RequestHeader<FileHandleType>& request) {
168 SendPayload payload;
169 rpc::Serialize(request, &payload);
170 return payload.Send(socket_fd, &request.cred);
171 }
172
173 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
174 size_t size);
175 Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
176 size_t count);
177
178 template <typename T>
ReceiveData(const BorrowedHandle & socket_fd,T * data)179 inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) {
180 ReceivePayload payload;
181 Status<void> status = payload.Receive(socket_fd);
182 if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR)
183 status.SetError(EIO);
184 return status;
185 }
186
187 template <typename FileHandleType>
ReceiveData(const BorrowedHandle & socket_fd,RequestHeader<FileHandleType> * request)188 inline Status<void> ReceiveData(const BorrowedHandle& socket_fd,
189 RequestHeader<FileHandleType>* request) {
190 ReceivePayload payload;
191 Status<void> status = payload.Receive(socket_fd, &request->cred);
192 if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR)
193 status.SetError(EIO);
194 return status;
195 }
196
197 Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
198 size_t size);
199 Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
200 const iovec* data, size_t count);
201
202 size_t CountVectorSize(const iovec* data, size_t count);
203 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
204 int opcode, uint32_t send_len, uint32_t max_recv_len,
205 bool is_impulse);
206
207 Status<void> WaitForEndpoint(const std::string& endpoint_path,
208 int64_t timeout_ms);
209
210 } // namespace uds
211 } // namespace pdx
212 } // namespace android
213
214 #endif // ANDROID_PDX_UDS_IPC_HELPER_H_
215