Home | History | Annotate | Download | only in libpdx
      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