• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EnableAutoReconnect(int64_t reconnect_timeout_ms)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 
DisableAutoReconnect()17 void Client::DisableAutoReconnect() { auto_reconnect_enabled_ = false; }
18 
IsConnected() const19 bool Client::IsConnected() const { return channel_.get() != nullptr; }
20 
CheckReconnect()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 
NeedToDisconnectChannel(int error) const50 bool Client::NeedToDisconnectChannel(int error) const {
51   return error == ESHUTDOWN && auto_reconnect_enabled_;
52 }
53 
CheckDisconnect(int error)54 void Client::CheckDisconnect(int error) {
55   if (NeedToDisconnectChannel(error))
56     Close(error);
57 }
58 
Client(std::unique_ptr<ClientChannel> channel)59 Client::Client(std::unique_ptr<ClientChannel> channel)
60     : channel_{std::move(channel)} {}
61 
Client(std::unique_ptr<ClientChannelFactory> channel_factory,int64_t timeout_ms)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 
IsInitialized() const75 bool Client::IsInitialized() const {
76   return IsConnected() || (channel_factory_ && auto_reconnect_enabled_);
77 }
78 
OnConnect()79 void Client::OnConnect() {}
80 
error() const81 int Client::error() const { return error_; }
82 
SendImpulse(int opcode)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 
SendImpulse(int opcode,const void * buffer,size_t length)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 
Close(int error)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 
event_fd() const114 int Client::event_fd() const {
115   return IsConnected() ? channel_->event_fd() : -1;
116 }
117 
GetChannelHandle()118 LocalChannelHandle& Client::GetChannelHandle() {
119   return channel_->GetChannelHandle();
120 }
121 
122 ///////////////////////////// Transaction implementation //////////////////////
123 
Transaction(Client & client)124 Transaction::Transaction(Client& client) : client_{client} {}
125 
~Transaction()126 Transaction::~Transaction() {
127   if (state_allocated_ && client_.GetChannel())
128     client_.GetChannel()->FreeTransactionState(state_);
129 }
130 
EnsureStateAllocated()131 bool Transaction::EnsureStateAllocated() {
132   if (!state_allocated_ && client_.GetChannel()) {
133     state_ = client_.GetChannel()->AllocateTransactionState();
134     state_allocated_ = true;
135   }
136   return state_allocated_;
137 }
138 
SendTransaction(int opcode,Status<void> * ret,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)139 void Transaction::SendTransaction(int opcode, Status<void>* ret,
140                                   const iovec* send_vector, size_t send_count,
141                                   const iovec* receive_vector,
142                                   size_t receive_count) {
143   *ret = client_.CheckReconnect();
144   if (!*ret)
145     return;
146 
147   if (!EnsureStateAllocated()) {
148     ret->SetError(ESHUTDOWN);
149     return;
150   }
151 
152   auto status = client_.GetChannel()->SendWithInt(
153       state_, opcode, send_vector, send_count, receive_vector, receive_count);
154 
155   if (status) {
156     ret->SetValue();
157   } else {
158     ret->SetError(status.error());
159   }
160   CheckDisconnect(status);
161 }
162 
SendTransaction(int opcode,Status<int> * ret,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)163 void Transaction::SendTransaction(int opcode, Status<int>* ret,
164                                   const iovec* send_vector, size_t send_count,
165                                   const iovec* receive_vector,
166                                   size_t receive_count) {
167   auto status = client_.CheckReconnect();
168   if (!status) {
169     ret->SetError(status.error());
170     return;
171   }
172 
173   if (!EnsureStateAllocated()) {
174     ret->SetError(ESHUTDOWN);
175     return;
176   }
177 
178   *ret = client_.GetChannel()->SendWithInt(
179       state_, opcode, send_vector, send_count, receive_vector, receive_count);
180 
181   CheckDisconnect(*ret);
182 }
183 
SendTransaction(int opcode,Status<LocalHandle> * ret,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)184 void Transaction::SendTransaction(int opcode, Status<LocalHandle>* ret,
185                                   const iovec* send_vector, size_t send_count,
186                                   const iovec* receive_vector,
187                                   size_t receive_count) {
188   auto status = client_.CheckReconnect();
189   if (!status) {
190     ret->SetError(status.error());
191     return;
192   }
193 
194   if (!EnsureStateAllocated()) {
195     ret->SetError(ESHUTDOWN);
196     return;
197   }
198 
199   *ret = client_.GetChannel()->SendWithFileHandle(
200       state_, opcode, send_vector, send_count, receive_vector, receive_count);
201 
202   CheckDisconnect(*ret);
203 }
204 
SendTransaction(int opcode,Status<LocalChannelHandle> * ret,const iovec * send_vector,size_t send_count,const iovec * receive_vector,size_t receive_count)205 void Transaction::SendTransaction(int opcode, Status<LocalChannelHandle>* ret,
206                                   const iovec* send_vector, size_t send_count,
207                                   const iovec* receive_vector,
208                                   size_t receive_count) {
209   auto status = client_.CheckReconnect();
210   if (!status) {
211     ret->SetError(status.error());
212     return;
213   }
214 
215   if (!EnsureStateAllocated()) {
216     ret->SetError(ESHUTDOWN);
217     return;
218   }
219 
220   *ret = client_.GetChannel()->SendWithChannelHandle(
221       state_, opcode, send_vector, send_count, receive_vector, receive_count);
222 
223   CheckDisconnect(*ret);
224 }
225 
PushFileHandle(const LocalHandle & handle)226 Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) {
227   if (client_.CheckReconnect() && EnsureStateAllocated())
228     return client_.GetChannel()->PushFileHandle(state_, handle);
229   return ErrorStatus{ESHUTDOWN};
230 }
231 
PushFileHandle(const BorrowedHandle & handle)232 Status<FileReference> Transaction::PushFileHandle(
233     const BorrowedHandle& handle) {
234   if (client_.CheckReconnect() && EnsureStateAllocated())
235     return client_.GetChannel()->PushFileHandle(state_, handle);
236   return ErrorStatus{ESHUTDOWN};
237 }
238 
PushFileHandle(const RemoteHandle & handle)239 Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) {
240   return handle.Get();
241 }
242 
PushChannelHandle(const LocalChannelHandle & handle)243 Status<ChannelReference> Transaction::PushChannelHandle(
244     const LocalChannelHandle& handle) {
245   if (client_.CheckReconnect() && EnsureStateAllocated())
246     return client_.GetChannel()->PushChannelHandle(state_, handle);
247   return ErrorStatus{ESHUTDOWN};
248 }
249 
PushChannelHandle(const BorrowedChannelHandle & handle)250 Status<ChannelReference> Transaction::PushChannelHandle(
251     const BorrowedChannelHandle& handle) {
252   if (client_.CheckReconnect() && EnsureStateAllocated())
253     return client_.GetChannel()->PushChannelHandle(state_, handle);
254   return ErrorStatus{ESHUTDOWN};
255 }
256 
PushChannelHandle(const RemoteChannelHandle & handle)257 Status<ChannelReference> Transaction::PushChannelHandle(
258     const RemoteChannelHandle& handle) {
259   return handle.value();
260 }
261 
GetFileHandle(FileReference ref,LocalHandle * handle)262 bool Transaction::GetFileHandle(FileReference ref, LocalHandle* handle) {
263   return client_.CheckReconnect() && EnsureStateAllocated() &&
264          client_.GetChannel()->GetFileHandle(state_, ref, handle);
265 }
266 
GetChannelHandle(ChannelReference ref,LocalChannelHandle * handle)267 bool Transaction::GetChannelHandle(ChannelReference ref,
268                                    LocalChannelHandle* handle) {
269   return client_.CheckReconnect() && EnsureStateAllocated() &&
270          client_.GetChannel()->GetChannelHandle(state_, ref, handle);
271 }
272 
CheckDisconnect(int error)273 void Transaction::CheckDisconnect(int error) {
274   if (client_.NeedToDisconnectChannel(error)) {
275     if (state_allocated_) {
276       if (client_.GetChannel())
277         client_.GetChannel()->FreeTransactionState(state_);
278       state_ = nullptr;
279       state_allocated_ = false;
280     }
281     client_.Close(error);
282   }
283 }
284 
285 }  // namespace pdx
286 }  // namespace android
287