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

往期知识点记录:

函数实现详解

相关实现代码位于distributedschedule_samgr_lite\samgr_server\source\samgr_server.c。上一篇分析了处理feature资源类型的函数,而它的处理又因为操作类型的不同而调用不同的函数。本篇文章接着继续分析。

处理操作类型为PUT的feature处理函数
/*
    函数功能:向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;
}
发送访问策略
/*
    函数功能:将访问策略作为响应消息发送给调用者
    函数参数:@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类型的访问策略
//发送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处理函数
/*
    函数功能:向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;
}

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请看下图提示:
    在这里插入图片描述
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值