OpenHarmony轻量系统服务管理|samgr_server功能详解(三)

函数实现详解

相关实现代码位于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;
}
相关推荐
高心星5 小时前
HarmonyOS 5.0应用开发——MVVM模式的应用
harmonyos·mvvm·鸿蒙5.0·备忘录应用
别说我什么都不会5 小时前
【仓颉三方库】工具类—— compress4cj
harmonyos
别说我什么都不会5 小时前
【仓颉三方库】工具类—— uuid4cj
harmonyos
__Benco12 小时前
OpenHarmony - 小型系统内核(LiteOS-A)(十),魔法键使用方法,用户态异常信息说明
人工智能·harmonyos
念风12 小时前
移植Tensorflow Lite Micro源码到ArmClang Cortex-M
嵌入式
NapleC1 天前
HarmonyOS:一多能力介绍:一次开发,多端部署
华为·harmonyos
我爱学习_zwj1 天前
【鸿蒙HarmonyOS】深入理解router与Navigation
华为·harmonyos
NapleC1 天前
HarmonyOS:1.7
harmonyos
鸿蒙布道师1 天前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei