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