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