From 53d581e9c39abddcc45c7f1e845ff8203716bbc0 Mon Sep 17 00:00:00 2001 From: SimonLi Date: Mon, 14 Feb 2022 00:09:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20samgr=5Flite=E9=80=82=E9=85=8D=E8=BD=BB?= =?UTF-8?q?=E9=87=8F=E7=B3=BB=E7=BB=9Frpc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 保持对外使用接口不变 2. 采用宏开关进行特性控制 2.1 enable_ohos_distributedschedule_samgr_lite_rpc_mini 进行编译控制 默认为false,可以在vendor目录下的config.json中配置打开 2.2 MINI_SAMGR_LITE_RPC 进行代码编译隔离。 3. 在samgr init的时候,初始化全局的said和saname的映射关系 4. 本端将said传给远端 Signed-off-by: SimonLi --- BUILD.gn | 8 + bundle.json | 1 - communication/broadcast/BUILD.gn | 4 +- config.gni | 3 + interfaces/kits/samgr/feature.h | 13 + interfaces/kits/samgr/message.h | 3 + interfaces/kits/samgr/samgr_lite.h | 4 +- samgr/BUILD.gn | 10 + samgr/adapter/BUILD.gn | 4 +- samgr/source/BUILD.gn | 15 +- samgr/source/samgr_lite.c | 13 + samgr_client/BUILD.gn | 72 +- samgr_client/source/remote_register_rpc.c | 143 ++++ samgr_endpoint/BUILD.gn | 162 +++-- samgr_endpoint/source/client_factory.c | 2 +- samgr_endpoint/source/default_client.h | 10 + samgr_endpoint/source/default_client_rpc.c | 320 +++++++++ samgr_endpoint/source/endpoint.h | 8 + samgr_endpoint/source/endpoint_rpc.c | 626 ++++++++++++++++++ samgr_endpoint/source/sa_store.c | 18 +- samgr_endpoint/source/sa_store.h | 9 + samgr_server/BUILD.gn | 88 ++- samgr_server/source/samgr_server.h | 14 + samgr_server/source/samgr_server_rpc.c | 730 +++++++++++++++++++++ 24 files changed, 2168 insertions(+), 112 deletions(-) create mode 100755 samgr_client/source/remote_register_rpc.c create mode 100755 samgr_endpoint/source/default_client_rpc.c create mode 100755 samgr_endpoint/source/endpoint_rpc.c create mode 100644 samgr_server/source/samgr_server_rpc.c diff --git a/BUILD.gn b/BUILD.gn index b052e13..3e84f90 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -12,6 +12,7 @@ # limitations under the License. import("//build/lite/config/component/lite_component.gni") import("//build/lite/ndk/ndk.gni") +import("config.gni") lite_component("samgr") { features = [ @@ -25,6 +26,13 @@ lite_component("samgr") { "samgr_client:client", ] } + + if (enable_ohos_distributedschedule_samgr_lite_rpc_mini) { + features += [ + "samgr_server:server", + "samgr_client:client", + ] + } } copy("ConfigFiles") { diff --git a/bundle.json b/bundle.json index 1d921f0..f139549 100644 --- a/bundle.json +++ b/bundle.json @@ -27,7 +27,6 @@ "deps": { "components": [ "utils_base", - "ipc_lite", "hilog_lite" ], "third_party": [ diff --git a/communication/broadcast/BUILD.gn b/communication/broadcast/BUILD.gn index 0c9d474..2da670e 100755 --- a/communication/broadcast/BUILD.gn +++ b/communication/broadcast/BUILD.gn @@ -46,9 +46,7 @@ if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { "-std=c11", "-Wall", ] - include_dirs = [ - "//third_party/bounds_checking_function/include", - ] + include_dirs = [ "//third_party/bounds_checking_function/include" ] public_deps = [ "//foundation/distributedschedule/samgr_lite/samgr:samgr", "//third_party/bounds_checking_function:libsec_shared", diff --git a/config.gni b/config.gni index 43b205b..3a017f3 100644 --- a/config.gni +++ b/config.gni @@ -15,4 +15,7 @@ declare_args() { # configuration for samgr_lite created shared task's stack size. # 0 means using system default thread stack size, other positive values will be accepted. config_ohos_distributedschedule_samgr_lite_shared_task_size = 2048 + + # enable samgr_lite adapt to rpc on mini system. + enable_ohos_distributedschedule_samgr_lite_rpc_mini = false } diff --git a/interfaces/kits/samgr/feature.h b/interfaces/kits/samgr/feature.h index 3bb5c39..1fa3f28 100755 --- a/interfaces/kits/samgr/feature.h +++ b/interfaces/kits/samgr/feature.h @@ -129,12 +129,25 @@ struct Feature { * This macro provides the capability of inheriting the feature lifecycle. \n * */ +#ifndef MINI_SAMGR_LITE_RPC + #define INHERIT_FEATURE \ const char *(*GetName)(Feature *feature); \ void (*OnInitialize)(Feature *feature, Service *parent, Identity identity); \ void (*OnStop)(Feature *feature, Identity identity); \ BOOL (*OnMessage)(Feature *feature, Request *request) +#else + +#define INHERIT_FEATURE \ + const char *(*GetName)(Feature *feature); \ + void (*OnInitialize)(Feature *feature, Service *parent, Identity identity); \ + void (*OnStop)(Feature *feature, Identity identity); \ + BOOL (*OnMessage)(Feature *feature, Request *request); \ + BOOL (*IsDistributed)(void) + +#endif + #ifdef __cplusplus #if __cplusplus } diff --git a/interfaces/kits/samgr/message.h b/interfaces/kits/samgr/message.h index 791c4dd..713fb28 100755 --- a/interfaces/kits/samgr/message.h +++ b/interfaces/kits/samgr/message.h @@ -116,6 +116,9 @@ struct Response { void *data; /** Data length */ int16 len; +#ifdef MINI_SAMGR_LITE_RPC + void *reply; +#endif }; #pragma pack() diff --git a/interfaces/kits/samgr/samgr_lite.h b/interfaces/kits/samgr/samgr_lite.h index 5e55861..3b21a0e 100755 --- a/interfaces/kits/samgr/samgr_lite.h +++ b/interfaces/kits/samgr/samgr_lite.h @@ -230,7 +230,9 @@ typedef struct SamgrLite { * @version 1.0 */ IUnknown *(*GetDefaultFeatureApi)(const char *service); - +#ifdef MINI_SAMGR_LITE_RPC + IUnknown *(*GetRemoteDefaultFeatureApi)(char *deviceId, const char *serviceName); +#endif /** * @brief Obtains the API specific to the feature. * diff --git a/samgr/BUILD.gn b/samgr/BUILD.gn index 77abb36..8cfc3ac 100755 --- a/samgr/BUILD.gn +++ b/samgr/BUILD.gn @@ -51,6 +51,16 @@ if (ohos_kernel_type == "liteos_m") { "//foundation/distributedschedule/samgr_lite/samgr/adapter:samgr_adapter", "//foundation/distributedschedule/samgr_lite/samgr/source:samgr_source", ] + + if (enable_ohos_distributedschedule_samgr_lite_rpc_mini) { + defines += [ "MINI_SAMGR_LITE_RPC" ] + include_dirs += [ + "//foundation/distributedschedule/samgr_lite/samgr_endpoint/source", + ] + public_deps += [ + "//foundation/communication/ipc/interfaces/innerkits/c/dbinder:dbinder", + ] + } } } diff --git a/samgr/adapter/BUILD.gn b/samgr/adapter/BUILD.gn index 3094e77..c6f339a 100755 --- a/samgr/adapter/BUILD.gn +++ b/samgr/adapter/BUILD.gn @@ -50,9 +50,7 @@ if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { public_configs = [ ":samgr_adapter_public" ] - include_dirs = [ - "//third_party/bounds_checking_function/include", - ] + include_dirs = [ "//third_party/bounds_checking_function/include" ] cflags = [ "-fPIC", diff --git a/samgr/source/BUILD.gn b/samgr/source/BUILD.gn index 873ef11..d46e29d 100755 --- a/samgr/source/BUILD.gn +++ b/samgr/source/BUILD.gn @@ -11,6 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("../../config.gni") + config("samgr_source_public") { include_dirs = [ "../adapter", @@ -39,7 +41,14 @@ if (ohos_kernel_type == "liteos_m") { "//foundation/distributedschedule/samgr_lite/samgr/adapter:samgr_adapter", ] - include_dirs = [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite" ] + include_dirs = + [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite" ] + + if (enable_ohos_distributedschedule_samgr_lite_rpc_mini) { + public_deps += [ + "//foundation/communication/ipc/interfaces/innerkits/c/dbinder:dbinder", + ] + } } } @@ -66,8 +75,6 @@ if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { "//foundation/distributedschedule/samgr_lite/samgr/adapter:samgr_adapter", ] - include_dirs = [ - "//third_party/bounds_checking_function/include", - ] + include_dirs = [ "//third_party/bounds_checking_function/include" ] } } diff --git a/samgr/source/samgr_lite.c b/samgr/source/samgr_lite.c index 1f2edc4..c947e73 100755 --- a/samgr/source/samgr_lite.c +++ b/samgr/source/samgr_lite.c @@ -45,6 +45,9 @@ static IUnknown *GetFeatureApi(const char *serviceName, const char *feature); static int32 AddSystemCapability(const char *sysCap); static BOOL HasSystemCapability(const char *sysCap); static int32 GetSystemAvailableCapabilities(char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], int32 *size); +#ifdef MINI_SAMGR_LITE_RPC +static IUnknown *GetRemoteDefaultFeatureApi(char *deviceId, const char *serviceName); +#endif /* ************************************************************************************************** * Samgr Lite location functions * ************************************************************************************************* */ @@ -93,6 +96,9 @@ static void Init(void) g_samgrImpl.vtbl.UnregisterDefaultFeatureApi = UnregisterDefaultFeatureApi; g_samgrImpl.vtbl.GetDefaultFeatureApi = GetDefaultFeatureApi; g_samgrImpl.vtbl.GetFeatureApi = GetFeatureApi; +#ifdef MINI_SAMGR_LITE_RPC + g_samgrImpl.vtbl.GetRemoteDefaultFeatureApi = GetRemoteDefaultFeatureApi; +#endif g_samgrImpl.vtbl.AddSystemCapability = AddSystemCapability; g_samgrImpl.vtbl.HasSystemCapability = HasSystemCapability; g_samgrImpl.vtbl.GetSystemAvailableCapabilities = GetSystemAvailableCapabilities; @@ -563,3 +569,10 @@ static TaskPool *GetSpecifiedTaskPool(TaskConfig *config) MUTEX_Unlock(samgr->mutex); return NULL; } + +#ifdef MINI_SAMGR_LITE_RPC +static IUnknown *GetRemoteDefaultFeatureApi(char *deviceId, const char *serviceName) +{ + return SAMGR_CreateIRemoteProxy(deviceId, serviceName, NULL); +} +#endif \ No newline at end of file diff --git a/samgr_client/BUILD.gn b/samgr_client/BUILD.gn index bed2b11..0d68883 100644 --- a/samgr_client/BUILD.gn +++ b/samgr_client/BUILD.gn @@ -11,26 +11,54 @@ # 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/samgr_lite/interfaces/kits/samgr", - "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", - "//utils/native/lite/include", - "//third_party/bounds_checking_function/include", - "//base/security/permission/services/permission_lite/include" - ] - - public_deps = [ - "//foundation/communication/ipc_lite:liteipc_adapter", - "//foundation/distributedschedule/samgr_lite/samgr_endpoint:endpoint_source", - "//third_party/bounds_checking_function:libsec_shared" - ] +import("../config.gni") + +if (!enable_ohos_distributedschedule_samgr_lite_rpc_mini) { + source_set("client") { + sources = [ "source/remote_register.c" ] + + cflags = [ + "-fPIC", + "-Wall", + ] + + include_dirs = [ + "../samgr_endpoint/source", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "//utils/native/lite/include", + "//third_party/bounds_checking_function/include", + "//base/security/permission/services/permission_lite/include", + ] + + public_deps = [ + "//foundation/communication/ipc_lite:liteipc_adapter", + "//foundation/distributedschedule/samgr_lite/samgr_endpoint:endpoint_source", + "//third_party/bounds_checking_function:libsec_shared", + ] + } +} else { + source_set("client") { + sources = [ "source/remote_register_rpc.c" ] + + cflags = [ "-Wall" ] + + include_dirs = [ + "../samgr_server/source", + "../samgr_endpoint/source", + "//base/security/permission/interfaces/innerkits/permission_lite", + "//base/security/permission/services/permission_lite/pms_base/include", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "//utils/native/lite/include", + "//third_party/bounds_checking_function/include", + "//base/security/permission/services/permission_lite/include", + ] + + public_deps = [ + "//foundation/communication/ipc/interfaces/innerkits/c/dbinder:dbinder", + "//foundation/distributedschedule/samgr_lite/samgr_endpoint:endpoint_source", + "//third_party/bounds_checking_function:libsec_static", + ] + } } diff --git a/samgr_client/source/remote_register_rpc.c b/samgr_client/source/remote_register_rpc.c new file mode 100755 index 0000000..e628a1f --- /dev/null +++ b/samgr_client/source/remote_register_rpc.c @@ -0,0 +1,143 @@ +/* + * 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 "dbinder_service.h" +#include "default_client.h" +#include "iproxy_client.h" +#include "memory_adapter.h" +#include "policy_define.h" +#include "pthread.h" +#include "samgr_lite.h" +#include "samgr_server.h" +#include "thread_adapter.h" +#include "unistd.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 ABILITY_UID_START 100 +static void ClientInitializeRegistry(void); +RemoteRegister g_remoteRegister; +static BOOL g_isAbilityInited = FALSE; + +int SAMGR_RegisterServiceApi(const char *service, const char *feature, const Identity *identity, IUnknown *iUnknown) +{ + if (service == NULL) { + return EC_INVALID; + } + ClientInitializeRegistry(); + MUTEX_Lock(g_remoteRegister.mtx); + SaName saName = {service, feature}; + int32 token = SAMGR_AddRouter(g_remoteRegister.endpoint, &saName, identity, iUnknown); + char saNameStr[2 * MAX_NAME_LEN + 2]; + sprintf_s(saNameStr, 2 * MAX_NAME_LEN + 2, "%s#%s", service?service:"", feature?feature:""); + HILOG_INFO(HILOG_MODULE_SAMGR, "register saname: %s index: %d\n", saNameStr, token); + SaNode *saNode = GetSaNodeBySaName(service, feature); + if (saNode != NULL) { + RegisterRemoteProxy(saNameStr, strlen(saNameStr), saNode->saId); + } + MUTEX_Unlock(g_remoteRegister.mtx); + if (token < 0 || !g_remoteRegister.endpoint->running) { + return token; + } + return EC_SUCCESS; +} + +IUnknown *SAMGR_FindServiceApi(const char *service, const char *feature) +{ + if (service == NULL) { + return NULL; + } + ClientInitializeRegistry(); + SaName key = {service, feature}; + int index = VECTOR_FindByKey(&g_remoteRegister.clients, &key); + if (index != INVALID_INDEX) { + return VECTOR_At(&g_remoteRegister.clients, index); + } + IUnknown *proxy = SAMGR_CreateIProxy(service, feature); + if (proxy == NULL) { + return NULL; + } + MUTEX_Lock(g_remoteRegister.mtx); + index = VECTOR_FindByKey(&g_remoteRegister.clients, &key); + if (index != INVALID_INDEX) { + MUTEX_Unlock(g_remoteRegister.mtx); + proxy->Release(proxy); + return VECTOR_At(&g_remoteRegister.clients, index); + } + VECTOR_Add(&g_remoteRegister.clients, proxy); + MUTEX_Unlock(g_remoteRegister.mtx); + HILOG_INFO(HILOG_MODULE_SAMGR, "Create remote sa proxy<%s, %s>!", service, feature); + return proxy; +} + +int32 SAMGR_RegisterSystemCapabilityApi(const char *sysCap, BOOL isReg) +{ + ClientInitializeRegistry(); + return SAMGR_AddSysCap(g_remoteRegister.endpoint, sysCap, isReg); +} + +BOOL SAMGR_QuerySystemCapabilityApi(const char *sysCap) +{ + ClientInitializeRegistry(); + BOOL isReg = FALSE; + if (SAMGR_GetSysCap(g_remoteRegister.endpoint, sysCap, &isReg) != EC_SUCCESS) { + return FALSE; + } + return isReg; +} + +int32 SAMGR_GetSystemCapabilitiesApi(char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], int32 *size) +{ + ClientInitializeRegistry(); + return SAMGR_GetSystemCapabilities(g_remoteRegister.endpoint, sysCaps, size); +} + +static void ClearRegistry(void) +{ + if (g_remoteRegister.endpoint == NULL) { + return; + } + HILOG_INFO(HILOG_MODULE_SAMGR, "Clear Client Registry!"); + SAMGR_Free(g_remoteRegister.mtx); + g_remoteRegister.mtx = NULL; + VECTOR_Clear(&(g_remoteRegister.clients)); + VECTOR_Clear(&(g_remoteRegister.endpoint->routers)); + SAMGR_Free(g_remoteRegister.endpoint); + g_remoteRegister.endpoint = NULL; +} + +static void ClientInitializeRegistry(void) +{ + if (g_remoteRegister.endpoint != NULL) { + return; + } + HILOG_INFO(HILOG_MODULE_SAMGR, "Initialize Client Registry!"); + MUTEX_GlobalLock(); + if (g_remoteRegister.endpoint == NULL) { + 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); + } + MUTEX_GlobalUnlock(); +} diff --git a/samgr_endpoint/BUILD.gn b/samgr_endpoint/BUILD.gn index 9d7cbcc..40fd787 100644 --- a/samgr_endpoint/BUILD.gn +++ b/samgr_endpoint/BUILD.gn @@ -11,64 +11,130 @@ # See the License for the specific language governing permissions and # limitations under the License. -config("endpoint_public") { - include_dirs = [ - "../samgr/adapter", - "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", - "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", - "//utils/native/lite/include", - "//foundation/communication/ipc_lite/interfaces/kits", - "//third_party/bounds_checking_function/include", - "//base/security/permission/services/permission_lite/ipc_auth/include", - ] -} +import("../config.gni") -config("endpoint_internal") { - include_dirs = [ "../samgr/registry" ] -} +if (!enable_ohos_distributedschedule_samgr_lite_rpc_mini) { + config("endpoint_public") { + include_dirs = [ + "../samgr/adapter", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "//utils/native/lite/include", + "//foundation/communication/ipc_lite/interfaces/kits", + "//third_party/bounds_checking_function/include", + "//base/security/permission/services/permission_lite/ipc_auth/include", + ] + } -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 = [ - "_GNU_SOURCE", - "LITE_LINUX_BINDER_IPC", + config("endpoint_internal") { + include_dirs = [ "../samgr/registry" ] + } + + 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 = [ + "_GNU_SOURCE", + "LITE_LINUX_BINDER_IPC", + ] + } + + configs += [ ":endpoint_internal" ] + + public_configs = [ ":endpoint_public" ] + + public_deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//foundation/communication/ipc_lite:liteipc_adapter", + "//third_party/bounds_checking_function:libsec_shared", ] } - configs += [ ":endpoint_internal" ] + source_set("store_source") { + sources = [ "source/sa_store.c" ] - public_configs = [ ":endpoint_public" ] + cflags = [ + "-fPIC", + "-Wall", + ] - public_deps = [ - "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", - "//foundation/communication/ipc_lite:liteipc_adapter", - "//third_party/bounds_checking_function:libsec_shared", - ] -} + configs += [ ":endpoint_internal" ] -source_set("store_source") { - sources = [ "source/sa_store.c" ] + public_configs = [ ":endpoint_public" ] - cflags = [ - "-fPIC", - "-Wall", - ] + public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ] + } +} else { + defines = [ "MINI_SAMGR_LITE_RPC" ] + config("endpoint_public") { + include_dirs = [ + "../samgr/adapter", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "//utils/native/lite/include", + "//third_party/bounds_checking_function/include", + "//base/security/permission/services/permission_lite/ipc_auth/include", + ] + } + + config("endpoint_internal") { + include_dirs = [ + "./source", + "../samgr/registry", + "//foundation/distributedschedule/samgr_lite/samgr_server/source", + "//base/security/permission/interfaces/innerkits/permission_lite", + "//base/security/permission/services/permission_lite/pms_base/include", + ] + } + + source_set("endpoint_source") { + sources = [ + "source/client_factory.c", + "source/default_client_rpc.c", + "source/endpoint_rpc.c", + "source/token_bucket.c", + ] + + cflags = [ "-Wall" ] + + if (ohos_kernel_type == "linux") { + defines = [ + "_GNU_SOURCE", + "LITE_LINUX_BINDER_IPC", + ] + } - configs += [ ":endpoint_internal" ] + configs += [ ":endpoint_internal" ] - public_configs = [ ":endpoint_public" ] + public_configs = [ ":endpoint_public" ] - public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ] + public_deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_static", + "//foundation/communication/ipc/interfaces/innerkits/c/dbinder:dbinder", + ] + } + + source_set("store_source") { + sources = [ "source/sa_store.c" ] + + cflags = [ "-Wall" ] + + configs += [ ":endpoint_internal" ] + + public_configs = [ ":endpoint_public" ] + public_deps = [ + "//foundation/communication/ipc/interfaces/innerkits/c/dbinder:dbinder", + ] + } } diff --git a/samgr_endpoint/source/client_factory.c b/samgr_endpoint/source/client_factory.c index bbc7c43..a71ec43 100755 --- a/samgr_endpoint/source/client_factory.c +++ b/samgr_endpoint/source/client_factory.c @@ -109,7 +109,7 @@ 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); + int16 index = VECTOR_FindByKey(&g_factories, &key); if (index != INVALID_INDEX) { factory = VECTOR_At(&g_factories, index); } diff --git a/samgr_endpoint/source/default_client.h b/samgr_endpoint/source/default_client.h index 2da93f8..ef83e31 100755 --- a/samgr_endpoint/source/default_client.h +++ b/samgr_endpoint/source/default_client.h @@ -15,7 +15,10 @@ #ifndef LITE_DEFAULT_CLIENT_H #define LITE_DEFAULT_CLIENT_H +#ifndef MINI_SAMGR_LITE_RPC #include +#endif + #include "iunknown.h" #ifdef __cplusplus @@ -28,7 +31,14 @@ struct SaName { const char *service; const char *feature; }; + +#ifndef MINI_SAMGR_LITE_RPC IUnknown *SAMGR_CreateIProxy(const IpcContext *context, const char *service, const char *feature); +#else +IUnknown *SAMGR_CreateIProxy(const char *service, const char *feature); +IUnknown *SAMGR_CreateIRemoteProxy(const char *deviceId, const char *service, const char *feature); +#endif + SaName *SAMGR_GetSAName(const IUnknown *proxy); int SAMGR_CompareSAName(const SaName *key1, const SaName *key2); #ifdef __cplusplus diff --git a/samgr_endpoint/source/default_client_rpc.c b/samgr_endpoint/source/default_client_rpc.c new file mode 100755 index 0000000..fe317b9 --- /dev/null +++ b/samgr_endpoint/source/default_client_rpc.c @@ -0,0 +1,320 @@ +/* + * 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 +#include +#include "client_factory.h" +#include "dbinder_service.h" +#include "endpoint.h" +#include "ipc_skeleton.h" +#include "iproxy_client.h" +#include "memory_adapter.h" +#include "samgr_server.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; + uintptr_t saId; +}; + +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(void *ipcMsg, IpcIo *data, void *argv); +static SvcIdentity QueryIdentity(const char *service, const char *feature); +static SvcIdentity QueryRemoteIdentity(const char *deviceId, const char *service, const char *feature); +static const IClientEntry DEFAULT_ENTRY = {CLIENT_IPROXY_BEGIN, .Invoke = ProxyInvoke, IPROXY_END}; +static MutexId g_mutex = NULL; +static pthread_mutex_t g_handleMutex = PTHREAD_MUTEX_INITIALIZER; +static int32_t g_handle = 0; + +static int32_t GetNextHandle(void) +{ + pthread_mutex_lock(&g_handleMutex); + int32_t handle = ++g_handle; + pthread_mutex_unlock(&g_handleMutex); + return handle; +} + +IUnknown *SAMGR_CreateIProxy(const char *service, const char *feature) +{ + SvcIdentity identity = QueryIdentity(service, feature); + if (identity.handle == INVALID_INDEX) { + 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; + (void)AddDeathRecipient(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); +} + +IUnknown *SAMGR_CreateIRemoteProxy(const char* deviceId, const char *service, const char *feature) +{ + SvcIdentity identity = QueryRemoteIdentity(deviceId, service, feature); + + 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; + SaNode *saNode = GetSaNodeBySaName(service, feature); + if (saNode != NULL) { + header->saId = saNode->saId; + } + + IClientEntry *entry = &client->entry; + entry->iUnknown.Invoke = ProxyInvoke; + entry->iUnknown.AddRef = AddRef; + entry->iUnknown.Release = Release; + return GET_IUNKNOWN(*entry); +} + +SvcIdentity SAMGR_GetRemoteIdentity(const char *service, const char *feature) +{ + SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + IUnknown *iUnknown = SAMGR_FindServiceApi(service, feature); + if (iUnknown == NULL) { + return identity; + } + IClientProxy *proxy = NULL; + if (iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy) != EC_SUCCESS || proxy == NULL) { + return identity; + } + struct IDefaultClient *client = GET_OBJECT(proxy, struct IDefaultClient, entry.iUnknown); + identity = client->header.target; + proxy->Release((IUnknown *)proxy); + 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; + + IpcIo reply; + void *replyBuf = NULL; + MessageOption flag = (notify == NULL) ? TF_OP_ASYNC : TF_OP_SYNC; + HILOG_DEBUG(HILOG_MODULE_SAMGR, "%d %lu, %lu, saId: %d\n", header->target.handle, header->target.token, + header->target.cookie, header->saId); + IpcIo requestWrapper; + uint8_t *tmpData2 = (uint8_t *) malloc(MAX_IO_SIZE); + if (tmpData2 == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "malloc data for ipc io failed\n"); + return EC_INVALID; + } else { + IpcIoInit(&requestWrapper, tmpData2, MAX_IO_SIZE, MAX_OBJ_NUM); + } + WriteInt32(&requestWrapper, (int32_t)header->saId); + if (!IpcIoAppend(&requestWrapper, request)) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "ipc io append fail\n"); + return EC_INVALID; + } + int ret = SendRequest(header->target, funcId, &requestWrapper, &reply, flag, (uintptr_t *)&replyBuf); + FreeBuffer(tmpData2); + + if (notify != NULL) { + notify(owner, ret, &reply); + } + + if (replyBuf != NULL) { + FreeBuffer(replyBuf); + } + return ret; +} + +static int OnServiceExit(void *ipcMsg, IpcIo *data, void *argv) +{ + (void)data; + IClientHeader *header = (IClientHeader *)argv; + (void)RemoveDeathRecipient(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(ipcMsg); + } + HILOG_ERROR(HILOG_MODULE_SAMGR, "Miss the remote service<%u, %u>!", header->target.handle, header->target.token); + return EC_SUCCESS; +} + +static SvcIdentity QueryIdentity(const char *service, const char *feature) +{ + IpcIo req; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&req, data, MAX_DATA_LEN, 0); + WriteUint32(&req, RES_FEATURE); + WriteUint32(&req, OP_GET); + WriteString(&req, service); + WriteBool(&req, feature == NULL); + if (feature != NULL) { + WriteBool(&req, feature); + } + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = SendRequest(samgr, INVALID_INDEX, &req, &reply, TF_OP_SYNC, (uintptr_t *)&replyBuf); + int32_t sa_ret; + ret = (ret != EC_SUCCESS) ? EC_FAILURE : ReadInt32(&reply, &sa_ret); + SvcIdentity target = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; + if (sa_ret == EC_SUCCESS) { + ReadRemoteObject(&reply, &target); + } + if (ret == EC_PERMISSION) { + HILOG_INFO(HILOG_MODULE_SAMGR, "Cannot Access<%s, %s> No Permission!", service, feature); + } + if (replyBuf != NULL) { + FreeBuffer(replyBuf); + } + return target; +} + +static SvcIdentity QueryRemoteIdentity(const char *deviceId, const char *service, const char *feature) +{ + char saName[2 * MAX_NAME_LEN + 2]; + sprintf_s(saName, 2 * MAX_NAME_LEN + 2, "%s#%s", service?service:"", feature?feature:""); + HILOG_INFO(HILOG_MODULE_SAMGR, "saName %s, make remote binder start", saName); + + SvcIdentity target = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};; + SaNode *saNode = GetSaNodeBySaName(service, feature); + if (saNode == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "service: %s feature: %s have no saId in sa map", service, feature); + return target; + } + int32_t ret = MakeRemoteBinder(saName, strlen(saName), deviceId, strlen(deviceId), saNode->saId, 0, + &target); + if (ret != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "MakeRemoteBinder failed"); + return target; + } + target.handle = GetNextHandle(); + // todo: in l1, we should use ReadRemoteObject, because we should use IPC + extern void WaitForProxyInit(SvcIdentity *svc); + WaitForProxyInit(&target); + HILOG_ERROR(HILOG_MODULE_SAMGR, "MakeRemoteBinder sid handle=%d", target.handle); + return target; +} \ No newline at end of file diff --git a/samgr_endpoint/source/endpoint.h b/samgr_endpoint/source/endpoint.h index 1a55d12..d36c256 100755 --- a/samgr_endpoint/source/endpoint.h +++ b/samgr_endpoint/source/endpoint.h @@ -55,10 +55,18 @@ typedef enum OptionID { OP_ALL, } OptionID; typedef struct Endpoint Endpoint; + +#ifndef MINI_SAMGR_LITE_RPC typedef int (*RegisterEndpoint)(const IpcContext *context, SvcIdentity *identity); +#else +typedef int (*RegisterEndpoint)(SvcIdentity *identity, int token, const char *service, const char *feature); +#endif + struct Endpoint { const char *name; +#ifndef MINI_SAMGR_LITE_RPC IpcContext *context; +#endif Vector routers; ThreadId boss; uint32 deadId; diff --git a/samgr_endpoint/source/endpoint_rpc.c b/samgr_endpoint/source/endpoint_rpc.c new file mode 100755 index 0000000..da8f445 --- /dev/null +++ b/samgr_endpoint/source/endpoint_rpc.c @@ -0,0 +1,626 @@ +/* + * 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 + +#include "default_client.h" +#include "ipc_skeleton.h" +#include "iproxy_server.h" +#include "memory_adapter.h" +#include "policy_define.h" +#include "pthread.h" +#include "samgr_server.h" +#include "serializer.h" +#include "thread_adapter.h" + +typedef struct RemoteRegister RemoteRegister; +struct RemoteRegister { + MutexId mtx; + Endpoint *endpoint; + Vector clients; +}; + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "Samgr" +#define LOG_DOMAIN 0xD001800 + +#ifdef LITE_LINUX_BINDER_IPC +#define MAX_STACK_SIZE 0x100000 +#else +#define MAX_STACK_SIZE 0x1000 +#endif +#define MAX_OBJECT_NUM 5 +#define MAX_RETRY_TIMES 300 +#define RETRY_INTERVAL (50 * 1000) +#define MAX_REGISTER_RETRY_TIMES 10 +#define REGISTER_RETRY_INTERVAL 2 +#define MAX_POLICY_NUM 8 + +#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 int Dispatch(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option); +static void HandleIpc(const Request *request, const Response *response); +static int OnSamgrServerExit(void *ipcMsg, IpcIo *data, void *argv); +static int RegisterRemoteFeatures(Endpoint *endpoint); +static void Listen(Endpoint *endpoint, int token, const char *service, const char *feature); +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(SvcIdentity *identity, int token, const char *service, const char *feature); +static int RegisterIdentity(const SaName *saName, SvcIdentity *saInfo, + PolicyTrans **policy, uint32 *policyNum); +static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum); + +Endpoint *SAMGR_CreateEndpoint(const char *name, RegisterEndpoint registry) +{ + Endpoint *endpoint = SAMGR_Malloc(sizeof(Endpoint)); + if (endpoint == NULL) { + return NULL; + } + endpoint->deadId = INVALID_INDEX; + 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) +{ + printf("%s %d %d service: %s\n", __FUNCTION__ , __LINE__, pthread_self(), saName->service?saName->service:""); + if (endpoint == NULL || id == NULL || proxy == NULL || saName == NULL) { + return EC_INVALID; + } + printf("%s %d %d\n", __FUNCTION__ , __LINE__, pthread_self()); + //todo: handle version + IServerProxy *serverProxy = NULL; + proxy->QueryInterface(proxy, SERVER_PROXY_VER, (void *)&serverProxy); + if (serverProxy == NULL) { + } + printf("%s %d %d\n", __FUNCTION__ , __LINE__, pthread_self()); + // Lock the multi-write + int index = VECTOR_FindByKey(&endpoint->routers, proxy); + if (index != INVALID_INDEX) { + serverProxy->Release((IUnknown *)serverProxy); + } + printf("%s %d %d\n", __FUNCTION__ , __LINE__, pthread_self()); + Router *router = SAMGR_Malloc(sizeof(Router)); + if (router == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Memory is not enough! Identity<%d, %d>", + id->serviceId, id->featureId); + return EC_NOMEMORY; + } + printf("%s %d %d\n", __FUNCTION__ , __LINE__, pthread_self()); + 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; + } + printf("%s %d %d\n", __FUNCTION__ , __LINE__, pthread_self()); + Listen(endpoint, index, saName->service, saName->feature); + return index; +} + +int32 SAMGR_AddSysCap(const Endpoint *endpoint, const char *sysCap, BOOL isReg) +{ + if (endpoint == NULL) { + return EC_INVALID; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap begin"); + IpcIo req; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&req, data, MAX_DATA_LEN, 0); + WriteUint32(&req, RES_SYSCAP); + WriteUint32(&req, OP_PUT); + WriteBool(&req, sysCap); + WriteBool(&req, isReg); + + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = SendRequest(samgr, INVALID_INDEX, &req, &reply, + TF_OP_SYNC, (uintptr_t *)&replyBuf); + ret = -ret; + int32_t ipcRet = ret; + if (ret == EC_SUCCESS) { + ReadInt32(&reply, &ipcRet); + } + + if (replyBuf != NULL) { + FreeBuffer(replyBuf); + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap ret = %d", ipcRet); + + return ipcRet; +} + +int32 SAMGR_GetSysCap(const Endpoint *endpoint, const char *sysCap, BOOL *isReg) +{ + if (endpoint == NULL) { + return EC_INVALID; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap begin"); + IpcIo req; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&req, data, MAX_DATA_LEN, 0); + WriteUint32(&req, RES_SYSCAP); + WriteUint32(&req, OP_GET); + WriteBool(&req, sysCap); + + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = SendRequest(samgr, INVALID_INDEX, &req, &reply, + TF_OP_SYNC, (uintptr_t *)&replyBuf); + ret = -ret; + *isReg = FALSE; + int32_t ipcRet = ret; + if (ret == EC_SUCCESS) { + (void)ReadInt32(&reply, &ipcRet); + } + if (ipcRet == EC_SUCCESS) { + (void)ReadBool(&reply, (bool *)isReg); + } + if (replyBuf != NULL) { + FreeBuffer(replyBuf); + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap ret = %d", ipcRet); + return ipcRet; +} + +static int SendGetAllSysCapsRequest(const Endpoint *endpoint, uint32 startIdx, IpcIo *reply, void **replyBuf) +{ + IpcIo req; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&req, data, MAX_DATA_LEN, 0); + WriteUint32(&req, RES_SYSCAP); + WriteUint32(&req, OP_ALL); + WriteUint32(&req, startIdx); + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = SendRequest(samgr, INVALID_INDEX, &req, reply, + TF_OP_SYNC, (uintptr_t *)replyBuf); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SendGetAllSysCapsRequest startIdx:%d, ret:%d!", startIdx, ret); + return -ret; +} + +static int32 ParseGetAllSysCapsReply(IpcIo *reply, char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], + int32 *sysCapNum, BOOL *isEnd, uint32 *nextRequestIdx) +{ + int32_t ret; + if (ReadInt32(reply, &ret)) { + if (ret != EC_SUCCESS) { + *isEnd = TRUE; + return ret; + } + } else { + *isEnd = TRUE; + return EC_INVALID; + } + + (void)ReadBool(reply, (bool *)isEnd); + (void)ReadUint32(reply, nextRequestIdx); + uint32 size; + (void)ReadUint32(reply, &size); + size = ((size > MAX_SYSCAP_NUM) ? MAX_SYSCAP_NUM : size); + int cnt = *sysCapNum; + for (uint32 i = 0; i < size; i++) { + uint32 len = 0; + char *sysCap = (char *)ReadString(reply, (size_t *)&len); + if (sysCap == NULL || len == 0) { + continue; + } + if (strcpy_s(sysCaps[cnt], sizeof(sysCaps[cnt]), sysCap) != EC_SUCCESS) { + continue; + } + cnt++; + } + *sysCapNum = cnt; + + return ret; +} + +int32 SAMGR_GetSystemCapabilities(const Endpoint *endpoint, + char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], int32 *sysCapNum) +{ + if (sysCapNum == NULL) { + return EC_INVALID; + } + *sysCapNum = 0; + if (endpoint == NULL) { + return EC_INVALID; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities begin"); + IpcIo reply; + void *replyBuf = NULL; + uint32 startIdx = 0; + BOOL isEnd = TRUE; + int ret; + do { + ret = SendGetAllSysCapsRequest(endpoint, startIdx, &reply, &replyBuf); + if (ret == EC_SUCCESS) { + ret = ParseGetAllSysCapsReply(&reply, sysCaps, sysCapNum, &isEnd, &startIdx); + } + if (replyBuf != NULL) { + FreeBuffer(replyBuf); + } + } while (isEnd == FALSE && ret == EC_SUCCESS); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities ret = %d", ret); + return ret; +} + +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 = RegisterIdentity(saName, &saInfo, &policy, &policyNum); + if (ret != EC_SUCCESS || policy == NULL) { + SAMGR_Free(policy); + continue; + } + HILOG_INFO(HILOG_MODULE_SAMGR, "Register server sa<%s, %s> id<%lu, %u> retry:%d ret:%d!", + saName->service, saName->feature, saInfo.handle, saInfo.token, retry, ret); + ret = AddPolicyToRouter(endpoint, &saInfo, policy, policyNum); + SAMGR_Free(policy); + if (ret == EC_SUCCESS) { + break; + } + sleep(REGISTER_RETRY_INTERVAL); + } + return ret; +} + +static void Listen(Endpoint *endpoint, int index, const char *service, const char *feature) +{ + endpoint->registerEP(&endpoint->identity, index, service, feature); +} + +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 int Dispatch(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option) +{ + extern RemoteRegister g_remoteRegister; + Endpoint *endpoint = g_remoteRegister.endpoint; + uintptr_t saId = 0; + ReadInt32(data, &saId); + SaNode *saNode = GetSaNodeBySaId(saId); + if (saNode == NULL) { + HILOG_WARN(HILOG_MODULE_SAMGR, "get sa node by sa id %d is NULL", saId); + goto ERROR; + } + if (TB_CheckMessage(&endpoint->bucket) == BUCKET_BUSY) { + HILOG_WARN(HILOG_MODULE_SAMGR, "Flow Control <%u> is NULL", saNode->token); + goto ERROR; + } + + Router *router = VECTOR_At(&endpoint->routers, saNode->token); + if (router == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, saNode->token); + goto ERROR; + } + Response resp = {0}; + resp.data = endpoint; + Request request = {0}; + request.msgId = saNode->token; + request.data = data; + resp.reply = reply; + request.msgValue = code; + 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> is busy", + saNode->token, router->identity.serviceId, router->identity.featureId); + goto ERROR; + } + + return EC_SUCCESS; +ERROR: + return EC_INVALID; +} + +static void HandleIpc(const Request *request, const Response *response) +{ + Endpoint *endpoint = (Endpoint *)response->data; + Router *router = VECTOR_At(&endpoint->routers, request->msgId); + + router->proxy->Invoke(router->proxy, request->msgValue, NULL, request->data, response->reply); +} + +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 RegisterIdentity(const SaName *saName, SvcIdentity *saInfo, + PolicyTrans **policy, uint32 *policyNum) +{ + IpcIo req; + uint8 data[MAX_DATA_LEN]; + IpcIoInit(&req, data, MAX_DATA_LEN, 0); + WriteUint32(&req, RES_FEATURE); + WriteUint32(&req, OP_PUT); + WriteBool(&req, saName->service); + WriteBool(&req, saName->feature == NULL); + if (saName->feature != NULL) { + WriteBool(&req, saName->feature); + } + WriteUint32(&req, saInfo->token); + IpcIo reply; + void *replyBuf = NULL; + SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + int ret = SendRequest(samgr, INVALID_INDEX, &req, &reply, TF_OP_SYNC, + (uintptr_t *)&replyBuf); + ret = -ret; + int32_t ipcRet; + if (ret == EC_SUCCESS) { + ret = ReadInt32(&reply, &ipcRet); + } + if (ipcRet == EC_SUCCESS) { + SvcIdentity target; + (void)ReadRemoteObject(&reply, &target); + GetRemotePolicy(&reply, policy, policyNum); + } + if (replyBuf != NULL) { + FreeBuffer(replyBuf); + } + return ret; +} + +static int RegisterRemoteFeatures(Endpoint *endpoint) +{ + int nums = 0; + 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 = RegisterIdentity(&(router->saName), &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(SvcIdentity *identity, int token, const char *service, const char *feature) +{ + IpcObjectStub *objectStubOne = (IpcObjectStub *)calloc(1, sizeof(IpcObjectStub)); + if (objectStubOne == NULL) { + return -1; + } + objectStubOne->func = Dispatch; + objectStubOne->isRemote = true; + // handle is used by rpc, should be bigger than 0 + identity->handle = token + 1; + identity->cookie = objectStubOne; + // token is used by router index, should be itself, and save in SaNode + identity->token = token; + extern int AddEndpoint(SvcIdentity identity, const char *service, const char *feature); + AddEndpoint(*identity, service, feature); + return EC_SUCCESS; +} + +static int OnSamgrServerExit(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(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; + } + + SvcIdentity old = endpoint->identity; + while (endpoint->registerEP(&endpoint->identity, 0, "", "") != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Reconnect to samgr server failed!"); + usleep(RETRY_INTERVAL); + } + SvcIdentity new = endpoint->identity; + if (old.handle != new.handle || old.cookie != new.cookie || old.token != new.token) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Samgr server identity error!"); + exit(-1); + } + + SvcIdentity identity = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE}; + (void)RemoveDeathRecipient(identity, endpoint->deadId); + (void)AddDeathRecipient(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 void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum) +{ + if (reply == NULL) { + return; + } + uint32 i; + uint32 j; + ReadUint32(reply, policyNum); + 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++) { + if (ReadInt32(reply, &(*policy)[i].type)) { + switch ((*policy)[i].type) { + case RANGE: + ReadInt32(reply, &((*policy)[i].uidMin)); + ReadInt32(reply, &((*policy)[i].uidMax)); + break; + case FIXED: + for (j = 0; j < UID_SIZE; j++) { + ReadInt32(reply, &((*policy)[i].fixedUid[j])); + } + break; + case BUNDLENAME: + ReadInt32(reply, &((*policy)[i].fixedUid[0])); + break; + default: + break; + } + } + } +} + +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/sa_store.c b/samgr_endpoint/source/sa_store.c index b9dd423..d9851d4 100755 --- a/samgr_endpoint/source/sa_store.c +++ b/samgr_endpoint/source/sa_store.c @@ -18,6 +18,10 @@ #include "common.h" #include "memory_adapter.h" +#ifdef MINI_SAMGR_LITE_RPC +#include "samgr_server.h" +#endif + #define GROW_STEP 4 #define MAX_SA_NUM 300 static void FreeTreeNode(SAStore *saStore, ListNode *node); @@ -50,7 +54,12 @@ int SASTORA_Save(SAStore *saStore, const char *service, const char *feature, con if (saStore == NULL || service == NULL || identity == NULL) { return EC_INVALID; } - +#ifdef MINI_SAMGR_LITE_RPC + SaNode *saNode = GetSaNodeBySaName(service, feature); + if (saNode != NULL) { + saNode->token = identity->token; + } +#endif ListNode *curNode = FindServiceByName(saStore->root, service); FeatureNode *fNode = (curNode == NULL) ? NULL : curNode->info.head; fNode = FindFeatureByName(fNode, feature); @@ -90,6 +99,9 @@ int SASTORA_Save(SAStore *saStore, const char *service, const char *feature, con } curNode->info.handle = identity->handle; +#ifdef MINI_SAMGR_LITE_RPC + curNode->info.cookie = identity->cookie; +#endif curNode->info.head = NULL; curNode->next = saStore->root; saStore->root = curNode; @@ -209,7 +221,9 @@ SvcIdentity SASTORA_Find(SAStore *saStore, const char *service, const char *feat } identity.handle = curNode->info.handle; - +#ifdef MINI_SAMGR_LITE_RPC + identity.cookie = curNode->info.cookie; +#endif FeatureNode *featureNode = FindFeatureByName(curNode->info.head, feature); if (featureNode != NULL) { identity.token = featureNode->token; diff --git a/samgr_endpoint/source/sa_store.h b/samgr_endpoint/source/sa_store.h index d249281..19754fb 100755 --- a/samgr_endpoint/source/sa_store.h +++ b/samgr_endpoint/source/sa_store.h @@ -16,7 +16,13 @@ #define LITE_SA_STORE_H #include + +#ifndef MINI_SAMGR_LITE_RPC #include +#else +#include +#include +#endif #ifdef __cplusplus #if __cplusplus @@ -33,6 +39,9 @@ typedef struct PidHandle PidHandle; struct ServiceInfo { char name[MAX_NAME_LEN]; uint32 handle; +#ifdef MINI_SAMGR_LITE_RPC + uintptr_t cookie; +#endif FeatureNode *head; }; diff --git a/samgr_server/BUILD.gn b/samgr_server/BUILD.gn index 3e787e1..d55e743 100644 --- a/samgr_server/BUILD.gn +++ b/samgr_server/BUILD.gn @@ -11,31 +11,65 @@ # 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/samgr_lite/interfaces/kits/samgr", - "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", - "//utils/native/lite/include", - "//third_party/bounds_checking_function/include", - "//base/security/permission/interfaces/innerkits/permission_lite", - "//base/security/permission/services/permission_lite/pms_base/include", - "//foundation/communication/ipc_lite/frameworks/liteipc/include", - ] - - deps = [ "//foundation/distributedschedule/samgr_lite:ConfigFiles" ] - - public_deps = [ - "//foundation/communication/ipc_lite:liteipc_adapter", - "//foundation/distributedschedule/samgr_lite/samgr:samgr", - "//foundation/distributedschedule/samgr_lite/samgr_endpoint:store_source", - "//third_party/bounds_checking_function:libsec_shared", - ] +import("../config.gni") + +if (!enable_ohos_distributedschedule_samgr_lite_rpc_mini) { + shared_library("server") { + sources = [ "source/samgr_server.c" ] + + cflags = [ + "-fPIC", + "-Wall", + ] + + include_dirs = [ + "../samgr_endpoint/source", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "//utils/native/lite/include", + "//third_party/bounds_checking_function/include", + "//base/security/permission/interfaces/innerkits/permission_lite", + "//base/security/permission/services/permission_lite/pms_base/include", + "//foundation/communication/ipc_lite/frameworks/liteipc/include", + ] + + deps = [ "//foundation/distributedschedule/samgr_lite:ConfigFiles" ] + + public_deps = [ + "//foundation/communication/ipc_lite:liteipc_adapter", + "//foundation/distributedschedule/samgr_lite/samgr:samgr", + "//foundation/distributedschedule/samgr_lite/samgr_endpoint:store_source", + "//third_party/bounds_checking_function:libsec_shared", + ] + } +} else { + if (ohos_kernel_type == "liteos_m") { + static_library("server") { + defines = [ "MINI_SAMGR_LITE_RPC" ] + sources = [ "source/samgr_server_rpc.c" ] + + cflags = [ "-Wall" ] + + include_dirs = [ + "../samgr_endpoint/source", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "//utils/native/lite/include", + "//third_party/bounds_checking_function/include", + "//third_party/cJSON", + "//base/security/permission/interfaces/innerkits/permission_lite", + "//base/security/permission/services/permission_lite/pms_base/include", + ] + + deps = [ "//foundation/distributedschedule/samgr_lite:ConfigFiles" ] + + public_deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_static", + "//foundation/communication/ipc/interfaces/innerkits/c/dbinder:dbinder", + "//foundation/distributedschedule/samgr_lite/samgr:samgr", + "//foundation/distributedschedule/samgr_lite/samgr_endpoint:store_source", + "//third_party/bounds_checking_function:libsec_static", + ] + } + } } diff --git a/samgr_server/source/samgr_server.h b/samgr_server/source/samgr_server.h index 8bd419c..ed53f5d 100755 --- a/samgr_server/source/samgr_server.h +++ b/samgr_server/source/samgr_server.h @@ -20,6 +20,9 @@ #include "iproxy_server.h" #include "endpoint.h" #include "sa_store.h" +#ifdef MINI_SAMGR_LITE_RPC +#include "utils_list.h" +#endif #ifdef __cplusplus #if __cplusplus @@ -55,6 +58,17 @@ struct SysCapImpl { BOOL isRegister; }; +#ifdef MINI_SAMGR_LITE_RPC +typedef struct { + UTILS_DL_LIST list; + SaName saName; + uintptr_t saId; + int token; +} SaNode; +SaNode *GetSaNodeBySaName(const char *service, const char *feature); +SaNode *GetSaNodeBySaId(uintptr_t saId); +#endif + #ifdef __cplusplus #if __cplusplus } diff --git a/samgr_server/source/samgr_server_rpc.c b/samgr_server/source/samgr_server_rpc.c new file mode 100644 index 0000000..55f1cb4 --- /dev/null +++ b/samgr_server/source/samgr_server_rpc.c @@ -0,0 +1,730 @@ +/* + * 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 +#include +#include + +#include "cJSON.h" +#include "dbinder_service.h" +#include "default_client.h" +#include "ipc_skeleton.h" +#include "memory_adapter.h" +#include "policy_define.h" +#include "samgr_lite.h" +#include "securec.h" +#include "stdio.h" +#include "thread_adapter.h" +#include "utils_list.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 +#define UID_HAP 10000 +#define MAX_SYSCAP_NUM_PER_REPLY 118 + +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 void OnEndpointExit(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 int RegisterSamgrEndpoint(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 int ProcSysCap(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply); +static void ParseSysCap(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, + [RES_SYSCAP] = ProcSysCap, +}; + +static struct UTILS_DL_LIST g_saList; +pthread_mutex_t g_saMutex = PTHREAD_MUTEX_INITIALIZER; + +SaNode *GetSaNodeBySaName(const char *service, const char *feature) +{ + SaNode *node = NULL; + SaNode *retNode = NULL; + pthread_mutex_lock(&g_saMutex); + UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_saList, SaNode, list) + { + if (strncmp(node->saName.service, service, MAX_NAME_LEN) == 0) { + if (feature != NULL) { + if (strncmp(node->saName.feature, feature, MAX_NAME_LEN) == 0) { + retNode = node; + } + } else { + if (node->saName.feature == NULL) { + retNode = node; + } + } + break; + } + } + pthread_mutex_unlock(&g_saMutex); + return retNode; +} + +SaNode *GetSaNodeBySaId(uintptr_t saId) +{ + SaNode *node = NULL; + SaNode *retNode = NULL; + + pthread_mutex_lock(&g_saMutex); + UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_saList, SaNode, list) + { + if (node->saId == saId) { + retNode = node; + break; + } + } + pthread_mutex_unlock(&g_saMutex); + return retNode; +} + +void RpcStartSamgr(void) +{ + pthread_setname_np(pthread_self(), "rpc_server"); + SvcIdentity target = { + .cookie = 0 + }; + (void)SetContextObject(target); + + StartDBinderService(); +} + +int32_t GetSystemAbilityById(int32_t saId, IpcIo *reply) +{ + SaNode *saNode = GetSaNodeBySaId(saId); + if (saNode == NULL) { + return EC_FAILURE; + } + SvcIdentity sid = SASTORA_Find(&g_server.store, saNode->saName.service, saNode->saName.feature); + WriteRemoteObject(reply, &sid); + reply->bufferCur = reply->bufferBase; + return EC_SUCCESS; +} + +static const char *GetSysCapName(const SysCapImpl *serviceImpl) +{ + if (serviceImpl == NULL) { + return NULL; + } + return serviceImpl->name; +} + +static void InitializeGSaList() +{ + SaNode *saNode = (SaNode *)malloc(sizeof(SaNode)); + if (saNode == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "malloc samap failed"); + return; + } + saNode->saName.service = "mini_sa_rpc"; + saNode->saName.feature = NULL; + saNode->saId = 16; + UtilsListInit(&g_saList); + UtilsListAdd(&g_saList, &saNode->list); +} + +static void InitializeRegistry(void) +{ + printf("%s %d\n", __FUNCTION__ , __LINE__); + InitializeGSaList(); + g_server.mtx = MUTEX_InitValue(); + SASTORA_Init(&g_server.store); + g_server.samgr = SAMGR_CreateEndpoint("samgr", RegisterSamgrEndpoint); + SAMGR_GetInstance()->RegisterService((Service *)&g_server); + g_server.sysCapMtx = MUTEX_InitValue(); + g_server.sysCapabilitys = VECTOR_Make((VECTOR_Key)GetSysCapName, (VECTOR_Compare)strcmp); +} +SYS_SERVICE_INIT(InitializeRegistry); + +static BOOL CanRequest(const void *origin) +{ + return TRUE; +} + +static const char *GetName(Service *service) +{ + (void)service; + return SAMGR_SERVICE; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + //todo: move rpc here + 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_BUTT - 1, 0x4000, 20, SINGLE_TASK}; // Cannot use PRI_BUTT directly, so minus 1 + return config; +} + +static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply) +{ + SamgrServer *server = GET_OBJECT(iProxy, SamgrServer, iUnknown); + uint32_t resource; + ReadUint32(req, &resource); + int32_t option; + ReadInt32(req, &option); + if (server == NULL || 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); +} + +int AddEndpoint(SvcIdentity identity, const char *service, const char *feature) +{ + return SASTORA_Save(&g_server.store, service, feature, &identity); +} + +static int ProcEndpoint(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply) +{ + if (option != OP_POST) { + WriteInt32(reply, INVALID_INDEX); + return EC_FAILURE; + } + + pid_t pid = 0; + PidHandle handle; + MUTEX_Lock(server->mtx); + int index = SASTORA_FindHandleByPid(&g_server.store, pid, &handle); + if (index == INVALID_INDEX) { + SvcIdentity identity = {(int32)INVALID_INDEX, (uint32)INVALID_INDEX, (uint32)INVALID_INDEX}; +#ifdef __LINUX__ + IpcMsg* data = (IpcMsg*)origin; + if (data == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "Register Endpoint origin null pointer!"); + return EC_FAILURE; + } + identity.handle = data->target.handle; + BinderAcquire(g_server.samgr->context, identity.handle); +#endif + handle.pid = pid; + handle.uid = 0; + handle.handle = identity.handle; + handle.deadId = INVALID_INDEX; + (void)SASTORA_SaveHandleByPid(&server->store, handle); + (void)RemoveDeathRecipient(identity, handle.deadId); + (void)AddDeathRecipient(identity, OnEndpointExit, (void*)((uintptr_t)pid), &handle.deadId); + } + MUTEX_Unlock(server->mtx); + WriteUint32(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 *)ReadString(req, &len); + if (service == NULL || len == 0) { + WriteInt32(reply, EC_INVALID); + return EC_INVALID; + } + pid_t pid = 0; + uid_t uid = 0; + bool isFeature; + ReadBool(req, &isFeature); + + char *feature = NULL; + if (isFeature) { + feature = (char *)ReadString(req, &len); + } + MUTEX_Lock(server->mtx); + PidHandle handle; + int index = SASTORA_FindHandleByUidPid(&server->store, uid, pid, &handle); + if (index == INVALID_INDEX) { + MUTEX_Unlock(server->mtx); + HILOG_ERROR(HILOG_MODULE_SAMGR, "Endpoint[%d] is not register", pid); + WriteInt32(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); + WriteInt32(reply, EC_INVALID); + return EC_INVALID; + } + identity->token = ReadPointer(req); + identity->handle = (int32_t)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(server->mtx); + SAMGR_Free(policy); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "Remote Get Communication Strategy<%s, %s> No Permission<%d>!", + service, feature, ret); + WriteInt32(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) { + WriteInt32(reply, EC_INVALID); + return; + } + if (ret != EC_SUCCESS) { + WriteInt32(reply, ret); + return; + } + WriteInt32(reply, ret); + WriteRemoteObject(reply, identity); + WriteUint32(reply, policyNum); + uint32 i; + for (i = 0; i < policyNum; i++) { + WriteInt32(reply, policy[i].type); + switch (policy[i].type) { + case RANGE: + WriteInt32(reply, policy[i].uidMin); + WriteInt32(reply, policy[i].uidMax); + break; + case FIXED: + TransmitFixedPolicy(reply, policy[i]); + break; + case BUNDLENAME: + WriteInt32(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++) { + WriteInt32(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 *)ReadString(req, &len); + if (service == NULL || len == 0) { + WriteInt32(reply, EC_INVALID); + return EC_INVALID; + } + bool isFeature; + ReadBool(req, &isFeature); + char *feature = NULL; + if (isFeature) { + feature = (char *)ReadString(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 = 0, + .consumerUid = 0, + .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); + return isAuth; +} + +static int ProcFeature(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply) +{ + if (option != OP_PUT && option != OP_GET) { + WriteInt32(reply, EC_INVALID); + return EC_INVALID; + } + + if (g_server.ipcAuth == NULL) { + g_server.ipcAuth = GetIpcAuthInterface(); + } + if (g_server.ipcAuth == NULL) { + WriteInt32(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); + WriteInt32(reply, ret); + if (ret == EC_SUCCESS) { + WriteRemoteObject(reply, &identity); + } + } + return ret; +} + +static int32 ProcAddSysCap(SamgrServer *server, IpcIo *req) +{ + size_t len = 0; + char *sysCap = (char *)ReadString(req, &len); + if (sysCap == NULL || len == 0 || len > MAX_SYSCAP_NAME_LEN) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "ProcAddSysCap sysCap invalid"); + return EC_INVALID; + } + MUTEX_Lock(server->sysCapMtx); + Vector *sysCapablitys = &(server->sysCapabilitys); + int16 pos = VECTOR_FindByKey(sysCapablitys, (void *)sysCap); + if (pos < 0) { + MUTEX_Unlock(server->sysCapMtx); + return EC_FAILURE; + } + SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, pos); + if (serviceImpl == NULL) { + MUTEX_Unlock(server->sysCapMtx); + return EC_FAILURE; + } + serviceImpl->isRegister = TRUE; + MUTEX_Unlock(server->sysCapMtx); + return EC_SUCCESS; +} + +static BOOL ProcGetSysCap(SamgrServer *server, IpcIo *req) +{ + size_t len = 0; + char *sysCap = (char *)ReadString(req, &len); + if (sysCap == NULL || len == 0 || len > MAX_SYSCAP_NAME_LEN) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "ProcGetSysCap sysCap invalid"); + return FALSE; + } + MUTEX_Lock(server->sysCapMtx); + Vector *sysCapablitys = &(server->sysCapabilitys); + int16 pos = VECTOR_FindByKey(sysCapablitys, (void *)sysCap); + if (pos < 0) { + MUTEX_Unlock(server->sysCapMtx); + return FALSE; + } + SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, pos); + if (serviceImpl == NULL) { + MUTEX_Unlock(server->sysCapMtx); + return FALSE; + } + + BOOL res = (serviceImpl->isRegister == TRUE); + MUTEX_Unlock(server->sysCapMtx); + return res; +} + +static int32 GetReplyNumAndNextReqIdx(Vector *sysCapablitys, int32 startIdx, int32 *nextRequestIdx) +{ + int32 registerNum = 0; + int32 size = VECTOR_Num(sysCapablitys); + int32 i = startIdx; + for (; i < size && registerNum < MAX_SYSCAP_NUM_PER_REPLY; i++) { + SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, i); + if (serviceImpl->isRegister == FALSE) { + continue; + } + registerNum++; + } + *nextRequestIdx = i; + return registerNum; +} + +void ProcGetAllSysCap(SamgrServer *server, IpcIo *req, IpcIo *reply) +{ + uint32_t startIdx; + ReadUint32(req, &startIdx); + MUTEX_Lock(server->sysCapMtx); + Vector *sysCapablitys = &(server->sysCapabilitys); + int32 size = VECTOR_Num(sysCapablitys); + if (size == INVALID_INDEX) { + WriteInt32(reply, EC_FAILURE); + WriteBool(reply, TRUE); + WriteUint32(reply, startIdx); + WriteUint32(reply, 0); + MUTEX_Unlock(server->sysCapMtx); + return; + } + int32 nextRequestIdx = startIdx; + int32 replyNum = GetReplyNumAndNextReqIdx(sysCapablitys, startIdx, &nextRequestIdx); + HILOG_DEBUG(HILOG_MODULE_SAMGR, "ProcGetAllSysCap replyNum: %d, size: %d, startIdx: %d, nextRequestIdx: %d", + replyNum, size, startIdx, nextRequestIdx); + WriteInt32(reply, EC_SUCCESS); + // indicate is the last reply + WriteBool(reply, nextRequestIdx == size); + // indicate is the next start idx + WriteUint32(reply, nextRequestIdx); + WriteUint32(reply, replyNum); + int32 cnt = 0; + int32 i = startIdx; + for (; i < size && cnt < replyNum; i++) { + SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, i); + if (serviceImpl->isRegister == FALSE) { + continue; + } + WriteBool(reply, serviceImpl->name); + cnt++; + } + MUTEX_Unlock(server->sysCapMtx); +} + +static int ProcSysCap(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply) +{ + if (CanRequest(origin) == FALSE) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "ProcSysCap no permission"); + WriteInt32(reply, EC_PERMISSION); + return EC_PERMISSION; + } + if (option != OP_PUT && option != OP_GET && option != OP_ALL) { + WriteInt32(reply, EC_INVALID); + return EC_INVALID; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "ProcSysCap option: %d begin", option); + if (option == OP_PUT) { + int32 ret = ProcAddSysCap(server, req); + WriteInt32(reply, ret); + } else if (option == OP_GET) { + BOOL ret = ProcGetSysCap(server, req); + WriteInt32(reply, EC_SUCCESS); + WriteBool(reply, ret); + } else if (option == OP_ALL) { + ProcGetAllSysCap(server, req, reply); + } else { + HILOG_WARN(HILOG_MODULE_SAMGR, "ProcSysCap error option: %d", option); + WriteInt32(reply, EC_INVALID); + return EC_INVALID; + } + HILOG_DEBUG(HILOG_MODULE_SAMGR, "ProcSysCap end"); + return EC_SUCCESS; +} + +static int RegisterSamgrEndpoint(SvcIdentity* identity) +{ + identity->handle = SAMGR_HANDLE; + identity->token = SAMGR_TOKEN; + identity->cookie = SAMGR_COOKIE; + return EC_SUCCESS; +} + +static void OnEndpointExit(void* argv) +{ + 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; + } +#ifdef __LINUX__ + PidHandle handle; + int err = SASTORA_FindHandleByPid(&g_server.store, pid, &handle); + if (err != INVALID_INDEX) { + BinderRelease(context, handle.handle); + } +#endif + 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; +} + +static cJSON *GetJsonStream() +{ + const char *path = "/etc/system_capability.json"; + struct stat fileInfo; + int32_t size = 0; + + if (stat(path, &fileInfo) != 0 || (size = fileInfo.st_size) == 0) { + return NULL; + } + + int32_t fp = open(path, O_RDONLY, S_IRUSR); + if (fp < 0) { + return NULL; + } + + char *json = (char *)SAMGR_Malloc(size * sizeof(char)); + if (json == NULL) { + close(fp); + return NULL; + } + if (read(fp, json, size * sizeof(char)) != size * sizeof(char)) { + SAMGR_Free(json); + close(fp); + return NULL; + } + close(fp); + + cJSON *root = cJSON_Parse(json); + SAMGR_Free(json); + json = NULL; + return root; +} + +static void ParseSysCap(void) +{ + cJSON *root = GetJsonStream(); + if (root == NULL) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "ParseSysCap GetJsonStream failed!"); + return; + } + cJSON *sysCaps = cJSON_GetObjectItem(root, "systemCapability"); + if (!cJSON_IsArray(sysCaps)) { + cJSON_Delete(root); + HILOG_ERROR(HILOG_MODULE_SAMGR, "ParseSysCap format failed!"); + return; + } + int32_t size = cJSON_GetArraySize(sysCaps); + int32_t sysCapNum = 0; + for (int32_t i = 0; i < size; i++) { + if (sysCapNum >= MAX_SYSCAP_NUM) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "ParseSycCapMap system capability exceed"); + break; + } + cJSON *item = cJSON_GetArrayItem(sysCaps, i); + if (!cJSON_IsObject(item)) { + continue; + } + cJSON *name = cJSON_GetObjectItem(item, "name"); + cJSON *isRegister = cJSON_GetObjectItem(item, "register-on-startup"); + if (!cJSON_IsString(name) || !cJSON_IsBool(isRegister)) { + continue; + } + char *nameStr = cJSON_GetStringValue(name); + if (VECTOR_FindByKey(&(g_server.sysCapabilitys), nameStr) != INVALID_INDEX) { + HILOG_WARN(HILOG_MODULE_SAMGR, "Duplicate system capability %s register!", nameStr); + continue; + } + SysCapImpl *impl = (SysCapImpl *)SAMGR_Malloc(sizeof(SysCapImpl)); + if (impl == NULL) { + continue; + } + if (strcpy_s(impl->name, sizeof(impl->name), cJSON_GetStringValue(name)) != EC_SUCCESS) { + SAMGR_Free(impl); + continue; + } + impl->isRegister = cJSON_IsTrue(isRegister); + if (VECTOR_Add(&(g_server.sysCapabilitys), impl) == INVALID_INDEX) { + SAMGR_Free(impl); + HILOG_ERROR(HILOG_MODULE_SAMGR, "system capability %s register failed!", impl->name); + continue; + } + sysCapNum++; + } + cJSON_Delete(root); +} -- Gitee