1 #ifndef ANDROID_PDX_CLIENT_H_ 2 #define ANDROID_PDX_CLIENT_H_ 3 4 #include <errno.h> 5 #include <sys/types.h> 6 7 #include <memory> 8 #include <string> 9 #include <type_traits> 10 11 #include <pdx/channel_handle.h> 12 #include <pdx/client_channel.h> 13 #include <pdx/client_channel_factory.h> 14 #include <pdx/file_handle.h> 15 #include <pdx/message_reader.h> 16 #include <pdx/message_writer.h> 17 #include <pdx/rpc/remote_method_type.h> 18 #include <pdx/status.h> 19 20 namespace android { 21 namespace pdx { 22 23 class Transaction; 24 25 /* 26 * Base class of client-side service API classes. 27 */ 28 class Client { 29 public: 30 static const int64_t kInfiniteTimeout = -1; 31 32 virtual ~Client() = default; 33 34 /* 35 * Returns true if the Client instance successfully initialized, false 36 * otherwise. Subclasses that can fail to initialize must override this and 37 * AND their initialization result with this base class method's result. 38 * 39 * This method is not intended to perform initialization, only to report 40 * the status of the initialization. 41 */ 42 virtual bool IsInitialized() const; 43 44 /* 45 * Returns the error code describing the Client initialization failure, or 0 46 * if there was no failure. 47 */ 48 int error() const; 49 50 // Returns a reference to IPC channel handle. 51 LocalChannelHandle& GetChannelHandle(); 52 53 protected: 54 friend Transaction; 55 explicit Client(std::unique_ptr<ClientChannel> channel); 56 explicit Client(std::unique_ptr<ClientChannelFactory> channel_factory, 57 int64_t timeout_ms = kInfiniteTimeout); 58 59 /* 60 * Called by Client::Connect() after successfully connecting to the service 61 * endpoint. Subclasses may override this method to perform additional setup, 62 * including sending messages to complete the connection process. 63 * 64 * Subclasses may call Client::Close() within this method to terminate the 65 * connection; Client::Connect() returns the negated error passed to 66 * Client::Close() when this happens. 67 */ 68 virtual void OnConnect(); 69 70 enum : size_t { MAX_IMPULSE_LENGTH = sizeof(uint64_t) * 4 }; 71 72 Status<void> SendImpulse(int opcode); 73 Status<void> SendImpulse(int opcode, const void* buffer, size_t length); 74 75 /* 76 * Remote method call API using pdx::rpc serialization. 77 * Include pdx/rpc/remote_method.h to use these methods. 78 */ 79 template <typename RemoteMethodType, typename... Args> 80 Status<typename RemoteMethodType::Return> InvokeRemoteMethod(Args&&... args); 81 82 template <typename RemoteMethodType, typename ReturnType, typename... Args> 83 Status<void> InvokeRemoteMethodInPlace(ReturnType* return_value, 84 Args&&... args); 85 86 /* 87 * Close the endpoint file descriptor and optionally indicate an error, which 88 * may be retrieved through error(). Subclasses may use this in their 89 * constructor to signal failure during initialization or at other times 90 * during operation. 91 */ 92 void Close(int error); 93 94 /* 95 * Returns true if the client is connected to the service, false otherwise. 96 */ 97 bool IsConnected() const; 98 99 /* 100 * Enables auto-reconnect with the given timeout. Use kInfiniteTimeout (-1) 101 * for no timeout. Auto-reconnect can only be enabled if the Client class 102 * was constructed with a ClientChannelFactory. 103 */ 104 void EnableAutoReconnect(int64_t reconnect_timeout_ms); 105 106 /* 107 * Disables auto-reconnect. 108 */ 109 void DisableAutoReconnect(); 110 111 /* 112 * Returns an fd that the client may use to check/wait for asynchronous 113 * notifications to the channel. It is implementation dependent how the 114 * transport backend handles this feature, however all implementations must 115 * support at least POLLIN/EPOLLIN/readable. 116 * 117 * For uses that require more than one type of event, use 118 * ClientChannel::GetEventMask() to distinguish between events. 119 */ 120 int event_fd() const; 121 122 /* 123 * Returns the underlying ClientChannel object. 124 */ GetChannel()125 ClientChannel* GetChannel() const { return channel_.get(); } TakeChannel()126 std::unique_ptr<ClientChannel>&& TakeChannel() { return std::move(channel_); } 127 128 private: 129 Client(const Client&) = delete; 130 void operator=(const Client&) = delete; 131 132 Status<void> CheckReconnect(); 133 bool NeedToDisconnectChannel(int error) const; 134 void CheckDisconnect(int error); 135 136 template <typename T> CheckDisconnect(const Status<T> & status)137 inline void CheckDisconnect(const Status<T>& status) { 138 if (!status) 139 CheckDisconnect(status.error()); 140 } 141 142 std::unique_ptr<ClientChannel> channel_; 143 int error_{0}; 144 145 // Reconnection state. 146 std::unique_ptr<ClientChannelFactory> channel_factory_; 147 int64_t reconnect_timeout_ms_{0}; 148 bool auto_reconnect_enabled_{false}; 149 }; 150 151 /* 152 * Utility template base class for client-side service API classes. Handles 153 * initialization checks during allocation and automatically cleans up on 154 * failure. 155 * 156 * @tparam T Type of the class extending this one. 157 * @tparam C Client class to wrap. Defaults to the Client class. 158 */ 159 template <typename T, typename ParentClient = Client> 160 class ClientBase : public ParentClient { 161 public: 162 // Type of the client this class wraps. 163 using ClientType = ParentClient; 164 165 static_assert(std::is_base_of<Client, ParentClient>::value, 166 "The provided parent client is not a Client subclass."); 167 168 /* 169 * Allocates a new instance of the superclass and checks for successful 170 * initialization. 171 * 172 * The variadic arguments must expand to match one of type T's constructors 173 * and are passed through unchanged. If a timeout is desired, subclasses are 174 * responsible for passing this through to the appropriate ClientBase 175 * constructor. 176 * 177 * Returns a unique_ptr to the new instance on success, or an empty unique_ptr 178 * otherwise. 179 */ 180 template <typename... Args> Create(Args &&...args)181 static inline std::unique_ptr<T> Create(Args&&... args) { 182 std::unique_ptr<T> client(new T(std::forward<Args>(args)...)); 183 if (client->IsInitialized()) 184 return client; 185 else 186 return nullptr; 187 } 188 189 protected: 190 /* 191 * Type of the base class. Useful for referencing the base class type and 192 * constructor in subclasses. Subclasses with non-public constructors 193 * must declare BASE a friend. 194 */ 195 using BASE = ClientBase<T, ParentClient>; 196 197 /* 198 * Type of the unique_ptr deleter. Useful for friend declarations. 199 */ 200 using deleter_type = typename std::unique_ptr<T>::deleter_type; 201 202 using ParentClient::ParentClient; 203 }; 204 205 class Transaction final : public OutputResourceMapper, 206 public InputResourceMapper { 207 public: 208 Transaction(Client& client); 209 ~Transaction(); 210 211 template <typename T> Send(int opcode)212 Status<T> Send(int opcode) { 213 return SendVector<T>(opcode, nullptr, 0, nullptr, 0); 214 } 215 216 template <typename T> Send(int opcode,const void * send_buffer,size_t send_length,void * receive_buffer,size_t receive_length)217 Status<T> Send(int opcode, const void* send_buffer, size_t send_length, 218 void* receive_buffer, size_t receive_length) { 219 const bool send = (send_buffer && send_length); 220 const bool receive = (receive_buffer && receive_length); 221 const iovec send_vector = {const_cast<void*>(send_buffer), send_length}; 222 const iovec receive_vector = {receive_buffer, receive_length}; 223 return SendVector<T>(opcode, send ? &send_vector : nullptr, send ? 1 : 0, 224 receive ? &receive_vector : nullptr, receive ? 1 : 0); 225 } 226 227 template <typename T> SendVector(int opcode,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)228 Status<T> SendVector(int opcode, const iovec* send_vector, size_t send_count, 229 const iovec* receive_vector, size_t receive_count) { 230 Status<T> ret; 231 SendTransaction(opcode, &ret, send_vector, send_count, receive_vector, 232 receive_count); 233 return ret; 234 } 235 236 template <typename T, size_t send_count, size_t receive_count> SendVector(int opcode,const iovec (& send_vector)[send_count],const iovec (& receive_vector)[receive_count])237 Status<T> SendVector(int opcode, const iovec (&send_vector)[send_count], 238 const iovec (&receive_vector)[receive_count]) { 239 return SendVector<T>(opcode, send_vector, send_count, receive_vector, 240 receive_count); 241 } 242 243 template <typename T, size_t send_count> SendVector(int opcode,const iovec (& send_vector)[send_count],std::nullptr_t)244 Status<T> SendVector(int opcode, const iovec (&send_vector)[send_count], 245 std::nullptr_t) { 246 return SendVector<T>(opcode, send_vector, send_count, nullptr, 0); 247 } 248 249 template <typename T, size_t receive_count> SendVector(int opcode,std::nullptr_t,const iovec (& receive_vector)[receive_count])250 Status<T> SendVector(int opcode, std::nullptr_t, 251 const iovec (&receive_vector)[receive_count]) { 252 return SendVector<T>(opcode, nullptr, 0, receive_vector, receive_count); 253 } 254 255 // OutputResourceMapper 256 Status<FileReference> PushFileHandle(const LocalHandle& handle) override; 257 Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override; 258 Status<FileReference> PushFileHandle(const RemoteHandle& handle) override; 259 Status<ChannelReference> PushChannelHandle( 260 const LocalChannelHandle& handle) override; 261 Status<ChannelReference> PushChannelHandle( 262 const BorrowedChannelHandle& handle) override; 263 Status<ChannelReference> PushChannelHandle( 264 const RemoteChannelHandle& handle) override; 265 266 // InputResourceMapper 267 bool GetFileHandle(FileReference ref, LocalHandle* handle) override; 268 bool GetChannelHandle(ChannelReference ref, 269 LocalChannelHandle* handle) override; 270 271 private: 272 bool EnsureStateAllocated(); 273 void SendTransaction(int opcode, Status<void>* ret, const iovec* send_vector, 274 size_t send_count, const iovec* receive_vector, 275 size_t receive_count); 276 void SendTransaction(int opcode, Status<int>* ret, const iovec* send_vector, 277 size_t send_count, const iovec* receive_vector, 278 size_t receive_count); 279 void SendTransaction(int opcode, Status<LocalHandle>* ret, 280 const iovec* send_vector, size_t send_count, 281 const iovec* receive_vector, size_t receive_count); 282 void SendTransaction(int opcode, Status<LocalChannelHandle>* ret, 283 const iovec* send_vector, size_t send_count, 284 const iovec* receive_vector, size_t receive_count); 285 void CheckDisconnect(int error); 286 287 template <typename T> CheckDisconnect(const Status<T> & status)288 inline void CheckDisconnect(const Status<T>& status) { 289 if (!status) 290 CheckDisconnect(status.error()); 291 } 292 293 Client& client_; 294 void* state_{nullptr}; 295 bool state_allocated_{false}; 296 }; 297 298 } // namespace pdx 299 } // namespace android 300 301 #endif // ANDROID_PDX_CLIENT_H_ 302