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   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 
     85 class 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 
    108 template <typename FileHandleType>
    109 class 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 
    118 template <typename FileHandleType>
    119 class ChannelConnectionInfo {
    120  public:
    121   FileHandleType channel_fd;
    122 
    123  private:
    124   PDX_SERIALIZABLE_MEMBERS(ChannelConnectionInfo, channel_fd);
    125 };
    126 
    127 template <typename FileHandleType>
    128 class 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 
    145 template <typename FileHandleType>
    146 class 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 
    158 template <typename T>
    159 inline 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 
    165 template <typename FileHandleType>
    166 inline 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 
    173 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
    174                       size_t size);
    175 Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
    176                             size_t count);
    177 
    178 template <typename T>
    179 inline 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 
    187 template <typename FileHandleType>
    188 inline 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 
    197 Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
    198                          size_t size);
    199 Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
    200                                const iovec* data, size_t count);
    201 
    202 size_t CountVectorSize(const iovec* data, size_t count);
    203 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
    204                  int opcode, uint32_t send_len, uint32_t max_recv_len,
    205                  bool is_impulse);
    206 
    207 Status<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