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