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