From c8c3a9577b0f30976463a3eba86597fe3e46ff93 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 5 Jan 2023 01:42:10 +0000 Subject: [PATCH 01/16] Release version 1.13.11 Changes: - Modify connect method of proxy Change-Id: I703dd13a99aaaa1bd96bceefcb49e93a8e99f719 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index d5e9ca6..d5b8dbc 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.13.10 +Version: 1.13.11 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 3698d559b4322fea0153e049552c163c3b594909 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 11 Jan 2023 10:55:05 +0000 Subject: [PATCH 02/16] Use tizen_base::SharedQueue To remove duplicated codes about shared queue, we add a tizen-shared-queue library. This patch uses the tizen_base::SharedQueue and removes duplicated shared queue codes. Change-Id: I43e1aa4ecce2c97524046145b0db02e3cb3e1d0d Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 1 + packaging/rpc-port.spec | 1 + src/CMakeLists.txt | 1 + src/debug-port-internal.cc | 8 ++--- src/shared-queue-internal.hh | 79 -------------------------------------------- 5 files changed, 7 insertions(+), 83 deletions(-) delete mode 100644 src/shared-queue-internal.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a5a157..33f92a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) PKG_CHECK_MODULES(LIBTZPLATFORM_CONFIG_DEPS REQUIRED libtzplatform-config) PKG_CHECK_MODULES(PARCEL_DEPS REQUIRED parcel) PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info) +PKG_CHECK_MODULES(TIZEN_SHARED_QUEUE_DEPS REQUIRED tizen-shared-queue) PKG_CHECK_MODULES(UUID_DEPS REQUIRED uuid) ADD_SUBDIRECTORY(src) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index d5b8dbc..ae8b751 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -18,6 +18,7 @@ BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(parcel) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(tizen-shared-queue) BuildRequires: pkgconfig(uuid) %if 0%{?gcov:1} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1061211..46b286d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,7 @@ APPLY_PKG_CONFIG(${TARGET_RPC_PORT} PUBLIC LIBTZPLATFORM_CONFIG_DEPS PARCEL_DEPS PKGMGR_INFO_DEPS + TIZEN_SHARED_QUEUE_DEPS UUID_DEPS ) diff --git a/src/debug-port-internal.cc b/src/debug-port-internal.cc index 06e44dc..df51d5b 100644 --- a/src/debug-port-internal.cc +++ b/src/debug-port-internal.cc @@ -33,9 +33,10 @@ #include #include +#include + #include "log-private.hh" #include "port-internal.hh" -#include "shared-queue-internal.hh" namespace rpc_port { namespace internal { @@ -119,7 +120,7 @@ class DebugPortImpl { std::list> sessions_; std::thread thread_; std::atomic is_running_ { false }; - SharedQueue> queue_; + tizen_base::SharedQueue> queue_; mutable std::recursive_mutex mutex_; aul_app_com_connection_h conn_ = nullptr; }; @@ -325,8 +326,7 @@ void DebugPortImpl::CreateThread() { thread_ = std::thread([&]() { _W("START"); do { - std::shared_ptr parcel; - queue_.WaitAndPop(parcel); + std::shared_ptr parcel = queue_.WaitAndPop(); int len = parcel->GetDataSize(); if (len == 0) { _W("Done"); diff --git a/src/shared-queue-internal.hh b/src/shared-queue-internal.hh deleted file mode 100644 index 4cd0d95..0000000 --- a/src/shared-queue-internal.hh +++ /dev/null @@ -1,79 +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 SHARED_QUEUE_INTERNAL_HH_ -#define SHARED_QUEUE_INTERNAL_HH_ - -#include -#include -#include -#include - -namespace rpc_port { -namespace internal { - -template -class SharedQueue { - public: - SharedQueue() = default; - virtual ~SharedQueue() = default; - - void Push(T item) { - std::lock_guard lock(mutex_); - queue_.push(item); - cond_var_.notify_one(); - } - - bool TryAndPop(T& item) { - std::lock_guard lock(mutex_); - if (queue_.empty()) - return false; - - item = queue_.front(); - queue_.pop_front(); - - return true; - } - - void WaitAndPop(T& item) { - std::unique_lock lock(mutex_); - while (queue_.empty()) - cond_var_.wait(lock); - - item = queue_.front(); - queue_.pop(); - } - - bool Empty() { - std::lock_guard lock(mutex_); - return queue_.empty(); - } - - int Size() { - std::lock_guard lock(mutex_); - return queue_.size(); - } - - private: - std::queue queue_; - mutable std::mutex mutex_; - std::condition_variable cond_var_; -}; - -} // namespace internal -} // namespace rpc_port - -#endif // SHARED_QUEUE_INTERNAL_HH_ -- 2.7.4 From 43cb14e6408ab07a9e84fe234b99f63ed57a0a67 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 11 Jan 2023 23:26:02 +0000 Subject: [PATCH 03/16] Release version 1.13.12 Changes: - Use tizen_base::SharedQueue Change-Id: I03fac659f314b95277f3552beca0765989ef0870 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index ae8b751..6a8a800 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.13.11 +Version: 1.13.12 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 95ab7b83df8ffc11a9514ca8209632a868ce41b5 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 18 Jan 2023 06:20:02 +0000 Subject: [PATCH 04/16] Modify Port::Write() method After this patch is applied, if the cache buffer is not empty, the rpc-port library checks the socket whether writing is possible or not. If it's possible, the rpc-port library writes the delayed message to the socket fd. Change-Id: If54967bbc7fce4d4494b9fee44d8dcfe5e57de50 Signed-off-by: Hwankyu Jhun --- src/port-internal.cc | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/port-internal.cc b/src/port-internal.cc index b895d88..a937278 100644 --- a/src/port-internal.cc +++ b/src/port-internal.cc @@ -223,19 +223,7 @@ int Port::Write(const void* buf, unsigned int size) { return RPC_PORT_ERROR_NONE; else if (ret == PORT_STATUS_ERROR_IO_ERROR) return RPC_PORT_ERROR_IO_ERROR; - } - - 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; - } - - ret = PushDelayedMessage( - std::make_shared(static_cast(buf), - sent_bytes, size)); - - if (CanWrite()) { + } else if (CanWrite()) { while (!queue_.empty()) { int port_status = PopDelayedMessage(); if (port_status != PORT_STATUS_ERROR_NONE) { @@ -247,7 +235,15 @@ int Port::Write(const void* buf, unsigned int size) { } } - return ret; + 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( + static_cast(buf), sent_bytes, size)); } int Port::Write(const void* buf, unsigned int size, int* sent_bytes) { @@ -299,6 +295,8 @@ gboolean Port::OnEventReceived(GIOChannel* io, GIOCondition condition, return G_SOURCE_REMOVE; } + _W("Writing is now possible. fd: %d, id: %s", + port->GetFd(), port->GetId().c_str()); std::lock_guard lock(port->rw_mutex_); if (port->source_id_ == 0) { _E("GSource is destroyed"); -- 2.7.4 From e0f52c1cd5ca3e92b2249157f770bd6bb858dee3 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 18 Jan 2023 06:43:56 +0000 Subject: [PATCH 05/16] Release version 1.13.13 Changes: - Modify Port::Write() method Change-Id: Ifeb3aab21595f577b57ebae0883f087b8f00a116 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 6a8a800..c533056 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.13.12 +Version: 1.13.13 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From d234a22cc5bc83726fb5d496ef81851a51c6adad Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 26 Jan 2023 03:39:02 +0000 Subject: [PATCH 06/16] Revert "Check current thread ID to destroy handle" This reverts commit 2da1742b97e33d2b9c42d01104080721143d8b59. When calling the event callback function, app developer releases the handle in the callback function. It makes a crash issue. Even if the destroy function is called in the main thread, the rpc-port library doesn't release the handle immediately to prevent the issue. Change-Id: I58a25d9e4c5f1f42065901dac8e6a30f22f898d2 Signed-off-by: Hwankyu Jhun --- src/rpc-port.cc | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 88799b0..1a09c2c 100644 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include @@ -303,13 +301,9 @@ RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) { } _W("rpc_port_proxy_destroy(%p)", proxy); - if (getpid() == gettid()) { - delete p; - return RPC_PORT_ERROR_NONE; - } - proxy->SetDestroying(true); proxy->DisconnectPort(); + g_idle_add_full(G_PRIORITY_HIGH, [](gpointer data) -> gboolean { auto p = static_cast*>(data); @@ -317,7 +311,6 @@ RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) { delete p; return G_SOURCE_REMOVE; }, h, nullptr); - return RPC_PORT_ERROR_NONE; } @@ -446,11 +439,6 @@ RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) { p->SetDestroying(true); aul_rpc_port_usr_destroy(p->GetPortName().c_str(), rpc_port_get_target_uid()); - if (getpid() == gettid()) { - delete p; - return RPC_PORT_ERROR_NONE; - } - p->Ignore(); g_idle_add_full(G_PRIORITY_HIGH, [](gpointer data) -> gboolean { @@ -459,7 +447,6 @@ RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) { delete p; return G_SOURCE_REMOVE; }, h, nullptr); - return RPC_PORT_ERROR_NONE; } -- 2.7.4 From 48d325c76040f097b3ce5f036c8ac9298a94ebba Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 26 Jan 2023 04:04:17 +0000 Subject: [PATCH 07/16] Release version 1.13.14 Changes: - Revert "Check current thread ID to destroy handle" Change-Id: I487c8d45b2abefab33204366ab4047c719d72ecf Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index c533056..1e3e117 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.13.13 +Version: 1.13.14 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 8222a5a4242f4efeb750d5a65c74b4732347e3da Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 2 Feb 2023 02:37:06 +0000 Subject: [PATCH 08/16] Move port existence check to the Watch method To make unblocking the main thread, the port existence check is moved to the Watch() method. If the proxy application calls the rpc_port_proxy_connect() function in the sub thread, the Aul::ExistPort() is called in the thread. Change-Id: Ie82e0527c56981337c1b241c8d2b090696a1b0de Signed-off-by: Hwankyu Jhun --- src/proxy-internal.cc | 7 ++++--- src/proxy-internal.hh | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc index 8465ed2..4a63e3a 100644 --- a/src/proxy-internal.cc +++ b/src/proxy-internal.cc @@ -298,6 +298,9 @@ int Proxy::Watch() { return -1; } + port_exist_ = Aul::ExistPort(real_appid_, port_name_, + rpc_port_get_target_uid()); + SetConnTimer(); SetIdler(); return 0; @@ -476,9 +479,7 @@ gboolean Proxy::OnIdle(gpointer user_data) { DestroyWeakPtr(proxy->idler_data_); proxy->idler_data_ = nullptr; - bool exist = Aul::ExistPort(proxy->real_appid_, proxy->port_name_, - rpc_port_get_target_uid()); - if (exist) { + if (proxy->port_exist_) { proxy->OnPortAppeared(proxy->real_appid_.c_str(), proxy->port_name_.c_str(), -1, proxy.get()); } else { diff --git a/src/proxy-internal.hh b/src/proxy-internal.hh index 2cfef0d..8da58ff 100644 --- a/src/proxy-internal.hh +++ b/src/proxy-internal.hh @@ -146,6 +146,7 @@ class Proxy : public std::enable_shared_from_this { gpointer conn_timer_data_ = nullptr; gpointer idler_data_ = nullptr; mutable std::recursive_mutex mutex_; + bool port_exist_ = false; }; } // namespace internal -- 2.7.4 From 650dcfdb919bae9e3d8ea4a080615fbd30fac566 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 2 Feb 2023 03:54:03 +0000 Subject: [PATCH 09/16] Release version 1.13.15 Changes: - Move port existence check to the Watch method Change-Id: Ib23c4b1c19e66a9c9aef2a494c3aaf899ccd63f1 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 1e3e117..44eeba5 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.13.14 +Version: 1.13.15 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 2530b57722f2ce466145737830e8799af0a3b20d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 7 Dec 2022 06:06:53 +0000 Subject: [PATCH 10/16] Add a new API for creating parcel handle To create a parcel handle without the header, a new API is added. Adds: - rpc_port_parcel_create_without_header() Change-Id: Ic4d0b79ea580243e988a02261a3c4b586f27bdd4 Signed-off-by: Hwankyu Jhun --- include/rpc-port-parcel.h | 14 ++++++++++++ src/parcel-internal.cc | 39 ++++++++++++++++++++------------- src/parcel-internal.hh | 4 ++-- src/rpc-port-parcel.cc | 15 +++++++++++++ test/unit_tests/rpc_port_parcel_test.cc | 33 +++++++++++++++++++++++++++- 5 files changed, 87 insertions(+), 18 deletions(-) diff --git a/include/rpc-port-parcel.h b/include/rpc-port-parcel.h index 73fdbfe..29cd7df 100644 --- a/include/rpc-port-parcel.h +++ b/include/rpc-port-parcel.h @@ -542,6 +542,20 @@ int rpc_port_parcel_get_raw(rpc_port_parcel_h h, void **raw, unsigned int *size) int rpc_port_parcel_create_from_raw(rpc_port_parcel_h *h, const void *raw, unsigned int size); /** + * @brief Creates the rpc port parcel handle without the header. + * @since_tizen 7.5 + * @remarks You must release @h using rpc_port_parcel_destroy(). + * @param[out] h The rpc port parcel handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see rpc_port_parcel_destroy() + */ +int rpc_port_parcel_create_without_header(rpc_port_parcel_h *h); + +/** * @} */ diff --git a/src/parcel-internal.cc b/src/parcel-internal.cc index 5cb299d..75f4302 100644 --- a/src/parcel-internal.cc +++ b/src/parcel-internal.cc @@ -22,36 +22,45 @@ namespace rpc_port { namespace internal { -Parcel::Parcel() {} +Parcel::Parcel(bool without_header) + : header_(without_header ? nullptr : new ParcelHeader()) { +} Parcel::~Parcel() {} void Parcel::WriteToParcel(tizen_base::Parcel* parcel) const { - parcel->WriteParcelable(header_); + if (header_.get() != nullptr) { + parcel->WriteParcelable(*header_.get()); + parcel->WriteUInt32(handle_.GetDataSize()); + } - parcel->WriteUInt32(handle_.GetDataSize()); parcel->Write(handle_.GetData(), handle_.GetDataSize()); } void Parcel::ReadFromParcel(tizen_base::Parcel* parcel) { - parcel->ReadParcelable(&header_); + if (header_.get() != nullptr) { + parcel->ReadParcelable(header_.get()); - uint32_t size = 0; - parcel->ReadUInt32(&size); - if (size > 0) { - auto* buf = static_cast(malloc(size)); - if (buf == nullptr) { - _E("Out of memory"); - return; - } + uint32_t size = 0; + parcel->ReadUInt32(&size); + if (size > 0) { + auto* buf = static_cast(malloc(size)); + if (buf == nullptr) { + _E("Out of memory"); + return; + } - parcel->Read(buf, size); - handle_ = std::move(tizen_base::Parcel(buf, size, false)); + parcel->Read(buf, size); + handle_ = std::move(tizen_base::Parcel(buf, size, false)); + } + } else { + handle_ = std::move( + tizen_base::Parcel(parcel->GetData(), parcel->GetDataSize())); } } const ParcelHeader* Parcel::GetParcelHeader() { - return &header_; + return header_.get(); } parcel_h Parcel::GetHandle() const { diff --git a/src/parcel-internal.hh b/src/parcel-internal.hh index 6c907b8..3d0911d 100644 --- a/src/parcel-internal.hh +++ b/src/parcel-internal.hh @@ -31,7 +31,7 @@ namespace internal { class Parcel : public tizen_base::Parcelable { public: - Parcel(); + Parcel(bool without_header = false); ~Parcel(); void WriteToParcel(tizen_base::Parcel* parcel) const override; @@ -44,7 +44,7 @@ class Parcel : public tizen_base::Parcelable { tizen_base::Parcel* GetRawParcel() const; private: - ParcelHeader header_; + std::unique_ptr header_; tizen_base::Parcel handle_; std::unique_ptr raw_parcel_ { nullptr }; }; diff --git a/src/rpc-port-parcel.cc b/src/rpc-port-parcel.cc index 098a53a..e665b5e 100644 --- a/src/rpc-port-parcel.cc +++ b/src/rpc-port-parcel.cc @@ -453,6 +453,9 @@ RPC_API int rpc_port_parcel_get_header(rpc_port_parcel_h h, auto* parcel = static_cast(h); auto* parcel_header = parcel->GetParcelHeader(); + if (parcel_header == nullptr) + return RPC_PORT_ERROR_INVALID_PARAMETER; + *header = reinterpret_cast( const_cast(parcel_header)); return RPC_PORT_ERROR_NONE; @@ -553,3 +556,15 @@ RPC_API int rpc_port_parcel_create_from_raw(rpc_port_parcel_h* h, *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(parcel); + return RPC_PORT_ERROR_NONE; +} diff --git a/test/unit_tests/rpc_port_parcel_test.cc b/test/unit_tests/rpc_port_parcel_test.cc index 63038ca..07de128 100644 --- a/test/unit_tests/rpc_port_parcel_test.cc +++ b/test/unit_tests/rpc_port_parcel_test.cc @@ -524,7 +524,7 @@ TEST_F(ParcelTest, rpc_port_parcel_create_from_raw_P) { } /* - * @testcase rpc_port_parcel_create_from_raw_B + * @testcase rpc_port_parcel_create_from_raw_N * @description Creates the rpc parcel handle with given the raw data. * @apicovered rpc_port_parcel_create_from_raw */ @@ -532,3 +532,34 @@ TEST_F(ParcelTest, rpc_port_parcel_create_from_raw_N) { int ret = rpc_port_parcel_create_from_raw(nullptr, nullptr, 0); ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER); } + +/* + * @testcase rpc_port_parcel_create_without_header_P + * @description Creates the rpc parcel handle without the header. + * @apicovered rpc_port_parcel_create_without_header + */ +TEST_F(ParcelTest, rpc_port_parcel_create_without_header_P) { + rpc_port_parcel_h parcel = nullptr; + int ret = rpc_port_parcel_create_without_header(&parcel); + ASSERT_EQ(ret, RPC_PORT_ERROR_NONE); + ASSERT_NE(parcel, nullptr); + + std::unique_ptr::type, + decltype(rpc_port_parcel_destroy)*> parcel_auto( + parcel, rpc_port_parcel_destroy); + + rpc_port_parcel_header_h header = nullptr; + ret = rpc_port_parcel_get_header(parcel, &header); + ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER); + ASSERT_EQ(header, nullptr); +} + +/* + * @testcase rpc_port_parcel_create_without_header_N + * @description Creates the rpc parcel handle without the header. + * @apicovered rpc_port_parcel_create_without_header + */ +TEST_F(ParcelTest, rpc_port_parcel_create_without_header_N) { + int ret = rpc_port_parcel_create_without_header(nullptr); + ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER); +} -- 2.7.4 From 92b606a086a4d7d40f86e378d64d13bf682d68f9 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 3 Feb 2023 04:13:59 +0000 Subject: [PATCH 11/16] Release version 1.14.0 Changes: - Add a new API for creating parcel handle Change-Id: I37c8bd60a218fea59dea9c39210187b09878ed90 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 44eeba5..53dd099 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.13.15 +Version: 1.14.0 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From e578435f79f872c76733351fa3f0d690e629c5f8 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 21 Feb 2023 01:55:55 +0000 Subject: [PATCH 12/16] Fix wrong API description The '@h' should be '@a h'. Change-Id: I4056ad50e14c7b2a1af775ff6741080463df49a2 Signed-off-by: Hwankyu Jhun --- include/rpc-port-parcel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rpc-port-parcel.h b/include/rpc-port-parcel.h index 29cd7df..02c5aa3 100644 --- a/include/rpc-port-parcel.h +++ b/include/rpc-port-parcel.h @@ -544,7 +544,7 @@ int rpc_port_parcel_create_from_raw(rpc_port_parcel_h *h, const void *raw, unsig /** * @brief Creates the rpc port parcel handle without the header. * @since_tizen 7.5 - * @remarks You must release @h using rpc_port_parcel_destroy(). + * @remarks You must release @a h using rpc_port_parcel_destroy(). * @param[out] h The rpc port parcel handle * @return @c 0 on success, * otherwise a negative error value -- 2.7.4 From b033515b64255bf494b5541e572a2202ab93ebab Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 21 Feb 2023 03:23:49 +0000 Subject: [PATCH 13/16] Release version 1.14.1 Changes: - Fix wrong API description Change-Id: Ie8f65243a06e3b06f7622893e25c0d2acc1e42c4 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 53dd099..8847243 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.14.0 +Version: 1.14.1 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 9c6f441dd423fbb400d7a0bc4069d8f9d62c9a36 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Mon, 20 Mar 2023 15:23:39 +0900 Subject: [PATCH 14/16] Add CynaraThread Some cynara apis cause blocking a thread. This patch adds a sub thread for processing cynara requests. Change-Id: Ib800d034ce0e545f18327b00f00ace729de8a8f2 Signed-off-by: Changgyu Choi --- src/ac-internal.cc | 23 ++++++++++++++++++ src/ac-internal.hh | 4 ++++ src/cynara_thread.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++ src/cynara_thread.hh | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/stub-internal.cc | 49 +++++++++++++++++++++++-------------- src/stub-internal.hh | 2 ++ 6 files changed, 189 insertions(+), 18 deletions(-) create mode 100644 src/cynara_thread.cc create mode 100644 src/cynara_thread.hh diff --git a/src/ac-internal.cc b/src/ac-internal.cc index 98addbb..8dbac48 100644 --- a/src/ac-internal.cc +++ b/src/ac-internal.cc @@ -25,6 +25,7 @@ #include "ac-internal.hh" #include "aul-internal.hh" #include "log-private.hh" +#include "cynara_thread.hh" namespace rpc_port { namespace internal { @@ -93,6 +94,28 @@ int AccessController::Check(int fd, const std::string& sender_appid) { return ret; } +void AccessController::CheckAsync(int fd, std::string sender_appid, + CompleteCallback callback) { + Job job([=]() -> Job::Type { + int res = Check(fd, sender_appid); + auto* cbdata = new std::pair(callback, res); + if (callback != nullptr) { + g_idle_add( + [](gpointer data) -> gboolean { + auto* cbdata = static_cast*>(data); + auto [callback, res] = *cbdata; + callback(res); + delete (cbdata); + return G_SOURCE_REMOVE; + }, cbdata); + } + + return Job::Type::Continue; + }); + + CynaraThread::GetInst().Push(std::move(job)); +} + AccessController::Cynara::Cynara() : cynara_(nullptr, cynara_finish), client_(nullptr, std::free), user_(nullptr, std::free) { diff --git a/src/ac-internal.hh b/src/ac-internal.hh index 7b60c62..a2309ee 100644 --- a/src/ac-internal.hh +++ b/src/ac-internal.hh @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,8 @@ namespace rpc_port { namespace internal { +using CompleteCallback = std::function; + class AccessController { public: explicit AccessController(bool trusted = false) : trusted_(trusted) {} @@ -37,6 +40,7 @@ class AccessController { 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: class Cynara { diff --git a/src/cynara_thread.cc b/src/cynara_thread.cc new file mode 100644 index 0000000..a8f7fd0 --- /dev/null +++ b/src/cynara_thread.cc @@ -0,0 +1,61 @@ +/* + * 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 + +namespace rpc_port { +namespace internal { + +Job::Job(Job::JobHandlerCallback cb) : cb_(std::move(cb)) {} + +Job::Job() : cb_([]() { return Job::Type::Finish; }) {} + +Job::Type Job::Do() { + return cb_(); +} + +CynaraThread& CynaraThread::GetInst() { + static CynaraThread* inst = new CynaraThread(); + return *inst; +} + +CynaraThread::CynaraThread() { + thread_ = std::thread([this]() { ThreadRun(); }); +} + +CynaraThread::~CynaraThread() { + Job finish_job; + Push(finish_job); + thread_.join(); +} + +void CynaraThread::ThreadRun() { + while (true) { + Job job = std::move(queue_.WaitAndPop()); + Job::Type ret = job.Do(); + if (ret == Job::Type::Finish) + return; + } +} + +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 new file mode 100644 index 0000000..8067f7a --- /dev/null +++ b/src/cynara_thread.hh @@ -0,0 +1,68 @@ +/* + * 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 +#include +#include + +namespace rpc_port { +namespace internal { + +class Job { + public: + enum class Type { + Continue = 0, + Finish = 1, + }; + + using JobHandlerCallback = std::function; + + explicit Job(JobHandlerCallback cb); + Job(); + + ~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 queue_; +}; + +} // namespace internal +} // namespace rpc_port + +#endif // CYNARA_THREAD_HH_ diff --git a/src/stub-internal.cc b/src/stub-internal.cc index 5508bc4..72b59b2 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -87,8 +87,11 @@ int SendResponse(ClientSocket* client, const Response& response) { } // namespace +std::unordered_set Stub::freed_stubs_; + Stub::Stub(std::string port_name) : port_name_(std::move(port_name)) { _D("Stub::Stub()"); + freed_stubs_.erase(this); } Stub::~Stub() { @@ -101,6 +104,7 @@ Stub::~Stub() { listener_ = nullptr; server_.reset(); + freed_stubs_.insert(this); } int Stub::Listen(IEventListener* ev, int fd) { @@ -363,7 +367,7 @@ gboolean Stub::Server::OnRequestReceived(GIOChannel* channel, GIOCondition cond, return G_SOURCE_REMOVE; } - std::unique_ptr client(stub->server_->Accept()); + std::shared_ptr client(stub->server_->Accept()); if (client.get() == nullptr) { _E("Out of memory"); return G_SOURCE_CONTINUE; @@ -374,21 +378,43 @@ gboolean Stub::Server::OnRequestReceived(GIOChannel* channel, GIOCondition cond, if (ret != 0) return G_SOURCE_CONTINUE; - std::unique_ptr request_auto(request); - std::unique_ptr cred(PeerCred::Get(client->GetFd())); + std::shared_ptr request_auto(request); + std::shared_ptr cred(PeerCred::Get(client->GetFd())); if (cred.get() == nullptr) { _E("Failed to create peer credentials"); return G_SOURCE_CONTINUE; } std::string app_id = Aul::GetAppId(cred->GetPid()); + auto response_func = [=](int res) -> void { + if (freed_stubs_.find(stub) != freed_stubs_.end()) + return; + + Response response(res); + int ret = SendResponse(client.get(), response); + if (ret != 0) + return; + + if (res != 0) { + _E("Access denied. fd(%d), pid(%d)", client->GetFd(), cred->GetPid()); + return; + } + + 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()); res = -1; } else { - res = stub->access_controller_.Check(client->GetFd(), app_id); + stub->access_controller_.CheckAsync(client->GetFd(), app_id, + response_func); + return G_SOURCE_CONTINUE; } } else { _W("Bypass access control. pid(%d), uid(%u)", @@ -396,20 +422,7 @@ gboolean Stub::Server::OnRequestReceived(GIOChannel* channel, GIOCondition cond, res = 0; } - Response response(res); - ret = SendResponse(client.get(), response); - if (ret != 0) - return G_SOURCE_CONTINUE; - - if (res != 0) { - _E("Access denied. fd(%d), pid(%d)", client->GetFd(), cred->GetPid()); - return G_SOURCE_CONTINUE; - } - - client->SetNonblock(); - int client_fd = client->RemoveFd(); - stub->AddAcceptedPort(app_id, request->GetInstance(), request->GetPortType(), - client_fd); + response_func(res); return G_SOURCE_CONTINUE; } diff --git a/src/stub-internal.hh b/src/stub-internal.hh index 7e32d4d..0f2723c 100644 --- a/src/stub-internal.hh +++ b/src/stub-internal.hh @@ -25,6 +25,7 @@ #include #include #include +#include #include "ac-internal.hh" #include "debug-port-internal.hh" @@ -113,6 +114,7 @@ class Stub { IEventListener* listener_ = nullptr; std::unique_ptr server_; mutable std::recursive_mutex mutex_; + static std::unordered_set freed_stubs_; }; } // namespace internal -- 2.7.4 From 5c7722effe30aa383da1add77a697463bb4f1c07 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Tue, 21 Mar 2023 17:40:35 +0900 Subject: [PATCH 15/16] Release version 1.14.2 Changes: - Add CynaraThread Change-Id: Icb60fde83d15d476876d796c39397ee9779d098a Signed-off-by: Changgyu Choi --- packaging/rpc-port.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 8847243..3256d04 100644 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -1,6 +1,6 @@ Name: rpc-port Summary: RPC Port library -Version: 1.14.1 +Version: 1.14.2 Release: 0 Group: Application Framework/Libraries License: Apache-2.0 -- 2.7.4 From 35d191c76efe9d96752e9e64403baa6ece301c07 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Tue, 21 Mar 2023 18:11:42 +0900 Subject: [PATCH 16/16] Fix static analysis issues Change-Id: I4e2de4075c4822edc168495db2cd4edadf9072a0 Signed-off-by: Changgyu Choi --- CMakeLists.txt | 2 +- src/ac-internal.cc | 20 +++++++++++--------- src/cynara_thread.cc | 5 +++-- src/cynara_thread.hh | 3 +-- src/proxy-internal.cc | 2 +- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33f92a3..9e9387d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") SET(CMAKE_C_FLAGS_RELEASE "-O2") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS} -std=c++14") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS} -std=c++17") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") diff --git a/src/ac-internal.cc b/src/ac-internal.cc index 8dbac48..70821d6 100644 --- a/src/ac-internal.cc +++ b/src/ac-internal.cc @@ -99,15 +99,17 @@ void AccessController::CheckAsync(int fd, std::string sender_appid, Job job([=]() -> Job::Type { int res = Check(fd, sender_appid); auto* cbdata = new std::pair(callback, res); - if (callback != nullptr) { - g_idle_add( - [](gpointer data) -> gboolean { - auto* cbdata = static_cast*>(data); - auto [callback, res] = *cbdata; - callback(res); - delete (cbdata); - return G_SOURCE_REMOVE; - }, cbdata); + guint sid = g_idle_add( + [](gpointer data) -> gboolean { + auto* cbdata = static_cast*>(data); + auto [callback, res] = *cbdata; + callback(res); + delete cbdata; + return G_SOURCE_REMOVE; + }, cbdata); + if (sid == 0) { + _E("Failed to call g_idle_add"); + delete cbdata; } return Job::Type::Continue; diff --git a/src/cynara_thread.cc b/src/cynara_thread.cc index a8f7fd0..7e5b84b 100644 --- a/src/cynara_thread.cc +++ b/src/cynara_thread.cc @@ -23,9 +23,10 @@ namespace internal { Job::Job(Job::JobHandlerCallback cb) : cb_(std::move(cb)) {} -Job::Job() : cb_([]() { return Job::Type::Finish; }) {} - Job::Type Job::Do() { + if (cb_ == nullptr) + return Job::Type::Finish; + return cb_(); } diff --git a/src/cynara_thread.hh b/src/cynara_thread.hh index 8067f7a..3babdd3 100644 --- a/src/cynara_thread.hh +++ b/src/cynara_thread.hh @@ -33,8 +33,7 @@ class Job { using JobHandlerCallback = std::function; - explicit Job(JobHandlerCallback cb); - Job(); + explicit Job(JobHandlerCallback cb = nullptr); ~Job() = default; diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc index 4a63e3a..67fd462 100644 --- a/src/proxy-internal.cc +++ b/src/proxy-internal.cc @@ -275,7 +275,7 @@ int Proxy::ConnectSync(std::string appid, std::string port_name, 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]); + DebugPort::AddSession(port_name_, target_appid_, fds_[0], fds_[1]); listener_->OnConnected(target_appid_, main_port_.get()); return RPC_PORT_ERROR_NONE; } -- 2.7.4