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