函数实现详解
相关实现代码位于distributedschedule_samgr_lite\samgr_server\source\samgr_server.c
。上一篇分析了处理feature
资源类型的函数,而它的处理又因为操作类型的不同而调用不同的函数。本篇文章接着继续分析。
处理操作类型为PUT的feature处理函数
scss
/*
函数功能:向SamgrServer注册feature
函数参数:@server:SamgrServer
@origin:请求消息数据
@req:请求IO
@reply:响应IO
@identity:通信地址标识
函数描述:首先从请求消息中获取请求者的服务名称、功能名称和进程号。
然后在系统功能存储中根据进程号查询该进程的endpoint是否已注册,若未注册则返回EC_NOSERVICE。
若该endpoint已注册,则继续查询与该服务和功能是否注册。然后更新identity的值,并注册到satore中。
再查询调用接口对应的访问策略,将访问策略等信息作为响应消息发送给调用者。
*/
static int32 ProcPutFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity)
{
size_t len = 0;
//从req中获取service的name及长度
char *service = (char *)IpcIoPopString(req, &len);
if (service == NULL || len == 0) {
//数据不合法,向请求者发送EC_INVALID响应
IpcIoPushInt32(reply, EC_INVALID);
return EC_INVALID;
}
//从请求信息中获取请求者的进程ID号
pid_t pid = GetCallingPid(origin);
//获取一个BOOL值,该BOOL值标识feature是否为NULL
//若不为NULL,则继续读取一个string消息,获取feature的name和长度
char *feature = IpcIoPopBool(req) ? NULL : (char *)IpcIoPopString(req, &len);
MUTEX_Lock(server->mtx);
PidHandle handle;
//根据进程ID在store的maps中查找对应的PidHandle,由handle返回,并返回其对应的下标
int index = SASTORA_FindHandleByPid(&server->store, pid, &handle);
if (index == INVALID_INDEX) {
//若不存在,则说明请求者所在进程的endpoint未在主endpoint中注册。
MUTEX_Unlock(server->mtx);
//记录错误日志,并发送EC_NOSERVICE响应
HILOG_ERROR(HILOG_MODULE_SAMGR, "Endpoint[%d] is not register", pid);
IpcIoPushInt32(reply, EC_NOSERVICE);
return EC_NOSERVICE;
}
//请求者所在进程的endpoint已注册,对应的PidHandle对象存在
//根据服务名和功能名查询相应的handle和token,若找到则返回对应的值,若未找到则返回无效值
*identity = SASTORA_Find(&server->store, service, feature);
if (identity->handle != INVALID_INDEX && identity->handle != handle.handle) {
//参数检查,若返回的identity对象的handle值与PidHandle对象的handle不一致,即maps中存储的和listnode中的信息不对应
//则发送EC_INVALID响应
MUTEX_Unlock(server->mtx);
IpcIoPushInt32(reply, EC_INVALID);
return EC_INVALID;
}//返回的identity是一个无效值,即该服务未注册
//从req中获取token值
identity->token = IpcIoPopUint32(req);
identity->handle = handle.handle;
PolicyTrans *policy = NULL;
//注册需要的参数信息,包括服务名,功能名,用户ID,进程ID
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) {
//查询失败,释放policy资源,并发送EC_PERMISSION响应
MUTEX_Unlock(server->mtx);
SAMGR_Free(policy);
HILOG_DEBUG(HILOG_MODULE_SAMGR, "Remote Get Communication Strategy<%s, %s> No Permission<%d>!",
service, feature, ret);
IpcIoPushInt32(reply, EC_PERMISSION);
return EC_PERMISSION;
}
//将identity中的handle和token注册到saStore中
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;
}
DD一下: 欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。
erlang
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案)
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......
发送访问策略
php
/*
函数功能:将访问策略作为响应消息发送给调用者
函数参数:@ret:标识feature是否注册成功
@identity:IPC通信地址标识
@reply:响应消息IO
@policy:访问策略集合
@policyNum:访问策略数目
函数描述:负责将feature注册情况、通信地址标识和访问策略等信息作为响应消息,发送给调用者。
*/
static void TransmitPolicy(int ret, const SvcIdentity* identity, IpcIo *reply,
const PolicyTrans *policy, uint32 policyNum)
{
if (identity == NULL || reply == NULL || policy == NULL) {
//参数检查,参数无效,发送EC_INVALID响应
IpcIoPushInt32(reply, EC_INVALID);
return;
}
if (ret != EC_SUCCESS) {
//注册失败,发送错误响应
IpcIoPushInt32(reply, ret);
return;
}
//注册成功,发送EC_SUCCESS响应
IpcIoPushInt32(reply, ret);
//将identity作为消息,发送响应
IpcIoPushSvc(reply, identity);
//发送policyNum数目
IpcIoPushUint32(reply, policyNum);
uint32 i;
//遍历所有的访问策略,发送给调用者
for (i = 0; i < policyNum; i++) {
//发送policy的类型,类型包含RANGE,FIXED,BUNDLENAME
IpcIoPushInt32(reply, policy[i].type);
//根据不同类型,发送不同的后续消息
switch (policy[i].type) {
case RANGE://允许某个特定范围UID的进程访问,指定uidMin和uidMax
IpcIoPushInt32(reply, policy[i].uidMin);
IpcIoPushInt32(reply, policy[i].uidMax);
break;
case FIXED:
//允许指定的几个UID的进程访问,指定fixedUid,最多配置8个
TransmitFixedPolicy(reply, policy[i]);
break;
case BUNDLENAME://只允许特定的应用访问,需要指定bundleName(包名)
IpcIoPushInt32(reply, policy[i].fixedUid[0]);
break;
default:
break;
}
}
}
发送fixed类型的访问策略
ini
//发送FIXED类型的policy,指定fixedUid
static void TransmitFixedPolicy(IpcIo *reply, PolicyTrans policy)
{
if (reply == NULL) {
return;
}
uint32 i;
//遍历,填充消息
for (i = 0; i < UID_SIZE; i++) {
IpcIoPushInt32(reply, policy.fixedUid[i]);
}
}
处理操作类型为GET的feature处理函数
scss
/*
函数功能:向SamgrServer查询指定服务名和功能名的IPC通信地址SvcIdentity
函数参数:@server:SamgrServer
@origin:请求消息数据
@req:请求IO
@reply:响应IO
@identity:通信地址标识
函数描述:从req中获取待查询的服务名和功能名,然后在satore中查找该服务和功能是否注册。
若未注册则返回EC_NOSERVICE,若已注册则获取对应的Pidhandle,查询是否有权限调用本进程的接口。
*/
static int32 ProcGetFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity)
{
size_t len = 0;
//从req中获取service的name和长度
char *service = (char *)IpcIoPopString(req, &len);
if (service == NULL || len == 0) {
//请求数据不合法,发送EC_INVALID响应
IpcIoPushInt32(reply, EC_INVALID);
return EC_INVALID;
}
//获取一个BOOL值,该BOOL值标识feature是否为NULL
//若不为NULL,则继续读取一个string消息,赋值给feature
char *feature = IpcIoPopBool(req) ? NULL : (char *)IpcIoPopString(req, &len);
MUTEX_Lock(server->mtx);
//根据service和feature获取相应的handle和token,保存到identity中返回
*identity = SASTORA_Find(&server->store, service, feature);
if (identity->handle == INVALID_INDEX) {
//未找到对应的服务名,则对应的feature也不存在
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;
}//查询到对应的服务信息
//根据服务名对应的handle,查找store中对应的PidHandle
//查找成功返回相应的PidHandle,失败返回一个INVALID_INDEX的PidHandle
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;
}//找到对应的PidHandle对象
//参数信息
AuthParams authParams = {
.providerService = service,//指定提供者的服务
.providerfeature = feature,//指定提供者的功能
.consumerPid = GetCallingPid(origin),//指定消费者的进程号,即向这个服务发起请求的进程
.consumerUid = GetCallingUid(origin),//指定消费者的用户id,即向这个服务发起请求的用户id
.providerPid = providerPid.pid,//提供者进程号
.providerUid = providerPid.uid//提供者用户号
};
//查询是否有权限调用本进程的接口
int isAuth = g_server.ipcAuth->IsCommunicationAllowed(authParams);
HILOG_DEBUG(HILOG_MODULE_SAMGR, "Judge Auth<%s, %s> ret:%d", service, feature, isAuth);
//若有权限,则添加服务访问
int32 ret = (isAuth == EC_SUCCESS) ? AddServiceAccess(*identity, GetCallingTid(origin)) : EC_PERMISSION;
HILOG_DEBUG(HILOG_MODULE_SAMGR, "Find Feature<%s, %s> id<%d, %d> ret:%d",
service, feature, identity->handle, identity->token, ret);
return ret;
}