+++ /dev/null
-/*
- * Copyright (c) 2015 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.
- *
- */
-
-#define _GNU_SOURCE
-#include <glib.h>
-#include "aul.h"
-#include "launch.h"
-#include "aul_cmd.h"
-#include "aul_util.h"
-#include "aul_api.h"
-#include "aul_app_com.h"
-
-static GList *handlers = NULL;
-
-struct _aul_app_com_connection_s {
- char *endpoint;
- app_com_cb callback;
- void *user_data;
-};
-
-struct _aul_app_com_permission_s {
- char *privilege;
- unsigned int propagation;
-};
-
-int app_com_recv(bundle *b)
-{
- int ret = 0;
- char *endpoint = NULL;
- size_t result_sz;
- int *result;
- GList *head = handlers;
- aul_app_com_connection_s *handler = NULL;
-
- if (b == NULL)
- return -1;
-
- ret = bundle_get_str(b, AUL_K_COM_ENDPOINT, &endpoint);
- if (ret != BUNDLE_ERROR_NONE)
- return -1;
-
- ret = bundle_get_byte(b, AUL_K_COM_RESULT, (void **)&result, &result_sz);
- if (ret != BUNDLE_ERROR_NONE)
- return -1;
-
- while (head) {
- handler = (aul_app_com_connection_s *)head->data;
- if (handler && handler->endpoint && g_strcmp0(handler->endpoint, endpoint) == 0)
- handler->callback(endpoint, *result, b, handler->user_data);
-
- head = head->next;
- }
-
- return 0;
-}
-
-API aul_app_com_permission_h aul_app_com_permission_create()
-{
- aul_app_com_permission_s *p = NULL;
- p = (aul_app_com_permission_s *)g_malloc0(sizeof(aul_app_com_permission_s));
-
- return p;
-}
-
-API void aul_app_com_permission_destroy(aul_app_com_permission_h permission)
-{
- if (permission == NULL)
- return;
-
- if (permission->privilege)
- g_free(permission->privilege);
- g_free(permission);
-}
-
-API int aul_app_com_permission_set_propagation(aul_app_com_permission_h permission, aul_app_com_propagate_option_e option)
-{
- if (permission)
- permission->propagation = option;
-
- return 0;
-}
-
-API int aul_app_com_permission_set_privilege(aul_app_com_permission_h permission, const char *privilege)
-{
- if (permission) {
- if (permission->privilege)
- g_free(permission->privilege);
-
- permission->privilege = g_strdup(privilege);
- }
-
- return 0;
-}
-
-static aul_app_com_connection_h __add_handler(const char *endpoint, app_com_cb callback, void *user_data)
-{
- aul_app_com_connection_s *h = NULL;
- h = (aul_app_com_connection_s *)g_malloc0(sizeof(aul_app_com_connection_s));
- if (h == NULL) {
- _E("out of memory");
- return NULL;
- }
-
- h->callback = callback;
- h->user_data = user_data;
- h->endpoint = g_strdup(endpoint);
-
- handlers = g_list_append(handlers, h);
-
- return h;
-}
-
-static int __create_app_com(const char *endpoint,
- aul_app_com_permission_h permission,
- app_com_cb callback,
- void *user_data,
- bool sync,
- aul_app_com_connection_h *connection)
-{
- bundle *b;
- int ret;
-
- if (endpoint == NULL || callback == NULL || connection == NULL) {
- _E("Invalid parameter");
- return AUL_R_EINVAL;
- }
-
- if (!aul_is_initialized()) {
- if (aul_launch_init(NULL, NULL) < 0)
- return AUL_R_ENOINIT;
- }
-
- b = bundle_create();
- if (!b) {
- _E("out of memory");
- return AUL_R_ENOMEM;
- }
-
- bundle_add_str(b, AUL_K_COM_ENDPOINT, endpoint);
-
- if (permission) {
- if (permission->propagation) {
- bundle_add_byte(b, AUL_K_COM_PROPAGATE,
- (GUINT_TO_POINTER(permission->propagation)),
- sizeof(unsigned int));
- }
-
- if (permission->privilege) {
- bundle_add_str(b, AUL_K_COM_PRIVILEGE,
- permission->privilege);
- }
- }
-
- if (sync) {
- ret = app_send_cmd(AUL_UTIL_PID, APP_COM_CREATE, b);
- } else {
- ret = app_send_cmd_with_noreply(AUL_UTIL_PID,
- APP_COM_CREATE, b);
- }
- bundle_free(b);
-
- if (ret == 0)
- *connection = __add_handler(endpoint, callback, user_data);
-
- return ret;
-}
-
-API int aul_app_com_create(const char *endpoint,
- aul_app_com_permission_h permission,
- app_com_cb callback,
- void *user_data,
- aul_app_com_connection_h *connection)
-{
- return __create_app_com(endpoint, permission, callback, user_data,
- true, connection);
-}
-
-API int aul_app_com_create_async(const char *endpoint,
- aul_app_com_permission_h permission,
- app_com_cb callback,
- void *user_data,
- aul_app_com_connection_h *connection)
-{
- return __create_app_com(endpoint, permission, callback, user_data,
- false, connection);
-}
-
-API int aul_app_com_join(const char *endpoint, const char *filter,
- app_com_cb callback, void *user_data,
- aul_app_com_connection_h *connection)
-{
- bundle *b;
- int ret;
-
- if (endpoint == NULL || callback == NULL || connection == NULL) {
- _E("Invalid parameter");
- return AUL_R_EINVAL;
- }
-
- if (!aul_is_initialized()) {
- if (aul_launch_init(NULL, NULL) < 0)
- return AUL_R_ENOINIT;
- }
-
- b = bundle_create();
- if (!b) {
- _E("out of memory");
- return AUL_R_ENOMEM;
- }
-
- bundle_add_str(b, AUL_K_COM_ENDPOINT, endpoint);
- if (filter)
- bundle_add_str(b, AUL_K_COM_FILTER, filter);
-
- ret = app_send_cmd(AUL_UTIL_PID, APP_COM_JOIN, b);
- bundle_free(b);
-
- if (ret == 0)
- *connection = __add_handler(endpoint, callback, user_data);
-
- return ret;
-}
-
-API int aul_app_com_send(const char *endpoint, bundle *envelope)
-{
- int ret = 0;
-
- if (endpoint == NULL || envelope == NULL)
- return -1;
-
- bundle_del(envelope, AUL_K_COM_ENDPOINT);
- bundle_add_str(envelope, AUL_K_COM_ENDPOINT, endpoint);
-
- ret = app_send_cmd(AUL_UTIL_PID, APP_COM_SEND, envelope);
-
- return ret;
-}
-
-API int aul_app_com_leave(aul_app_com_connection_h connection)
-{
- bundle *b = NULL;
- int ret = 0;
- GList *head = handlers;
- aul_app_com_connection_s *h = NULL;
- int endpoint_cnt = 0;
-
- if (connection == NULL)
- return -1;
-
- while (head) {
- h = (aul_app_com_connection_s *)head->data;
- head = head->next;
- if (h && h->endpoint && g_strcmp0(h->endpoint, connection->endpoint) == 0) {
- if (h == connection)
- handlers = g_list_remove(handlers, h);
- else
- endpoint_cnt++;
- }
- }
-
- if (endpoint_cnt > 0) {
- g_free(connection->endpoint);
- g_free(connection);
- return 0;
- }
-
- b = bundle_create();
- if (!b) {
- _E("out of memory");
- return -1;
- }
-
- bundle_add_str(b, AUL_K_COM_ENDPOINT, connection->endpoint);
-
- ret = app_send_cmd(AUL_UTIL_PID, APP_COM_LEAVE, b);
-
- bundle_free(b);
- g_free(connection->endpoint);
- g_free(connection);
-
- return ret;
-}
--- /dev/null
+/*
+ * Copyright (c) 2015 - 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 <bundle_cpp.h>
+#include <bundle_internal.h>
+
+#include <list>
+#include <mutex>
+#include <string>
+
+#include "aul_api.h"
+#include "aul_util.h"
+#include "include/aul.h"
+#include "include/aul_app_com.h"
+#include "include/aul_cmd.h"
+#include "launch.h"
+
+namespace {
+
+class AppComConnection {
+ public:
+ AppComConnection(std::string endpoint, app_com_cb cb, void* user_data)
+ : endpoint_(std::move(endpoint)),
+ cb_(cb),
+ user_data_(user_data) {
+ }
+
+ ~AppComConnection() = default;
+
+ const std::string& GetEndpoint() const {
+ return endpoint_;
+ }
+
+ void Invoke(aul_app_com_result_e result, bundle* envelope) {
+ if (cb_)
+ cb_(endpoint_.c_str(), result, envelope, user_data_);
+ }
+
+ private:
+ std::string endpoint_;
+ app_com_cb cb_;
+ void* user_data_;
+};
+
+class AppComPermission {
+ public:
+ AppComPermission() {}
+ ~AppComPermission() {}
+
+ void SetPrivilege(std::string privilege) {
+ privilege_ = std::move(privilege);
+ }
+
+ void SetPropagationOption(aul_app_com_propagate_option_e option) {
+ option_ = option;
+ }
+
+ const std::string& GetPrivilege() const {
+ return privilege_;
+ }
+
+ aul_app_com_propagate_option_e GetPropagationOption() const {
+ return option_;
+ }
+
+ private:
+ std::string privilege_;
+ aul_app_com_propagate_option_e option_;
+};
+
+class Context {
+ public:
+ Context() {}
+ ~Context() {}
+
+ int Receive(bundle* b) {
+ const char* val = bundle_get_val(b, AUL_K_COM_ENDPOINT);
+ if (val == nullptr)
+ return -1;
+
+ size_t result_size = 0;
+ aul_app_com_result_e* result = nullptr;
+ int ret = bundle_get_byte(b, AUL_K_COM_RESULT,
+ reinterpret_cast<void**>(&result), &result_size);
+ if (ret != BUNDLE_ERROR_NONE)
+ return -1;
+
+ std::string endpoint(val);
+
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ for (auto& conn : conns_) {
+ if (conn->GetEndpoint() == endpoint)
+ conn->Invoke(*result, b);
+ }
+
+ return 0;
+ }
+
+ AppComConnection* AddConnection(std::string endpoint, app_com_cb cb,
+ void* user_data) {
+ auto* conn = new (std::nothrow) AppComConnection(endpoint, cb, user_data);
+ if (conn == nullptr)
+ return nullptr;
+
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ conns_.emplace_back(conn);
+ return conn;
+ }
+
+ void RemoveConnection(AppComConnection* conn) {
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ auto iter = conns_.begin();
+ while (iter != conns_.end()) {
+ if ((*iter).get() == conn) {
+ iter = conns_.erase(iter);
+ break;
+ } else {
+ iter++;
+ }
+ }
+ }
+
+ bool ExistConnection(const std::string& endpoint) {
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ for (auto& conn : conns_) {
+ if (conn->GetEndpoint() == endpoint)
+ return true;
+ }
+
+ return false;
+ }
+
+ bool ExistConnection(AppComConnection* conn) {
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ for (auto& i : conns_) {
+ if (i.get() == conn)
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ std::list<std::unique_ptr<AppComConnection>> conns_;
+ mutable std::recursive_mutex mutex_;
+};
+
+Context context;
+
+} // namespace
+
+int app_com_recv(bundle* b) {
+ if (b == nullptr)
+ return -1;
+
+ return context.Receive(b);
+}
+
+extern "C" API aul_app_com_permission_h aul_app_com_permission_create() {
+ auto* handle = new (std::nothrow) AppComPermission();
+ return static_cast<aul_app_com_permission_h>(handle);
+}
+
+extern "C" API void aul_app_com_permission_destroy(
+ aul_app_com_permission_h permission) {
+ if (permission == nullptr)
+ return;
+
+ auto* handle = static_cast<AppComPermission*>(permission);
+ delete handle;
+}
+
+extern "C" API int aul_app_com_permission_set_propagation(
+ aul_app_com_permission_h permission,
+ aul_app_com_propagate_option_e option) {
+ if (permission == nullptr)
+ return AUL_R_EINVAL;
+
+ auto* handle = static_cast<AppComPermission*>(permission);
+ handle->SetPropagationOption(option);
+ return AUL_R_OK;
+}
+
+extern "C" API int aul_app_com_permission_set_privilege(
+ aul_app_com_permission_h permission, const char* privilege) {
+ if (permission == nullptr || privilege == nullptr)
+ return AUL_R_EINVAL;
+
+ auto* handle = static_cast<AppComPermission*>(permission);
+ handle->SetPrivilege(privilege);
+ return AUL_R_OK;
+}
+
+static int AppComCreate(const char* endpoint,
+ aul_app_com_permission_h permission, app_com_cb callback, void* user_data,
+ bool sync, aul_app_com_connection_h* connection) {
+ if (endpoint == nullptr || callback == nullptr || connection == nullptr) {
+ _E("Invalid parameter");
+ return AUL_R_EINVAL;
+ }
+
+ if (!aul_is_initialized()) {
+ if (aul_launch_init(nullptr, nullptr) < 0)
+ return AUL_R_ENOINIT;
+ }
+
+ tizen_base::Bundle b;
+ b.Add(AUL_K_COM_ENDPOINT, endpoint);
+
+ if (permission) {
+ auto* handle = static_cast<AppComPermission*>(permission);
+ auto option = handle->GetPropagationOption();
+ if (option) {
+ auto* p = reinterpret_cast<unsigned char*>(&option);
+ std::vector<unsigned char> bytes;
+ std::copy(p, p + sizeof(option), std::back_inserter(bytes));
+ b.Add(AUL_K_COM_PROPAGATE, bytes);
+ }
+
+ if (!handle->GetPrivilege().empty())
+ b.Add(AUL_K_COM_PRIVILEGE, handle->GetPrivilege());
+ }
+
+ int ret;
+ if (sync) {
+ ret = app_send_cmd(AUL_UTIL_PID, APP_COM_CREATE, b.GetHandle());
+ } else {
+ ret = app_send_cmd_with_noreply(AUL_UTIL_PID, APP_COM_CREATE,
+ b.GetHandle());
+ }
+
+ if (ret == 0) {
+ *connection = static_cast<aul_app_com_connection_h>(
+ context.AddConnection(endpoint, callback, user_data));
+ }
+
+ return ret;
+}
+
+extern "C" API int aul_app_com_create(const char* endpoint,
+ aul_app_com_permission_h permission, app_com_cb callback,
+ void* user_data, aul_app_com_connection_h* connection) {
+ return AppComCreate(endpoint, permission, callback, user_data,
+ true, connection);
+}
+
+extern "C" API int aul_app_com_create_async(const char* endpoint,
+ aul_app_com_permission_h permission, app_com_cb callback,
+ void* user_data, aul_app_com_connection_h* connection) {
+ return AppComCreate(endpoint, permission, callback, user_data,
+ false, connection);
+}
+
+extern "C" API int aul_app_com_join(const char* endpoint, const char* filter,
+ app_com_cb callback, void* user_data,
+ aul_app_com_connection_h* connection) {
+ if (endpoint == nullptr || callback == nullptr || connection == nullptr) {
+ _E("Invalid parameter");
+ return AUL_R_EINVAL;
+ }
+
+ if (!aul_is_initialized()) {
+ if (aul_launch_init(nullptr, nullptr) < 0)
+ return AUL_R_ENOINIT;
+ }
+
+ tizen_base::Bundle b;
+ b.Add(AUL_K_COM_ENDPOINT, endpoint);
+ if (filter)
+ b.Add(AUL_K_COM_FILTER, filter);
+
+ int ret = app_send_cmd(AUL_UTIL_PID, APP_COM_JOIN, b.GetHandle());
+ if (ret == 0) {
+ *connection = static_cast<aul_app_com_connection_h>(
+ context.AddConnection(endpoint, callback, user_data));
+ }
+
+ return ret;
+}
+
+extern "C" API int aul_app_com_send(const char* endpoint, bundle* envelope) {
+ if (endpoint == nullptr || envelope == nullptr)
+ return AUL_R_EINVAL;
+
+ bundle_del(envelope, AUL_K_COM_ENDPOINT);
+ bundle_add(envelope, AUL_K_COM_ENDPOINT, endpoint);
+ return app_send_cmd(AUL_UTIL_PID, APP_COM_SEND, envelope);
+}
+
+extern "C" API int aul_app_com_leave(aul_app_com_connection_h connection) {
+ if (connection == nullptr)
+ return AUL_R_EINVAL;
+
+ auto* conn = static_cast<AppComConnection*>(connection);
+ if (!context.ExistConnection(conn)) {
+ _E("Invalid parameter");
+ return AUL_R_EINVAL;
+ }
+
+ std::string endpoint = conn->GetEndpoint();
+ context.RemoveConnection(conn);
+
+ if (context.ExistConnection(endpoint))
+ return AUL_R_OK;
+
+ tizen_base::Bundle b;
+ b.Add(AUL_K_COM_ENDPOINT, endpoint);
+ return app_send_cmd(AUL_UTIL_PID, APP_COM_LEAVE, b.GetHandle());
+}