1 #include "pdx/client.h" 2 3 #include <log/log.h> 4 5 #include <pdx/trace.h> 6 7 namespace android { 8 namespace pdx { 9 10 void Client::EnableAutoReconnect(int64_t reconnect_timeout_ms) { 11 if (channel_factory_) { 12 reconnect_timeout_ms_ = reconnect_timeout_ms; 13 auto_reconnect_enabled_ = true; 14 } 15 } 16 17 void Client::DisableAutoReconnect() { auto_reconnect_enabled_ = false; } 18 19 bool Client::IsConnected() const { return channel_.get() != nullptr; } 20 21 Status<void> Client::CheckReconnect() { 22 Status<void> ret; 23 bool was_disconnected = !IsConnected(); 24 if (auto_reconnect_enabled_ && was_disconnected && channel_factory_) { 25 auto status = channel_factory_->Connect(reconnect_timeout_ms_); 26 if (!status) { 27 error_ = -status.error(); 28 ret.SetError(status.error()); 29 return ret; 30 } 31 channel_ = status.take(); 32 } 33 34 if (!IsConnected()) { 35 ret.SetError(ESHUTDOWN); 36 } else { 37 // Call the subclass OnConnect handler. The subclass may choose to close the 38 // connection in the handler, in which case error_ will be non-zero. 39 if (was_disconnected) 40 OnConnect(); 41 if (!IsConnected()) 42 ret.SetError(-error_); 43 else 44 ret.SetValue(); 45 } 46 47 return ret; 48 } 49 50 bool Client::NeedToDisconnectChannel(int error) const { 51 return error == ESHUTDOWN && auto_reconnect_enabled_; 52 } 53 54 void Client::CheckDisconnect(int error) { 55 if (NeedToDisconnectChannel(error)) 56 Close(error); 57 } 58 59 Client::Client(std::unique_ptr<ClientChannel> channel) 60 : channel_{std::move(channel)} {} 61 62 Client::Client(std::unique_ptr<ClientChannelFactory> channel_factory, 63 int64_t timeout_ms) 64 : channel_factory_{std::move(channel_factory)} { 65 auto status = channel_factory_->Connect(timeout_ms); 66 if (!status) { 67 ALOGE("Client::Client: Failed to connect to service because: %s", 68 status.GetErrorMessage().c_str()); 69 error_ = -status.error(); 70 } else { 71 channel_ = status.take(); 72 } 73 } 74 75 bool Client::IsInitialized() const { 76 return IsConnected() || (channel_factory_ && auto_reconnect_enabled_); 77 } 78 79 void Client::OnConnect() {} 80 81 int Client::error() const { return error_; } 82 83 Status<void> Client::SendImpulse(int opcode) { 84 PDX_TRACE_NAME("Client::SendImpulse"); 85 86 auto status = CheckReconnect(); 87 if (!status) 88 return status; 89 90 status = channel_->SendImpulse(opcode, nullptr, 0); 91 CheckDisconnect(status); 92 return status; 93 } 94 95 Status<void> Client::SendImpulse(int opcode, const void* buffer, 96 size_t length) { 97 PDX_TRACE_NAME("Client::SendImpulse"); 98 99 auto status = CheckReconnect(); 100 if (!status) 101 return status; 102 103 status = channel_->SendImpulse(opcode, buffer, length); 104 CheckDisconnect(status); 105 return status; 106 } 107 108 void Client::Close(int error) { 109 channel_.reset(); 110 // Normalize error codes to negative integer space. 111 error_ = error <= 0 ? error : -error; 112 } 113 114 int Client::event_fd() const { 115 return IsConnected() ? channel_->event_fd() : -1; 116 } 117 118 LocalChannelHandle& Client::GetChannelHandle() { 119 return channel_->GetChannelHandle(); 120 } 121 122 const LocalChannelHandle& Client::GetChannelHandle() const { 123 return channel_->GetChannelHandle(); 124 } 125 126 ///////////////////////////// Transaction implementation ////////////////////// 127 128 Transaction::Transaction(Client& client) : client_{client} {} 129 130 Transaction::~Transaction() { 131 if (state_allocated_ && client_.GetChannel()) 132 client_.GetChannel()->FreeTransactionState(state_); 133 } 134 135 bool Transaction::EnsureStateAllocated() { 136 if (!state_allocated_ && client_.GetChannel()) { 137 state_ = client_.GetChannel()->AllocateTransactionState(); 138 state_allocated_ = true; 139 } 140 return state_allocated_; 141 } 142 143 void Transaction::SendTransaction(int opcode, Status<void>* ret, 144 const iovec* send_vector, size_t send_count, 145 const iovec* receive_vector, 146 size_t receive_count) { 147 *ret = client_.CheckReconnect(); 148 if (!*ret) 149 return; 150 151 if (!EnsureStateAllocated()) { 152 ret->SetError(ESHUTDOWN); 153 return; 154 } 155 156 auto status = client_.GetChannel()->SendWithInt( 157 state_, opcode, send_vector, send_count, receive_vector, receive_count); 158 159 if (status) { 160 ret->SetValue(); 161 } else { 162 ret->SetError(status.error()); 163 } 164 CheckDisconnect(status); 165 } 166 167 void Transaction::SendTransaction(int opcode, Status<int>* ret, 168 const iovec* send_vector, size_t send_count, 169 const iovec* receive_vector, 170 size_t receive_count) { 171 auto status = client_.CheckReconnect(); 172 if (!status) { 173 ret->SetError(status.error()); 174 return; 175 } 176 177 if (!EnsureStateAllocated()) { 178 ret->SetError(ESHUTDOWN); 179 return; 180 } 181 182 *ret = client_.GetChannel()->SendWithInt( 183 state_, opcode, send_vector, send_count, receive_vector, receive_count); 184 185 CheckDisconnect(*ret); 186 } 187 188 void Transaction::SendTransaction(int opcode, Status<LocalHandle>* ret, 189 const iovec* send_vector, size_t send_count, 190 const iovec* receive_vector, 191 size_t receive_count) { 192 auto status = client_.CheckReconnect(); 193 if (!status) { 194 ret->SetError(status.error()); 195 return; 196 } 197 198 if (!EnsureStateAllocated()) { 199 ret->SetError(ESHUTDOWN); 200 return; 201 } 202 203 *ret = client_.GetChannel()->SendWithFileHandle( 204 state_, opcode, send_vector, send_count, receive_vector, receive_count); 205 206 CheckDisconnect(*ret); 207 } 208 209 void Transaction::SendTransaction(int opcode, Status<LocalChannelHandle>* ret, 210 const iovec* send_vector, size_t send_count, 211 const iovec* receive_vector, 212 size_t receive_count) { 213 auto status = client_.CheckReconnect(); 214 if (!status) { 215 ret->SetError(status.error()); 216 return; 217 } 218 219 if (!EnsureStateAllocated()) { 220 ret->SetError(ESHUTDOWN); 221 return; 222 } 223 224 *ret = client_.GetChannel()->SendWithChannelHandle( 225 state_, opcode, send_vector, send_count, receive_vector, receive_count); 226 227 CheckDisconnect(*ret); 228 } 229 230 Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) { 231 if (client_.CheckReconnect() && EnsureStateAllocated()) 232 return client_.GetChannel()->PushFileHandle(state_, handle); 233 return ErrorStatus{ESHUTDOWN}; 234 } 235 236 Status<FileReference> Transaction::PushFileHandle( 237 const BorrowedHandle& handle) { 238 if (client_.CheckReconnect() && EnsureStateAllocated()) 239 return client_.GetChannel()->PushFileHandle(state_, handle); 240 return ErrorStatus{ESHUTDOWN}; 241 } 242 243 Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) { 244 return handle.Get(); 245 } 246 247 Status<ChannelReference> Transaction::PushChannelHandle( 248 const LocalChannelHandle& handle) { 249 if (client_.CheckReconnect() && EnsureStateAllocated()) 250 return client_.GetChannel()->PushChannelHandle(state_, handle); 251 return ErrorStatus{ESHUTDOWN}; 252 } 253 254 Status<ChannelReference> Transaction::PushChannelHandle( 255 const BorrowedChannelHandle& handle) { 256 if (client_.CheckReconnect() && EnsureStateAllocated()) 257 return client_.GetChannel()->PushChannelHandle(state_, handle); 258 return ErrorStatus{ESHUTDOWN}; 259 } 260 261 Status<ChannelReference> Transaction::PushChannelHandle( 262 const RemoteChannelHandle& handle) { 263 return handle.value(); 264 } 265 266 bool Transaction::GetFileHandle(FileReference ref, LocalHandle* handle) { 267 return client_.CheckReconnect() && EnsureStateAllocated() && 268 client_.GetChannel()->GetFileHandle(state_, ref, handle); 269 } 270 271 bool Transaction::GetChannelHandle(ChannelReference ref, 272 LocalChannelHandle* handle) { 273 return client_.CheckReconnect() && EnsureStateAllocated() && 274 client_.GetChannel()->GetChannelHandle(state_, ref, handle); 275 } 276 277 void Transaction::CheckDisconnect(int error) { 278 if (client_.NeedToDisconnectChannel(error)) { 279 if (state_allocated_) { 280 if (client_.GetChannel()) 281 client_.GetChannel()->FreeTransactionState(state_); 282 state_ = nullptr; 283 state_allocated_ = false; 284 } 285 client_.Close(error); 286 } 287 } 288 289 } // namespace pdx 290 } // namespace android 291