*/
typedef void (*component_port_sync_request_cb)(const char *sender, parcel_h request, parcel_h response, void *user_data);
+/**
+ * @breif Called when the port is appeared.
+ * @details The function is called when a component port is registered.
+ * @since_tizen 6.5
+ * @param[in] endpoint The endpoint name
+ * @param[in] owner The process ID of the owner
+ * @param[in] user_data The user data passed from the registeration function
+ * @see component_port_watch()
+ */
+typedef void (*component_port_appeared_cb)(const char *endpoint, pid_t owner, void *user_data);
+
+/**
+ * @breif Called when the port is vanished.
+ * @details The function is called when a component port is deregistered.
+ * @since_tizen 6.5
+ * @param[in] endpoint The endpoint name
+ * @param[in] user_data The user data passed from the registeration function
+ * @see component_port_watch();
+ */
+typedef void (*component_port_vanished_cb)(const char *endpoint, void *user_data);
+
/**
* @brief Creates the component port handle.
* @since_tizen 6.5
*/
int component_port_send_sync(component_port_h port, const char *endpoint, int timeout, parcel_h request, parcel_h *response);
+/**
+ * @brief Checks whether the endpoint is running or not.
+ * @since_tizen 6.5
+ * @param[in] endpoint The endpoint name
+ * @param[out] is_running true, if the endpoint is running
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #COMPONENT_PORT_ERROR_NONE Successful
+ * @retval #COMPONENT_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPONENT_PORT_ERROR_IO_ERROR I/O error
+ */
+int component_port_is_running(const char *endpoint, bool *is_running);
+
+/**
+ * @brief Starts watching the endpoint.
+ * @details The component_port_appeared_cb() is invoked when the endpoint of component port is registered.
+ * The component_port_vanished_cb() is invoked when the endpoint of component port is deregistered.
+ * @since_tizen 6.5
+ * @param[in] endpoint The endpoint name
+ * @param[in] appeared_cb The callback function to invoke
+ * @param[in] vanished_cb The callback function to invoke
+ * @param[in] user_data The user data to be passed to the callback function
+ * @param[out] watcher_id The identifier that can be used with component_port_unwatch() to stop watching the endpoint
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #COMPONENT_PORT_ERROR_NONE Successful
+ * @retval #COMPONENT_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPONENT_PORT_ERROR_IO_ERROR I/O error
+ * @retval #COMPONENT_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see component_port_set_appeared_cb()
+ * @see component_port_set_vanished_cb()
+ * @see component_port_unwatch()
+ */
+int component_port_watch(const char *endpoint, component_port_appeared_cb appeared_cb, component_port_vanished_cb vanished_cb, void *user_data, unsigned int *watcher_id);
+
+/**
+ * @brief Stops watching the endpoint.
+ * @since_tizen 6.5
+ * @param[in] watcher_id The identifier obtained from component_port_watch()
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #COMPONENT_PORT_ERROR_NONE Successful
+ * @retval #COMPONENT_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPONENT_PORT_ERROR_IO_ERROR I/O error
+ * @see component_port_watch()
+ */
+int component_port_unwatch_endpoint(unsigned int watcher_id);
+
#ifdef __cplusplus
}
#endif
* limitations under the License.
*/
+#include <aul.h>
+#include <aul_component_port.h>
#include <errno.h>
#include <tizen.h>
+#include <bundle_cpp.h>
+
#include "component_based/port/client.hh"
#include "component_based/port/exception.hh"
#include "component_based/port/log_private.hh"
namespace component_based {
-Port::Impl::~Impl() {
-}
+Port::Impl::~Impl() = default;
Port::Impl::Impl(Port* parent, std::string name, Port::IEvent* listener)
: parent_(parent),
--- /dev/null
+/*
+ * 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 <bundle_cpp.h>
+#include <errno.h>
+
+#include "component_based/port/exception.hh"
+#include "component_based/port/log_private.hh"
+#include "component_based/port/port_watcher.hh"
+
+namespace component_based {
+
+PortWatcher::PortWatcher(IEvent* listener) : listener_(listener) {
+}
+
+PortWatcher::~PortWatcher() {
+ Unwatch();
+}
+
+void PortWatcher::Watch() {
+ if (conn_)
+ return;
+
+ int ret = aul_app_com_create("component.port.watch", nullptr, AppComCb,
+ this, &conn_);
+ if (ret != AUL_R_OK) {
+ _E("aul_app_com_create() is failed. error(%d)", ret);
+ THROW(-EIO);
+ }
+}
+
+void PortWatcher::Unwatch() {
+ if (conn_) {
+ aul_app_com_leave(conn_);
+ conn_ = nullptr;
+ }
+}
+
+int PortWatcher::AppComCb(const char* endpoint, aul_app_com_result_e result,
+ bundle* envelope, void* user_data) {
+ tizen_base::Bundle b(envelope, false, false);
+ std::string port_name = b.GetString(AUL_K_COMPONENT_PORT);
+ std::string event = b.GetString(AUL_K_EVENT_NAME);
+ _D("event(%s), endpoint(%s)", event.c_str(), port_name.c_str());
+ if (event == "appeared") {
+ pid_t pid = std::stoi(b.GetString(AUL_K_PID));
+ auto* handle = static_cast<PortWatcher*>(user_data);
+ handle->listener_->OnPortAppeared(port_name, pid);
+ } else {
+ auto* handle = static_cast<PortWatcher*>(user_data);
+ handle->listener_->OnPortVanished(port_name);
+ }
+ return 0;
+}
+
+} // namespace component_based
--- /dev/null
+/*
+ * 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 COMPONENT_BASED_PORT_PORT_WATCHER_HH_
+#define COMPONENT_BASED_PORT_PORT_WATCHER_HH_
+
+#include <aul.h>
+#include <aul_app_com.h>
+#include <bundle.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+
+namespace component_based {
+
+class PortWatcher {
+ public:
+ class IEvent {
+ public:
+ virtual void OnPortAppeared(const std::string& endpoint, pid_t owner) = 0;
+ virtual void OnPortVanished(const std::string& endpoint) = 0;
+ };
+
+ PortWatcher(IEvent* listener);
+ virtual ~PortWatcher();
+
+ void Watch();
+ void Unwatch();
+
+ private:
+ static int AppComCb(const char* endpoint, aul_app_com_result_e result,
+ bundle* envelope, void* user_data);
+
+ private:
+ IEvent* listener_ = nullptr;
+ aul_app_com_connection_h conn_ = nullptr;
+};
+
+} // namespace component_based
+
+#endif // COMPONENT_BASED_PORT_PORT_WATCHER_HH_
* limitations under the License.
*/
+#include <aul_component_port.h>
+#include <tizen.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+
#include "component_based/port/api/component_port.h"
#include "component_based/port/exception.hh"
#include "component_based/port/export_api.hh"
#include "component_based/port/log_private.hh"
#include "component_based/port/port.hh"
+#include "component_based/port/port_watcher.hh"
namespace {
virtual ~PortStub() = default;
void SetRequestCb(component_port_request_cb cb, void* user_data) {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
request_cb_ = cb;
request_cb_user_data_ = user_data;
}
void SetSyncRequestCb(component_port_sync_request_cb cb, void* user_data) {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
sync_request_cb_ = cb;
sync_request_cb_user_data_ = user_data;
}
private:
void OnRequest(const std::shared_ptr<component_based::SenderInfo>& sender,
const std::shared_ptr<tizen_base::Parcel>& request) override {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
if (request_cb_) {
parcel_h parcel = static_cast<parcel_h>(request.get());
request_cb_(sender->GetName().c_str(), parcel, request_cb_user_data_);
void OnSyncRequest(const std::shared_ptr<component_based::SenderInfo>& sender,
const std::shared_ptr<tizen_base::Parcel>& request,
std::shared_ptr<tizen_base::Parcel>& response) override {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
if (sync_request_cb_) {
parcel_h req_parcel = static_cast<parcel_h>(request.get());
parcel_h res_parcel = static_cast<parcel_h>(response.get());
}
}
+ std::recursive_mutex& GetMutex() const {
+ return mutex_;
+ }
+
private:
component_port_request_cb request_cb_ = nullptr;
void* request_cb_user_data_ = nullptr;
component_port_sync_request_cb sync_request_cb_ = nullptr;
void* sync_request_cb_user_data_ = nullptr;
+ mutable std::recursive_mutex mutex_;
+};
+
+class Watcher {
+ public:
+ Watcher(std::string endpoint,
+ component_port_appeared_cb appeared_cb,
+ component_port_vanished_cb vanished_cb,
+ void* user_data)
+ : endpoint_(std::move(endpoint)),
+ appeared_cb_(appeared_cb),
+ vanished_cb_(vanished_cb),
+ user_data_(user_data) {
+ }
+
+ std::string endpoint_;
+ component_port_appeared_cb appeared_cb_;
+ component_port_vanished_cb vanished_cb_;
+ void* user_data_;
+};
+
+class PortWatcherStub : public component_based::PortWatcher,
+ public component_based::PortWatcher::IEvent {
+ public:
+ PortWatcherStub() : component_based::PortWatcher(this) {
+ }
+
+ unsigned int Watch(std::string endpoint,
+ component_port_appeared_cb appeared_cb,
+ component_port_vanished_cb vanished_cb,
+ void* user_data) {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
+ try {
+ component_based::PortWatcher::Watch();
+ } catch (component_based::Exception& e) {
+ return 0;
+ }
+
+ unsigned int watcher_id = CreateWatcherId();
+ watchers_[watcher_id] = std::make_unique<Watcher>(
+ endpoint, appeared_cb, vanished_cb, user_data);
+ return watcher_id;
+ }
+
+ void Unwatch(unsigned int watcher_id) {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
+ auto found = watchers_.find(watcher_id);
+ if (found == watchers_.end())
+ return;
+
+ watchers_.erase(found);
+ }
+
+ private:
+ std::recursive_mutex& GetMutex() const {
+ return mutex_;
+ }
+
+ void OnPortAppeared(const std::string& endpoint, pid_t owner) override {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
+ auto iter = watchers_.begin();
+ while (iter != watchers_.end()) {
+ auto& watcher = iter->second;
+ iter++;
+ if (watcher->endpoint_ == endpoint)
+ watcher->appeared_cb_(endpoint.c_str(), owner, watcher->user_data_);
+ }
+ }
+
+ void OnPortVanished(const std::string& endpoint) override {
+ std::lock_guard<std::recursive_mutex> lock(GetMutex());
+ auto iter = watchers_.begin();
+ while (iter != watchers_.end()) {
+ auto& watcher = iter->second;
+ iter++;
+ if (watcher->endpoint_ == endpoint)
+ watcher->vanished_cb_(endpoint.c_str(), watcher->user_data_);
+ }
+ }
+
+ static int CreateWatcherId() {
+ static std::atomic<unsigned int> id { 0 };
+ if (id + 1 == 0)
+ id.exchange(0);
+ return ++id;
+ }
+
+ private:
+ std::unordered_map<unsigned int, std::unique_ptr<Watcher>> watchers_;
+ mutable std::recursive_mutex mutex_;
};
+PortWatcherStub port_watcher;
+
} // namespace
extern "C" EXPORT_API int component_port_create(const char* port_name,
return COMPONENT_PORT_ERROR_NONE;
}
+extern "C" EXPORT_API int component_port_is_running(const char* endpoint,
+ bool* is_running) {
+ if (endpoint == nullptr || is_running == nullptr) {
+ _E("Invalid parameter");
+ return COMPONENT_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ int ret = aul_component_port_exist(endpoint, is_running);
+ if (ret != AUL_R_OK) {
+ _E("aul_component_port_exist() is failed. error(%d)", ret);
+ return COMPONENT_PORT_ERROR_IO_ERROR;
+ }
+
+ _D("%s is %s", endpoint, *is_running ? "running" : "not running");
+ return COMPONENT_PORT_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int component_port_watch(const char *endpoint,
+ component_port_appeared_cb appeared_cb,
+ component_port_vanished_cb vanished_cb,
+ void* user_data,
+ unsigned int* watcher_id) {
+ if (endpoint == nullptr || appeared_cb == nullptr || vanished_cb == nullptr ||
+ watcher_id == nullptr) {
+ _E("Invalid parameter");
+ return COMPONENT_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ *watcher_id = ::port_watcher.Watch(endpoint, appeared_cb, vanished_cb,
+ user_data);
+ if (*watcher_id == 0) {
+ _E("Watch() is failed");
+ return COMPONENT_PORT_ERROR_IO_ERROR;
+ }
+
+ _D("endpoint(%s), watcher_id(%u)", endpoint, *watcher_id);
+ return COMPONENT_PORT_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int component_port_unwatch(unsigned int watcher_id) {
+ if (watcher_id == 0) {
+ _E("Invalid parameter");
+ return COMPONENT_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ ::port_watcher.Unwatch(watcher_id);
+ _D("watcher_id(%u)", watcher_id);
+ return COMPONENT_PORT_ERROR_NONE;
+}