往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)
✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✏️ 记录一场鸿蒙开发岗位面试经历~
✏️ 持续更新中……
前言
在上篇博客中已经分析了discovery_service.h头文件,在这个头文件中声明了与设备服务发布相关功能和数据结构。
服务发布
discovery_service.c实现了轻量级设备端的服务发布功能。 首先它的入口函数为PublishService
,这个函数实现服务发布的总流程。 服务发布函数关系已经在 discover_service.c函数调用关系 给出了图示。
首先介绍发布模块的结构信息,它包含服务模块的属性:
/*
发布模块结构
publishId : 服务发布ID
medium : 服务发布的媒介(wifi 蓝牙..)
capabilityBitmap : 对应的功能位图
capabilityData : 服务发布的功能数据
dataLength : 数据长度
*/
typedef struct {
char package[MAX_PACKAGE_NAME];
int publishId;
unsigned short medium;
unsigned short capabilityBitmap;
char *capabilityData;
unsigned short dataLength;
unsigned short used;
} PublishModule;
下面从入口函数开始分析代码 PublishService
/*
函数功能: 发布服务
函数参数:
moduleName :
info : 发布的服务信息
IPublishCallback: 服务发布成功或者失败的回调函数 发布成功后会创建会话,等待发现端连接
函数返回值: 成功返回0,否则返回非零
详细:
1.检查权限和参数是否满足条件
2.检查moduleName和发布信息中id 和数据长度是否满足条件
3.如果上述条件不满足条件,调用发布失败回调函数
4.初始化发布锁, 之后的任何失败都会调用发布失败的回调函数,并且打印失败信息
5.加锁, 因为发布过程中的会改变很多共享变量,如:g_publishModule 所以需要保持发布的互斥性。使得服务只能一个一个的先后发布
6.初始化服务,这个过程初始化发布服务所需的功能,比如为发布模块,发布服务数据,coap初始化等
7.添加发布模块,所有的已发布服务的信息都存储在g_publishModule,所以需要判断能否添加一个服务模块
8.注册服务,如果没有提供详细的服务, 就注册默认服务,否则注册提供的服务
9.释放锁
10.注册成功就调用发布成功的回调函数
*/
int PublishService(const char *moduleName, const struct PublishInfo *info, const struct IPublishCallback *cb)
{
//检查权限和参数是否满足条件
if (SoftBusCheckPermission(SOFTBUS_PERMISSION) != 0 || info == NULL || cb == NULL) {
SOFTBUS_PRINT("[DISCOVERY] PublishService invalid para(info or cb)\n");
return ERROR_INVALID;
}
//检查moduleName和发布信息中id和数据长度是否满足条件
if (moduleName == NULL || strlen(moduleName) >= MAX_PACKAGE_NAME || info->publishId <= 0 ||
info->dataLen > MAX_CAPABILITY_DATA_LEN) {
SOFTBUS_PRINT("[DISCOVERY] PublishService invliad para\n");
//调用 服务发布的回调函数 失败
PublishCallback(info->publishId, PUBLISH_FAIL_REASON_PARAMETER_INVALID, NULL, cb);
return ERROR_INVALID;
}
//当前media只支持WIFI -COAP
if (info->medium != COAP) {
PublishCallback(info->publishId, PUBLISH_FAIL_REASON_NOT_SUPPORT_MEDIUM, NULL, cb);
return ERROR_INVALID;
}
//锁没有初始化
if (g_discoveryMutex == NULL) {
//初始化锁
g_discoveryMutex = MutexInit();
if (g_discoveryMutex == NULL) {
PublishCallback(info->publishId, PUBLISH_FAIL_REASON_UNKNOWN, NULL, cb);
return ERROR_FAIL;
}
}
//保证发布过程的原子性
MutexLock(g_discoveryMutex);
//初始化服务
if (InitService() != ERROR_SUCCESS) {
SOFTBUS_PRINT("[DISCOVERY] PublishService InitService fail\n");
PublishCallback(info->publishId, PUBLISH_FAIL_REASON_UNKNOWN, NULL, cb);
MutexUnlock(g_discoveryMutex);
return ERROR_FAIL;
}
// 添加成功返回添加之后相应g_publishModule中模块
PublishModule *findModule = AddPublishModule(moduleName, info);
//添加失败
if (findModule == NULL) {
SOFTBUS_PRINT("[DISCOVERY] PublishService AddPublishModule fail\n");
PublishCallback(info->publishId, PUBLISH_FAIL_REASON_UNKNOWN, NULL, cb);
MutexUnlock(g_discoveryMutex);
return ERROR_FAIL;
}
//功能为空或者没有功能数据为空
int ret = ERROR_SUCCESS;
if (info->capability == NULL || info->capabilityData == NULL) {
(void)CoapRegisterDefualtService(); //注册默认服务
} else {
//注册相应的服务,也是更新了所提供给的服务
ret = DoRegistService(info->medium);
}
//释放锁
MutexUnlock(g_discoveryMutex);
//注册失败
if (ret != ERROR_SUCCESS) {
//调用失败回调函数
PublishCallback(info->publishId, PUBLISH_FAIL_REASON_UNKNOWN, findModule, cb);
return ERROR_FAIL;
} else {
//调用发布成功回调函数
PublishCallback(info->publishId, ERROR_SUCCESS, findModule, cb);
return ERROR_SUCCESS;
}
}
在UnPublishService
实现了取消已经发布的服务的功能。 与发布服务函数是discovery_service.c两个主要的函数:
/*
函数功能:取消已经发布的服务
函数参数:
moduleName : 模块名
publishId : 发布id
函数返回值: 成功返回0,否则非零
详细:
1.检查权限和发布id,模块名,发布锁参数
2.加锁,与发布服务一样,同样保持互斥性
3. 通过moduleName,publishId找到相应的模块
4. 释放存储功能数据的空间,并且将相应的发布模块属性置为0
5. 删除之后,重新注册服务,更新提供的服务
5.释放锁
*/
int UnPublishService(const char* moduleName, int publishId)
{
//检查权限
if (SoftBusCheckPermission(SOFTBUS_PERMISSION) != 0) {
SOFTBUS_PRINT("[DISCOVERY] No permission\n");
return ERROR_FAIL;
}
//检查各参数
if (moduleName == NULL || publishId <= 0 || g_discoveryMutex == NULL) {
SOFTBUS_PRINT("[DISCOVERY] UnPublishService invliad para\n");
return ERROR_INVALID;
}
MutexLock(g_discoveryMutex); //加锁
//返回要找的模块
PublishModule *findModule = FindExistModule(moduleName, publishId);
//如果没有相应的服务模块
if (findModule == NULL) {
SOFTBUS_PRINT("[DISCOVERY] UnPublishService get module fail\n");
MutexUnlock(g_discoveryMutex);
return ERROR_NONEXIST;
}
//释放存储功能服务数据的空间
if (findModule->capabilityData != NULL) {
free(findModule->capabilityData);
}
//将该服务模块重置为0 ,used = 0
unsigned short medium = findModule->medium;
memset_s(findModule, sizeof(PublishModule), 0, sizeof(PublishModule));
//删除之后,重新注册服务,更新了提供的服务
int ret = DoRegistService(medium);
if (ret != ERROR_SUCCESS) {
SOFTBUS_PRINT("[DISCOVERY] UnPublishService DoRegistService fail, error = %d\n", ret);
MutexUnlock(g_discoveryMutex);
return ret;
}
MutexUnlock(g_discoveryMutex);
SOFTBUS_PRINT("[DISCOVERY] UnPublishService ok\n");
return ret;
}
总结
本文分析了发布服务函数和取消已发布服务函数,它们所调用其他功能函数在之后进行分析。