ipc_helper.h revision e41826ac301b9afad1cbfe59c57e27f2495be968
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
13namespace android {
14namespace pdx {
15namespace uds {
16
17// Test interfaces used for unit-testing payload sending/receiving over sockets.
18class 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
28class 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.
40Status<void> SendAll(SendInterface* sender, const BorrowedHandle& socket_fd,
41                     const void* data, size_t size);
42Status<void> SendMsgAll(SendInterface* sender, const BorrowedHandle& socket_fd,
43                        const msghdr* msg);
44Status<void> RecvAll(RecvInterface* receiver, const BorrowedHandle& socket_fd,
45                     void* data, size_t size);
46Status<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
58class 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
85class 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
108template <typename FileHandleType>
109class 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
118template <typename FileHandleType>
119class ChannelConnectionInfo {
120 public:
121  FileHandleType channel_fd;
122
123 private:
124  PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd);
125};
126
127template <typename FileHandleType>
128class 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
145template <typename FileHandleType>
146class 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
158template <typename T>
159inline 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
165template <typename FileHandleType>
166inline 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
173Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
174                      size_t size);
175Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
176                            size_t count);
177
178template <typename T>
179inline 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
187template <typename FileHandleType>
188inline 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
197Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
198                         size_t size);
199Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
200                               const iovec* data, size_t count);
201
202size_t CountVectorSize(const iovec* data, size_t count);
203void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
204                 int opcode, uint32_t send_len, uint32_t max_recv_len,
205                 bool is_impulse);
206
207Status<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