feat: samgr_lite适配轻量系统rpc

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 <likailong@huawei.com>
This commit is contained in:
SimonLi 2022-02-14 00:09:47 +08:00
parent d86c0aea95
commit 53d581e9c3
24 changed files with 2167 additions and 111 deletions

View File

@ -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") {

View File

@ -27,7 +27,6 @@
"deps": {
"components": [
"utils_base",
"ipc_lite",
"hilog_lite"
],
"third_party": [

View File

@ -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",

View File

@ -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
}

View File

@ -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
}

View File

@ -116,6 +116,9 @@ struct Response {
void *data;
/** Data length */
int16 len;
#ifdef MINI_SAMGR_LITE_RPC
void *reply;
#endif
};
#pragma pack()

View File

@ -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.
*

View File

@ -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",
]
}
}
}

View File

@ -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",

View File

@ -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" ]
}
}

View File

@ -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

View File

@ -11,7 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
source_set("client") {
import("../config.gni")
if (!enable_ohos_distributedschedule_samgr_lite_rpc_mini) {
source_set("client") {
sources = [ "source/remote_register.c" ]
cflags = [
@ -25,12 +28,37 @@ source_set("client") {
"//foundation/distributedschedule/samgr_lite/interfaces/kits/registry",
"//utils/native/lite/include",
"//third_party/bounds_checking_function/include",
"//base/security/permission/services/permission_lite/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"
"//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",
]
}
}

View File

@ -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 <ohos_errno.h>
#include <ohos_init.h>
#include <log.h>
#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();
}

View File

@ -11,7 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
config("endpoint_public") {
import("../config.gni")
if (!enable_ohos_distributedschedule_samgr_lite_rpc_mini) {
config("endpoint_public") {
include_dirs = [
"../samgr/adapter",
"//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr",
@ -21,13 +24,13 @@ config("endpoint_public") {
"//third_party/bounds_checking_function/include",
"//base/security/permission/services/permission_lite/ipc_auth/include",
]
}
}
config("endpoint_internal") {
config("endpoint_internal") {
include_dirs = [ "../samgr/registry" ]
}
}
source_set("endpoint_source") {
source_set("endpoint_source") {
sources = [
"source/client_factory.c",
"source/default_client.c",
@ -56,9 +59,9 @@ source_set("endpoint_source") {
"//foundation/communication/ipc_lite:liteipc_adapter",
"//third_party/bounds_checking_function:libsec_shared",
]
}
}
source_set("store_source") {
source_set("store_source") {
sources = [ "source/sa_store.c" ]
cflags = [
@ -71,4 +74,67 @@ source_set("store_source") {
public_configs = [ ":endpoint_public" ]
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" ]
public_configs = [ ":endpoint_public" ]
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",
]
}
}

View File

@ -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);
}

View File

@ -15,7 +15,10 @@
#ifndef LITE_DEFAULT_CLIENT_H
#define LITE_DEFAULT_CLIENT_H
#ifndef MINI_SAMGR_LITE_RPC
#include <liteipc_adapter.h>
#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

View File

@ -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 <log.h>
#include <ohos_errno.h>
#include <pthread.h>
#include <string.h>
#include <service_registry.h>
#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;
}

View File

@ -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;

View File

@ -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 <log.h>
#include <ohos_errno.h>
#include <securec.h>
#include <service.h>
#include <stdlib.h>
#include <unistd.h>
#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;
}

View File

@ -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;

View File

@ -16,7 +16,13 @@
#define LITE_SA_STORE_H
#include <ohos_types.h>
#ifndef MINI_SAMGR_LITE_RPC
#include <liteipc_adapter.h>
#else
#include <serializer.h>
#include <unistd.h>
#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;
};

View File

@ -11,7 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
shared_library("server") {
import("../config.gni")
if (!enable_ohos_distributedschedule_samgr_lite_rpc_mini) {
shared_library("server") {
sources = [ "source/samgr_server.c" ]
cflags = [
@ -38,4 +41,35 @@ shared_library("server") {
"//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",
]
}
}
}

View File

@ -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
}

View File

@ -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 <fcntl.h>
#include <log.h>
#include <ohos_errno.h>
#include <ohos_init.h>
#include <ohos_types.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#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);
}