ipc_helper.h revision e4eec20f6263f4a42ae462456f60ea6c4518bb0a
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#define RETRY_EINTR(fnc_call)                 \
18  ([&]() -> decltype(fnc_call) {              \
19    decltype(fnc_call) result;                \
20    do {                                      \
21      result = (fnc_call);                    \
22    } while (result == -1 && errno == EINTR); \
23    return result;                            \
24  })()
25
26class SendPayload : public MessageWriter, public OutputResourceMapper {
27 public:
28  Status<void> Send(int socket_fd);
29  Status<void> Send(int socket_fd, const ucred* cred);
30
31  // MessageWriter
32  void* GetNextWriteBufferSection(size_t size) override;
33  OutputResourceMapper* GetOutputResourceMapper() override;
34
35  // OutputResourceMapper
36  FileReference PushFileHandle(const LocalHandle& handle) override;
37  FileReference PushFileHandle(const BorrowedHandle& handle) override;
38  FileReference PushFileHandle(const RemoteHandle& handle) override;
39  ChannelReference PushChannelHandle(const LocalChannelHandle& handle) override;
40  ChannelReference PushChannelHandle(
41      const BorrowedChannelHandle& handle) override;
42  ChannelReference PushChannelHandle(
43      const RemoteChannelHandle& handle) override;
44
45 private:
46  ByteBuffer buffer_;
47  std::vector<int> file_handles_;
48};
49
50class ReceivePayload : public MessageReader, public InputResourceMapper {
51 public:
52  Status<void> Receive(int socket_fd);
53  Status<void> Receive(int socket_fd, ucred* cred);
54
55  // MessageReader
56  BufferSection GetNextReadBufferSection() override;
57  void ConsumeReadBufferSectionData(const void* new_start) override;
58  InputResourceMapper* GetInputResourceMapper() override;
59
60  // InputResourceMapper
61  bool GetFileHandle(FileReference ref, LocalHandle* handle) override;
62  bool GetChannelHandle(ChannelReference ref,
63                        LocalChannelHandle* handle) override;
64
65 private:
66  ByteBuffer buffer_;
67  std::vector<LocalHandle> file_handles_;
68  size_t read_pos_{0};
69};
70
71template <typename FileHandleType>
72class ChannelInfo {
73 public:
74  FileHandleType data_fd;
75  FileHandleType event_fd;
76
77 private:
78  PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd);
79};
80
81template <typename FileHandleType>
82class RequestHeader {
83 public:
84  int32_t op{0};
85  ucred cred;
86  uint32_t send_len{0};
87  uint32_t max_recv_len{0};
88  std::vector<FileHandleType> file_descriptors;
89  std::vector<ChannelInfo<FileHandleType>> channels;
90  std::array<uint8_t, 32> impulse_payload;
91  bool is_impulse{false};
92
93 private:
94  PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len,
95                           file_descriptors, channels, impulse_payload,
96                           is_impulse);
97};
98
99template <typename FileHandleType>
100class ResponseHeader {
101 public:
102  int32_t ret_code{0};
103  uint32_t recv_len{0};
104  std::vector<FileHandleType> file_descriptors;
105  std::vector<ChannelInfo<FileHandleType>> channels;
106
107 private:
108  PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors,
109                           channels);
110};
111
112template <typename T>
113inline Status<void> SendData(int socket_fd, const T& data) {
114  SendPayload payload;
115  rpc::Serialize(data, &payload);
116  return payload.Send(socket_fd);
117}
118
119template <typename FileHandleType>
120inline Status<void> SendData(int socket_fd,
121                             const RequestHeader<FileHandleType>& request) {
122  SendPayload payload;
123  rpc::Serialize(request, &payload);
124  return payload.Send(socket_fd, &request.cred);
125}
126
127Status<void> SendData(int socket_fd, const void* data, size_t size);
128Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count);
129
130template <typename T>
131inline Status<void> ReceiveData(int socket_fd, T* data) {
132  ReceivePayload payload;
133  Status<void> status = payload.Receive(socket_fd);
134  if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR)
135    status.SetError(EIO);
136  return status;
137}
138
139template <typename FileHandleType>
140inline Status<void> ReceiveData(int socket_fd,
141                                RequestHeader<FileHandleType>* request) {
142  ReceivePayload payload;
143  Status<void> status = payload.Receive(socket_fd, &request->cred);
144  if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR)
145    status.SetError(EIO);
146  return status;
147}
148
149Status<void> ReceiveData(int socket_fd, void* data, size_t size);
150Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count);
151
152size_t CountVectorSize(const iovec* data, size_t count);
153void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
154                 int opcode, uint32_t send_len, uint32_t max_recv_len,
155                 bool is_impulse);
156
157Status<void> WaitForEndpoint(const std::string& endpoint_path,
158                             int64_t timeout_ms);
159
160}  // namespace uds
161}  // namespace pdx
162}  // namespace android
163
164#endif  // ANDROID_PDX_UDS_IPC_HELPER_H_
165