1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define LOG_TAG "ServiceFramework"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "pdx/service.h"
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <fcntl.h>
54fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko#include <log/log.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <utils/misc.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <algorithm>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cstdint>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/trace.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define TRACE 0
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::shared_ptr<Channel> Channel::GetFromMessageInfo(const MessageInfo& info) {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return info.channel ? info.channel->shared_from_this()
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      : std::shared_ptr<Channel>();
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessage::Message() : replied_(true) {}
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessage::Message(const MessageInfo& info)
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : service_{Service::GetFromMessageInfo(info)},
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      channel_{Channel::GetFromMessageInfo(info)},
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      info_{info},
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      replied_{IsImpulse()} {
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (svc)
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    state_ = svc->endpoint()->AllocateMessageState();
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// C++11 specifies the move semantics for shared_ptr but not weak_ptr. This
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// means we have to manually implement the desired move semantics for Message.
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessage::Message(Message&& other) { *this = std::move(other); }
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessage& Message::operator=(Message&& other) {
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Destroy();
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto base = reinterpret_cast<std::uint8_t*>(&info_);
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::fill(&base[0], &base[sizeof(info_)], 0);
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  replied_ = true;
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::swap(service_, other.service_);
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::swap(channel_, other.channel_);
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::swap(info_, other.info_);
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::swap(state_, other.state_);
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::swap(replied_, other.replied_);
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return *this;
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessage::~Message() { Destroy(); }
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid Message::Destroy() {
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (svc) {
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!replied_) {
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGE(
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          "ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d "
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          "cid=%d\n",
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          svc->name_.c_str(), info_.op, info_.pid, info_.cid);
62f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      svc->DefaultHandleMessage(*this);
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    svc->endpoint()->FreeMessageState(state_);
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  state_ = nullptr;
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  service_.reset();
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_.reset();
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst std::uint8_t* Message::ImpulseBegin() const {
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return reinterpret_cast<const std::uint8_t*>(info_.impulse);
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst std::uint8_t* Message::ImpulseEnd() const {
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
79f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<size_t> Message::ReadVector(const struct iovec* vector,
80f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                   size_t vector_length) {
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ReadVector");
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
83f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->ReadMessageData(this, vector, vector_length);
84f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  } else {
85f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
86f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  }
87f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko}
88f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko
89f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::ReadVectorAll(const struct iovec* vector,
90f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                    size_t vector_length) {
91f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  PDX_TRACE_NAME("Message::ReadVectorAll");
92f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (auto svc = service_.lock()) {
93f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto status =
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        svc->endpoint()->ReadMessageData(this, vector, vector_length);
95f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (!status)
96f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return status.error_status();
97f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    size_t size_to_read = 0;
98f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    for (size_t i = 0; i < vector_length; i++)
99f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      size_to_read += vector[i].iov_len;
100f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (status.get() < size_to_read)
101f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return ErrorStatus{EIO};
102f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return {};
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
104f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
108f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<size_t> Message::Read(void* buffer, size_t length) {
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::Read");
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const struct iovec vector = {buffer, length};
112f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->ReadMessageData(this, &vector, 1);
113f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  } else {
114f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
115f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  }
116f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko}
117f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko
118f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<size_t> Message::WriteVector(const struct iovec* vector,
119f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                    size_t vector_length) {
120f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  PDX_TRACE_NAME("Message::WriteVector");
121f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (auto svc = service_.lock()) {
122f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->WriteMessageData(this, vector, vector_length);
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
124f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
128f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::WriteVectorAll(const struct iovec* vector,
129f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                     size_t vector_length) {
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::WriteVector");
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
132f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto status =
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        svc->endpoint()->WriteMessageData(this, vector, vector_length);
134f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (!status)
135f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return status.error_status();
136f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    size_t size_to_write = 0;
137f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    for (size_t i = 0; i < vector_length; i++)
138f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      size_to_write += vector[i].iov_len;
139f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (status.get() < size_to_write)
140f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return ErrorStatus{EIO};
141f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return {};
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
143f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
147f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<size_t> Message::Write(const void* buffer, size_t length) {
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::Write");
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const struct iovec vector = {const_cast<void*>(buffer), length};
151f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->WriteMessageData(this, &vector, 1);
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
153f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
157f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> Message::PushFileHandle(const LocalHandle& handle) {
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushFileHandle");
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
160f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->PushFileHandle(this, handle);
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
162f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
166f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) {
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushFileHandle");
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
169f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->PushFileHandle(this, handle);
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
171f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
175f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> Message::PushFileHandle(const RemoteHandle& handle) {
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushFileHandle");
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
178f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->PushFileHandle(this, handle);
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
180f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
184f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> Message::PushChannelHandle(
185f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const LocalChannelHandle& handle) {
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushChannelHandle");
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
188f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->PushChannelHandle(this, handle);
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
190f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
194f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> Message::PushChannelHandle(
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const BorrowedChannelHandle& handle) {
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushChannelHandle");
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
198f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->PushChannelHandle(this, handle);
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
200f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
204f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> Message::PushChannelHandle(
205f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const RemoteChannelHandle& handle) {
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushChannelHandle");
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
208f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->PushChannelHandle(this, handle);
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
210f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool Message::GetFileHandle(FileReference ref, LocalHandle* handle) {
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::GetFileHandle");
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!svc)
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return false;
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ref >= 0) {
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = svc->endpoint()->GetFileHandle(this, ref);
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle->IsValid())
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = LocalHandle{ref};
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return true;
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool Message::GetChannelHandle(ChannelReference ref,
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                               LocalChannelHandle* handle) {
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::GetChannelHandle");
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!svc)
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return false;
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ref >= 0) {
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = svc->endpoint()->GetChannelHandle(this, ref);
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!handle->valid())
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return false;
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = LocalChannelHandle{nullptr, ref};
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return true;
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
247f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(int return_code) {
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::Reply");
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
251f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto ret = svc->endpoint()->MessageReply(this, return_code);
252f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
253f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
255f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
259f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::ReplyFileDescriptor(unsigned int fd) {
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ReplyFileDescriptor");
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
263f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto ret = svc->endpoint()->MessageReplyFd(this, fd);
264f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
265f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
267f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
271f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::ReplyError(unsigned int error) {
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ReplyError");
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
275f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto ret =
276f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        svc->endpoint()->MessageReply(this, -static_cast<int>(error));
277f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
278f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
280f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
284f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(const LocalHandle& handle) {
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ReplyFileHandle");
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
288f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Status<void> ret;
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (handle)
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = svc->endpoint()->MessageReply(this, handle.Get());
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
295f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
296f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
298f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
302f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(const BorrowedHandle& handle) {
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ReplyFileHandle");
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
306f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Status<void> ret;
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (handle)
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = svc->endpoint()->MessageReply(this, handle.Get());
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
313f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
314f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
316f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
320f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(const RemoteHandle& handle) {
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ReplyFileHandle");
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
324f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    Status<void> ret;
325f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko
326f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (handle)
327f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      ret = svc->endpoint()->MessageReply(this, handle.Get());
328f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    else
329f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      ret = svc->endpoint()->MessageReply(this, handle.Get());
330f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko
331f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
332f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
334f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
338f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(const LocalChannelHandle& handle) {
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
341f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
342f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
343f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
345f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
349f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(const BorrowedChannelHandle& handle) {
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
352f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
353f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
354f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
356f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
360f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::Reply(const RemoteChannelHandle& handle) {
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto svc = service_.lock();
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!replied_ && svc) {
363f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
364f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    replied_ = ret.ok();
365f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ret;
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
367f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
371f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) {
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::ModifyChannelEvents");
373e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
374f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask,
375f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                                set_mask);
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
377f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{ESHUTDOWN};
378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<RemoteChannelHandle> Message::PushChannel(
382e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int flags, const std::shared_ptr<Channel>& channel, int* channel_id) {
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushChannel");
384e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
385e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return svc->PushChannel(this, flags, channel, channel_id);
386e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
387e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(ESHUTDOWN);
388e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
389e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
391e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<RemoteChannelHandle> Message::PushChannel(
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Service* service, int flags, const std::shared_ptr<Channel>& channel,
393e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int* channel_id) {
394e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::PushChannel");
395e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return service->PushChannel(this, flags, channel, channel_id);
396e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
397e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> Message::CheckChannel(ChannelReference ref,
399e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  std::shared_ptr<Channel>* channel) const {
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::CheckChannel");
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock()) {
402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return svc->CheckChannel(this, ref, channel);
403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(ESHUTDOWN);
405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
407e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
408e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> Message::CheckChannel(const Service* service, ChannelReference ref,
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  std::shared_ptr<Channel>* channel) const {
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Message::CheckChannel");
411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return service->CheckChannel(this, ref, channel);
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkopid_t Message::GetProcessId() const { return info_.pid; }
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkopid_t Message::GetThreadId() const { return info_.tid; }
417e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
418e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkouid_t Message::GetEffectiveUserId() const { return info_.euid; }
419e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
420e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkogid_t Message::GetEffectiveGroupId() const { return info_.egid; }
421e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
422e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Message::GetChannelId() const { return info_.cid; }
423e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
424e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Message::GetMessageId() const { return info_.mid; }
425e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
426e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Message::GetOp() const { return info_.op; }
427e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
428e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Message::GetFlags() const { return info_.flags; }
429e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
430e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkosize_t Message::GetSendLength() const { return info_.send_len; }
431e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
432e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkosize_t Message::GetReceiveLength() const { return info_.recv_len; }
433e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
434e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkosize_t Message::GetFileDescriptorCount() const { return info_.fd_count; }
435e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
436e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }
437e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
438f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) {
439e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channel_ = chan;
440f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<void> status;
441e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto svc = service_.lock())
442f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    status = svc->SetChannel(info_.cid, chan);
443f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return status;
444e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
445e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
446e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::shared_ptr<Service> Message::GetService() const { return service_.lock(); }
447e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
448e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst MessageInfo& Message::GetInfo() const { return info_; }
449e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
450e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoService::Service(const std::string& name, std::unique_ptr<Endpoint> endpoint)
451e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : name_(name), endpoint_{std::move(endpoint)} {
452e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!endpoint_)
453e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
454e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
455f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  const auto status = endpoint_->SetService(this);
456f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  ALOGE_IF(!status, "Failed to set service context because: %s",
457f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko           status.GetErrorMessage().c_str());
458e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
459e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
460e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoService::~Service() {
461e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (endpoint_) {
462f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const auto status = endpoint_->SetService(nullptr);
463f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    ALOGE_IF(!status, "Failed to clear service context because: %s",
464f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko             status.GetErrorMessage().c_str());
465e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
466e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
467e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
468e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::shared_ptr<Service> Service::GetFromMessageInfo(const MessageInfo& info) {
469e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return info.service ? info.service->shared_from_this()
470e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      : std::shared_ptr<Service>();
471e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
472e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
473e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool Service::IsInitialized() const { return endpoint_.get() != nullptr; }
474e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
475e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) {
476e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return nullptr;
477e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
478e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
479e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid Service::OnChannelClose(Message& /*message*/,
480e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             const std::shared_ptr<Channel>& /*channel*/) {}
481e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
482f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::SetChannel(int channel_id,
483f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                 const std::shared_ptr<Channel>& channel) {
484e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Service::SetChannel");
485e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channels_mutex_);
486e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
487f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  const auto status = endpoint_->SetChannel(channel_id, channel.get());
488f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (!status) {
489e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(),
490f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          status.GetErrorMessage().c_str());
491e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
492e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // It's possible someone mucked with things behind our back by calling the C
493e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // API directly. Since we know the channel id isn't valid, make sure we
494e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // don't have it in the channels map.
495f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (status.error() == ENOENT)
496f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      channels_.erase(channel_id);
497f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  } else {
498f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    if (channel != nullptr)
499f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      channels_[channel_id] = channel;
500f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    else
501e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      channels_.erase(channel_id);
502e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
503f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return status;
504e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
505e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
506e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::shared_ptr<Channel> Service::GetChannel(int channel_id) const {
507e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Service::GetChannel");
508e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channels_mutex_);
509e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
510e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto search = channels_.find(channel_id);
511e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (search != channels_.end())
512e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return search->second;
513e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  else
514e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return nullptr;
515e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
516e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
517f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::CloseChannel(int channel_id) {
518e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Service::CloseChannel");
519e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channels_mutex_);
520e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
521f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  const auto status = endpoint_->CloseChannel(channel_id);
522e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
523e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Always erase the map entry, in case someone mucked with things behind our
524e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // back using the C API directly.
525e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  channels_.erase(channel_id);
526e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
527f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return status;
528e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
529e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
530f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::ModifyChannelEvents(int channel_id, int clear_mask,
531f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                                          int set_mask) {
532e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Service::ModifyChannelEvents");
533e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask);
534e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
535e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
536e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<RemoteChannelHandle> Service::PushChannel(
537e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Message* message, int flags, const std::shared_ptr<Channel>& channel,
538e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int* channel_id) {
539e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Service::PushChannel");
540e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
541e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channels_mutex_);
542e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
543e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id_temp = -1;
544e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<RemoteChannelHandle> ret =
545e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      endpoint_->PushChannel(message, flags, channel.get(), &channel_id_temp);
546e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ALOGE_IF(!ret.ok(), "%s::PushChannel: Failed to push channel: %s",
547e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko           name_.c_str(), strerror(ret.error()));
548e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
549e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel && channel_id_temp != -1)
550e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    channels_[channel_id_temp] = channel;
551e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (channel_id)
552e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *channel_id = channel_id_temp;
553e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
554e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ret;
555e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
556e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
557e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<int> Service::CheckChannel(const Message* message, ChannelReference ref,
558e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                  std::shared_ptr<Channel>* channel) const {
559e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  PDX_TRACE_NAME("Service::CheckChannel");
560e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
561e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Synchronization to maintain consistency between the kernel's channel
562e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // context pointer and the userspace channels_ map. Other threads may attempt
563e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // to modify the map at the same time, which could cause the channel context
564e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // pointer returned by the kernel to be invalid.
565e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::lock_guard<std::mutex> autolock(channels_mutex_);
566e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
567e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Channel* channel_context = nullptr;
568e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<int> ret = endpoint_->CheckChannel(
569e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      message, ref, channel ? &channel_context : nullptr);
570e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ret && channel) {
571e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (channel_context)
572e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *channel = channel_context->shared_from_this();
573e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
574e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      *channel = nullptr;
575e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
576e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
577e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return ret;
578e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
579e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
580e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::string Service::DumpState(size_t /*max_length*/) { return ""; }
581e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
582f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::HandleMessage(Message& message) {
583e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return DefaultHandleMessage(message);
584e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
585e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
586e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid Service::HandleImpulse(Message& /*impulse*/) {}
587e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
588f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::HandleSystemMessage(Message& message) {
589e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const MessageInfo& info = message.GetInfo();
590e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
591e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  switch (info.op) {
592e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_OPEN: {
593e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid,
594e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            info.cid);
595e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      message.SetChannel(OnChannelOpen(message));
596f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return message.Reply(0);
597e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
598e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
599e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_CLOSE: {
600e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGD("%s::OnChannelClose: pid=%d cid=%d\n", name_.c_str(), info.pid,
601e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            info.cid);
602e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      OnChannelClose(message, Channel::GetFromMessageInfo(info));
603e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      message.SetChannel(nullptr);
604f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return message.Reply(0);
605e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
606e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
607e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::REPORT_SYSPROP_CHANGE:
608e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGD("%s:REPORT_SYSPROP_CHANGE: pid=%d cid=%d\n", name_.c_str(),
609e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            info.pid, info.cid);
610e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      OnSysPropChange();
611e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      android::report_sysprop_change();
612f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return message.Reply(0);
613e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
614e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::DUMP_STATE: {
615e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid,
616e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            info.cid);
617e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      auto response = DumpState(message.GetReceiveLength());
618e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const size_t response_size = response.size() < message.GetReceiveLength()
619e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       ? response.size()
620e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       : message.GetReceiveLength();
621f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      const Status<size_t> status =
622e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          message.Write(response.data(), response_size);
623f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      if (status && status.get() < response_size)
624f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        return message.ReplyError(EIO);
625e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      else
626f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        return message.Reply(status);
627e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
628e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
629e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    default:
630f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return ErrorStatus{EOPNOTSUPP};
631e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
632e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
633e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
634f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::DefaultHandleMessage(Message& message) {
635e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const MessageInfo& info = message.GetInfo();
636e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
637e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n",
638e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko           info.pid, info.cid, info.op);
639e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
640e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  switch (info.op) {
641e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_OPEN:
642e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::CHANNEL_CLOSE:
643e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::REPORT_SYSPROP_CHANGE:
644e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    case opcodes::DUMP_STATE:
645f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return HandleSystemMessage(message);
646e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
647e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    default:
648f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko      return message.ReplyError(EOPNOTSUPP);
649e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
650e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
651e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
652e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid Service::OnSysPropChange() {}
653e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
654f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::ReceiveAndDispatch() {
655e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Message message;
656f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  const auto status = endpoint_->MessageReceive(&message);
657f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  if (!status) {
658f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str());
659f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return status;
660e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
661e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
662e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<Service> service = message.GetService();
663e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
664e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!service) {
665e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n");
666e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Don't block the sender indefinitely in this error case.
667e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    endpoint_->MessageReply(&message, -EINVAL);
668f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return ErrorStatus{EINVAL};
669e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
670e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
671e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (message.IsImpulse()) {
672e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    service->HandleImpulse(message);
673f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return {};
674e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else if (service->HandleSystemMessage(message)) {
675f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    return {};
676e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
677e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return service->HandleMessage(message);
678e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
679e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
680e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
681f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<void> Service::Cancel() { return endpoint_->Cancel(); }
682e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
683e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
684e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
685