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