OSDN Git Service

Reduce the number of Send requests over UDS per IPC invocation
[android-x86/frameworks-native.git] / libs / vr / libpdx_uds / private / uds / ipc_helper.h
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 event_fd;
114
115  private:
116   PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd);
117 };
118
119 template <typename FileHandleType>
120 class ChannelConnectionInfo {
121  public:
122   FileHandleType channel_fd;
123
124  private:
125   PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd);
126 };
127
128 template <typename FileHandleType>
129 class RequestHeader {
130  public:
131   int32_t op{0};
132   ucred cred;
133   uint32_t send_len{0};
134   uint32_t max_recv_len{0};
135   std::vector<FileHandleType> file_descriptors;
136   std::vector<ChannelInfo<FileHandleType>> channels;
137   std::array<uint8_t, 32> impulse_payload;
138   bool is_impulse{false};
139
140  private:
141   PDX_SERIALIZABLE_MEMBERS(RequestHeader, op, send_len, max_recv_len,
142                            file_descriptors, channels, impulse_payload,
143                            is_impulse);
144 };
145
146 template <typename FileHandleType>
147 class ResponseHeader {
148  public:
149   int32_t ret_code{0};
150   uint32_t recv_len{0};
151   std::vector<FileHandleType> file_descriptors;
152   std::vector<ChannelInfo<FileHandleType>> channels;
153
154  private:
155   PDX_SERIALIZABLE_MEMBERS(ResponseHeader, ret_code, recv_len, file_descriptors,
156                            channels);
157 };
158
159 template <typename T>
160 inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data,
161                              const iovec* data_vec = nullptr,
162                              size_t vec_count = 0) {
163   SendPayload payload;
164   rpc::Serialize(data, &payload);
165   return payload.Send(socket_fd, nullptr, data_vec, vec_count);
166 }
167
168 template <typename FileHandleType>
169 inline Status<void> SendData(const BorrowedHandle& socket_fd,
170                              const RequestHeader<FileHandleType>& request,
171                              const iovec* data_vec = nullptr,
172                              size_t vec_count = 0) {
173   SendPayload payload;
174   rpc::Serialize(request, &payload);
175   return payload.Send(socket_fd, &request.cred, data_vec, vec_count);
176 }
177
178 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
179                       size_t size);
180 Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
181                             size_t count);
182
183 template <typename T>
184 inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) {
185   ReceivePayload payload;
186   Status<void> status = payload.Receive(socket_fd);
187   if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR)
188     status.SetError(EIO);
189   return status;
190 }
191
192 template <typename FileHandleType>
193 inline Status<void> ReceiveData(const BorrowedHandle& socket_fd,
194                                 RequestHeader<FileHandleType>* request) {
195   ReceivePayload payload;
196   Status<void> status = payload.Receive(socket_fd, &request->cred);
197   if (status && rpc::Deserialize(request, &payload) != rpc::ErrorCode::NO_ERROR)
198     status.SetError(EIO);
199   return status;
200 }
201
202 Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
203                          size_t size);
204 Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
205                                const iovec* data, size_t count);
206
207 size_t CountVectorSize(const iovec* data, size_t count);
208 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
209                  int opcode, uint32_t send_len, uint32_t max_recv_len,
210                  bool is_impulse);
211
212 Status<void> WaitForEndpoint(const std::string& endpoint_path,
213                              int64_t timeout_ms);
214
215 }  // namespace uds
216 }  // namespace pdx
217 }  // namespace android
218
219 #endif  // ANDROID_PDX_UDS_IPC_HELPER_H_