2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/socket.h>
24 #include <sys/types.h>
26 #include "debug-port-internal.hh"
27 #include "log-private.hh"
28 #include "proxy-internal.h"
30 #define EILLEGALACCESS 127
35 Proxy::Proxy(bool mock)
36 : fd_broker_(new FdBroker(mock)) {}
42 gboolean Proxy::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond,
44 Proxy* proxy = static_cast<Proxy*>(data);
45 IEventListener* listener = proxy->listener_;
46 int fd = g_io_channel_unix_get_fd(gio);
48 _W("Socket was disconnected. fd(%d)", fd);
50 if (proxy->main_port_.get()->GetFd() == fd) {
51 proxy->listener_ = nullptr;
52 proxy->main_port_.get()->SetDisconnectedSource(0);
54 listener->OnDisconnected(proxy->target_appid_);
56 proxy->main_port_.reset();
57 proxy->delegate_port_.reset();
58 } else if (proxy->delegate_port_.get()->GetFd() == fd) {
59 proxy->listener_ = nullptr;
60 proxy->delegate_port_.get()->SetDisconnectedSource(0);
62 listener->OnDisconnected(proxy->target_appid_);
64 proxy->main_port_.reset();
65 proxy->delegate_port_.reset();
67 DebugPort::GetInst().RemoveSession(fd);
72 gboolean Proxy::OnDataReceived(GIOChannel *gio, GIOCondition cond,
74 Proxy* proxy = static_cast<Proxy*>(data);
75 int fd = g_io_channel_unix_get_fd(gio);
78 if (proxy->delegate_port_.get()->GetFd() == fd) {
79 if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
80 _W("Socket was disconnected by stub. fd(%d)", fd);
81 IEventListener* listener = proxy->listener_;
82 proxy->listener_ = nullptr;
83 proxy->delegate_port_.get()->SetSource(0);
85 listener->OnDisconnected(proxy->target_appid_);
87 DebugPort::GetInst().RemoveSession(proxy->main_port_->GetFd());
88 proxy->main_port_.reset();
89 proxy->delegate_port_.reset();
94 proxy->listener_->OnReceived(proxy->target_appid_);
100 void Proxy::OnPortRejected(int error) {
101 _W("[__OnPortRejected__] endpoint(%s), error(%d)",
102 target_appid_.c_str(), error);
103 if (listener_ == nullptr)
106 IEventListener* listener = listener_;
108 listener->OnRejected(target_appid_, error);
111 void Proxy::OnPortAppeared() {
112 _D("endpoint(%s), port_name(%s)", target_appid_.c_str(), port_name_.c_str());
113 if (listener_ == nullptr)
118 int r = fd_broker_->Send(real_appid_, port_name_, &fds_);
121 IEventListener* listener = listener_;
123 if (r == -EILLEGALACCESS)
124 listener->OnRejected(target_appid_, RPC_PORT_ERROR_PERMISSION_DENIED);
126 listener->OnDisconnected(target_appid_);
131 _W("[__OnPortAppeared__] fds[0]: %d, fds[1]: %d", fds_[0], fds_[1]);
134 void Proxy::OnPortVanished() {
135 _W("[__OnPortVanished__] endpoint(%s), port_name(%s)",
136 target_appid_.c_str(), port_name_.c_str());
139 void Proxy::OnPortConnected() {
140 _W("[__OnPortConnected__] endpoint(%s), port_name(%s)",
141 target_appid_.c_str(), port_name_.c_str());
143 _W("listener is null"); // LCOV_EXCL_LINE
144 return; // LCOV_EXCL_LINE
147 main_port_.reset(new ProxyPort(this, fds_[0], target_appid_, false));
148 delegate_port_.reset(new ProxyPort(this, fds_[1], target_appid_));
149 listener_->OnConnected(target_appid_, main_port_.get());
150 DebugPort::GetInst().AddSession(port_name_, target_appid_, fds_[0], fds_[1]);
154 void Proxy::OnPortDisconnected(bool cancel) {
155 _W("[__OnPortDisconnected__] endporint(%s), port_name(%s)",
156 target_appid_.c_str(), port_name_.c_str());
164 _W("listener is null");
168 IEventListener* listener = listener_;
170 listener->OnDisconnected(target_appid_);
171 DebugPort::GetInst().RemoveSession(fds_[0]);
175 int Proxy::Connect(std::string appid, std::string port_name,
176 IEventListener* ev) {
178 return RPC_PORT_ERROR_INVALID_PARAMETER;
180 if (listener_ != nullptr) {
181 _D("Already connected"); // LCOV_EXCL_LINE
182 return RPC_PORT_ERROR_INVALID_PARAMETER; // LCOV_EXCL_LINE
186 target_appid_ = std::move(appid);
187 port_name_ = std::move(port_name);
188 SetRealAppId(target_appid_);
190 int r = fd_broker_->Watch(this, real_appid_, port_name_);
194 if (r == -EILLEGALACCESS)
195 return RPC_PORT_ERROR_PERMISSION_DENIED;
197 return RPC_PORT_ERROR_IO_ERROR;
201 return RPC_PORT_ERROR_NONE;
204 int Proxy::ConnectSync(std::string appid, std::string port_name,
205 IEventListener* ev) {
207 return RPC_PORT_ERROR_INVALID_PARAMETER;
209 if (listener_ != nullptr) {
210 _W("Already connected");
211 return RPC_PORT_ERROR_INVALID_PARAMETER;
215 target_appid_ = std::move(appid);
216 port_name_ = std::move(port_name);
217 SetRealAppId(target_appid_);
219 int ret = fd_broker_->Prepare(real_appid_, port_name_);
222 if (ret == -EILLEGALACCESS)
223 return RPC_PORT_ERROR_PERMISSION_DENIED;
225 return RPC_PORT_ERROR_IO_ERROR;
230 ret = fd_broker_->SendSync(real_appid_, port_name_, &fds_);
233 if (ret == -EILLEGALACCESS)
234 return RPC_PORT_ERROR_PERMISSION_DENIED;
236 return RPC_PORT_ERROR_IO_ERROR;
239 main_port_.reset(new ProxyPort(this, fds_[0], target_appid_, false));
240 delegate_port_.reset(new ProxyPort(this, fds_[1], target_appid_));
241 listener_->OnConnected(target_appid_, main_port_.get());
242 DebugPort::GetInst().AddSession(port_name, target_appid_, fds_[0], fds_[1]);
244 return RPC_PORT_ERROR_NONE;
247 void Proxy::DisconnectPort() {
251 void Proxy::SetRealAppId(const std::string& alias_appid) {
252 if (!real_appid_.empty())
255 char* appid = nullptr;
256 int ret = aul_svc_get_appid_by_alias_appid(alias_appid.c_str(), &appid);
257 if (ret != AUL_SVC_RET_OK) {
258 real_appid_ = alias_appid;
262 std::unique_ptr<char, decltype(std::free)*> appid_ptr(appid, std::free);
263 real_appid_ = std::string(appid);
264 _W("alias_appid(%s), real_appid(%s)", alias_appid.c_str(), appid);
267 Proxy::ProxyPort::ProxyPort(Proxy* parent, int fd, const std::string& id,
268 bool receive) : Port(fd, id), parent_(parent) {
272 Proxy::ProxyPort::~ProxyPort() {
273 if (disconn_src_ > 0)
274 g_source_remove(disconn_src_);
277 g_source_remove(src_);
279 if (gioc_ != nullptr)
280 g_io_channel_unref(gioc_);
283 int Proxy::ProxyPort::Watch(bool receive) {
287 gioc_ = g_io_channel_unix_new(fd);
289 _E("Error is %s", strerror_r(errno, buf, sizeof(buf))); // LCOV_EXCL_LINE
290 return -1; // LCOV_EXCL_LINE
293 disconn_src_ = g_io_add_watch(gioc_,
294 (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
295 Proxy::OnSocketDisconnected, parent_);
296 if (disconn_src_ == 0) {
298 _E("Failed to add watch on socket");
299 g_io_channel_unref(gioc_);
308 src_ = g_io_add_watch(gioc_,
309 (GIOCondition)(G_IO_IN),
310 Proxy::OnDataReceived, parent_);
313 _E("Failed to add watch on socket");
314 g_source_remove(disconn_src_);
316 g_io_channel_unref(gioc_);
325 void Proxy::ProxyPort::SetDisconnectedSource(int sourceId) {
326 disconn_src_ = sourceId;
329 void Proxy::ProxyPort::SetSource(int sourceId) {
333 } // namespace internal
334 } // namespace rpc_port