Modify directory hierarchy 26/310526/2
authorChanggyu Choi <changyu.choi@samsung.com>
Tue, 30 Apr 2024 09:02:01 +0000 (18:02 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Tue, 30 Apr 2024 09:11:21 +0000 (18:11 +0900)
The rpc-port sources have been moved to 'src/rpc-port'.

src/
 + src/rpc-port

Change-Id: I93ab201047ba4bfa424baaf2c80bc5dd6cd53e59
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
79 files changed:
src/CMakeLists.txt
src/ac-internal.cc [deleted file]
src/ac-internal.hh [deleted file]
src/aul-internal.cc [deleted file]
src/aul-internal.hh [deleted file]
src/client-socket-internal.cc [deleted file]
src/client-socket-internal.hh [deleted file]
src/cynara_thread.cc [deleted file]
src/cynara_thread.hh [deleted file]
src/debug-port-internal.cc [deleted file]
src/debug-port-internal.hh [deleted file]
src/exception-internal.cc [deleted file]
src/exception-internal.hh [deleted file]
src/file-monitor-internal.cc [deleted file]
src/file-monitor-internal.hh [deleted file]
src/log-private.hh [deleted file]
src/message-sending-thread-internal.cc [deleted file]
src/message-sending-thread-internal.hh [deleted file]
src/parcel-header-internal.cc [deleted file]
src/parcel-header-internal.hh [deleted file]
src/parcel-internal.cc [deleted file]
src/parcel-internal.hh [deleted file]
src/peer-cred-internal.cc [deleted file]
src/peer-cred-internal.hh [deleted file]
src/port-internal.cc [deleted file]
src/port-internal.hh [deleted file]
src/proxy-internal.cc [deleted file]
src/proxy-internal.hh [deleted file]
src/request-internal.cc [deleted file]
src/request-internal.hh [deleted file]
src/response-internal.cc [deleted file]
src/response-internal.hh [deleted file]
src/rpc-port-internal.cc [deleted file]
src/rpc-port-parcel.cc [deleted file]
src/rpc-port.cc [deleted file]
src/rpc-port/CMakeLists.txt [new file with mode: 0644]
src/rpc-port/ac-internal.cc [new file with mode: 0644]
src/rpc-port/ac-internal.hh [new file with mode: 0644]
src/rpc-port/aul-internal.cc [new file with mode: 0644]
src/rpc-port/aul-internal.hh [new file with mode: 0644]
src/rpc-port/client-socket-internal.cc [new file with mode: 0644]
src/rpc-port/client-socket-internal.hh [new file with mode: 0644]
src/rpc-port/cynara_thread.cc [new file with mode: 0644]
src/rpc-port/cynara_thread.hh [new file with mode: 0644]
src/rpc-port/debug-port-internal.cc [new file with mode: 0644]
src/rpc-port/debug-port-internal.hh [new file with mode: 0644]
src/rpc-port/exception-internal.cc [new file with mode: 0644]
src/rpc-port/exception-internal.hh [new file with mode: 0644]
src/rpc-port/file-monitor-internal.cc [new file with mode: 0644]
src/rpc-port/file-monitor-internal.hh [new file with mode: 0644]
src/rpc-port/log-private.hh [new file with mode: 0644]
src/rpc-port/message-sending-thread-internal.cc [new file with mode: 0644]
src/rpc-port/message-sending-thread-internal.hh [new file with mode: 0644]
src/rpc-port/parcel-header-internal.cc [new file with mode: 0644]
src/rpc-port/parcel-header-internal.hh [new file with mode: 0644]
src/rpc-port/parcel-internal.cc [new file with mode: 0644]
src/rpc-port/parcel-internal.hh [new file with mode: 0644]
src/rpc-port/peer-cred-internal.cc [new file with mode: 0644]
src/rpc-port/peer-cred-internal.hh [new file with mode: 0644]
src/rpc-port/port-internal.cc [new file with mode: 0644]
src/rpc-port/port-internal.hh [new file with mode: 0644]
src/rpc-port/proxy-internal.cc [new file with mode: 0644]
src/rpc-port/proxy-internal.hh [new file with mode: 0644]
src/rpc-port/request-internal.cc [new file with mode: 0644]
src/rpc-port/request-internal.hh [new file with mode: 0644]
src/rpc-port/response-internal.cc [new file with mode: 0644]
src/rpc-port/response-internal.hh [new file with mode: 0644]
src/rpc-port/rpc-port-internal.cc [new file with mode: 0644]
src/rpc-port/rpc-port-parcel.cc [new file with mode: 0644]
src/rpc-port/rpc-port.cc [new file with mode: 0644]
src/rpc-port/server-socket-internal.cc [new file with mode: 0644]
src/rpc-port/server-socket-internal.hh [new file with mode: 0644]
src/rpc-port/stub-internal.cc [new file with mode: 0644]
src/rpc-port/stub-internal.hh [new file with mode: 0644]
src/server-socket-internal.cc [deleted file]
src/server-socket-internal.hh [deleted file]
src/stub-internal.cc [deleted file]
src/stub-internal.hh [deleted file]
utils/CMakeLists.txt

index 3e45a738e116c0191c54fe2aa9a044dec6dbeb59..b07040e2ce380115415700250a0719fdfa50d13d 100644 (file)
@@ -1,36 +1 @@
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} RPC_PORT_SRCS)
-
-ADD_LIBRARY(${TARGET_RPC_PORT} SHARED ${RPC_PORT_SRCS})
-SET_TARGET_PROPERTIES(${TARGET_RPC_PORT} PROPERTIES SOVERSION ${MAJORVER})
-SET_TARGET_PROPERTIES(${TARGET_RPC_PORT} PROPERTIES VERSION ${FULLVER})
-
-TARGET_INCLUDE_DIRECTORIES(${TARGET_RPC_PORT} PUBLIC
-  ${CMAKE_CURRENT_SOURCE_DIR}
-  ${CMAKE_CURRENT_SOURCE_DIR}/../
-  ${CMAKE_CURRENT_SOURCE_DIR}/../include)
-
-APPLY_PKG_CONFIG(${TARGET_RPC_PORT} PUBLIC
-  AUL_DEPS
-  BUNDLE_DEPS
-  CYNARA_CLIENT_DEPS
-  CYNARA_CREDS_SOCKET_DEPS
-  DLOG_DEPS
-  GIO_DEPS
-  GIO_UNIX_DEPS
-  GLIB_DEPS
-  LIBSYSTEMD_DEPS
-  LIBTZPLATFORM_CONFIG_DEPS
-  PARCEL_DEPS
-  PKGMGR_INFO_DEPS
-  TIZEN_SHARED_QUEUE_DEPS
-  UUID_DEPS
-)
-
-TARGET_LINK_LIBRARIES(${TARGET_RPC_PORT} PUBLIC "-Wl,-z,nodelete")
-
-INSTALL(TARGETS ${TARGET_RPC_PORT} DESTINATION ${LIB_INSTALL_DIR})
-INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../include/
-  DESTINATION include/rpc-port
-  FILES_MATCHING
-  PATTERN "*.h"
-)
+ADD_SUBDIRECTORY(rpc-port)
diff --git a/src/ac-internal.cc b/src/ac-internal.cc
deleted file mode 100644 (file)
index 4a746bb..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ac-internal.hh"
-
-#include <aul.h>
-#include <cynara-client.h>
-#include <cynara-creds-socket.h>
-#include <cynara-error.h>
-#include <dlog.h>
-#include <pkgmgr-info.h>
-
-#include <utility>
-
-#include "aul-internal.hh"
-#include "cynara_thread.hh"
-#include "log-private.hh"
-
-namespace rpc_port {
-namespace internal {
-namespace {
-
-constexpr const uid_t kRegularUidMin = 5000;
-
-class Cynara {
- public:
-  class Creds {
-   public:
-    Creds(int fd, std::string user, std::string client)
-        : fd_(fd), user_(std::move(user)), client_(std::move(client)) {
-      _W("client(%s), user(%s), fd(%d)", client_.c_str(), user_.c_str(), fd);
-    }
-
-    int GetFd() const { return fd_; }
-
-    const std::string& GetUser() const { return user_; }
-
-    const std::string& GetClient() const { return client_; }
-
-   private:
-    int fd_;
-    std::string user_;
-    std::string client_;
-  };
-
-  Cynara() : handle_(nullptr, cynara_finish) {
-    cynara* handle = nullptr;
-    if (cynara_initialize(&handle, nullptr) != CYNARA_API_SUCCESS) {
-      _E("cynara_initialize() is failed");  // LCOV_EXCL_LINE
-    } else {
-      handle_.reset(handle);
-    }
-  }
-
-  ~Cynara() = default;
-
-  std::shared_ptr<Creds> FetchCredsFromSocket(int fd) {
-    char* user = nullptr;
-    int ret = cynara_creds_socket_get_user(fd, USER_METHOD_DEFAULT, &user);
-    if (ret != CYNARA_API_SUCCESS) {
-      // LCOV_EXCL_START
-      char buf[128] = { 0, };
-      cynara_strerror(ret, buf, sizeof(buf));
-      _E("cynara_creds_socket_get_user() is failed. fd(%d), error(%d:%s)",
-         fd, ret, buf);
-      return nullptr;
-      // LCOV_EXCL_STOP
-    }
-    auto user_auto = std::unique_ptr<char, decltype(free)*>(user, free);
-
-    char* client = nullptr;
-    ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_DEFAULT, &client);
-    if (ret != CYNARA_API_SUCCESS) {
-      // LCOV_EXCL_START
-      char buf[128] = { 0, };
-      cynara_strerror(ret, buf, sizeof(buf));
-      _E("cynara_creds_socket_get_client() is failed. fd(%d), error(%d:%s)",
-          fd, ret, buf);
-      return nullptr;
-      // LCOV_EXCL_STOP
-    }
-    auto client_auto = std::unique_ptr<char, decltype(free)*>(client, free);
-
-    return std::make_shared<Creds>(fd, user, client);
-  }
-
-  int Check(const std::shared_ptr<Creds>& creds,
-            const std::string& privilege) const {
-    std::lock_guard<std::recursive_mutex> lock(mutex_);
-    _W("cynara_check() ++ privilege(%s), user(%s)",
-        privilege.c_str(), creds->GetUser().c_str());
-    int ret = cynara_check(handle_.get(), creds->GetClient().c_str(), "",
-                           creds->GetUser().c_str(), privilege.c_str());
-    _W("cynara_check() -- privilege(%s), user(%s)",
-        privilege.c_str(), creds->GetUser().c_str());
-    if (ret != CYNARA_API_ACCESS_ALLOWED) {
-      _E("cynara_check() is not allowed. privilege(%s), error(%d)",
-         privilege.c_str(), ret);
-      return -1;
-    }
-
-    return 0;
-  }
-
- private:
-  std::unique_ptr<cynara, decltype(cynara_finish)*> handle_;
-  mutable std::recursive_mutex mutex_;
-};
-
-Cynara cynara_inst;
-
-}  // namespace
-
-void AccessController::AddPrivilege(std::string privilege) {
-  privileges_.push_back(std::move(privilege));
-}
-
-void AccessController::SetTrusted(const bool trusted) {
-  trusted_ = trusted;
-}
-
-int AccessController::CheckPrivilege(int fd) {
-  auto creds = cynara_inst.FetchCredsFromSocket(fd);
-  if (creds == nullptr) return -1;
-
-  for (const auto& privilege : privileges_) {
-    if (cynara_inst.Check(creds, privilege) != 0)
-      return -1;
-  }
-
-  return 0;
-}
-
-// LCOV_EXCL_START
-int AccessController::CheckTrusted(const std::string& sender_appid) {
-  if (getuid() < kRegularUidMin)
-    return 0;
-
-  if (appid_.empty())
-    appid_ = Aul::GetAppId(getpid());
-
-  _D("CheckCertificate : %s :: %s", appid_.c_str(), sender_appid.c_str());
-  pkgmgrinfo_cert_compare_result_type_e res;
-  int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(appid_.c_str(),
-      sender_appid.c_str(), getuid(), &res);
-  if (ret < 0) {
-    _E("CheckCertificate() Failed");
-    return -1;
-  }
-  if (res != PMINFO_CERT_COMPARE_MATCH) {
-    _E("CheckCertificate() Failed : Certificate Not Matched");
-    return -1;
-  }
-
-  return 0;
-}
-// LCOV_EXCL_STOP
-
-int AccessController::Check(int fd, const std::string& sender_appid) {
-  int ret = 0;
-  if (!privileges_.empty()) {
-    ret = CheckPrivilege(fd);
-    if (ret != 0)
-      return ret;
-  }
-
-  if (trusted_)
-    ret = CheckTrusted(sender_appid);
-
-  return ret;
-}
-
-void AccessController::CheckAsync(int fd, std::string sender_appid,
-    CompleteCallback callback) {
-  /* This is for handle freed issue */
-  auto* tmp_handle = new std::shared_ptr<AccessController>(shared_from_this());
-  Job job([=]() -> Job::Type {
-    if ((*tmp_handle).use_count() == 1) {
-      delete tmp_handle;  // LCOV_EXCL_LINE
-      return Job::Type::Continue;  // LCOV_EXCL_LINE
-    }
-
-    int res = Check(fd, sender_appid);
-    auto* cbdata = new std::pair<CompleteCallback, int>(
-        std::move(callback), res);
-    guint sid = g_idle_add(
-        [](gpointer data) -> gboolean {
-          auto* cb_data = static_cast<std::pair<CompleteCallback, int>*>(data);
-          auto [callback, res] = *cb_data;
-          callback(res);
-          delete cb_data;
-          return G_SOURCE_REMOVE;
-        }, cbdata);
-    if (sid == 0) {
-      _E("Failed to call g_idle_add");  // LCOV_EXCL_LINE
-      delete cbdata;  // LCOV_EXCL_LINE
-    }
-
-    delete tmp_handle;
-    return Job::Type::Continue;
-  });
-
-  CynaraThread::GetInst().Push(std::move(job));
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/ac-internal.hh b/src/ac-internal.hh
deleted file mode 100644 (file)
index 0b48d5c..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef AC_INTERNAL_HH_
-#define AC_INTERNAL_HH_
-
-#include <gio/gio.h>
-#include <glib-unix.h>
-#include <glib.h>
-
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace rpc_port {
-namespace internal {
-
-using CompleteCallback = std::function<void(int)>;
-
-class AccessController : public std::enable_shared_from_this<AccessController> {
- public:
-  explicit AccessController(bool trusted = false) : trusted_(trusted) {}
-
-  void AddPrivilege(std::string privilege);
-  void SetTrusted(const bool trusted);
-  int Check(int fd, const std::string& sender_appid);
-  void CheckAsync(int fd, std::string sender_appid, CompleteCallback callback);
-
- private:
-  int CheckTrusted(const std::string& sender_appid);
-  int CheckPrivilege(int fd);
-
- private:
-  std::vector<std::string> privileges_;
-  std::map<std::string, bool> cache_;
-  bool trusted_;
-  std::string appid_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // AC_INTERNAL_HH_
diff --git a/src/aul-internal.cc b/src/aul-internal.cc
deleted file mode 100644 (file)
index 628cd5f..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <aul.h>
-#include <aul_rpc_port.h>
-#include <aul_proc.h>
-
-#include <memory>
-
-#include "aul-internal.hh"
-#include "include/rpc-port.h"
-#include "log-private.hh"
-
-namespace rpc_port {
-namespace internal {
-
-std::string Aul::GetName(int pid) {
-  char* name = nullptr;
-  if (aul_proc_get_name(pid, &name) != AUL_R_OK) return "";
-
-  std::unique_ptr<char, decltype(std::free)*> name_auto(name, std::free);
-  return std::string(name);
-}
-
-std::string Aul::GetAppId(int pid) {
-  char app_id[256] = { 0, };
-  int ret = aul_app_get_appid_bypid(pid, app_id, sizeof(app_id));
-  if (ret != AUL_R_OK) {
-    // LCOV_EXCL_START
-    _E("aul_app_get_appid_bypid() is failed. pid(%d), error(%d)", pid, ret);
-    return GetName(pid);
-    // LCOV_EXCL_STOP
-  }
-
-  return std::string(app_id);
-}
-
-std::string Aul::GetPortPath(const std::string& app_id,
-    const std::string& port_name, uid_t uid) {
-  char* port_path = nullptr;
-  int ret = aul_rpc_port_usr_get_path(app_id.c_str(), port_name.c_str(), uid,
-      &port_path);
-  if (ret != AUL_R_OK) {
-    _E("aul_rpc_port_usr_get_path() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return {};  // LCOV_EXCL_LINE
-  }
-
-  std::unique_ptr<char, decltype(std::free)*> ptr(port_path, std::free);
-  return std::string(port_path);
-}
-
-int Aul::PrepareStub(const std::string& app_id, const std::string& port_name,
-    uid_t uid) {
-  int ret = aul_rpc_port_usr_prepare_stub(app_id.c_str(), port_name.c_str(),
-      uid);
-  if (ret != AUL_R_OK) {
-    _E("aul_rpc_port_usr_prepare_stub() is failed. error(%d)", ret);
-    if (ret == AUL_R_EILLACC)
-      return RPC_PORT_ERROR_PERMISSION_DENIED;
-
-    return RPC_PORT_ERROR_IO_ERROR;
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-bool Aul::ExistPort(const std::string& app_id, const std::string& port_name,
-    uid_t uid) {
-  bool exist = false;
-  int ret = aul_rpc_port_usr_exist(app_id.c_str(), port_name.c_str(), uid,
-      &exist);
-  if (ret != AUL_R_OK)
-    _W("aul_rpc_port_usr_exist() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return exist;
-}
-
-void Aul::NotifyRpcFinished() {
-  int ret = aul_rpc_port_notify_rpc_finished();
-  if (ret != AUL_R_OK)
-    _W("aul_rpc_port_notify_rpc_finished() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/aul-internal.hh b/src/aul-internal.hh
deleted file mode 100644 (file)
index 3d74be4..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef AUL_INTERNAL_HH_
-#define AUL_INTERNAL_HH_
-
-#include <string>
-
-namespace rpc_port {
-namespace internal {
-
-class Aul {
- public:
-  static std::string GetName(int pid);
-  static std::string GetAppId(int pid);
-  static std::string GetPortPath(const std::string& app_id,
-      const std::string& port_name, uid_t uid);
-  static int PrepareStub(const std::string& app_id,
-      const std::string& port_name, uid_t uid);
-  static bool ExistPort(const std::string& app_id, const std::string& port_name,
-      uid_t uid);
-  static void NotifyRpcFinished();
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // AUL_INTERNAL_HH_
diff --git a/src/client-socket-internal.cc b/src/client-socket-internal.cc
deleted file mode 100644 (file)
index 9a71b4e..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "client-socket-internal.hh"
-#include "exception-internal.hh"
-#include "log-private.hh"
-
-namespace rpc_port {
-namespace internal {
-
-ClientSocket::ClientSocket() {
-  fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-  if (fd_ < 0) {
-    // LCOV_EXCL_START
-    fd_ = -errno;
-    _E("socket() is failed. errno(%d)", errno);
-    THROW(fd_);
-    // LCOV_EXCL_STOP
-  }
-}
-
-ClientSocket::ClientSocket(int fd) : fd_(fd) {
-  SetCloseOnExec();
-}
-
-ClientSocket::~ClientSocket() {
-  if (!IsClosed())
-    Close();
-}
-
-void ClientSocket::SetCloseOnExec() {
-  int flags = fcntl(fd_, F_GETFL, 0);
-  fcntl(fd_, F_SETFL, flags | FD_CLOEXEC);
-  _I("Close on exec. fd(%d)", fd_);
-}
-
-void ClientSocket::Close() {
-  if (fd_ > -1) {
-    close(fd_);
-    fd_ = -1;
-  }
-}
-
-int ClientSocket::Connect(const std::string& endpoint) {
-  int flag = fcntl(GetFd(), F_GETFL, 0);
-  fcntl(GetFd(), F_SETFL, flag | O_NONBLOCK);
-
-  struct sockaddr_un sockaddr = { 0, };
-  sockaddr.sun_family = AF_UNIX;
-  snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
-      endpoint.c_str());
-  struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
-  socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
-  int ret = connect(GetFd(), sockaddr_ptr, len);
-  fcntl(GetFd(), F_SETFL, flag);
-  if (ret < 0) {
-    // LCOV_EXCL_START
-    ret = -errno;
-    _E("connect() is failed. errno(%d)", errno);
-    return ret;
-    // LCOV_EXCL_STOP
-  }
-
-  return 0;
-}
-
-int ClientSocket::Send(const void* buf, unsigned int size) {
-  const unsigned char* buffer = static_cast<const unsigned char*>(buf);
-  size_t len = size;
-  while (len) {
-    ssize_t bytes = send(GetFd(), buffer, len, MSG_NOSIGNAL);
-    if (bytes < 0) {
-      // LCOV_EXCL_START
-      int ret = -errno;
-      _E("send() is failed. fd(%d), errno(%d)", GetFd(), errno);
-      return ret;
-      // LCOV_EXCL_STOP
-    }
-
-    len -= bytes;
-    buffer += bytes;
-  }
-
-  return 0;
-}
-
-int ClientSocket::Receive(void* buf, unsigned int size) {
-  unsigned char* buffer = static_cast<unsigned char*>(buf);
-  size_t len = size;
-  while (len) {
-    ssize_t bytes = read(GetFd(), buffer, len);
-    if (bytes == 0) {
-      _W("EOF. fd(%d)", GetFd());  // LCOV_EXCL_START
-      return -EIO;  // LCOV_EXCL_STOP
-    }
-
-    if (bytes < 0) {
-      if (errno == EINTR) {
-        usleep(100 * 1000);
-        continue;
-      }
-
-      return -errno;  // LCOV_EXCL_LINE
-    }
-
-    len -= bytes;
-    buffer += bytes;
-  }
-
-  return 0;
-}
-
-void ClientSocket::SetReceiveTimeout(int timeout) {
-  if (timeout == INT_MAX)
-    return;  // LCOV_EXCL_LINE
-
-  if (timeout == -1)
-    timeout = 5000;
-
-  if (timeout < 0) {
-    _E("Invalid parameter");  // LCOV_EXCL_LINE
-    THROW(-EINVAL);  // LCOV_EXCL_LINE
-  }
-
-  struct timeval tv = {
-    .tv_sec = static_cast<time_t>(timeout / 1000),
-    .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000)
-  };
-  socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
-  int ret = setsockopt(GetFd(), SOL_SOCKET, SO_RCVTIMEO, &tv, len);
-  if (ret < 0) {
-    // LCOV_EXCL_START
-    ret = -errno;
-    _E("setsockopt() is failed. errno(%d)", errno);
-    THROW(ret);
-    // LCOV_EXCL_STOP
-  }
-}
-
-bool ClientSocket::IsClosed() {
-  return fd_ < 0 ? true : false;
-}
-
-int ClientSocket::GetFd() const {
-  return fd_;
-}
-
-int ClientSocket::RemoveFd() {
-  int fd = fd_;
-  fd_ = -1;
-  return fd;
-}
-
-void ClientSocket::SetNonblock() {
-  int flag = fcntl(GetFd(), F_GETFL, 0);
-  fcntl(GetFd(), F_SETFL, flag | O_NONBLOCK);
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/client-socket-internal.hh b/src/client-socket-internal.hh
deleted file mode 100644 (file)
index d033b2e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CLIENT_SOCKET_INTERNAL_HH_
-#define CLIENT_SOCKET_INTERNAL_HH_
-
-#include <string>
-
-namespace rpc_port {
-namespace internal {
-
-class ClientSocket {
- public:
-  ClientSocket();
-  explicit ClientSocket(int fd);
-  virtual ~ClientSocket();
-
-  void Close();
-  int Connect(const std::string& endpoint);
-  int Send(const void* buf, unsigned int size);
-  int Receive(void* buf, unsigned int size);
-  void SetReceiveTimeout(int timeout);
-  bool IsClosed();
-  int GetFd() const;
-  int RemoveFd();
-  void SetNonblock();
-  void SetCloseOnExec();
-
- private:
-  int fd_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // CLIENT_SOCKET_INTERNAL_HH_
diff --git a/src/cynara_thread.cc b/src/cynara_thread.cc
deleted file mode 100644 (file)
index a5a2f67..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "cynara_thread.hh"
-
-#include <utility>
-
-namespace rpc_port {
-namespace internal {
-
-Job::Job(Job::JobHandlerCallback cb) : cb_(std::move(cb)) {}
-
-Job::Type Job::Do() {
-  if (cb_ == nullptr)
-    return Job::Type::Finish;
-
-  return cb_();
-}
-
-CynaraThread& CynaraThread::GetInst() {
-  static CynaraThread* inst = new CynaraThread();
-  return *inst;
-}
-
-CynaraThread::CynaraThread() {
-  thread_ = std::thread([this]() { ThreadRun(); });
-}
-
-// LCOV_EXCL_START
-CynaraThread::~CynaraThread() {
-  queue_.Push(Job());
-  thread_.join();
-}
-// LCOV_EXCL_STOP
-
-void CynaraThread::ThreadRun() {
-  while (true) {
-    Job job = queue_.WaitAndPop();
-    if (job.Do() == Job::Type::Finish)
-      return;  // LCOV_EXCL_LINE
-  }
-}
-
-void CynaraThread::Push(Job job) {
-  queue_.Push(std::move(job));
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/cynara_thread.hh b/src/cynara_thread.hh
deleted file mode 100644 (file)
index 3babdd3..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CYNARA_THREAD_HH_
-#define CYNARA_THREAD_HH_
-
-#include <functional>
-#include <shared-queue.hpp>
-#include <thread>
-
-namespace rpc_port {
-namespace internal {
-
-class Job {
- public:
-  enum class Type {
-    Continue = 0,
-    Finish = 1,
-  };
-
-  using JobHandlerCallback = std::function<Type(void)>;
-
-  explicit Job(JobHandlerCallback cb = nullptr);
-
-  ~Job() = default;
-
-  Type Do();
-
- private:
-  JobHandlerCallback cb_;
-};
-
-class CynaraThread {
- public:
-  static CynaraThread& GetInst();
-  CynaraThread(CynaraThread&) = delete;
-  CynaraThread& operator=(CynaraThread&) = delete;
-  ~CynaraThread();
-
-  void ThreadRun();
-  void Push(Job job);
-
- private:
-  CynaraThread();
-  Job Pop();
-
-  std::thread thread_;
-  mutable tizen_base::SharedQueue<Job> queue_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // CYNARA_THREAD_HH_
diff --git a/src/debug-port-internal.cc b/src/debug-port-internal.cc
deleted file mode 100644 (file)
index eabe432..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "debug-port-internal.hh"
-
-#include <aul_app_com.h>
-#include <bundle_internal.h>
-#include <gio/gio.h>
-#include <glib.h>
-#include <parcel.hh>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <time.h>
-
-#include <atomic>
-#include <list>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <utility>
-
-#include <shared-queue.hpp>
-
-#include "log-private.hh"
-#include "port-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-namespace {
-
-constexpr const char PATH_RPC_PORT_UTIL_SOCK[] =
-    "/run/aul/daemons/.rpc-port-util-sock";
-constexpr const char ENDPOINT_RPC_PORT_DEBUG[] = "org.tizen.rpcport.debug";
-constexpr const char KEY_PORT_NAME[] = "__K_PORT_NAME__";
-
-class Session {
- public:
-  Session(std::string port_name, std::string destination,
-      int main_port, int delegate_port)
-      : port_name_(std::move(port_name)),
-        destination_(std::move(destination)),
-        main_port_(main_port),
-        delegate_port_(delegate_port) {
-  }
-
-  const std::string& GetPortName() const {
-    return port_name_;
-  }
-
-  const std::string& GetDestination() const {
-    return destination_;
-  }
-
-  int GetMainPort() const {
-    return main_port_;
-  }
-
-  int GetDelegatePort() const {
-    return delegate_port_;
-  }
-
- private:
-  std::string port_name_;
-  std::string destination_;
-  int main_port_;
-  int delegate_port_;
-};
-
-class DebugPortImpl {
- public:
-  DebugPortImpl() = default;
-  ~DebugPortImpl();
-
-  void Dispose();
-  bool IsConnected() const;
-  void AddSession(std::string port_name, std::string destination,
-      int main_port, int delegate_port);
-  void RemoveSession(int port);
-  int Send(int port, bool is_read, uint32_t seq,
-      const void* buf, unsigned int size);
-  void Init();
-
- private:
-  int Connect();
-  int Watch(int fd);
-  void Unwatch();
-  void SetConnectionStatus(bool status);
-  void CreateThread();
-  void JoinThread();
-
-  std::recursive_mutex& GetMutex() const;
-  std::shared_ptr<Session> FindSession(int port);
-  std::shared_ptr<Session> FindSession(const std::string& port_name);
-
-  static gboolean OnDebugPortDisconnectedCb(GIOChannel* io,
-      GIOCondition cond, gpointer data);
-  static int AppComCb(const char* endpoint, aul_app_com_result_e result,
-      bundle* envelope, void* user_data);
-
- private:
-  bool disposed_ = true;
-  std::atomic<bool> connected_ { false };
-  std::unique_ptr<Port> port_;
-  GIOChannel* io_ = nullptr;
-  guint watch_tag_ = 0;
-  std::list<std::shared_ptr<Session>> sessions_;
-  std::thread thread_;
-  std::atomic<bool> is_running_ { false };
-  tizen_base::SharedQueue<std::shared_ptr<tizen_base::Parcel>> queue_;
-  mutable std::recursive_mutex mutex_;
-  aul_app_com_connection_h conn_ = nullptr;
-};
-
-DebugPortImpl::~DebugPortImpl() {
-  Dispose();
-}
-
-void DebugPortImpl::Dispose() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (disposed_)
-    return;
-
-  if (conn_) {
-    aul_app_com_leave(conn_);
-    conn_ = nullptr;
-  }
-
-  Unwatch();
-  JoinThread();
-  disposed_ = true;
-}
-
-bool DebugPortImpl::IsConnected() const {
-  return connected_;
-}
-
-void DebugPortImpl::AddSession(std::string port_name, std::string destination,
-    int main_port, int delegate_port) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  sessions_.emplace_back(
-      new Session(std::move(port_name), std::move(destination),
-        main_port, delegate_port));
-}
-
-void DebugPortImpl::RemoveSession(int port) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  auto iter = std::find_if(sessions_.begin(), sessions_.end(),
-      [port](std::shared_ptr<Session>& sess) -> bool {
-        return sess->GetMainPort() == port || sess->GetDelegatePort() == port;
-      });
-
-  if (iter != sessions_.end()) {
-    _W("Remove session. port(%d)", port);
-    iter = sessions_.erase(iter);
-  }
-}
-
-std::shared_ptr<Session> DebugPortImpl::FindSession(int port) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  for (auto& s : sessions_) {
-    if (s->GetMainPort() == port || s->GetDelegatePort() == port)
-      return s;
-  }
-
-  return nullptr;
-}
-
-std::shared_ptr<Session> DebugPortImpl::FindSession(
-    const std::string& port_name) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  for (auto& s : sessions_) {
-    if (s->GetPortName() == port_name)
-      return s;
-  }
-
-  return nullptr;
-}
-
-int DebugPortImpl::Send(int port, bool is_read, uint32_t seq,
-    const void* buf, unsigned int size) {
-  if (!IsConnected())
-    return 0;
-
-  auto session = FindSession(port);
-  if (session == nullptr) {
-    _E("Failed to find session. port(%d)", port);
-    return -1;
-  }
-
-  // time + port_name + destination + is_delegate + port + is_read + seq + size + data
-  tizen_base::Parcel parcel;
-  parcel.WriteInt64(time(nullptr));
-  parcel.WriteString(session->GetPortName().c_str());
-  parcel.WriteString(session->GetDestination().c_str());
-  parcel.WriteBool(session->GetDelegatePort() == port);
-  parcel.WriteInt32(port);
-  parcel.WriteBool(is_read);
-  parcel.WriteInt32(seq);
-  parcel.WriteInt32(size);
-  parcel.Write(static_cast<const unsigned char*>(buf), size);
-
-  queue_.Push(std::make_shared<tizen_base::Parcel>(parcel));
-  return 0;
-}
-
-void DebugPortImpl::Init() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (!disposed_)
-    return;
-
-  aul_app_com_create_async(ENDPOINT_RPC_PORT_DEBUG, nullptr, AppComCb, this,
-      &conn_);
-  if (conn_ == nullptr)
-    return;
-
-  do {
-    int fd = Connect();
-    if (fd < 0)
-      break;
-
-    port_.reset(new Port(fd, "Debug"));
-    if (Watch(fd) < 0)
-      break;
-
-    SetConnectionStatus(true);
-    _W("Connected");
-    CreateThread();
-  } while (0);
-
-  disposed_ = false;
-}
-
-int DebugPortImpl::Connect() {
-  if (access(PATH_RPC_PORT_UTIL_SOCK, F_OK) != 0)
-    return -1;
-
-  int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-  if (fd < 0) {
-    _E("socket() is failed. errno(%d)", errno);
-    return -1;
-  }
-
-  struct sockaddr_un addr = { 0, };
-  addr.sun_family = AF_UNIX;
-  snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", PATH_RPC_PORT_UTIL_SOCK);
-
-  int ret = connect(fd, reinterpret_cast<struct sockaddr*>(&addr),
-      sizeof(addr));
-  if (ret < 0) {
-    _E("connect() is failed. fd(%d), errno(%d)", fd, errno);
-    close(fd);
-    return -1;
-  }
-
-  return fd;
-}
-
-int DebugPortImpl::Watch(int fd) {
-  GIOChannel* io = g_io_channel_unix_new(fd);
-  if (io == nullptr) {
-    _E("g_io_channel_unix_new() is failed");
-    return -1;
-  }
-
-  GIOCondition cond = static_cast<GIOCondition>(
-      (G_IO_ERR | G_IO_HUP | G_IO_NVAL));
-  guint tag = g_io_add_watch(io, cond, OnDebugPortDisconnectedCb, this);
-  if (tag == 0) {
-    _E("g_io_add_watch() is failed");
-    g_io_channel_unref(io);
-    return -1;
-  }
-
-  io_ = io;
-  watch_tag_ = tag;
-  return 0;
-}
-
-void DebugPortImpl::Unwatch() {
-  if (io_) {
-    g_io_channel_unref(io_);
-    io_ = nullptr;
-  }
-
-  if (watch_tag_) {
-    g_source_remove(watch_tag_);
-    watch_tag_ = 0;
-  }
-}
-
-gboolean DebugPortImpl::OnDebugPortDisconnectedCb(GIOChannel* io,
-    GIOCondition cond, gpointer data) {
-  _W("cond(%d)", static_cast<int>(cond));
-  auto* debug_port = static_cast<DebugPortImpl*>(data);
-  std::lock_guard<std::recursive_mutex> lock(debug_port->GetMutex());
-  debug_port->SetConnectionStatus(false);
-  debug_port->watch_tag_ = 0;
-  debug_port->Unwatch();
-  debug_port->port_.reset();
-  _W("Disconnected");
-  return G_SOURCE_REMOVE;
-}
-
-void DebugPortImpl::SetConnectionStatus(bool status) {
-  connected_.exchange(status);
-}
-
-void DebugPortImpl::CreateThread() {
-  if (is_running_)
-    return;
-
-  thread_ = std::thread([&]() {
-      _W("START");
-      do {
-        std::shared_ptr<tizen_base::Parcel> parcel = queue_.WaitAndPop();
-        int len = parcel->GetDataSize();
-        if (len == 0) {
-          _W("Done");
-          break;
-        }
-
-        if (!IsConnected())
-          continue;
-
-        int ret = port_->Write(reinterpret_cast<void*>(&len), sizeof(len));
-        if (ret < 0) {
-          _E("Failed to write size");
-          SetConnectionStatus(false);
-          continue;
-        }
-
-        ret = port_->Write(parcel->GetData(), len);
-        if (ret < 0) {
-          _E("Failed to write data");
-          SetConnectionStatus(false);
-        }
-      } while (true);
-      _W("END");
-    });
-
-  is_running_ = true;
-}
-
-void DebugPortImpl::JoinThread() {
-  if (is_running_)
-    queue_.Push(std::shared_ptr<tizen_base::Parcel>(new tizen_base::Parcel()));
-
-  if (thread_.joinable()) {
-    _W("Join thread");
-    thread_.join();
-  }
-}
-
-
-std::recursive_mutex& DebugPortImpl::GetMutex() const {
-  return mutex_;
-}
-
-int DebugPortImpl::AppComCb(const char* endpoint, aul_app_com_result_e result,
-    bundle* envelope, void* user_data) {
-  const char* val = bundle_get_val(envelope, KEY_PORT_NAME);
-  if (val == nullptr)
-    return -1;
-
-  auto* handle = static_cast<DebugPortImpl*>(user_data);
-  std::string port_name(val);
-  if (port_name.empty() || handle->FindSession(port_name) != nullptr) {
-    auto* handle = static_cast<DebugPortImpl*>(user_data);
-    int fd = handle->Connect();
-    if (fd < 0)
-      return -1;
-
-    std::lock_guard<std::recursive_mutex> lock(handle->GetMutex());
-    handle->port_.reset(new Port(fd, "Debug"));
-    int ret = handle->Watch(fd);
-    if (ret < 0)
-      return -1;
-
-    handle->SetConnectionStatus(true);
-    _W("Connected");
-    handle->CreateThread();
-  }
-
-  return 0;
-}
-
-DebugPortImpl impl;
-
-}  // namespace
-
-bool DebugPort::IsConnected() {
-  impl.Init();
-  return impl.IsConnected();
-}
-
-void DebugPort::AddSession(std::string port_name, std::string destination,
-    int main_port, int delegate_port) {
-  impl.Init();
-  return impl.AddSession(std::move(port_name), std::move(destination),
-      main_port, delegate_port);
-}
-
-void DebugPort::RemoveSession(int port) {
-  impl.Init();
-  return impl.RemoveSession(port);
-}
-
-int DebugPort::Send(int port, bool is_read, uint32_t seq, const void* buf,
-    unsigned int size) {
-  impl.Init();
-  return impl.Send(port, is_read, seq, buf, size);
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/debug-port-internal.hh b/src/debug-port-internal.hh
deleted file mode 100644 (file)
index 9b68c65..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DEBUG_PORT_INTERNAL_HH_
-#define DEBUG_PORT_INTERNAL_HH_
-
-#include <cstdint>
-#include <string>
-
-namespace rpc_port {
-namespace internal {
-
-class DebugPort {
- public:
-  static bool IsConnected();
-  static void AddSession(std::string port_name, std::string destination,
-      int main_port, int delegate_port);
-  static void RemoveSession(int port);
-  static int Send(int port, bool is_read, uint32_t seq,
-      const void* buf, unsigned int size);
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // DEBUG_PORT_INTERNAL_HH_
diff --git a/src/exception-internal.cc b/src/exception-internal.cc
deleted file mode 100644 (file)
index 51a7bb9..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "exception-internal.hh"
-
-#include <utility>
-
-namespace rpc_port {
-namespace internal {
-
-// LCOV_EXCL_START
-Exception::Exception(int error_code, const std::string& file, int line)
-    : error_code_(error_code),
-      message_(std::move(GetErrorMessage(error_code_, file, line))) {
-}
-
-const char* Exception::what() const noexcept {
-  return message_.c_str();
-}
-
-int Exception::GetErrorCode() {
-  return error_code_;
-}
-
-std::string Exception::GetErrorMessage(int error_code, const std::string& file,
-    int line) {
-  return file.substr(file.find_last_of("/") + 1) + ":" + std::to_string(line) +
-      " error_code: " + std::to_string(error_code);
-}
-// LCOV_EXCL_STOP
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/exception-internal.hh b/src/exception-internal.hh
deleted file mode 100644 (file)
index 226c909..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef EXCEPTION_INTERNAL_HH_
-#define EXCEPTION_INTERNAL_HH_
-
-#include <exception>
-#include <string>
-
-#define THROW(error_code) throw Exception(error_code, __FUNCTION__, __LINE__)
-
-namespace rpc_port {
-namespace internal {
-
-class Exception : public std::exception {
- public:
-  explicit Exception(int error_code, const std::string& file, int line);
-  virtual ~Exception() = default;  // LCOV_EXCL_LINE
-
-  virtual const char* what() const noexcept;
-  int GetErrorCode();
-
- private:
-  static std::string GetErrorMessage(int error_code, const std::string& file,
-      int line);
-
- private:
-  int error_code_;
-  std::string message_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // EXCEPTION_INTERNAL_HH_
diff --git a/src/file-monitor-internal.cc b/src/file-monitor-internal.cc
deleted file mode 100644 (file)
index f8b0303..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "file-monitor-internal.hh"
-
-#include <sys/inotify.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <filesystem>
-#include <utility>
-
-#include "exception-internal.hh"
-#include "log-private.hh"
-
-namespace rpc_port {
-namespace internal {
-namespace fs = std::filesystem;
-
-FileMonitor::FileMonitor(std::string path, IEvent* listener)
-    : path_(std::move(path)), listener_(listener) {
-  const auto fs_path = fs::path(path_);
-  parent_path_ = fs_path.parent_path().string();
-  file_name_ = fs_path.filename().string();
-  _W("path=%s, parent_path=%s, file_name=%s",
-     path_.c_str(), parent_path_.c_str(), file_name_.c_str());
-}
-
-FileMonitor::~FileMonitor() {
-  _W("path=%s", path_.c_str());
-  Stop();
-}
-
-bool FileMonitor::Exist() {
-  if (access(path_.c_str(), F_OK) == 0) return true;
-
-  return false;
-}
-
-void FileMonitor::Start() {
-  fd_ = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
-  if (fd_ < 0) {
-    _E("inotify_init1() is failed. errno(%d)", errno);
-    THROW(-1);
-  }
-
-  wd_ = inotify_add_watch(fd_, parent_path_.c_str(), IN_CREATE | IN_DELETE);
-  if (wd_ < 0) {
-    _E("inotify_add_watch() is failed. errno(%d)", errno);
-    Stop();
-    THROW(-1);
-  }
-
-  channel_ = g_io_channel_unix_new(fd_);
-  if (channel_ == nullptr) {
-    _E("g_io_channel_unix_new() is failed");
-    Stop();
-    THROW(-1);
-  }
-
-  source_ = g_io_create_watch(channel_, G_IO_IN);
-  if (source_ == nullptr) {
-    _E("g_io_create_watch() is failed");
-    Stop();
-    THROW(-1);
-  }
-
-  g_source_set_callback(source_, reinterpret_cast<GSourceFunc>(GIOFunc), this,
-                        nullptr);
-  g_source_attach(source_, nullptr);
-  g_source_unref(source_);
-}
-
-void FileMonitor::Stop() {
-  if (source_ && !g_source_is_destroyed(source_)) {
-    g_source_destroy(source_);
-    source_ = nullptr;
-  }
-
-  if (channel_) {
-    g_io_channel_unref(channel_);
-    channel_ = nullptr;
-  }
-
-  if (wd_ > -1) {
-    inotify_rm_watch(fd_, wd_);
-    wd_ = -1;
-  }
-
-  if (fd_ > -1) {
-    close(fd_);
-    fd_ = -1;
-  }
-}
-
-gboolean FileMonitor::GIOFunc(GIOChannel* channel, GIOCondition condition,
-                              gpointer user_data) {
-  char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
-  auto* monitor = static_cast<FileMonitor*>(user_data);
-  auto* listener = monitor->listener_;
-  int fd = g_io_channel_unix_get_fd(channel);
-  struct inotify_event* event;
-  ssize_t len;
-  char* ptr;
-  char* nptr;
-
-  while ((len = read(fd, buf, sizeof(buf))) > 0) {
-    for (ptr = buf; ptr < buf + len;
-         ptr += sizeof(struct inotify_event) + event->len) {
-      event = reinterpret_cast<struct inotify_event*>(ptr);
-      nptr = ptr + sizeof(struct inotify_event) + event->len;
-      if (nptr > buf + len) break;
-
-      if (monitor->file_name_ != event->name) continue;
-
-      if (event->mask & IN_CREATE) {
-        listener->OnFileCreated(monitor->path_);
-        return G_SOURCE_CONTINUE;
-      }
-
-      if (event->mask & IN_DELETE)
-        listener->OnFileDeleted(monitor->path_);
-    }
-  }
-
-  return G_SOURCE_CONTINUE;
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/file-monitor-internal.hh b/src/file-monitor-internal.hh
deleted file mode 100644 (file)
index 2058402..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FILE_MONITOR_INTERNAL_HH_
-#define FILE_MONITOR_INTERNAL_HH_
-
-#include <gio/gio.h>
-#include <glib.h>
-
-#include <string>
-
-namespace rpc_port {
-namespace internal {
-
-class FileMonitor {
- public:
-  class IEvent {
-   public:
-    virtual ~IEvent() = default;
-    virtual void OnFileCreated(const std::string& path) = 0;
-    virtual void OnFileDeleted(const std::string& path) = 0;
-  };
-
-  explicit FileMonitor(std::string path, IEvent* listener = nullptr);
-  ~FileMonitor();
-
-  void Start();
-  void Stop();
-  bool Exist();
-
- private:
-  static gboolean GIOFunc(GIOChannel* channel, GIOCondition condition,
-                          gpointer user_data);
-
- private:
-  std::string path_;
-  std::string parent_path_;
-  std::string file_name_;
-  IEvent* listener_ = nullptr;
-  int fd_ = -1;
-  int wd_ = -1;
-  GIOChannel* channel_ = nullptr;
-  GSource* source_ = nullptr;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // FILE_MONITOR_INTERNAL_HH_
diff --git a/src/log-private.hh b/src/log-private.hh
deleted file mode 100644 (file)
index 36aeb9c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LOG_PRIVATE_HH_
-#define LOG_PRIVATE_HH_
-
-#include <dlog.h>
-
-#undef LOG_TAG
-#define LOG_TAG "RPC_PORT"
-
-#undef _E
-#define _E LOGE
-
-#undef _W
-#define _W LOGW
-
-#undef _I
-#define _I LOGI
-
-#undef _D
-#define _D LOGD
-
-#endif  // LOG_PRIVATE_HH_
diff --git a/src/message-sending-thread-internal.cc b/src/message-sending-thread-internal.cc
deleted file mode 100644 (file)
index b21eddd..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "log-private.hh"
-#include "message-sending-thread-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-// LCOV_EXCL_START
-MessageSendingThread& MessageSendingThread::GetInst() {
-  static MessageSendingThread inst;
-  return inst;
-}
-
-MessageSendingThread::MessageSendingThread() {
-  context_ = g_main_context_new();
-  loop_ = g_main_loop_new(context_, false);
-  std::unique_lock<std::mutex> lock(mutex_);
-  thread_ = std::make_unique<std::thread>([&]() -> void { ThreadLoop(); });
-  cond_.wait(lock, [&] { return thread_ok_; });
-}
-
-MessageSendingThread::~MessageSendingThread() {
-  Dispose();
-}
-
-gboolean MessageSendingThread::NotifyOne(gpointer data) {
-  auto* sender = static_cast<MessageSendingThread*>(data);
-  std::unique_lock<std::mutex> lock(sender->mutex_);
-  sender->thread_ok_ = true;
-  sender->cond_.notify_one();
-  return G_SOURCE_REMOVE;
-}
-
-void MessageSendingThread::ThreadLoop() {
-  {
-    std::unique_lock<std::mutex> lock(mutex_);
-    GSource* source = g_idle_source_new();
-    if (source == nullptr) {
-      _E("Failed to create GSource");
-      cond_.notify_one();
-      return;
-    }
-
-    g_source_set_callback(source, NotifyOne, this, nullptr);
-    g_source_set_priority(source, G_PRIORITY_HIGH);
-    g_source_attach(source, context_);
-    g_source_unref(source);
-
-    g_main_context_push_thread_default(context_);
-  }
-
-  g_main_loop_run(loop_);
-
-  g_main_context_pop_thread_default(context_);
-  _W("Shutdown message sending thread");
-}
-
-void MessageSendingThread::Dispose() {
-  std::unique_lock<std::mutex> lock(mutex_);
-  if (g_main_loop_is_running(loop_))
-    g_main_loop_quit(loop_);
-  else
-    _E("GMainLoop is not running");
-
-  thread_->join();
-
-  g_main_loop_unref(loop_);
-  loop_ = nullptr;
-
-  g_main_context_unref(context_);
-  context_ = nullptr;
-}
-
-GMainContext* MessageSendingThread::GetContext() {
-  return context_;
-}
-// LCOV_EXCL_STOP
-
-}  // namespace internal
-}  // namespace rpc_port
-
diff --git a/src/message-sending-thread-internal.hh b/src/message-sending-thread-internal.hh
deleted file mode 100644 (file)
index 1d3acad..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MESSAGE_SENDING_THREAD_INTERNAL_HH_
-#define MESSAGE_SENDING_THREAD_INTERNAL_HH_
-
-#include <gio/gio.h>
-#include <glib.h>
-
-#include <condition_variable>
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <thread>
-
-#include "port-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-class MessageSendingThread {
- public:
-  static MessageSendingThread& GetInst();
-  ~MessageSendingThread();
-  GMainContext* GetContext();
-
- private:
-  MessageSendingThread();
-  void ThreadLoop();
-  void Dispose();
-  static gboolean NotifyOne(gpointer data);
-
-  GMainContext* context_ = nullptr;
-  GMainLoop* loop_ = nullptr;
-  bool thread_ok_ = false;
-  std::unique_ptr<std::thread> thread_;
-  std::mutex mutex_;
-  std::condition_variable cond_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // MESSAGE_SENDING_THREAD_INTERNAL_HH_
diff --git a/src/parcel-header-internal.cc b/src/parcel-header-internal.cc
deleted file mode 100644 (file)
index f4413dd..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <atomic>
-#include <climits>
-#include <limits>
-#include <utility>
-
-#include "parcel-header-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-ParcelHeader::ParcelHeader() : seq_num_(GenerateSeqNum()) {
-  clock_gettime(CLOCK_MONOTONIC_RAW, &time_stamp_);
-}
-
-void ParcelHeader::WriteToParcel(tizen_base::Parcel* parcel) const {
-  parcel->WriteString(tag_);
-  parcel->WriteInt32(seq_num_);
-  parcel->WriteInt64(static_cast<int64_t>(time_stamp_.tv_sec));
-  parcel->WriteInt64(static_cast<int64_t>(time_stamp_.tv_nsec));
-}
-
-void ParcelHeader::ReadFromParcel(tizen_base::Parcel* parcel) {
-  tag_ = std::move(parcel->ReadString());
-  parcel->ReadInt32(&seq_num_);
-
-  int64_t tv_sec = 0;
-  parcel->ReadInt64(&tv_sec);
-  time_stamp_.tv_sec = tv_sec & std::numeric_limits<time_t>::max();
-
-  int64_t tv_nsec = 0;
-  parcel->ReadInt64(&tv_nsec);
-  time_stamp_.tv_nsec = tv_nsec & std::numeric_limits<long>::max();
-}
-
-void ParcelHeader::SetTag(std::string tag) {
-  tag_ = std::move(tag);
-}
-
-const std::string& ParcelHeader::GetTag() const {
-  return tag_;
-}
-
-void ParcelHeader::SetSeqNum(int seq_num) {
-  seq_num_ = seq_num;
-}
-
-int ParcelHeader::GetSeqNum() const {
-  return seq_num_;
-}
-
-struct timespec ParcelHeader::GetTimeStamp() const {
-  return time_stamp_;
-}
-
-int ParcelHeader::GenerateSeqNum() {
-  static std::atomic<unsigned int> num { 0 };
-  ++num;
-  return static_cast<int>(num & INT_MAX);
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/parcel-header-internal.hh b/src/parcel-header-internal.hh
deleted file mode 100644 (file)
index 32a9007..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PARCEL_HEADER_INTERNAL_H_
-#define PARCEL_HEADER_INTERNAL_H_
-
-#include <time.h>
-
-#include <string>
-
-#include <parcel.hh>
-
-namespace rpc_port {
-namespace internal {
-
-class ParcelHeader : public tizen_base::Parcelable {
- public:
-   ParcelHeader();
-
-  void WriteToParcel(tizen_base::Parcel* parcel) const override;
-  void ReadFromParcel(tizen_base::Parcel* parcel) override;
-
-  void SetTag(std::string tag);
-  const std::string& GetTag() const;
-  void SetSeqNum(int seq_num);
-  int GetSeqNum() const;
-  struct timespec GetTimeStamp() const;
-
-  static int GenerateSeqNum();
-
- private:
-  std::string tag_;
-  int seq_num_;
-  struct timespec time_stamp_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // PARCEL_HEADER_INTERNAL_H_
diff --git a/src/parcel-internal.cc b/src/parcel-internal.cc
deleted file mode 100644 (file)
index 932569c..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "parcel-internal.hh"
-
-#include <memory>
-#include <utility>
-
-#include "log-private.hh"
-
-namespace rpc_port {
-namespace internal {
-
-Parcel::Parcel(bool without_header)
-    : header_(without_header ? nullptr : new ParcelHeader()) {
-}
-
-Parcel::~Parcel() {}
-
-void Parcel::WriteToParcel(tizen_base::Parcel* parcel) const {
-  if (header_.get() != nullptr) {
-    parcel->WriteParcelable(*header_.get());
-    parcel->WriteUInt32(handle_.GetDataSize());
-  }
-
-  parcel->Write(handle_.GetData(), handle_.GetDataSize());
-}
-
-void Parcel::ReadFromParcel(tizen_base::Parcel* parcel) {
-  if (header_.get() != nullptr) {
-    parcel->ReadParcelable(header_.get());
-
-    uint32_t size = 0;
-    parcel->ReadUInt32(&size);
-    if (size > 0) {
-      auto* buf = static_cast<uint8_t*>(malloc(size));
-      if (buf == nullptr) {
-        _E("Out of memory");  // LCOV_EXEC_LINE
-        return;  // LCOV_EXCL_LINE
-      }
-
-      parcel->Read(buf, size);
-      handle_ = std::move(tizen_base::Parcel(buf, size, false));
-    }
-  } else {
-    // LCOV_EXCL_START
-    handle_ = std::move(
-        tizen_base::Parcel(parcel->GetData(), parcel->GetDataSize()));
-    // LCOV_EXCL_STOP
-  }
-}
-
-const ParcelHeader* Parcel::GetParcelHeader() {
-  return header_.get();
-}
-
-parcel_h Parcel::GetHandle() const {
-  return static_cast<parcel_h>(const_cast<tizen_base::Parcel*>(&handle_));
-}
-
-void Parcel::SetRawParcel(tizen_base::Parcel* raw_parcel) {
-  raw_parcel_.reset(raw_parcel);
-}
-
-// LCOV_EXCL_START
-tizen_base::Parcel* Parcel::GetRawParcel() const {
-  return raw_parcel_.get();
-}
-// LCOV_EXCL_STOP
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/parcel-internal.hh b/src/parcel-internal.hh
deleted file mode 100644 (file)
index 3d0911d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PARCEL_INTERNAL_HH_
-#define PARCEL_INTERNAL_HH_
-
-#include <parcel.h>
-
-#include <parcel.hh>
-#include <parcelable.hh>
-
-#include <memory>
-
-#include "parcel-header-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-class Parcel : public tizen_base::Parcelable {
- public:
-   Parcel(bool without_header = false);
-   ~Parcel();
-
-  void WriteToParcel(tizen_base::Parcel* parcel) const override;
-  void ReadFromParcel(tizen_base::Parcel* parcel) override;
-
-  const ParcelHeader* GetParcelHeader();
-  parcel_h GetHandle() const;
-
-  void SetRawParcel(tizen_base::Parcel* raw_parcel);
-  tizen_base::Parcel* GetRawParcel() const;
-
- private:
-  std::unique_ptr<ParcelHeader> header_;
-  tizen_base::Parcel handle_;
-  std::unique_ptr<tizen_base::Parcel> raw_parcel_ { nullptr };
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // PARCEL_INTERNAL_HH_
diff --git a/src/peer-cred-internal.cc b/src/peer-cred-internal.cc
deleted file mode 100644 (file)
index 150d3ab..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <new>
-
-#include "log-private.hh"
-#include "peer-cred-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-PeerCred::PeerCred(pid_t pid, uid_t uid, gid_t gid)
-    : pid_(pid), uid_(uid), gid_(gid) {
-}
-
-PeerCred* PeerCred::Get(int fd) {
-  struct ucred cred;
-  socklen_t len = static_cast<socklen_t>(sizeof(struct ucred));
-  int ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
-      static_cast<void*>(&cred), &len);
-  if (ret != 0) {
-    _E("getsockopt() is failed. fd(%d), errno(%d)", fd, errno);  // LCOV_EXCL_LINE
-    return nullptr;  // LCOV_EXCL_LINE
-  }
-
-  return new (std::nothrow) PeerCred(cred.pid, cred.uid, cred.gid);
-}
-
-pid_t PeerCred::GetPid() const {
-  return pid_;
-}
-
-uid_t PeerCred::GetUid() const {
-  return uid_;
-}
-
-
-// LCOV_EXCL_START
-gid_t PeerCred::GetGid() const {
-  return gid_;
-}
-// LCOV_EXCL_STOP
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/peer-cred-internal.hh b/src/peer-cred-internal.hh
deleted file mode 100644 (file)
index bf57ed5..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PEER_CRED_INTERNAL_HH_
-#define PEER_CRED_INTERNAL_HH_
-
-namespace rpc_port {
-namespace internal {
-
-class PeerCred {
- public:
-  static PeerCred* Get(int fd);
-
-  pid_t GetPid() const;
-  uid_t GetUid() const;
-  gid_t GetGid() const;
-
- private:
-  PeerCred(pid_t pid, uid_t uid, gid_t gid);
-
- private:
-  pid_t pid_;
-  uid_t uid_;
-  gid_t gid_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // PEER_CRED_INTERNAL_HH_
diff --git a/src/port-internal.cc b/src/port-internal.cc
deleted file mode 100644 (file)
index c32d5fb..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <aul_rpc_port.h>
-#include <dlog.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-
-#include <chrono>
-#include <utility>
-
-#include "include/rpc-port.h"
-#include "log-private.hh"
-#include "message-sending-thread-internal.hh"
-#include "port-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-namespace {
-
-constexpr const int QUEUE_SIZE_MAX = 1024 * 1024 * 10;
-constexpr const int MAX_RETRY_CNT = 10;
-constexpr const int MAX_TIMEOUT = 1000;
-constexpr const int MIN_TIMEOUT = 50;
-
-}  // namespace
-
-// LCOV_EXCL_START
-Port::DelayMessage::DelayMessage(const char* msg, int index, int size)
-    : message_(msg, msg + size), index_(index), size_(size) {
-}
-
-void Port::DelayMessage::SetIndex(int index) {
-  index_ += index;
-}
-
-int Port::DelayMessage::GetSize() {
-  return size_ - index_;
-}
-
-int Port::DelayMessage::GetOriginalSize() {
-  return size_;
-}
-
-char* Port::DelayMessage::GetMessage() {
-  char* ptr = reinterpret_cast<char*>(message_.data());
-  ptr += index_;
-  return ptr;
-}
-// LCOV_EXCL_STOP
-
-Port::Port(int fd, std::string id)
-    : fd_(fd), id_(std::move(id)), instance_(""), seq_(0) {
-  char uuid[37];
-  uuid_t u;
-  uuid_generate(u);
-  uuid_unparse(u, uuid);
-  instance_ = std::string(uuid) + ":" + id_;
-  SetReceiveTimeout(10000);
-}
-
-Port::Port(int fd, std::string id, std::string instance)
-    : fd_(fd), id_(std::move(id)), instance_(std::move(instance)), seq_(0) {
-  SetReceiveTimeout(10000);
-}
-
-Port::~Port() {
-  std::lock_guard<std::recursive_mutex> lock(mutex_);
-  ClearQueue();
-  Disconnect();
-}
-
-void Port::Disconnect() {
-  IgnoreIOEvent();
-
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-  if (fd_ > 0) {
-    _W("Close fd(%d)", fd_);
-    close(fd_);
-    fd_ = -1;
-  }
-}
-
-int Port::SetPrivateSharing(const char* paths[], unsigned int size) {
-  int ret = aul_rpc_port_set_private_sharing(id_.c_str(), paths, size);
-  if (ret != 0)
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Port::SetPrivateSharing(const char* path) {
-  const char* file_list[1] = {path};
-  int ret = aul_rpc_port_set_private_sharing(id_.c_str(), file_list, 1);
-  if (ret != 0)
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Port::UnsetPrivateSharing() {
-  int ret = aul_rpc_port_unset_private_sharing(id_.c_str());
-  if (ret != 0)
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Port::Read(void* buf, unsigned int size) {
-  unsigned int left = size;
-  ssize_t nb;
-  int bytes_read = 0;
-  char* buffer = static_cast<char*>(buf);
-  int flags;
-
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-  if (fd_ < 0 || fd_ >= sysconf(_SC_OPEN_MAX)) {
-    _E("Invalid fd(%d)", fd_);  // LCOV_EXCL_LINE
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  }
-
-  flags = fcntl(fd_, F_GETFL, 0);
-  fcntl(fd_, F_SETFL, flags & ~O_NONBLOCK);
-
-  while (left) {
-    nb = read(fd_, buffer, left);
-    if (nb == 0) {
-      _E("read_socket: ...read EOF, socket closed %d: nb %zd\n", fd_, nb);
-      fcntl(fd_, F_SETFL, flags);
-      return RPC_PORT_ERROR_IO_ERROR;
-    }
-
-    if (nb == -1) {
-      if (errno == EINTR) {
-        usleep(100 * 1000);
-        continue;
-      }
-
-      _E("read_socket: ...error fd %d: errno %d\n", fd_, errno);
-      fcntl(fd_, F_SETFL, flags);
-      return RPC_PORT_ERROR_IO_ERROR;
-    }
-
-    left -= nb;
-    buffer += nb;
-    bytes_read += nb;
-  }
-
-  fcntl(fd_, F_SETFL, flags);
-  return RPC_PORT_ERROR_NONE;
-}
-
-// LCOV_EXCL_START
-int Port::SetReceiveTimeout(int timeout) {
-   if (timeout == INT_MAX)
-    return -EINVAL;
-
-  if (timeout == -1)
-    timeout = 10000;
-
-  if (timeout < 0) {
-    _E("Invalid parameter");
-    return -EINVAL;
-  }
-
-  struct timeval tv = {
-    .tv_sec = static_cast<time_t>(timeout / 1000),
-    .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000)
-  };
-  socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
-  int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &tv, len);
-  if (ret < 0) {
-    ret = -errno;
-    _E("setsockopt() is failed. errno(%d)", errno);
-  }
-
-  return ret;
-}
-
-bool Port::CanWrite() {
-  struct pollfd fds[1];
-  fds[0].fd = fd_;
-  fds[0].events = POLLOUT;
-  fds[0].revents = 0;
-  int ret = poll(fds, 1, 100);
-  if (ret <= 0) {
-    _W("poll() is failed. fd(%d), error(%s)",
-        fd_, ret == 0 ? "timed out" : std::to_string(-errno).c_str());
-    return false;
-  }
-
-  return true;
-}
-// LCOV_EXCL_STOP
-
-int Port::Write(const void* buf, unsigned int size) {
-  int sent_bytes = 0;
-  int ret;
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-
-  if (queue_.empty()) {
-    ret = Write(buf, size, &sent_bytes);
-    if (ret == PORT_STATUS_ERROR_NONE)
-      return RPC_PORT_ERROR_NONE;
-    else if (ret == PORT_STATUS_ERROR_IO_ERROR)
-      return RPC_PORT_ERROR_IO_ERROR;
-  } else if (CanWrite()) {  // LCOV_EXCL_LINE
-    // LCOV_EXCL_START
-    while (!queue_.empty()) {
-      int port_status = PopDelayedMessage();
-      if (port_status != PORT_STATUS_ERROR_NONE) {
-        if (port_status == PORT_STATUS_ERROR_IO_ERROR)
-          return RPC_PORT_ERROR_IO_ERROR;
-
-        break;
-      }
-    }
-    // LCOV_EXCL_STOP
-  }
-
-  // LCOV_EXCL_START
-  if (delayed_message_size_ > QUEUE_SIZE_MAX) {
-    _E("cache fail : delayed_message_size (%d), count(%zu)",
-        delayed_message_size_, queue_.size());
-    return RPC_PORT_ERROR_IO_ERROR;
-  }
-
-  return PushDelayedMessage(
-      std::make_shared<DelayMessage>(
-        static_cast<const char*>(buf), sent_bytes, size));
-  // LCOV_EXCL_STOP
-}
-
-int Port::Write(const void* buf, unsigned int size, int* sent_bytes) {
-  unsigned int left = size;
-  ssize_t nb;
-  int retry_cnt = 0;
-  const char* buffer = static_cast<const char*>(buf);
-
-  if (fd_ < 0 || fd_ >= sysconf(_SC_OPEN_MAX)) {
-    _E("Invalid fd(%d)", fd_);  // LCOV_EXCL_LINE
-    return PORT_STATUS_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  }
-
-  while (left && (retry_cnt < MAX_RETRY_CNT)) {
-    nb = send(fd_, buffer, left, MSG_NOSIGNAL);
-    if (nb == -1) {
-      if (errno == EINTR) {
-        // LCOV_EXCL_START
-        LOGI("write_socket: EINTR continue ...");
-        retry_cnt++;
-        continue;
-        // LCOV_EXCL_STOP
-      }
-
-      if (errno == EAGAIN || errno == EWOULDBLOCK)
-        return PORT_STATUS_ERROR_RESOURCE_UNAVAILABLE;
-
-      _E("write_socket: ...error fd: %d, errno: %d", fd_, errno);
-      return PORT_STATUS_ERROR_IO_ERROR;
-    }
-
-    left -= nb;
-    buffer += nb;
-    *sent_bytes += nb;
-  }
-
-  if (left != 0) {
-    _E("error fd %d: retry_cnt %d", fd_, retry_cnt);
-    return PORT_STATUS_ERROR_IO_ERROR;
-  }
-
-  return PORT_STATUS_ERROR_NONE;
-}
-
-// LCOV_EXCL_START
-gboolean Port::OnEventReceived(GIOChannel* io, GIOCondition condition,
-                               gpointer data) {
-  auto* ptr = static_cast<std::weak_ptr<Port>*>(data);
-  auto port = ptr->lock();
-  if (port == nullptr) {
-    _E("port is destructed");
-    return G_SOURCE_REMOVE;
-  }
-
-  _W("Writing is now possible. fd: %d, id: %s",
-      port->GetFd(), port->GetId().c_str());
-  std::lock_guard<std::recursive_mutex> lock(port->rw_mutex_);
-  if (port->source_id_ == 0) {
-    _E("GSource is destroyed");
-    return G_SOURCE_REMOVE;
-  }
-
-  if (port->queue_.empty()) {
-    port->IgnoreIOEvent();
-    return G_SOURCE_CONTINUE;
-  }
-
-  port->PopDelayedMessage();
-  return G_SOURCE_CONTINUE;
-}
-// LCOV_EXCL_STOP
-
-void Port::ClearQueue() {
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-
-  while (queue_.empty() == false)
-    queue_.pop();
-
-  IgnoreIOEvent();
-  delayed_message_size_ = 0;
-}
-
-void Port::IgnoreIOEvent() {
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-  if (source_id_ != 0) {
-    // LCOV_EXCL_START
-    GSource* source = g_main_context_find_source_by_id(
-        MessageSendingThread::GetInst().GetContext(), source_id_);
-    if (source != nullptr && !g_source_is_destroyed(source))
-      g_source_destroy(source);
-
-    source_id_ = 0;
-    // LCOV_EXCL_STOP
-  }
-
-  if (channel_ != nullptr) {
-    g_io_channel_unref(channel_);  // LCOV_EXCL_LINE
-    channel_ = nullptr;  // LCOV_EXCL_LINE
-  }
-}
-
-// LCOV_EXCL_START
-int Port::ListenIOEvent() {
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-  channel_ = g_io_channel_unix_new(fd_);
-  if (channel_ == nullptr) {
-    _E("Failed to create GIOChannel");
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;
-  }
-
-  GSource* source = g_io_create_watch(channel_,
-      static_cast<GIOCondition>(G_IO_OUT));
-  if (source == nullptr) {
-    _E("Failed to create GSource");
-    IgnoreIOEvent();
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;
-  }
-
-  auto* ptr = new (std::nothrow) std::weak_ptr<Port>(shared_from_this());
-  g_source_set_callback(source, reinterpret_cast<GSourceFunc>(OnEventReceived),
-                        static_cast<gpointer>(ptr), [](gpointer ptr) {
-                          auto* port = static_cast<std::weak_ptr<Port>*>(ptr);
-                          delete port;
-                        });
-  g_source_set_priority(source, G_PRIORITY_DEFAULT);
-  source_id_ = g_source_attach(source,
-      MessageSendingThread::GetInst().GetContext());
-  g_source_unref(source);
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Port::PopDelayedMessage() {
-  int sent_bytes = 0;
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-  auto dm = queue_.front();
-
-  int ret = Write(dm->GetMessage(), dm->GetSize(), &sent_bytes);
-  if (ret == PORT_STATUS_ERROR_RESOURCE_UNAVAILABLE) {
-    dm->SetIndex(sent_bytes);
-  } else if (ret == PORT_STATUS_ERROR_IO_ERROR) {
-    ClearQueue();
-  } else {
-    delayed_message_size_ -= dm->GetOriginalSize();
-    queue_.pop();
-  }
-
-  _W("cache : count(%zu), delayed_message_size(%d), ret(%d), sent_bytes(%d)",
-      queue_.size(), delayed_message_size_, ret, sent_bytes);
-  return ret;
-}
-
-int Port::PushDelayedMessage(std::shared_ptr<DelayMessage> dm) {
-  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
-  if (queue_.empty()) {
-    int ret = ListenIOEvent();
-    if (ret != RPC_PORT_ERROR_NONE)
-      return ret;
-  }
-
-  delayed_message_size_ += dm->GetOriginalSize();
-  queue_.push(dm);
-
-  _W("cache : count(%zu), delayed_message_size(%d)",
-      queue_.size(), delayed_message_size_);
-  return RPC_PORT_ERROR_NONE;
-}
-// LCOV_EXCL_STOP
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/port-internal.hh b/src/port-internal.hh
deleted file mode 100644 (file)
index 64d33ec..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PORT_INTERNAL_HH_
-#define PORT_INTERNAL_HH_
-
-#include <gio/gio.h>
-#include <glib.h>
-
-#include <algorithm>
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <queue>
-#include <string>
-#include <thread>
-#include <vector>
-
-namespace rpc_port {
-namespace internal {
-
-class Port : public std::enable_shared_from_this<Port> {
- public:
-  Port(int fd, std::string id, std::string instance);
-  Port(int fd, std::string id);
-  virtual ~Port();
-
-  void Disconnect();
-  int SetPrivateSharing(const char* paths[], unsigned int size);
-  int SetPrivateSharing(const char* path);
-  int UnsetPrivateSharing();
-
-  int Read(void* buf, unsigned int size);
-  int Write(const void* buf, unsigned int size);
-  int Write(const void* buf, unsigned int size, int* sent_bytes);
-  int GetFd() const {
-    return fd_;
-  }
-
-  const std::string& GetId() const {
-    return id_;
-  }
-
-  std::recursive_mutex& GetMutex() const {
-    return mutex_;
-  }
-
-  const std::string& GetInstance() const {
-    return instance_;
-  }
-
-  uint32_t GetSeq() {
-    return ++seq_;
-  }
-
- private:
-  // LCOV_EXCL_START
-  int SetReceiveTimeout(int timeout);
-  bool CanWrite();
-  void IgnoreIOEvent();
-  int ListenIOEvent();
-
-  class DelayMessage {
-   public:
-    DelayMessage(const char* msg, int start_index, int size);
-    ~DelayMessage() = default;
-    void SetIndex(int index);
-    int GetSize();
-    int GetOriginalSize();
-    char* GetMessage();
-
-   private:
-    std::vector<unsigned char> message_;
-    int index_;
-    int size_;
-  };
-
-  enum PortStatus {
-    PORT_STATUS_ERROR_NONE,
-    PORT_STATUS_ERROR_IO_ERROR,
-    PORT_STATUS_ERROR_RESOURCE_UNAVAILABLE
-  };
-
-  int PushDelayedMessage(std::shared_ptr<DelayMessage> dm);
-  int PopDelayedMessage();
-  static gboolean OnEventReceived(GIOChannel* io,
-      GIOCondition condition, gpointer data);
-  void ClearQueue();
-  // LCOV_EXCL_STOP
-
-  int fd_;
-  std::string id_;
-  std::string instance_;
-  std::atomic<uint32_t> seq_;
-  mutable std::recursive_mutex mutex_;
-  mutable std::recursive_mutex rw_mutex_;
-  std::queue<std::shared_ptr<DelayMessage>> queue_;
-  int delayed_message_size_ = 0;
-  GIOChannel* channel_ = nullptr;
-  guint source_id_ = 0;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // PORT_INTERNAL_HH_
diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc
deleted file mode 100644 (file)
index cd52cd6..0000000
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <aul_svc.h>
-#include <dlog.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <uuid.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "aul-internal.hh"
-#include "debug-port-internal.hh"
-#include "exception-internal.hh"
-#include "include/rpc-port-internal.h"
-#include "log-private.hh"
-#include "proxy-internal.hh"
-#include "request-internal.hh"
-#include "response-internal.hh"
-
-#define EILLEGALACCESS 127
-
-namespace rpc_port {
-namespace internal {
-namespace {
-
-constexpr const char kPortTypeMain[] = "main";
-constexpr const char kPortTypeDelegate[] = "delegate";
-constexpr const char kDPrefix[] = "d::";
-constexpr const char kUdPrefix[] = "ud::";
-
-std::string GenInstance() {
-  uuid_t u;
-  uuid_generate(u);
-  char uuid[37];
-  uuid_unparse(u, uuid);
-  return std::string(uuid) + "@" + Aul::GetAppId(getpid());
-}
-
-int SendRequest(ClientSocket* client, const Request& request) {
-  tizen_base::Parcel parcel;
-  parcel.WriteParcelable(const_cast<Request&>(request));
-  size_t size = parcel.GetDataSize();
-  int ret = client->Send(reinterpret_cast<void*>(&size), sizeof(size));
-  if (ret != 0) {
-    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  ret = client->Send(parcel.GetData(), size);
-  if (ret != 0) {
-    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  return 0;
-}
-
-int ReceiveResponse(ClientSocket* client, Response** response) {
-  int flags = fcntl(client->GetFd(), F_GETFL, 0);
-  fcntl(client->GetFd(), F_SETFL, flags & ~O_NONBLOCK);
-
-  size_t size = 0;
-  int ret = client->Receive(reinterpret_cast<void*>(&size), sizeof(size));
-  if (ret != 0) {
-    // LCOV_EXCL_START
-    _E("Receive() is failed. error(%d)", ret);
-    fcntl(client->GetFd(), F_SETFL, flags);
-    return -1;
-    // LCOV_EXCL_STOP
-  }
-
-  uint8_t* buf = static_cast<uint8_t*>(malloc(size));
-  if (buf == nullptr) {
-    // LCOV_EXCL_START
-    _E("Out of memory");
-    fcntl(client->GetFd(), F_SETFL, flags);
-    return -1;
-    // LCOV_EXCL_STOP
-  }
-
-  ret = client->Receive(buf, size);
-  if (ret != 0) {
-    // LCOV_EXCL_START
-    _E("Receive() is failed. error(%d)", ret);
-    free(buf);
-    fcntl(client->GetFd(), F_SETFL, flags);
-    return -1;
-    // LCOV_EXCL_STOP
-  }
-
-  tizen_base::Parcel parcel(buf, size, false);
-  *response = new (std::nothrow) Response();
-  if (*response == nullptr) {
-    // LCOV_EXCL_START
-    _E("Out of memory");
-    fcntl(client->GetFd(), F_SETFL, flags);
-    return -1;
-    // LCOV_EXCL_STOP
-  }
-
-  parcel.ReadParcelable(*response);
-  fcntl(client->GetFd(), F_SETFL, flags);
-  return 0;
-}
-
-bool IsDaemon(const std::string& name) {
-  if (name.compare(0, strlen(kDPrefix), kDPrefix) == 0) return true;
-
-  if (name.compare(0, strlen(kUdPrefix), kUdPrefix) == 0) return true;
-
-  return false;
-}
-
-}  // namespace
-
-Proxy::Proxy() {
-  _D("Proxy::Proxy()");
-}
-
-Proxy::~Proxy() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  _D("Proxy::~Proxy()");
-  if (main_port_.get() != nullptr)
-    DebugPort::RemoveSession(main_port_->GetFd());  // LCOV_EXCL_LINE
-
-  listener_ = nullptr;
-  UnsetIdler();
-  UnsetConnTimer();
-  Cancel();
-}
-
-int Proxy::MainPortConnect(const std::string& instance, bool sync) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  fds_[0] = 0;
-  main_client_.reset(Client::Create(this, port_path_));
-  if (main_client_.get() == nullptr)
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-  Request request(instance.c_str(), kPortTypeMain);
-  int ret = SendRequest(main_client_.get(), request);
-  if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-  main_client_->SetNonblock();
-  if (sync) {
-    Response* response = nullptr;
-    ret = ReceiveResponse(main_client_.get(), &response);
-    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-    std::unique_ptr<Response> response_auto(response);
-    if (response->GetResult() != 0) {
-      _E("Permission denied");                  // LCOV_EXCL_LINE
-      return RPC_PORT_ERROR_PERMISSION_DENIED;  // LCOV_EXCL_LINE
-    }
-
-    fds_[0] = main_client_->RemoveFd();
-  } else {
-    ret = main_client_->Watch();
-    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Proxy::DelegatePortConnect(const std::string& instance, bool sync) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  fds_[1] = 0;
-  delegate_client_.reset(Client::Create(this, port_path_));
-  if (delegate_client_.get() == nullptr)
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-  Request request(instance.c_str(), kPortTypeDelegate);
-  int ret = SendRequest(delegate_client_.get(), request);
-  if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-  delegate_client_->SetNonblock();
-  if (sync) {
-    Response* response = nullptr;
-    ret = ReceiveResponse(delegate_client_.get(), &response);
-    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-    std::unique_ptr<Response> response_auto(response);
-    if (response->GetResult() != 0) {
-      _E("Permission denied");                  // LCOV_EXCL_LINE
-      return RPC_PORT_ERROR_PERMISSION_DENIED;  // LCOV_EXCL_LINE
-    }
-
-    fds_[1] = delegate_client_->RemoveFd();
-  } else {
-    ret = delegate_client_->Watch();
-    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Proxy::Connect(bool sync) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  std::string instance = GenInstance();
-  int ret = MainPortConnect(instance, sync);
-  if (ret != RPC_PORT_ERROR_NONE) return ret;
-
-  ret = DelegatePortConnect(instance, sync);
-  if (ret != RPC_PORT_ERROR_NONE) return ret;
-
-  if (sync) {
-    main_port_.reset(new ProxyPort(this, fds_[0], target_appid_, false));
-    delegate_port_.reset(new ProxyPort(this, fds_[1], target_appid_));
-    DebugPort::AddSession(port_name_, target_appid_, fds_[0], fds_[1]);
-    listener_->OnConnected(target_appid_, main_port_.get());
-  }
-
-  return ret;
-}
-
-int Proxy::Connect(std::string appid, std::string port_name,
-    IEventListener* listener) {
-  if (listener == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (HasRequested()) {
-    _D("Already requested");  // LCOV_EXCL_LINE
-    return RPC_PORT_ERROR_INVALID_PARAMETER;  // LCOV_EXCL_LINE
-  }
-
-  listener_ = listener;
-  target_appid_ = std::move(appid);
-  port_name_ = std::move(port_name);
-  SetRealAppId(target_appid_);
-  main_port_.reset();
-  delegate_port_.reset();
-  port_path_ =
-      Aul::GetPortPath(real_appid_, port_name_, rpc_port_get_target_uid());
-
-  Cancel();
-  UnsetConnTimer();
-  if (!IsDaemon(real_appid_)) {
-    int ret = Aul::PrepareStub(real_appid_, port_name_,
-        rpc_port_get_target_uid());
-    if (ret != RPC_PORT_ERROR_NONE) {
-      listener_ = nullptr;
-      return ret;
-    }
-  }
-
-  if (Watch() != 0) {
-    listener_ = nullptr;  // LCOV_EXCL_LINE
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-int Proxy::ConnectSync(std::string appid, std::string port_name,
-    IEventListener* listener) {
-  if (listener == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (HasRequested()) {
-    _D("Already requested");
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-  }
-
-  listener_ = listener;
-  target_appid_ = std::move(appid);
-  port_name_ = std::move(port_name);
-  SetRealAppId(target_appid_);
-  port_path_ =
-      Aul::GetPortPath(real_appid_, port_name_, rpc_port_get_target_uid());
-
-  if (!IsDaemon(real_appid_)) {
-    int ret = Aul::PrepareStub(real_appid_, port_name_,
-        rpc_port_get_target_uid());
-    if (ret != RPC_PORT_ERROR_NONE) {
-      listener_ = nullptr;
-      return ret;
-    }
-  }
-
-  if (!WaitUntilPortCreation())
-    return RPC_PORT_ERROR_IO_ERROR;
-
-  int ret = Connect(true);
-  if (ret != RPC_PORT_ERROR_NONE) {
-    // LCOV_EXCL_START
-    listener_ = nullptr;
-    return ret;
-    // LCOV_EXCL_STOP
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-bool Proxy::WaitUntilPortCreation() {
-  file_monitor_.reset(new FileMonitor(port_path_));
-  int retry_count = 100;
-  do {
-    if (file_monitor_->Exist()) return true;
-
-    usleep(100 * 1000);
-    retry_count--;
-  } while (retry_count > 0);
-
-  if (!file_monitor_->Exist()) {
-    // LCOV_EXCL_START
-    _E("port(%s) of appid(%s) is not ready",
-        port_name_.c_str(), target_appid_.c_str());
-    return false;
-    // LCOV_EXCL_STOP
-  }
-
-  return true;
-}
-
-void Proxy::DisconnectPort() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (main_port_.get() != nullptr) {
-    DebugPort::RemoveSession(main_port_->GetFd());
-    main_port_.reset();
-  }
-}
-
-int Proxy::Watch() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  try {
-    file_monitor_.reset(new FileMonitor(port_path_, this));
-    file_monitor_->Start();
-    SetConnTimer();
-    SetIdler();
-  } catch (const Exception& e) {
-    LOGE("Exception occurs. error(%s)", e.what());
-    return -1;
-  }
-
-  return 0;
-}
-
-void Proxy::Cancel() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (!file_monitor_) return;
-
-  file_monitor_->Stop();
-}
-
-void Proxy::SetRealAppId(const std::string& alias_appid) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (!real_appid_.empty())
-    return;
-
-  if (IsDaemon(alias_appid)) {
-    real_appid_ = alias_appid;
-    return;
-  }
-
-  char* appid = nullptr;
-  int ret = aul_svc_get_appid_by_alias_appid(alias_appid.c_str(), &appid);
-  if (ret != AUL_SVC_RET_OK) {
-    real_appid_ = alias_appid;
-    return;
-  }
-
-  // LCOV_EXCL_START
-  std::unique_ptr<char, decltype(std::free)*> appid_ptr(appid, std::free);
-  real_appid_ = std::string(appid);
-  _W("alias_appid(%s), real_appid(%s)", alias_appid.c_str(), appid);
-  // LCOV_EXCL_STOP
-}
-
-std::recursive_mutex& Proxy::GetMutex() const {
-  return mutex_;
-}
-
-void Proxy::SetConnTimer() {
-  if (conn_timer_data_) {
-    _W("Already exists");  // LCOV_EXCL_START
-    return;  // LCOV_EXCL_START
-  }
-
-  conn_timer_data_ = CreateWeakPtr();
-  if (conn_timer_data_ == nullptr) {
-    _E("Out of memory");  // LCOV_EXCL_START
-    return;  // LCOV_EXCL_START
-  }
-
-  g_timeout_add_seconds(10, OnTimedOut, conn_timer_data_);
-}
-
-void Proxy::UnsetConnTimer() {
-  if (conn_timer_data_ == nullptr)
-    return;
-
-  GSource* source = g_main_context_find_source_by_user_data(nullptr,
-      conn_timer_data_);
-  if (source && !g_source_is_destroyed(source))
-    g_source_destroy(source);
-
-  DestroyWeakPtr(conn_timer_data_);
-  conn_timer_data_ = nullptr;
-}
-
-void Proxy::SetIdler() {
-  if (idler_data_) {
-    _W("Already exists");  // LCOV_EXCL_START
-    return;  // LCOV_EXCL_START
-  }
-
-  idler_data_ = CreateWeakPtr();
-  if (idler_data_ == nullptr) {
-    _E("Out of memory");  // LCOV_EXCL_START
-    return;  // LCOV_EXCL_START
-  }
-
-  g_idle_add(OnIdle, idler_data_);
-}
-
-void Proxy::UnsetIdler() {
-  if (idler_data_ == nullptr)
-    return;
-
-  GSource* source = g_main_context_find_source_by_user_data(nullptr,
-      idler_data_);
-  if (source && !g_source_is_destroyed(source))
-    g_source_destroy(source);
-
-  DestroyWeakPtr(idler_data_);
-  idler_data_ = nullptr;
-}
-
-void Proxy::OnFileCreated(const std::string& path) {
-  _W("appid=%s, port_name=%s, port_path=%s",
-      target_appid_.c_str(), port_name_.c_str(), path.c_str());
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  UnsetIdler();
-  Cancel();
-  if (listener_ == nullptr) return;  // LCOV_EXCL_LINE
-
-  int ret = Connect(false);
-  if (ret != RPC_PORT_ERROR_NONE) {
-    // LCOV_EXCL_START
-    UnsetConnTimer();
-    auto* listener = listener_;
-    listener_ = nullptr;
-    if (ret == RPC_PORT_ERROR_PERMISSION_DENIED)
-      listener->OnRejected(target_appid_, ret);
-    else
-      listener->OnDisconnected(target_appid_);
-    // LCOV_EXCL_STOP
-  }
-}
-
-void Proxy::OnFileDeleted(const std::string& path) {
-  _W("appid=%s, port_name=%s, port_path=%s",
-      target_appid_.c_str(), port_name_.c_str(), path.c_str());
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  UnsetIdler();
-}
-
-gboolean Proxy::OnTimedOut(gpointer user_data) {
-  _E("Timed out");
-  auto* ptr = static_cast<std::weak_ptr<Proxy>*>(user_data);
-  auto proxy = ptr->lock();
-  if (proxy == nullptr) {
-    _E("Proxy is nullptr");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  if (proxy->conn_timer_data_ == nullptr) {
-    _E("Invalid context. proxy(%p)", proxy.get());  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  proxy->Cancel();
-  proxy->main_client_.reset();
-  proxy->delegate_client_.reset();
-  DestroyWeakPtr(proxy->conn_timer_data_);
-  proxy->conn_timer_data_ = nullptr;
-
-  auto* listener = proxy->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  proxy->listener_ = nullptr;
-  listener->OnRejected(proxy->target_appid_, RPC_PORT_ERROR_IO_ERROR);
-  return G_SOURCE_REMOVE;
-}
-
-gboolean Proxy::OnIdle(gpointer user_data) {
-  auto* ptr = static_cast<std::weak_ptr<Proxy>*>(user_data);
-  auto proxy = ptr->lock();
-  if (proxy == nullptr) {
-    _E("Proxy is nullptr");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  if (proxy->idler_data_ == nullptr) {
-    _E("Invalid context. proxy(%p)", proxy.get());  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  DestroyWeakPtr(proxy->idler_data_);
-  proxy->idler_data_ = nullptr;
-
-  if (proxy->file_monitor_->Exist()) {
-    proxy->OnFileCreated(proxy->port_path_);
-  } else {
-    proxy->OnFileDeleted(proxy->port_path_);
-  }
-
-  return G_SOURCE_REMOVE;
-}
-
-Proxy::ProxyPort::ProxyPort(Proxy* parent, int fd, const std::string& id,
-    bool receive)
-    : Port(fd, id), parent_(parent) {
-  Watch(receive);
-}
-
-Proxy::ProxyPort::~ProxyPort() {
-  if (disconn_source_ > 0)
-    g_source_remove(disconn_source_);
-
-  if (source_ > 0)
-    g_source_remove(source_);
-
-  if (channel_ != nullptr)
-    g_io_channel_unref(channel_);
-}
-
-int Proxy::ProxyPort::Watch(bool receive) {
-  channel_ = g_io_channel_unix_new(GetFd());
-  if (channel_ == nullptr) {
-    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  disconn_source_ = g_io_add_watch(channel_,
-      static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
-      Proxy::ProxyPort::OnSocketDisconnected, parent_);
-  if (disconn_source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  if (!receive)
-    return 0;
-
-  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
-      Proxy::ProxyPort::OnDataReceived, parent_);
-  if (source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  return 0;
-}
-
-void Proxy::ProxyPort::SetDisconnectedSource(guint source_id) {
-  disconn_source_ = source_id;
-}
-
-void Proxy::ProxyPort::SetSource(guint source_id) {
-  source_ = source_id;
-}
-
-gboolean Proxy::ProxyPort::OnSocketDisconnected(GIOChannel* channel,
-    GIOCondition cond, gpointer user_data) {
-  auto* proxy = static_cast<Proxy*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  auto* listener = proxy->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  int fd = g_io_channel_unix_get_fd(channel);
-  _W("Socket was disconnected. fd(%d)", fd);
-  if (proxy->main_port_.get() != nullptr &&
-      proxy->main_port_->GetFd() == fd) {
-    proxy->main_port_->SetDisconnectedSource(0);
-  } else if (proxy->delegate_port_.get() != nullptr &&
-             proxy->delegate_port_->GetFd() == fd) {
-    proxy->delegate_port_->SetDisconnectedSource(0);
-  }
-
-  proxy->main_port_.reset();
-  proxy->delegate_port_.reset();
-  proxy->listener_ = nullptr;
-  listener->OnDisconnected(proxy->target_appid_);
-  DebugPort::RemoveSession(fd);
-  return G_SOURCE_REMOVE;
-}
-
-gboolean Proxy::ProxyPort::OnDataReceived(GIOChannel* channel,
-    GIOCondition cond, gpointer user_data) {
-  auto* proxy = static_cast<Proxy*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  auto* listener = proxy->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  int fd = g_io_channel_unix_get_fd(channel);
-  if (proxy->delegate_port_->GetFd() == fd) {
-    char buffer[4];
-    if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
-      _W("Socket was disconnected by stub. fd(%d)", fd);
-      proxy->listener_ = nullptr;
-      proxy->delegate_port_->SetSource(0);
-      if (proxy->main_port_.get() != nullptr) {
-        DebugPort::RemoveSession(proxy->main_port_->GetFd());
-        proxy->main_port_.reset();
-      }
-      proxy->delegate_port_.reset();
-      listener->OnDisconnected(proxy->target_appid_);
-      return G_SOURCE_REMOVE;
-    }
-
-    listener->OnReceived(proxy->target_appid_);
-  }
-
-  return G_SOURCE_CONTINUE;
-}
-
-Proxy::Client::Client(Proxy* parent) : parent_(parent) {
-}
-
-Proxy::Client::~Client() {
-  if (channel_)
-    g_io_channel_unref(channel_);
-
-  if (disconn_source_ > 0)
-    g_source_remove(disconn_source_);
-
-  if (source_ > 0)
-    g_source_remove(source_);
-}
-
-Proxy::Client* Proxy::Client::Create(Proxy* parent,
-    const std::string& endpoint) {
-  std::unique_ptr<Proxy::Client> client;
-  try {
-    client.reset(new (std::nothrow) Proxy::Client(parent));
-  } catch (const Exception& e) {
-    _E("Exception(%s) occurs", e.what());  // LCOV_EXCL_LINE
-    return nullptr;  // LCOV_EXCL_LINE
-  }
-
-  int ret;
-  int retry_count = 5;
-  do {
-    ret = client->Connect(endpoint);
-    if (ret == 0) {
-      break;
-    } else if (ret < 0) {
-      // LCOV_EXCL_START
-      _D("Connect() is failed");
-      usleep(100 * 1000);
-      retry_count--;
-      // LCOV_EXCL_STOP
-    }
-  } while (retry_count > 0);
-
-  if (ret != 0) {
-    _E("Connect() is failed");  // LCOV_EXCL_LINE
-    return nullptr;  // LCOV_EXCL_LINE
-  }
-
-  try {
-    client->SetReceiveTimeout(10000);
-  } catch (const Exception& e) {
-    _E("Exception occurs. error(%s)", e.what());  // LCOV_EXCL_LINE
-    return nullptr;  // LCOV_EXCL_LINE
-  }
-
-  _W("endpoint(%s), fd(%d)", endpoint.c_str(), client->GetFd());
-  return client.release();
-}
-
-int Proxy::Client::Watch() {
-  channel_ = g_io_channel_unix_new(GetFd());
-  if (channel_ == nullptr) {
-    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
-      Proxy::Client::OnResponseReceived, parent_);
-  if (source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  disconn_source_ = g_io_add_watch(channel_,
-      static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
-      Proxy::Client::OnSocketDisconnected, parent_);
-  if (disconn_source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  return 0;
-}
-
-// LCOV_EXCL_START
-void Proxy::Client::SetDisconnectedSource(guint source) {
-  disconn_source_ = source;
-}
-// LCOV_EXCL_STOP
-
-void Proxy::Client::SetSource(guint source) {
-  source_ = source;
-}
-
-// LCOV_EXCL_START
-gboolean Proxy::Client::OnSocketDisconnected(GIOChannel* channel,
-    GIOCondition cond, gpointer user_data) {
-  auto* proxy = static_cast<Proxy*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  proxy->UnsetConnTimer();
-  auto* listener = proxy->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");
-    return G_SOURCE_REMOVE;
-  }
-
-  int fd = g_io_channel_unix_get_fd(channel);
-  _W("Socket was disconnected. fd(%d)", fd);
-  if (proxy->main_client_.get() != nullptr &&
-      proxy->main_client_->GetFd() == fd) {
-    proxy->main_client_->SetDisconnectedSource(0);
-  } else if (proxy->delegate_client_.get() != nullptr &&
-             proxy->delegate_client_->GetFd() == fd) {
-    proxy->delegate_client_->SetDisconnectedSource(0);
-  }
-
-  proxy->main_client_.reset();
-  proxy->delegate_client_.reset();
-  proxy->listener_ = nullptr;
-  listener->OnDisconnected(proxy->target_appid_);
-  return G_SOURCE_REMOVE;
-}
-// LCOV_EXCL_STOP
-
-gboolean Proxy::Client::OnResponseReceived(GIOChannel* channel,
-    GIOCondition cond, gpointer user_data) {
-  auto* proxy = static_cast<Proxy*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  proxy->UnsetConnTimer();
-  auto* listener = proxy->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  bool is_delegate = false;
-  std::unique_ptr<Client> client;
-  int fd = g_io_channel_unix_get_fd(channel);
-  if (proxy->main_client_.get() != nullptr &&
-      proxy->main_client_->GetFd() == fd) {
-    client.reset(proxy->main_client_.release());
-  } else if (proxy->delegate_client_.get() != nullptr &&
-             proxy->delegate_client_->GetFd() == fd) {
-    client.reset(proxy->delegate_client_.release());
-    is_delegate = true;
-  }
-
-  if (client.get() == nullptr) {
-    _E("Unknown fd(%d)", fd);  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  client->SetSource(0);
-
-  Response* response = nullptr;
-  int ret = ReceiveResponse(client.get(), &response);
-  if (ret != 0) {
-    // LCOV_EXCL_START
-    proxy->listener_ = nullptr;
-    proxy->main_client_.reset();
-    proxy->delegate_client_.reset();
-    listener->OnRejected(proxy->target_appid_, RPC_PORT_ERROR_IO_ERROR);
-    return G_SOURCE_REMOVE;
-    // LCOV_EXCL_STOP
-  }
-
-  std::unique_ptr<Response> response_auto(response);
-  if (response->GetResult() != 0) {
-    _E("Permission denied");
-    proxy->listener_ = nullptr;
-    proxy->main_client_.reset();
-    proxy->delegate_client_.reset();
-    listener->OnRejected(proxy->target_appid_,
-        RPC_PORT_ERROR_PERMISSION_DENIED);
-    return G_SOURCE_REMOVE;
-  }
-
-  client->SetNonblock();
-  int client_fd = client->RemoveFd();
-  if (is_delegate) {
-    _W("[DELEGATE] Result received");
-    proxy->fds_[1] = client_fd;
-    proxy->delegate_port_.reset(
-        new ProxyPort(proxy, proxy->fds_[1], proxy->target_appid_));
-  } else {
-    _W("[MAIN] Result received");
-    proxy->fds_[0] = client_fd;
-    proxy->main_port_.reset(
-        new ProxyPort(proxy, proxy->fds_[0], proxy->target_appid_, false));
-  }
-
-  if (proxy->main_port_.get() != nullptr &&
-      proxy->delegate_port_.get() != nullptr) {
-    _W("target_appid(%s), port_name(%s), main_fd(%d), delegate_fd(%d)",
-        proxy->target_appid_.c_str(), proxy->port_name_.c_str(),
-        proxy->fds_[0], proxy->fds_[1]);
-
-    DebugPort::AddSession(proxy->port_name_, proxy->target_appid_,
-        proxy->fds_[0], proxy->fds_[1]);
-    listener->OnConnected(proxy->target_appid_, proxy->main_port_.get());
-  }
-
-  return G_SOURCE_REMOVE;
-}
-
-std::shared_ptr<Proxy> Proxy::GetSharedPtr() {
-  return shared_from_this();
-}
-
-gpointer Proxy::CreateWeakPtr() {
-  auto* ptr = new (std::nothrow) std::weak_ptr<Proxy>(GetSharedPtr());
-  return static_cast<gpointer>(ptr);
-}
-
-void Proxy::DestroyWeakPtr(gpointer data) {
-  auto* ptr = static_cast<std::weak_ptr<Proxy>*>(data);
-  delete ptr;
-}
-
-bool Proxy::HasRequested() const {
-  return listener_ != nullptr &&
-      (!main_port_ || !delegate_port_ || main_port_->GetFd() > 0);
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/proxy-internal.hh b/src/proxy-internal.hh
deleted file mode 100644 (file)
index 2ef4dcc..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PROXY_INTERNAL_HH_
-#define PROXY_INTERNAL_HH_
-
-#include <aul_rpc_port.h>
-#include <gio/gio.h>
-#include <glib-unix.h>
-#include <glib.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-
-#include "client-socket-internal.hh"
-#include "file-monitor-internal.hh"
-#include "port-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-class Proxy : public std::enable_shared_from_this<Proxy>,
-              public FileMonitor::IEvent {
- public:
-  Proxy();
-  virtual ~Proxy();
-
-  class IEventListener {
-   public:
-    virtual void OnConnected(const std::string& endpoint, Port* port) = 0;
-    virtual void OnDisconnected(const std::string& endpoint) = 0;
-    virtual void OnRejected(const std::string& endpoint, int err_code) = 0;
-    virtual void OnReceived(const std::string& endpoint) = 0;
-  };
-
-  int Connect(std::string appid, std::string port_name, IEventListener* ev);
-  int ConnectSync(std::string appid, std::string port_name, IEventListener* ev);
-  void DisconnectPort();
-
-  std::shared_ptr<Port> GetPort() const {
-    return main_port_;
-  }
-
-  std::shared_ptr<Port> GetDelegatePort() const {
-    return delegate_port_;
-  }
-
-  const std::string& GetPortName() {
-    return port_name_;
-  }
-
- private:
-  class ProxyPort : public Port {
-   public:
-    ProxyPort(Proxy* parent, int fd, const std::string& id,
-        bool receive = true);
-    virtual ~ProxyPort();
-    void SetDisconnectedSource(guint source_id);
-    void SetSource(guint source_id);
-
-   private:
-    int Watch(bool receive);
-
-    static gboolean OnSocketDisconnected(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-    static gboolean OnDataReceived(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-
-   private:
-    Proxy* parent_ = nullptr;
-    GIOChannel* channel_ = nullptr;
-    guint disconn_source_ = 0;
-    guint source_ = 0;
-  };
-
-  class Client : public ClientSocket {
-   public:
-    explicit Client(Proxy* parent);
-    virtual ~Client();
-
-    static Client* Create(Proxy* parent, const std::string& endpoint);
-
-    int Watch();
-    void SetDisconnectedSource(guint source);
-    void SetSource(guint source);
-
-   private:
-    static gboolean OnSocketDisconnected(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-    static gboolean OnResponseReceived(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-
-   private:
-    Proxy* parent_;
-    GIOChannel* channel_ = nullptr;
-    guint disconn_source_ = 0;
-    guint source_ = 0;
-  };
-
- private:
-  void OnFileCreated(const std::string& path) override;
-  void OnFileDeleted(const std::string& path) override;
-  static gboolean OnTimedOut(gpointer user_data);
-  static gboolean OnIdle(gpointer user_data);
-
-  void SetRealAppId(const std::string& alias_appid);
-  std::recursive_mutex& GetMutex() const;
-  int MainPortConnect(const std::string& instance, bool sync);
-  int DelegatePortConnect(const std::string& instance, bool sync);
-  int Connect(bool sync);
-  bool WaitUntilPortCreation();
-  int Watch();
-  void Cancel();
-  void SetConnTimer();
-  void UnsetConnTimer();
-  void SetIdler();
-  void UnsetIdler();
-
-  std::shared_ptr<Proxy> GetSharedPtr();
-  gpointer CreateWeakPtr();
-  static void DestroyWeakPtr(gpointer data);
-  bool HasRequested() const;
-
- private:
-  std::string port_name_;
-  std::string port_path_;
-  std::shared_ptr<ProxyPort> main_port_;
-  std::shared_ptr<ProxyPort> delegate_port_;
-  IEventListener* listener_ = nullptr;
-  std::string target_appid_;
-  std::string real_appid_;
-  int fds_[2];
-  std::unique_ptr<Client> main_client_;
-  std::unique_ptr<Client> delegate_client_;
-  gpointer conn_timer_data_ = nullptr;
-  gpointer idler_data_ = nullptr;
-  mutable std::recursive_mutex mutex_;
-  std::unique_ptr<FileMonitor> file_monitor_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // PROXY_INTERNAL_HH_
diff --git a/src/request-internal.cc b/src/request-internal.cc
deleted file mode 100644 (file)
index c293c29..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "request-internal.hh"
-
-#include <utility>
-
-namespace rpc_port {
-namespace internal {
-
-Request::Request(std::string instance, std::string port_type)
-    : instance_(std::move(instance)),
-      port_type_(std::move(port_type)) {
-}
-
-void Request::SetPortType(std::string port_type) {
-  port_type_ = std::move(port_type);
-}
-
-const std::string& Request::GetInstance() {
-  return instance_;
-}
-
-const std::string& Request::GetPortType() {
-  return port_type_;
-}
-
-void Request::WriteToParcel(tizen_base::Parcel* parcel) const {
-  parcel->WriteString(instance_);
-  parcel->WriteString(port_type_);
-}
-
-void Request::ReadFromParcel(tizen_base::Parcel* parcel) {
-  instance_ = parcel->ReadString();
-  port_type_ = parcel->ReadString();
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/request-internal.hh b/src/request-internal.hh
deleted file mode 100644 (file)
index 3aa9b05..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef REQUEST_INTERNAL_HH_
-#define REQUEST_INTERNAL_HH_
-
-#include <parcel.hh>
-#include <parcelable.hh>
-
-#include <string>
-
-namespace rpc_port {
-namespace internal {
-
-class Request : public tizen_base::Parcelable {
- public:
-  Request(std::string instance, std::string port_type);
-  Request() = default;
-  ~Request() = default;
-
-  void SetPortType(std::string port_type);
-  const std::string& GetInstance();
-  const std::string& GetPortType();
-
-  void WriteToParcel(tizen_base::Parcel* parcel) const override;
-  void ReadFromParcel(tizen_base::Parcel* parcel) override;
-
- private:
-  std::string instance_;
-  std::string port_type_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // REQUEST_INTERNAL_HH_
diff --git a/src/response-internal.cc b/src/response-internal.cc
deleted file mode 100644 (file)
index 9d32604..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "response-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-Response::Response(int result) : result_(result) {
-}
-
-Response::Response() : result_(0) {
-}
-
-int Response::GetResult() {
-  return result_;
-}
-
-void Response::WriteToParcel(tizen_base::Parcel* parcel) const {
-  parcel->WriteInt32(result_);
-}
-
-void Response::ReadFromParcel(tizen_base::Parcel* parcel) {
-  parcel->ReadInt32(&result_);
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/response-internal.hh b/src/response-internal.hh
deleted file mode 100644 (file)
index 2c12ab2..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RESPONSE_INTERNAL_HH_
-#define RESPONSE_INTERNAL_HH_
-
-#include <parcel.hh>
-#include <parcelable.hh>
-
-namespace rpc_port {
-namespace internal {
-
-class Response : public tizen_base::Parcelable {
- public:
-  explicit Response(int result);
-  Response();
-  ~Response() = default;
-
-  int GetResult();
-
-  void WriteToParcel(tizen_base::Parcel* parcel) const override;
-  void ReadFromParcel(tizen_base::Parcel* parcel) override;
-
- private:
-  int result_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // RESPONSE_INTERNAL_HH_
diff --git a/src/rpc-port-internal.cc b/src/rpc-port-internal.cc
deleted file mode 100644 (file)
index ba78616..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <aul_proc.h>
-#include <sys/types.h>
-#include <tzplatform_config.h>
-#include <unistd.h>
-
-#include <atomic>
-
-#include "include/rpc-port-internal.h"
-#include "include/rpc-port.h"
-#include "peer-cred-internal.hh"
-#include "port-internal.hh"
-
-#undef RPC_API
-#define RPC_API extern "C" __attribute__((visibility("default")))
-
-namespace {
-using namespace rpc_port::internal;
-
-constexpr uid_t kRegularUidMin = 5000;
-std::atomic<uid_t> __target_uid { getuid() };
-
-}  // namespace
-
-RPC_API void rpc_port_set_target_uid(uid_t target_uid) {
-  __target_uid.exchange(target_uid);
-  set_last_result(RPC_PORT_ERROR_NONE);
-}
-
-RPC_API uid_t rpc_port_get_target_uid(void) {
-  if (__target_uid < kRegularUidMin)
-    __target_uid.exchange(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
-
-  return __target_uid;
-}
-
-RPC_API int rpc_port_register_proc_info(const char* proc_name, bundle* extra) {
-  if (proc_name == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  int ret = aul_proc_register(proc_name, extra);
-  if (ret != AUL_R_OK)
-    return RPC_PORT_ERROR_IO_ERROR;
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_deregister_proc_info(void) {
-  int ret = aul_proc_deregister();
-  if (ret != AUL_R_OK)
-    return RPC_PORT_ERROR_IO_ERROR;
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int  rpc_port_get_peer_info(rpc_port_h h, pid_t* pid, uid_t* uid) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-  std::shared_ptr<PeerCred> cred(PeerCred::Get(port->GetFd()));
-  if (cred.get() == nullptr)
-    return RPC_PORT_ERROR_IO_ERROR;
-
-  if (pid)
-    *pid = cred->GetPid();
-
-  if (uid)
-    *uid = cred->GetUid();
-
-  return RPC_PORT_ERROR_NONE;
-}
-
diff --git a/src/rpc-port-parcel.cc b/src/rpc-port-parcel.cc
deleted file mode 100644 (file)
index e78b6da..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (c) 2018 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "include/rpc-port-parcel.h"
-
-#include <parcel.hh>
-#include <stdint.h>
-#include <string.h>
-
-#include <memory>
-
-#include "log-private.hh"
-#include "parcel-internal.hh"
-#include "port-internal.hh"
-
-#define MAX_PARCEL_SIZE   (1024 * 1024 * 10)
-
-#undef RPC_API
-#define RPC_API extern "C" __attribute__((visibility("default")))
-
-using namespace rpc_port;
-
-RPC_API int rpc_port_parcel_create(rpc_port_parcel_h* h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = new (std::nothrow) internal::Parcel();
-  if (parcel == nullptr)
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;
-
-  *h = static_cast<rpc_port_parcel_h>(parcel);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h* h,
-    rpc_port_h port) {
-  int len;
-  unsigned char* buf;
-
-  if (h == nullptr || port == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  internal::Port* pt = static_cast<internal::Port*>(port);
-  {
-    std::lock_guard<std::recursive_mutex> lock(pt->GetMutex());
-    int ret = rpc_port_read(port, &len, 4);
-    if (ret != 0)
-      return ret;
-
-    if (len <= 0 || len > MAX_PARCEL_SIZE)
-      return RPC_PORT_ERROR_IO_ERROR;
-
-    buf = static_cast<unsigned char*>(malloc(len));
-    if (buf == nullptr) {
-      _E("Out of memory");  // LCOV_EXCL_LINE
-      return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-    }
-
-    ret = rpc_port_read(port, buf, len);
-    if (ret != 0) {
-      free(buf);  // LCOV_EXCL_LINE
-      return ret;  // LCOV_EXCL_LINE
-    }
-  }
-
-  auto* parcel = new (std::nothrow) internal::Parcel();
-  if (parcel == nullptr) {
-    // LCOV_EXCL_START
-    _E("Out of memory");
-    free(buf);
-    return RPC_PORT_ERROR_IO_ERROR;
-    // LCOV_EXCL_STOP
-  }
-
-  tizen_base::Parcel raw_parcel(buf, len, false);
-  raw_parcel.ReadParcelable(parcel);
-  *h = static_cast<rpc_port_parcel_h>(parcel);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_send(rpc_port_parcel_h h, rpc_port_h port) {
-  if (h == nullptr || port == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  tizen_base::Parcel raw_parcel;
-  raw_parcel.WriteParcelable(*parcel);
-  void* raw = reinterpret_cast<void*>(raw_parcel.GetData());
-  uint32_t len = static_cast<uint32_t>(raw_parcel.GetDataSize());
-  if (len <= 0)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  internal::Port* pt = static_cast<internal::Port*>(port);
-  {
-    std::lock_guard<std::recursive_mutex> lock(pt->GetMutex());
-    int ret = rpc_port_write(port, &len, sizeof(len));
-    if (ret != 0)
-      return ret;
-
-    ret = rpc_port_write(port, raw, len);
-    if (ret != 0)
-      return ret;
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_destroy(rpc_port_parcel_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  delete parcel;
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_byte(parcel->GetHandle(), b);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_int16(parcel->GetHandle(), i);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_int32(parcel->GetHandle(), i);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_int64(parcel->GetHandle(), i);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_float(parcel->GetHandle(), f);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_double(parcel->GetHandle(), d);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char* str) {
-  if (h == nullptr || str == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_string(parcel->GetHandle(), str);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_bool(parcel->GetHandle(), b);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle* b) {
-  if (h == nullptr || b == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  bundle_raw* raw = nullptr;
-  int len = 0;
-  bundle_encode(b, &raw, &len);
-  auto ptr = std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free);
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_string(parcel->GetHandle(), reinterpret_cast<char*>(raw));
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_write_int32(parcel->GetHandle(), count);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_write(rpc_port_parcel_h h,
-    rpc_port_parcelable_t* parcelable, void* data) {
-  if (parcelable == nullptr || parcelable->to == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  parcelable->to(h, data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char* b) {
-  if (h == nullptr || b == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_byte(parcel->GetHandle(), b);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read_byte() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short* i) {
-  if (h == nullptr || i == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_int16(parcel->GetHandle(), i);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read_int16() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int* i) {
-  if (h == nullptr || i == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_int32(parcel->GetHandle(), i);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read_int32() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long* i) {
-  if (h == nullptr || i == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int64_t val = 0;
-  int ret = parcel_read_int64(parcel->GetHandle(), &val);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read_int64() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  *i = static_cast<long long>(val);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_float(rpc_port_parcel_h h, float* f) {
-  if (h == nullptr || f == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_float(parcel->GetHandle(), f);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read_float() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_double(rpc_port_parcel_h h, double* d) {
-  if (h == nullptr || d == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_double(parcel->GetHandle(), d);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read_double() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char** str) {
-  if (h == nullptr || str == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_string(parcel->GetHandle(), str);
-  if (ret != PARCEL_ERROR_NONE) {
-    _E("parcel_read_string() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    *str = strdup("");  // LCOV_EXCL_LINE
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool* b) {
-  if (h == nullptr || b == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_bool(parcel->GetHandle(), b);
-  if (ret != 0)
-    _E("parcel_read_bool() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle** b) {
-  if (h == nullptr || b == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  char* raw = nullptr;
-  int ret = parcel_read_string(parcel->GetHandle(), &raw);
-  if (ret != 0) {
-    _E("parcel_read_string() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    *b = bundle_create();  // LCOV_EXCL_LINE
-  } else {
-    *b = bundle_decode(reinterpret_cast<bundle_raw*>(raw), strlen(raw));
-    std::free(raw);
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int* count) {
-  if (h == nullptr || count == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  int ret = parcel_read_int32(parcel->GetHandle(), count);
-  if (ret != 0)
-    _E("parcel_read_int32() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_read(rpc_port_parcel_h h,
-    rpc_port_parcelable_t* parcelable, void* data) {
-  if (parcelable == nullptr || parcelable->from == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  parcelable->from(h, data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_burst_read(rpc_port_parcel_h h, unsigned char *buf,
-    unsigned int size) {
-  if (h == nullptr || buf == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  uint32_t valid_size = size & UINT32_MAX;
-  int ret = parcel_burst_read(parcel->GetHandle(), static_cast<void*>(buf),
-      valid_size);
-  if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_read() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_burst_write(rpc_port_parcel_h h,
-    const unsigned char *buf, unsigned int size) {
-  if (h == nullptr || buf == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  uint32_t valid_size = size & UINT32_MAX;
-  parcel_burst_write(parcel->GetHandle(), static_cast<const void*>(buf),
-      valid_size);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_reset_reader(rpc_port_parcel_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  parcel_reset_reader(parcel->GetHandle());
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_to_array(rpc_port_parcel_h h, void** array,
-    unsigned int* size) {
-  if (h == nullptr || !array || !size)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  tizen_base::Parcel raw_parcel;
-  raw_parcel.WriteParcelable(*parcel);
-  void* raw = raw_parcel.GetData();
-  size_t raw_size = raw_parcel.GetDataSize();
-  if (raw_size == 0) {
-    _E("raw_size is zero");
-    return RPC_PORT_ERROR_IO_ERROR;
-  }
-
-  void* array_ptr = malloc(raw_size);
-  if (array_ptr == nullptr)
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;
-
-  memcpy(array_ptr, raw, raw_size);
-  *array = array_ptr;
-  *size = static_cast<unsigned int>(raw_size);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_from_array(rpc_port_parcel_h h, const void* array,
-    unsigned int size) {
-  if (h == nullptr || array == nullptr || size == 0)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  uint32_t valid_size = size & UINT32_MAX;
-  tizen_base::Parcel raw_parcel(array, valid_size);
-  raw_parcel.ReadParcelable(parcel);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_get_header(rpc_port_parcel_h h,
-    rpc_port_parcel_header_h* header) {
-  if (h == nullptr || header == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  auto* parcel_header = parcel->GetParcelHeader();
-  if (parcel_header == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  *header = reinterpret_cast<rpc_port_parcel_header_h>(
-      const_cast<internal::ParcelHeader*>(parcel_header));
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_header_set_tag(rpc_port_parcel_header_h header,
-    const char* tag) {
-  if (header == nullptr || tag == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
-  parcel_header->SetTag(tag);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_header_get_tag(rpc_port_parcel_header_h header,
-    char** tag) {
-  if (header == nullptr || tag == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
-  const std::string& raw_tag = parcel_header->GetTag();
-
-  *tag = strdup(raw_tag.c_str());
-  if (*tag == nullptr)
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_header_set_seq_num(rpc_port_parcel_header_h header,
-    int seq_num) {
-  if (header == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
-  parcel_header->SetSeqNum(seq_num);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_header_get_seq_num(rpc_port_parcel_header_h header,
-    int* seq_num) {
-  if (header == nullptr || seq_num == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
-  *seq_num = parcel_header->GetSeqNum();
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_header_get_timestamp(
-    rpc_port_parcel_header_h header, struct timespec* timestamp) {
-  if (header == nullptr || timestamp == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
-  *timestamp = parcel_header->GetTimeStamp();
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_get_raw(rpc_port_parcel_h h, void** raw,
-    unsigned int* size) {
-  if (h == nullptr || raw == nullptr || size == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = static_cast<internal::Parcel*>(h);
-  auto* raw_parcel = new (std::nothrow) tizen_base::Parcel();
-  if (raw_parcel != nullptr) {
-    raw_parcel->WriteParcelable(*parcel);
-    parcel->SetRawParcel(raw_parcel);
-    *raw = raw_parcel->GetData();
-    *size = static_cast<unsigned int>(raw_parcel->GetDataSize());
-  } else {
-    // LCOV_EXCL_START
-    _E("Out of memory");
-    *raw = nullptr;
-    *size = 0;
-    // LCOV_EXCL_STOP
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_create_from_raw(rpc_port_parcel_h* h,
-    const void* raw, unsigned int size) {
-  if (h == nullptr || raw == nullptr || size == 0)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  rpc_port_parcel_h parcel;
-  int ret = rpc_port_parcel_create(&parcel);
-  if (ret != RPC_PORT_ERROR_NONE)
-    return ret;
-
-  ret = rpc_port_parcel_from_array(parcel, raw, size);
-  if (ret != RPC_PORT_ERROR_NONE) {
-    rpc_port_parcel_destroy(parcel);  // LCOV_EXCL_LINE
-    return ret;  // LCOV_EXCL_LINE
-  }
-
-  *h = parcel;
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_parcel_create_without_header(rpc_port_parcel_h* h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto* parcel = new (std::nothrow) internal::Parcel(true);
-  if (parcel == nullptr)
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;
-
-  *h = static_cast<rpc_port_parcel_h>(parcel);
-  return RPC_PORT_ERROR_NONE;
-}
diff --git a/src/rpc-port.cc b/src/rpc-port.cc
deleted file mode 100644 (file)
index 023a9ab..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "include/rpc-port.h"
-
-#include <aul.h>
-#include <aul_rpc_port.h>
-#include <glib.h>
-
-#include <atomic>
-#include <mutex>
-#include <thread>
-#include <utility>
-
-#include "include/rpc-port-internal.h"
-#include "log-private.hh"
-#include "port-internal.hh"
-#include "proxy-internal.hh"
-#include "stub-internal.hh"
-
-#undef RPC_API
-#define RPC_API extern "C" __attribute__((visibility("default")))
-
-namespace {
-using namespace rpc_port::internal;
-
-template<typename T>
-class Event {
- public:
-  Event(T cb, void* user_data)
-      : cb_(cb), user_data_(user_data) {}
-
-  T cb_;
-  void* user_data_;
-};
-
-class ProxyExt : public Proxy, public Proxy::IEventListener {
- public:
-  ProxyExt() : Proxy(), destroying_(false) {}
-  virtual ~ProxyExt() = default;
-
-  void AddConnectedEventListener(rpc_port_proxy_connected_event_cb cb,
-                            void* user_data) {
-    connected_events_.emplace_back(
-        new Event<rpc_port_proxy_connected_event_cb>(cb, user_data));
-  }
-
-  void AddDisconnectedEventListener(rpc_port_proxy_disconnected_event_cb cb,
-                                    void* user_data) {
-    disconnected_events_.emplace_back(
-        new Event<rpc_port_proxy_disconnected_event_cb>(cb, user_data));
-  }
-
-  void AddRejectedEventListener(rpc_port_proxy_rejected_event_cb cb,
-                                void* user_data) {
-    rejected_events_.emplace_back(
-        new Event<rpc_port_proxy_rejected_event_cb>(cb, user_data));
-  }
-
-  void AddReceivedEventListener(rpc_port_proxy_received_event_cb cb,
-                                void* user_data) {
-    received_events_.emplace_back(
-        new Event<rpc_port_proxy_received_event_cb>(cb, user_data));
-  }
-
-  void OnConnected(const std::string& endpoint, Port* port) override {
-    if (IsDestroying())
-      return;
-
-    for (auto& ev : connected_events_) {
-      ev->cb_(endpoint.c_str(), GetPortName().c_str(), port,
-              ev->user_data_);
-    }
-  }
-
-  void OnDisconnected(const std::string& endpoint) override {
-    if (IsDestroying())
-      return;
-
-    for (auto& ev : disconnected_events_) {
-      ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_);
-    }
-  }
-
-  void OnRejected(const std::string& endpoint, int err_code) override {
-    if (IsDestroying())
-      return;
-
-    for (auto& ev : rejected_events_) {
-      set_last_result(err_code);
-      ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_);
-    }
-  }
-
-  void OnReceived(const std::string& endpoint) override {
-    if (IsDestroying())
-      return;
-
-    for (auto& ev : received_events_) {
-      ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_);
-    }
-  }
-
-  std::recursive_mutex& GetMutex() const {
-    return mutex_;
-  }
-
-  void SetDestroying(bool destroying) {
-    destroying_ = destroying;
-  }
-
-  bool IsDestroying() {
-    return destroying_;
-  }
-
- private:
-  std::atomic<bool> destroying_;
-  std::list<std::unique_ptr<Event<rpc_port_proxy_connected_event_cb>>>
-      connected_events_;
-  std::list<std::unique_ptr<Event<rpc_port_proxy_disconnected_event_cb>>>
-      disconnected_events_;
-  std::list<std::unique_ptr<Event<rpc_port_proxy_rejected_event_cb>>>
-      rejected_events_;
-  std::list<std::unique_ptr<Event<rpc_port_proxy_received_event_cb>>>
-      received_events_;
-  mutable std::recursive_mutex mutex_;
-};
-
-class StubExt : public Stub, public Stub::IEventListener {
- public:
-  explicit StubExt(const std::string& port) : Stub(port), destroying_(false) {}
-  virtual ~StubExt() = default;
-
-  void AddConnectedEventListener(rpc_port_stub_connected_event_cb cb,
-                                 void* user_data) {
-    connected_events_.emplace_back(
-        new Event<rpc_port_stub_connected_event_cb>(cb, user_data));
-  }
-
-  void AddDisconnectedEventListener(rpc_port_stub_disconnected_event_cb cb,
-                                    void* user_data) {
-    disconnected_events_.emplace_back(
-        new Event<rpc_port_stub_disconnected_event_cb>(cb, user_data));
-  }
-
-  void AddReceivedEventListener(rpc_port_stub_received_event_cb cb,
-                                void* user_data) {
-    received_events_.emplace_back(
-        new Event<rpc_port_stub_received_event_cb>(cb, user_data));
-  }
-
-  void OnConnected(const std::string& sender,
-                   const std::string& instance) override {
-    if (IsDestroying())
-      return;
-
-    for (auto& ev : connected_events_) {
-      ev->cb_(sender.c_str(), instance.c_str(), ev->user_data_);
-    }
-  }
-
-  void OnDisconnected(const std::string& sender,
-                      const std::string& instance) override {
-    if (IsDestroying())
-      return;
-
-    for (auto& ev : disconnected_events_) {
-      ev->cb_(sender.c_str(), instance.c_str(), ev->user_data_);
-    }
-  }
-
-  int OnReceived(const std::string& sender,
-                 const std::string& instance, Port* port) override {
-    if (IsDestroying())
-      return -1;
-
-    for (auto& ev : received_events_) {
-      int ret = ev->cb_(sender.c_str(), instance.c_str(), port,
-          ev->user_data_);
-      if (ret != 0)
-        return -1;
-    }
-
-    return 0;
-  }
-
-  void SetDestroying(bool destroying) {
-    destroying_ = destroying;
-  }
-
-  bool IsDestroying() {
-    return destroying_;
-  }
-
-  std::recursive_mutex& GetMutex() const {
-    return mutex_;
-  }
-
- private:
-  std::atomic<bool> destroying_;
-  std::list<std::unique_ptr<Event<rpc_port_stub_connected_event_cb>>>
-      connected_events_;
-  std::list<std::unique_ptr<Event<rpc_port_stub_disconnected_event_cb>>>
-      disconnected_events_;
-  std::list<std::unique_ptr<Event<rpc_port_stub_received_event_cb>>>
-      received_events_;
-  mutable std::recursive_mutex mutex_;
-};
-
-}  // namespace
-
-RPC_API int rpc_port_read(rpc_port_h h, void* buf, unsigned int size) {
-  if (h == nullptr || buf == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-  uint32_t seq = 0;
-  if (DebugPort::IsConnected()) {
-    int ret = port->Read(reinterpret_cast<uint32_t*>(&seq), sizeof(seq));
-    if (ret < 0) {
-      _E("IO Error");
-      return ret;
-    }
-  }
-
-  int ret = port->Read(buf, size);
-  if (ret < 0) {
-    _E("IO Error");
-    return ret;
-  }
-
-  if (DebugPort::IsConnected())
-    DebugPort::Send(port->GetFd(), true, seq, buf, size);
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_write(rpc_port_h h, const void* buf, unsigned int size) {
-  if (h == nullptr || buf == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-  uint32_t seq = port->GetSeq();
-  if (DebugPort::IsConnected()) {
-    int ret = port->Write(reinterpret_cast<void*>(&seq), sizeof(seq));
-    if (ret < 0)
-      return ret;
-  }
-
-  int ret = port->Write(buf, size);
-  if (ret < 0)
-    return ret;
-
-  if (DebugPort::IsConnected())
-    DebugPort::Send(port->GetFd(), false, seq, buf, size);
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_create(rpc_port_proxy_h* h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = new (std::nothrow) std::shared_ptr<::ProxyExt>(
-      new (std::nothrow) ::ProxyExt());
-  if (p == nullptr) {
-    _E("Out of memory");  // LCOV_EXCL_LINE
-  } else if (p->get() == nullptr) {
-    // LCOV_EXCL_START
-    _E("Out of memory");
-    delete p;
-    p = nullptr;
-    // LCOV_EXCL_STOP
-  } else {
-    _W("rpc_port_proxy_create(%p)", p->get());
-  }
-
-  *h = p;
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  if (proxy->IsDestroying()) {
-    _E("already destroyed. handle(%p)", proxy);  // LCOV_EXCL_LINE
-    abort();  // LCOV_EXCL_LINE
-  }
-
-  _W("rpc_port_proxy_destroy(%p)", proxy);
-  proxy->SetDestroying(true);
-  proxy->DisconnectPort();
-
-  g_idle_add_full(G_PRIORITY_HIGH,
-      [](gpointer data) -> gboolean {
-        auto p = static_cast<std::shared_ptr<::ProxyExt>*>(data);
-        _W("rpc_port_proxy_destroy(%p)", p->get());
-        delete p;
-        return G_SOURCE_REMOVE;
-      }, h, nullptr);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char* appid,
-    const char* port) {
-  if (h == nullptr || appid == nullptr || port == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  _W("rpc_port_proxy_connect(%p, %s, %s)", proxy, appid, port);
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  return proxy->Connect(appid, port, proxy);
-}
-
-// LCOV_EXCL_START
-RPC_API int rpc_port_proxy_connect_sync(rpc_port_proxy_h h, const char* appid,
-    const char* port) {
-  if (h == nullptr || appid == nullptr || port == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  _W("rpc_port_proxy_connect(%p, %s, %s)", proxy, appid, port);
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  return proxy->ConnectSync(appid, port, proxy);
-}
-// LCOV_EXCL_STOP
-
-RPC_API int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h,
-    rpc_port_proxy_connected_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  proxy->AddConnectedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h,
-    rpc_port_proxy_disconnected_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  proxy->AddDisconnectedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h,
-    rpc_port_proxy_rejected_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  proxy->AddRejectedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h,
-    rpc_port_proxy_received_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  proxy->AddReceivedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_proxy_get_port(rpc_port_proxy_h h,
-    rpc_port_port_type_e type, rpc_port_h* port) {
-  if (h == nullptr || port == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
-  auto* proxy = p->get();
-  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
-  rpc_port_h ret_port;
-
-  switch (type) {
-    case RPC_PORT_PORT_MAIN:
-      ret_port = static_cast<rpc_port_h>(proxy->GetPort().get());
-      if (ret_port == nullptr)
-        return RPC_PORT_ERROR_IO_ERROR;
-      *port = ret_port;
-      break;
-    case RPC_PORT_PORT_CALLBACK:
-      ret_port = static_cast<rpc_port_h>(proxy->GetDelegatePort().get());
-      if (ret_port == nullptr)
-        return RPC_PORT_ERROR_IO_ERROR;
-      *port = ret_port;
-      break;
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_create(rpc_port_stub_h* h, const char* port_name) {
-  if (h == nullptr || port_name == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = new ::StubExt(port_name);
-  *h = p;
-  _W("rpc_port_stub_create(%p, %s)", p, port_name);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  _W("rpc_port_stub_destroy(%p)", h);
-  auto p = static_cast<::StubExt*>(h);
-  if (p->IsDestroying()) {
-    _E("already destroyed. handle(%p)", h);  // LCOV_EXCL_LINE
-    abort();  // LCOV_EXCL_LINE
-  }
-
-  p->SetDestroying(true);
-  aul_rpc_port_usr_destroy(p->GetPortName().c_str(), rpc_port_get_target_uid());
-  p->Ignore();
-  g_idle_add_full(G_PRIORITY_HIGH,
-      [](gpointer data) -> gboolean {
-        auto p = static_cast<::StubExt*>(data);
-        _W("rpc_port_stub_destroy(%p)", p);
-        delete p;
-        return G_SOURCE_REMOVE;
-      }, h, nullptr);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  _W("rpc_port_stub_listen(%p)", h);
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-
-  int fd = p->CreatePort();
-  if (fd < 0)
-    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
-
-  return p->Listen(p, fd);
-}
-
-RPC_API int rpc_port_stub_add_privilege(rpc_port_stub_h h,
-    const char* privilege) {
-  if (h == nullptr || privilege == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-
-  p->AddPrivilege(privilege);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_set_trusted(rpc_port_stub_h h,
-    const bool trusted) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-
-  p->SetTrusted(trusted);
-  return RPC_PORT_ERROR_NONE;
-}
-
-
-RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h,
-    rpc_port_stub_connected_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-
-  p->AddConnectedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h,
-    rpc_port_stub_disconnected_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-
-  p->AddDisconnectedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h,
-    rpc_port_stub_received_event_cb cb, void* user_data) {
-  if (h == nullptr || cb == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-
-  p->AddReceivedEventListener(cb, user_data);
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_stub_get_port(rpc_port_stub_h h,
-    rpc_port_port_type_e type, const char* instance, rpc_port_h* port) {
-  if (h == nullptr || port == nullptr || instance == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto p = static_cast<::StubExt*>(h);
-  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
-  rpc_port_h ret_port;
-
-  switch (type) {
-    case RPC_PORT_PORT_MAIN:
-      ret_port = static_cast<rpc_port_h>(p->FindPort(instance).get());
-      if (ret_port == nullptr)
-        return RPC_PORT_ERROR_IO_ERROR;
-      *port = ret_port;
-      break;
-    case RPC_PORT_PORT_CALLBACK:
-      ret_port = static_cast<rpc_port_h>(p->FindDelegatePort(instance).get());
-      if (ret_port == nullptr)
-        return RPC_PORT_ERROR_IO_ERROR;
-      *port = ret_port;
-      break;
-  }
-
-  return RPC_PORT_ERROR_NONE;
-}
-
-RPC_API int rpc_port_set_private_sharing_array(rpc_port_h h,
-    const char* paths[], unsigned int size) {
-  if (h == nullptr || paths == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-
-  return port->SetPrivateSharing(paths, size);
-}
-
-RPC_API int rpc_port_set_private_sharing(rpc_port_h h, const char* path) {
-  if (h == nullptr || path == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-
-  return port->SetPrivateSharing(path);
-}
-
-RPC_API int rpc_port_unset_private_sharing(rpc_port_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-
-  return port->UnsetPrivateSharing();
-}
-
-RPC_API int rpc_port_disconnect(rpc_port_h h) {
-  if (h == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  auto port = static_cast<Port*>(h);
-  port->Disconnect();
-
-  return RPC_PORT_ERROR_NONE;
-}
diff --git a/src/rpc-port/CMakeLists.txt b/src/rpc-port/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fdee107
--- /dev/null
@@ -0,0 +1,37 @@
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} RPC_PORT_SRCS)
+
+ADD_LIBRARY(${TARGET_RPC_PORT} SHARED ${RPC_PORT_SRCS})
+SET_TARGET_PROPERTIES(${TARGET_RPC_PORT} PROPERTIES SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${TARGET_RPC_PORT} PROPERTIES VERSION ${FULLVER})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_RPC_PORT} PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
+
+APPLY_PKG_CONFIG(${TARGET_RPC_PORT} PUBLIC
+  AUL_DEPS
+  BUNDLE_DEPS
+  CYNARA_CLIENT_DEPS
+  CYNARA_CREDS_SOCKET_DEPS
+  DLOG_DEPS
+  GIO_DEPS
+  GIO_UNIX_DEPS
+  GLIB_DEPS
+  LIBSYSTEMD_DEPS
+  LIBTZPLATFORM_CONFIG_DEPS
+  PARCEL_DEPS
+  PKGMGR_INFO_DEPS
+  TIZEN_SHARED_QUEUE_DEPS
+  UUID_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_RPC_PORT} PUBLIC "-Wl,-z,nodelete")
+
+INSTALL(TARGETS ${TARGET_RPC_PORT} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../include/
+  DESTINATION include/rpc-port
+  FILES_MATCHING
+  PATTERN "*.h"
+)
diff --git a/src/rpc-port/ac-internal.cc b/src/rpc-port/ac-internal.cc
new file mode 100644 (file)
index 0000000..4a746bb
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ac-internal.hh"
+
+#include <aul.h>
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#include <cynara-error.h>
+#include <dlog.h>
+#include <pkgmgr-info.h>
+
+#include <utility>
+
+#include "aul-internal.hh"
+#include "cynara_thread.hh"
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace internal {
+namespace {
+
+constexpr const uid_t kRegularUidMin = 5000;
+
+class Cynara {
+ public:
+  class Creds {
+   public:
+    Creds(int fd, std::string user, std::string client)
+        : fd_(fd), user_(std::move(user)), client_(std::move(client)) {
+      _W("client(%s), user(%s), fd(%d)", client_.c_str(), user_.c_str(), fd);
+    }
+
+    int GetFd() const { return fd_; }
+
+    const std::string& GetUser() const { return user_; }
+
+    const std::string& GetClient() const { return client_; }
+
+   private:
+    int fd_;
+    std::string user_;
+    std::string client_;
+  };
+
+  Cynara() : handle_(nullptr, cynara_finish) {
+    cynara* handle = nullptr;
+    if (cynara_initialize(&handle, nullptr) != CYNARA_API_SUCCESS) {
+      _E("cynara_initialize() is failed");  // LCOV_EXCL_LINE
+    } else {
+      handle_.reset(handle);
+    }
+  }
+
+  ~Cynara() = default;
+
+  std::shared_ptr<Creds> FetchCredsFromSocket(int fd) {
+    char* user = nullptr;
+    int ret = cynara_creds_socket_get_user(fd, USER_METHOD_DEFAULT, &user);
+    if (ret != CYNARA_API_SUCCESS) {
+      // LCOV_EXCL_START
+      char buf[128] = { 0, };
+      cynara_strerror(ret, buf, sizeof(buf));
+      _E("cynara_creds_socket_get_user() is failed. fd(%d), error(%d:%s)",
+         fd, ret, buf);
+      return nullptr;
+      // LCOV_EXCL_STOP
+    }
+    auto user_auto = std::unique_ptr<char, decltype(free)*>(user, free);
+
+    char* client = nullptr;
+    ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_DEFAULT, &client);
+    if (ret != CYNARA_API_SUCCESS) {
+      // LCOV_EXCL_START
+      char buf[128] = { 0, };
+      cynara_strerror(ret, buf, sizeof(buf));
+      _E("cynara_creds_socket_get_client() is failed. fd(%d), error(%d:%s)",
+          fd, ret, buf);
+      return nullptr;
+      // LCOV_EXCL_STOP
+    }
+    auto client_auto = std::unique_ptr<char, decltype(free)*>(client, free);
+
+    return std::make_shared<Creds>(fd, user, client);
+  }
+
+  int Check(const std::shared_ptr<Creds>& creds,
+            const std::string& privilege) const {
+    std::lock_guard<std::recursive_mutex> lock(mutex_);
+    _W("cynara_check() ++ privilege(%s), user(%s)",
+        privilege.c_str(), creds->GetUser().c_str());
+    int ret = cynara_check(handle_.get(), creds->GetClient().c_str(), "",
+                           creds->GetUser().c_str(), privilege.c_str());
+    _W("cynara_check() -- privilege(%s), user(%s)",
+        privilege.c_str(), creds->GetUser().c_str());
+    if (ret != CYNARA_API_ACCESS_ALLOWED) {
+      _E("cynara_check() is not allowed. privilege(%s), error(%d)",
+         privilege.c_str(), ret);
+      return -1;
+    }
+
+    return 0;
+  }
+
+ private:
+  std::unique_ptr<cynara, decltype(cynara_finish)*> handle_;
+  mutable std::recursive_mutex mutex_;
+};
+
+Cynara cynara_inst;
+
+}  // namespace
+
+void AccessController::AddPrivilege(std::string privilege) {
+  privileges_.push_back(std::move(privilege));
+}
+
+void AccessController::SetTrusted(const bool trusted) {
+  trusted_ = trusted;
+}
+
+int AccessController::CheckPrivilege(int fd) {
+  auto creds = cynara_inst.FetchCredsFromSocket(fd);
+  if (creds == nullptr) return -1;
+
+  for (const auto& privilege : privileges_) {
+    if (cynara_inst.Check(creds, privilege) != 0)
+      return -1;
+  }
+
+  return 0;
+}
+
+// LCOV_EXCL_START
+int AccessController::CheckTrusted(const std::string& sender_appid) {
+  if (getuid() < kRegularUidMin)
+    return 0;
+
+  if (appid_.empty())
+    appid_ = Aul::GetAppId(getpid());
+
+  _D("CheckCertificate : %s :: %s", appid_.c_str(), sender_appid.c_str());
+  pkgmgrinfo_cert_compare_result_type_e res;
+  int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(appid_.c_str(),
+      sender_appid.c_str(), getuid(), &res);
+  if (ret < 0) {
+    _E("CheckCertificate() Failed");
+    return -1;
+  }
+  if (res != PMINFO_CERT_COMPARE_MATCH) {
+    _E("CheckCertificate() Failed : Certificate Not Matched");
+    return -1;
+  }
+
+  return 0;
+}
+// LCOV_EXCL_STOP
+
+int AccessController::Check(int fd, const std::string& sender_appid) {
+  int ret = 0;
+  if (!privileges_.empty()) {
+    ret = CheckPrivilege(fd);
+    if (ret != 0)
+      return ret;
+  }
+
+  if (trusted_)
+    ret = CheckTrusted(sender_appid);
+
+  return ret;
+}
+
+void AccessController::CheckAsync(int fd, std::string sender_appid,
+    CompleteCallback callback) {
+  /* This is for handle freed issue */
+  auto* tmp_handle = new std::shared_ptr<AccessController>(shared_from_this());
+  Job job([=]() -> Job::Type {
+    if ((*tmp_handle).use_count() == 1) {
+      delete tmp_handle;  // LCOV_EXCL_LINE
+      return Job::Type::Continue;  // LCOV_EXCL_LINE
+    }
+
+    int res = Check(fd, sender_appid);
+    auto* cbdata = new std::pair<CompleteCallback, int>(
+        std::move(callback), res);
+    guint sid = g_idle_add(
+        [](gpointer data) -> gboolean {
+          auto* cb_data = static_cast<std::pair<CompleteCallback, int>*>(data);
+          auto [callback, res] = *cb_data;
+          callback(res);
+          delete cb_data;
+          return G_SOURCE_REMOVE;
+        }, cbdata);
+    if (sid == 0) {
+      _E("Failed to call g_idle_add");  // LCOV_EXCL_LINE
+      delete cbdata;  // LCOV_EXCL_LINE
+    }
+
+    delete tmp_handle;
+    return Job::Type::Continue;
+  });
+
+  CynaraThread::GetInst().Push(std::move(job));
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/ac-internal.hh b/src/rpc-port/ac-internal.hh
new file mode 100644 (file)
index 0000000..0b48d5c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AC_INTERNAL_HH_
+#define AC_INTERNAL_HH_
+
+#include <gio/gio.h>
+#include <glib-unix.h>
+#include <glib.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace rpc_port {
+namespace internal {
+
+using CompleteCallback = std::function<void(int)>;
+
+class AccessController : public std::enable_shared_from_this<AccessController> {
+ public:
+  explicit AccessController(bool trusted = false) : trusted_(trusted) {}
+
+  void AddPrivilege(std::string privilege);
+  void SetTrusted(const bool trusted);
+  int Check(int fd, const std::string& sender_appid);
+  void CheckAsync(int fd, std::string sender_appid, CompleteCallback callback);
+
+ private:
+  int CheckTrusted(const std::string& sender_appid);
+  int CheckPrivilege(int fd);
+
+ private:
+  std::vector<std::string> privileges_;
+  std::map<std::string, bool> cache_;
+  bool trusted_;
+  std::string appid_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // AC_INTERNAL_HH_
diff --git a/src/rpc-port/aul-internal.cc b/src/rpc-port/aul-internal.cc
new file mode 100644 (file)
index 0000000..628cd5f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aul.h>
+#include <aul_rpc_port.h>
+#include <aul_proc.h>
+
+#include <memory>
+
+#include "aul-internal.hh"
+#include "include/rpc-port.h"
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace internal {
+
+std::string Aul::GetName(int pid) {
+  char* name = nullptr;
+  if (aul_proc_get_name(pid, &name) != AUL_R_OK) return "";
+
+  std::unique_ptr<char, decltype(std::free)*> name_auto(name, std::free);
+  return std::string(name);
+}
+
+std::string Aul::GetAppId(int pid) {
+  char app_id[256] = { 0, };
+  int ret = aul_app_get_appid_bypid(pid, app_id, sizeof(app_id));
+  if (ret != AUL_R_OK) {
+    // LCOV_EXCL_START
+    _E("aul_app_get_appid_bypid() is failed. pid(%d), error(%d)", pid, ret);
+    return GetName(pid);
+    // LCOV_EXCL_STOP
+  }
+
+  return std::string(app_id);
+}
+
+std::string Aul::GetPortPath(const std::string& app_id,
+    const std::string& port_name, uid_t uid) {
+  char* port_path = nullptr;
+  int ret = aul_rpc_port_usr_get_path(app_id.c_str(), port_name.c_str(), uid,
+      &port_path);
+  if (ret != AUL_R_OK) {
+    _E("aul_rpc_port_usr_get_path() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return {};  // LCOV_EXCL_LINE
+  }
+
+  std::unique_ptr<char, decltype(std::free)*> ptr(port_path, std::free);
+  return std::string(port_path);
+}
+
+int Aul::PrepareStub(const std::string& app_id, const std::string& port_name,
+    uid_t uid) {
+  int ret = aul_rpc_port_usr_prepare_stub(app_id.c_str(), port_name.c_str(),
+      uid);
+  if (ret != AUL_R_OK) {
+    _E("aul_rpc_port_usr_prepare_stub() is failed. error(%d)", ret);
+    if (ret == AUL_R_EILLACC)
+      return RPC_PORT_ERROR_PERMISSION_DENIED;
+
+    return RPC_PORT_ERROR_IO_ERROR;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+bool Aul::ExistPort(const std::string& app_id, const std::string& port_name,
+    uid_t uid) {
+  bool exist = false;
+  int ret = aul_rpc_port_usr_exist(app_id.c_str(), port_name.c_str(), uid,
+      &exist);
+  if (ret != AUL_R_OK)
+    _W("aul_rpc_port_usr_exist() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return exist;
+}
+
+void Aul::NotifyRpcFinished() {
+  int ret = aul_rpc_port_notify_rpc_finished();
+  if (ret != AUL_R_OK)
+    _W("aul_rpc_port_notify_rpc_finished() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/aul-internal.hh b/src/rpc-port/aul-internal.hh
new file mode 100644 (file)
index 0000000..3d74be4
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUL_INTERNAL_HH_
+#define AUL_INTERNAL_HH_
+
+#include <string>
+
+namespace rpc_port {
+namespace internal {
+
+class Aul {
+ public:
+  static std::string GetName(int pid);
+  static std::string GetAppId(int pid);
+  static std::string GetPortPath(const std::string& app_id,
+      const std::string& port_name, uid_t uid);
+  static int PrepareStub(const std::string& app_id,
+      const std::string& port_name, uid_t uid);
+  static bool ExistPort(const std::string& app_id, const std::string& port_name,
+      uid_t uid);
+  static void NotifyRpcFinished();
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // AUL_INTERNAL_HH_
diff --git a/src/rpc-port/client-socket-internal.cc b/src/rpc-port/client-socket-internal.cc
new file mode 100644 (file)
index 0000000..9a71b4e
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "client-socket-internal.hh"
+#include "exception-internal.hh"
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace internal {
+
+ClientSocket::ClientSocket() {
+  fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+  if (fd_ < 0) {
+    // LCOV_EXCL_START
+    fd_ = -errno;
+    _E("socket() is failed. errno(%d)", errno);
+    THROW(fd_);
+    // LCOV_EXCL_STOP
+  }
+}
+
+ClientSocket::ClientSocket(int fd) : fd_(fd) {
+  SetCloseOnExec();
+}
+
+ClientSocket::~ClientSocket() {
+  if (!IsClosed())
+    Close();
+}
+
+void ClientSocket::SetCloseOnExec() {
+  int flags = fcntl(fd_, F_GETFL, 0);
+  fcntl(fd_, F_SETFL, flags | FD_CLOEXEC);
+  _I("Close on exec. fd(%d)", fd_);
+}
+
+void ClientSocket::Close() {
+  if (fd_ > -1) {
+    close(fd_);
+    fd_ = -1;
+  }
+}
+
+int ClientSocket::Connect(const std::string& endpoint) {
+  int flag = fcntl(GetFd(), F_GETFL, 0);
+  fcntl(GetFd(), F_SETFL, flag | O_NONBLOCK);
+
+  struct sockaddr_un sockaddr = { 0, };
+  sockaddr.sun_family = AF_UNIX;
+  snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
+      endpoint.c_str());
+  struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
+  socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
+  int ret = connect(GetFd(), sockaddr_ptr, len);
+  fcntl(GetFd(), F_SETFL, flag);
+  if (ret < 0) {
+    // LCOV_EXCL_START
+    ret = -errno;
+    _E("connect() is failed. errno(%d)", errno);
+    return ret;
+    // LCOV_EXCL_STOP
+  }
+
+  return 0;
+}
+
+int ClientSocket::Send(const void* buf, unsigned int size) {
+  const unsigned char* buffer = static_cast<const unsigned char*>(buf);
+  size_t len = size;
+  while (len) {
+    ssize_t bytes = send(GetFd(), buffer, len, MSG_NOSIGNAL);
+    if (bytes < 0) {
+      // LCOV_EXCL_START
+      int ret = -errno;
+      _E("send() is failed. fd(%d), errno(%d)", GetFd(), errno);
+      return ret;
+      // LCOV_EXCL_STOP
+    }
+
+    len -= bytes;
+    buffer += bytes;
+  }
+
+  return 0;
+}
+
+int ClientSocket::Receive(void* buf, unsigned int size) {
+  unsigned char* buffer = static_cast<unsigned char*>(buf);
+  size_t len = size;
+  while (len) {
+    ssize_t bytes = read(GetFd(), buffer, len);
+    if (bytes == 0) {
+      _W("EOF. fd(%d)", GetFd());  // LCOV_EXCL_START
+      return -EIO;  // LCOV_EXCL_STOP
+    }
+
+    if (bytes < 0) {
+      if (errno == EINTR) {
+        usleep(100 * 1000);
+        continue;
+      }
+
+      return -errno;  // LCOV_EXCL_LINE
+    }
+
+    len -= bytes;
+    buffer += bytes;
+  }
+
+  return 0;
+}
+
+void ClientSocket::SetReceiveTimeout(int timeout) {
+  if (timeout == INT_MAX)
+    return;  // LCOV_EXCL_LINE
+
+  if (timeout == -1)
+    timeout = 5000;
+
+  if (timeout < 0) {
+    _E("Invalid parameter");  // LCOV_EXCL_LINE
+    THROW(-EINVAL);  // LCOV_EXCL_LINE
+  }
+
+  struct timeval tv = {
+    .tv_sec = static_cast<time_t>(timeout / 1000),
+    .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000)
+  };
+  socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
+  int ret = setsockopt(GetFd(), SOL_SOCKET, SO_RCVTIMEO, &tv, len);
+  if (ret < 0) {
+    // LCOV_EXCL_START
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+    // LCOV_EXCL_STOP
+  }
+}
+
+bool ClientSocket::IsClosed() {
+  return fd_ < 0 ? true : false;
+}
+
+int ClientSocket::GetFd() const {
+  return fd_;
+}
+
+int ClientSocket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
+void ClientSocket::SetNonblock() {
+  int flag = fcntl(GetFd(), F_GETFL, 0);
+  fcntl(GetFd(), F_SETFL, flag | O_NONBLOCK);
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/client-socket-internal.hh b/src/rpc-port/client-socket-internal.hh
new file mode 100644 (file)
index 0000000..d033b2e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLIENT_SOCKET_INTERNAL_HH_
+#define CLIENT_SOCKET_INTERNAL_HH_
+
+#include <string>
+
+namespace rpc_port {
+namespace internal {
+
+class ClientSocket {
+ public:
+  ClientSocket();
+  explicit ClientSocket(int fd);
+  virtual ~ClientSocket();
+
+  void Close();
+  int Connect(const std::string& endpoint);
+  int Send(const void* buf, unsigned int size);
+  int Receive(void* buf, unsigned int size);
+  void SetReceiveTimeout(int timeout);
+  bool IsClosed();
+  int GetFd() const;
+  int RemoveFd();
+  void SetNonblock();
+  void SetCloseOnExec();
+
+ private:
+  int fd_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // CLIENT_SOCKET_INTERNAL_HH_
diff --git a/src/rpc-port/cynara_thread.cc b/src/rpc-port/cynara_thread.cc
new file mode 100644 (file)
index 0000000..a5a2f67
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cynara_thread.hh"
+
+#include <utility>
+
+namespace rpc_port {
+namespace internal {
+
+Job::Job(Job::JobHandlerCallback cb) : cb_(std::move(cb)) {}
+
+Job::Type Job::Do() {
+  if (cb_ == nullptr)
+    return Job::Type::Finish;
+
+  return cb_();
+}
+
+CynaraThread& CynaraThread::GetInst() {
+  static CynaraThread* inst = new CynaraThread();
+  return *inst;
+}
+
+CynaraThread::CynaraThread() {
+  thread_ = std::thread([this]() { ThreadRun(); });
+}
+
+// LCOV_EXCL_START
+CynaraThread::~CynaraThread() {
+  queue_.Push(Job());
+  thread_.join();
+}
+// LCOV_EXCL_STOP
+
+void CynaraThread::ThreadRun() {
+  while (true) {
+    Job job = queue_.WaitAndPop();
+    if (job.Do() == Job::Type::Finish)
+      return;  // LCOV_EXCL_LINE
+  }
+}
+
+void CynaraThread::Push(Job job) {
+  queue_.Push(std::move(job));
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/cynara_thread.hh b/src/rpc-port/cynara_thread.hh
new file mode 100644 (file)
index 0000000..3babdd3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CYNARA_THREAD_HH_
+#define CYNARA_THREAD_HH_
+
+#include <functional>
+#include <shared-queue.hpp>
+#include <thread>
+
+namespace rpc_port {
+namespace internal {
+
+class Job {
+ public:
+  enum class Type {
+    Continue = 0,
+    Finish = 1,
+  };
+
+  using JobHandlerCallback = std::function<Type(void)>;
+
+  explicit Job(JobHandlerCallback cb = nullptr);
+
+  ~Job() = default;
+
+  Type Do();
+
+ private:
+  JobHandlerCallback cb_;
+};
+
+class CynaraThread {
+ public:
+  static CynaraThread& GetInst();
+  CynaraThread(CynaraThread&) = delete;
+  CynaraThread& operator=(CynaraThread&) = delete;
+  ~CynaraThread();
+
+  void ThreadRun();
+  void Push(Job job);
+
+ private:
+  CynaraThread();
+  Job Pop();
+
+  std::thread thread_;
+  mutable tizen_base::SharedQueue<Job> queue_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // CYNARA_THREAD_HH_
diff --git a/src/rpc-port/debug-port-internal.cc b/src/rpc-port/debug-port-internal.cc
new file mode 100644 (file)
index 0000000..eabe432
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "debug-port-internal.hh"
+
+#include <aul_app_com.h>
+#include <bundle_internal.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <parcel.hh>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <time.h>
+
+#include <atomic>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <utility>
+
+#include <shared-queue.hpp>
+
+#include "log-private.hh"
+#include "port-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+namespace {
+
+constexpr const char PATH_RPC_PORT_UTIL_SOCK[] =
+    "/run/aul/daemons/.rpc-port-util-sock";
+constexpr const char ENDPOINT_RPC_PORT_DEBUG[] = "org.tizen.rpcport.debug";
+constexpr const char KEY_PORT_NAME[] = "__K_PORT_NAME__";
+
+class Session {
+ public:
+  Session(std::string port_name, std::string destination,
+      int main_port, int delegate_port)
+      : port_name_(std::move(port_name)),
+        destination_(std::move(destination)),
+        main_port_(main_port),
+        delegate_port_(delegate_port) {
+  }
+
+  const std::string& GetPortName() const {
+    return port_name_;
+  }
+
+  const std::string& GetDestination() const {
+    return destination_;
+  }
+
+  int GetMainPort() const {
+    return main_port_;
+  }
+
+  int GetDelegatePort() const {
+    return delegate_port_;
+  }
+
+ private:
+  std::string port_name_;
+  std::string destination_;
+  int main_port_;
+  int delegate_port_;
+};
+
+class DebugPortImpl {
+ public:
+  DebugPortImpl() = default;
+  ~DebugPortImpl();
+
+  void Dispose();
+  bool IsConnected() const;
+  void AddSession(std::string port_name, std::string destination,
+      int main_port, int delegate_port);
+  void RemoveSession(int port);
+  int Send(int port, bool is_read, uint32_t seq,
+      const void* buf, unsigned int size);
+  void Init();
+
+ private:
+  int Connect();
+  int Watch(int fd);
+  void Unwatch();
+  void SetConnectionStatus(bool status);
+  void CreateThread();
+  void JoinThread();
+
+  std::recursive_mutex& GetMutex() const;
+  std::shared_ptr<Session> FindSession(int port);
+  std::shared_ptr<Session> FindSession(const std::string& port_name);
+
+  static gboolean OnDebugPortDisconnectedCb(GIOChannel* io,
+      GIOCondition cond, gpointer data);
+  static int AppComCb(const char* endpoint, aul_app_com_result_e result,
+      bundle* envelope, void* user_data);
+
+ private:
+  bool disposed_ = true;
+  std::atomic<bool> connected_ { false };
+  std::unique_ptr<Port> port_;
+  GIOChannel* io_ = nullptr;
+  guint watch_tag_ = 0;
+  std::list<std::shared_ptr<Session>> sessions_;
+  std::thread thread_;
+  std::atomic<bool> is_running_ { false };
+  tizen_base::SharedQueue<std::shared_ptr<tizen_base::Parcel>> queue_;
+  mutable std::recursive_mutex mutex_;
+  aul_app_com_connection_h conn_ = nullptr;
+};
+
+DebugPortImpl::~DebugPortImpl() {
+  Dispose();
+}
+
+void DebugPortImpl::Dispose() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (disposed_)
+    return;
+
+  if (conn_) {
+    aul_app_com_leave(conn_);
+    conn_ = nullptr;
+  }
+
+  Unwatch();
+  JoinThread();
+  disposed_ = true;
+}
+
+bool DebugPortImpl::IsConnected() const {
+  return connected_;
+}
+
+void DebugPortImpl::AddSession(std::string port_name, std::string destination,
+    int main_port, int delegate_port) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  sessions_.emplace_back(
+      new Session(std::move(port_name), std::move(destination),
+        main_port, delegate_port));
+}
+
+void DebugPortImpl::RemoveSession(int port) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  auto iter = std::find_if(sessions_.begin(), sessions_.end(),
+      [port](std::shared_ptr<Session>& sess) -> bool {
+        return sess->GetMainPort() == port || sess->GetDelegatePort() == port;
+      });
+
+  if (iter != sessions_.end()) {
+    _W("Remove session. port(%d)", port);
+    iter = sessions_.erase(iter);
+  }
+}
+
+std::shared_ptr<Session> DebugPortImpl::FindSession(int port) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  for (auto& s : sessions_) {
+    if (s->GetMainPort() == port || s->GetDelegatePort() == port)
+      return s;
+  }
+
+  return nullptr;
+}
+
+std::shared_ptr<Session> DebugPortImpl::FindSession(
+    const std::string& port_name) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  for (auto& s : sessions_) {
+    if (s->GetPortName() == port_name)
+      return s;
+  }
+
+  return nullptr;
+}
+
+int DebugPortImpl::Send(int port, bool is_read, uint32_t seq,
+    const void* buf, unsigned int size) {
+  if (!IsConnected())
+    return 0;
+
+  auto session = FindSession(port);
+  if (session == nullptr) {
+    _E("Failed to find session. port(%d)", port);
+    return -1;
+  }
+
+  // time + port_name + destination + is_delegate + port + is_read + seq + size + data
+  tizen_base::Parcel parcel;
+  parcel.WriteInt64(time(nullptr));
+  parcel.WriteString(session->GetPortName().c_str());
+  parcel.WriteString(session->GetDestination().c_str());
+  parcel.WriteBool(session->GetDelegatePort() == port);
+  parcel.WriteInt32(port);
+  parcel.WriteBool(is_read);
+  parcel.WriteInt32(seq);
+  parcel.WriteInt32(size);
+  parcel.Write(static_cast<const unsigned char*>(buf), size);
+
+  queue_.Push(std::make_shared<tizen_base::Parcel>(parcel));
+  return 0;
+}
+
+void DebugPortImpl::Init() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (!disposed_)
+    return;
+
+  aul_app_com_create_async(ENDPOINT_RPC_PORT_DEBUG, nullptr, AppComCb, this,
+      &conn_);
+  if (conn_ == nullptr)
+    return;
+
+  do {
+    int fd = Connect();
+    if (fd < 0)
+      break;
+
+    port_.reset(new Port(fd, "Debug"));
+    if (Watch(fd) < 0)
+      break;
+
+    SetConnectionStatus(true);
+    _W("Connected");
+    CreateThread();
+  } while (0);
+
+  disposed_ = false;
+}
+
+int DebugPortImpl::Connect() {
+  if (access(PATH_RPC_PORT_UTIL_SOCK, F_OK) != 0)
+    return -1;
+
+  int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+  if (fd < 0) {
+    _E("socket() is failed. errno(%d)", errno);
+    return -1;
+  }
+
+  struct sockaddr_un addr = { 0, };
+  addr.sun_family = AF_UNIX;
+  snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", PATH_RPC_PORT_UTIL_SOCK);
+
+  int ret = connect(fd, reinterpret_cast<struct sockaddr*>(&addr),
+      sizeof(addr));
+  if (ret < 0) {
+    _E("connect() is failed. fd(%d), errno(%d)", fd, errno);
+    close(fd);
+    return -1;
+  }
+
+  return fd;
+}
+
+int DebugPortImpl::Watch(int fd) {
+  GIOChannel* io = g_io_channel_unix_new(fd);
+  if (io == nullptr) {
+    _E("g_io_channel_unix_new() is failed");
+    return -1;
+  }
+
+  GIOCondition cond = static_cast<GIOCondition>(
+      (G_IO_ERR | G_IO_HUP | G_IO_NVAL));
+  guint tag = g_io_add_watch(io, cond, OnDebugPortDisconnectedCb, this);
+  if (tag == 0) {
+    _E("g_io_add_watch() is failed");
+    g_io_channel_unref(io);
+    return -1;
+  }
+
+  io_ = io;
+  watch_tag_ = tag;
+  return 0;
+}
+
+void DebugPortImpl::Unwatch() {
+  if (io_) {
+    g_io_channel_unref(io_);
+    io_ = nullptr;
+  }
+
+  if (watch_tag_) {
+    g_source_remove(watch_tag_);
+    watch_tag_ = 0;
+  }
+}
+
+gboolean DebugPortImpl::OnDebugPortDisconnectedCb(GIOChannel* io,
+    GIOCondition cond, gpointer data) {
+  _W("cond(%d)", static_cast<int>(cond));
+  auto* debug_port = static_cast<DebugPortImpl*>(data);
+  std::lock_guard<std::recursive_mutex> lock(debug_port->GetMutex());
+  debug_port->SetConnectionStatus(false);
+  debug_port->watch_tag_ = 0;
+  debug_port->Unwatch();
+  debug_port->port_.reset();
+  _W("Disconnected");
+  return G_SOURCE_REMOVE;
+}
+
+void DebugPortImpl::SetConnectionStatus(bool status) {
+  connected_.exchange(status);
+}
+
+void DebugPortImpl::CreateThread() {
+  if (is_running_)
+    return;
+
+  thread_ = std::thread([&]() {
+      _W("START");
+      do {
+        std::shared_ptr<tizen_base::Parcel> parcel = queue_.WaitAndPop();
+        int len = parcel->GetDataSize();
+        if (len == 0) {
+          _W("Done");
+          break;
+        }
+
+        if (!IsConnected())
+          continue;
+
+        int ret = port_->Write(reinterpret_cast<void*>(&len), sizeof(len));
+        if (ret < 0) {
+          _E("Failed to write size");
+          SetConnectionStatus(false);
+          continue;
+        }
+
+        ret = port_->Write(parcel->GetData(), len);
+        if (ret < 0) {
+          _E("Failed to write data");
+          SetConnectionStatus(false);
+        }
+      } while (true);
+      _W("END");
+    });
+
+  is_running_ = true;
+}
+
+void DebugPortImpl::JoinThread() {
+  if (is_running_)
+    queue_.Push(std::shared_ptr<tizen_base::Parcel>(new tizen_base::Parcel()));
+
+  if (thread_.joinable()) {
+    _W("Join thread");
+    thread_.join();
+  }
+}
+
+
+std::recursive_mutex& DebugPortImpl::GetMutex() const {
+  return mutex_;
+}
+
+int DebugPortImpl::AppComCb(const char* endpoint, aul_app_com_result_e result,
+    bundle* envelope, void* user_data) {
+  const char* val = bundle_get_val(envelope, KEY_PORT_NAME);
+  if (val == nullptr)
+    return -1;
+
+  auto* handle = static_cast<DebugPortImpl*>(user_data);
+  std::string port_name(val);
+  if (port_name.empty() || handle->FindSession(port_name) != nullptr) {
+    auto* handle = static_cast<DebugPortImpl*>(user_data);
+    int fd = handle->Connect();
+    if (fd < 0)
+      return -1;
+
+    std::lock_guard<std::recursive_mutex> lock(handle->GetMutex());
+    handle->port_.reset(new Port(fd, "Debug"));
+    int ret = handle->Watch(fd);
+    if (ret < 0)
+      return -1;
+
+    handle->SetConnectionStatus(true);
+    _W("Connected");
+    handle->CreateThread();
+  }
+
+  return 0;
+}
+
+DebugPortImpl impl;
+
+}  // namespace
+
+bool DebugPort::IsConnected() {
+  impl.Init();
+  return impl.IsConnected();
+}
+
+void DebugPort::AddSession(std::string port_name, std::string destination,
+    int main_port, int delegate_port) {
+  impl.Init();
+  return impl.AddSession(std::move(port_name), std::move(destination),
+      main_port, delegate_port);
+}
+
+void DebugPort::RemoveSession(int port) {
+  impl.Init();
+  return impl.RemoveSession(port);
+}
+
+int DebugPort::Send(int port, bool is_read, uint32_t seq, const void* buf,
+    unsigned int size) {
+  impl.Init();
+  return impl.Send(port, is_read, seq, buf, size);
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/debug-port-internal.hh b/src/rpc-port/debug-port-internal.hh
new file mode 100644 (file)
index 0000000..9b68c65
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEBUG_PORT_INTERNAL_HH_
+#define DEBUG_PORT_INTERNAL_HH_
+
+#include <cstdint>
+#include <string>
+
+namespace rpc_port {
+namespace internal {
+
+class DebugPort {
+ public:
+  static bool IsConnected();
+  static void AddSession(std::string port_name, std::string destination,
+      int main_port, int delegate_port);
+  static void RemoveSession(int port);
+  static int Send(int port, bool is_read, uint32_t seq,
+      const void* buf, unsigned int size);
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // DEBUG_PORT_INTERNAL_HH_
diff --git a/src/rpc-port/exception-internal.cc b/src/rpc-port/exception-internal.cc
new file mode 100644 (file)
index 0000000..51a7bb9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "exception-internal.hh"
+
+#include <utility>
+
+namespace rpc_port {
+namespace internal {
+
+// LCOV_EXCL_START
+Exception::Exception(int error_code, const std::string& file, int line)
+    : error_code_(error_code),
+      message_(std::move(GetErrorMessage(error_code_, file, line))) {
+}
+
+const char* Exception::what() const noexcept {
+  return message_.c_str();
+}
+
+int Exception::GetErrorCode() {
+  return error_code_;
+}
+
+std::string Exception::GetErrorMessage(int error_code, const std::string& file,
+    int line) {
+  return file.substr(file.find_last_of("/") + 1) + ":" + std::to_string(line) +
+      " error_code: " + std::to_string(error_code);
+}
+// LCOV_EXCL_STOP
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/exception-internal.hh b/src/rpc-port/exception-internal.hh
new file mode 100644 (file)
index 0000000..226c909
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EXCEPTION_INTERNAL_HH_
+#define EXCEPTION_INTERNAL_HH_
+
+#include <exception>
+#include <string>
+
+#define THROW(error_code) throw Exception(error_code, __FUNCTION__, __LINE__)
+
+namespace rpc_port {
+namespace internal {
+
+class Exception : public std::exception {
+ public:
+  explicit Exception(int error_code, const std::string& file, int line);
+  virtual ~Exception() = default;  // LCOV_EXCL_LINE
+
+  virtual const char* what() const noexcept;
+  int GetErrorCode();
+
+ private:
+  static std::string GetErrorMessage(int error_code, const std::string& file,
+      int line);
+
+ private:
+  int error_code_;
+  std::string message_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // EXCEPTION_INTERNAL_HH_
diff --git a/src/rpc-port/file-monitor-internal.cc b/src/rpc-port/file-monitor-internal.cc
new file mode 100644 (file)
index 0000000..f8b0303
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "file-monitor-internal.hh"
+
+#include <sys/inotify.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <filesystem>
+#include <utility>
+
+#include "exception-internal.hh"
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace internal {
+namespace fs = std::filesystem;
+
+FileMonitor::FileMonitor(std::string path, IEvent* listener)
+    : path_(std::move(path)), listener_(listener) {
+  const auto fs_path = fs::path(path_);
+  parent_path_ = fs_path.parent_path().string();
+  file_name_ = fs_path.filename().string();
+  _W("path=%s, parent_path=%s, file_name=%s",
+     path_.c_str(), parent_path_.c_str(), file_name_.c_str());
+}
+
+FileMonitor::~FileMonitor() {
+  _W("path=%s", path_.c_str());
+  Stop();
+}
+
+bool FileMonitor::Exist() {
+  if (access(path_.c_str(), F_OK) == 0) return true;
+
+  return false;
+}
+
+void FileMonitor::Start() {
+  fd_ = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+  if (fd_ < 0) {
+    _E("inotify_init1() is failed. errno(%d)", errno);
+    THROW(-1);
+  }
+
+  wd_ = inotify_add_watch(fd_, parent_path_.c_str(), IN_CREATE | IN_DELETE);
+  if (wd_ < 0) {
+    _E("inotify_add_watch() is failed. errno(%d)", errno);
+    Stop();
+    THROW(-1);
+  }
+
+  channel_ = g_io_channel_unix_new(fd_);
+  if (channel_ == nullptr) {
+    _E("g_io_channel_unix_new() is failed");
+    Stop();
+    THROW(-1);
+  }
+
+  source_ = g_io_create_watch(channel_, G_IO_IN);
+  if (source_ == nullptr) {
+    _E("g_io_create_watch() is failed");
+    Stop();
+    THROW(-1);
+  }
+
+  g_source_set_callback(source_, reinterpret_cast<GSourceFunc>(GIOFunc), this,
+                        nullptr);
+  g_source_attach(source_, nullptr);
+  g_source_unref(source_);
+}
+
+void FileMonitor::Stop() {
+  if (source_ && !g_source_is_destroyed(source_)) {
+    g_source_destroy(source_);
+    source_ = nullptr;
+  }
+
+  if (channel_) {
+    g_io_channel_unref(channel_);
+    channel_ = nullptr;
+  }
+
+  if (wd_ > -1) {
+    inotify_rm_watch(fd_, wd_);
+    wd_ = -1;
+  }
+
+  if (fd_ > -1) {
+    close(fd_);
+    fd_ = -1;
+  }
+}
+
+gboolean FileMonitor::GIOFunc(GIOChannel* channel, GIOCondition condition,
+                              gpointer user_data) {
+  char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
+  auto* monitor = static_cast<FileMonitor*>(user_data);
+  auto* listener = monitor->listener_;
+  int fd = g_io_channel_unix_get_fd(channel);
+  struct inotify_event* event;
+  ssize_t len;
+  char* ptr;
+  char* nptr;
+
+  while ((len = read(fd, buf, sizeof(buf))) > 0) {
+    for (ptr = buf; ptr < buf + len;
+         ptr += sizeof(struct inotify_event) + event->len) {
+      event = reinterpret_cast<struct inotify_event*>(ptr);
+      nptr = ptr + sizeof(struct inotify_event) + event->len;
+      if (nptr > buf + len) break;
+
+      if (monitor->file_name_ != event->name) continue;
+
+      if (event->mask & IN_CREATE) {
+        listener->OnFileCreated(monitor->path_);
+        return G_SOURCE_CONTINUE;
+      }
+
+      if (event->mask & IN_DELETE)
+        listener->OnFileDeleted(monitor->path_);
+    }
+  }
+
+  return G_SOURCE_CONTINUE;
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/file-monitor-internal.hh b/src/rpc-port/file-monitor-internal.hh
new file mode 100644 (file)
index 0000000..2058402
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FILE_MONITOR_INTERNAL_HH_
+#define FILE_MONITOR_INTERNAL_HH_
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include <string>
+
+namespace rpc_port {
+namespace internal {
+
+class FileMonitor {
+ public:
+  class IEvent {
+   public:
+    virtual ~IEvent() = default;
+    virtual void OnFileCreated(const std::string& path) = 0;
+    virtual void OnFileDeleted(const std::string& path) = 0;
+  };
+
+  explicit FileMonitor(std::string path, IEvent* listener = nullptr);
+  ~FileMonitor();
+
+  void Start();
+  void Stop();
+  bool Exist();
+
+ private:
+  static gboolean GIOFunc(GIOChannel* channel, GIOCondition condition,
+                          gpointer user_data);
+
+ private:
+  std::string path_;
+  std::string parent_path_;
+  std::string file_name_;
+  IEvent* listener_ = nullptr;
+  int fd_ = -1;
+  int wd_ = -1;
+  GIOChannel* channel_ = nullptr;
+  GSource* source_ = nullptr;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // FILE_MONITOR_INTERNAL_HH_
diff --git a/src/rpc-port/log-private.hh b/src/rpc-port/log-private.hh
new file mode 100644 (file)
index 0000000..36aeb9c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOG_PRIVATE_HH_
+#define LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "RPC_PORT"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif  // LOG_PRIVATE_HH_
diff --git a/src/rpc-port/message-sending-thread-internal.cc b/src/rpc-port/message-sending-thread-internal.cc
new file mode 100644 (file)
index 0000000..b21eddd
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "log-private.hh"
+#include "message-sending-thread-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+// LCOV_EXCL_START
+MessageSendingThread& MessageSendingThread::GetInst() {
+  static MessageSendingThread inst;
+  return inst;
+}
+
+MessageSendingThread::MessageSendingThread() {
+  context_ = g_main_context_new();
+  loop_ = g_main_loop_new(context_, false);
+  std::unique_lock<std::mutex> lock(mutex_);
+  thread_ = std::make_unique<std::thread>([&]() -> void { ThreadLoop(); });
+  cond_.wait(lock, [&] { return thread_ok_; });
+}
+
+MessageSendingThread::~MessageSendingThread() {
+  Dispose();
+}
+
+gboolean MessageSendingThread::NotifyOne(gpointer data) {
+  auto* sender = static_cast<MessageSendingThread*>(data);
+  std::unique_lock<std::mutex> lock(sender->mutex_);
+  sender->thread_ok_ = true;
+  sender->cond_.notify_one();
+  return G_SOURCE_REMOVE;
+}
+
+void MessageSendingThread::ThreadLoop() {
+  {
+    std::unique_lock<std::mutex> lock(mutex_);
+    GSource* source = g_idle_source_new();
+    if (source == nullptr) {
+      _E("Failed to create GSource");
+      cond_.notify_one();
+      return;
+    }
+
+    g_source_set_callback(source, NotifyOne, this, nullptr);
+    g_source_set_priority(source, G_PRIORITY_HIGH);
+    g_source_attach(source, context_);
+    g_source_unref(source);
+
+    g_main_context_push_thread_default(context_);
+  }
+
+  g_main_loop_run(loop_);
+
+  g_main_context_pop_thread_default(context_);
+  _W("Shutdown message sending thread");
+}
+
+void MessageSendingThread::Dispose() {
+  std::unique_lock<std::mutex> lock(mutex_);
+  if (g_main_loop_is_running(loop_))
+    g_main_loop_quit(loop_);
+  else
+    _E("GMainLoop is not running");
+
+  thread_->join();
+
+  g_main_loop_unref(loop_);
+  loop_ = nullptr;
+
+  g_main_context_unref(context_);
+  context_ = nullptr;
+}
+
+GMainContext* MessageSendingThread::GetContext() {
+  return context_;
+}
+// LCOV_EXCL_STOP
+
+}  // namespace internal
+}  // namespace rpc_port
+
diff --git a/src/rpc-port/message-sending-thread-internal.hh b/src/rpc-port/message-sending-thread-internal.hh
new file mode 100644 (file)
index 0000000..1d3acad
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MESSAGE_SENDING_THREAD_INTERNAL_HH_
+#define MESSAGE_SENDING_THREAD_INTERNAL_HH_
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include <condition_variable>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <thread>
+
+#include "port-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+class MessageSendingThread {
+ public:
+  static MessageSendingThread& GetInst();
+  ~MessageSendingThread();
+  GMainContext* GetContext();
+
+ private:
+  MessageSendingThread();
+  void ThreadLoop();
+  void Dispose();
+  static gboolean NotifyOne(gpointer data);
+
+  GMainContext* context_ = nullptr;
+  GMainLoop* loop_ = nullptr;
+  bool thread_ok_ = false;
+  std::unique_ptr<std::thread> thread_;
+  std::mutex mutex_;
+  std::condition_variable cond_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // MESSAGE_SENDING_THREAD_INTERNAL_HH_
diff --git a/src/rpc-port/parcel-header-internal.cc b/src/rpc-port/parcel-header-internal.cc
new file mode 100644 (file)
index 0000000..f4413dd
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <atomic>
+#include <climits>
+#include <limits>
+#include <utility>
+
+#include "parcel-header-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+ParcelHeader::ParcelHeader() : seq_num_(GenerateSeqNum()) {
+  clock_gettime(CLOCK_MONOTONIC_RAW, &time_stamp_);
+}
+
+void ParcelHeader::WriteToParcel(tizen_base::Parcel* parcel) const {
+  parcel->WriteString(tag_);
+  parcel->WriteInt32(seq_num_);
+  parcel->WriteInt64(static_cast<int64_t>(time_stamp_.tv_sec));
+  parcel->WriteInt64(static_cast<int64_t>(time_stamp_.tv_nsec));
+}
+
+void ParcelHeader::ReadFromParcel(tizen_base::Parcel* parcel) {
+  tag_ = std::move(parcel->ReadString());
+  parcel->ReadInt32(&seq_num_);
+
+  int64_t tv_sec = 0;
+  parcel->ReadInt64(&tv_sec);
+  time_stamp_.tv_sec = tv_sec & std::numeric_limits<time_t>::max();
+
+  int64_t tv_nsec = 0;
+  parcel->ReadInt64(&tv_nsec);
+  time_stamp_.tv_nsec = tv_nsec & std::numeric_limits<long>::max();
+}
+
+void ParcelHeader::SetTag(std::string tag) {
+  tag_ = std::move(tag);
+}
+
+const std::string& ParcelHeader::GetTag() const {
+  return tag_;
+}
+
+void ParcelHeader::SetSeqNum(int seq_num) {
+  seq_num_ = seq_num;
+}
+
+int ParcelHeader::GetSeqNum() const {
+  return seq_num_;
+}
+
+struct timespec ParcelHeader::GetTimeStamp() const {
+  return time_stamp_;
+}
+
+int ParcelHeader::GenerateSeqNum() {
+  static std::atomic<unsigned int> num { 0 };
+  ++num;
+  return static_cast<int>(num & INT_MAX);
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/parcel-header-internal.hh b/src/rpc-port/parcel-header-internal.hh
new file mode 100644 (file)
index 0000000..32a9007
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PARCEL_HEADER_INTERNAL_H_
+#define PARCEL_HEADER_INTERNAL_H_
+
+#include <time.h>
+
+#include <string>
+
+#include <parcel.hh>
+
+namespace rpc_port {
+namespace internal {
+
+class ParcelHeader : public tizen_base::Parcelable {
+ public:
+   ParcelHeader();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+  void SetTag(std::string tag);
+  const std::string& GetTag() const;
+  void SetSeqNum(int seq_num);
+  int GetSeqNum() const;
+  struct timespec GetTimeStamp() const;
+
+  static int GenerateSeqNum();
+
+ private:
+  std::string tag_;
+  int seq_num_;
+  struct timespec time_stamp_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PARCEL_HEADER_INTERNAL_H_
diff --git a/src/rpc-port/parcel-internal.cc b/src/rpc-port/parcel-internal.cc
new file mode 100644 (file)
index 0000000..932569c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "parcel-internal.hh"
+
+#include <memory>
+#include <utility>
+
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace internal {
+
+Parcel::Parcel(bool without_header)
+    : header_(without_header ? nullptr : new ParcelHeader()) {
+}
+
+Parcel::~Parcel() {}
+
+void Parcel::WriteToParcel(tizen_base::Parcel* parcel) const {
+  if (header_.get() != nullptr) {
+    parcel->WriteParcelable(*header_.get());
+    parcel->WriteUInt32(handle_.GetDataSize());
+  }
+
+  parcel->Write(handle_.GetData(), handle_.GetDataSize());
+}
+
+void Parcel::ReadFromParcel(tizen_base::Parcel* parcel) {
+  if (header_.get() != nullptr) {
+    parcel->ReadParcelable(header_.get());
+
+    uint32_t size = 0;
+    parcel->ReadUInt32(&size);
+    if (size > 0) {
+      auto* buf = static_cast<uint8_t*>(malloc(size));
+      if (buf == nullptr) {
+        _E("Out of memory");  // LCOV_EXEC_LINE
+        return;  // LCOV_EXCL_LINE
+      }
+
+      parcel->Read(buf, size);
+      handle_ = std::move(tizen_base::Parcel(buf, size, false));
+    }
+  } else {
+    // LCOV_EXCL_START
+    handle_ = std::move(
+        tizen_base::Parcel(parcel->GetData(), parcel->GetDataSize()));
+    // LCOV_EXCL_STOP
+  }
+}
+
+const ParcelHeader* Parcel::GetParcelHeader() {
+  return header_.get();
+}
+
+parcel_h Parcel::GetHandle() const {
+  return static_cast<parcel_h>(const_cast<tizen_base::Parcel*>(&handle_));
+}
+
+void Parcel::SetRawParcel(tizen_base::Parcel* raw_parcel) {
+  raw_parcel_.reset(raw_parcel);
+}
+
+// LCOV_EXCL_START
+tizen_base::Parcel* Parcel::GetRawParcel() const {
+  return raw_parcel_.get();
+}
+// LCOV_EXCL_STOP
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/parcel-internal.hh b/src/rpc-port/parcel-internal.hh
new file mode 100644 (file)
index 0000000..3d0911d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PARCEL_INTERNAL_HH_
+#define PARCEL_INTERNAL_HH_
+
+#include <parcel.h>
+
+#include <parcel.hh>
+#include <parcelable.hh>
+
+#include <memory>
+
+#include "parcel-header-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+class Parcel : public tizen_base::Parcelable {
+ public:
+   Parcel(bool without_header = false);
+   ~Parcel();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+  const ParcelHeader* GetParcelHeader();
+  parcel_h GetHandle() const;
+
+  void SetRawParcel(tizen_base::Parcel* raw_parcel);
+  tizen_base::Parcel* GetRawParcel() const;
+
+ private:
+  std::unique_ptr<ParcelHeader> header_;
+  tizen_base::Parcel handle_;
+  std::unique_ptr<tizen_base::Parcel> raw_parcel_ { nullptr };
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PARCEL_INTERNAL_HH_
diff --git a/src/rpc-port/peer-cred-internal.cc b/src/rpc-port/peer-cred-internal.cc
new file mode 100644 (file)
index 0000000..150d3ab
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <new>
+
+#include "log-private.hh"
+#include "peer-cred-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+PeerCred::PeerCred(pid_t pid, uid_t uid, gid_t gid)
+    : pid_(pid), uid_(uid), gid_(gid) {
+}
+
+PeerCred* PeerCred::Get(int fd) {
+  struct ucred cred;
+  socklen_t len = static_cast<socklen_t>(sizeof(struct ucred));
+  int ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+      static_cast<void*>(&cred), &len);
+  if (ret != 0) {
+    _E("getsockopt() is failed. fd(%d), errno(%d)", fd, errno);  // LCOV_EXCL_LINE
+    return nullptr;  // LCOV_EXCL_LINE
+  }
+
+  return new (std::nothrow) PeerCred(cred.pid, cred.uid, cred.gid);
+}
+
+pid_t PeerCred::GetPid() const {
+  return pid_;
+}
+
+uid_t PeerCred::GetUid() const {
+  return uid_;
+}
+
+
+// LCOV_EXCL_START
+gid_t PeerCred::GetGid() const {
+  return gid_;
+}
+// LCOV_EXCL_STOP
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/peer-cred-internal.hh b/src/rpc-port/peer-cred-internal.hh
new file mode 100644 (file)
index 0000000..bf57ed5
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PEER_CRED_INTERNAL_HH_
+#define PEER_CRED_INTERNAL_HH_
+
+namespace rpc_port {
+namespace internal {
+
+class PeerCred {
+ public:
+  static PeerCred* Get(int fd);
+
+  pid_t GetPid() const;
+  uid_t GetUid() const;
+  gid_t GetGid() const;
+
+ private:
+  PeerCred(pid_t pid, uid_t uid, gid_t gid);
+
+ private:
+  pid_t pid_;
+  uid_t uid_;
+  gid_t gid_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PEER_CRED_INTERNAL_HH_
diff --git a/src/rpc-port/port-internal.cc b/src/rpc-port/port-internal.cc
new file mode 100644 (file)
index 0000000..c32d5fb
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aul_rpc_port.h>
+#include <dlog.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+
+#include <chrono>
+#include <utility>
+
+#include "include/rpc-port.h"
+#include "log-private.hh"
+#include "message-sending-thread-internal.hh"
+#include "port-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+namespace {
+
+constexpr const int QUEUE_SIZE_MAX = 1024 * 1024 * 10;
+constexpr const int MAX_RETRY_CNT = 10;
+constexpr const int MAX_TIMEOUT = 1000;
+constexpr const int MIN_TIMEOUT = 50;
+
+}  // namespace
+
+// LCOV_EXCL_START
+Port::DelayMessage::DelayMessage(const char* msg, int index, int size)
+    : message_(msg, msg + size), index_(index), size_(size) {
+}
+
+void Port::DelayMessage::SetIndex(int index) {
+  index_ += index;
+}
+
+int Port::DelayMessage::GetSize() {
+  return size_ - index_;
+}
+
+int Port::DelayMessage::GetOriginalSize() {
+  return size_;
+}
+
+char* Port::DelayMessage::GetMessage() {
+  char* ptr = reinterpret_cast<char*>(message_.data());
+  ptr += index_;
+  return ptr;
+}
+// LCOV_EXCL_STOP
+
+Port::Port(int fd, std::string id)
+    : fd_(fd), id_(std::move(id)), instance_(""), seq_(0) {
+  char uuid[37];
+  uuid_t u;
+  uuid_generate(u);
+  uuid_unparse(u, uuid);
+  instance_ = std::string(uuid) + ":" + id_;
+  SetReceiveTimeout(10000);
+}
+
+Port::Port(int fd, std::string id, std::string instance)
+    : fd_(fd), id_(std::move(id)), instance_(std::move(instance)), seq_(0) {
+  SetReceiveTimeout(10000);
+}
+
+Port::~Port() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  ClearQueue();
+  Disconnect();
+}
+
+void Port::Disconnect() {
+  IgnoreIOEvent();
+
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+  if (fd_ > 0) {
+    _W("Close fd(%d)", fd_);
+    close(fd_);
+    fd_ = -1;
+  }
+}
+
+int Port::SetPrivateSharing(const char* paths[], unsigned int size) {
+  int ret = aul_rpc_port_set_private_sharing(id_.c_str(), paths, size);
+  if (ret != 0)
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Port::SetPrivateSharing(const char* path) {
+  const char* file_list[1] = {path};
+  int ret = aul_rpc_port_set_private_sharing(id_.c_str(), file_list, 1);
+  if (ret != 0)
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Port::UnsetPrivateSharing() {
+  int ret = aul_rpc_port_unset_private_sharing(id_.c_str());
+  if (ret != 0)
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Port::Read(void* buf, unsigned int size) {
+  unsigned int left = size;
+  ssize_t nb;
+  int bytes_read = 0;
+  char* buffer = static_cast<char*>(buf);
+  int flags;
+
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+  if (fd_ < 0 || fd_ >= sysconf(_SC_OPEN_MAX)) {
+    _E("Invalid fd(%d)", fd_);  // LCOV_EXCL_LINE
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  }
+
+  flags = fcntl(fd_, F_GETFL, 0);
+  fcntl(fd_, F_SETFL, flags & ~O_NONBLOCK);
+
+  while (left) {
+    nb = read(fd_, buffer, left);
+    if (nb == 0) {
+      _E("read_socket: ...read EOF, socket closed %d: nb %zd\n", fd_, nb);
+      fcntl(fd_, F_SETFL, flags);
+      return RPC_PORT_ERROR_IO_ERROR;
+    }
+
+    if (nb == -1) {
+      if (errno == EINTR) {
+        usleep(100 * 1000);
+        continue;
+      }
+
+      _E("read_socket: ...error fd %d: errno %d\n", fd_, errno);
+      fcntl(fd_, F_SETFL, flags);
+      return RPC_PORT_ERROR_IO_ERROR;
+    }
+
+    left -= nb;
+    buffer += nb;
+    bytes_read += nb;
+  }
+
+  fcntl(fd_, F_SETFL, flags);
+  return RPC_PORT_ERROR_NONE;
+}
+
+// LCOV_EXCL_START
+int Port::SetReceiveTimeout(int timeout) {
+   if (timeout == INT_MAX)
+    return -EINVAL;
+
+  if (timeout == -1)
+    timeout = 10000;
+
+  if (timeout < 0) {
+    _E("Invalid parameter");
+    return -EINVAL;
+  }
+
+  struct timeval tv = {
+    .tv_sec = static_cast<time_t>(timeout / 1000),
+    .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000)
+  };
+  socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
+  int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &tv, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+  }
+
+  return ret;
+}
+
+bool Port::CanWrite() {
+  struct pollfd fds[1];
+  fds[0].fd = fd_;
+  fds[0].events = POLLOUT;
+  fds[0].revents = 0;
+  int ret = poll(fds, 1, 100);
+  if (ret <= 0) {
+    _W("poll() is failed. fd(%d), error(%s)",
+        fd_, ret == 0 ? "timed out" : std::to_string(-errno).c_str());
+    return false;
+  }
+
+  return true;
+}
+// LCOV_EXCL_STOP
+
+int Port::Write(const void* buf, unsigned int size) {
+  int sent_bytes = 0;
+  int ret;
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+
+  if (queue_.empty()) {
+    ret = Write(buf, size, &sent_bytes);
+    if (ret == PORT_STATUS_ERROR_NONE)
+      return RPC_PORT_ERROR_NONE;
+    else if (ret == PORT_STATUS_ERROR_IO_ERROR)
+      return RPC_PORT_ERROR_IO_ERROR;
+  } else if (CanWrite()) {  // LCOV_EXCL_LINE
+    // LCOV_EXCL_START
+    while (!queue_.empty()) {
+      int port_status = PopDelayedMessage();
+      if (port_status != PORT_STATUS_ERROR_NONE) {
+        if (port_status == PORT_STATUS_ERROR_IO_ERROR)
+          return RPC_PORT_ERROR_IO_ERROR;
+
+        break;
+      }
+    }
+    // LCOV_EXCL_STOP
+  }
+
+  // LCOV_EXCL_START
+  if (delayed_message_size_ > QUEUE_SIZE_MAX) {
+    _E("cache fail : delayed_message_size (%d), count(%zu)",
+        delayed_message_size_, queue_.size());
+    return RPC_PORT_ERROR_IO_ERROR;
+  }
+
+  return PushDelayedMessage(
+      std::make_shared<DelayMessage>(
+        static_cast<const char*>(buf), sent_bytes, size));
+  // LCOV_EXCL_STOP
+}
+
+int Port::Write(const void* buf, unsigned int size, int* sent_bytes) {
+  unsigned int left = size;
+  ssize_t nb;
+  int retry_cnt = 0;
+  const char* buffer = static_cast<const char*>(buf);
+
+  if (fd_ < 0 || fd_ >= sysconf(_SC_OPEN_MAX)) {
+    _E("Invalid fd(%d)", fd_);  // LCOV_EXCL_LINE
+    return PORT_STATUS_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  }
+
+  while (left && (retry_cnt < MAX_RETRY_CNT)) {
+    nb = send(fd_, buffer, left, MSG_NOSIGNAL);
+    if (nb == -1) {
+      if (errno == EINTR) {
+        // LCOV_EXCL_START
+        LOGI("write_socket: EINTR continue ...");
+        retry_cnt++;
+        continue;
+        // LCOV_EXCL_STOP
+      }
+
+      if (errno == EAGAIN || errno == EWOULDBLOCK)
+        return PORT_STATUS_ERROR_RESOURCE_UNAVAILABLE;
+
+      _E("write_socket: ...error fd: %d, errno: %d", fd_, errno);
+      return PORT_STATUS_ERROR_IO_ERROR;
+    }
+
+    left -= nb;
+    buffer += nb;
+    *sent_bytes += nb;
+  }
+
+  if (left != 0) {
+    _E("error fd %d: retry_cnt %d", fd_, retry_cnt);
+    return PORT_STATUS_ERROR_IO_ERROR;
+  }
+
+  return PORT_STATUS_ERROR_NONE;
+}
+
+// LCOV_EXCL_START
+gboolean Port::OnEventReceived(GIOChannel* io, GIOCondition condition,
+                               gpointer data) {
+  auto* ptr = static_cast<std::weak_ptr<Port>*>(data);
+  auto port = ptr->lock();
+  if (port == nullptr) {
+    _E("port is destructed");
+    return G_SOURCE_REMOVE;
+  }
+
+  _W("Writing is now possible. fd: %d, id: %s",
+      port->GetFd(), port->GetId().c_str());
+  std::lock_guard<std::recursive_mutex> lock(port->rw_mutex_);
+  if (port->source_id_ == 0) {
+    _E("GSource is destroyed");
+    return G_SOURCE_REMOVE;
+  }
+
+  if (port->queue_.empty()) {
+    port->IgnoreIOEvent();
+    return G_SOURCE_CONTINUE;
+  }
+
+  port->PopDelayedMessage();
+  return G_SOURCE_CONTINUE;
+}
+// LCOV_EXCL_STOP
+
+void Port::ClearQueue() {
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+
+  while (queue_.empty() == false)
+    queue_.pop();
+
+  IgnoreIOEvent();
+  delayed_message_size_ = 0;
+}
+
+void Port::IgnoreIOEvent() {
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+  if (source_id_ != 0) {
+    // LCOV_EXCL_START
+    GSource* source = g_main_context_find_source_by_id(
+        MessageSendingThread::GetInst().GetContext(), source_id_);
+    if (source != nullptr && !g_source_is_destroyed(source))
+      g_source_destroy(source);
+
+    source_id_ = 0;
+    // LCOV_EXCL_STOP
+  }
+
+  if (channel_ != nullptr) {
+    g_io_channel_unref(channel_);  // LCOV_EXCL_LINE
+    channel_ = nullptr;  // LCOV_EXCL_LINE
+  }
+}
+
+// LCOV_EXCL_START
+int Port::ListenIOEvent() {
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+  channel_ = g_io_channel_unix_new(fd_);
+  if (channel_ == nullptr) {
+    _E("Failed to create GIOChannel");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  GSource* source = g_io_create_watch(channel_,
+      static_cast<GIOCondition>(G_IO_OUT));
+  if (source == nullptr) {
+    _E("Failed to create GSource");
+    IgnoreIOEvent();
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  auto* ptr = new (std::nothrow) std::weak_ptr<Port>(shared_from_this());
+  g_source_set_callback(source, reinterpret_cast<GSourceFunc>(OnEventReceived),
+                        static_cast<gpointer>(ptr), [](gpointer ptr) {
+                          auto* port = static_cast<std::weak_ptr<Port>*>(ptr);
+                          delete port;
+                        });
+  g_source_set_priority(source, G_PRIORITY_DEFAULT);
+  source_id_ = g_source_attach(source,
+      MessageSendingThread::GetInst().GetContext());
+  g_source_unref(source);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Port::PopDelayedMessage() {
+  int sent_bytes = 0;
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+  auto dm = queue_.front();
+
+  int ret = Write(dm->GetMessage(), dm->GetSize(), &sent_bytes);
+  if (ret == PORT_STATUS_ERROR_RESOURCE_UNAVAILABLE) {
+    dm->SetIndex(sent_bytes);
+  } else if (ret == PORT_STATUS_ERROR_IO_ERROR) {
+    ClearQueue();
+  } else {
+    delayed_message_size_ -= dm->GetOriginalSize();
+    queue_.pop();
+  }
+
+  _W("cache : count(%zu), delayed_message_size(%d), ret(%d), sent_bytes(%d)",
+      queue_.size(), delayed_message_size_, ret, sent_bytes);
+  return ret;
+}
+
+int Port::PushDelayedMessage(std::shared_ptr<DelayMessage> dm) {
+  std::lock_guard<std::recursive_mutex> lock(rw_mutex_);
+  if (queue_.empty()) {
+    int ret = ListenIOEvent();
+    if (ret != RPC_PORT_ERROR_NONE)
+      return ret;
+  }
+
+  delayed_message_size_ += dm->GetOriginalSize();
+  queue_.push(dm);
+
+  _W("cache : count(%zu), delayed_message_size(%d)",
+      queue_.size(), delayed_message_size_);
+  return RPC_PORT_ERROR_NONE;
+}
+// LCOV_EXCL_STOP
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/port-internal.hh b/src/rpc-port/port-internal.hh
new file mode 100644 (file)
index 0000000..64d33ec
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PORT_INTERNAL_HH_
+#define PORT_INTERNAL_HH_
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include <algorithm>
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace rpc_port {
+namespace internal {
+
+class Port : public std::enable_shared_from_this<Port> {
+ public:
+  Port(int fd, std::string id, std::string instance);
+  Port(int fd, std::string id);
+  virtual ~Port();
+
+  void Disconnect();
+  int SetPrivateSharing(const char* paths[], unsigned int size);
+  int SetPrivateSharing(const char* path);
+  int UnsetPrivateSharing();
+
+  int Read(void* buf, unsigned int size);
+  int Write(const void* buf, unsigned int size);
+  int Write(const void* buf, unsigned int size, int* sent_bytes);
+  int GetFd() const {
+    return fd_;
+  }
+
+  const std::string& GetId() const {
+    return id_;
+  }
+
+  std::recursive_mutex& GetMutex() const {
+    return mutex_;
+  }
+
+  const std::string& GetInstance() const {
+    return instance_;
+  }
+
+  uint32_t GetSeq() {
+    return ++seq_;
+  }
+
+ private:
+  // LCOV_EXCL_START
+  int SetReceiveTimeout(int timeout);
+  bool CanWrite();
+  void IgnoreIOEvent();
+  int ListenIOEvent();
+
+  class DelayMessage {
+   public:
+    DelayMessage(const char* msg, int start_index, int size);
+    ~DelayMessage() = default;
+    void SetIndex(int index);
+    int GetSize();
+    int GetOriginalSize();
+    char* GetMessage();
+
+   private:
+    std::vector<unsigned char> message_;
+    int index_;
+    int size_;
+  };
+
+  enum PortStatus {
+    PORT_STATUS_ERROR_NONE,
+    PORT_STATUS_ERROR_IO_ERROR,
+    PORT_STATUS_ERROR_RESOURCE_UNAVAILABLE
+  };
+
+  int PushDelayedMessage(std::shared_ptr<DelayMessage> dm);
+  int PopDelayedMessage();
+  static gboolean OnEventReceived(GIOChannel* io,
+      GIOCondition condition, gpointer data);
+  void ClearQueue();
+  // LCOV_EXCL_STOP
+
+  int fd_;
+  std::string id_;
+  std::string instance_;
+  std::atomic<uint32_t> seq_;
+  mutable std::recursive_mutex mutex_;
+  mutable std::recursive_mutex rw_mutex_;
+  std::queue<std::shared_ptr<DelayMessage>> queue_;
+  int delayed_message_size_ = 0;
+  GIOChannel* channel_ = nullptr;
+  guint source_id_ = 0;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PORT_INTERNAL_HH_
diff --git a/src/rpc-port/proxy-internal.cc b/src/rpc-port/proxy-internal.cc
new file mode 100644 (file)
index 0000000..cd52cd6
--- /dev/null
@@ -0,0 +1,867 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aul_svc.h>
+#include <dlog.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <uuid.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "aul-internal.hh"
+#include "debug-port-internal.hh"
+#include "exception-internal.hh"
+#include "include/rpc-port-internal.h"
+#include "log-private.hh"
+#include "proxy-internal.hh"
+#include "request-internal.hh"
+#include "response-internal.hh"
+
+#define EILLEGALACCESS 127
+
+namespace rpc_port {
+namespace internal {
+namespace {
+
+constexpr const char kPortTypeMain[] = "main";
+constexpr const char kPortTypeDelegate[] = "delegate";
+constexpr const char kDPrefix[] = "d::";
+constexpr const char kUdPrefix[] = "ud::";
+
+std::string GenInstance() {
+  uuid_t u;
+  uuid_generate(u);
+  char uuid[37];
+  uuid_unparse(u, uuid);
+  return std::string(uuid) + "@" + Aul::GetAppId(getpid());
+}
+
+int SendRequest(ClientSocket* client, const Request& request) {
+  tizen_base::Parcel parcel;
+  parcel.WriteParcelable(const_cast<Request&>(request));
+  size_t size = parcel.GetDataSize();
+  int ret = client->Send(reinterpret_cast<void*>(&size), sizeof(size));
+  if (ret != 0) {
+    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  ret = client->Send(parcel.GetData(), size);
+  if (ret != 0) {
+    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  return 0;
+}
+
+int ReceiveResponse(ClientSocket* client, Response** response) {
+  int flags = fcntl(client->GetFd(), F_GETFL, 0);
+  fcntl(client->GetFd(), F_SETFL, flags & ~O_NONBLOCK);
+
+  size_t size = 0;
+  int ret = client->Receive(reinterpret_cast<void*>(&size), sizeof(size));
+  if (ret != 0) {
+    // LCOV_EXCL_START
+    _E("Receive() is failed. error(%d)", ret);
+    fcntl(client->GetFd(), F_SETFL, flags);
+    return -1;
+    // LCOV_EXCL_STOP
+  }
+
+  uint8_t* buf = static_cast<uint8_t*>(malloc(size));
+  if (buf == nullptr) {
+    // LCOV_EXCL_START
+    _E("Out of memory");
+    fcntl(client->GetFd(), F_SETFL, flags);
+    return -1;
+    // LCOV_EXCL_STOP
+  }
+
+  ret = client->Receive(buf, size);
+  if (ret != 0) {
+    // LCOV_EXCL_START
+    _E("Receive() is failed. error(%d)", ret);
+    free(buf);
+    fcntl(client->GetFd(), F_SETFL, flags);
+    return -1;
+    // LCOV_EXCL_STOP
+  }
+
+  tizen_base::Parcel parcel(buf, size, false);
+  *response = new (std::nothrow) Response();
+  if (*response == nullptr) {
+    // LCOV_EXCL_START
+    _E("Out of memory");
+    fcntl(client->GetFd(), F_SETFL, flags);
+    return -1;
+    // LCOV_EXCL_STOP
+  }
+
+  parcel.ReadParcelable(*response);
+  fcntl(client->GetFd(), F_SETFL, flags);
+  return 0;
+}
+
+bool IsDaemon(const std::string& name) {
+  if (name.compare(0, strlen(kDPrefix), kDPrefix) == 0) return true;
+
+  if (name.compare(0, strlen(kUdPrefix), kUdPrefix) == 0) return true;
+
+  return false;
+}
+
+}  // namespace
+
+Proxy::Proxy() {
+  _D("Proxy::Proxy()");
+}
+
+Proxy::~Proxy() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  _D("Proxy::~Proxy()");
+  if (main_port_.get() != nullptr)
+    DebugPort::RemoveSession(main_port_->GetFd());  // LCOV_EXCL_LINE
+
+  listener_ = nullptr;
+  UnsetIdler();
+  UnsetConnTimer();
+  Cancel();
+}
+
+int Proxy::MainPortConnect(const std::string& instance, bool sync) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  fds_[0] = 0;
+  main_client_.reset(Client::Create(this, port_path_));
+  if (main_client_.get() == nullptr)
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+  Request request(instance.c_str(), kPortTypeMain);
+  int ret = SendRequest(main_client_.get(), request);
+  if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+  main_client_->SetNonblock();
+  if (sync) {
+    Response* response = nullptr;
+    ret = ReceiveResponse(main_client_.get(), &response);
+    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+    std::unique_ptr<Response> response_auto(response);
+    if (response->GetResult() != 0) {
+      _E("Permission denied");                  // LCOV_EXCL_LINE
+      return RPC_PORT_ERROR_PERMISSION_DENIED;  // LCOV_EXCL_LINE
+    }
+
+    fds_[0] = main_client_->RemoveFd();
+  } else {
+    ret = main_client_->Watch();
+    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Proxy::DelegatePortConnect(const std::string& instance, bool sync) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  fds_[1] = 0;
+  delegate_client_.reset(Client::Create(this, port_path_));
+  if (delegate_client_.get() == nullptr)
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+  Request request(instance.c_str(), kPortTypeDelegate);
+  int ret = SendRequest(delegate_client_.get(), request);
+  if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+  delegate_client_->SetNonblock();
+  if (sync) {
+    Response* response = nullptr;
+    ret = ReceiveResponse(delegate_client_.get(), &response);
+    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+    std::unique_ptr<Response> response_auto(response);
+    if (response->GetResult() != 0) {
+      _E("Permission denied");                  // LCOV_EXCL_LINE
+      return RPC_PORT_ERROR_PERMISSION_DENIED;  // LCOV_EXCL_LINE
+    }
+
+    fds_[1] = delegate_client_->RemoveFd();
+  } else {
+    ret = delegate_client_->Watch();
+    if (ret != 0) return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Proxy::Connect(bool sync) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  std::string instance = GenInstance();
+  int ret = MainPortConnect(instance, sync);
+  if (ret != RPC_PORT_ERROR_NONE) return ret;
+
+  ret = DelegatePortConnect(instance, sync);
+  if (ret != RPC_PORT_ERROR_NONE) return ret;
+
+  if (sync) {
+    main_port_.reset(new ProxyPort(this, fds_[0], target_appid_, false));
+    delegate_port_.reset(new ProxyPort(this, fds_[1], target_appid_));
+    DebugPort::AddSession(port_name_, target_appid_, fds_[0], fds_[1]);
+    listener_->OnConnected(target_appid_, main_port_.get());
+  }
+
+  return ret;
+}
+
+int Proxy::Connect(std::string appid, std::string port_name,
+    IEventListener* listener) {
+  if (listener == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (HasRequested()) {
+    _D("Already requested");  // LCOV_EXCL_LINE
+    return RPC_PORT_ERROR_INVALID_PARAMETER;  // LCOV_EXCL_LINE
+  }
+
+  listener_ = listener;
+  target_appid_ = std::move(appid);
+  port_name_ = std::move(port_name);
+  SetRealAppId(target_appid_);
+  main_port_.reset();
+  delegate_port_.reset();
+  port_path_ =
+      Aul::GetPortPath(real_appid_, port_name_, rpc_port_get_target_uid());
+
+  Cancel();
+  UnsetConnTimer();
+  if (!IsDaemon(real_appid_)) {
+    int ret = Aul::PrepareStub(real_appid_, port_name_,
+        rpc_port_get_target_uid());
+    if (ret != RPC_PORT_ERROR_NONE) {
+      listener_ = nullptr;
+      return ret;
+    }
+  }
+
+  if (Watch() != 0) {
+    listener_ = nullptr;  // LCOV_EXCL_LINE
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int Proxy::ConnectSync(std::string appid, std::string port_name,
+    IEventListener* listener) {
+  if (listener == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (HasRequested()) {
+    _D("Already requested");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  listener_ = listener;
+  target_appid_ = std::move(appid);
+  port_name_ = std::move(port_name);
+  SetRealAppId(target_appid_);
+  port_path_ =
+      Aul::GetPortPath(real_appid_, port_name_, rpc_port_get_target_uid());
+
+  if (!IsDaemon(real_appid_)) {
+    int ret = Aul::PrepareStub(real_appid_, port_name_,
+        rpc_port_get_target_uid());
+    if (ret != RPC_PORT_ERROR_NONE) {
+      listener_ = nullptr;
+      return ret;
+    }
+  }
+
+  if (!WaitUntilPortCreation())
+    return RPC_PORT_ERROR_IO_ERROR;
+
+  int ret = Connect(true);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    // LCOV_EXCL_START
+    listener_ = nullptr;
+    return ret;
+    // LCOV_EXCL_STOP
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+bool Proxy::WaitUntilPortCreation() {
+  file_monitor_.reset(new FileMonitor(port_path_));
+  int retry_count = 100;
+  do {
+    if (file_monitor_->Exist()) return true;
+
+    usleep(100 * 1000);
+    retry_count--;
+  } while (retry_count > 0);
+
+  if (!file_monitor_->Exist()) {
+    // LCOV_EXCL_START
+    _E("port(%s) of appid(%s) is not ready",
+        port_name_.c_str(), target_appid_.c_str());
+    return false;
+    // LCOV_EXCL_STOP
+  }
+
+  return true;
+}
+
+void Proxy::DisconnectPort() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (main_port_.get() != nullptr) {
+    DebugPort::RemoveSession(main_port_->GetFd());
+    main_port_.reset();
+  }
+}
+
+int Proxy::Watch() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  try {
+    file_monitor_.reset(new FileMonitor(port_path_, this));
+    file_monitor_->Start();
+    SetConnTimer();
+    SetIdler();
+  } catch (const Exception& e) {
+    LOGE("Exception occurs. error(%s)", e.what());
+    return -1;
+  }
+
+  return 0;
+}
+
+void Proxy::Cancel() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (!file_monitor_) return;
+
+  file_monitor_->Stop();
+}
+
+void Proxy::SetRealAppId(const std::string& alias_appid) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (!real_appid_.empty())
+    return;
+
+  if (IsDaemon(alias_appid)) {
+    real_appid_ = alias_appid;
+    return;
+  }
+
+  char* appid = nullptr;
+  int ret = aul_svc_get_appid_by_alias_appid(alias_appid.c_str(), &appid);
+  if (ret != AUL_SVC_RET_OK) {
+    real_appid_ = alias_appid;
+    return;
+  }
+
+  // LCOV_EXCL_START
+  std::unique_ptr<char, decltype(std::free)*> appid_ptr(appid, std::free);
+  real_appid_ = std::string(appid);
+  _W("alias_appid(%s), real_appid(%s)", alias_appid.c_str(), appid);
+  // LCOV_EXCL_STOP
+}
+
+std::recursive_mutex& Proxy::GetMutex() const {
+  return mutex_;
+}
+
+void Proxy::SetConnTimer() {
+  if (conn_timer_data_) {
+    _W("Already exists");  // LCOV_EXCL_START
+    return;  // LCOV_EXCL_START
+  }
+
+  conn_timer_data_ = CreateWeakPtr();
+  if (conn_timer_data_ == nullptr) {
+    _E("Out of memory");  // LCOV_EXCL_START
+    return;  // LCOV_EXCL_START
+  }
+
+  g_timeout_add_seconds(10, OnTimedOut, conn_timer_data_);
+}
+
+void Proxy::UnsetConnTimer() {
+  if (conn_timer_data_ == nullptr)
+    return;
+
+  GSource* source = g_main_context_find_source_by_user_data(nullptr,
+      conn_timer_data_);
+  if (source && !g_source_is_destroyed(source))
+    g_source_destroy(source);
+
+  DestroyWeakPtr(conn_timer_data_);
+  conn_timer_data_ = nullptr;
+}
+
+void Proxy::SetIdler() {
+  if (idler_data_) {
+    _W("Already exists");  // LCOV_EXCL_START
+    return;  // LCOV_EXCL_START
+  }
+
+  idler_data_ = CreateWeakPtr();
+  if (idler_data_ == nullptr) {
+    _E("Out of memory");  // LCOV_EXCL_START
+    return;  // LCOV_EXCL_START
+  }
+
+  g_idle_add(OnIdle, idler_data_);
+}
+
+void Proxy::UnsetIdler() {
+  if (idler_data_ == nullptr)
+    return;
+
+  GSource* source = g_main_context_find_source_by_user_data(nullptr,
+      idler_data_);
+  if (source && !g_source_is_destroyed(source))
+    g_source_destroy(source);
+
+  DestroyWeakPtr(idler_data_);
+  idler_data_ = nullptr;
+}
+
+void Proxy::OnFileCreated(const std::string& path) {
+  _W("appid=%s, port_name=%s, port_path=%s",
+      target_appid_.c_str(), port_name_.c_str(), path.c_str());
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  UnsetIdler();
+  Cancel();
+  if (listener_ == nullptr) return;  // LCOV_EXCL_LINE
+
+  int ret = Connect(false);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    // LCOV_EXCL_START
+    UnsetConnTimer();
+    auto* listener = listener_;
+    listener_ = nullptr;
+    if (ret == RPC_PORT_ERROR_PERMISSION_DENIED)
+      listener->OnRejected(target_appid_, ret);
+    else
+      listener->OnDisconnected(target_appid_);
+    // LCOV_EXCL_STOP
+  }
+}
+
+void Proxy::OnFileDeleted(const std::string& path) {
+  _W("appid=%s, port_name=%s, port_path=%s",
+      target_appid_.c_str(), port_name_.c_str(), path.c_str());
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  UnsetIdler();
+}
+
+gboolean Proxy::OnTimedOut(gpointer user_data) {
+  _E("Timed out");
+  auto* ptr = static_cast<std::weak_ptr<Proxy>*>(user_data);
+  auto proxy = ptr->lock();
+  if (proxy == nullptr) {
+    _E("Proxy is nullptr");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  if (proxy->conn_timer_data_ == nullptr) {
+    _E("Invalid context. proxy(%p)", proxy.get());  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  proxy->Cancel();
+  proxy->main_client_.reset();
+  proxy->delegate_client_.reset();
+  DestroyWeakPtr(proxy->conn_timer_data_);
+  proxy->conn_timer_data_ = nullptr;
+
+  auto* listener = proxy->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  proxy->listener_ = nullptr;
+  listener->OnRejected(proxy->target_appid_, RPC_PORT_ERROR_IO_ERROR);
+  return G_SOURCE_REMOVE;
+}
+
+gboolean Proxy::OnIdle(gpointer user_data) {
+  auto* ptr = static_cast<std::weak_ptr<Proxy>*>(user_data);
+  auto proxy = ptr->lock();
+  if (proxy == nullptr) {
+    _E("Proxy is nullptr");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  if (proxy->idler_data_ == nullptr) {
+    _E("Invalid context. proxy(%p)", proxy.get());  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  DestroyWeakPtr(proxy->idler_data_);
+  proxy->idler_data_ = nullptr;
+
+  if (proxy->file_monitor_->Exist()) {
+    proxy->OnFileCreated(proxy->port_path_);
+  } else {
+    proxy->OnFileDeleted(proxy->port_path_);
+  }
+
+  return G_SOURCE_REMOVE;
+}
+
+Proxy::ProxyPort::ProxyPort(Proxy* parent, int fd, const std::string& id,
+    bool receive)
+    : Port(fd, id), parent_(parent) {
+  Watch(receive);
+}
+
+Proxy::ProxyPort::~ProxyPort() {
+  if (disconn_source_ > 0)
+    g_source_remove(disconn_source_);
+
+  if (source_ > 0)
+    g_source_remove(source_);
+
+  if (channel_ != nullptr)
+    g_io_channel_unref(channel_);
+}
+
+int Proxy::ProxyPort::Watch(bool receive) {
+  channel_ = g_io_channel_unix_new(GetFd());
+  if (channel_ == nullptr) {
+    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  disconn_source_ = g_io_add_watch(channel_,
+      static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+      Proxy::ProxyPort::OnSocketDisconnected, parent_);
+  if (disconn_source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  if (!receive)
+    return 0;
+
+  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
+      Proxy::ProxyPort::OnDataReceived, parent_);
+  if (source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  return 0;
+}
+
+void Proxy::ProxyPort::SetDisconnectedSource(guint source_id) {
+  disconn_source_ = source_id;
+}
+
+void Proxy::ProxyPort::SetSource(guint source_id) {
+  source_ = source_id;
+}
+
+gboolean Proxy::ProxyPort::OnSocketDisconnected(GIOChannel* channel,
+    GIOCondition cond, gpointer user_data) {
+  auto* proxy = static_cast<Proxy*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  auto* listener = proxy->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  int fd = g_io_channel_unix_get_fd(channel);
+  _W("Socket was disconnected. fd(%d)", fd);
+  if (proxy->main_port_.get() != nullptr &&
+      proxy->main_port_->GetFd() == fd) {
+    proxy->main_port_->SetDisconnectedSource(0);
+  } else if (proxy->delegate_port_.get() != nullptr &&
+             proxy->delegate_port_->GetFd() == fd) {
+    proxy->delegate_port_->SetDisconnectedSource(0);
+  }
+
+  proxy->main_port_.reset();
+  proxy->delegate_port_.reset();
+  proxy->listener_ = nullptr;
+  listener->OnDisconnected(proxy->target_appid_);
+  DebugPort::RemoveSession(fd);
+  return G_SOURCE_REMOVE;
+}
+
+gboolean Proxy::ProxyPort::OnDataReceived(GIOChannel* channel,
+    GIOCondition cond, gpointer user_data) {
+  auto* proxy = static_cast<Proxy*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  auto* listener = proxy->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  int fd = g_io_channel_unix_get_fd(channel);
+  if (proxy->delegate_port_->GetFd() == fd) {
+    char buffer[4];
+    if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
+      _W("Socket was disconnected by stub. fd(%d)", fd);
+      proxy->listener_ = nullptr;
+      proxy->delegate_port_->SetSource(0);
+      if (proxy->main_port_.get() != nullptr) {
+        DebugPort::RemoveSession(proxy->main_port_->GetFd());
+        proxy->main_port_.reset();
+      }
+      proxy->delegate_port_.reset();
+      listener->OnDisconnected(proxy->target_appid_);
+      return G_SOURCE_REMOVE;
+    }
+
+    listener->OnReceived(proxy->target_appid_);
+  }
+
+  return G_SOURCE_CONTINUE;
+}
+
+Proxy::Client::Client(Proxy* parent) : parent_(parent) {
+}
+
+Proxy::Client::~Client() {
+  if (channel_)
+    g_io_channel_unref(channel_);
+
+  if (disconn_source_ > 0)
+    g_source_remove(disconn_source_);
+
+  if (source_ > 0)
+    g_source_remove(source_);
+}
+
+Proxy::Client* Proxy::Client::Create(Proxy* parent,
+    const std::string& endpoint) {
+  std::unique_ptr<Proxy::Client> client;
+  try {
+    client.reset(new (std::nothrow) Proxy::Client(parent));
+  } catch (const Exception& e) {
+    _E("Exception(%s) occurs", e.what());  // LCOV_EXCL_LINE
+    return nullptr;  // LCOV_EXCL_LINE
+  }
+
+  int ret;
+  int retry_count = 5;
+  do {
+    ret = client->Connect(endpoint);
+    if (ret == 0) {
+      break;
+    } else if (ret < 0) {
+      // LCOV_EXCL_START
+      _D("Connect() is failed");
+      usleep(100 * 1000);
+      retry_count--;
+      // LCOV_EXCL_STOP
+    }
+  } while (retry_count > 0);
+
+  if (ret != 0) {
+    _E("Connect() is failed");  // LCOV_EXCL_LINE
+    return nullptr;  // LCOV_EXCL_LINE
+  }
+
+  try {
+    client->SetReceiveTimeout(10000);
+  } catch (const Exception& e) {
+    _E("Exception occurs. error(%s)", e.what());  // LCOV_EXCL_LINE
+    return nullptr;  // LCOV_EXCL_LINE
+  }
+
+  _W("endpoint(%s), fd(%d)", endpoint.c_str(), client->GetFd());
+  return client.release();
+}
+
+int Proxy::Client::Watch() {
+  channel_ = g_io_channel_unix_new(GetFd());
+  if (channel_ == nullptr) {
+    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
+      Proxy::Client::OnResponseReceived, parent_);
+  if (source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  disconn_source_ = g_io_add_watch(channel_,
+      static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+      Proxy::Client::OnSocketDisconnected, parent_);
+  if (disconn_source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  return 0;
+}
+
+// LCOV_EXCL_START
+void Proxy::Client::SetDisconnectedSource(guint source) {
+  disconn_source_ = source;
+}
+// LCOV_EXCL_STOP
+
+void Proxy::Client::SetSource(guint source) {
+  source_ = source;
+}
+
+// LCOV_EXCL_START
+gboolean Proxy::Client::OnSocketDisconnected(GIOChannel* channel,
+    GIOCondition cond, gpointer user_data) {
+  auto* proxy = static_cast<Proxy*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  proxy->UnsetConnTimer();
+  auto* listener = proxy->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");
+    return G_SOURCE_REMOVE;
+  }
+
+  int fd = g_io_channel_unix_get_fd(channel);
+  _W("Socket was disconnected. fd(%d)", fd);
+  if (proxy->main_client_.get() != nullptr &&
+      proxy->main_client_->GetFd() == fd) {
+    proxy->main_client_->SetDisconnectedSource(0);
+  } else if (proxy->delegate_client_.get() != nullptr &&
+             proxy->delegate_client_->GetFd() == fd) {
+    proxy->delegate_client_->SetDisconnectedSource(0);
+  }
+
+  proxy->main_client_.reset();
+  proxy->delegate_client_.reset();
+  proxy->listener_ = nullptr;
+  listener->OnDisconnected(proxy->target_appid_);
+  return G_SOURCE_REMOVE;
+}
+// LCOV_EXCL_STOP
+
+gboolean Proxy::Client::OnResponseReceived(GIOChannel* channel,
+    GIOCondition cond, gpointer user_data) {
+  auto* proxy = static_cast<Proxy*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  proxy->UnsetConnTimer();
+  auto* listener = proxy->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  bool is_delegate = false;
+  std::unique_ptr<Client> client;
+  int fd = g_io_channel_unix_get_fd(channel);
+  if (proxy->main_client_.get() != nullptr &&
+      proxy->main_client_->GetFd() == fd) {
+    client.reset(proxy->main_client_.release());
+  } else if (proxy->delegate_client_.get() != nullptr &&
+             proxy->delegate_client_->GetFd() == fd) {
+    client.reset(proxy->delegate_client_.release());
+    is_delegate = true;
+  }
+
+  if (client.get() == nullptr) {
+    _E("Unknown fd(%d)", fd);  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  client->SetSource(0);
+
+  Response* response = nullptr;
+  int ret = ReceiveResponse(client.get(), &response);
+  if (ret != 0) {
+    // LCOV_EXCL_START
+    proxy->listener_ = nullptr;
+    proxy->main_client_.reset();
+    proxy->delegate_client_.reset();
+    listener->OnRejected(proxy->target_appid_, RPC_PORT_ERROR_IO_ERROR);
+    return G_SOURCE_REMOVE;
+    // LCOV_EXCL_STOP
+  }
+
+  std::unique_ptr<Response> response_auto(response);
+  if (response->GetResult() != 0) {
+    _E("Permission denied");
+    proxy->listener_ = nullptr;
+    proxy->main_client_.reset();
+    proxy->delegate_client_.reset();
+    listener->OnRejected(proxy->target_appid_,
+        RPC_PORT_ERROR_PERMISSION_DENIED);
+    return G_SOURCE_REMOVE;
+  }
+
+  client->SetNonblock();
+  int client_fd = client->RemoveFd();
+  if (is_delegate) {
+    _W("[DELEGATE] Result received");
+    proxy->fds_[1] = client_fd;
+    proxy->delegate_port_.reset(
+        new ProxyPort(proxy, proxy->fds_[1], proxy->target_appid_));
+  } else {
+    _W("[MAIN] Result received");
+    proxy->fds_[0] = client_fd;
+    proxy->main_port_.reset(
+        new ProxyPort(proxy, proxy->fds_[0], proxy->target_appid_, false));
+  }
+
+  if (proxy->main_port_.get() != nullptr &&
+      proxy->delegate_port_.get() != nullptr) {
+    _W("target_appid(%s), port_name(%s), main_fd(%d), delegate_fd(%d)",
+        proxy->target_appid_.c_str(), proxy->port_name_.c_str(),
+        proxy->fds_[0], proxy->fds_[1]);
+
+    DebugPort::AddSession(proxy->port_name_, proxy->target_appid_,
+        proxy->fds_[0], proxy->fds_[1]);
+    listener->OnConnected(proxy->target_appid_, proxy->main_port_.get());
+  }
+
+  return G_SOURCE_REMOVE;
+}
+
+std::shared_ptr<Proxy> Proxy::GetSharedPtr() {
+  return shared_from_this();
+}
+
+gpointer Proxy::CreateWeakPtr() {
+  auto* ptr = new (std::nothrow) std::weak_ptr<Proxy>(GetSharedPtr());
+  return static_cast<gpointer>(ptr);
+}
+
+void Proxy::DestroyWeakPtr(gpointer data) {
+  auto* ptr = static_cast<std::weak_ptr<Proxy>*>(data);
+  delete ptr;
+}
+
+bool Proxy::HasRequested() const {
+  return listener_ != nullptr &&
+      (!main_port_ || !delegate_port_ || main_port_->GetFd() > 0);
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/proxy-internal.hh b/src/rpc-port/proxy-internal.hh
new file mode 100644 (file)
index 0000000..2ef4dcc
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROXY_INTERNAL_HH_
+#define PROXY_INTERNAL_HH_
+
+#include <aul_rpc_port.h>
+#include <gio/gio.h>
+#include <glib-unix.h>
+#include <glib.h>
+
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include "client-socket-internal.hh"
+#include "file-monitor-internal.hh"
+#include "port-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+class Proxy : public std::enable_shared_from_this<Proxy>,
+              public FileMonitor::IEvent {
+ public:
+  Proxy();
+  virtual ~Proxy();
+
+  class IEventListener {
+   public:
+    virtual void OnConnected(const std::string& endpoint, Port* port) = 0;
+    virtual void OnDisconnected(const std::string& endpoint) = 0;
+    virtual void OnRejected(const std::string& endpoint, int err_code) = 0;
+    virtual void OnReceived(const std::string& endpoint) = 0;
+  };
+
+  int Connect(std::string appid, std::string port_name, IEventListener* ev);
+  int ConnectSync(std::string appid, std::string port_name, IEventListener* ev);
+  void DisconnectPort();
+
+  std::shared_ptr<Port> GetPort() const {
+    return main_port_;
+  }
+
+  std::shared_ptr<Port> GetDelegatePort() const {
+    return delegate_port_;
+  }
+
+  const std::string& GetPortName() {
+    return port_name_;
+  }
+
+ private:
+  class ProxyPort : public Port {
+   public:
+    ProxyPort(Proxy* parent, int fd, const std::string& id,
+        bool receive = true);
+    virtual ~ProxyPort();
+    void SetDisconnectedSource(guint source_id);
+    void SetSource(guint source_id);
+
+   private:
+    int Watch(bool receive);
+
+    static gboolean OnSocketDisconnected(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+    static gboolean OnDataReceived(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+
+   private:
+    Proxy* parent_ = nullptr;
+    GIOChannel* channel_ = nullptr;
+    guint disconn_source_ = 0;
+    guint source_ = 0;
+  };
+
+  class Client : public ClientSocket {
+   public:
+    explicit Client(Proxy* parent);
+    virtual ~Client();
+
+    static Client* Create(Proxy* parent, const std::string& endpoint);
+
+    int Watch();
+    void SetDisconnectedSource(guint source);
+    void SetSource(guint source);
+
+   private:
+    static gboolean OnSocketDisconnected(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+    static gboolean OnResponseReceived(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+
+   private:
+    Proxy* parent_;
+    GIOChannel* channel_ = nullptr;
+    guint disconn_source_ = 0;
+    guint source_ = 0;
+  };
+
+ private:
+  void OnFileCreated(const std::string& path) override;
+  void OnFileDeleted(const std::string& path) override;
+  static gboolean OnTimedOut(gpointer user_data);
+  static gboolean OnIdle(gpointer user_data);
+
+  void SetRealAppId(const std::string& alias_appid);
+  std::recursive_mutex& GetMutex() const;
+  int MainPortConnect(const std::string& instance, bool sync);
+  int DelegatePortConnect(const std::string& instance, bool sync);
+  int Connect(bool sync);
+  bool WaitUntilPortCreation();
+  int Watch();
+  void Cancel();
+  void SetConnTimer();
+  void UnsetConnTimer();
+  void SetIdler();
+  void UnsetIdler();
+
+  std::shared_ptr<Proxy> GetSharedPtr();
+  gpointer CreateWeakPtr();
+  static void DestroyWeakPtr(gpointer data);
+  bool HasRequested() const;
+
+ private:
+  std::string port_name_;
+  std::string port_path_;
+  std::shared_ptr<ProxyPort> main_port_;
+  std::shared_ptr<ProxyPort> delegate_port_;
+  IEventListener* listener_ = nullptr;
+  std::string target_appid_;
+  std::string real_appid_;
+  int fds_[2];
+  std::unique_ptr<Client> main_client_;
+  std::unique_ptr<Client> delegate_client_;
+  gpointer conn_timer_data_ = nullptr;
+  gpointer idler_data_ = nullptr;
+  mutable std::recursive_mutex mutex_;
+  std::unique_ptr<FileMonitor> file_monitor_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PROXY_INTERNAL_HH_
diff --git a/src/rpc-port/request-internal.cc b/src/rpc-port/request-internal.cc
new file mode 100644 (file)
index 0000000..c293c29
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "request-internal.hh"
+
+#include <utility>
+
+namespace rpc_port {
+namespace internal {
+
+Request::Request(std::string instance, std::string port_type)
+    : instance_(std::move(instance)),
+      port_type_(std::move(port_type)) {
+}
+
+void Request::SetPortType(std::string port_type) {
+  port_type_ = std::move(port_type);
+}
+
+const std::string& Request::GetInstance() {
+  return instance_;
+}
+
+const std::string& Request::GetPortType() {
+  return port_type_;
+}
+
+void Request::WriteToParcel(tizen_base::Parcel* parcel) const {
+  parcel->WriteString(instance_);
+  parcel->WriteString(port_type_);
+}
+
+void Request::ReadFromParcel(tizen_base::Parcel* parcel) {
+  instance_ = parcel->ReadString();
+  port_type_ = parcel->ReadString();
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/request-internal.hh b/src/rpc-port/request-internal.hh
new file mode 100644 (file)
index 0000000..3aa9b05
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef REQUEST_INTERNAL_HH_
+#define REQUEST_INTERNAL_HH_
+
+#include <parcel.hh>
+#include <parcelable.hh>
+
+#include <string>
+
+namespace rpc_port {
+namespace internal {
+
+class Request : public tizen_base::Parcelable {
+ public:
+  Request(std::string instance, std::string port_type);
+  Request() = default;
+  ~Request() = default;
+
+  void SetPortType(std::string port_type);
+  const std::string& GetInstance();
+  const std::string& GetPortType();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+ private:
+  std::string instance_;
+  std::string port_type_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // REQUEST_INTERNAL_HH_
diff --git a/src/rpc-port/response-internal.cc b/src/rpc-port/response-internal.cc
new file mode 100644 (file)
index 0000000..9d32604
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "response-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+Response::Response(int result) : result_(result) {
+}
+
+Response::Response() : result_(0) {
+}
+
+int Response::GetResult() {
+  return result_;
+}
+
+void Response::WriteToParcel(tizen_base::Parcel* parcel) const {
+  parcel->WriteInt32(result_);
+}
+
+void Response::ReadFromParcel(tizen_base::Parcel* parcel) {
+  parcel->ReadInt32(&result_);
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/response-internal.hh b/src/rpc-port/response-internal.hh
new file mode 100644 (file)
index 0000000..2c12ab2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RESPONSE_INTERNAL_HH_
+#define RESPONSE_INTERNAL_HH_
+
+#include <parcel.hh>
+#include <parcelable.hh>
+
+namespace rpc_port {
+namespace internal {
+
+class Response : public tizen_base::Parcelable {
+ public:
+  explicit Response(int result);
+  Response();
+  ~Response() = default;
+
+  int GetResult();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+ private:
+  int result_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // RESPONSE_INTERNAL_HH_
diff --git a/src/rpc-port/rpc-port-internal.cc b/src/rpc-port/rpc-port-internal.cc
new file mode 100644 (file)
index 0000000..ba78616
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aul_proc.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
+#include <unistd.h>
+
+#include <atomic>
+
+#include "include/rpc-port-internal.h"
+#include "include/rpc-port.h"
+#include "peer-cred-internal.hh"
+#include "port-internal.hh"
+
+#undef RPC_API
+#define RPC_API extern "C" __attribute__((visibility("default")))
+
+namespace {
+using namespace rpc_port::internal;
+
+constexpr uid_t kRegularUidMin = 5000;
+std::atomic<uid_t> __target_uid { getuid() };
+
+}  // namespace
+
+RPC_API void rpc_port_set_target_uid(uid_t target_uid) {
+  __target_uid.exchange(target_uid);
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+RPC_API uid_t rpc_port_get_target_uid(void) {
+  if (__target_uid < kRegularUidMin)
+    __target_uid.exchange(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
+
+  return __target_uid;
+}
+
+RPC_API int rpc_port_register_proc_info(const char* proc_name, bundle* extra) {
+  if (proc_name == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  int ret = aul_proc_register(proc_name, extra);
+  if (ret != AUL_R_OK)
+    return RPC_PORT_ERROR_IO_ERROR;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_deregister_proc_info(void) {
+  int ret = aul_proc_deregister();
+  if (ret != AUL_R_OK)
+    return RPC_PORT_ERROR_IO_ERROR;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int  rpc_port_get_peer_info(rpc_port_h h, pid_t* pid, uid_t* uid) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+  std::shared_ptr<PeerCred> cred(PeerCred::Get(port->GetFd()));
+  if (cred.get() == nullptr)
+    return RPC_PORT_ERROR_IO_ERROR;
+
+  if (pid)
+    *pid = cred->GetPid();
+
+  if (uid)
+    *uid = cred->GetUid();
+
+  return RPC_PORT_ERROR_NONE;
+}
+
diff --git a/src/rpc-port/rpc-port-parcel.cc b/src/rpc-port/rpc-port-parcel.cc
new file mode 100644 (file)
index 0000000..e78b6da
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2018 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/rpc-port-parcel.h"
+
+#include <parcel.hh>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+
+#include "log-private.hh"
+#include "parcel-internal.hh"
+#include "port-internal.hh"
+
+#define MAX_PARCEL_SIZE   (1024 * 1024 * 10)
+
+#undef RPC_API
+#define RPC_API extern "C" __attribute__((visibility("default")))
+
+using namespace rpc_port;
+
+RPC_API int rpc_port_parcel_create(rpc_port_parcel_h* h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = new (std::nothrow) internal::Parcel();
+  if (parcel == nullptr)
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+
+  *h = static_cast<rpc_port_parcel_h>(parcel);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h* h,
+    rpc_port_h port) {
+  int len;
+  unsigned char* buf;
+
+  if (h == nullptr || port == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  internal::Port* pt = static_cast<internal::Port*>(port);
+  {
+    std::lock_guard<std::recursive_mutex> lock(pt->GetMutex());
+    int ret = rpc_port_read(port, &len, 4);
+    if (ret != 0)
+      return ret;
+
+    if (len <= 0 || len > MAX_PARCEL_SIZE)
+      return RPC_PORT_ERROR_IO_ERROR;
+
+    buf = static_cast<unsigned char*>(malloc(len));
+    if (buf == nullptr) {
+      _E("Out of memory");  // LCOV_EXCL_LINE
+      return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+    }
+
+    ret = rpc_port_read(port, buf, len);
+    if (ret != 0) {
+      free(buf);  // LCOV_EXCL_LINE
+      return ret;  // LCOV_EXCL_LINE
+    }
+  }
+
+  auto* parcel = new (std::nothrow) internal::Parcel();
+  if (parcel == nullptr) {
+    // LCOV_EXCL_START
+    _E("Out of memory");
+    free(buf);
+    return RPC_PORT_ERROR_IO_ERROR;
+    // LCOV_EXCL_STOP
+  }
+
+  tizen_base::Parcel raw_parcel(buf, len, false);
+  raw_parcel.ReadParcelable(parcel);
+  *h = static_cast<rpc_port_parcel_h>(parcel);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_send(rpc_port_parcel_h h, rpc_port_h port) {
+  if (h == nullptr || port == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  tizen_base::Parcel raw_parcel;
+  raw_parcel.WriteParcelable(*parcel);
+  void* raw = reinterpret_cast<void*>(raw_parcel.GetData());
+  uint32_t len = static_cast<uint32_t>(raw_parcel.GetDataSize());
+  if (len <= 0)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  internal::Port* pt = static_cast<internal::Port*>(port);
+  {
+    std::lock_guard<std::recursive_mutex> lock(pt->GetMutex());
+    int ret = rpc_port_write(port, &len, sizeof(len));
+    if (ret != 0)
+      return ret;
+
+    ret = rpc_port_write(port, raw, len);
+    if (ret != 0)
+      return ret;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_destroy(rpc_port_parcel_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  delete parcel;
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_byte(parcel->GetHandle(), b);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int16(parcel->GetHandle(), i);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int32(parcel->GetHandle(), i);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int64(parcel->GetHandle(), i);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_float(parcel->GetHandle(), f);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_double(parcel->GetHandle(), d);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char* str) {
+  if (h == nullptr || str == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_string(parcel->GetHandle(), str);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_bool(parcel->GetHandle(), b);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle* b) {
+  if (h == nullptr || b == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  bundle_raw* raw = nullptr;
+  int len = 0;
+  bundle_encode(b, &raw, &len);
+  auto ptr = std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free);
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_string(parcel->GetHandle(), reinterpret_cast<char*>(raw));
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int32(parcel->GetHandle(), count);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_write(rpc_port_parcel_h h,
+    rpc_port_parcelable_t* parcelable, void* data) {
+  if (parcelable == nullptr || parcelable->to == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  parcelable->to(h, data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char* b) {
+  if (h == nullptr || b == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_byte(parcel->GetHandle(), b);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read_byte() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short* i) {
+  if (h == nullptr || i == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_int16(parcel->GetHandle(), i);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read_int16() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int* i) {
+  if (h == nullptr || i == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_int32(parcel->GetHandle(), i);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read_int32() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long* i) {
+  if (h == nullptr || i == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int64_t val = 0;
+  int ret = parcel_read_int64(parcel->GetHandle(), &val);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read_int64() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  *i = static_cast<long long>(val);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_float(rpc_port_parcel_h h, float* f) {
+  if (h == nullptr || f == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_float(parcel->GetHandle(), f);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read_float() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_double(rpc_port_parcel_h h, double* d) {
+  if (h == nullptr || d == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_double(parcel->GetHandle(), d);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read_double() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char** str) {
+  if (h == nullptr || str == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_string(parcel->GetHandle(), str);
+  if (ret != PARCEL_ERROR_NONE) {
+    _E("parcel_read_string() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    *str = strdup("");  // LCOV_EXCL_LINE
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool* b) {
+  if (h == nullptr || b == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_bool(parcel->GetHandle(), b);
+  if (ret != 0)
+    _E("parcel_read_bool() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle** b) {
+  if (h == nullptr || b == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  char* raw = nullptr;
+  int ret = parcel_read_string(parcel->GetHandle(), &raw);
+  if (ret != 0) {
+    _E("parcel_read_string() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    *b = bundle_create();  // LCOV_EXCL_LINE
+  } else {
+    *b = bundle_decode(reinterpret_cast<bundle_raw*>(raw), strlen(raw));
+    std::free(raw);
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int* count) {
+  if (h == nullptr || count == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_int32(parcel->GetHandle(), count);
+  if (ret != 0)
+    _E("parcel_read_int32() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_read(rpc_port_parcel_h h,
+    rpc_port_parcelable_t* parcelable, void* data) {
+  if (parcelable == nullptr || parcelable->from == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  parcelable->from(h, data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_burst_read(rpc_port_parcel_h h, unsigned char *buf,
+    unsigned int size) {
+  if (h == nullptr || buf == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  uint32_t valid_size = size & UINT32_MAX;
+  int ret = parcel_burst_read(parcel->GetHandle(), static_cast<void*>(buf),
+      valid_size);
+  if (ret != PARCEL_ERROR_NONE)
+    _E("parcel_read() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_burst_write(rpc_port_parcel_h h,
+    const unsigned char *buf, unsigned int size) {
+  if (h == nullptr || buf == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  uint32_t valid_size = size & UINT32_MAX;
+  parcel_burst_write(parcel->GetHandle(), static_cast<const void*>(buf),
+      valid_size);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_reset_reader(rpc_port_parcel_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_reset_reader(parcel->GetHandle());
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_to_array(rpc_port_parcel_h h, void** array,
+    unsigned int* size) {
+  if (h == nullptr || !array || !size)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  tizen_base::Parcel raw_parcel;
+  raw_parcel.WriteParcelable(*parcel);
+  void* raw = raw_parcel.GetData();
+  size_t raw_size = raw_parcel.GetDataSize();
+  if (raw_size == 0) {
+    _E("raw_size is zero");
+    return RPC_PORT_ERROR_IO_ERROR;
+  }
+
+  void* array_ptr = malloc(raw_size);
+  if (array_ptr == nullptr)
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+
+  memcpy(array_ptr, raw, raw_size);
+  *array = array_ptr;
+  *size = static_cast<unsigned int>(raw_size);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_from_array(rpc_port_parcel_h h, const void* array,
+    unsigned int size) {
+  if (h == nullptr || array == nullptr || size == 0)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  uint32_t valid_size = size & UINT32_MAX;
+  tizen_base::Parcel raw_parcel(array, valid_size);
+  raw_parcel.ReadParcelable(parcel);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_get_header(rpc_port_parcel_h h,
+    rpc_port_parcel_header_h* header) {
+  if (h == nullptr || header == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  auto* parcel_header = parcel->GetParcelHeader();
+  if (parcel_header == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  *header = reinterpret_cast<rpc_port_parcel_header_h>(
+      const_cast<internal::ParcelHeader*>(parcel_header));
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_set_tag(rpc_port_parcel_header_h header,
+    const char* tag) {
+  if (header == nullptr || tag == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  parcel_header->SetTag(tag);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_get_tag(rpc_port_parcel_header_h header,
+    char** tag) {
+  if (header == nullptr || tag == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  const std::string& raw_tag = parcel_header->GetTag();
+
+  *tag = strdup(raw_tag.c_str());
+  if (*tag == nullptr)
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_set_seq_num(rpc_port_parcel_header_h header,
+    int seq_num) {
+  if (header == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  parcel_header->SetSeqNum(seq_num);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_get_seq_num(rpc_port_parcel_header_h header,
+    int* seq_num) {
+  if (header == nullptr || seq_num == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  *seq_num = parcel_header->GetSeqNum();
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_get_timestamp(
+    rpc_port_parcel_header_h header, struct timespec* timestamp) {
+  if (header == nullptr || timestamp == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  *timestamp = parcel_header->GetTimeStamp();
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_get_raw(rpc_port_parcel_h h, void** raw,
+    unsigned int* size) {
+  if (h == nullptr || raw == nullptr || size == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  auto* raw_parcel = new (std::nothrow) tizen_base::Parcel();
+  if (raw_parcel != nullptr) {
+    raw_parcel->WriteParcelable(*parcel);
+    parcel->SetRawParcel(raw_parcel);
+    *raw = raw_parcel->GetData();
+    *size = static_cast<unsigned int>(raw_parcel->GetDataSize());
+  } else {
+    // LCOV_EXCL_START
+    _E("Out of memory");
+    *raw = nullptr;
+    *size = 0;
+    // LCOV_EXCL_STOP
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_create_from_raw(rpc_port_parcel_h* h,
+    const void* raw, unsigned int size) {
+  if (h == nullptr || raw == nullptr || size == 0)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  rpc_port_parcel_h parcel;
+  int ret = rpc_port_parcel_create(&parcel);
+  if (ret != RPC_PORT_ERROR_NONE)
+    return ret;
+
+  ret = rpc_port_parcel_from_array(parcel, raw, size);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    rpc_port_parcel_destroy(parcel);  // LCOV_EXCL_LINE
+    return ret;  // LCOV_EXCL_LINE
+  }
+
+  *h = parcel;
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_create_without_header(rpc_port_parcel_h* h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = new (std::nothrow) internal::Parcel(true);
+  if (parcel == nullptr)
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+
+  *h = static_cast<rpc_port_parcel_h>(parcel);
+  return RPC_PORT_ERROR_NONE;
+}
diff --git a/src/rpc-port/rpc-port.cc b/src/rpc-port/rpc-port.cc
new file mode 100644 (file)
index 0000000..023a9ab
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/rpc-port.h"
+
+#include <aul.h>
+#include <aul_rpc_port.h>
+#include <glib.h>
+
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include <utility>
+
+#include "include/rpc-port-internal.h"
+#include "log-private.hh"
+#include "port-internal.hh"
+#include "proxy-internal.hh"
+#include "stub-internal.hh"
+
+#undef RPC_API
+#define RPC_API extern "C" __attribute__((visibility("default")))
+
+namespace {
+using namespace rpc_port::internal;
+
+template<typename T>
+class Event {
+ public:
+  Event(T cb, void* user_data)
+      : cb_(cb), user_data_(user_data) {}
+
+  T cb_;
+  void* user_data_;
+};
+
+class ProxyExt : public Proxy, public Proxy::IEventListener {
+ public:
+  ProxyExt() : Proxy(), destroying_(false) {}
+  virtual ~ProxyExt() = default;
+
+  void AddConnectedEventListener(rpc_port_proxy_connected_event_cb cb,
+                            void* user_data) {
+    connected_events_.emplace_back(
+        new Event<rpc_port_proxy_connected_event_cb>(cb, user_data));
+  }
+
+  void AddDisconnectedEventListener(rpc_port_proxy_disconnected_event_cb cb,
+                                    void* user_data) {
+    disconnected_events_.emplace_back(
+        new Event<rpc_port_proxy_disconnected_event_cb>(cb, user_data));
+  }
+
+  void AddRejectedEventListener(rpc_port_proxy_rejected_event_cb cb,
+                                void* user_data) {
+    rejected_events_.emplace_back(
+        new Event<rpc_port_proxy_rejected_event_cb>(cb, user_data));
+  }
+
+  void AddReceivedEventListener(rpc_port_proxy_received_event_cb cb,
+                                void* user_data) {
+    received_events_.emplace_back(
+        new Event<rpc_port_proxy_received_event_cb>(cb, user_data));
+  }
+
+  void OnConnected(const std::string& endpoint, Port* port) override {
+    if (IsDestroying())
+      return;
+
+    for (auto& ev : connected_events_) {
+      ev->cb_(endpoint.c_str(), GetPortName().c_str(), port,
+              ev->user_data_);
+    }
+  }
+
+  void OnDisconnected(const std::string& endpoint) override {
+    if (IsDestroying())
+      return;
+
+    for (auto& ev : disconnected_events_) {
+      ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_);
+    }
+  }
+
+  void OnRejected(const std::string& endpoint, int err_code) override {
+    if (IsDestroying())
+      return;
+
+    for (auto& ev : rejected_events_) {
+      set_last_result(err_code);
+      ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_);
+    }
+  }
+
+  void OnReceived(const std::string& endpoint) override {
+    if (IsDestroying())
+      return;
+
+    for (auto& ev : received_events_) {
+      ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_);
+    }
+  }
+
+  std::recursive_mutex& GetMutex() const {
+    return mutex_;
+  }
+
+  void SetDestroying(bool destroying) {
+    destroying_ = destroying;
+  }
+
+  bool IsDestroying() {
+    return destroying_;
+  }
+
+ private:
+  std::atomic<bool> destroying_;
+  std::list<std::unique_ptr<Event<rpc_port_proxy_connected_event_cb>>>
+      connected_events_;
+  std::list<std::unique_ptr<Event<rpc_port_proxy_disconnected_event_cb>>>
+      disconnected_events_;
+  std::list<std::unique_ptr<Event<rpc_port_proxy_rejected_event_cb>>>
+      rejected_events_;
+  std::list<std::unique_ptr<Event<rpc_port_proxy_received_event_cb>>>
+      received_events_;
+  mutable std::recursive_mutex mutex_;
+};
+
+class StubExt : public Stub, public Stub::IEventListener {
+ public:
+  explicit StubExt(const std::string& port) : Stub(port), destroying_(false) {}
+  virtual ~StubExt() = default;
+
+  void AddConnectedEventListener(rpc_port_stub_connected_event_cb cb,
+                                 void* user_data) {
+    connected_events_.emplace_back(
+        new Event<rpc_port_stub_connected_event_cb>(cb, user_data));
+  }
+
+  void AddDisconnectedEventListener(rpc_port_stub_disconnected_event_cb cb,
+                                    void* user_data) {
+    disconnected_events_.emplace_back(
+        new Event<rpc_port_stub_disconnected_event_cb>(cb, user_data));
+  }
+
+  void AddReceivedEventListener(rpc_port_stub_received_event_cb cb,
+                                void* user_data) {
+    received_events_.emplace_back(
+        new Event<rpc_port_stub_received_event_cb>(cb, user_data));
+  }
+
+  void OnConnected(const std::string& sender,
+                   const std::string& instance) override {
+    if (IsDestroying())
+      return;
+
+    for (auto& ev : connected_events_) {
+      ev->cb_(sender.c_str(), instance.c_str(), ev->user_data_);
+    }
+  }
+
+  void OnDisconnected(const std::string& sender,
+                      const std::string& instance) override {
+    if (IsDestroying())
+      return;
+
+    for (auto& ev : disconnected_events_) {
+      ev->cb_(sender.c_str(), instance.c_str(), ev->user_data_);
+    }
+  }
+
+  int OnReceived(const std::string& sender,
+                 const std::string& instance, Port* port) override {
+    if (IsDestroying())
+      return -1;
+
+    for (auto& ev : received_events_) {
+      int ret = ev->cb_(sender.c_str(), instance.c_str(), port,
+          ev->user_data_);
+      if (ret != 0)
+        return -1;
+    }
+
+    return 0;
+  }
+
+  void SetDestroying(bool destroying) {
+    destroying_ = destroying;
+  }
+
+  bool IsDestroying() {
+    return destroying_;
+  }
+
+  std::recursive_mutex& GetMutex() const {
+    return mutex_;
+  }
+
+ private:
+  std::atomic<bool> destroying_;
+  std::list<std::unique_ptr<Event<rpc_port_stub_connected_event_cb>>>
+      connected_events_;
+  std::list<std::unique_ptr<Event<rpc_port_stub_disconnected_event_cb>>>
+      disconnected_events_;
+  std::list<std::unique_ptr<Event<rpc_port_stub_received_event_cb>>>
+      received_events_;
+  mutable std::recursive_mutex mutex_;
+};
+
+}  // namespace
+
+RPC_API int rpc_port_read(rpc_port_h h, void* buf, unsigned int size) {
+  if (h == nullptr || buf == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+  uint32_t seq = 0;
+  if (DebugPort::IsConnected()) {
+    int ret = port->Read(reinterpret_cast<uint32_t*>(&seq), sizeof(seq));
+    if (ret < 0) {
+      _E("IO Error");
+      return ret;
+    }
+  }
+
+  int ret = port->Read(buf, size);
+  if (ret < 0) {
+    _E("IO Error");
+    return ret;
+  }
+
+  if (DebugPort::IsConnected())
+    DebugPort::Send(port->GetFd(), true, seq, buf, size);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_write(rpc_port_h h, const void* buf, unsigned int size) {
+  if (h == nullptr || buf == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+  uint32_t seq = port->GetSeq();
+  if (DebugPort::IsConnected()) {
+    int ret = port->Write(reinterpret_cast<void*>(&seq), sizeof(seq));
+    if (ret < 0)
+      return ret;
+  }
+
+  int ret = port->Write(buf, size);
+  if (ret < 0)
+    return ret;
+
+  if (DebugPort::IsConnected())
+    DebugPort::Send(port->GetFd(), false, seq, buf, size);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_create(rpc_port_proxy_h* h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = new (std::nothrow) std::shared_ptr<::ProxyExt>(
+      new (std::nothrow) ::ProxyExt());
+  if (p == nullptr) {
+    _E("Out of memory");  // LCOV_EXCL_LINE
+  } else if (p->get() == nullptr) {
+    // LCOV_EXCL_START
+    _E("Out of memory");
+    delete p;
+    p = nullptr;
+    // LCOV_EXCL_STOP
+  } else {
+    _W("rpc_port_proxy_create(%p)", p->get());
+  }
+
+  *h = p;
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  if (proxy->IsDestroying()) {
+    _E("already destroyed. handle(%p)", proxy);  // LCOV_EXCL_LINE
+    abort();  // LCOV_EXCL_LINE
+  }
+
+  _W("rpc_port_proxy_destroy(%p)", proxy);
+  proxy->SetDestroying(true);
+  proxy->DisconnectPort();
+
+  g_idle_add_full(G_PRIORITY_HIGH,
+      [](gpointer data) -> gboolean {
+        auto p = static_cast<std::shared_ptr<::ProxyExt>*>(data);
+        _W("rpc_port_proxy_destroy(%p)", p->get());
+        delete p;
+        return G_SOURCE_REMOVE;
+      }, h, nullptr);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char* appid,
+    const char* port) {
+  if (h == nullptr || appid == nullptr || port == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  _W("rpc_port_proxy_connect(%p, %s, %s)", proxy, appid, port);
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  return proxy->Connect(appid, port, proxy);
+}
+
+// LCOV_EXCL_START
+RPC_API int rpc_port_proxy_connect_sync(rpc_port_proxy_h h, const char* appid,
+    const char* port) {
+  if (h == nullptr || appid == nullptr || port == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  _W("rpc_port_proxy_connect(%p, %s, %s)", proxy, appid, port);
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  return proxy->ConnectSync(appid, port, proxy);
+}
+// LCOV_EXCL_STOP
+
+RPC_API int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h,
+    rpc_port_proxy_connected_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  proxy->AddConnectedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h,
+    rpc_port_proxy_disconnected_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  proxy->AddDisconnectedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h,
+    rpc_port_proxy_rejected_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  proxy->AddRejectedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h,
+    rpc_port_proxy_received_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  proxy->AddReceivedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_proxy_get_port(rpc_port_proxy_h h,
+    rpc_port_port_type_e type, rpc_port_h* port) {
+  if (h == nullptr || port == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<std::shared_ptr<::ProxyExt>*>(h);
+  auto* proxy = p->get();
+  std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
+  rpc_port_h ret_port;
+
+  switch (type) {
+    case RPC_PORT_PORT_MAIN:
+      ret_port = static_cast<rpc_port_h>(proxy->GetPort().get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+    case RPC_PORT_PORT_CALLBACK:
+      ret_port = static_cast<rpc_port_h>(proxy->GetDelegatePort().get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_create(rpc_port_stub_h* h, const char* port_name) {
+  if (h == nullptr || port_name == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = new ::StubExt(port_name);
+  *h = p;
+  _W("rpc_port_stub_create(%p, %s)", p, port_name);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  _W("rpc_port_stub_destroy(%p)", h);
+  auto p = static_cast<::StubExt*>(h);
+  if (p->IsDestroying()) {
+    _E("already destroyed. handle(%p)", h);  // LCOV_EXCL_LINE
+    abort();  // LCOV_EXCL_LINE
+  }
+
+  p->SetDestroying(true);
+  aul_rpc_port_usr_destroy(p->GetPortName().c_str(), rpc_port_get_target_uid());
+  p->Ignore();
+  g_idle_add_full(G_PRIORITY_HIGH,
+      [](gpointer data) -> gboolean {
+        auto p = static_cast<::StubExt*>(data);
+        _W("rpc_port_stub_destroy(%p)", p);
+        delete p;
+        return G_SOURCE_REMOVE;
+      }, h, nullptr);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  _W("rpc_port_stub_listen(%p)", h);
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+
+  int fd = p->CreatePort();
+  if (fd < 0)
+    return RPC_PORT_ERROR_IO_ERROR;  // LCOV_EXCL_LINE
+
+  return p->Listen(p, fd);
+}
+
+RPC_API int rpc_port_stub_add_privilege(rpc_port_stub_h h,
+    const char* privilege) {
+  if (h == nullptr || privilege == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+
+  p->AddPrivilege(privilege);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_set_trusted(rpc_port_stub_h h,
+    const bool trusted) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+
+  p->SetTrusted(trusted);
+  return RPC_PORT_ERROR_NONE;
+}
+
+
+RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h,
+    rpc_port_stub_connected_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+
+  p->AddConnectedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h,
+    rpc_port_stub_disconnected_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+
+  p->AddDisconnectedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h,
+    rpc_port_stub_received_event_cb cb, void* user_data) {
+  if (h == nullptr || cb == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+
+  p->AddReceivedEventListener(cb, user_data);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_stub_get_port(rpc_port_stub_h h,
+    rpc_port_port_type_e type, const char* instance, rpc_port_h* port) {
+  if (h == nullptr || port == nullptr || instance == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+  rpc_port_h ret_port;
+
+  switch (type) {
+    case RPC_PORT_PORT_MAIN:
+      ret_port = static_cast<rpc_port_h>(p->FindPort(instance).get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+    case RPC_PORT_PORT_CALLBACK:
+      ret_port = static_cast<rpc_port_h>(p->FindDelegatePort(instance).get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_set_private_sharing_array(rpc_port_h h,
+    const char* paths[], unsigned int size) {
+  if (h == nullptr || paths == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+
+  return port->SetPrivateSharing(paths, size);
+}
+
+RPC_API int rpc_port_set_private_sharing(rpc_port_h h, const char* path) {
+  if (h == nullptr || path == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+
+  return port->SetPrivateSharing(path);
+}
+
+RPC_API int rpc_port_unset_private_sharing(rpc_port_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+
+  return port->UnsetPrivateSharing();
+}
+
+RPC_API int rpc_port_disconnect(rpc_port_h h) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto port = static_cast<Port*>(h);
+  port->Disconnect();
+
+  return RPC_PORT_ERROR_NONE;
+}
diff --git a/src/rpc-port/server-socket-internal.cc b/src/rpc-port/server-socket-internal.cc
new file mode 100644 (file)
index 0000000..3aca86b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "server-socket-internal.hh"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "exception-internal.hh"
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace internal {
+
+ServerSocket::ServerSocket() {
+  fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+  if (fd_ < 0) {
+    fd_ = -errno;
+    _E("socket() is failed. errno(%d)", errno);
+    THROW(fd_);
+  }
+}
+
+ServerSocket::ServerSocket(int fd) : fd_(fd) {
+  SetCloseOnExec();
+}
+
+ServerSocket::~ServerSocket() {
+  if (!IsClosed())
+    Close();
+}
+
+bool ServerSocket::IsClosed() {
+  return fd_ < 0 ? true : false;
+}
+
+ClientSocket* ServerSocket::Accept() {
+  struct sockaddr_un addr = { 0, };
+  socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_un));
+  auto* addr_ptr = reinterpret_cast<struct sockaddr*>(&addr);
+  int client_fd = accept(GetFd(), addr_ptr, &len);
+  if (client_fd == -1) {
+    _E("accept() is failed. errno(%d)", errno);  // LCOV_EXCL_LINE
+    return nullptr;  // LCOV_EXCL_LINE
+  }
+
+  return new (std::nothrow) ClientSocket(client_fd);
+}
+
+int ServerSocket::GetFd() const {
+  return fd_;
+}
+
+void ServerSocket::Bind(const std::string& bindpoint) {
+  struct sockaddr_un sockaddr = { 0, };
+  sockaddr.sun_family = AF_UNIX;
+  snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
+      bindpoint.c_str());
+  struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
+  socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
+
+  unlink(bindpoint.c_str());
+  int ret = bind(GetFd(), sockaddr_ptr, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("bind() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+// LCOV_EXCL_START
+int ServerSocket::Listen(int backlog) {
+  int ret = listen(GetFd(), backlog);
+  if (ret < 0) {
+    _E("listen() is failed. errno(%d)", errno);
+    return -1;
+  }
+
+  return 0;
+}
+
+void ServerSocket::SetCloseOnExec() {
+  int flags = fcntl(fd_, F_GETFL, 0);
+  fcntl(fd_, F_SETFL, flags | FD_CLOEXEC);
+  _I("Close on exec. fd(%d)", fd_);
+}
+// LCOV_EXCL_STOP
+
+void ServerSocket::Close() {
+  if (fd_ > -1) {
+    close(fd_);
+    fd_ = -1;
+  }
+}
+
+int ServerSocket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/server-socket-internal.hh b/src/rpc-port/server-socket-internal.hh
new file mode 100644 (file)
index 0000000..ee96155
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SERVER_SOCKET_INTERNAL_HH_
+#define SERVER_SOCKET_INTERNAL_HH_
+
+#include <string>
+
+#include "client-socket-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+class ServerSocket {
+ public:
+  ServerSocket();
+  explicit ServerSocket(int fd);
+  virtual ~ServerSocket();
+
+  bool IsClosed();
+  ClientSocket* Accept();
+  int GetFd() const;
+  void Bind(const std::string& endpoint);
+  int Listen(int backlog);
+  void Close();
+  void SetCloseOnExec();
+  int RemoveFd();
+
+ private:
+  int fd_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // SERVER_SOCKET_INTERNAL_HH_
diff --git a/src/rpc-port/stub-internal.cc b/src/rpc-port/stub-internal.cc
new file mode 100644 (file)
index 0000000..eccdd29
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stub-internal.hh"
+
+#include <aul.h>
+#include <aul_rpc_port.h>
+#include <dlog.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <systemd/sd-daemon.h>
+
+#include <utility>
+#include <vector>
+
+#include "aul-internal.hh"
+#include "debug-port-internal.hh"
+#include "exception-internal.hh"
+#include "include/rpc-port.h"
+#include "log-private.hh"
+#include "peer-cred-internal.hh"
+#include "request-internal.hh"
+#include "response-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+namespace {
+
+constexpr const char kPortTypeMain[] = "main";
+constexpr const char kPortTypeDelegate[] = "delegate";
+constexpr uid_t kRegularUidMin = 5000;
+
+int ReceiveRequest(ClientSocket* client, Request** request) {
+  size_t size = 0;
+  int ret = client->Receive(reinterpret_cast<void*>(&size), sizeof(size));
+  if (ret != 0) {
+    _E("Receive() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  std::vector<uint8_t> buf(size);
+  ret = client->Receive(buf.data(), size);
+  if (ret != 0) {
+    _E("Receive() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  tizen_base::Parcel parcel(buf.data(), buf.size());
+  *request = new (std::nothrow) Request();
+  if (*request == nullptr) {
+    _E("Out of memory");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  parcel.ReadParcelable(*request);
+  return 0;
+}
+
+int SendResponse(ClientSocket* client, const Response& response) {
+  tizen_base::Parcel parcel;
+  parcel.WriteParcelable(const_cast<Response&>(response));
+  size_t size = parcel.GetDataSize();
+  int ret = client->Send(reinterpret_cast<void*>(&size), sizeof(size));
+  if (ret != 0) {
+    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  ret = client->Send(parcel.GetData(), size);
+  if (ret != 0) {
+    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  return 0;
+}
+
+}  // namespace
+
+std::unordered_set<Stub*> Stub::freed_stubs_;
+
+Stub::Stub(std::string port_name) : port_name_(std::move(port_name)) {
+  _D("Stub::Stub()");
+  freed_stubs_.erase(this);
+}
+
+Stub::~Stub() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  _D("Stub::~Stub");
+  for (auto& p : ports_) {
+    if (!p->IsDelegate())
+      DebugPort::RemoveSession(p->GetFd());
+  }
+
+  listener_ = nullptr;
+  server_.reset();
+  if (!port_path_.empty()) {
+    _W("Delete port path=%s", port_path_.c_str());
+    unlink(port_path_.c_str());
+  }
+
+  freed_stubs_.insert(this);
+}
+
+int Stub::Listen(IEventListener* ev, int fd) {
+  if (ev == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (listener_ != nullptr) {
+    _E("Already listening!");  // LCOV_EXCL_LINE
+    return RPC_PORT_ERROR_INVALID_PARAMETER;  // LCOV_EXCL_LINE
+  }
+
+  listener_ = ev;
+  server_.reset(new Server(fd, this));
+  return server_->Listen();
+}
+
+void Stub::Ignore() {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  listener_ = nullptr;
+}
+
+void Stub::AddPrivilege(const std::string& privilege) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  access_controller_->AddPrivilege(privilege);
+}
+
+void Stub::SetTrusted(const bool trusted) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  access_controller_->SetTrusted(trusted);
+}
+
+// LCOV_EXCL_START
+std::shared_ptr<Port> Stub::FindPort(const std::string& instance) const {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  for (auto& p : ports_) {
+    if (p->GetInstance() == instance && !p->IsDelegate()) {
+      return p;
+    }
+  }
+
+  return {};
+}
+// LCOV_EXCL_STOP
+
+std::shared_ptr<Port> Stub::FindDelegatePort(
+    const std::string& instance) const {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  for (auto& p : ports_) {
+    if (p->GetInstance() == instance && p->IsDelegate()) {
+      return p;
+    }
+  }
+
+  return {};
+}
+
+const std::string& Stub::GetPortName() const {
+  return port_name_;
+}
+
+void Stub::RemoveAcceptedPorts(std::string instance) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  auto iter = ports_.begin();
+  while (iter != ports_.end()) {
+    if ((*iter)->GetInstance().compare(instance) == 0) {
+      LOGI("Close: fd(%d)", (*iter)->GetFd());
+      DebugPort::RemoveSession((*iter)->GetFd());
+      iter = ports_.erase(iter);
+    } else {
+      iter++;
+    }
+  }
+}
+
+int Stub::CreatePort() {
+  if (getenv("AUL_APPID") == nullptr) {
+    std::string name = Aul::GetName(getpid());
+    if (!name.empty()) {
+      port_path_ = Aul::GetPortPath(name, GetPortName(), getuid());
+      int fd = GetFdFromSystemd();
+      if (fd > -1) return fd;
+
+      fd = CreateServerSocket();
+      if (fd > -1) return fd;
+    }
+  }
+
+  int fd = -1;
+  int ret = aul_rpc_port_usr_create(GetPortName().c_str(), getuid(), &fd);
+  if (ret != AUL_R_OK) {
+    // LCOV_EXCL_START
+    _E("aul_rpc_port_usr_create() is failed. error(%d)", ret);
+    return RPC_PORT_ERROR_IO_ERROR;
+    // LCOV_EXCL_STOP
+  }
+
+  return fd;
+}
+
+int Stub::GetFdFromSystemd() {
+  int fds = sd_listen_fds(0);
+  for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; ++fd) {
+    if (sd_is_socket_unix(fd, SOCK_STREAM, 1, port_path_.c_str(), 0) > 0)
+      return fd;
+  }
+
+  _E("There is no socket stream");
+  return -1;
+}
+
+int Stub::CreateServerSocket() {
+  try {
+    ServerSocket socket;
+    socket.Bind(port_path_);
+    socket.Listen(128);
+    return socket.RemoveFd();
+  } catch (const Exception& e) {
+    _E("Exception occurs. error(%s)", e.what());
+    return -1;
+  }
+}
+
+gboolean Stub::AcceptedPort::OnDataReceived(GIOChannel* channel,
+    GIOCondition cond, gpointer user_data) {
+  auto* stub = static_cast<Stub*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(stub->GetMutex());
+  auto* listener = stub->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  int fd = g_io_channel_unix_get_fd(channel);
+  for (auto& p : stub->ports_) {
+    if (p->GetFd() == fd && !p->IsDelegate()) {
+      char buffer[4];
+      if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
+        _W("Socket was disconnected from proxy. fd(%d)", fd);
+        listener->OnDisconnected(p->GetId(), p->GetInstance());
+        stub->RemoveAcceptedPorts(p->GetInstance());
+        Aul::NotifyRpcFinished();
+        return G_SOURCE_CONTINUE;
+      }
+
+      int ret = stub->listener_->OnReceived(p->GetId(), p->GetInstance(),
+          p.get());
+      if (ret != 0) {
+        _W("Invalid protocol");
+        listener->OnDisconnected(p->GetId(), p->GetInstance());
+        stub->RemoveAcceptedPorts(p->GetInstance());
+        Aul::NotifyRpcFinished();
+        return G_SOURCE_CONTINUE;
+      }
+
+      break;
+    }
+  }
+
+  return G_SOURCE_CONTINUE;
+}
+
+gboolean Stub::AcceptedPort::OnSocketDisconnected(GIOChannel* channel,
+    GIOCondition cond, gpointer user_data) {
+  auto* stub = static_cast<Stub*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(stub->GetMutex());
+  auto* listener = stub->listener_;
+  if (listener == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  int fd = g_io_channel_unix_get_fd(channel);
+  _W("Socket was disconnected. fd(%d)", fd);
+  for (auto& p : stub->ports_) {
+    if (p->GetFd() == fd) {
+      listener->OnDisconnected(p->GetId(), p->GetInstance());
+      stub->RemoveAcceptedPorts(p->GetInstance());
+      Aul::NotifyRpcFinished();
+      break;
+    }
+  }
+
+  return G_SOURCE_REMOVE;
+}
+
+void Stub::AddAcceptedPort(const std::string& sender_appid,
+    const std::string& instance, const std::string& port_type, int fd) {
+  std::lock_guard<std::recursive_mutex> lock(GetMutex());
+  if (port_type == kPortTypeMain) {
+    auto* main_port = new AcceptedPort(this, false, fd, sender_appid,
+        instance, true);
+    ports_.emplace_back(main_port);
+    return;
+  }
+
+  auto* delegate_port = new AcceptedPort(this, true, fd, sender_appid,
+      instance, false);
+  ports_.emplace_back(delegate_port);
+
+  int main_fd = -1;
+  for (auto& p : ports_) {
+    if (p->GetId() == delegate_port->GetId() &&
+        p->GetInstance() == delegate_port->GetInstance() &&
+        p->GetFd() != delegate_port->GetFd()) {
+      main_fd = p->GetFd();
+      break;
+    }
+  }
+
+  _W("sender_appid(%s), instance(%s), main_fd(%d), delegate_fd(%d)",
+      sender_appid.c_str(), instance.c_str(), main_fd, fd);
+  DebugPort::AddSession(port_name_, sender_appid, main_fd, fd);
+  listener_->OnConnected(sender_appid, instance);
+}
+
+std::recursive_mutex& Stub::GetMutex() const {
+  return mutex_;
+}
+
+Stub::AcceptedPort::AcceptedPort(Stub* parent, bool isDelegate, int fd,
+    std::string id, std::string inst, bool watch)
+    : Port(fd, std::move(id), std::move(inst)), parent_(parent),
+      is_delegate_(isDelegate) {
+  Watch(watch);
+}
+
+// LCOV_EXCL_START
+Stub::AcceptedPort::AcceptedPort(Stub* parent, bool isDelegate, int fd,
+    std::string id, bool watch)
+    : Port(fd, std::move(id)), parent_(parent),
+      is_delegate_(isDelegate) {
+  Watch(watch);
+}
+// LCOV_EXCL_STOP
+
+Stub::AcceptedPort::~AcceptedPort() {
+  if (disconn_source_ > 0)
+    g_source_remove(disconn_source_);
+
+  if (source_ > 0)
+    g_source_remove(source_);
+
+  if (channel_ != nullptr)
+    g_io_channel_unref(channel_);
+}
+
+int Stub::AcceptedPort::Watch(bool receive) {
+  channel_ = g_io_channel_unix_new(GetFd());
+  if (channel_ == nullptr) {
+    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  disconn_source_ = g_io_add_watch(channel_,
+      static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+      OnSocketDisconnected, parent_);
+  if (disconn_source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  if (!receive)
+    return 0;
+
+  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
+      OnDataReceived, parent_);
+  if (source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  return 0;
+}
+
+Stub::Server::Server(int fd, Stub* parent)
+    : ServerSocket(fd),
+      parent_(parent) {
+}
+
+Stub::Server::~Server() {
+  if (channel_)
+    g_io_channel_unref(channel_);
+
+  if (source_ > 0)
+    g_source_remove(source_);
+}
+
+int Stub::Server::Listen() {
+  channel_ = g_io_channel_unix_new(GetFd());
+  if (channel_ == nullptr) {
+    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
+      OnRequestReceived, parent_);
+  if (source_ == 0) {
+    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
+    return -1;  // LCOV_EXCL_LINE
+  }
+
+  return 0;
+}
+
+gboolean Stub::Server::OnRequestReceived(GIOChannel* channel, GIOCondition cond,
+    gpointer user_data) {
+  auto* stub = static_cast<Stub*>(user_data);
+  std::lock_guard<std::recursive_mutex> lock(stub->GetMutex());
+  if (stub->listener_ == nullptr) {
+    _E("Invalid context");  // LCOV_EXCL_LINE
+    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
+  }
+
+  std::shared_ptr<ClientSocket> client(stub->server_->Accept());
+  if (client.get() == nullptr) {
+    _E("Out of memory");  // LCOV_EXCL_LINE
+    return G_SOURCE_CONTINUE;  // LCOV_EXCL_LINE
+  }
+
+  Request* request = nullptr;
+  int ret = ReceiveRequest(client.get(), &request);
+  if (ret != 0)
+    return G_SOURCE_CONTINUE;  // LCOV_EXCL_LINE
+
+  std::shared_ptr<Request> request_auto(request);
+  std::shared_ptr<PeerCred> cred(PeerCred::Get(client->GetFd()));
+  if (cred.get() == nullptr) {
+    _E("Failed to create peer credentials");  // LCOV_EXCL_LINE
+    return G_SOURCE_CONTINUE;  // LCOV_EXCL_LINE
+  }
+
+  std::string app_id = Aul::GetAppId(cred->GetPid());
+  auto response_func = [=](int res) -> void {
+    if (freed_stubs_.find(stub) != freed_stubs_.end())
+      return;  // LCOV_EXCL_LINE
+
+    Response response(res);
+    int ret = SendResponse(client.get(), response);
+    if (ret != 0)
+      return;  // LCOV_EXCL_LINE
+
+    if (res != 0) {
+      _E("Access denied. fd(%d), pid(%d)",
+          client->GetFd(), cred->GetPid());  // LCOV_EXCL_LINE
+      return;              // LCOV_EXCL_LINE
+    }
+
+    client->SetNonblock();
+    int client_fd = client->RemoveFd();
+    stub->AddAcceptedPort(app_id, request_auto->GetInstance(),
+        request_auto->GetPortType(), client_fd);
+  };
+
+  int res;
+  if (cred->GetUid() >= kRegularUidMin) {
+    if (cred->GetUid() != getuid() && getuid() >= kRegularUidMin) {
+      _E("Reject request. %u:%u", cred->GetUid(), getuid());  // LCOV_EXCL_LINE
+      res = -1;  // LCOV_EXCL_LINE
+    } else {
+      stub->access_controller_->CheckAsync(client->GetFd(), app_id,
+          response_func);
+      return G_SOURCE_CONTINUE;
+    }
+  } else {
+    _W("Bypass access control. pid(%d), uid(%u)",
+        cred->GetPid(), cred->GetUid());
+    res = 0;
+  }
+
+  response_func(res);
+  return G_SOURCE_CONTINUE;
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/rpc-port/stub-internal.hh b/src/rpc-port/stub-internal.hh
new file mode 100644 (file)
index 0000000..b1ac248
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STUB_INTERNAL_HH_
+#define STUB_INTERNAL_HH_
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <glib-unix.h>
+
+#include <list>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_set>
+
+#include "ac-internal.hh"
+#include "debug-port-internal.hh"
+#include "port-internal.hh"
+#include "server-socket-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+class Stub {
+ public:
+  class IEventListener {
+   public:
+    virtual void OnConnected(const std::string& sender,
+        const std::string& instance) = 0;
+    virtual void OnDisconnected(const std::string& sender,
+        const std::string& instance) = 0;
+    virtual int OnReceived(const std::string& sender,
+        const std::string& instance, Port* port) = 0;
+  };
+
+  explicit Stub(std::string port_name);
+  virtual ~Stub();
+
+  int Listen(IEventListener* ev, int fd);
+  void Ignore();
+  void AddPrivilege(const std::string& privilege);
+  void SetTrusted(const bool trusted);
+  std::shared_ptr<Port> FindPort(const std::string& instance) const;
+  std::shared_ptr<Port> FindDelegatePort(const std::string& instance) const;
+  const std::string& GetPortName() const;
+  int CreatePort();
+
+ private:
+  class AcceptedPort : public Port {
+   public:
+    AcceptedPort(Stub* parent, bool isDelegate, int fd, std::string id,
+        std::string inst, bool receive);
+    AcceptedPort(Stub* parent, bool isDelegate, int fd, std::string id,
+        bool receive);
+    virtual ~AcceptedPort();
+    bool IsDelegate() const {
+      return is_delegate_;
+    }
+
+   private:
+    int Watch(bool receive);
+    static gboolean OnDataReceived(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+    static gboolean OnSocketDisconnected(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+
+   private:
+    GIOChannel* channel_ = nullptr;
+    guint disconn_source_ = 0;
+    guint source_ = 0;
+    Stub* parent_;
+    bool is_delegate_ = false;
+  };
+
+  class Server : public ServerSocket {
+   public:
+    Server(int fd, Stub* parent);
+    virtual ~Server();
+
+    int Listen();
+
+   private:
+    static gboolean OnRequestReceived(GIOChannel* channel, GIOCondition cond,
+        gpointer user_data);
+
+   private:
+    Stub* parent_;
+    GIOChannel* channel_ = nullptr;
+    guint source_ = 0;
+  };
+
+  void AddAcceptedPort(const std::string& sender_appid,
+      const std::string& instance, const std::string& port_type, int fd);
+  void RemoveAcceptedPorts(std::string instance);
+  std::recursive_mutex& GetMutex() const;
+  int GetFdFromSystemd();
+  int CreateServerSocket();
+
+ private:
+  std::shared_ptr<AccessController> access_controller_ =
+      std::make_shared<AccessController>();
+  std::string port_name_;
+  std::string port_path_;
+  std::list<std::shared_ptr<AcceptedPort>> ports_;
+  IEventListener* listener_ = nullptr;
+  std::unique_ptr<Server> server_;
+  mutable std::recursive_mutex mutex_;
+  static std::unordered_set<Stub*> freed_stubs_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // STUB_INTERNAL_HH_
diff --git a/src/server-socket-internal.cc b/src/server-socket-internal.cc
deleted file mode 100644 (file)
index 3aca86b..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "server-socket-internal.hh"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "exception-internal.hh"
-#include "log-private.hh"
-
-namespace rpc_port {
-namespace internal {
-
-ServerSocket::ServerSocket() {
-  fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
-  if (fd_ < 0) {
-    fd_ = -errno;
-    _E("socket() is failed. errno(%d)", errno);
-    THROW(fd_);
-  }
-}
-
-ServerSocket::ServerSocket(int fd) : fd_(fd) {
-  SetCloseOnExec();
-}
-
-ServerSocket::~ServerSocket() {
-  if (!IsClosed())
-    Close();
-}
-
-bool ServerSocket::IsClosed() {
-  return fd_ < 0 ? true : false;
-}
-
-ClientSocket* ServerSocket::Accept() {
-  struct sockaddr_un addr = { 0, };
-  socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_un));
-  auto* addr_ptr = reinterpret_cast<struct sockaddr*>(&addr);
-  int client_fd = accept(GetFd(), addr_ptr, &len);
-  if (client_fd == -1) {
-    _E("accept() is failed. errno(%d)", errno);  // LCOV_EXCL_LINE
-    return nullptr;  // LCOV_EXCL_LINE
-  }
-
-  return new (std::nothrow) ClientSocket(client_fd);
-}
-
-int ServerSocket::GetFd() const {
-  return fd_;
-}
-
-void ServerSocket::Bind(const std::string& bindpoint) {
-  struct sockaddr_un sockaddr = { 0, };
-  sockaddr.sun_family = AF_UNIX;
-  snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
-      bindpoint.c_str());
-  struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
-  socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
-
-  unlink(bindpoint.c_str());
-  int ret = bind(GetFd(), sockaddr_ptr, len);
-  if (ret < 0) {
-    ret = -errno;
-    _E("bind() is failed. errno(%d)", errno);
-    THROW(ret);
-  }
-}
-
-// LCOV_EXCL_START
-int ServerSocket::Listen(int backlog) {
-  int ret = listen(GetFd(), backlog);
-  if (ret < 0) {
-    _E("listen() is failed. errno(%d)", errno);
-    return -1;
-  }
-
-  return 0;
-}
-
-void ServerSocket::SetCloseOnExec() {
-  int flags = fcntl(fd_, F_GETFL, 0);
-  fcntl(fd_, F_SETFL, flags | FD_CLOEXEC);
-  _I("Close on exec. fd(%d)", fd_);
-}
-// LCOV_EXCL_STOP
-
-void ServerSocket::Close() {
-  if (fd_ > -1) {
-    close(fd_);
-    fd_ = -1;
-  }
-}
-
-int ServerSocket::RemoveFd() {
-  int fd = fd_;
-  fd_ = -1;
-  return fd;
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/server-socket-internal.hh b/src/server-socket-internal.hh
deleted file mode 100644 (file)
index ee96155..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SERVER_SOCKET_INTERNAL_HH_
-#define SERVER_SOCKET_INTERNAL_HH_
-
-#include <string>
-
-#include "client-socket-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-class ServerSocket {
- public:
-  ServerSocket();
-  explicit ServerSocket(int fd);
-  virtual ~ServerSocket();
-
-  bool IsClosed();
-  ClientSocket* Accept();
-  int GetFd() const;
-  void Bind(const std::string& endpoint);
-  int Listen(int backlog);
-  void Close();
-  void SetCloseOnExec();
-  int RemoveFd();
-
- private:
-  int fd_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // SERVER_SOCKET_INTERNAL_HH_
diff --git a/src/stub-internal.cc b/src/stub-internal.cc
deleted file mode 100644 (file)
index eccdd29..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "stub-internal.hh"
-
-#include <aul.h>
-#include <aul_rpc_port.h>
-#include <dlog.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <systemd/sd-daemon.h>
-
-#include <utility>
-#include <vector>
-
-#include "aul-internal.hh"
-#include "debug-port-internal.hh"
-#include "exception-internal.hh"
-#include "include/rpc-port.h"
-#include "log-private.hh"
-#include "peer-cred-internal.hh"
-#include "request-internal.hh"
-#include "response-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-namespace {
-
-constexpr const char kPortTypeMain[] = "main";
-constexpr const char kPortTypeDelegate[] = "delegate";
-constexpr uid_t kRegularUidMin = 5000;
-
-int ReceiveRequest(ClientSocket* client, Request** request) {
-  size_t size = 0;
-  int ret = client->Receive(reinterpret_cast<void*>(&size), sizeof(size));
-  if (ret != 0) {
-    _E("Receive() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  std::vector<uint8_t> buf(size);
-  ret = client->Receive(buf.data(), size);
-  if (ret != 0) {
-    _E("Receive() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  tizen_base::Parcel parcel(buf.data(), buf.size());
-  *request = new (std::nothrow) Request();
-  if (*request == nullptr) {
-    _E("Out of memory");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  parcel.ReadParcelable(*request);
-  return 0;
-}
-
-int SendResponse(ClientSocket* client, const Response& response) {
-  tizen_base::Parcel parcel;
-  parcel.WriteParcelable(const_cast<Response&>(response));
-  size_t size = parcel.GetDataSize();
-  int ret = client->Send(reinterpret_cast<void*>(&size), sizeof(size));
-  if (ret != 0) {
-    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  ret = client->Send(parcel.GetData(), size);
-  if (ret != 0) {
-    _E("Send() is failed. error(%d)", ret);  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  return 0;
-}
-
-}  // namespace
-
-std::unordered_set<Stub*> Stub::freed_stubs_;
-
-Stub::Stub(std::string port_name) : port_name_(std::move(port_name)) {
-  _D("Stub::Stub()");
-  freed_stubs_.erase(this);
-}
-
-Stub::~Stub() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  _D("Stub::~Stub");
-  for (auto& p : ports_) {
-    if (!p->IsDelegate())
-      DebugPort::RemoveSession(p->GetFd());
-  }
-
-  listener_ = nullptr;
-  server_.reset();
-  if (!port_path_.empty()) {
-    _W("Delete port path=%s", port_path_.c_str());
-    unlink(port_path_.c_str());
-  }
-
-  freed_stubs_.insert(this);
-}
-
-int Stub::Listen(IEventListener* ev, int fd) {
-  if (ev == nullptr)
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (listener_ != nullptr) {
-    _E("Already listening!");  // LCOV_EXCL_LINE
-    return RPC_PORT_ERROR_INVALID_PARAMETER;  // LCOV_EXCL_LINE
-  }
-
-  listener_ = ev;
-  server_.reset(new Server(fd, this));
-  return server_->Listen();
-}
-
-void Stub::Ignore() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  listener_ = nullptr;
-}
-
-void Stub::AddPrivilege(const std::string& privilege) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  access_controller_->AddPrivilege(privilege);
-}
-
-void Stub::SetTrusted(const bool trusted) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  access_controller_->SetTrusted(trusted);
-}
-
-// LCOV_EXCL_START
-std::shared_ptr<Port> Stub::FindPort(const std::string& instance) const {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  for (auto& p : ports_) {
-    if (p->GetInstance() == instance && !p->IsDelegate()) {
-      return p;
-    }
-  }
-
-  return {};
-}
-// LCOV_EXCL_STOP
-
-std::shared_ptr<Port> Stub::FindDelegatePort(
-    const std::string& instance) const {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  for (auto& p : ports_) {
-    if (p->GetInstance() == instance && p->IsDelegate()) {
-      return p;
-    }
-  }
-
-  return {};
-}
-
-const std::string& Stub::GetPortName() const {
-  return port_name_;
-}
-
-void Stub::RemoveAcceptedPorts(std::string instance) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  auto iter = ports_.begin();
-  while (iter != ports_.end()) {
-    if ((*iter)->GetInstance().compare(instance) == 0) {
-      LOGI("Close: fd(%d)", (*iter)->GetFd());
-      DebugPort::RemoveSession((*iter)->GetFd());
-      iter = ports_.erase(iter);
-    } else {
-      iter++;
-    }
-  }
-}
-
-int Stub::CreatePort() {
-  if (getenv("AUL_APPID") == nullptr) {
-    std::string name = Aul::GetName(getpid());
-    if (!name.empty()) {
-      port_path_ = Aul::GetPortPath(name, GetPortName(), getuid());
-      int fd = GetFdFromSystemd();
-      if (fd > -1) return fd;
-
-      fd = CreateServerSocket();
-      if (fd > -1) return fd;
-    }
-  }
-
-  int fd = -1;
-  int ret = aul_rpc_port_usr_create(GetPortName().c_str(), getuid(), &fd);
-  if (ret != AUL_R_OK) {
-    // LCOV_EXCL_START
-    _E("aul_rpc_port_usr_create() is failed. error(%d)", ret);
-    return RPC_PORT_ERROR_IO_ERROR;
-    // LCOV_EXCL_STOP
-  }
-
-  return fd;
-}
-
-int Stub::GetFdFromSystemd() {
-  int fds = sd_listen_fds(0);
-  for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; ++fd) {
-    if (sd_is_socket_unix(fd, SOCK_STREAM, 1, port_path_.c_str(), 0) > 0)
-      return fd;
-  }
-
-  _E("There is no socket stream");
-  return -1;
-}
-
-int Stub::CreateServerSocket() {
-  try {
-    ServerSocket socket;
-    socket.Bind(port_path_);
-    socket.Listen(128);
-    return socket.RemoveFd();
-  } catch (const Exception& e) {
-    _E("Exception occurs. error(%s)", e.what());
-    return -1;
-  }
-}
-
-gboolean Stub::AcceptedPort::OnDataReceived(GIOChannel* channel,
-    GIOCondition cond, gpointer user_data) {
-  auto* stub = static_cast<Stub*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(stub->GetMutex());
-  auto* listener = stub->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  int fd = g_io_channel_unix_get_fd(channel);
-  for (auto& p : stub->ports_) {
-    if (p->GetFd() == fd && !p->IsDelegate()) {
-      char buffer[4];
-      if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
-        _W("Socket was disconnected from proxy. fd(%d)", fd);
-        listener->OnDisconnected(p->GetId(), p->GetInstance());
-        stub->RemoveAcceptedPorts(p->GetInstance());
-        Aul::NotifyRpcFinished();
-        return G_SOURCE_CONTINUE;
-      }
-
-      int ret = stub->listener_->OnReceived(p->GetId(), p->GetInstance(),
-          p.get());
-      if (ret != 0) {
-        _W("Invalid protocol");
-        listener->OnDisconnected(p->GetId(), p->GetInstance());
-        stub->RemoveAcceptedPorts(p->GetInstance());
-        Aul::NotifyRpcFinished();
-        return G_SOURCE_CONTINUE;
-      }
-
-      break;
-    }
-  }
-
-  return G_SOURCE_CONTINUE;
-}
-
-gboolean Stub::AcceptedPort::OnSocketDisconnected(GIOChannel* channel,
-    GIOCondition cond, gpointer user_data) {
-  auto* stub = static_cast<Stub*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(stub->GetMutex());
-  auto* listener = stub->listener_;
-  if (listener == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  int fd = g_io_channel_unix_get_fd(channel);
-  _W("Socket was disconnected. fd(%d)", fd);
-  for (auto& p : stub->ports_) {
-    if (p->GetFd() == fd) {
-      listener->OnDisconnected(p->GetId(), p->GetInstance());
-      stub->RemoveAcceptedPorts(p->GetInstance());
-      Aul::NotifyRpcFinished();
-      break;
-    }
-  }
-
-  return G_SOURCE_REMOVE;
-}
-
-void Stub::AddAcceptedPort(const std::string& sender_appid,
-    const std::string& instance, const std::string& port_type, int fd) {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (port_type == kPortTypeMain) {
-    auto* main_port = new AcceptedPort(this, false, fd, sender_appid,
-        instance, true);
-    ports_.emplace_back(main_port);
-    return;
-  }
-
-  auto* delegate_port = new AcceptedPort(this, true, fd, sender_appid,
-      instance, false);
-  ports_.emplace_back(delegate_port);
-
-  int main_fd = -1;
-  for (auto& p : ports_) {
-    if (p->GetId() == delegate_port->GetId() &&
-        p->GetInstance() == delegate_port->GetInstance() &&
-        p->GetFd() != delegate_port->GetFd()) {
-      main_fd = p->GetFd();
-      break;
-    }
-  }
-
-  _W("sender_appid(%s), instance(%s), main_fd(%d), delegate_fd(%d)",
-      sender_appid.c_str(), instance.c_str(), main_fd, fd);
-  DebugPort::AddSession(port_name_, sender_appid, main_fd, fd);
-  listener_->OnConnected(sender_appid, instance);
-}
-
-std::recursive_mutex& Stub::GetMutex() const {
-  return mutex_;
-}
-
-Stub::AcceptedPort::AcceptedPort(Stub* parent, bool isDelegate, int fd,
-    std::string id, std::string inst, bool watch)
-    : Port(fd, std::move(id), std::move(inst)), parent_(parent),
-      is_delegate_(isDelegate) {
-  Watch(watch);
-}
-
-// LCOV_EXCL_START
-Stub::AcceptedPort::AcceptedPort(Stub* parent, bool isDelegate, int fd,
-    std::string id, bool watch)
-    : Port(fd, std::move(id)), parent_(parent),
-      is_delegate_(isDelegate) {
-  Watch(watch);
-}
-// LCOV_EXCL_STOP
-
-Stub::AcceptedPort::~AcceptedPort() {
-  if (disconn_source_ > 0)
-    g_source_remove(disconn_source_);
-
-  if (source_ > 0)
-    g_source_remove(source_);
-
-  if (channel_ != nullptr)
-    g_io_channel_unref(channel_);
-}
-
-int Stub::AcceptedPort::Watch(bool receive) {
-  channel_ = g_io_channel_unix_new(GetFd());
-  if (channel_ == nullptr) {
-    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  disconn_source_ = g_io_add_watch(channel_,
-      static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
-      OnSocketDisconnected, parent_);
-  if (disconn_source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  if (!receive)
-    return 0;
-
-  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
-      OnDataReceived, parent_);
-  if (source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  return 0;
-}
-
-Stub::Server::Server(int fd, Stub* parent)
-    : ServerSocket(fd),
-      parent_(parent) {
-}
-
-Stub::Server::~Server() {
-  if (channel_)
-    g_io_channel_unref(channel_);
-
-  if (source_ > 0)
-    g_source_remove(source_);
-}
-
-int Stub::Server::Listen() {
-  channel_ = g_io_channel_unix_new(GetFd());
-  if (channel_ == nullptr) {
-    _E("g_io_channel_unix_new() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
-      OnRequestReceived, parent_);
-  if (source_ == 0) {
-    _E("g_io_add_watch() is failed");  // LCOV_EXCL_LINE
-    return -1;  // LCOV_EXCL_LINE
-  }
-
-  return 0;
-}
-
-gboolean Stub::Server::OnRequestReceived(GIOChannel* channel, GIOCondition cond,
-    gpointer user_data) {
-  auto* stub = static_cast<Stub*>(user_data);
-  std::lock_guard<std::recursive_mutex> lock(stub->GetMutex());
-  if (stub->listener_ == nullptr) {
-    _E("Invalid context");  // LCOV_EXCL_LINE
-    return G_SOURCE_REMOVE;  // LCOV_EXCL_LINE
-  }
-
-  std::shared_ptr<ClientSocket> client(stub->server_->Accept());
-  if (client.get() == nullptr) {
-    _E("Out of memory");  // LCOV_EXCL_LINE
-    return G_SOURCE_CONTINUE;  // LCOV_EXCL_LINE
-  }
-
-  Request* request = nullptr;
-  int ret = ReceiveRequest(client.get(), &request);
-  if (ret != 0)
-    return G_SOURCE_CONTINUE;  // LCOV_EXCL_LINE
-
-  std::shared_ptr<Request> request_auto(request);
-  std::shared_ptr<PeerCred> cred(PeerCred::Get(client->GetFd()));
-  if (cred.get() == nullptr) {
-    _E("Failed to create peer credentials");  // LCOV_EXCL_LINE
-    return G_SOURCE_CONTINUE;  // LCOV_EXCL_LINE
-  }
-
-  std::string app_id = Aul::GetAppId(cred->GetPid());
-  auto response_func = [=](int res) -> void {
-    if (freed_stubs_.find(stub) != freed_stubs_.end())
-      return;  // LCOV_EXCL_LINE
-
-    Response response(res);
-    int ret = SendResponse(client.get(), response);
-    if (ret != 0)
-      return;  // LCOV_EXCL_LINE
-
-    if (res != 0) {
-      _E("Access denied. fd(%d), pid(%d)",
-          client->GetFd(), cred->GetPid());  // LCOV_EXCL_LINE
-      return;              // LCOV_EXCL_LINE
-    }
-
-    client->SetNonblock();
-    int client_fd = client->RemoveFd();
-    stub->AddAcceptedPort(app_id, request_auto->GetInstance(),
-        request_auto->GetPortType(), client_fd);
-  };
-
-  int res;
-  if (cred->GetUid() >= kRegularUidMin) {
-    if (cred->GetUid() != getuid() && getuid() >= kRegularUidMin) {
-      _E("Reject request. %u:%u", cred->GetUid(), getuid());  // LCOV_EXCL_LINE
-      res = -1;  // LCOV_EXCL_LINE
-    } else {
-      stub->access_controller_->CheckAsync(client->GetFd(), app_id,
-          response_func);
-      return G_SOURCE_CONTINUE;
-    }
-  } else {
-    _W("Bypass access control. pid(%d), uid(%u)",
-        cred->GetPid(), cred->GetUid());
-    res = 0;
-  }
-
-  response_func(res);
-  return G_SOURCE_CONTINUE;
-}
-
-}  // namespace internal
-}  // namespace rpc_port
diff --git a/src/stub-internal.hh b/src/stub-internal.hh
deleted file mode 100644 (file)
index b1ac248..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef STUB_INTERNAL_HH_
-#define STUB_INTERNAL_HH_
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <glib-unix.h>
-
-#include <list>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <unordered_set>
-
-#include "ac-internal.hh"
-#include "debug-port-internal.hh"
-#include "port-internal.hh"
-#include "server-socket-internal.hh"
-
-namespace rpc_port {
-namespace internal {
-
-class Stub {
- public:
-  class IEventListener {
-   public:
-    virtual void OnConnected(const std::string& sender,
-        const std::string& instance) = 0;
-    virtual void OnDisconnected(const std::string& sender,
-        const std::string& instance) = 0;
-    virtual int OnReceived(const std::string& sender,
-        const std::string& instance, Port* port) = 0;
-  };
-
-  explicit Stub(std::string port_name);
-  virtual ~Stub();
-
-  int Listen(IEventListener* ev, int fd);
-  void Ignore();
-  void AddPrivilege(const std::string& privilege);
-  void SetTrusted(const bool trusted);
-  std::shared_ptr<Port> FindPort(const std::string& instance) const;
-  std::shared_ptr<Port> FindDelegatePort(const std::string& instance) const;
-  const std::string& GetPortName() const;
-  int CreatePort();
-
- private:
-  class AcceptedPort : public Port {
-   public:
-    AcceptedPort(Stub* parent, bool isDelegate, int fd, std::string id,
-        std::string inst, bool receive);
-    AcceptedPort(Stub* parent, bool isDelegate, int fd, std::string id,
-        bool receive);
-    virtual ~AcceptedPort();
-    bool IsDelegate() const {
-      return is_delegate_;
-    }
-
-   private:
-    int Watch(bool receive);
-    static gboolean OnDataReceived(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-    static gboolean OnSocketDisconnected(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-
-   private:
-    GIOChannel* channel_ = nullptr;
-    guint disconn_source_ = 0;
-    guint source_ = 0;
-    Stub* parent_;
-    bool is_delegate_ = false;
-  };
-
-  class Server : public ServerSocket {
-   public:
-    Server(int fd, Stub* parent);
-    virtual ~Server();
-
-    int Listen();
-
-   private:
-    static gboolean OnRequestReceived(GIOChannel* channel, GIOCondition cond,
-        gpointer user_data);
-
-   private:
-    Stub* parent_;
-    GIOChannel* channel_ = nullptr;
-    guint source_ = 0;
-  };
-
-  void AddAcceptedPort(const std::string& sender_appid,
-      const std::string& instance, const std::string& port_type, int fd);
-  void RemoveAcceptedPorts(std::string instance);
-  std::recursive_mutex& GetMutex() const;
-  int GetFdFromSystemd();
-  int CreateServerSocket();
-
- private:
-  std::shared_ptr<AccessController> access_controller_ =
-      std::make_shared<AccessController>();
-  std::string port_name_;
-  std::string port_path_;
-  std::list<std::shared_ptr<AcceptedPort>> ports_;
-  IEventListener* listener_ = nullptr;
-  std::unique_ptr<Server> server_;
-  mutable std::recursive_mutex mutex_;
-  static std::unordered_set<Stub*> freed_stubs_;
-};
-
-}  // namespace internal
-}  // namespace rpc_port
-
-#endif  // STUB_INTERNAL_HH_
index 6353206a4e4570d28594d9f7664e9675e2db1451..4e5b2fafa29e9a9bef948b741a5e72703546895a 100644 (file)
@@ -5,8 +5,7 @@ ADD_EXECUTABLE(${TARGET_RPC_PORT_UTIL} ${UTIL_SRCS})
 TARGET_INCLUDE_DIRECTORIES(${TARGET_RPC_PORT_UTIL} PUBLIC
   ${CMAKE_CURRENT_SOURCE_DIR}
   ${CMAKE_CURRENT_SOURCE_DIR}/../
-  ${CMAKE_CURRENT_SOURCE_DIR}/../../
-  ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
+  ${CMAKE_CURRENT_SOURCE_DIR}/../include)
 
 APPLY_PKG_CONFIG(${TARGET_RPC_PORT_UTIL} PUBLIC
   AUL_DEPS