Refactor App Com 35/259935/4
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 17 Jun 2021 01:10:10 +0000 (10:10 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Fri, 18 Jun 2021 00:55:46 +0000 (00:55 +0000)
The implementation is changed to c++.

Change-Id: Idaa0b8881443d8646dc944af0b82070d92b12f6a
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
include/aul_app_com.h
src/app_com.c [deleted file]
src/app_com.cc [new file with mode: 0644]

index 2afd864..c747d9a 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  aul
- *
- * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ * 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.
@@ -14,7 +12,6 @@
  * 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 __APP_COM_H__
@@ -46,10 +43,8 @@ typedef enum {
        AUL_APP_COM_R_ILLEGAL_ACCESS = -1,
 } aul_app_com_result_e;
 
-typedef struct _aul_app_com_permission_s aul_app_com_permission_s;
-typedef aul_app_com_permission_s *aul_app_com_permission_h;
-typedef struct _aul_app_com_connection_s aul_app_com_connection_s;
-typedef aul_app_com_connection_s *aul_app_com_connection_h;
+typedef void *aul_app_com_permission_h;
+typedef void *aul_app_com_connection_h;
 
 typedef int (*app_com_cb)(const char *endpoint, aul_app_com_result_e result, bundle *envelope, void *user_data);
 
diff --git a/src/app_com.c b/src/app_com.c
deleted file mode 100644 (file)
index 90631a4..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * 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;
-}
diff --git a/src/app_com.cc b/src/app_com.cc
new file mode 100644 (file)
index 0000000..ac1d988
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * 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());
+}