blob: 3c66a40a1bfe693cb04ed87fea0fa7ea67e44fd1 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "pdx/client.h"
2
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08003#include <log/log.h>
4
5#include <pdx/trace.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08006
7namespace android {
8namespace pdx {
9
10void 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
17void Client::DisableAutoReconnect() { auto_reconnect_enabled_ = false; }
18
19bool Client::IsConnected() const { return channel_.get() != nullptr; }
20
21Status<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
50bool Client::NeedToDisconnectChannel(int error) const {
51 return error == ESHUTDOWN && auto_reconnect_enabled_;
52}
53
54void Client::CheckDisconnect(int error) {
55 if (NeedToDisconnectChannel(error))
56 Close(error);
57}
58
59Client::Client(std::unique_ptr<ClientChannel> channel)
60 : channel_{std::move(channel)} {}
61
62Client::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
75bool Client::IsInitialized() const {
76 return IsConnected() || (channel_factory_ && auto_reconnect_enabled_);
77}
78
79void Client::OnConnect() {}
80
81int Client::error() const { return error_; }
82
83Status<void> Client::SendImpulse(int opcode) {
84 PDX_TRACE_NAME("Client::SendImpulse");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080085
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
95Status<void> Client::SendImpulse(int opcode, const void* buffer,
96 size_t length) {
97 PDX_TRACE_NAME("Client::SendImpulse");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080098
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
108void Client::Close(int error) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800109 channel_.reset();
110 // Normalize error codes to negative integer space.
111 error_ = error <= 0 ? error : -error;
112}
113
114int Client::event_fd() const {
115 return IsConnected() ? channel_->event_fd() : -1;
116}
117
118LocalChannelHandle& Client::GetChannelHandle() {
119 return channel_->GetChannelHandle();
120}
121
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700122const LocalChannelHandle& Client::GetChannelHandle() const {
123 return channel_->GetChannelHandle();
124}
125
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800126///////////////////////////// Transaction implementation //////////////////////
127
128Transaction::Transaction(Client& client) : client_{client} {}
129
130Transaction::~Transaction() {
131 if (state_allocated_ && client_.GetChannel())
132 client_.GetChannel()->FreeTransactionState(state_);
133}
134
135bool Transaction::EnsureStateAllocated() {
136 if (!state_allocated_ && client_.GetChannel()) {
137 state_ = client_.GetChannel()->AllocateTransactionState();
138 state_allocated_ = true;
139 }
140 return state_allocated_;
141}
142
143void 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
167void 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
188void 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
209void 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
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700230Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) {
231 if (client_.CheckReconnect() && EnsureStateAllocated())
232 return client_.GetChannel()->PushFileHandle(state_, handle);
233 return ErrorStatus{ESHUTDOWN};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800234}
235
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700236Status<FileReference> Transaction::PushFileHandle(
237 const BorrowedHandle& handle) {
238 if (client_.CheckReconnect() && EnsureStateAllocated())
239 return client_.GetChannel()->PushFileHandle(state_, handle);
240 return ErrorStatus{ESHUTDOWN};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800241}
242
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700243Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800244 return handle.Get();
245}
246
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700247Status<ChannelReference> Transaction::PushChannelHandle(
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800248 const LocalChannelHandle& handle) {
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700249 if (client_.CheckReconnect() && EnsureStateAllocated())
250 return client_.GetChannel()->PushChannelHandle(state_, handle);
251 return ErrorStatus{ESHUTDOWN};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800252}
253
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700254Status<ChannelReference> Transaction::PushChannelHandle(
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800255 const BorrowedChannelHandle& handle) {
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700256 if (client_.CheckReconnect() && EnsureStateAllocated())
257 return client_.GetChannel()->PushChannelHandle(state_, handle);
258 return ErrorStatus{ESHUTDOWN};
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800259}
260
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700261Status<ChannelReference> Transaction::PushChannelHandle(
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800262 const RemoteChannelHandle& handle) {
263 return handle.value();
264}
265
266bool Transaction::GetFileHandle(FileReference ref, LocalHandle* handle) {
267 return client_.CheckReconnect() && EnsureStateAllocated() &&
268 client_.GetChannel()->GetFileHandle(state_, ref, handle);
269}
270
271bool Transaction::GetChannelHandle(ChannelReference ref,
272 LocalChannelHandle* handle) {
273 return client_.CheckReconnect() && EnsureStateAllocated() &&
274 client_.GetChannel()->GetChannelHandle(state_, ref, handle);
275}
276
277void 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