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>
ReceiveData(const BorrowedHandle & socket_fd,T * data)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>
ReceiveData(const BorrowedHandle & socket_fd,RequestHeader<FileHandleType> * request)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