From ba18e3df614b0defad9015106866d493949a1ea4 Mon Sep 17 00:00:00 2001 From: wenjun Date: Tue, 8 Sep 2020 10:21:39 +0800 Subject: [PATCH] add OpenHarmony 1.0 baseline --- .gitee/ISSUE_TEMPLATE.zh-CN.md | 13 + .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 15 + BUILD.gn | 57 ++ LICENSE | 177 ++++++ communication/broadcast/BUILD.gn | 61 ++ .../broadcast/source/broadcast_service.c | 71 +++ .../broadcast/source/broadcast_service.h | 41 ++ .../broadcast/source/pub_sub_feature.c | 116 ++++ .../broadcast/source/pub_sub_feature.h | 56 ++ .../broadcast/source/pub_sub_implement.c | 256 +++++++++ .../broadcast/source/pub_sub_implement.h | 44 ++ readme.md | 1 + samgr/BUILD.gn | 75 +++ samgr/adapter/BUILD.gn | 70 +++ samgr/adapter/cmsis/memory_adapter.c | 32 ++ samgr/adapter/cmsis/queue_adapter.c | 53 ++ samgr/adapter/cmsis/thread_adapter.c | 72 +++ samgr/adapter/cmsis/time_adapter.c | 40 ++ samgr/adapter/memory_adapter.h | 35 ++ samgr/adapter/posix/lock_free_queue.c | 119 ++++ samgr/adapter/posix/lock_free_queue.h | 49 ++ samgr/adapter/posix/memory_adapter.c | 31 + samgr/adapter/posix/queue_adapter.c | 93 +++ samgr/adapter/posix/thread_adapter.c | 101 ++++ samgr/adapter/posix/time_adapter.c | 43 ++ samgr/adapter/queue_adapter.h | 40 ++ samgr/adapter/thread_adapter.h | 60 ++ samgr/adapter/time_adapter.h | 39 ++ samgr/registry/service_registry.c | 44 ++ samgr/registry/service_registry.h | 35 ++ samgr/source/BUILD.gn | 77 +++ samgr/source/common.c | 154 +++++ samgr/source/feature.c | 64 +++ samgr/source/feature_impl.h | 57 ++ samgr/source/iunknown.c | 72 +++ samgr/source/message.c | 229 ++++++++ samgr/source/message_inner.h | 63 +++ samgr/source/samgr_lite.c | 535 ++++++++++++++++++ samgr/source/samgr_lite_inner.h | 68 +++ samgr/source/samgr_maintenance.c | 98 ++++ samgr/source/samgr_maintenance.h | 29 + samgr/source/service.c | 195 +++++++ samgr/source/service_impl.h | 80 +++ samgr/source/task_manager.c | 248 ++++++++ samgr/source/task_manager.h | 58 ++ samgr_client/BUILD.gn | 40 ++ samgr_client/source/remote_register.c | 206 +++++++ samgr_client/source/remote_register.h | 38 ++ samgr_endpoint/BUILD.gn | 69 +++ samgr_endpoint/source/client_factory.c | 118 ++++ samgr_endpoint/source/client_factory.h | 32 ++ samgr_endpoint/source/default_client.c | 222 ++++++++ samgr_endpoint/source/default_client.h | 41 ++ samgr_endpoint/source/endpoint.c | 475 ++++++++++++++++ samgr_endpoint/source/endpoint.h | 75 +++ samgr_endpoint/source/sa_store.c | 251 ++++++++ samgr_endpoint/source/sa_store.h | 87 +++ samgr_endpoint/source/token_bucket.c | 34 ++ samgr_endpoint/source/token_bucket.h | 52 ++ samgr_server/BUILD.gn | 42 ++ samgr_server/source/samgr_server.c | 475 ++++++++++++++++ samgr_server/source/samgr_server.h | 56 ++ 62 files changed, 6279 insertions(+) create mode 100755 .gitee/ISSUE_TEMPLATE.zh-CN.md create mode 100755 .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md create mode 100755 BUILD.gn create mode 100755 LICENSE create mode 100755 communication/broadcast/BUILD.gn create mode 100755 communication/broadcast/source/broadcast_service.c create mode 100755 communication/broadcast/source/broadcast_service.h create mode 100755 communication/broadcast/source/pub_sub_feature.c create mode 100755 communication/broadcast/source/pub_sub_feature.h create mode 100755 communication/broadcast/source/pub_sub_implement.c create mode 100755 communication/broadcast/source/pub_sub_implement.h create mode 100755 readme.md create mode 100755 samgr/BUILD.gn create mode 100755 samgr/adapter/BUILD.gn create mode 100755 samgr/adapter/cmsis/memory_adapter.c create mode 100755 samgr/adapter/cmsis/queue_adapter.c create mode 100755 samgr/adapter/cmsis/thread_adapter.c create mode 100755 samgr/adapter/cmsis/time_adapter.c create mode 100755 samgr/adapter/memory_adapter.h create mode 100755 samgr/adapter/posix/lock_free_queue.c create mode 100755 samgr/adapter/posix/lock_free_queue.h create mode 100755 samgr/adapter/posix/memory_adapter.c create mode 100755 samgr/adapter/posix/queue_adapter.c create mode 100755 samgr/adapter/posix/thread_adapter.c create mode 100755 samgr/adapter/posix/time_adapter.c create mode 100755 samgr/adapter/queue_adapter.h create mode 100755 samgr/adapter/thread_adapter.h create mode 100755 samgr/adapter/time_adapter.h create mode 100755 samgr/registry/service_registry.c create mode 100755 samgr/registry/service_registry.h create mode 100755 samgr/source/BUILD.gn create mode 100755 samgr/source/common.c create mode 100755 samgr/source/feature.c create mode 100755 samgr/source/feature_impl.h create mode 100755 samgr/source/iunknown.c create mode 100755 samgr/source/message.c create mode 100755 samgr/source/message_inner.h create mode 100755 samgr/source/samgr_lite.c create mode 100755 samgr/source/samgr_lite_inner.h create mode 100755 samgr/source/samgr_maintenance.c create mode 100755 samgr/source/samgr_maintenance.h create mode 100755 samgr/source/service.c create mode 100755 samgr/source/service_impl.h create mode 100755 samgr/source/task_manager.c create mode 100755 samgr/source/task_manager.h create mode 100755 samgr_client/BUILD.gn create mode 100755 samgr_client/source/remote_register.c create mode 100755 samgr_client/source/remote_register.h create mode 100755 samgr_endpoint/BUILD.gn create mode 100755 samgr_endpoint/source/client_factory.c create mode 100755 samgr_endpoint/source/client_factory.h create mode 100755 samgr_endpoint/source/default_client.c create mode 100755 samgr_endpoint/source/default_client.h create mode 100755 samgr_endpoint/source/endpoint.c create mode 100755 samgr_endpoint/source/endpoint.h create mode 100755 samgr_endpoint/source/sa_store.c create mode 100755 samgr_endpoint/source/sa_store.h create mode 100755 samgr_endpoint/source/token_bucket.c create mode 100755 samgr_endpoint/source/token_bucket.h create mode 100755 samgr_server/BUILD.gn create mode 100755 samgr_server/source/samgr_server.c create mode 100755 samgr_server/source/samgr_server.h diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md new file mode 100755 index 0000000..f09d98d --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -0,0 +1,13 @@ +### 该问题是怎么引起的? + + + +### 重现步骤 + + + +### 报错信息 + + + + diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md new file mode 100755 index 0000000..33948fd --- /dev/null +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -0,0 +1,15 @@ +### 相关的Issue + + +### 原因(目的、解决的问题等) + + +### 描述(做了什么,变更了什么) + + +### 测试用例(新增、改动、可能影响的功能) + + + + + diff --git a/BUILD.gn b/BUILD.gn new file mode 100755 index 0000000..6c54db1 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2020 Huawei Device 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. +import("//build/lite/config/component/lite_component.gni") +import("//build/lite/ndk/ndk.gni") + +lite_component("samgr") { + features = [ + "samgr", + "communication/broadcast", + ] + + if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux"){ + features += [ + "samgr_server:server", + "samgr_client:client", + ] + } +} + +ndk_lib("samgr_lite_ndk") { + if(ohos_kernel_type == "liteos_riscv" || ohos_kernel_type == "liteos_m") { + lib_extension = ".a" + } else if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + lib_extension = ".so" + } + deps = [ + "samgr", + "communication/broadcast", + ] + head_files = [ + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/communication/broadcast", + ] + if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux"){ + deps += [ + "samgr_server:server", + ] + head_files += ["//foundation/distributedschedule/interfaces/kits/samgr_lite/registry"] + } +} + +generate_notice_file("samgr_notice_file") { + module_name = "samgr" + module_source_dir_list = [ + "//third_party/bounds_checking_function" + ] +} diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..4a45986 --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/communication/broadcast/BUILD.gn b/communication/broadcast/BUILD.gn new file mode 100755 index 0000000..6943420 --- /dev/null +++ b/communication/broadcast/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright (c) 2020 Huawei Device 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. + +config("broadcast_public") { + include_dirs = [ + "//foundation/distributedschedule/interfaces/kits/samgr_lite/communication/broadcast", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//foundation/distributedschedule/services/samgr_lite/samgr/adapter", + "//utils/native/lite/include", + ] +} + +if (ohos_kernel_type == "liteos_riscv" || ohos_kernel_type == "liteos_m") { + static_library("broadcast") { + sources = [ + "source/pub_sub_implement.c", + "source/pub_sub_feature.c", + "source/broadcast_service.c", + ] + public_configs = [":broadcast_public"] + cflags = [ "-Wall" ] + include_dirs = [ + "//kernel/liteos_m/components/cmsis", + ] + } +} + +if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + shared_library("broadcast") { + sources = [ + "source/pub_sub_implement.c", + "source/pub_sub_feature.c", + "source/broadcast_service.c", + ] + public_configs = [":broadcast_public"] + configs -= [ "//build/lite/config:language_c" ] + cflags_c = [ + "-std=c11", + "-Wall" + ] + include_dirs = [ + "//kernel/liteos_a/kernel/include/", + "//third_party/bounds_checking_function/include", + "//kernel/liteos_a/kernel/common", + ] + public_deps = [ + "//third_party/bounds_checking_function:libsec_shared", + "//foundation/distributedschedule/services/samgr_lite/samgr:samgr", + ] + } +} diff --git a/communication/broadcast/source/broadcast_service.c b/communication/broadcast/source/broadcast_service.c new file mode 100755 index 0000000..467126f --- /dev/null +++ b/communication/broadcast/source/broadcast_service.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "broadcast_service.h" +#include "ohos_init.h" +#include "common.h" +#include "samgr_lite.h" +#include "thread_adapter.h" +#include "pub_sub_feature.h" +static const char *GetName(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static TaskConfig GetTaskConfig(Service *service); +static BOOL MessageHandle(Service *service, Request *request); +static BroadcastService g_broadcastService = { + GetName, + Initialize, + MessageHandle, + GetTaskConfig, +}; + +static void Init(void) +{ + SAMGR_GetInstance()->RegisterService((Service *)&g_broadcastService); +} +SYS_SERVICE_INIT(Init); + +static const char *GetName(Service *service) +{ + (void)service; + return BROADCAST_SERVICE; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + (void)identity; + if (service == NULL) { + return FALSE; + } + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *request) +{ + (void)service; + switch (request->msgId) { + case BROADCAST_MSG: + break; + default: + break; + } + return TRUE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_ABOVE_NORMAL, 0x800, 40, SPECIFIED_TASK}; + return config; +} diff --git a/communication/broadcast/source/broadcast_service.h b/communication/broadcast/source/broadcast_service.h new file mode 100755 index 0000000..fd53e9d --- /dev/null +++ b/communication/broadcast/source/broadcast_service.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_BROADCAST_SERVICE_H +#define LITE_BROADCAST_SERVICE_H + +#include "service.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +enum BroadcastMsgType { + BROADCAST_MSG, +}; +typedef struct BroadcastService BroadcastService; + +struct BroadcastService { + INHERIT_SERVICE; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_BROADCAST_SERVICE_H diff --git a/communication/broadcast/source/pub_sub_feature.c b/communication/broadcast/source/pub_sub_feature.c new file mode 100755 index 0000000..89e4cc2 --- /dev/null +++ b/communication/broadcast/source/pub_sub_feature.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "pub_sub_feature.h" +#include +#include "samgr_lite.h" +#include "thread_adapter.h" +#include "pub_sub_implement.h" + +static const char *GetName(Feature *feature); +static void OnInitialize(Feature *feature, Service *parent, Identity identity); +static void OnStop(Feature *feature, Identity identity); +static BOOL OnMessage(Feature *feature, Request *request); +static Relation *GetRelation(PubSubFeature *feature, const Topic *topic); +static BOOL IsTopicEqual(const Topic *current, const Topic *other); +static PubSubFeature g_broadcastFeature = { + .GetName = GetName, + .OnInitialize = OnInitialize, + .OnStop = OnStop, + .OnMessage = OnMessage, + .GetRelation = GetRelation, +}; + +static void Init(void) +{ + PubSubFeature *feature = &g_broadcastFeature; + feature->relations.topic = -1; + feature->relations.callbacks.consumer = NULL; + UtilsListInit(&feature->relations.callbacks.node); + UtilsListInit(&feature->relations.node); + feature->mutex = MUTEX_InitValue(); + SAMGR_GetInstance()->RegisterFeature(BROADCAST_SERVICE, (Feature *)feature); + + PubSubImplement *apiEntry = BCE_CreateInstance((Feature *)feature); + SAMGR_GetInstance()->RegisterFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE, GET_IUNKNOWN(*apiEntry)); +} +SYS_FEATURE_INIT(Init); + +static const char *GetName(Feature *feature) +{ + (void)feature; + return PUB_SUB_FEATURE; +} + +static void OnInitialize(Feature *feature, Service *parent, Identity identity) +{ + (void)parent; + ((PubSubFeature *)feature)->identity = identity; +} + +static void OnStop(Feature *feature, Identity identity) +{ + (void)feature; + (void)identity; +} + +static BOOL OnMessage(Feature *feature, Request *request) +{ + PubSubFeature *broadcast = (PubSubFeature *)feature; + switch (request->msgId) { + case MSG_PUBLISH: { + Topic topic = request->msgValue; + Relation *relation = broadcast->GetRelation(broadcast, &topic); + if (relation == NULL) { + return FALSE; + } + MUTEX_Lock(broadcast->mutex); + ConsumerNode *item = NULL; + UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) { + if (item->consumer->identity == NULL) { + item->consumer->Notify(item->consumer, &topic, request); + } + } + MUTEX_Unlock(broadcast->mutex); + } + break; + default: + break; + } + return TRUE; +} + +static Relation *GetRelation(PubSubFeature *feature, const Topic *topic) +{ + if (feature == NULL || topic == NULL) { + return NULL; + } + + UTILS_DL_LIST *list = &feature->relations.node; + Relation *item = NULL; + MUTEX_Lock(feature->mutex); + UTILS_DL_LIST_FOR_EACH_ENTRY(item, list, Relation, node) { + if (IsTopicEqual(&item->topic, topic)) { + MUTEX_Unlock(feature->mutex); + return item; + } + } + MUTEX_Unlock(feature->mutex); + return NULL; +} + +static BOOL IsTopicEqual(const Topic *current, const Topic *other) +{ + return *current == *other; +} diff --git a/communication/broadcast/source/pub_sub_feature.h b/communication/broadcast/source/pub_sub_feature.h new file mode 100755 index 0000000..8f0e6d2 --- /dev/null +++ b/communication/broadcast/source/pub_sub_feature.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_PUB_SUB_FEATURE_H +#define LITE_PUB_SUB_FEATURE_H + +#include "utils_list.h" +#include "message.h" +#include "feature.h" +#include "common.h" +#include "broadcast_interface.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct ConsumerNode { + UTILS_DL_LIST node; + Consumer *consumer; +} ConsumerNode; + +typedef struct Relation { + UTILS_DL_LIST node; + ConsumerNode callbacks; + Topic topic; +} Relation; +typedef struct PubSubFeature PubSubFeature; + +struct PubSubFeature { + INHERIT_FEATURE; + Relation *(*GetRelation)(PubSubFeature *feature, const Topic *topic); + MutexId mutex; + Relation relations; + Identity identity; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_PUB_SUB_FEATURE_H diff --git a/communication/broadcast/source/pub_sub_implement.c b/communication/broadcast/source/pub_sub_implement.c new file mode 100755 index 0000000..275facb --- /dev/null +++ b/communication/broadcast/source/pub_sub_implement.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "pub_sub_implement.h" +#include "securec.h" +#include "ohos_errno.h" +#include "memory_adapter.h" +#include "thread_adapter.h" + +static int AddTopic(IUnknown *iUnknown, const Topic *topic); +static int Subscribe(IUnknown *iUnknown, const Topic *topic, Consumer *consumer); +static Consumer *ModifyConsumer(IUnknown *iUnknown, const Topic *topic, Consumer *oldConsumer, Consumer *newConsumer); +static Consumer *Unsubscribe(IUnknown *iUnknown, const Topic *topic, const Consumer *consumer); +static BOOL Publish(IUnknown *iUnknown, const Topic *topic, uint8 *data, int16 len); +static void DefaultHandle(const Request *request, const Response *response); +static BOOL ImmediatelyPublish(PubSubFeature *feature, const Topic *topic, const Request *request); + +static PubSubImplement g_pubSubImplement = { + DEFAULT_IUNKNOWN_ENTRY_BEGIN, + .subscriber.AddTopic = AddTopic, + .subscriber.Subscribe = Subscribe, + .subscriber.ModifyConsumer = ModifyConsumer, + .subscriber.Unsubscribe = Unsubscribe, + .provider.Publish = Publish, + DEFAULT_IUNKNOWN_ENTRY_END, + .feature = NULL +}; +PubSubImplement *BCE_CreateInstance(Feature *feature) +{ + g_pubSubImplement.feature = (PubSubFeature *)feature; + return &g_pubSubImplement; +} + + +static int AddTopic(IUnknown *iUnknown, const Topic *topic) +{ + if (iUnknown == NULL || topic == NULL) { + return EC_INVALID; + } + + PubSubImplement *broadcast = GET_OBJECT(iUnknown, PubSubImplement, iUnknown); + if (broadcast->feature == NULL || broadcast->feature->GetRelation == NULL) { + return EC_FAILURE; + } + + if (broadcast->feature->GetRelation(broadcast->feature, topic) != NULL) { + return EC_FAILURE; + } + + Relation *head = &broadcast->feature->relations; + Relation *newRelation = (Relation *)SAMGR_Malloc(sizeof(Relation)); + if (newRelation == NULL) { + return EC_NOMEMORY; + } + newRelation->topic = *topic; + newRelation->callbacks.consumer = NULL; + UtilsListInit(&newRelation->callbacks.node); + + MUTEX_Lock(broadcast->feature->mutex); + UtilsListAdd(&head->node, &(newRelation->node)); + MUTEX_Unlock(broadcast->feature->mutex); + return EC_SUCCESS; +} + +static int Subscribe(IUnknown *iUnknown, const Topic *topic, Consumer *consumer) +{ + if (iUnknown == NULL || topic == NULL || consumer == NULL) { + return EC_INVALID; + } + + PubSubImplement *broadcast = GET_OBJECT(iUnknown, PubSubImplement, iUnknown); + if (broadcast->feature == NULL || broadcast->feature->GetRelation == NULL) { + return EC_FAILURE; + } + + Relation *relation = broadcast->feature->GetRelation(broadcast->feature, topic); + if (relation == NULL) { + return EC_FAILURE; + } + + MUTEX_Lock(broadcast->feature->mutex); + ConsumerNode *item = NULL; + UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) { + if (item->consumer->Equal(item->consumer, consumer)) { + MUTEX_Unlock(broadcast->feature->mutex); + return EC_ALREADY_SUBSCRIBED; + } + } + MUTEX_Unlock(broadcast->feature->mutex); + ConsumerNode *consumerNode = (ConsumerNode *)SAMGR_Malloc(sizeof(ConsumerNode)); + if (consumerNode == NULL) { + return EC_NOMEMORY; + } + + UtilsListInit(&consumerNode->node); + consumerNode->consumer = consumer; + MUTEX_Lock(broadcast->feature->mutex); + ConsumerNode *head = &relation->callbacks; + UtilsListAdd(&head->node, &consumerNode->node); + MUTEX_Unlock(broadcast->feature->mutex); + return EC_SUCCESS; +} + +static Consumer *ModifyConsumer(IUnknown *iUnknown, const Topic *topic, Consumer *oldConsumer, Consumer *newConsumer) +{ + if (iUnknown == NULL || topic == NULL || oldConsumer == NULL || newConsumer == NULL) { + return NULL; + } + + PubSubImplement *broadcast = GET_OBJECT(iUnknown, PubSubImplement, iUnknown); + if (broadcast->feature == NULL || broadcast->feature->GetRelation == NULL) { + return NULL; + } + + Relation *relation = broadcast->feature->GetRelation(broadcast->feature, topic); + if (relation == NULL) { + return NULL; + } + + MUTEX_Lock(broadcast->feature->mutex); + ConsumerNode *item = NULL; + UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) { + if (item->consumer->Equal(item->consumer, oldConsumer)) { + Consumer *older = item->consumer; + item->consumer = newConsumer; + MUTEX_Unlock(broadcast->feature->mutex); + return older; + } + } + MUTEX_Unlock(broadcast->feature->mutex); + return NULL; +} + +static Consumer *Unsubscribe(IUnknown *iUnknown, const Topic *topic, const Consumer *consumer) +{ + if (iUnknown == NULL || topic == NULL || consumer == NULL) { + return NULL; + } + + PubSubImplement *broadcast = GET_OBJECT(iUnknown, PubSubImplement, iUnknown); + if (broadcast->feature == NULL || broadcast->feature->GetRelation == NULL) { + return NULL; + } + + Relation *relation = broadcast->feature->GetRelation(broadcast->feature, topic); + if (relation == NULL) { + return NULL; + } + MUTEX_Lock(broadcast->feature->mutex); + ConsumerNode *item = NULL; + UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) { + if (item->consumer->Equal(item->consumer, consumer)) { + UtilsListDelete(&item->node); + break; + } + } + MUTEX_Unlock(broadcast->feature->mutex); + if (item == &relation->callbacks || item == NULL) { + return NULL; + } + Consumer *oldConsumer = item->consumer; + SAMGR_Free(item); + return oldConsumer; +} + +static BOOL Publish(IUnknown *iUnknown, const Topic *topic, uint8 *data, int16 len) +{ + PubSubImplement *broadcast = GET_OBJECT(iUnknown, PubSubImplement, iUnknown); + PubSubFeature *feature = broadcast->feature; + if (feature == NULL) { + return FALSE; + } + + Request request = {MSG_PUBLISH, 0, NULL, *(uint32 *)topic}; + if (data != NULL && len > 0) { + request.data = (uint8 *)SAMGR_Malloc(len); + if (request.data == NULL) { + return FALSE; + } + request.len = len; + // There is no problem, the request.data length is equal the input data length. + (void)memcpy_s(request.data, request.len, data, len); + } + + if (!ImmediatelyPublish(feature, topic, &request)) { + (void)SAMGR_Free(request.data); + request.data = NULL; + request.len = 0; + return FALSE; + } + return TRUE; +} + +static BOOL ImmediatelyPublish(PubSubFeature *feature, const Topic *topic, const Request *request) +{ + if (feature->GetRelation == NULL) { + return FALSE; + } + + Relation *relation = feature->GetRelation(feature, topic); + if (relation == NULL) { + return FALSE; + } + + if (UtilsListEmpty(&relation->callbacks.node)) { + return FALSE; + } + + BOOL needAync = FALSE; + ConsumerNode *item = NULL; + uint32 *token = NULL; + MUTEX_Lock(feature->mutex); + UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) { + if (item->consumer->identity == NULL) { + needAync = TRUE; + continue; + } + + Response response = {item->consumer, 0}; + int ret = SAMGR_SendSharedDirectRequest(item->consumer->identity, request, &response, &token, DefaultHandle); + if (ret != EC_SUCCESS) { + needAync = FALSE; + break; + } + } + if (needAync) { + token = SAMGR_SendSharedRequest(&feature->identity, request, token, NULL); + } + MUTEX_Unlock(feature->mutex); + return (token != NULL); +} + +static void DefaultHandle(const Request *request, const Response *response) +{ + Consumer *consumer = (Consumer *)response->data; + if (consumer == NULL || consumer->Notify == NULL || g_pubSubImplement.feature == NULL) { + return; + } + + // wait ImmediatelyPublish finished. + MUTEX_Lock(g_pubSubImplement.feature->mutex); + MUTEX_Unlock(g_pubSubImplement.feature->mutex); + Topic topic = request->msgValue; + consumer->Notify(consumer, &topic, request); +} \ No newline at end of file diff --git a/communication/broadcast/source/pub_sub_implement.h b/communication/broadcast/source/pub_sub_implement.h new file mode 100755 index 0000000..325c920 --- /dev/null +++ b/communication/broadcast/source/pub_sub_implement.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_PUB_SUB_IMPLEMENT_H +#define LITE_PUB_SUB_IMPLEMENT_H + +#include "broadcast_interface.h" +#include "pub_sub_feature.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +enum MessageID { + MSG_PUBLISH = 1, + MSG_BUTT +}; + +typedef struct PubSubImplement { + INHERIT_IUNKNOWNENTRY(PubSubInterface); + PubSubFeature *feature; +} PubSubImplement; + +PubSubImplement *BCE_CreateInstance(Feature *feature); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_PUB_SUB_IMPLEMENT_H diff --git a/readme.md b/readme.md new file mode 100755 index 0000000..33fe50d --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +详见:https://gitee.com/openharmony/docs/blob/master/readme/系统服务框架子系统README.md diff --git a/samgr/BUILD.gn b/samgr/BUILD.gn new file mode 100755 index 0000000..ba813e7 --- /dev/null +++ b/samgr/BUILD.gn @@ -0,0 +1,75 @@ +# Copyright (c) 2020 Huawei Device 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. +config("external_settings_shared") { + defines = ["LAYER_INIT_SHARED_LIB"] +} + +config("samgr_public") { + include_dirs = [ + "adapter", + "registry", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/registry", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//utils/native/lite/include", + ] +} + +if (ohos_kernel_type == "liteos_riscv" || ohos_kernel_type == "liteos_m") { + static_library("samgr") { + sources = [ + "source/samgr_lite.c", + "registry/service_registry.c", + ] + + public_configs = [":samgr_public"] + cflags = [ "-Wall" ] + + include_dirs = [ + "//base/hiviewdfx/interfaces/kits/hilog_lite", + "//kernel/liteos_m/components/cmsis", + ] + + public_deps = [ + "//foundation/distributedschedule/services/samgr_lite/samgr/adapter:samgr_adapter", + "//foundation/distributedschedule/services/samgr_lite/samgr/source:samgr_source" + ] + } +} + +if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + shared_library("samgr") { + sources = [ + "source/samgr_lite.c", + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + + public_configs = [":samgr_public"] + + include_dirs = [ + "//kernel/liteos_a/kernel/include/", + "//third_party/bounds_checking_function/include", + ] + + public_deps = [ + "//foundation/distributedschedule/services/samgr_lite/samgr/source:samgr_source", + "//foundation/distributedschedule/services/samgr_lite/samgr_client:client", + "//foundation/communication/frameworks/ipc_lite:liteipc_adapter", + ] + + public_configs += [":external_settings_shared"] + } +} diff --git a/samgr/adapter/BUILD.gn b/samgr/adapter/BUILD.gn new file mode 100755 index 0000000..637f1f8 --- /dev/null +++ b/samgr/adapter/BUILD.gn @@ -0,0 +1,70 @@ +# Copyright (c) 2020 Huawei Device 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. + +config("samgr_adapter_public") { + include_dirs = [ + "./", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//utils/native/lite/include", + ] +} + +if (ohos_kernel_type == "liteos_riscv" || ohos_kernel_type == "liteos_m") { + static_library("samgr_adapter") { + sources = [ + "cmsis/memory_adapter.c", + "cmsis/queue_adapter.c", + "cmsis/thread_adapter.c", + "cmsis/time_adapter.c", + ] + + public_configs = [":samgr_adapter_public"] + cflags = [ "-Wall" ] + + include_dirs = [ + "//kernel/liteos_m/components/cmsis", + "//kernel/liteos_m/components/kal/include", + ] + } +} + +if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + source_set("samgr_adapter") { + sources = [ + "posix/lock_free_queue.c", + "posix/memory_adapter.c", + "posix/queue_adapter.c", + "posix/thread_adapter.c", + "posix/time_adapter.c", + ] + + public_configs = [":samgr_adapter_public"] + + include_dirs = [ + "//kernel/liteos_a/kernel/include/", + "//third_party/bounds_checking_function/include", + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + public_deps = [ + "//third_party/bounds_checking_function:libsec_shared" + ] + defines = [ "_GNU_SOURCE" ] + if (ohos_kernel_type == "linux") { + defines += [ "SAMGR_LINUX_ADAPTER" ] + } + } +} diff --git a/samgr/adapter/cmsis/memory_adapter.c b/samgr/adapter/cmsis/memory_adapter.c new file mode 100755 index 0000000..337ca3c --- /dev/null +++ b/samgr/adapter/cmsis/memory_adapter.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "memory_adapter.h" +#include + +void *SAMGR_Malloc(uint32 size) +{ + if (size == 0) { + return NULL; + } + return LOS_MemAlloc(m_aucSysMem0, (UINT32)size); +} + +void SAMGR_Free(void *buffer) +{ + if (buffer == NULL) { + return; + } + (void)LOS_MemFree(m_aucSysMem0, buffer); +} \ No newline at end of file diff --git a/samgr/adapter/cmsis/queue_adapter.c b/samgr/adapter/cmsis/queue_adapter.c new file mode 100755 index 0000000..e2725fd --- /dev/null +++ b/samgr/adapter/cmsis/queue_adapter.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "queue_adapter.h" +#include +#include +#include + +MQueueId QUEUE_Create(const char *name, int size, int count) +{ + osMessageQueueAttr_t queueAttr = {name, 0, NULL, 0, NULL, 0}; + return (MQueueId)osMessageQueueNew(count, size, &queueAttr); +} + +int QUEUE_Put(MQueueId queueId, const void *element, uint8 pri, int timeout) +{ + uint32_t waitTime = (timeout <= 0) ? 0 : (uint32_t)timeout; + osStatus_t ret = osMessageQueuePut(queueId, element, pri, waitTime); + if (ret != osOK) { + return EC_BUSBUSY; + } + return EC_SUCCESS; +} + +int QUEUE_Pop(MQueueId queueId, void *element, uint8 *pri, int timeout) +{ + uint32_t waitTime = (timeout <= 0) ? osWaitForever : (uint32_t)timeout; + osStatus_t evt = osMessageQueueGet(queueId, element, pri, waitTime); + if (evt != osOK) { + return EC_BUSBUSY; + } + return EC_SUCCESS; +} + +int QUEUE_Destroy(MQueueId queueId) +{ + osStatus_t evt = osMessageQueueDelete(queueId); + if (evt != osOK) { + return EC_FAILURE; + } + return EC_SUCCESS; +} \ No newline at end of file diff --git a/samgr/adapter/cmsis/thread_adapter.c b/samgr/adapter/cmsis/thread_adapter.c new file mode 100755 index 0000000..69dbad2 --- /dev/null +++ b/samgr/adapter/cmsis/thread_adapter.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "thread_adapter.h" +#include "common.h" +#include +#include + +extern void *osThreadGetArgument(void); + +MutexId MUTEX_InitValue() +{ + return osMutexNew(NULL); +} + +void MUTEX_Lock(MutexId mutex) +{ + if (mutex == NULL) { + return; + } + osMutexAcquire(mutex, LOS_WAIT_FOREVER); +} + +void MUTEX_Unlock(MutexId mutex) +{ + if (mutex == NULL) { + return; + } + osMutexRelease(mutex); +} + +void MUTEX_GlobalLock(void) +{ + LOS_TaskLock(); +} + +void MUTEX_GlobalUnlock(void) +{ + LOS_TaskUnlock(); +} + +ThreadId THREAD_Create(Runnable run, void *argv, const ThreadAttr *attr) +{ + osThreadAttr_t taskAttr = {attr->name, 0, NULL, 0, NULL, attr->stackSize, attr->priority, 0, 0}; + return (ThreadId)osThreadNew((osThreadFunc_t)run, argv, &taskAttr); +} + +int THREAD_Total(void) +{ + return osThreadGetCount(); +} + +void *THREAD_GetThreadLocal(void) +{ + return osThreadGetArgument(); +} + +void THREAD_SetThreadLocal(const void *local) +{ + (void)local; +} \ No newline at end of file diff --git a/samgr/adapter/cmsis/time_adapter.c b/samgr/adapter/cmsis/time_adapter.c new file mode 100755 index 0000000..d3e0f32 --- /dev/null +++ b/samgr/adapter/cmsis/time_adapter.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "time_adapter.h" +#include +#include +#include + +int32 WDT_Start(uint32 ms) +{ + return WDT_Reset(ms); +} + +int32 WDT_Reset(uint32 ms) +{ + (void)ms; + return EC_FAILURE; +} + +int32 WDT_Stop(void) +{ + return EC_FAILURE; +} + +uint64 SAMGR_GetProcessTime(void) +{ + uint32 tick = osKernelGetTickCount(); + return KalTickToMs(tick); +} diff --git a/samgr/adapter/memory_adapter.h b/samgr/adapter/memory_adapter.h new file mode 100755 index 0000000..2948ca1 --- /dev/null +++ b/samgr/adapter/memory_adapter.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_MEMORY_ADAPTER_H +#define LITE_MEMORY_ADAPTER_H + +#include "ohos_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +void *SAMGR_Malloc(uint32 size); + +void SAMGR_Free(void *buffer); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_MEMORY_ADAPTER_H diff --git a/samgr/adapter/posix/lock_free_queue.c b/samgr/adapter/posix/lock_free_queue.c new file mode 100755 index 0000000..6f53448 --- /dev/null +++ b/samgr/adapter/posix/lock_free_queue.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "lock_free_queue.h" +#include +#include +#include +#include + +LockFreeQueue *LFQUE_Create(int size, int count) +{ + if (size <= 0 || count <= 0) { + return NULL; + } + + int total = size * count + 1; + if (total <= 0) { + return NULL; + } + + register LockFreeQueue *queue = (LockFreeQueue *)SAMGR_Malloc(sizeof(LockFreeQueue) + total); + if (queue == NULL) { + return NULL; + } + queue->write = 0; + queue->read = 0; + queue->itemSize = size; + queue->totalSize = total; + return queue; +} + +BOOL LFQUE_IsFull(LockFreeQueue *queue) +{ + uint32 nextWrite = queue->write + 1; + if (nextWrite >= queue->totalSize) { + nextWrite = 0; + } + return (nextWrite == queue->read); +} + +BOOL LFQUE_IsEmpty(LockFreeQueue *queue) +{ + return (queue->write == queue->read); +} + +int LFQUE_Push(LockFreeQueue *queue, const void *element, uint8 pri) +{ + (void)pri; + if (queue == NULL || element == NULL) { + return EC_INVALID; + } + + if (LFQUE_IsFull(queue)) { + return EC_BUSBUSY; + } + uint32 copyLen = (queue->totalSize - queue->write < queue->itemSize) ? + (queue->totalSize - queue->write) : queue->itemSize; + if (memcpy_s(&queue->buffer[queue->write], copyLen, element, copyLen) != EOK) { + return EC_INVALID; + } + + element += copyLen; + copyLen = queue->itemSize - copyLen; + if (copyLen > 0) { + if (memcpy_s(queue->buffer, copyLen, element, copyLen) != EOK) { + return EC_INVALID; + } + } + + uint32 write = queue->write + queue->itemSize; + if (write >= queue->totalSize) { + write = write - queue->totalSize; + } + queue->write = write; + return EC_SUCCESS; +} + +int LFQUE_Pop(LockFreeQueue *queue, void *element, uint8 *pri) +{ + (void)pri; + if (queue == NULL || element == NULL) { + return EC_INVALID; + } + if (LFQUE_IsEmpty(queue)) { + return EC_FAILURE; + } + + uint32 copyLen = (queue->totalSize - queue->read < queue->itemSize) ? + (queue->totalSize - queue->read) : queue->itemSize; + if (memcpy_s(element, copyLen, &queue->buffer[queue->read], copyLen) != EOK) { + return EC_FAILURE; + } + + element += copyLen; + copyLen = queue->itemSize - copyLen; + if (copyLen > 0) { + if (memcpy_s(element, copyLen, queue->buffer, copyLen) != EOK) { + return EC_FAILURE; + } + } + + uint32 read = queue->read + queue->itemSize; + if (read >= queue->totalSize) { + read = read - queue->totalSize; + } + queue->read = read; + return EC_SUCCESS; +} \ No newline at end of file diff --git a/samgr/adapter/posix/lock_free_queue.h b/samgr/adapter/posix/lock_free_queue.h new file mode 100755 index 0000000..7e42835 --- /dev/null +++ b/samgr/adapter/posix/lock_free_queue.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_LOCK_FREE_QUEUE_H +#define LITE_LOCK_FREE_QUEUE_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct LockFreeQueue LockFreeQueue; +struct LockFreeQueue { + uint32 write; + uint32 read; + uint32 itemSize; + uint32 totalSize; + uint8 buffer[0]; +}; +LockFreeQueue *LFQUE_Create(int size, int count); + +BOOL LFQUE_IsEmpty(LockFreeQueue *queue); + +BOOL LFQUE_IsFull(LockFreeQueue *queue); + +int LFQUE_Push(LockFreeQueue *queue, const void *element, uint8 pri); + +int LFQUE_Pop(LockFreeQueue *queue, void *element, uint8 *pri); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_LOCK_FREE_QUEUE_H diff --git a/samgr/adapter/posix/memory_adapter.c b/samgr/adapter/posix/memory_adapter.c new file mode 100755 index 0000000..2504b65 --- /dev/null +++ b/samgr/adapter/posix/memory_adapter.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "memory_adapter.h" +#include +void *SAMGR_Malloc(uint32 size) +{ + if (size == 0) { + return NULL; + } + return malloc(size); +} + +void SAMGR_Free(void *buffer) +{ + if (buffer == NULL) { + return; + } + (void)free(buffer); +} \ No newline at end of file diff --git a/samgr/adapter/posix/queue_adapter.c b/samgr/adapter/posix/queue_adapter.c new file mode 100755 index 0000000..6aa0636 --- /dev/null +++ b/samgr/adapter/posix/queue_adapter.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "queue_adapter.h" +#include +#include +#include "memory_adapter.h" +#include "lock_free_queue.h" + +typedef struct LockFreeBlockQueue LockFreeBlockQueue; +struct LockFreeBlockQueue { + pthread_mutex_t wMutex; + pthread_mutex_t rMutex; + pthread_cond_t cond; + LockFreeQueue *queue; +}; + +MQueueId QUEUE_Create(const char *name, int size, int count) +{ + LockFreeBlockQueue *queue = (LockFreeBlockQueue *)SAMGR_Malloc(sizeof(LockFreeBlockQueue)); + if (queue == NULL) { + return NULL; + } + queue->queue = LFQUE_Create(size, count); + if (queue->queue == NULL) { + SAMGR_Free(queue); + return NULL; + } + pthread_mutex_init(&queue->wMutex, NULL); + pthread_mutex_init(&queue->rMutex, NULL); + pthread_cond_init(&queue->cond, NULL); + return (MQueueId)queue; +} + +int QUEUE_Put(MQueueId queueId, const void *element, uint8 pri, int timeout) +{ + if (queueId == NULL || element == NULL || timeout > 0) { + return EC_INVALID; + } + LockFreeBlockQueue *queue = (LockFreeBlockQueue *)queueId; + pthread_mutex_lock(&queue->wMutex); + int ret = LFQUE_Push(queue->queue, element, pri); + pthread_mutex_unlock(&queue->wMutex); + pthread_mutex_lock(&queue->rMutex); + pthread_cond_signal(&queue->cond); + pthread_mutex_unlock(&queue->rMutex); + return ret; +} + +int QUEUE_Pop(MQueueId queueId, void *element, uint8 *pri, int timeout) +{ + if (queueId == NULL || element == NULL || timeout > 0) { + return EC_INVALID; + } + + LockFreeBlockQueue *queue = (LockFreeBlockQueue *)queueId; + if (LFQUE_Pop(queue->queue, element, pri) == EC_SUCCESS) { + return EC_SUCCESS; + } + + pthread_mutex_lock(&queue->rMutex); + while (LFQUE_Pop(queue->queue, element, pri) != EC_SUCCESS) { + pthread_cond_wait(&queue->cond, &queue->rMutex); + } + pthread_mutex_unlock(&queue->rMutex); + return EC_SUCCESS; +} + +int QUEUE_Destroy(MQueueId queueId) +{ + if (queueId == NULL) { + return EC_INVALID; + } + + LockFreeBlockQueue *queue = (LockFreeBlockQueue *)queueId; + pthread_mutex_destroy(&queue->wMutex); + pthread_mutex_destroy(&queue->rMutex); + pthread_cond_destroy(&queue->cond); + SAMGR_Free(queue->queue); + SAMGR_Free(queue); + return EC_SUCCESS; +} \ No newline at end of file diff --git a/samgr/adapter/posix/thread_adapter.c b/samgr/adapter/posix/thread_adapter.c new file mode 100755 index 0000000..d855abb --- /dev/null +++ b/samgr/adapter/posix/thread_adapter.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "thread_adapter.h" +#include +#include +#include "common.h" +#include "memory_adapter.h" +#define PRI_BUTT 39 +#define MIN_STACK_SIZE 0x8000 +static int g_threadCount = 0; +static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t g_localKey = 0; + +MutexId MUTEX_InitValue() +{ + pthread_mutex_t *mutex = SAMGR_Malloc(sizeof(pthread_mutex_t)); + if (mutex == NULL) { + return NULL; + } + (void)pthread_mutex_init(mutex, NULL); + return (MutexId)mutex; +} + +void MUTEX_Lock(MutexId mutex) +{ + if (mutex == NULL) { + return; + } + pthread_mutex_lock((pthread_mutex_t *)mutex); +} + +void MUTEX_Unlock(MutexId mutex) +{ + if (mutex == NULL) { + return; + } + pthread_mutex_unlock((pthread_mutex_t *)mutex); +} + +void MUTEX_GlobalLock(void) +{ + pthread_mutex_lock(&g_mutex); +} + +void MUTEX_GlobalUnlock(void) +{ + pthread_mutex_unlock(&g_mutex); +} + +ThreadId THREAD_Create(Runnable run, void *argv, const ThreadAttr *attr) +{ + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + pthread_attr_setstacksize(&threadAttr, (attr->stackSize | MIN_STACK_SIZE)); + pthread_attr_setinheritsched(&threadAttr, PTHREAD_EXPLICIT_SCHED); +#ifdef SAMGR_LINUX_ADAPTER + struct sched_param sched = {attr->priority}; +#else + struct sched_param sched = {PRI_BUTT - attr->priority}; +#endif + pthread_attr_setschedpolicy(&threadAttr, SCHED_RR); + pthread_attr_setschedparam(&threadAttr, &sched); + pthread_key_create(&g_localKey, NULL); + pthread_t threadId = 0; + int errno = pthread_create(&threadId, &threadAttr, run, argv); + if (errno != 0) { + return NULL; + } + + MUTEX_GlobalLock(); + g_threadCount++; + MUTEX_GlobalUnlock(); + return (ThreadId)threadId; +} + +int THREAD_Total(void) +{ + return g_threadCount; +} + +void *THREAD_GetThreadLocal(void) +{ + return pthread_getspecific(g_localKey); +} + +void THREAD_SetThreadLocal(const void *local) +{ + pthread_setspecific(g_localKey, local); +} diff --git a/samgr/adapter/posix/time_adapter.c b/samgr/adapter/posix/time_adapter.c new file mode 100755 index 0000000..32cd6ec --- /dev/null +++ b/samgr/adapter/posix/time_adapter.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "time_adapter.h" +#include +#include + +#define MS_PER_SECOND 1000 +#define NS_PER_MS 1000000 + +int32 WDT_Start(uint32 ms) +{ + return WDT_Reset(ms); +} + +int32 WDT_Reset(uint32 ms) +{ + (void)ms; + return EC_FAILURE; +} + +int32 WDT_Stop(void) +{ + return EC_FAILURE; +} + +uint64 SAMGR_GetProcessTime(void) +{ + struct timespec ts = {0, 0}; + clock_gettime(CLOCK_REALTIME, &ts); + return ((ts.tv_sec * MS_PER_SECOND) + (ts.tv_nsec / NS_PER_MS)); +} diff --git a/samgr/adapter/queue_adapter.h b/samgr/adapter/queue_adapter.h new file mode 100755 index 0000000..475a028 --- /dev/null +++ b/samgr/adapter/queue_adapter.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_QUEUE_ADAPTER_H +#define LITE_QUEUE_ADAPTER_H + +#include +#include "common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +MQueueId QUEUE_Create(const char *name, int size, int count); + +int QUEUE_Put(MQueueId queueId, const void *element, uint8 pri, int timeout); + +int QUEUE_Pop(MQueueId queueId, void *element, uint8 *pri, int timeout); + +int QUEUE_Destroy(MQueueId queueId); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_QUEUE_ADAPTER_H diff --git a/samgr/adapter/thread_adapter.h b/samgr/adapter/thread_adapter.h new file mode 100755 index 0000000..9c58ffd --- /dev/null +++ b/samgr/adapter/thread_adapter.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_THREAD_ADAPTER_H +#define LITE_THREAD_ADAPTER_H + +#include +#include "common.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/// \details Mutex ID identifies the mutex. +typedef void *(*Runnable)(void *argv); + +typedef struct ThreadAttr ThreadAttr; +struct ThreadAttr { + const char *name; // name of the thread + uint32 stackSize; // size of stack + uint8 priority; // initial thread priority + uint8 reserved1; // reserved1 (must be 0) + uint16 reserved2; // reserved2 (must be 0) +}; + +MutexId MUTEX_InitValue(void); + +void MUTEX_Lock(MutexId mutex); + +void MUTEX_Unlock(MutexId mutex); + +void MUTEX_GlobalLock(void); + +void MUTEX_GlobalUnlock(void); + +ThreadId THREAD_Create(Runnable run, void *argv, const ThreadAttr *attr); + +int THREAD_Total(void); + +void *THREAD_GetThreadLocal(void); + +void THREAD_SetThreadLocal(const void *local); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_THREAD_ADAPTER_H diff --git a/samgr/adapter/time_adapter.h b/samgr/adapter/time_adapter.h new file mode 100755 index 0000000..61f8f81 --- /dev/null +++ b/samgr/adapter/time_adapter.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_TIME_ADAPTER_H +#define LITE_TIME_ADAPTER_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int32 WDT_Start(uint32 ms); + +int32 WDT_Reset(uint32 ms); + +int32 WDT_Stop(void); + +uint64 SAMGR_GetProcessTime(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_TIME_ADAPTER_H diff --git a/samgr/registry/service_registry.c b/samgr/registry/service_registry.c new file mode 100755 index 0000000..f9df6ba --- /dev/null +++ b/samgr/registry/service_registry.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "service_registry.h" +#include +#include + +int __attribute__((weak)) SAMGR_RegisterServiceApi(const char *service, const char *feature, + const Identity *identity, IUnknown *iUnknown) +{ + (void)service; + (void)feature; + (void)iUnknown; + (void)identity; + return EC_FAILURE; +} + +IUnknown *__attribute__((weak)) SAMGR_FindServiceApi(const char *service, const char *feature) +{ + (void)service; + (void)feature; + return NULL; +} + +int __attribute__((weak)) SAMGR_RegisterFactory(const char *service, const char *feature, + Creator creator, Destroyer destroyer) +{ + (void)service; + (void)feature; + (void)creator; + (void)destroyer; + return EC_INVALID; +} diff --git a/samgr/registry/service_registry.h b/samgr/registry/service_registry.h new file mode 100755 index 0000000..d4a3be4 --- /dev/null +++ b/samgr/registry/service_registry.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_SERVICE_REGISTRY_H +#define LITE_SERVICE_REGISTRY_H + +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int SAMGR_RegisterServiceApi(const char *service, const char *feature, const Identity *identity, IUnknown *iUnknown); +IUnknown *SAMGR_FindServiceApi(const char *service, const char *feature); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_SERVICE_REGISTRY_H diff --git a/samgr/source/BUILD.gn b/samgr/source/BUILD.gn new file mode 100755 index 0000000..a228b94 --- /dev/null +++ b/samgr/source/BUILD.gn @@ -0,0 +1,77 @@ +# Copyright (c) 2020 Huawei Device 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. + +config("samgr_source_public") { + include_dirs = [ + "../adapter", + "../registry", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/registry", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//utils/native/lite/include", + ] +} + +if (ohos_kernel_type == "liteos_riscv" || ohos_kernel_type == "liteos_m") { + static_library("samgr_source") { + sources = [ + "common.c", + "iunknown.c", + "feature.c", + "service.c", + "message.c", + "task_manager.c", + ] + + public_configs = [":samgr_source_public"] + cflags = [ "-Wall" ] + + public_deps = [ + "//foundation/distributedschedule/services/samgr_lite/samgr/adapter:samgr_adapter" + ] + + include_dirs = [ + "//base/hiviewdfx/interfaces/kits/hilog_lite", + "//kernel/liteos_m/components/cmsis", + ] + } +} + +if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + source_set("samgr_source") { + sources = [ + "common.c", + "iunknown.c", + "feature.c", + "service.c", + "message.c", + "task_manager.c", + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + + public_configs = [":samgr_source_public"] + + public_deps = [ + "//foundation/distributedschedule/services/samgr_lite/samgr/adapter:samgr_adapter", + "//base/hiviewdfx/frameworks/hilog_lite/featured:hilog_shared", + ] + + include_dirs = [ + "//kernel/liteos_a/kernel/include/", + "//third_party/bounds_checking_function/include", + ] + } +} diff --git a/samgr/source/common.c b/samgr/source/common.c new file mode 100755 index 0000000..cc23a7c --- /dev/null +++ b/samgr/source/common.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "common.h" +#include +#include "memory_adapter.h" + +#define GROW_STEP 4 +Vector VECTOR_Make(VECTOR_Key key, VECTOR_Compare compare) +{ + Vector vector = {0, 0, 0, NULL, key, compare}; + return vector; +} + +void VECTOR_Clear(Vector *vector) +{ + if (vector == NULL) { + return; + } + if (vector->data == NULL) { + return; + } + SAMGR_Free(vector->data); + vector->max = 0; + vector->top = 0; + vector->free = 0; + vector->data = NULL; +} + +int16 VECTOR_Add(Vector *vector, void *element) +{ + if (vector == NULL || element == NULL) { + return INVALID_INDEX; + } + + if (vector->top >= vector->max) { + int16 i; + // use released data elements preferentially + for (i = vector->top - (int16)1; i >= 0; --i) { + if (vector->data[i] == NULL) { + vector->data[i] = element; + vector->free--; + return i; + } + } + + if (vector->max + GROW_STEP < 0) { + return INVALID_INDEX; + } + + void **data = (void **)SAMGR_Malloc(sizeof(void *) * (vector->max + GROW_STEP)); + if (data == NULL) { + return INVALID_INDEX; + } + + if (vector->data != NULL) { + // data's length is bigger than vector->data's length and only copy vector->data's length's memory; + // no need to check return value + (void)memcpy_s(data, sizeof(void *) * (vector->max + GROW_STEP), + vector->data, sizeof(void *) * vector->max); + SAMGR_Free(vector->data); + } + vector->data = data; + vector->max += GROW_STEP; + } + + vector->data[vector->top] = element; + return vector->top++; +} + +void *VECTOR_At(Vector *vector, int16 index) +{ + if (vector == NULL || vector->top <= index || index < 0) { + return NULL; + } + + return vector->data[index]; +} + +void *VECTOR_Swap(Vector *vector, int16 index, void *element) +{ + if (vector == NULL || vector->top <= index || index < 0) { + return NULL; + } + if (element == NULL) { + vector->free++; + } + void *oldElement = vector->data[index]; + vector->data[index] = element; + return oldElement; +} + +int16 VECTOR_Find(Vector *vector, const void *element) +{ + if (vector == NULL || element == NULL) { + return INVALID_INDEX; + } + return VECTOR_FindByKey(vector, (vector->key == NULL) ? element : vector->key(element)); +} + +int16 VECTOR_FindByKey(Vector *vector, const void *key) +{ + if (vector == NULL || key == NULL) { + return INVALID_INDEX; + } + + int16 i; + for (i = 0; i < vector->top; ++i) { + if (vector->data[i] == NULL) { + continue; + } + + void *first = (vector->key != NULL) ? vector->key(vector->data[i]) : vector->data[i]; + if (first == key) { + return i; + } + + if (vector->compare == NULL || first == NULL) { + continue; + } + + if (vector->compare(first, key) == 0) { + return i; + } + } + return INVALID_INDEX; +} + +int16 VECTOR_Size(Vector *vector) +{ + if (vector == NULL) { + return INVALID_INDEX; + } + return vector->top; +} + +int16 VECTOR_Num(Vector *vector) +{ + if (vector == NULL) { + return INVALID_INDEX; + } + return vector->top - vector->free; +} diff --git a/samgr/source/feature.c b/samgr/source/feature.c new file mode 100755 index 0000000..763e4d1 --- /dev/null +++ b/samgr/source/feature.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "feature.h" +#include "feature_impl.h" +#include "memory_adapter.h" + +BOOL SAMGR_AddInterface(FeatureImpl *featureImpl, IUnknown *iUnknown) +{ + if (featureImpl == NULL || iUnknown == NULL || featureImpl->iUnknown != NULL) { + return FALSE; + } + + featureImpl->iUnknown = iUnknown; + return TRUE; +} + +IUnknown *SAMGR_DelInterface(FeatureImpl *featureImpl) +{ + if (featureImpl == NULL) { + return NULL; + } + IUnknown *iUnknown = featureImpl->iUnknown; + featureImpl->iUnknown = NULL; + return iUnknown; +} + +IUnknown *SAMGR_GetInterface(FeatureImpl *featureImpl) +{ + if (featureImpl == NULL) { + return NULL; + } + return featureImpl->iUnknown; +} + +BOOL SAMGR_IsNoInterface(FeatureImpl *featureImpl) +{ + return (BOOL)(featureImpl == NULL || featureImpl->iUnknown == NULL); +} + +FeatureImpl *FEATURE_CreateInstance(Feature *feature) +{ + if (feature == NULL) { + return NULL; + } + FeatureImpl *featureImpl = (FeatureImpl *)SAMGR_Malloc(sizeof(FeatureImpl)); + if (featureImpl == NULL) { + return NULL; + } + featureImpl->feature = feature; + featureImpl->iUnknown = NULL; + return featureImpl; +} \ No newline at end of file diff --git a/samgr/source/feature_impl.h b/samgr/source/feature_impl.h new file mode 100755 index 0000000..5f9a933 --- /dev/null +++ b/samgr/source/feature_impl.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_FEATUREIMPL_H +#define LITE_FEATUREIMPL_H + +#include "common.h" +#include "iunknown.h" +#include "feature.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +typedef struct FeatureImpl FeatureImpl; + +struct FeatureImpl { + Feature *feature; + IUnknown *iUnknown; +}; + +inline static BOOL IsInvalidFeature(Feature *feature) +{ + return (feature == NULL || feature->GetName == NULL || feature->OnInitialize == NULL || + feature->OnMessage == NULL || feature->OnStop == NULL); +} + +inline static BOOL IsInvalidIUnknown(IUnknown *iUnknown) +{ + return (iUnknown == NULL || iUnknown->QueryInterface == NULL || iUnknown->AddRef == NULL || + iUnknown->Release == NULL); +} +BOOL SAMGR_AddInterface(FeatureImpl *featureImpl, IUnknown *iUnknown); +IUnknown *SAMGR_DelInterface(FeatureImpl *featureImpl); +IUnknown *SAMGR_GetInterface(FeatureImpl *featureImpl); +BOOL SAMGR_IsNoInterface(FeatureImpl *featureImpl); +FeatureImpl *FEATURE_CreateInstance(Feature *feature); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // LITE_FEATUREIMPL_H diff --git a/samgr/source/iunknown.c b/samgr/source/iunknown.c new file mode 100755 index 0000000..5f77e58 --- /dev/null +++ b/samgr/source/iunknown.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "iunknown.h" +#include "common.h" + +#define OLD_VERSION 0 + +int IUNKNOWN_AddRef(IUnknown *iUnknown) +{ + if (iUnknown == NULL) { + return EC_INVALID; + } + + IUnknownEntry *entry = GET_OBJECT(iUnknown, IUnknownEntry, iUnknown); + entry->ref++; + return entry->ref; +} + +int IUNKNOWN_QueryInterface(IUnknown *iUnknown, int ver, void **target) +{ + if (iUnknown == NULL || target == NULL) { + return EC_INVALID; + } + + IUnknownEntry *entry = GET_OBJECT(iUnknown, IUnknownEntry, iUnknown); + if ((entry->ver & (uint16)ver) != ver) { + return EC_INVALID; + } + + if (ver == OLD_VERSION && + entry->ver != OLD_VERSION && + (entry->ver & (uint16)DEFAULT_VERSION) != DEFAULT_VERSION) { + return EC_INVALID; + } + + *target = iUnknown; + iUnknown->AddRef(iUnknown); + return EC_SUCCESS; +} + +int IUNKNOWN_Release(IUnknown *iUnknown) +{ + if (iUnknown == NULL) { + return EC_INVALID; + } + + IUnknownEntry *entry = GET_OBJECT(iUnknown, IUnknownEntry, iUnknown); + int ref = entry->ref - 1; + if (ref < 0) { + // The iUnknown is already freed, there is some exception; + } else { + if (ref == 0) { + // Nobody reference to the iUnknown, should delete it. + // But iUnknown may be global variable, so the default version don`t delete it. + } else { + entry->ref = ref; + } + } + return ref; +} \ No newline at end of file diff --git a/samgr/source/message.c b/samgr/source/message.c new file mode 100755 index 0000000..5fd8500 --- /dev/null +++ b/samgr/source/message.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "message_inner.h" +#include +#include +#include "memory_adapter.h" +#include "queue_adapter.h" +#include "securec.h" +#include "task_manager.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +#define DONT_WAIT 0 +#define WAIT_FOREVER (-1) +static int32 SharedSend(MQueueId queueId, Exchange *exchange); +static BOOL FreeReference(Exchange *exchange); + +int32 SAMGR_SendRequest(const Identity *identity, const Request *request, Handler handler) +{ + if (request == NULL || identity == NULL) { + return EC_INVALID; + } + + Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, NULL}; + exchange.id.queueId = NULL; + if (handler != NULL) { + exchange.id.queueId = SAMGR_GetCurrentQueueID(); + exchange.type = MSG_CON; + } + + return QUEUE_Put(identity->queueId, &exchange, 0, DONT_WAIT); +} + +int32 SAMGR_SendResponse(const Request *request, const Response *response) +{ + // we need send the default the con message or not? + if (request == NULL) { + return EC_INVALID; + } + + Exchange *exchange = GET_OBJECT(request, Exchange, request); + if (exchange->type == MSG_NON) { + return EC_INVALID; + } + + if (exchange->handler == NULL) { + return EC_SUCCESS; + } + + exchange->type = MSG_ACK; + exchange->response.data = NULL; + exchange->response.len = 0; + if (response != NULL) { + exchange->response = *response; + } + + // If there is no task queue, we will call the response processor in current task. + if (exchange->id.queueId == NULL) { + exchange->handler(&exchange->request, &exchange->response); + return EC_SUCCESS; + } + + // Send back to the origin to process the task. + int32 ret = SharedSend(exchange->id.queueId, exchange); + if (ret != EC_SUCCESS) { + exchange->handler(&exchange->request, &exchange->response); + (void)FreeReference(exchange); + } + return EC_SUCCESS; +} + +int32 SAMGR_MsgRecv(MQueueId queueId, uint8 *interMsg, uint32 size) +{ + if (queueId == NULL || interMsg == NULL || size == 0) { + return EC_INVALID; + } + + if (memset_s(interMsg, size, 0x00, size) != EOK) { + return EC_FAILURE; + } + + return QUEUE_Pop(queueId, interMsg, 0, WAIT_FOREVER); +} + +int32 SAMGR_FreeMsg(Exchange *exchange) +{ + if (!FreeReference(exchange)) { + return EC_SUCCESS; + } + + if (exchange->request.len > 0) { + SAMGR_Free(exchange->request.data); + exchange->request.data = NULL; + } + + if (exchange->response.len > 0) { + SAMGR_Free(exchange->response.data); + exchange->response.data = NULL; + } + return EC_SUCCESS; +} + +uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler) +{ + if (identity == NULL || request == NULL) { + return NULL; + } + Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, token}; + exchange.type = (handler == NULL) ? MSG_NON : MSG_CON; + exchange.id.queueId = NULL; + int32 err = SharedSend(identity->queueId, &exchange); + if (err != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend [%p] failed(%d)!", identity->queueId, err); + (void)FreeReference(&exchange); + } + return exchange.sharedRef; +} + +int32 SAMGR_SendSharedDirectRequest(const Identity *id, const Request *req, const Response *resp, uint32 **ref, + Handler handler) +{ + if (handler == NULL || ref == NULL) { + return EC_INVALID; + } + + Exchange exchange = {0}; + if (req != NULL) { + exchange.request = *req; + } + + if (resp != NULL) { + exchange.response = *resp; + } + + exchange.handler = handler; + exchange.sharedRef = *ref; + exchange.type = MSG_DIRECT; + exchange.id = *id; + exchange.id.queueId = NULL; + int32 err = SharedSend(id->queueId, &exchange); + if (err != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend [%p] failed(%d)!", id->queueId, err); + (void)FreeReference(&exchange); + } + *ref = exchange.sharedRef; + return err; +} + +int32 SAMGR_SendResponseByIdentity(const Identity *id, const Request *request, const Response *response) +{ + // we need send the default the con message or not? + if (request == NULL || id == NULL) { + return EC_INVALID; + } + + Exchange *exchange = GET_OBJECT(request, Exchange, request); + if (exchange->type == MSG_NON) { + return EC_INVALID; + } + exchange->id.queueId = id->queueId; + + return SAMGR_SendResponse(request, response); +} + +static int32 SharedSend(MQueueId queueId, Exchange *exchange) +{ + /* if the msg data and response is NULL, we just direct copy, no need shared the message. */ + if ((exchange->request.data == NULL || exchange->request.len <= 0) && + (exchange->response.data == NULL || exchange->response.len <= 0)) { + return QUEUE_Put(queueId, exchange, 0, DONT_WAIT); + } + + /* 1.add reference */ + MUTEX_GlobalLock(); + if (exchange->sharedRef == NULL) { + exchange->sharedRef = (uint32 *)SAMGR_Malloc(sizeof(uint32)); + if (exchange->sharedRef == NULL) { + MUTEX_GlobalUnlock(); + return EC_NOMEMORY; + } + *(exchange->sharedRef) = 0; + } + (*(exchange->sharedRef))++; + MUTEX_GlobalUnlock(); + + return QUEUE_Put(queueId, exchange, 0, DONT_WAIT); +} + +static BOOL FreeReference(Exchange *exchange) +{ + if (exchange == NULL) { + return FALSE; + } + + BOOL needFree = TRUE; + /* 1. check the shared reference */ + MUTEX_GlobalLock(); + if (exchange->sharedRef != NULL) { + if (*(exchange->sharedRef) > 0) { + (*(exchange->sharedRef))--; + } + + if (*(exchange->sharedRef) > 0) { + needFree = FALSE; + } + } + MUTEX_GlobalUnlock(); + + if (needFree) { + SAMGR_Free(exchange->sharedRef); + exchange->sharedRef = NULL; + } + return needFree; +} \ No newline at end of file diff --git a/samgr/source/message_inner.h b/samgr/source/message_inner.h new file mode 100755 index 0000000..2bdda45 --- /dev/null +++ b/samgr/source/message_inner.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_MESSAGEINNER_H +#define LITE_MESSAGEINNER_H + +#include "message.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +enum ExchangeType { + MSG_EXIT = -1, + MSG_NON = 0, + MSG_CON = 1, + MSG_ACK = 2, + MSG_SYNC = 3, + MSG_DIRECT = 4, +}; +// Will be used for message interaction, so use one-byte alignment +#pragma pack(1) +typedef struct Exchange Exchange; +struct Exchange { + Identity id; /**< The target service or feature identity. */ + Request request; + Response response; + short type; /**< The exchange type. */ + Handler handler; /**< async response or immediately request callback function */ + uint32 *sharedRef; /**< use to share the request and response for saving memory */ +}; +#pragma pack() + +int32 SAMGR_MsgRecv(MQueueId queueId, uint8 *interMsg, uint32 size); + +/** + * The function just release the Message->data and Message->sharedRef(use free), not release the msg entry. + * If you alloc the msg on the heep, you should release it by yourself, you`d better alloc on the stack. + * The function will be called automatically. + * Do not call this function manually, except the SM_SendRequest return error! + * + **/ +int32 SAMGR_FreeMsg(Exchange *exchange); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_MESSAGEINNER_H diff --git a/samgr/source/samgr_lite.c b/samgr/source/samgr_lite.c new file mode 100755 index 0000000..aac7561 --- /dev/null +++ b/samgr/source/samgr_lite.c @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "samgr_lite_inner.h" +#include +#include +#include +#include +#include "memory_adapter.h" +#include "time_adapter.h" +#include "thread_adapter.h" +#include "service_impl.h" +#include "feature_impl.h" +#include "service_registry.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +/* ************************************************************************************************** + * Samgr Lite public interfaces + * ************************************************************************************************* */ +static BOOL RegisterService(Service *service); +static Service *UnregisterService(const char *name); +static BOOL RegisterFeature(const char *serviceName, Feature *feature); +static Feature *UnregisterFeature(const char *serviceName, const char *featureName); +static BOOL RegisterFeatureApi(const char *serviceName, const char *feature, IUnknown *publicApi); +static IUnknown *UnregisterFeatureApi(const char *serviceName, const char *feature); +static BOOL RegisterDefaultFeatureApi(const char *serviceName, IUnknown *publicApi); +static IUnknown *UnregisterDefaultFeatureApi(const char *serviceName); +static IUnknown *GetDefaultFeatureApi(const char *serviceName); +static IUnknown *GetFeatureApi(const char *serviceName, const char *feature); + +/* ************************************************************************************************** + * Samgr Lite location functions + * ************************************************************************************************* */ +static void InitializeAllServices(Vector *services); +static void InitializeSingleService(ServiceImpl *service); +static int32 SendBootRequest(int msgId, uint32 msgValue); +static const char *GetServiceName(const ServiceImpl *serviceImpl); +static short GetUninitializedPos(void); +static void AddTaskPool(ServiceImpl *service, TaskConfig *cfg, const char *name); +static int32 InitCompleted(void); +static void HandleInitRequest(const Request *request, const Response *response); +static SamgrLiteImpl *GetImplement(void); +static ServiceImpl *GetService(const char *name); +static TaskPool *GetSpecifiedTaskPool(TaskConfig *config); +static void Init(void); +/* ************************************************************************************************** + * Samgr Lite location structure and local variable + * ************************************************************************************************* */ +static SamgrLiteImpl g_samgrImpl; + +#define TO_NEXT_STATUS(status) (BootStatus)((uint8)(status) | 0x1) + +SamgrLite *SAMGR_GetInstance(void) +{ + if (g_samgrImpl.mutex == NULL) { + Init(); + } + return &(GetImplement()->vtbl); +} + +static SamgrLiteImpl *GetImplement(void) +{ + return &g_samgrImpl; +} + +static void Init(void) +{ + WDT_Start(WDG_SAMGR_INIT_TIME); + g_samgrImpl.vtbl.RegisterService = RegisterService; + g_samgrImpl.vtbl.UnregisterService = UnregisterService; + g_samgrImpl.vtbl.RegisterFeature = RegisterFeature; + g_samgrImpl.vtbl.UnregisterFeature = UnregisterFeature; + g_samgrImpl.vtbl.RegisterFeatureApi = RegisterFeatureApi; + g_samgrImpl.vtbl.UnregisterFeatureApi = UnregisterFeatureApi; + g_samgrImpl.vtbl.RegisterDefaultFeatureApi = RegisterDefaultFeatureApi; + g_samgrImpl.vtbl.UnregisterDefaultFeatureApi = UnregisterDefaultFeatureApi; + g_samgrImpl.vtbl.GetDefaultFeatureApi = GetDefaultFeatureApi; + g_samgrImpl.vtbl.GetFeatureApi = GetFeatureApi; + g_samgrImpl.status = BOOT_SYS; + g_samgrImpl.services = VECTOR_Make((VECTOR_Key)GetServiceName, (VECTOR_Compare)strcmp); + g_samgrImpl.mutex = MUTEX_InitValue(); + (void)memset_s(g_samgrImpl.sharedPool, sizeof(TaskPool *) * MAX_POOL_NUM, 0, + sizeof(TaskPool *) * MAX_POOL_NUM); + WDT_Reset(WDG_SVC_REG_TIME); +} + +void SAMGR_Bootstrap(void) +{ + SamgrLiteImpl *samgr = GetImplement(); + if (samgr->mutex == NULL) { + HILOG_INFO(HILOG_MODULE_SAMGR, "Samgr is not init, no service!"); + return; + } + WDT_Reset(WDG_SVC_BOOT_TIME); + Vector initServices = VECTOR_Make(NULL, NULL); + MUTEX_Lock(samgr->mutex); + samgr->status = TO_NEXT_STATUS(samgr->status); + int16 size = VECTOR_Size(&(samgr->services)); + int16 i; + for (i = 0; i < size; ++i) { + ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(&(samgr->services), i); + if (serviceImpl == NULL || serviceImpl->inited != SVC_INIT) { + continue; + } + VECTOR_Add(&initServices, serviceImpl); + } + MUTEX_Unlock(samgr->mutex); + HILOG_INFO(HILOG_MODULE_SAMGR, BOOT_FMT(samgr->status), VECTOR_Size(&initServices)); + InitializeAllServices(&initServices); + VECTOR_Clear(&initServices); + int32 err = InitCompleted(); + if (err != EC_SUCCESS) { + HILOG_INFO(HILOG_MODULE_SAMGR, "Goto next boot step failed! errno:%d", err); + } +} + +ServiceImpl *SAMGR_GetServiceByID(int16 serviceId) +{ + SamgrLiteImpl *manager = GetImplement(); + MUTEX_Lock(manager->mutex); + int16 size = VECTOR_Size(&(manager->services)); + if (serviceId < 0 || serviceId > size) { + MUTEX_Unlock(manager->mutex); + return NULL; + } + ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(&(manager->services), serviceId); + MUTEX_Unlock(manager->mutex); + return serviceImpl; +} + +static int32 InitCompleted(void) +{ + // Did all services be inited? + SamgrLiteImpl *manager = GetImplement(); + int16 pos = GetUninitializedPos(); + int16 size = VECTOR_Size(&(manager->services)); + if (pos < size) { + return EC_SUCCESS; + } + + MUTEX_Lock(manager->mutex); + if (manager->status == BOOT_SYS_WAIT) { + manager->status = BOOT_APP; + MUTEX_Unlock(manager->mutex); + HILOG_INFO(HILOG_MODULE_SAMGR, "Initialized all core system services!"); + WDT_Reset(WDG_SVC_REG_TIME); + return SendBootRequest(BOOT_SYS_COMPLETED, pos); + } + + if (manager->status == BOOT_APP_WAIT) { + manager->status = BOOT_DYNAMIC; + MUTEX_Unlock(manager->mutex); + HILOG_INFO(HILOG_MODULE_SAMGR, "Initialized all system and application services!"); + WDT_Reset(WDG_SVC_TEST_TIME); + return SendBootRequest(BOOT_APP_COMPLETED, pos); + } + MUTEX_Unlock(manager->mutex); + WDT_Stop(); + return EC_SUCCESS; +} + +static void InitializeAllServices(Vector *services) +{ + int16 size = VECTOR_Size(services); + int16 i; + for (i = 0; i < size; ++i) { + ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(services, i); + if (serviceImpl == NULL) { + continue; + } + + TaskConfig config = serviceImpl->service->GetTaskConfig(serviceImpl->service); + const char *name = serviceImpl->service->GetName(serviceImpl->service); + AddTaskPool(serviceImpl, &config, name); + + HILOG_INFO(HILOG_MODULE_SAMGR, "Init service:%s TaskPool:%p", name, serviceImpl->taskPool); + InitializeSingleService(serviceImpl); + } + SamgrLiteImpl *samgr = GetImplement(); + MUTEX_Lock(samgr->mutex); + for (i = 0; i < size; ++i) { + ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(services, i); + if (serviceImpl == NULL) { + continue; + } + const char *name = serviceImpl->service->GetName(serviceImpl->service); + SAMGR_StartTaskPool(serviceImpl->taskPool, name); + } + MUTEX_Unlock(samgr->mutex); +} + +static BOOL RegisterService(Service *service) +{ + if (IsInvalidService(service)) { + return FALSE; + } + + SamgrLiteImpl *samgr = GetImplement(); + MUTEX_Lock(samgr->mutex); + int16 pos = VECTOR_FindByKey(&(samgr->services), (void *)service->GetName(service)); + if (pos >= 0) { + MUTEX_Unlock(samgr->mutex); + return FALSE; + } + + if (VECTOR_Num(&(samgr->services)) >= MAX_SERVICE_NUM) { + MUTEX_Unlock(samgr->mutex); + return FALSE; + } + + ServiceImpl *serviceImpl = SAMGR_CreateServiceImpl(service, samgr->status); + if (serviceImpl == NULL) { + MUTEX_Unlock(samgr->mutex); + return FALSE; + } + serviceImpl->serviceId = VECTOR_Add(&(samgr->services), serviceImpl); + MUTEX_Unlock(samgr->mutex); + if (serviceImpl->serviceId == INVALID_INDEX) { + SAMGR_Free(serviceImpl); + return FALSE; + } + return TRUE; +} + +static Service *UnregisterService(const char *name) +{ + if (name == NULL) { + return NULL; + } + + SamgrLiteImpl *samgr = GetImplement(); + MUTEX_Lock(samgr->mutex); + Vector *services = &(samgr->services); + int16 pos = VECTOR_FindByKey(services, (void *)name); + ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(services, pos); + if (serviceImpl == NULL || serviceImpl->defaultApi != NULL || VECTOR_Num(&serviceImpl->features) > 0) { + MUTEX_Unlock(samgr->mutex); + return NULL; + } + + VECTOR_Swap(services, pos, NULL); + // release task pool must be in the lock to keep atomicity of the reference + SAMGR_ReleaseTaskPool(serviceImpl->taskPool); + MUTEX_Unlock(samgr->mutex); + + Service *service = serviceImpl->service; + VECTOR_Clear(&serviceImpl->features); + SAMGR_Free(serviceImpl); + return service; +} + +static BOOL RegisterFeature(const char *serviceName, Feature *feature) +{ + if (IsInvalidFeature(feature)) { + return FALSE; + } + + ServiceImpl *serviceImpl = GetService(serviceName); + if (serviceImpl == NULL || serviceImpl->inited != SVC_INIT) { + return FALSE; + } + + if (DEFAULT_GetFeature(serviceImpl, feature->GetName(feature)) != NULL) { + return FALSE; + } + + int16 featureId = DEFAULT_AddFeature(serviceImpl, feature); + if (featureId < 0) { + return FALSE; + } + return TRUE; +} + +static Feature *UnregisterFeature(const char *serviceName, const char *featureName) +{ + ServiceImpl *serviceImpl = GetService(serviceName); + if (serviceImpl == NULL) { + return NULL; + } + return DEFAULT_DeleteFeature(serviceImpl, featureName); +} + +static BOOL RegisterFeatureApi(const char *serviceName, const char *feature, IUnknown *publicApi) +{ + if (IsInvalidIUnknown(publicApi)) { + return FALSE; + } + + ServiceImpl *serviceImpl = GetService(serviceName); + if (serviceImpl == NULL) { + return FALSE; + } + + if (feature == NULL) { + if (serviceImpl->defaultApi != NULL) { + return FALSE; + } + serviceImpl->defaultApi = publicApi; + return TRUE; + } + + FeatureImpl *featureImpl = DEFAULT_GetFeature(serviceImpl, feature); + if (featureImpl == NULL) { + return FALSE; + } + return SAMGR_AddInterface(featureImpl, publicApi); +} + +static IUnknown *UnregisterFeatureApi(const char *serviceName, const char *feature) +{ + ServiceImpl *serviceImpl = GetService(serviceName); + if (serviceImpl == NULL) { + return NULL; + } + + if (feature == NULL) { + IUnknown *iUnknown = serviceImpl->defaultApi; + serviceImpl->defaultApi = NULL; + return iUnknown; + } + + return SAMGR_DelInterface(DEFAULT_GetFeature(serviceImpl, feature)); +} + +static BOOL RegisterDefaultFeatureApi(const char *serviceName, IUnknown *publicApi) +{ + return RegisterFeatureApi(serviceName, NULL, publicApi); +} + +static IUnknown *UnregisterDefaultFeatureApi(const char *serviceName) +{ + return UnregisterFeatureApi(serviceName, NULL); +} + +static IUnknown *GetDefaultFeatureApi(const char *serviceName) +{ + return GetFeatureApi(serviceName, NULL); +} + +static IUnknown *GetFeatureApi(const char *serviceName, const char *feature) +{ + ServiceImpl *serviceImpl = GetService(serviceName); + if (serviceImpl == NULL) { + return SAMGR_FindServiceApi(serviceName, feature); + } + + FeatureImpl *featureImpl = DEFAULT_GetFeature(serviceImpl, feature); + if (featureImpl == NULL && feature == NULL) { + return serviceImpl->defaultApi; + } + + return SAMGR_GetInterface(featureImpl); +} + +static short GetUninitializedPos() +{ + SamgrLiteImpl *manager = GetImplement(); + MUTEX_Lock(manager->mutex); + int16 size = VECTOR_Size(&(manager->services)); + int16 i; + for (i = 0; i < size; ++i) { + ServiceImpl *service = (ServiceImpl *)VECTOR_At(&(manager->services), i); + if (service == NULL) { + continue; + } + + if (service->inited == SVC_INIT) { + MUTEX_Unlock(manager->mutex); + return i; + } + } + MUTEX_Unlock(manager->mutex); + return size; +} + +static const char *GetServiceName(const ServiceImpl *serviceImpl) +{ + if (serviceImpl == NULL) { + return NULL; + } + return serviceImpl->service->GetName(serviceImpl->service); +} + +static void AddTaskPool(ServiceImpl *service, TaskConfig *cfg, const char *name) +{ + if (service->taskPool != NULL) { + return; + } + + if (cfg->priority < PRI_LOW || cfg->priority >= PRI_BUTT) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "The %s service pri(%d) is out of range!", name, cfg->priority); + cfg->priority = PRI_LOW; + } + + switch (cfg->taskFlags) { + case SHARED_TASK: { + int pos = (int)cfg->priority / PROPERTY_STEP; + SamgrLiteImpl *samgr = GetImplement(); + if (samgr->sharedPool[pos] == NULL) { + TaskConfig shareCfg = DEFAULT_TASK_CFG(pos); + samgr->sharedPool[pos] = SAMGR_CreateFixedTaskPool(&shareCfg, name, DEFAULT_SIZE); + } + service->taskPool = samgr->sharedPool[pos]; + if (SAMGR_ReferenceTaskPool(service->taskPool) == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "shared task:%p pri:%d ref is full", service->taskPool, cfg->priority); + samgr->sharedPool[pos] = NULL; + } + } + break; + + case SPECIFIED_TASK: + service->taskPool = GetSpecifiedTaskPool(cfg); + if (service->taskPool != NULL) { + break; + } + // fallthrough + case SINGLE_TASK: + service->taskPool = SAMGR_CreateFixedTaskPool(cfg, name, SINGLE_SIZE); + break; + default: + break; + } + + if (service->taskPool == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Service create taskPool failed!", name, cfg->taskFlags); + } +} + +static ServiceImpl *GetService(const char *name) +{ + if (name == NULL) { + return NULL; + } + + SamgrLiteImpl *manager = GetImplement(); + MUTEX_Lock(manager->mutex); + Vector *services = &(manager->services); + short pos = VECTOR_FindByKey(services, (void *)name); + if (pos < 0) { + MUTEX_Unlock(manager->mutex); + return NULL; + } + ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(services, pos); + MUTEX_Unlock(manager->mutex); + return serviceImpl; +} + +static int32 SendBootRequest(int msgId, uint32 msgValue) +{ + Identity id = DEFAULT_GetFeatureId(GetService(BOOTSTRAP_SERVICE), NULL); + Request request = {msgId, 0, NULL, msgValue}; + return SAMGR_SendRequest(&id, &request, (Handler)SAMGR_Bootstrap); +} + +static void HandleInitRequest(const Request *request, const Response *response) +{ + ServiceImpl *serviceImpl = (ServiceImpl *)request->data; + if (serviceImpl == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Init service Request:<%d,%d>, Response:<%p,%d>!", + request->msgId, request->msgValue, response->data, response->len); + return; + } + uint32 lastTime = serviceImpl->ops.timestamp; + + DEFAULT_Initialize(serviceImpl); + serviceImpl->ops.timestamp = SAMGR_GetProcessTime(); + serviceImpl->inited = SVC_IDLE; + HILOG_INFO(HILOG_MODULE_SAMGR, "Init service %s success!", + serviceImpl->service->GetName(serviceImpl->service), serviceImpl->ops.timestamp - lastTime); + int32 err = InitCompleted(); + if (err != EC_SUCCESS) { + HILOG_INFO(HILOG_MODULE_SAMGR, "Goto next boot step failed! errno:%d", err); + } +} + +static void InitializeSingleService(ServiceImpl *service) +{ + // service is guaranteed not to be NULL by the caller; and it's a static function, won't have external call. + if (service->taskPool == NULL) { + DEFAULT_Initialize(service); + return; + } + + Identity identity = {service->serviceId, INVALID_INDEX, service->taskPool->queueId}; + Request request = {0, 0, service, 0}; + uint32 *ref = NULL; + (void)SAMGR_SendSharedDirectRequest(&identity, &request, NULL, &ref, HandleInitRequest); +} + +static TaskPool *GetSpecifiedTaskPool(TaskConfig *config) +{ + SamgrLiteImpl *samgr = GetImplement(); + Vector *services = &(samgr->services); + MUTEX_Lock(samgr->mutex); + int16 serviceNum = VECTOR_Size(services); + int i; + for (i = 0; i < serviceNum; ++i) { + ServiceImpl *impl = VECTOR_At(services, i); + if (impl == NULL) { + continue; + } + + TaskConfig cfg = impl->service->GetTaskConfig(impl->service); + if (memcmp(&cfg, config, sizeof(TaskConfig)) != 0) { + continue; + } + + if (impl->taskPool == NULL) { + break; + } + + TaskPool *taskPool = SAMGR_ReferenceTaskPool(impl->taskPool); + if (taskPool != NULL) { + MUTEX_Unlock(samgr->mutex); + return taskPool; + } + } + MUTEX_Unlock(samgr->mutex); + return NULL; +} \ No newline at end of file diff --git a/samgr/source/samgr_lite_inner.h b/samgr/source/samgr_lite_inner.h new file mode 100755 index 0000000..d4e92c8 --- /dev/null +++ b/samgr/source/samgr_lite_inner.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_SAMGR_LITE_INNER_H +#define LITE_SAMGR_LITE_INNER_H + +#include "samgr_lite.h" +#include "task_manager.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#ifndef MAX_SERVICE_NUM +#define MAX_SERVICE_NUM 0x7FF0 +#endif + +#define DEFAULT_SIZE 1 +#define SINGLE_SIZE 1 +#define MAX_POOL_NUM 8 +#define PROPERTY_STEP 8 +#define DEFAULT_TASK_CFG(pos) {LEVEL_HIGH, (int16) ((pos) * PROPERTY_STEP + 1), 0x800, 25, SHARED_TASK} +#define WDG_SAMGR_INIT_TIME 1000 +#define WDG_SVC_REG_TIME 5000 +#define WDG_SVC_BOOT_TIME 5000 +#define WDG_SVC_TEST_TIME 100000 + +#define BOOT_FMT(status) ((status) == BOOT_SYS_WAIT ? "Bootstrap core services(count:%d)." : \ +((status) == BOOT_APP_WAIT ? "Bootstrap system and application services(count:%d)." : \ +((status) == BOOT_DYNAMIC_WAIT ? "Bootstrap dynamic registered services(count:%d)." : \ +"Bootstrap other services(count:%d)."))) + +typedef enum { + BOOT_SYS = 0, + BOOT_SYS_WAIT = 1, + BOOT_APP = 2, + BOOT_APP_WAIT = 3, + BOOT_DYNAMIC = 4, + BOOT_DYNAMIC_WAIT = 5, +} BootStatus; + +typedef struct SamgrLiteImpl SamgrLiteImpl; +struct SamgrLiteImpl { + SamgrLite vtbl; + MutexId mutex; + BootStatus status; + Vector services; + TaskPool *sharedPool[MAX_POOL_NUM]; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_SAMGR_LITE_INNER_H diff --git a/samgr/source/samgr_maintenance.c b/samgr/source/samgr_maintenance.c new file mode 100755 index 0000000..51064fe --- /dev/null +++ b/samgr/source/samgr_maintenance.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "samgr_maintenance.h" +#include +#include "service_impl.h" +#include "samgr_lite_inner.h" +#include "time_adapter.h" + +void SAMGR_PrintServices(void) +{ + SamgrLiteImpl *samgr = GET_OBJECT(SAMGR_GetInstance(), SamgrLiteImpl, vtbl); + int16 num = VECTOR_Num(&samgr->services); + HILOG_INFO(HILOG_MODULE_SAMGR, "[Maintenance]Print Services(%d) Information:", num); + if (num == 0) { + return; + } + + MUTEX_Lock(samgr->mutex); + int16 size = VECTOR_Size(&(samgr->services)); + int i; + for (i = 0; i < size; ++i) { + ServiceImpl *impl = VECTOR_At(&(samgr->services), i); + if (impl == NULL) { + continue; + } + + MUTEX_Unlock(samgr->mutex); + const char *name = impl->service->GetName(impl->service); + HILOG_INFO(HILOG_MODULE_SAMGR, "[Service:%d]", + impl->serviceId, impl->inited, name, impl->defaultApi, VECTOR_Num(&impl->features), impl->taskPool); + + TaskPool *pool = impl->taskPool; + if (pool != NULL) { + HILOG_INFO(HILOG_MODULE_SAMGR, "[TaskPool:%p]", + pool, pool->tasks[0], pool->queueId, pool->ref, pool->priority, pool->stackSize); + } + + int16 featureSize = VECTOR_Size(&impl->features); + int j; + for (j = 0; j < featureSize; ++j) { + FeatureImpl *feature = VECTOR_At(&impl->features, j); + if (feature == NULL) { + continue; + } + name = feature->feature->GetName(feature->feature); + HILOG_INFO(HILOG_MODULE_SAMGR, "[Feature:%d]", j, name, feature->iUnknown); + } + MUTEX_Lock(samgr->mutex); + } + MUTEX_Unlock(samgr->mutex); +} + +void SAMGR_PrintOperations(void) +{ + SamgrLiteImpl *samgr = GET_OBJECT(SAMGR_GetInstance(), SamgrLiteImpl, vtbl); + int16 num = VECTOR_Num(&samgr->services); + HILOG_INFO(HILOG_MODULE_SAMGR, "[Maintenance]Print Services(%d) Statistics:", num); + if (num == 0) { + return; + } + + uint32 now = SAMGR_GetProcessTime(); + MUTEX_Lock(samgr->mutex); + int16 size = VECTOR_Size(&(samgr->services)); + int i; + for (i = 0; i < size; ++i) { + ServiceImpl *impl = VECTOR_At(&(samgr->services), i); + if (impl == NULL) { + continue; + } + MUTEX_Unlock(samgr->mutex); + const char *name = impl->service->GetName(impl->service); + uint8 abnormal = impl->ops.abnormal; + if (impl->inited == SVC_BUSY) { + if (GET_INTERVAL(impl->ops.timestamp, now) > MSG_PROC_THRESHOLD) { + abnormal = abnormal + 1; + } + } + + MQueueId queueId = ((impl->taskPool == NULL) ? NULL : impl->taskPool->queueId); + HILOG_INFO(HILOG_MODULE_SAMGR, "[Qid:%p] ", + queueId, impl->inited, name, abnormal, impl->ops.messages, impl->ops.timestamp); + MUTEX_Lock(samgr->mutex); + } + MUTEX_Unlock(samgr->mutex); +} \ No newline at end of file diff --git a/samgr/source/samgr_maintenance.h b/samgr/source/samgr_maintenance.h new file mode 100755 index 0000000..f77eb48 --- /dev/null +++ b/samgr/source/samgr_maintenance.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_SAMGR_MAINTENANCE_H +#define LITE_SAMGR_MAINTENANCE_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +void SAMGR_PrintServices(void); +void SAMGR_PrintOperations(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_SAMGR_MAINTENANCE_H diff --git a/samgr/source/service.c b/samgr/source/service.c new file mode 100755 index 0000000..c3556e0 --- /dev/null +++ b/samgr/source/service.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "service_impl.h" +#include +#include "memory_adapter.h" +#include "thread_adapter.h" +#include "time_adapter.h" +#include "feature_impl.h" +#include "service_registry.h" + +static const char *GetFeatureName(const FeatureImpl *featureImpl); + +ServiceImpl *SAMGR_CreateServiceImpl(Service *service, uint8 step) +{ + ServiceImpl *impl = (ServiceImpl *)SAMGR_Malloc(sizeof(ServiceImpl)); + if (impl == NULL) { + return NULL; + } + impl->service = service; + impl->defaultApi = NULL; + impl->taskPool = NULL; + impl->features = VECTOR_Make((VECTOR_Key)GetFeatureName, (VECTOR_Compare)strcmp); + impl->serviceId = INVALID_INDEX; + impl->inited = SVC_INIT; + impl->ops.abnormal = 0; + impl->ops.messages = 0; + impl->ops.step = step; + impl->ops.timestamp = (uint32)SAMGR_GetProcessTime(); + return impl; +} + +int16 DEFAULT_AddFeature(ServiceImpl *serviceImpl, Feature *feature) +{ + if (serviceImpl == NULL || feature == NULL) { + return INVALID_INDEX; + } + + if (VECTOR_Num(&(serviceImpl->features)) >= MAX_FEATURE_NUM) { + return INVALID_INDEX; + } + + FeatureImpl *impl = FEATURE_CreateInstance(feature); + if (impl == NULL) { + return INVALID_INDEX; + } + + int16 featureId = VECTOR_Add(&(serviceImpl->features), impl); + if (featureId == INVALID_INDEX) { + SAMGR_Free(impl); + } + return featureId; +} + +void DEFAULT_Initialize(ServiceImpl *impl) +{ + if (impl == NULL) { + return; + } + Identity id = {impl->serviceId, INVALID_INDEX, (impl->taskPool != NULL) ? impl->taskPool->queueId : NULL}; + + impl->service->Initialize(impl->service, id); + const char *serviceName = impl->service->GetName(impl->service); + SAMGR_RegisterServiceApi(serviceName, NULL, &id, impl->defaultApi); + + int16 size = VECTOR_Size(&impl->features); + int16 i; + for (i = 0; i < size; ++i) { + FeatureImpl *feature = (FeatureImpl *)VECTOR_At(&(impl->features), i); + if (feature == NULL) { + continue; + } + id.featureId = i; + feature->feature->OnInitialize(feature->feature, impl->service, id); + SAMGR_RegisterServiceApi(serviceName, feature->feature->GetName(feature->feature), &id, feature->iUnknown); + } +} + +void DEFAULT_MessageHandle(ServiceImpl *serviceImpl, const Identity *identity, Request *msg) +{ + if (serviceImpl->serviceId != identity->serviceId) { + return; + } + + if (identity->featureId < 0) { + if (serviceImpl->service->MessageHandle != NULL) { + serviceImpl->service->MessageHandle(serviceImpl->service, msg); + } + return; + } + + if (VECTOR_Size(&serviceImpl->features) <= identity->featureId) { + return; + } + + FeatureImpl *featureImpl = (FeatureImpl *)VECTOR_At(&(serviceImpl->features), identity->featureId); + if (featureImpl == NULL) { + return; + } + featureImpl->feature->OnMessage(featureImpl->feature, msg); +} + +void DEFAULT_StopService(ServiceImpl *service) +{ + if (service == NULL) { + return; + } + + Identity id = {service->serviceId, INVALID_INDEX, (service->taskPool != NULL) ? service->taskPool->queueId : NULL}; + int16 size = VECTOR_Size(&service->features); + int16 i; + for (i = 0; i < size; ++i) { + FeatureImpl *featureImpl = (FeatureImpl *)VECTOR_At(&(service->features), i); + if (featureImpl == NULL) { + continue; + } + id.featureId = i; + featureImpl->feature->OnStop(featureImpl->feature, id); + } + service->inited = SVC_INIT; +} + +FeatureImpl *DEFAULT_GetFeature(ServiceImpl *serviceImpl, const char *featureName) +{ + if (serviceImpl == NULL || featureName == NULL) { + return NULL; + } + + short pos = VECTOR_FindByKey(&(serviceImpl->features), (void *)featureName); + return (FeatureImpl *)VECTOR_At(&(serviceImpl->features), pos); +} + +Identity DEFAULT_GetFeatureId(ServiceImpl *serviceImpl, const char *feature) +{ + Identity identity = {INVALID_INDEX, INVALID_INDEX, NULL}; + if (serviceImpl == NULL) { + return identity; + } + + identity.serviceId = serviceImpl->serviceId; + if (serviceImpl->taskPool != NULL) { + identity.queueId = serviceImpl->taskPool->queueId; + } + + int16 pos = VECTOR_FindByKey(&(serviceImpl->features), (void *)feature); + FeatureImpl *featureImpl = (FeatureImpl *)VECTOR_At(&(serviceImpl->features), pos); + if (featureImpl == NULL) { + return identity; + } + identity.featureId = pos; + return identity; +} + +Feature *DEFAULT_DeleteFeature(ServiceImpl *serviceImpl, const char *featureName) +{ + if (serviceImpl == NULL || featureName == NULL) { + return NULL; + } + + int16 pos = VECTOR_FindByKey(&(serviceImpl->features), (void *)featureName); + if (pos < 0 || !SAMGR_IsNoInterface((FeatureImpl *)VECTOR_At(&serviceImpl->features, pos))) { + return NULL; + } + + FeatureImpl *featureImpl = (FeatureImpl *)VECTOR_Swap(&(serviceImpl->features), pos, NULL); + if (featureImpl == NULL) { + return NULL; + } + + Identity id = {serviceImpl->serviceId, INVALID_INDEX, NULL}; + featureImpl->feature->OnStop(featureImpl->feature, id); + + Feature *feature = featureImpl->feature; + SAMGR_Free(featureImpl); + return feature; +} + +static const char *GetFeatureName(const FeatureImpl *featureImpl) +{ + if (featureImpl == NULL) { + return NULL; + } + return featureImpl->feature->GetName(featureImpl->feature); +} diff --git a/samgr/source/service_impl.h b/samgr/source/service_impl.h new file mode 100755 index 0000000..d5e9d88 --- /dev/null +++ b/samgr/source/service_impl.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_SERVICEIMPL_H +#define LITE_SERVICEIMPL_H + +#include "common.h" +#include "iunknown.h" +#include "service.h" +#include "feature_impl.h" +#include "task_manager.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +enum InitStatus { + SVC_INIT = 0, + SVC_IDLE, + SVC_BUSY, +}; +#ifndef MAX_FEATURE_NUM +#define MAX_FEATURE_NUM 0x70 +#endif +#pragma pack(1) +typedef struct Operations Operations; +struct Operations { + uint8 abnormal; + uint8 step; + uint16 messages; + uint32 timestamp; +}; +typedef struct ServiceImpl ServiceImpl; +struct ServiceImpl { + Service *service; + IUnknown *defaultApi; + TaskPool *taskPool; + Vector features; + int16 serviceId; + uint8 inited; + Operations ops; +}; +#pragma pack() + +inline static BOOL IsInvalidService(Service *service) +{ + return (service == NULL || service->GetName == NULL || service->Initialize == NULL || + service->GetTaskConfig == NULL || service->MessageHandle == NULL); +} + +int16 DEFAULT_AddFeature(ServiceImpl *serviceImpl, Feature *feature); +void DEFAULT_Initialize(ServiceImpl *impl); +void DEFAULT_MessageHandle(ServiceImpl *serviceImpl, const Identity *identity, Request *msg); +void DEFAULT_StopService(ServiceImpl *service); +FeatureImpl *DEFAULT_GetFeature(ServiceImpl *serviceImpl, const char *featureName); +Feature *DEFAULT_DeleteFeature(ServiceImpl *serviceImpl, const char *featureName); +Identity DEFAULT_GetFeatureId(ServiceImpl *serviceImpl, const char *feature); +ServiceImpl *SAMGR_CreateServiceImpl(Service *service, uint8 step); +ServiceImpl *SAMGR_GetServiceByID(int16 serviceId); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_SERVICEIMPL_H diff --git a/samgr/source/task_manager.c b/samgr/source/task_manager.c new file mode 100755 index 0000000..e72f35e --- /dev/null +++ b/samgr/source/task_manager.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "task_manager.h" +#include +#include +#include +#include "memory_adapter.h" +#include "time_adapter.h" +#include "queue_adapter.h" +#include "service_impl.h" +#include "message_inner.h" +#include "samgr_lite_inner.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +#define DONT_WAIT 0 +static void BeginWork(ServiceImpl *service); +static void EndWork(ServiceImpl *service, const Exchange *exchange); +static void *TaskEntry(void *); +static void ProcRequest(Exchange *exchange, ServiceImpl *serviceImpl); +static void ProcDirectRequest(Exchange *exchange); +static void ProcResponse(Exchange *exchange); +static ServiceImpl *CorrectServiceImpl(Exchange *exchange, ServiceImpl *serviceImpl); + +TaskPool *SAMGR_CreateFixedTaskPool(const TaskConfig *config, const char *name, uint8 size) +{ + if (config == NULL || size == 0 || MAX_TASK_SIZE <= THREAD_Total()) { + return NULL; + } + + MQueueId queueId = (MQueueId)QUEUE_Create(name, sizeof(Exchange), config->queueSize); + if (queueId == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Create Queue<%s> size:%d failed!", name, config->queueSize); + return NULL; + } + + TaskPool *taskPool = (TaskPool *)SAMGR_Malloc(sizeof(TaskPool) + sizeof(ThreadId) * size); + if (taskPool == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Create TaskPool<%s> size:%d failed!", name, config->queueSize); + QUEUE_Destroy(queueId); + return NULL; + } + + (void)memset_s(taskPool, sizeof(TaskPool) + sizeof(ThreadId) * size, 0, + sizeof(TaskPool) + sizeof(ThreadId) * size); + taskPool->queueId = queueId; + taskPool->stackSize = config->stackSize; + taskPool->priority = (uint8)config->priority; + taskPool->size = size; + taskPool->top = 0; + taskPool->ref = 1; + return taskPool; +} + +int32 SAMGR_StartTaskPool(TaskPool *pool, const char *name) +{ + if (pool == NULL) { + return EC_INVALID; + } + + if (pool->top > 0) { + return EC_SUCCESS; + } + + ThreadAttr attr = {name, pool->stackSize, pool->priority, 0, 0}; + while (pool->top < pool->size) { + register ThreadId threadId = (ThreadId)THREAD_Create(TaskEntry, pool->queueId, &attr); + if (threadId == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Start Task<%s, %d, %d> failed!", name, pool->stackSize, pool->priority); + break; + } + pool->tasks[pool->top] = threadId; + ++(pool->top); + } + return EC_SUCCESS; +} + +int32 SAMGR_ReleaseTaskPool(TaskPool *pool) +{ + if (pool == NULL) { + return EC_INVALID; + } + + pool->ref--; + if (pool->ref == 0) { + Exchange exchange = {0}; + exchange.type = MSG_EXIT; + QUEUE_Put(pool->queueId, &exchange, 0, DONT_WAIT); + SAMGR_Free(pool); + } + return EC_SUCCESS; +} + +TaskPool *SAMGR_ReferenceTaskPool(TaskPool *pool) +{ + if (pool == NULL) { + return NULL; + } + + if (pool->ref >= MAX_REF_NUM) { + return NULL; + } + + pool->ref++; + return pool; +} + +static void *TaskEntry(void *argv) +{ + ServiceImpl *serviceImpl = NULL; + THREAD_SetThreadLocal(argv); + while (TRUE) { + Exchange exchange; + uint32 msgRcvRet = SAMGR_MsgRecv((MQueueId)argv, (uint8 *)&exchange, sizeof(Exchange)); + if (msgRcvRet != EC_SUCCESS) { + continue; + } + + if (exchange.type == MSG_EXIT) { + SAMGR_FreeMsg(&exchange); + break; + } + + serviceImpl = CorrectServiceImpl(&exchange, serviceImpl); + BeginWork(serviceImpl); + ProcResponse(&exchange); + ProcDirectRequest(&exchange); + ProcRequest(&exchange, serviceImpl); + EndWork(serviceImpl, &exchange); + SAMGR_FreeMsg(&exchange); + } + QUEUE_Destroy((MQueueId)argv); + return NULL; +} + +static void ProcRequest(Exchange *exchange, ServiceImpl *serviceImpl) +{ + if (serviceImpl == NULL || exchange->type == MSG_ACK || exchange->type == MSG_DIRECT) { + return; + } + + DEFAULT_MessageHandle(serviceImpl, &(exchange->id), &(exchange->request)); + + if (exchange->type == MSG_CON) { + SAMGR_SendResponse(&exchange->request, &exchange->response); + } +} + +static void ProcResponse(Exchange *exchange) +{ + if (exchange->handler == NULL) { + return; + } + + if (exchange->type != MSG_ACK) { + return; + } + + exchange->handler(&exchange->request, &exchange->response); +} + +static void ProcDirectRequest(Exchange *exchange) +{ + if (exchange->handler == NULL) { + return; + } + + if (exchange->type != MSG_DIRECT) { + return; + } + + exchange->handler(&exchange->request, &exchange->response); +} + +static ServiceImpl *CorrectServiceImpl(Exchange *exchange, ServiceImpl *serviceImpl) +{ + if (exchange->type == MSG_ACK) { + // The ack message use the last service. + return serviceImpl; + } + + if (serviceImpl == NULL || serviceImpl->serviceId != exchange->id.serviceId) { + serviceImpl = SAMGR_GetServiceByID(exchange->id.serviceId); + } + + if (serviceImpl == NULL) { + return NULL; + } + + return serviceImpl; +} + +MQueueId SAMGR_GetCurrentQueueID() +{ + return (MQueueId)THREAD_GetThreadLocal(); +} + +static void BeginWork(ServiceImpl *service) +{ + if (service == NULL || service->inited != SVC_IDLE) { + return; + } + + if (service->ops.step == BOOT_SYS_WAIT) { + WDT_Start(MSG_PROC_THRESHOLD); + } + + service->ops.messages++; + service->ops.timestamp = SAMGR_GetProcessTime(); + service->inited = SVC_BUSY; +} + +static void EndWork(ServiceImpl *service, const Exchange *exchange) +{ + if (service == NULL || service->inited != SVC_BUSY) { + return; + } + + if (service->ops.step == BOOT_SYS_WAIT) { + WDT_Stop(); + } + + uint32 lastTime = service->ops.timestamp; + service->ops.timestamp = (uint32)SAMGR_GetProcessTime(); + uint32 interval = GET_INTERVAL(lastTime, service->ops.timestamp); + if (interval > MSG_PROC_THRESHOLD) { + const char *name = service->service->GetName(service->service); + HILOG_INFO(HILOG_MODULE_SAMGR, "Message Timeout ", + name, exchange->id.featureId, exchange->type, exchange->request.msgId, interval); + service->ops.abnormal++; + } + service->inited = SVC_IDLE; +} diff --git a/samgr/source/task_manager.h b/samgr/source/task_manager.h new file mode 100755 index 0000000..8fea21e --- /dev/null +++ b/samgr/source/task_manager.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_TASKMANAGER_H +#define LITE_TASKMANAGER_H + +#include +#include "thread_adapter.h" +#include "service.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef MAX_TASK_SIZE +#define MAX_TASK_SIZE 0xFFFFFF +#endif +#define MAX_REF_NUM 15 +#define MSG_PROC_THRESHOLD (10 * 1000) +#define GET_REMAIN_TIME(time) ((0xFFFFFFFF - (time)) + 1) +#define GET_INTERVAL(last, now) (((last) > (now)) ? (GET_REMAIN_TIME(last) + (now)) : ((now) - (last))) + +typedef struct TaskPool TaskPool; +struct TaskPool { + MQueueId queueId; + uint16 stackSize; + uint8 priority; // task run priority + uint8 size; + uint8 top; + int8 ref; + ThreadId tasks[0]; +}; +TaskPool *SAMGR_CreateFixedTaskPool(const TaskConfig *config, const char *name, uint8 size); +int32 SAMGR_StartTaskPool(TaskPool *pool, const char *name); +int32 SAMGR_ReleaseTaskPool(TaskPool *pool); +TaskPool *SAMGR_ReferenceTaskPool(TaskPool *pool); +MQueueId SAMGR_GetCurrentQueueID(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // LITE_TASKMANAGER_H diff --git a/samgr_client/BUILD.gn b/samgr_client/BUILD.gn new file mode 100755 index 0000000..bd78a1c --- /dev/null +++ b/samgr_client/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2020 Huawei Device 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. + +source_set("client") { + sources = [ + "source/remote_register.c", + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + + include_dirs = [ + "../samgr_endpoint/source", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/registry", + "//utils/native/lite/include", + "//kernel/liteos_a/kernel/include", + "//kernel/liteos_a/kernel/common", + "//third_party/bounds_checking_function/include", + "//base/security/services/iam_lite/include", + ] + + public_deps = [ + "//foundation/distributedschedule/services/samgr_lite/samgr_endpoint:endpoint_source", + "//third_party/bounds_checking_function:libsec_shared", + "//foundation/communication/frameworks/ipc_lite:liteipc_adapter", + ] +} diff --git a/samgr_client/source/remote_register.c b/samgr_client/source/remote_register.c new file mode 100755 index 0000000..6f021da --- /dev/null +++ b/samgr_client/source/remote_register.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "remote_register.h" +#include +#include +#include +#include +#include "policy_define.h" +#include "samgr_lite.h" +#include "memory_adapter.h" +#include "thread_adapter.h" +#include "iproxy_client.h" +#include "default_client.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +#define RETRY_INTERVAL 2 +#define MAX_RETRY_TIMES 10 +#define MAX_POLICY_NUM 8 +static void InitializeRegistry(void); +static SvcIdentity QueryRemoteIdentity(const char *service, const char *feature); +static int RegisterRemoteIdentity(const char *service, const char *feature, SvcIdentity *saInfo, + PolicyTrans **policy, uint32 *policyNum); +static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum); +static RemoteRegister g_remoteRegister; + +int __attribute__((weak)) SAMGR_RegisterServiceApi(const char *service, const char *feature, + const Identity *identity, IUnknown *iUnknown) +{ + if (service == NULL) { + return EC_INVALID; + } + InitializeRegistry(); + MUTEX_Lock(g_remoteRegister.mtx); + SaName saName = {service, feature}; + int32 token = SAMGR_AddRouter(g_remoteRegister.endpoint, &saName, identity, iUnknown); + MUTEX_Unlock(g_remoteRegister.mtx); + if (token < 0 || !g_remoteRegister.endpoint->running) { + return token; + } + return SAMGR_ProcPolicy(g_remoteRegister.endpoint, &saName, token); +} + +IUnknown *__attribute__((weak)) SAMGR_FindServiceApi(const char *service, const char *feature) +{ + InitializeRegistry(); + SaName key = {service, feature}; + // the proxy already exits. + int index = VECTOR_FindByKey(&g_remoteRegister.clients, &key); + if (index != INVALID_INDEX) { + return VECTOR_At(&g_remoteRegister.clients, index); + } + + SvcIdentity identity = QueryRemoteIdentity(service, feature); + if (identity.handle == INVALID_INDEX) { + return NULL; + } + MUTEX_Lock(g_remoteRegister.mtx); + index = VECTOR_FindByKey(&g_remoteRegister.clients, &key); + if (index != INVALID_INDEX) { + MUTEX_Unlock(g_remoteRegister.mtx); + return VECTOR_At(&g_remoteRegister.clients, index); + } + IUnknown *proxy = SAMGR_CreateIProxy(g_remoteRegister.endpoint->context, service, feature, identity); + VECTOR_Add(&g_remoteRegister.clients, proxy); + MUTEX_Unlock(g_remoteRegister.mtx); + HILOG_INFO(HILOG_MODULE_SAMGR, "Create remote sa proxy[%p]<%s, %s> id<%u,%u>!", + proxy, service, feature, identity.handle, identity.token); + return proxy; +} + +static SvcIdentity QueryRemoteIdentity(const char *service, const char *feature) +{ + IpcIo req; + uint8 data[MIN_DATA_LEN]; + IpcIoInit(&req, data, MIN_DATA_LEN, 0); + IpcIoPushUint32(&req, RES_FEATURE); + IpcIoPushUint32(&req, OP_GET); + IpcIoPushString(&req, service); + IpcIoPushBool(&req, feature == NULL); + if (feature != NULL) { + IpcIoPushString(&req, feature); + } + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = Transact(g_remoteRegister.endpoint->context, samgr, INVALID_INDEX, &req, &reply, + LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf); + ret = (ret != LITEIPC_OK) ? EC_FAILURE : IpcIoPopInt32(&reply); + SvcIdentity target = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + if (ret == EC_SUCCESS) { + SvcIdentity *svc = IpcIoPopSvc(&reply); + if (svc != NULL) { + target = *svc; + } + } + if (ret == EC_PERMISSION) { + HILOG_INFO(HILOG_MODULE_SAMGR, "Cannot Access<%s, %s> No Permission!", service, feature); + } + if (replyBuf != NULL) { + FreeBuffer(g_remoteRegister.endpoint->context, replyBuf); + } + return target; +} + +static int RegisterRemoteIdentity(const char *service, const char *feature, SvcIdentity *saInfo, + PolicyTrans **policy, uint32 *policyNum) +{ + IpcIo req; + uint8 data[MIN_DATA_LEN]; + IpcIoInit(&req, data, MIN_DATA_LEN, 0); + IpcIoPushUint32(&req, RES_FEATURE); + IpcIoPushUint32(&req, OP_PUT); + IpcIoPushString(&req, service); + IpcIoPushBool(&req, feature == NULL); + if (feature != NULL) { + IpcIoPushString(&req, feature); + } + IpcIoPushUint32(&req, saInfo->token); + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = Transact(g_remoteRegister.endpoint->context, samgr, INVALID_INDEX, &req, &reply, + LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf); + ret = -ret; + if (ret == LITEIPC_OK) { + ret = IpcIoPopInt32(&reply); + } + if (ret == EC_SUCCESS) { + saInfo = IpcIoPopSvc(&reply); + GetRemotePolicy(&reply, policy, policyNum); + } + if (replyBuf != NULL) { + FreeBuffer(g_remoteRegister.endpoint->context, replyBuf); + } + return ret; +} + +static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum) +{ + if (reply == NULL) { + return; + } + uint32 i; + uint32 j; + *policyNum = IpcIoPopUint32(reply); + if (*policyNum > MAX_POLICY_NUM) { + *policyNum = MAX_POLICY_NUM; + } + SAMGR_Free(*policy); + if (*policyNum == 0) { + *policy = NULL; + return; + } + *policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * (*policyNum)); + if (*policy == NULL) { + return; + } + for (i = 0; i < *policyNum; i++) { + (*policy)[i].type = IpcIoPopInt32(reply); + switch ((*policy)[i].type) { + case RANGE: + (*policy)[i].uidMin = IpcIoPopInt32(reply); + (*policy)[i].uidMax = IpcIoPopInt32(reply); + break; + case FIXED: + for (j = 0; j < UID_SIZE; j++) { + (*policy)[i].fixedUid[j] = IpcIoPopInt32(reply); + } + break; + case BUNDLENAME: + (*policy)[i].fixedUid[0] = IpcIoPopInt32(reply); + break; + default: + break; + } + } +} + +static void InitializeRegistry(void) +{ + if (g_remoteRegister.endpoint != NULL) { + return; + } + HILOG_INFO(HILOG_MODULE_SAMGR, "Initialize Registry!"); + SAMGR_RegisterQueryIdentity(QueryRemoteIdentity); + SAMGR_RegisterRegisterIdentity(RegisterRemoteIdentity); + g_remoteRegister.mtx = MUTEX_InitValue(); + g_remoteRegister.clients = VECTOR_Make((VECTOR_Key)SAMGR_GetSAName, (VECTOR_Compare)SAMGR_CompareSAName); + g_remoteRegister.endpoint = SAMGR_CreateEndpoint("ipc client", NULL); +} diff --git a/samgr_client/source/remote_register.h b/samgr_client/source/remote_register.h new file mode 100755 index 0000000..7d073dd --- /dev/null +++ b/samgr_client/source/remote_register.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_REMOTE_REGISTER_H +#define LITE_REMOTE_REGISTER_H + +#include "common.h" +#include "endpoint.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +typedef struct RemoteRegister RemoteRegister; +struct RemoteRegister { + MutexId mtx; + Endpoint *endpoint; + Vector clients; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_REMOTE_REGISTER_H diff --git a/samgr_endpoint/BUILD.gn b/samgr_endpoint/BUILD.gn new file mode 100755 index 0000000..f67790a --- /dev/null +++ b/samgr_endpoint/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (c) 2020 Huawei Device 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. + +config("endpoint_public") { + include_dirs = [ + "../samgr/adapter", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/registry", + "//utils/native/lite/include", + "//foundation/communication/interfaces/kits/ipc_lite", + "//third_party/bounds_checking_function/include", + "//base/security/services/iam_lite/ipc_auth/include", + "//kernel/liteos_a/kernel/include/", + "//kernel/liteos_a/kernel/common", + ] +} + +source_set("endpoint_source") { + sources = [ + "source/client_factory.c", + "source/default_client.c", + "source/endpoint.c", + "source/token_bucket.c" + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + + if (ohos_kernel_type == "linux") { + defines = ["LITE_LINUX_BINDER_IPC"] + } + + public_configs = [":endpoint_public"] + + public_deps = [ + "//third_party/bounds_checking_function:libsec_shared", + "//foundation/communication/frameworks/ipc_lite:liteipc_adapter", + "//base/hiviewdfx/frameworks/hilog_lite/featured:hilog_shared", + ] +} + +source_set("store_source") { + sources = [ + "source/sa_store.c", + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + + public_configs = [":endpoint_public"] + + public_deps = [ + "//third_party/bounds_checking_function:libsec_shared", + ] +} diff --git a/samgr_endpoint/source/client_factory.c b/samgr_endpoint/source/client_factory.c new file mode 100755 index 0000000..bbc7c43 --- /dev/null +++ b/samgr_endpoint/source/client_factory.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "client_factory.h" +#include +#include "registry.h" +#include "memory_adapter.h" +#include "thread_adapter.h" +#include "default_client.h" + +typedef struct Factory Factory; +struct Factory { + SaName key; + Creator creator; + Destroyer destroyer; +}; + +static Vector g_factories; +static MutexId g_mutex; +static Factory *GetFactory(const char *service, const char *feature); + +void *SAMGR_CreateIClient(const char *service, const char *feature, uint32 size) +{ + if (service == NULL) { + return NULL; + } + + if (g_mutex == NULL) { + return NULL; + } + + Factory *factory = GetFactory(service, feature); + if (factory == NULL) { + return NULL; + } + + return factory->creator(service, feature, size); +} + +int SAMGR_ReleaseIClient(const char *service, const char *feature, void *iClient) +{ + if (service == NULL || iClient == NULL) { + return EC_INVALID; + } + + if (g_mutex == NULL) { + return EC_NOHANDLER; + } + + Factory *factory = GetFactory(service, feature); + if (factory == NULL) { + return EC_NOHANDLER; + } + factory->destroyer(service, feature, iClient); + return EC_SUCCESS; +} + +int SAMGR_RegisterFactory(const char *service, const char *feature, Creator creator, Destroyer destroyer) +{ + if (service == NULL || creator == NULL || destroyer == NULL) { + return EC_INVALID; + } + + if (g_mutex == NULL) { + g_factories = VECTOR_Make(NULL, (VECTOR_Compare)SAMGR_CompareSAName); + g_mutex = MUTEX_InitValue(); + if (g_mutex == NULL) { + return EC_NOMEMORY; + } + } + + Factory *factory = GetFactory(service, feature); + if (factory != NULL) { + return EC_SUCCESS; + } + + MUTEX_Lock(g_mutex); + factory = SAMGR_Malloc(sizeof(Factory)); + if (factory == NULL) { + MUTEX_Unlock(g_mutex); + return EC_NOMEMORY; + } + factory->key.service = service; + factory->key.feature = feature; + factory->creator = creator; + factory->destroyer = destroyer; + int ret = VECTOR_Add(&g_factories, factory); + MUTEX_Unlock(g_mutex); + if (ret == INVALID_INDEX) { + SAMGR_Free(factory); + return EC_NOMEMORY; + } + return EC_SUCCESS; +} + +static Factory *GetFactory(const char *service, const char *feature) +{ + SaName key = {service, feature}; + Factory *factory = NULL; + MUTEX_Lock(g_mutex); + int index = VECTOR_FindByKey(&g_factories, &key); + if (index != INVALID_INDEX) { + factory = VECTOR_At(&g_factories, index); + } + MUTEX_Unlock(g_mutex); + return factory; +} diff --git a/samgr_endpoint/source/client_factory.h b/samgr_endpoint/source/client_factory.h new file mode 100755 index 0000000..6191fb2 --- /dev/null +++ b/samgr_endpoint/source/client_factory.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_CLIENT_FACTORY_H +#define LITE_CLIENT_FACTORY_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +void *SAMGR_CreateIClient(const char *service, const char *feature, uint32 size); +int SAMGR_ReleaseIClient(const char *service, const char *feature, void *iClient); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_CLIENT_FACTORY_H diff --git a/samgr_endpoint/source/default_client.c b/samgr_endpoint/source/default_client.c new file mode 100755 index 0000000..efb19ec --- /dev/null +++ b/samgr_endpoint/source/default_client.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "default_client.h" +#include +#include +#include +#include "client_factory.h" +#include "iproxy_client.h" +#include "memory_adapter.h" +#include "thread_adapter.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +typedef struct IClientHeader IClientHeader; +typedef struct IDefaultClient IDefaultClient; +typedef struct IClientEntry IClientEntry; +struct IClientHeader { + SaName key; + SvcIdentity target; + uint32 deadId; + const IpcContext *context; +}; + +struct IClientEntry { + INHERIT_IUNKNOWNENTRY(IClientProxy); +}; + +#pragma pack(1) +struct IDefaultClient { + IClientHeader header; + IClientEntry entry; +}; +#pragma pack() + +static int AddRef(IUnknown *iUnknown); +static int Release(IUnknown *proxy); +static int ProxyInvoke(IClientProxy *proxy, int funcId, IpcIo *request, IOwner owner, INotify notify); +static int OnServiceExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv); +static const IClientEntry DEFAULT_ENTRY = {CLIENT_IPROXY_BEGIN, .Invoke = ProxyInvoke, IPROXY_END}; +static MutexId g_mutex = NULL; +static QueryIdentity g_queryID = NULL; + +IUnknown *SAMGR_CreateIProxy(const IpcContext *context, const char *service, const char *feature, SvcIdentity identity) +{ + if (g_queryID == NULL) { + return NULL; + } + + IDefaultClient *client = SAMGR_CreateIClient(service, feature, sizeof(IClientHeader)); + if (client == NULL) { + client = SAMGR_Malloc(sizeof(IDefaultClient)); + if (client == NULL) { + return NULL; + } + client->entry = DEFAULT_ENTRY; + } + + IClientHeader *header = &client->header; + header->target = identity; + header->key.service = service; + header->key.feature = feature; + header->context = context; + (void)RegisteDeathCallback(context, identity, OnServiceExit, client, &header->deadId); + + IClientEntry *entry = &client->entry; + entry->iUnknown.Invoke = ProxyInvoke; + entry->iUnknown.AddRef = AddRef; + entry->iUnknown.Release = Release; + return GET_IUNKNOWN(*entry); +} + +int SAMGR_RegisterQueryIdentity(QueryIdentity query) +{ + if (g_mutex == NULL) { + g_mutex = MUTEX_InitValue(); + } + + if (query == NULL || g_queryID != NULL) { + return EC_INVALID; + } + + g_queryID = query; + return EC_SUCCESS; +} + +SvcIdentity SAMGR_GetRemoteIdentity(const char *service, const char *feature) +{ + if (g_queryID != NULL) { + return g_queryID(service, feature); + } + SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + return identity; +} + +SaName *SAMGR_GetSAName(const IUnknown *proxy) +{ + IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown); + return &(client->header.key); +} + +int SAMGR_CompareSAName(const SaName *key1, const SaName *key2) +{ + if (key1 == key2) { + return 0; + } + + if (key1->service != key2->service) { + int ret = strcmp(key1->service, key2->service); + if (ret != 0) { + return ret; + } + } + + if (key1->feature == key2->feature) { + return 0; + } + + if (key1->feature == NULL) { + return -1; + } + + if (key2->feature == NULL) { + return 1; + } + + return strcmp(key1->feature, key2->feature); +} + +static int AddRef(IUnknown *iUnknown) +{ + MUTEX_Lock(g_mutex); + int ref = IUNKNOWN_AddRef(iUnknown); + MUTEX_Unlock(g_mutex); + return ref; +} + +static int Release(IUnknown *proxy) +{ + MUTEX_Lock(g_mutex); + int ref = IUNKNOWN_Release(proxy); + MUTEX_Unlock(g_mutex); + if (ref != 0) { + return ref; + } + IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown); + int ret = SAMGR_ReleaseIClient(client->header.key.service, client->header.key.feature, client); + if (ret == EC_NOHANDLER) { + SAMGR_Free(client); + return EC_SUCCESS; + } + return ret; +} + +static int ProxyInvoke(IClientProxy *proxy, int funcId, IpcIo *request, IOwner owner, INotify notify) +{ + if (proxy == NULL) { + return EC_INVALID; + } + + IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown); + IClientHeader *header = &client->header; + if (header->target.handle == INVALID_INDEX) { + header->target = g_queryID(header->key.service, header->key.feature); + if (header->target.handle == INVALID_INDEX) { + return EC_INVALID; + } + (void)RegisteDeathCallback(header->context, header->target, OnServiceExit, header, &header->deadId); + } + + IpcIo reply; + void *replyBuf = NULL; + IpcFlag flag = (notify == NULL) ? LITEIPC_FLAG_ONEWAY : LITEIPC_FLAG_DEFAULT; + int ret = Transact(header->context, header->target, funcId, request, &reply, flag, (uintptr_t *)&replyBuf); + if (ret != LITEIPC_OK) { + (void)UnRegisteDeathCallback(header->target, header->deadId); + header->deadId = INVALID_INDEX; + header->target.handle = INVALID_INDEX; + header->target.token = INVALID_INDEX; + header->target.cookie = INVALID_INDEX; + return EC_FAILURE; + } + + if (notify != NULL) { + notify(owner, ret, &reply); + } + + if (replyBuf != NULL) { + FreeBuffer(header->context, replyBuf); + } + return ret; +} + +static int OnServiceExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv) +{ + (void)data; + IClientHeader *header = (IClientHeader *)argv; + (void)UnRegisteDeathCallback(header->target, header->deadId); + header->deadId = INVALID_INDEX; + header->target.handle = INVALID_INDEX; + header->target.token = INVALID_INDEX; + header->target.cookie = INVALID_INDEX; + if (ipcMsg != NULL) { + FreeBuffer(header->context, ipcMsg); + } + HILOG_ERROR(HILOG_MODULE_SAMGR, "Miss the remote service<%u, %u>!", header->target.handle, header->target.token); + return EC_SUCCESS; +} diff --git a/samgr_endpoint/source/default_client.h b/samgr_endpoint/source/default_client.h new file mode 100755 index 0000000..96cd87f --- /dev/null +++ b/samgr_endpoint/source/default_client.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_DEFAULT_CLIENT_H +#define LITE_DEFAULT_CLIENT_H + +#include +#include "iunknown.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +typedef struct SaName SaName; +struct SaName { + const char *service; + const char *feature; +}; +typedef SvcIdentity (*QueryIdentity)(const char *service, const char *feature); +int SAMGR_RegisterQueryIdentity(QueryIdentity query); +IUnknown *SAMGR_CreateIProxy(const IpcContext *context, const char *service, const char *feature, SvcIdentity identity); +SaName *SAMGR_GetSAName(const IUnknown *proxy); +int SAMGR_CompareSAName(const SaName *key1, const SaName *key2); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_DEFAULT_CLIENT_H diff --git a/samgr_endpoint/source/endpoint.c b/samgr_endpoint/source/endpoint.c new file mode 100755 index 0000000..f4d4e60 --- /dev/null +++ b/samgr_endpoint/source/endpoint.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "endpoint.h" +#include +#include +#include +#include +#include +#include "iproxy_server.h" +#include "memory_adapter.h" +#include "thread_adapter.h" +#include "default_client.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +#define MAX_STACK_SIZE 0x1000 +#define MAX_OBJECT_NUM 5 +#define MAX_RETRY_TIMES 3 +#define RETRY_INTERVAL 5 +#define MAX_REGISTER_RETRY_TIMES 10 +#define REGISTER_RETRY_INTERVAL 2 + +#ifndef MAX_BUCKET_RATE +#define MAX_BUCKET_RATE 1000 +#endif + +#ifndef MAX_BURST_RATE +#define MAX_BURST_RATE (MAX_BUCKET_RATE + (MAX_BUCKET_RATE >> 1)) +#endif + +#define SAMGR_SERVICE "samgr" + +typedef struct Router { + SaName saName; + Identity identity; + IServerProxy *proxy; + PolicyTrans *policy; + uint32 policyNum; +} Router; + +static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2); +static IServerProxy *GetIServerProxy(const Router *router); +static void *Receive(void *argv); +static int Dispatch(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv); +static void HandleIpc(const Request *request, const Response *response); +static int OnSamgrServerExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv); +static int RegisterRemoteFeatures(Endpoint *endpoint); +static void Listen(Endpoint *endpoint); +static boolean JudgePolicy(uid_t callingUid, const PolicyTrans *policy, uint32 policyNum); +static boolean SearchFixedPolicy(uid_t callingUid, PolicyTrans policy); +static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo, + const PolicyTrans *policy, uint32 policyNum); +static int RegisterRemoteEndpoint(const IpcContext *context, SvcIdentity *identity); +static RegisterIdentity g_registerID = NULL; +int SAMGR_RegisterRegisterIdentity(RegisterIdentity action) +{ + if (action == NULL || g_registerID != NULL) { + return EC_INVALID; + } + + g_registerID = action; + return EC_SUCCESS; +} + +Endpoint *SAMGR_CreateEndpoint(const char *name, RegisterEndpoint registry) +{ + Endpoint *endpoint = SAMGR_Malloc(sizeof(Endpoint)); + if (endpoint == NULL) { + return NULL; + } + endpoint->deadId = INVALID_INDEX; + endpoint->context = OpenLiteIpc(LITEIPC_DEFAULT_MAP_SIZE); + endpoint->boss = NULL; + endpoint->routers = VECTOR_Make((VECTOR_Key)GetIServerProxy, (VECTOR_Compare)CompareIServerProxy); + endpoint->name = name; + endpoint->running = FALSE; + endpoint->identity.handle = (uint32_t)INVALID_INDEX; + endpoint->identity.token = (uint32_t)INVALID_INDEX; + endpoint->identity.cookie = (uint32_t)INVALID_INDEX; + endpoint->registerEP = (registry == NULL) ? RegisterRemoteEndpoint : registry; + TB_InitBucket(&endpoint->bucket, MAX_BUCKET_RATE, MAX_BURST_RATE); + return endpoint; +} + +int SAMGR_AddRouter(Endpoint *endpoint, const SaName *saName, const Identity *id, IUnknown *proxy) +{ + if (endpoint == NULL || id == NULL || proxy == NULL || saName == NULL) { + return EC_INVALID; + } + + IServerProxy *serverProxy = NULL; + proxy->QueryInterface(proxy, SERVER_PROXY_VER, (void *)&serverProxy); + if (serverProxy == NULL) { + return EC_INVALID; + } + // Lock the multi-write + int index = VECTOR_FindByKey(&endpoint->routers, proxy); + if (index != INVALID_INDEX) { + serverProxy->Release((IUnknown *)serverProxy); + return index; + } + + Router *router = SAMGR_Malloc(sizeof(Router)); + if (router == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Memory is not enough! Identity<%d, %d, %p>", + id->serviceId, id->featureId, id->queueId); + return EC_NOMEMORY; + } + router->saName = *saName; + router->identity = *id; + router->proxy = serverProxy; + router->policy = NULL; + router->policyNum = 0; + index = VECTOR_Add(&endpoint->routers, router); + if (index == INVALID_INDEX) { + SAMGR_Free(router); + return EC_FAILURE; + } + Listen(endpoint); + return index; +} + +int SAMGR_ProcPolicy(const Endpoint *endpoint, const SaName *saName, int token) +{ + if (endpoint == NULL || saName == NULL || token == INVALID_INDEX) { + return EC_INVALID; + } + // retry until success or 20 seconds. + int ret = EC_INVALID; + uint8 retry = 0; + SvcIdentity saInfo = {INVALID_INDEX, token, INVALID_INDEX}; + while (retry < MAX_REGISTER_RETRY_TIMES) { + ++retry; + PolicyTrans *policy = NULL; + uint32 policyNum = 0; + ret = g_registerID(saName->service, saName->feature, &saInfo, &policy, &policyNum); + if (ret != EC_SUCCESS || policy == NULL) { + SAMGR_Free(policy); + continue; + } + HILOG_INFO(HILOG_MODULE_SAMGR, "Register server sa<%s, %s> id<%u, %u> retry:%d ret:%d!", + saName->service, saName->feature, saInfo.handle, saInfo.token, retry, ret); + ret = AddPolicyToRouter(endpoint, &saInfo, policy, policyNum); + if (ret == EC_SUCCESS) { + SAMGR_Free(policy); + break; + } + SAMGR_Free(policy); + sleep(REGISTER_RETRY_INTERVAL); + } + return ret; +} + +static void Listen(Endpoint *endpoint) +{ + if (endpoint->boss != NULL) { + return; + } + ThreadAttr attr = {endpoint->name, MAX_STACK_SIZE, PRI_ABOVE_NORMAL, 0, 0}; + endpoint->boss = (ThreadId)THREAD_Create(Receive, endpoint, &attr); +} + +static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo, + const PolicyTrans *policy, uint32 policyNum) +{ + if (endpoint == NULL || saInfo == NULL || policy == NULL) { + return EC_INVALID; + } + + Router *router = VECTOR_At((Vector *)&endpoint->routers, saInfo->token); + if (router == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, saInfo->token); + return EC_INVALID; + } + + if (router->policy != NULL) { + return EC_SUCCESS; + } + router->policyNum = policyNum; + if (policyNum == 0) { + return EC_INVALID; + } + router->policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * policyNum); + if (router->policy == NULL) { + return EC_NOMEMORY; + } + if (memcpy_s(router->policy, sizeof(PolicyTrans) * policyNum, policy, sizeof(PolicyTrans) * policyNum) != EOK) { + SAMGR_Free(router->policy); + router->policy = NULL; + HILOG_ERROR(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Failed!", + endpoint->name, router->saName.service, router->saName.feature); + return EC_FAILURE; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Success", + endpoint->name, router->saName.service, router->saName.feature); + return EC_SUCCESS; +} + +static void *Receive(void *argv) +{ + Endpoint *endpoint = (Endpoint *)argv; + if (endpoint == NULL || endpoint->registerEP == NULL) { + return NULL; + } + + int ret = EC_INVALID; + uint8 retry = 0; + while (retry < MAX_RETRY_TIMES) { + ret = endpoint->registerEP(endpoint->context, &endpoint->identity); + if (ret == EC_SUCCESS) { + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + (void)UnRegisteDeathCallback(samgr, endpoint->deadId); + (void)RegisteDeathCallback(endpoint->context, samgr, OnSamgrServerExit, endpoint, &endpoint->deadId); + break; + } + ++retry; + sleep(RETRY_INTERVAL); + } + + if (ret != EC_SUCCESS) { + HILOG_FATAL(HILOG_MODULE_SAMGR, "Register endpoint<%s>, handle<%u> failed! will exit to recover!", + endpoint->name, endpoint->identity.handle); + exit(-ret); + } + + endpoint->running = TRUE; + if (endpoint->identity.handle != SAMGR_HANDLE) { + int remain = RegisterRemoteFeatures(endpoint); + HILOG_INFO(HILOG_MODULE_SAMGR, "Register endpoint<%s> and iunknown finished! remain<%d> iunknown!", + endpoint->name, remain); + } + StartLoop(endpoint->context, Dispatch, endpoint); + return NULL; +} + +static int Dispatch(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv) +{ + if (argv == NULL || ipcMsg == NULL) { + return EC_INVALID; + } + + Endpoint *endpoint = (Endpoint *)argv; + uint32_t token = (uint32_t)INVALID_INDEX; + GetToken(ipcMsg, &token); + if (TB_CheckMessage(&endpoint->bucket) == BUCKET_BUSY) { + HILOG_WARN(HILOG_MODULE_SAMGR, "Flow Control <%u> is NULL", token); + goto ERROR; + } + + Router *router = VECTOR_At(&endpoint->routers, token); + if (router == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, token); + goto ERROR; + } + Response resp = {0}; + resp.data = endpoint; + Request request = {0}; + request.msgId = token; + request.data = ipcMsg; + request.msgValue = INVALID_INDEX; + GetCode(ipcMsg, &request.msgValue); +#ifdef LITE_LINUX_BINDER_IPC + HandleIpc(&request, &resp); +#else + uint32 *ref = NULL; + int ret = SAMGR_SendSharedDirectRequest(&router->identity, &request, &resp, &ref, HandleIpc); + if (ret != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Router[%u] Service<%d, %d, %p> is busy", + token, router->identity.serviceId, router->identity.featureId, router->identity.queueId); + goto ERROR; + } +#endif + return EC_SUCCESS; +ERROR: + if (ipcMsg != NULL) { + FreeBuffer(endpoint->context, ipcMsg); + } + return EC_INVALID; +} + +static void HandleIpc(const Request *request, const Response *response) +{ + void *ipcMsg = (void *)request->data; + Endpoint *endpoint = (Endpoint *)response->data; + Router *router = VECTOR_At(&endpoint->routers, request->msgId); + if (ipcMsg == NULL) { + return; + } + + if (router == NULL || router->proxy == NULL || router->proxy->Invoke == NULL) { + FreeBuffer(endpoint->context, ipcMsg); + HILOG_ERROR(HILOG_MODULE_SAMGR, "Invalid IPC router<%p>!", router); + return; + } + + uid_t uid = GetCallingUid(ipcMsg); + if ((strcmp(router->saName.service, SAMGR_SERVICE) != 0) && + !JudgePolicy(uid, (const PolicyTrans *)(router->policy), router->policyNum)) { + FreeBuffer(endpoint->context, ipcMsg); + HILOG_ERROR(HILOG_MODULE_SAMGR, "Consumer uid<%d> has no permission to access<%s, %d, %d>!", + uid, router->saName.service, router->identity.serviceId, router->identity.featureId); + return; + } + + IpcIo req; + IpcIoInitFromMsg(&req, ipcMsg); + IpcIo reply; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&reply, data, MAX_DATA_LEN, MAX_OBJECT_NUM); + router->proxy->Invoke(router->proxy, request->msgValue, ipcMsg, &req, &reply); + uint32_t flag = 0; + GetFlag(ipcMsg, &flag); + if (flag == LITEIPC_FLAG_DEFAULT) { + SendReply(endpoint->context, ipcMsg, &reply); + } else { + FreeBuffer(endpoint->context, ipcMsg); + } +} +static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2) +{ + if (proxy1 == proxy2) { + return 0; + } + return (proxy1 > proxy2) ? 1 : -1; +} + +static IServerProxy *GetIServerProxy(const Router *router) +{ + if (router == NULL) { + return NULL; + } + return router->proxy; +} + +static int RegisterRemoteFeatures(Endpoint *endpoint) +{ + int nums = 0; + if (g_registerID == NULL) { + return nums; + } + int size = VECTOR_Size(&endpoint->routers); + int i; + SvcIdentity identity; + for (i = 0; i < size; ++i) { + Router *router = VECTOR_At(&endpoint->routers, i); + if (router == NULL) { + continue; + } + + identity.handle = endpoint->identity.handle; + identity.token = i; + int ret = g_registerID(router->saName.service, router->saName.feature, &identity, + &(router->policy), &(router->policyNum)); + if (ret == EC_SUCCESS) { + ++nums; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "RegisterRemoteFeatures<%s, %s> ret:%d", + router->saName.service, router->saName.feature, ret); + } + return VECTOR_Num(&endpoint->routers) - nums; +} + +static int RegisterRemoteEndpoint(const IpcContext *context, SvcIdentity *identity) +{ + IpcIo req; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&req, data, MAX_DATA_LEN, 0); + IpcIoPushUint32(&req, RES_ENDPOINT); + IpcIoPushUint32(&req, OP_POST); + IpcIoPushUint32(&req, identity->handle); + uint8 retry = 0; + while (retry < MAX_RETRY_TIMES) { + ++retry; + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int err = Transact(context, samgr, INVALID_INDEX, &req, &reply, LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf); + if (err == LITEIPC_OK) { + identity->handle = IpcIoPopUint32(&reply); + if (replyBuf != NULL) { + FreeBuffer(context, replyBuf); + } + if (identity->handle == (uint32)INVALID_INDEX) { + continue; + } + return EC_SUCCESS; + } + sleep(RETRY_INTERVAL); + } + return EC_FAILURE; +} + +static int OnSamgrServerExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv) +{ + (void)data; + HILOG_ERROR(HILOG_MODULE_SAMGR, "Disconnect to samgr server!"); + Endpoint *endpoint = (Endpoint *)argv; + if (endpoint == NULL || endpoint->registerEP == NULL) { + return EC_FAILURE; + } + if (ipcMsg != NULL) { + FreeBuffer(endpoint->context, ipcMsg); + } + int size = VECTOR_Size(&endpoint->routers); + int i; + for (i = 0; i < size; i++) { + Router *router = VECTOR_At(&endpoint->routers, i); + if (router == NULL) { + continue; + } + SAMGR_Free(router->policy); + router->policy = NULL; + router->policyNum = 0; + } + + while (endpoint->registerEP(endpoint->context, &endpoint->identity) != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Reconnect to samgr server failed!"); + sleep(RETRY_INTERVAL); + } + + SvcIdentity identity; + identity.handle = SAMGR_HANDLE; + identity.token = SAMGR_TOKEN; + identity.cookie = SAMGR_COOKIE; + (void)UnRegisteDeathCallback(identity, endpoint->deadId); + (void)RegisteDeathCallback(endpoint->context, identity, OnSamgrServerExit, endpoint, &endpoint->deadId); + int remain = RegisterRemoteFeatures(endpoint); + HILOG_INFO(HILOG_MODULE_SAMGR, "Reconnect and register finished! remain<%d> iunknown!", remain); + return EC_SUCCESS; +} + +static boolean JudgePolicy(uid_t callingUid, const PolicyTrans *policy, uint32 policyNum) +{ + if (policy == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Policy is NULL! Num is %u", policyNum); + return FALSE; + } + + uint32 i; + for (i = 0; i < policyNum; i++) { + if (policy[i].type == RANGE && callingUid >= policy[i].uidMin && callingUid <= policy[i].uidMax) { + return TRUE; + } + if (policy[i].type == FIXED && SearchFixedPolicy(callingUid, policy[i])) { + return TRUE; + } + } + return FALSE; +} + +static boolean SearchFixedPolicy(uid_t callingUid, PolicyTrans policy) +{ + int i; + for (i = 0; i < UID_SIZE; i++) { + if (callingUid == policy.fixedUid[i]) { + return TRUE; + } + } + return FALSE; +} \ No newline at end of file diff --git a/samgr_endpoint/source/endpoint.h b/samgr_endpoint/source/endpoint.h new file mode 100755 index 0000000..27540ff --- /dev/null +++ b/samgr_endpoint/source/endpoint.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_ENDPOINT_H +#define LITE_ENDPOINT_H + +#include +#include "policy_define.h" +#include "common.h" +#include "iproxy_server.h" +#include "default_client.h" +#include "token_bucket.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define SAMGR_HANDLE 0 +#define SAMGR_TOKEN 0 +#define SAMGR_COOKIE 0 +#define MAX_DATA_LEN 0x100 +#define MIN_DATA_LEN 0x40 + +typedef enum ResourceID { + RES_ENDPOINT, + RES_FEATURE, + RES_BUTT, +} ResourceID; + +typedef enum OptionID { + OP_GET, + OP_POST, + OP_PUT, + OP_DELETE, +} OptionID; +typedef struct Endpoint Endpoint; +typedef int (*RegisterIdentity)(const char *service, const char *feature, SvcIdentity *identity, + PolicyTrans **policy, uint32 *policyNum); +typedef int (*RegisterEndpoint)(const IpcContext *context, SvcIdentity *identity); +struct Endpoint { + const char *name; + IpcContext *context; + Vector routers; + ThreadId boss; + uint32 deadId; + int running; + SvcIdentity identity; + RegisterEndpoint registerEP; + TokenBucket bucket; +}; + +int SAMGR_RegisterRegisterIdentity(RegisterIdentity action); +Endpoint *SAMGR_CreateEndpoint(const char *name, RegisterEndpoint registry); +int SAMGR_AddRouter(Endpoint *endpoint, const SaName *saName, const Identity *id, IUnknown *proxy); +int SAMGR_ProcPolicy(const Endpoint *endpoint, const SaName *saName, int token); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_ENDPOINT_H diff --git a/samgr_endpoint/source/sa_store.c b/samgr_endpoint/source/sa_store.c new file mode 100755 index 0000000..c3731e0 --- /dev/null +++ b/samgr_endpoint/source/sa_store.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "sa_store.h" +#include +#include +#include "common.h" +#include "memory_adapter.h" + +#define GROW_STEP 4 +#define MAX_SA_NUM 300 +static void FreeTreeNode(SAStore *saStore, ListNode *node); +static void SASTORA_ClearServiceByHandle(SAStore *saStore, uint32 handle); +static inline ListNode *FindServiceByName(ListNode *curNode, const char *service) +{ + while (curNode != NULL) { + if (strncmp(curNode->info.name, service, MAX_NAME_LEN) == 0) { + break; + } + curNode = curNode->next; + } + return curNode; +} + +static inline FeatureNode *FindFeatureByName(FeatureNode *curNode, const char *feature) +{ + while (curNode != NULL) { + if ((feature == NULL && curNode->isDefault) || + (feature != NULL && strncmp(curNode->name, feature, MAX_NAME_LEN) == 0)) { + break; + } + curNode = curNode->next; + } + return curNode; +} + +int SASTORA_Save(SAStore *saStore, const char *service, const char *feature, const SvcIdentity *identity) +{ + if (saStore == NULL || service == NULL || identity == NULL) { + return EC_INVALID; + } + + ListNode *curNode = FindServiceByName(saStore->root, service); + FeatureNode *fNode = (curNode == NULL) ? NULL : curNode->info.head; + fNode = FindFeatureByName(fNode, feature); + if (fNode != NULL) { + return EC_SUCCESS; + } + + if (saStore->saSize >= MAX_SA_NUM) { + return EC_NOSPACE; + } + + fNode = SAMGR_Malloc(sizeof(FeatureNode)); + if (fNode == NULL) { + return EC_NOMEMORY; + } + + fNode->token = identity->token; + fNode->isDefault = feature == NULL; + fNode->name[0] = 0; + if (feature != NULL) { + if (strcpy_s(fNode->name, MAX_NAME_LEN, feature) != EOK) { + SAMGR_Free(fNode); + return EC_INVALID; + } + } + + if (curNode == NULL) { + curNode = SAMGR_Malloc(sizeof(ListNode)); + if (curNode == NULL) { + SAMGR_Free(fNode); + return EC_NOMEMORY; + } + if (strcpy_s(curNode->info.name, MAX_NAME_LEN, service) != EOK) { + SAMGR_Free(fNode); + SAMGR_Free(curNode); + return EC_INVALID; + } + + curNode->info.handle = identity->handle; + curNode->info.head = NULL; + curNode->next = saStore->root; + saStore->root = curNode; + } + fNode->next = curNode->info.head; + curNode->info.head = fNode; + saStore->saSize++; + return EC_SUCCESS; +} + +int SASTORA_SaveHandleByPid(SAStore *saStore, PidHandle handle) +{ + PidHandle saved = {.handle = INVALID_INDEX}; + int index = SASTORA_FindHandleByPid(saStore, handle.pid, &saved); + if (saved.handle == handle.handle) { + return EC_SUCCESS; + } + if (index != INVALID_INDEX) { + saStore->maps[index] = handle; + return EC_SUCCESS; + } + + if (saStore->mapSize <= saStore->mapTop) { + PidHandle *newMap = (PidHandle *)SAMGR_Malloc(sizeof(PidHandle) * (saStore->mapSize + GROW_STEP)); + if (newMap == NULL) { + return EC_NOMEMORY; + } + + if (saStore->maps != NULL) { + (void)memcpy_s(newMap, sizeof(PidHandle) * (saStore->mapSize + GROW_STEP), + saStore->maps, sizeof(PidHandle) * saStore->mapSize); + } + PidHandle *oldMap = saStore->maps; + saStore->maps = newMap; + saStore->mapSize += GROW_STEP; + SAMGR_Free(oldMap); + } + int i; + for (i = saStore->mapTop - 1; i >= 0; --i) { + if (saStore->maps[i].pid < handle.pid) { + break; + } + saStore->maps[i + 1] = saStore->maps[i]; + } + saStore->maps[i + 1] = handle; + ++(saStore->mapTop); + return EC_SUCCESS; +} + +int SASTORA_FindHandleByPid(SAStore *saStore, pid_t callingPid, PidHandle *handle) +{ + if (saStore == NULL || saStore->maps == NULL || handle == NULL) { + return INVALID_INDEX; + } + int16 high = saStore->mapTop - 1; + int16 low = 0; + while (low <= high) { + // binary search need div 2 + int16 mid = (high + low) / 2; + if (saStore->maps[mid].pid == callingPid) { + *handle = saStore->maps[mid]; + return mid; + } + if (saStore->maps[mid].pid < callingPid) { + low = mid + 1; + continue; + } + high = mid - 1; + } + return INVALID_INDEX; +} + +PidHandle SASTORA_FindPidHandleByIpcHandle(const SAStore *saStore, uint32 handle) +{ + PidHandle pidHandle = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + if (saStore == NULL || saStore->maps == NULL) { + return pidHandle; + } + int i; + for (i = 0; i < saStore->mapTop; i++) { + if (saStore->maps[i].handle == handle) { + return saStore->maps[i]; + } + } + return pidHandle; +} + +SvcIdentity SASTORA_Find(SAStore *saStore, const char *service, const char *feature) +{ + SvcIdentity identity = {(uint32)INVALID_INDEX, (uint32)INVALID_INDEX, (uint32)INVALID_INDEX}; + ListNode *curNode = FindServiceByName(saStore->root, service); + if (curNode == NULL) { + return identity; + } + + identity.handle = curNode->info.handle; + + FeatureNode *featureNode = FindFeatureByName(curNode->info.head, feature); + if (featureNode != NULL) { + identity.token = featureNode->token; + } + return identity; +} + +int SASTORA_ClearByPid(SAStore *saStore, pid_t pid) +{ + PidHandle pidHandle; + int index = SASTORA_FindHandleByPid(saStore, pid, &pidHandle); + if (index == INVALID_INDEX) { + return EC_INVALID; + } + + SASTORA_ClearServiceByHandle(saStore, pidHandle.handle); + if (saStore->mapTop <= (index + 1)) { + saStore->mapTop--; + return EC_SUCCESS; + } + + errno_t err = memmove_s(&saStore->maps[index], sizeof(PidHandle) * (saStore->mapTop - index), + &saStore->maps[index + 1], sizeof(PidHandle) * (saStore->mapTop - index - 1)); + if (err != EOK) { + return EC_FAILURE; + } + saStore->mapTop--; + return EC_SUCCESS; +} + +static void SASTORA_ClearServiceByHandle(SAStore *saStore, uint32 handle) +{ + ListNode *node = saStore->root; + ListNode *prev = NULL; + while (node != NULL) { + if (node->info.handle == handle) { + ListNode *freeNode = node; + if (prev != NULL) { + prev->next = node->next; + node = node->next; + } else { + saStore->root = node->next; + node = node->next; + } + FreeTreeNode(saStore, freeNode); + continue; + } + prev = node; + node = node->next; + } +} + +static void FreeTreeNode(SAStore *saStore, ListNode *node) +{ + while (node->info.head != NULL) { + FeatureNode *freeNode = node->info.head; + node->info.head = node->info.head->next; + SAMGR_Free(freeNode); + saStore->saSize--; + } + SAMGR_Free(node); +} \ No newline at end of file diff --git a/samgr_endpoint/source/sa_store.h b/samgr_endpoint/source/sa_store.h new file mode 100755 index 0000000..762badf --- /dev/null +++ b/samgr_endpoint/source/sa_store.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_SA_STORE_H +#define LITE_SA_STORE_H + +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MAX_NAME_LEN 16 +typedef struct ServiceInfo ServiceInfo; +typedef struct FeatureNode FeatureNode; +typedef struct SAStore SAStore; +typedef struct ListNode ListNode; +typedef struct PidHandle PidHandle; +struct ServiceInfo { + char name[MAX_NAME_LEN]; + uint32 handle; + FeatureNode *head; +}; + +struct FeatureNode { + char name[MAX_NAME_LEN]; + uint32 isDefault; + uint32 token; + FeatureNode *next; +}; + +struct SAStore { + int saSize; + ListNode *root; + int16 mapSize; + int16 mapTop; + PidHandle *maps; +}; + +struct ListNode { + ListNode *next; + ServiceInfo info; +}; + +struct PidHandle { + pid_t pid; + uid_t uid; + uint32 handle; + uint32 deadId; +}; + +static inline void SASTORA_Init(SAStore *saStore) +{ + saStore->saSize = 0; + saStore->root = NULL; + saStore->mapTop = 0; + saStore->mapSize = 0; + saStore->maps = NULL; +} + +int SASTORA_Save(SAStore *saStore, const char *service, const char *feature, const SvcIdentity *identity); +int SASTORA_SaveHandleByPid(SAStore *saStore, PidHandle handle); +int SASTORA_FindHandleByPid(SAStore *saStore, pid_t callingPid, PidHandle *handle); +SvcIdentity SASTORA_Find(SAStore *saStore, const char *service, const char *feature); +int SASTORA_ClearByPid(SAStore *saStore, pid_t pid); +PidHandle SASTORA_FindPidHandleByIpcHandle(const SAStore *saStore, uint32 handle); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_SA_STORE_H diff --git a/samgr_endpoint/source/token_bucket.c b/samgr_endpoint/source/token_bucket.c new file mode 100755 index 0000000..858b65b --- /dev/null +++ b/samgr_endpoint/source/token_bucket.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "token_bucket.h" +#include +#include +#include "time_adapter.h" +int TB_CheckMessage(TokenBucket *bucket) +{ + if (bucket == NULL) { + return BUCKET_INVALID; + } + uint64 now = SAMGR_GetProcessTime(); + uint64 generated = (now > bucket->last) ? ((now - bucket->last) * bucket->rate) : 0; + int used = bucket->used + TOKEN_PRE_MSG; + used = (generated > used) ? 0 : (used - (int)generated); + if (used >= bucket->burst * TOKEN_PRE_MSG) { + return BUCKET_BUSY; + } + bucket->used = used; + bucket->last = now; + return BUCKET_IDLE; +} \ No newline at end of file diff --git a/samgr_endpoint/source/token_bucket.h b/samgr_endpoint/source/token_bucket.h new file mode 100755 index 0000000..20e4534 --- /dev/null +++ b/samgr_endpoint/source/token_bucket.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_TOKEN_BUCKET_H +#define LITE_TOKEN_BUCKET_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#define TOKEN_PRE_MSG 1000 +typedef struct TokenBucket TokenBucket; +struct TokenBucket { + int rate; // The rate of token generation per millisecond. Now, we use the TPS instead. + int burst; // The burst size of the token bucket + uint64 last; // The time of the last message + int used; // The used buckets. When the rate is TPS, the value is used * TOKEN_PRE_MSG. +}; +typedef enum BucketStatus { + BUCKET_BUSY, + BUCKET_IDLE, + BUCKET_INVALID, +} BucketStatus; + +inline static void TB_InitBucket(TokenBucket *bucket, int rate, int burst) +{ + bucket->last = 0; + bucket->rate = rate; + bucket->burst = burst; + bucket->used = 0; +} +int TB_CheckMessage(TokenBucket *bucket); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_TOKEN_BUCKET_H diff --git a/samgr_server/BUILD.gn b/samgr_server/BUILD.gn new file mode 100755 index 0000000..9cf2124 --- /dev/null +++ b/samgr_server/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2020 Huawei Device 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. + +shared_library("server") { + sources = [ + "source/samgr_server.c", + ] + + cflags = [ + "-fPIC", + "-Wall" + ] + + include_dirs = [ + "../samgr_endpoint/source", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/samgr", + "//foundation/distributedschedule/interfaces/kits/samgr_lite/registry", + "//utils/native/lite/include", + "//kernel/liteos_a/kernel/include/", + "//kernel/liteos_a/kernel/common", + "//third_party/bounds_checking_function/include", + "//base/security/interfaces/innerkits/iam_lite", + "//base/security/services/iam_lite/pms_base/include", + ] + + public_deps = [ + "//third_party/bounds_checking_function:libsec_shared", + "//foundation/distributedschedule/services/samgr_lite/samgr:samgr", + "//foundation/distributedschedule/services/samgr_lite/samgr_endpoint:store_source", + "//foundation/communication/frameworks/ipc_lite:liteipc_adapter", + ] +} diff --git a/samgr_server/source/samgr_server.c b/samgr_server/source/samgr_server.c new file mode 100755 index 0000000..3b580a3 --- /dev/null +++ b/samgr_server/source/samgr_server.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2020 Huawei Device 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 "samgr_server.h" +#include +#include +#include +#include +#include +#include +#include "policy_define.h" +#include "samgr_lite.h" +#include "memory_adapter.h" +#include "thread_adapter.h" +#include "default_client.h" + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +typedef int(*ProcFunc)(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply); +#define MAX_SA_SIZE 0x100 +#define RETRY_TIMES 3 +#define RETRY_INTERVAL 1 + +static const char *GetName(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static TaskConfig GetTaskConfig(Service *service); +static BOOL MessageHandle(Service *service, Request *request); +static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply); +static int OnEndpointExit(const IpcContext *context, void* ipcMsg, IpcIo* data, void* argv); +static int ProcEndpoint(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply); +static int32 ProcPutFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity); +static int32 ProcGetFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity); +static int ProcFeature(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply); +static SvcIdentity QueryLocalIdentity(const char *service, const char *feature); +static int RegisterLocalIdentity(const char *service, const char *feature, SvcIdentity *identity, + PolicyTrans **policy, uint32 *policyNum); +static int RegisterSamgrEndpoint(const IpcContext* context, SvcIdentity* identity); +static void TransmitPolicy(int ret, const SvcIdentity* identity, IpcIo *reply, + const PolicyTrans *policy, uint32 policyNum); +static void TransmitFixedPolicy(IpcIo *reply, PolicyTrans policy); +static IpcAuthInterface *GetIpcAuthInterface(void); + +static SamgrServer g_server = { + .GetName = GetName, + .Initialize = Initialize, + .GetTaskConfig = GetTaskConfig, + .MessageHandle = MessageHandle, + SERVER_IPROXY_IMPL_BEGIN, + .Invoke = Invoke, + IPROXY_END, +}; + +static ProcFunc g_functions[] = { + [RES_ENDPOINT] = ProcEndpoint, + [RES_FEATURE] = ProcFeature, +}; + +static void InitializeRegistry(void) +{ + HILOG_INFO(HILOG_MODULE_SAMGR, "Initialize Registry!"); + SAMGR_RegisterQueryIdentity(QueryLocalIdentity); + SAMGR_RegisterRegisterIdentity(RegisterLocalIdentity); + g_server.mtx = MUTEX_InitValue(); + g_server.clients = VECTOR_Make((VECTOR_Key)SAMGR_GetSAName, (VECTOR_Compare)SAMGR_CompareSAName); + SASTORA_Init(&g_server.store); + g_server.samgr = SAMGR_CreateEndpoint("samgr", RegisterSamgrEndpoint); + g_server.endpoint = SAMGR_CreateEndpoint("ipc receive", NULL); + SAMGR_GetInstance()->RegisterService((Service *)&g_server); +} +SYS_SERVICE_INIT(InitializeRegistry); + +int SAMGR_RegisterServiceApi(const char *service, const char *feature, const Identity *identity, IUnknown *iUnknown) +{ + if (service == NULL) { + return EC_INVALID; + } + MUTEX_Lock(g_server.mtx); + SaName saName = {service, feature}; + int32 token = SAMGR_AddRouter(g_server.endpoint, &saName, identity, iUnknown); + MUTEX_Unlock(g_server.mtx); + if (token < 0 || !g_server.endpoint->running) { + return token; + } + return SAMGR_ProcPolicy(g_server.endpoint, &saName, token); +} + +IUnknown *SAMGR_FindServiceApi(const char *service, const char *feature) +{ + SaName key = {service, feature}; + // the proxy already exits. + int index = VECTOR_FindByKey(&g_server.clients, &key); + if (index != INVALID_INDEX) { + return VECTOR_At(&g_server.clients, index); + } + + SvcIdentity identity = QueryLocalIdentity(service, feature); + if (identity.handle == INVALID_INDEX) { + return NULL; + } + MUTEX_Lock(g_server.mtx); + index = VECTOR_FindByKey(&g_server.clients, &key); + if (index != INVALID_INDEX) { + MUTEX_Unlock(g_server.mtx); + return VECTOR_At(&g_server.clients, index); + } + IUnknown* client = SAMGR_CreateIProxy(g_server.endpoint->context, service, feature, identity); + (void)VECTOR_Add(&g_server.clients, client); + MUTEX_Unlock(g_server.mtx); + HILOG_INFO(HILOG_MODULE_SAMGR, "Create proxy[%p]<%s, %s, %u, %u>", + client, service, feature, identity.handle, identity.token); + return client; +} + +static const char *GetName(Service *service) +{ + (void)service; + return SAMGR_SERVICE; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + SamgrServer *server = (SamgrServer *)service; + server->identity = identity; + SaName saName = {SAMGR_SERVICE, NULL}; + SAMGR_AddRouter(server->samgr, &saName, &server->identity, GET_IUNKNOWN(*server)); + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *request) +{ + SamgrServer *server = (SamgrServer *)service; + switch (request->msgId) { + case MSG_CLEAN: + MUTEX_Lock(server->mtx); + SASTORA_ClearByPid(&server->store, request->msgValue); + MUTEX_Unlock(server->mtx); + break; + default: + break; + } + return TRUE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, 0x400, 20, SINGLE_TASK}; + return config; +} + +static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply) +{ + SamgrServer *server = GET_OBJECT(iProxy, SamgrServer, iUnknown); + int32 resource = IpcIoPopUint32(req); + int32 option = IpcIoPopUint32(req); + if (resource >= RES_BUTT || resource < 0 || g_functions[resource] == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Invalid Msg<%d, %d, %d>", resource, option, funcId); + return EC_INVALID; + } + return g_functions[resource](server, option, origin, req, reply); +} + +static int ProcEndpoint(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply) +{ + if (option != OP_POST) { + IpcIoPushUint32(reply, (uint32)INVALID_INDEX); + return EC_FAILURE; + } + + pid_t pid = GetCallingPid(origin); + PidHandle handle; + MUTEX_Lock(server->mtx); + int index = SASTORA_FindHandleByPid(&g_server.store, pid, &handle); + if (index == INVALID_INDEX) { + SvcIdentity identity = {(uint32)INVALID_INDEX, (uint32)INVALID_INDEX, (uint32)INVALID_INDEX}; + identity.handle = IpcIoPopUint32(req); + if (identity.handle == (uint32)INVALID_INDEX) { // generate handle + (void)GenServiceHandle(&identity, GetCallingTid(origin)); + } + + handle.pid = pid; + handle.uid = GetCallingUid(origin); + handle.handle = identity.handle; + handle.deadId = INVALID_INDEX; + (void)SASTORA_SaveHandleByPid(&server->store, handle); + (void)UnRegisteDeathCallback(identity, handle.deadId); + (void)RegisteDeathCallback(server->endpoint->context, identity, OnEndpointExit, (void*)((uintptr_t)pid), + &handle.deadId); + } + MUTEX_Unlock(server->mtx); + IpcIoPushUint32(reply, handle.handle); + HILOG_INFO(HILOG_MODULE_SAMGR, "Register Endpoint<%d, %d, %d>", handle.pid, handle.handle, handle.deadId); + return EC_SUCCESS; +} + +static int32 ProcPutFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity) +{ + size_t len = 0; + char *service = (char *)IpcIoPopString(req, &len); + if (service == NULL || len == 0) { + IpcIoPushInt32(reply, EC_INVALID); + return EC_INVALID; + } + pid_t pid = GetCallingPid(origin); + char *feature = IpcIoPopBool(req) ? NULL : (char *)IpcIoPopString(req, &len); + MUTEX_Lock(server->mtx); + PidHandle handle; + int index = SASTORA_FindHandleByPid(&server->store, pid, &handle); + if (index == INVALID_INDEX) { + MUTEX_Unlock(server->mtx); + HILOG_ERROR(HILOG_MODULE_SAMGR, "Endpoint[%d] is not register", pid); + IpcIoPushInt32(reply, EC_NOSERVICE); + return EC_NOSERVICE; + } + *identity = SASTORA_Find(&server->store, service, feature); + if (identity->handle != INVALID_INDEX && identity->handle != handle.handle) { + MUTEX_Unlock(server->mtx); + IpcIoPushInt32(reply, EC_INVALID); + return EC_INVALID; + } + identity->token = IpcIoPopUint32(req); + identity->handle = handle.handle; + + PolicyTrans *policy = NULL; + RegParams regParams = {service, feature, handle.uid, handle.pid}; + uint32 policyNum = 0; + int ret = g_server.ipcAuth->GetCommunicationStrategy(regParams, &policy, &policyNum); + if (ret != EC_SUCCESS || policy == NULL) { + MUTEX_Unlock(g_server.mtx); + SAMGR_Free(policy); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Remote Get Communication Strategy<%s, %s> No Permission<%d>!", + service, feature, ret); + IpcIoPushInt32(reply, EC_PERMISSION); + return EC_PERMISSION; + } + + ret = SASTORA_Save(&server->store, service, feature, identity); + MUTEX_Unlock(server->mtx); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Register Feature<%s, %s> pid<%d>, id<%d, %d> ret:%d", + service, feature, pid, identity->handle, identity->token, ret); + TransmitPolicy(ret, identity, reply, policy, policyNum); + SAMGR_Free(policy); + return ret; +} + +static void TransmitPolicy(int ret, const SvcIdentity* identity, IpcIo *reply, + const PolicyTrans *policy, uint32 policyNum) +{ + if (identity == NULL || reply == NULL || policy == NULL) { + IpcIoPushInt32(reply, EC_INVALID); + return; + } + if (ret != EC_SUCCESS) { + IpcIoPushInt32(reply, ret); + return; + } + IpcIoPushInt32(reply, ret); + IpcIoPushSvc(reply, identity); + IpcIoPushUint32(reply, policyNum); + uint32 i; + for (i = 0; i < policyNum; i++) { + IpcIoPushInt32(reply, policy[i].type); + switch (policy[i].type) { + case RANGE: + IpcIoPushInt32(reply, policy[i].uidMin); + IpcIoPushInt32(reply, policy[i].uidMax); + break; + case FIXED: + TransmitFixedPolicy(reply, policy[i]); + break; + case BUNDLENAME: + IpcIoPushInt32(reply, policy[i].fixedUid[0]); + break; + default: + break; + } + } +} + +static void TransmitFixedPolicy(IpcIo *reply, PolicyTrans policy) +{ + if (reply == NULL) { + return; + } + uint32 i; + for (i = 0; i < UID_SIZE; i++) { + IpcIoPushInt32(reply, policy.fixedUid[i]); + } +} + +static int32 ProcGetFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity) +{ + size_t len = 0; + char *service = (char *)IpcIoPopString(req, &len); + if (service == NULL || len == 0) { + IpcIoPushInt32(reply, EC_INVALID); + return EC_INVALID; + } + char *feature = IpcIoPopBool(req) ? NULL : (char *)IpcIoPopString(req, &len); + MUTEX_Lock(server->mtx); + *identity = SASTORA_Find(&server->store, service, feature); + if (identity->handle == INVALID_INDEX) { + MUTEX_Unlock(server->mtx); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Cannot Find Feature<%s, %s> id<%d, %d> ret:%d", + service, feature, identity->handle, identity->token, EC_NOSERVICE); + return EC_NOSERVICE; + } + + PidHandle providerPid = SASTORA_FindPidHandleByIpcHandle(&server->store, identity->handle); + MUTEX_Unlock(server->mtx); + if (providerPid.pid == INVALID_INDEX || providerPid.uid == INVALID_INDEX) { + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Cannot Find PidHandle<%s, %s> id<%d, %d> ret:%d", + service, feature, identity->handle, identity->token, EC_FAILURE); + return EC_FAILURE; + } + AuthParams authParams = { + .providerService = service, + .providerfeature = feature, + .consumerPid = GetCallingPid(origin), + .consumerUid = GetCallingUid(origin), + .providerPid = providerPid.pid, + .providerUid = providerPid.uid + }; + int isAuth = g_server.ipcAuth->IsCommunicationAllowed(authParams); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Judge Auth<%s, %s> ret:%d", service, feature, isAuth); + + int32 ret = (isAuth == EC_SUCCESS) ? AddServiceAccess(*identity, GetCallingTid(origin)) : EC_PERMISSION; + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Find Feature<%s, %s> id<%d, %d> ret:%d", + service, feature, identity->handle, identity->token, ret); + return ret; +} + +static int ProcFeature(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply) +{ + if (option != OP_PUT && option != OP_GET) { + IpcIoPushInt32(reply, EC_INVALID); + return EC_INVALID; + } + + if (g_server.ipcAuth == NULL) { + g_server.ipcAuth = GetIpcAuthInterface(); + } + if (g_server.ipcAuth == NULL) { + IpcIoPushInt32(reply, EC_NOINIT); + return EC_NOINIT; + } + + int ret = EC_SUCCESS; + SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + if (option == OP_PUT) { + ret = ProcPutFeature(server, origin, req, reply, &identity); + } + if (ret != EC_SUCCESS) { + return ret; + } + + if (option == OP_GET) { + ret = ProcGetFeature(server, origin, req, reply, &identity); + IpcIoPushInt32(reply, ret); + IpcIoPushSvc(reply, &identity); + } + return ret; +} + +static SvcIdentity QueryLocalIdentity(const char *service, const char *feature) +{ + MUTEX_Lock(g_server.mtx); + SvcIdentity saInfo = SASTORA_Find(&g_server.store, service, feature); + MUTEX_Unlock(g_server.mtx); + return saInfo; +} + +static int RegisterLocalIdentity(const char *service, const char *feature, SvcIdentity *identity, + PolicyTrans **policy, uint32 *policyNum) +{ + pid_t selfPid = getpid(); + MUTEX_Lock(g_server.mtx); + PidHandle pidHandle = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + int ret = SASTORA_FindHandleByPid(&g_server.store, selfPid, &pidHandle); + if (ret != INVALID_INDEX) { + identity->handle = pidHandle.handle; + ret = SASTORA_Save(&g_server.store, service, feature, identity); + } else { + ret = EC_NODEVICE; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "RegisterIdentity <%s, %s> pid<%d> <%u, %u> ", + service, feature, selfPid, identity->handle, identity->token); + if (ret != EC_SUCCESS) { + MUTEX_Unlock(g_server.mtx); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SaStore Save FAILED(%d), <%s, %s> <%u, %u> ", + ret, service, feature, identity->handle, identity->token); + return ret; + } + MUTEX_Unlock(g_server.mtx); + + RegParams regParams = { + .service = (char *)service, + .feature = (char *)feature, + .uid = getuid(), + .pid = selfPid + }; + if (g_server.ipcAuth == NULL) { + g_server.ipcAuth = GetIpcAuthInterface(); + } + if (g_server.ipcAuth == NULL) { + HILOG_DEBUG(HILOG_MODULE_SAMGR, "g_server.ipcAuth is NULL"); + return EC_FAILURE; + } + ret = g_server.ipcAuth->GetCommunicationStrategy(regParams, policy, policyNum); + return ret; +} + +static int RegisterSamgrEndpoint(const IpcContext* context, SvcIdentity* identity) +{ + int ret = SetSaManager(context, MAX_SA_SIZE); + if (ret != LITEIPC_OK) { + HILOG_FATAL(HILOG_MODULE_SAMGR, "Set sa manager<%d> failed!", ret); + // Set sa manager failed! We need restart to recover + exit(-ret); + } + identity->handle = SAMGR_HANDLE; + identity->token = SAMGR_TOKEN; + identity->cookie = SAMGR_COOKIE; + return EC_SUCCESS; +} + +static int OnEndpointExit(const IpcContext *context, void* ipcMsg, IpcIo* data, void* argv) +{ + (void)data; + if (ipcMsg != NULL) { + FreeBuffer(g_server.endpoint->context, ipcMsg); + } + pid_t pid = (pid_t)((uintptr_t)argv); + Request request = {0}; + request.msgId = MSG_CLEAN; + request.msgValue = pid; + int retry = RETRY_TIMES; + int ret = EC_INVALID; + while (retry > 0) { + ret = SAMGR_SendRequest(&g_server.identity, &request, NULL); + if (ret == EC_SUCCESS) { + break; + } + sleep(RETRY_INTERVAL); + --retry; + } + HILOG_ERROR(HILOG_MODULE_SAMGR, "IPC pid<%d> exit! send clean request retry(%d), ret(%d)!", pid, retry, ret); + return EC_SUCCESS; +} + +static IpcAuthInterface *GetIpcAuthInterface(void) +{ + IpcAuthInterface *ipcAuth = NULL; + IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(PERMISSION_SERVICE, IPCAUTH); + if (iUnknown == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Get IpcAuthInterface: IUnknown NULL"); + return NULL; + } + (void)iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&ipcAuth); + return ipcAuth; +} diff --git a/samgr_server/source/samgr_server.h b/samgr_server/source/samgr_server.h new file mode 100755 index 0000000..aa346f9 --- /dev/null +++ b/samgr_server/source/samgr_server.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Huawei Device 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 LITE_IPC_MANAGER_H +#define LITE_IPC_MANAGER_H + +#include +#include "service.h" +#include "iproxy_server.h" +#include "endpoint.h" +#include "sa_store.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +#define SAMGR_SERVICE "samgr" +typedef struct SamgrServer SamgrServer; +typedef struct SamgrProxy SamgrProxy; +typedef enum MsgId { + MSG_CLEAN, +}MsgId; +struct SamgrProxy { + INHERIT_SERVER_IPROXY; +}; + +struct SamgrServer { + INHERIT_SERVICE; + INHERIT_IPROXY_ENTRY(SamgrProxy); + Identity identity; + Endpoint *samgr; + Endpoint *endpoint; + Vector clients; + MutexId mtx; + SAStore store; + IpcAuthInterface *ipcAuth; +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // LITE_IPC_MANAGER_H