分布式软总线组网流程源码解析(一)
系统开机
分布式软总线在开机的时候,系统会直接调用onstart()函数,实现如下:
void SoftBusServer::OnStart()
{
COMM_LOGI(COMM_SVC, "SoftBusServer OnStart called!");
InitSoftBusServer();
if (!Publish(this)) {
COMM_LOGE(COMM_SVC, "SoftBusServer publish failed!");
}
IPCSkeleton::SetMaxWorkThreadNum(SOFTBUS_IPC_THREAD_NUM);
}
初始化软总线配置
这个里面调用的InitSoftBusServer()函数就是初始化软总线的配置的,这个函数内部实现像LnnInitMonitorInit()、InitServicesAndModules()、
void InitSoftBusServer(void)
{
SoftbusConfigInit();//初始化软总线配置系统
LnnInitMonitorInit();//初始化LNN(局域网)初始化监控器
if (ServerStubInit() != SOFTBUS_OK) { //初始化默认返回SOFTBUS_OK,运行时覆盖,本函数用于建立IPC通道
COMM_LOGE(COMM_SVC, "server stub init failed.");
return;
}
if (SoftBusTimerInit() != SOFTBUS_OK) { //定时器系统
COMM_LOGE(COMM_SVC, "softbus timer init failed.");
return;
}
if (LooperInit() != SOFTBUS_OK) { //事件循环系统
COMM_LOGE(COMM_SVC, "softbus looper init failed.");
return;
}
if (InitDdos() != SOFTBUS_OK) { //安全防护系统
COMM_LOGE(COMM_SVC, "softbus ddos init failed.");
}
//核心服务与模块初始化
int32_t ret = InitServicesAndModules();
if (ret != SOFTBUS_OK) {
ServerModuleDeinit();//初始化失败会清除已初始化模块
COMM_LOGE(COMM_SVC, "softbus framework init failed, err = %{public}d", ret);
return;
}
ret = SoftBusBtInit();
if (ret != SOFTBUS_OK) {
LnnInitModuleReturnSet(INIT_DEPS_BLUETOOTH, ret);
LnnInitModuleStatusSet(INIT_DEPS_BLUETOOTH, DEPS_STATUS_FAILED);
ServerModuleDeinit();
COMM_LOGE(COMM_SVC, "softbus bt init failed, err = %{public}d", ret);
return;
}
LnnInitModuleStatusSet(INIT_DEPS_BLUETOOTH, DEPS_STATUS_SUCCESS);
LnnModuleInitMonitorCheckStart();
g_isInit = true; //初始化成功标志
COMM_LOGI(COMM_SVC, "softbus framework init success.");
}
这里面最后一段的蓝牙初始化特殊些,因为他集成了LNN监控机制
LnnInitModuleReturnSet/LnnInitModuleStatusSet:向 LNN 初始化监控器报告蓝牙模块的初始化状态和错误码LnnModuleInitMonitorCheckStart:检查所有依赖模块是否都已成功初始化,如果是则触发后续的组网流程
整体初始化流程图
InitSoftBusServer()
│
├─ SoftbusConfigInit() ← 配置
├─ LnnInitMonitorInit() ← 监控器
├─ ServerStubInit() ← IPC桩 (失败→退出)
├─ SoftBusTimerInit() ← 定时器 (失败→退出)
├─ LooperInit() ← 事件循环 (失败→退出)
├─ InitDdos() ← DDOS防护 (失败→仅日志)
│
├─ InitServicesAndModules() ← 核心服务链 (失败→清理退出)
│ ├─ ConnServerInit ← 连接
│ ├─ AuthInit ← 认证
│ ├─ DiscServerInit ← 发现
│ ├─ BusCenterServerInit ← 组网
│ ├─ TransServerInit ← 传输
│ ├─ WifiDirect / BleDirect ← 直连
│ └─ DFX ← 可维护性
│
├─ SoftBusBtInit() ← 蓝牙 (失败→清理退出+状态上报)
│
└─ g_isInit = true ← 完成
核心模块初始化顺序
上面的InitServicesAndModules()初始化函数的初始化顺序是严格依照依赖顺序实现,
static int32_t InitServicesAndModules(void)
{
if (ConnServerInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus conn server init failed.");
return SOFTBUS_CONN_SERVER_INIT_FAILED;
}
if (AuthInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus auth init failed.");
return SOFTBUS_AUTH_INIT_FAIL;
}
if (DiscServerInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus disc server init failed.");
return SOFTBUS_DISC_SERVER_INIT_FAILED;
}
if (BusCenterServerInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus buscenter server init failed.");
return SOFTBUS_CENTER_SERVER_INIT_FAILED;
}
if (TransServerInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus trans server init failed.");
return SOFTBUS_TRANS_SERVER_INIT_FAILED;
}
if (DiscEventManagerInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus disc event manager init failed.");
return SOFTBUS_DISCOVER_MANAGER_INIT_FAIL;
}
if (GetWifiDirectManager()->init() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus wifi direct init failed.");
return SOFTBUS_WIFI_DIRECT_INIT_FAILED;
}
if (ConnBleDirectInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus ble direct init failed.");
return SOFTBUS_CONN_BLE_DIRECT_INIT_FAILED;
}
if (InitSoftbusSysEvt() != SOFTBUS_OK || SoftBusHiDumperInit() != SOFTBUS_OK) {
COMM_LOGE(COMM_SVC, "softbus dfx init failed.");
return SOFTBUS_DFX_INIT_FAILED;
}
InstRegister(NULL);
return SOFTBUS_OK;
}
| 顺序 | 模块 | 说明 |
|---|---|---|
| 1 | ConnServerInit |
连接管理(BLE/WiFi/BR等) |
| 2 | AuthInit |
设备认证、鉴权初始化 |
| 3 | DiscServerInit |
设备发现 |
| 4 | BusCenterServerInit |
软总线控制中心(组网管理) |
| 5 | TransServerInit |
传输服务(传输权限、会话管理、传输通道、传输质量初始化) |
| 6 | DiscEventManagerInit |
发现事件管理服务初始化 |
| 7 |
GetWifiDirectManager .init |
WiFi Direct |
| 8 | ConnBleDirectInit |
BLE Direct |
| 9 | InitSoftbusSysEvt + HiDumperInit |
DFX(可维护性) |
连接 → 认证 → 发现 → 组网 → 传输
失败时调用ServerModuleDeinit()反向清理模块
发布服务
/L0/foundation/communication/dsoftbus/sdk/frame/standard/src/softbus_server_proxy_standard.cpp
整体架构理解
┌──────────────┐ IPC (SendRequest) ┌──────────────────┐
│ Client Side │ ──────────────────────► │ Server Side │
│ (Proxy) │ │ (Stub) │
│ │ │ │
│ clientStub │ ◄─── callback ──────── │ 通过 clientStub │
│ (单例) │ │ 回调客户端 │
└──────────────┘ └──────────────────┘
该函数的核心目的是:客户端向 SoftBus 服务端注册自己,同时将客户端的回调 stub 传递给服务端,以便服务端后续能通过该 stub 回调客户端。
抽象理解就是一个设备或者应用,有一个什么能力,比如拍照,这个应用将自己的服务注册到分布式网络中,希望被其他设备使用。
谁发布:调用者,即服务提供方。它是一个应用或服务进程,拥有某种能力(如文件分享、播放控制),希望被其他设备使用
接收方:分布式软总线,SoftBusServerProxyFrame 指向的远端服务,即软总线服务端(softbus_server)。它是系统级的核心服务,负责管理所有设备的服务注册信息,充当“服务管理中心”。
执行流程拆解
int32_t SoftBusServerProxyFrame::SoftbusRegisterService(const char *clientPkgName, const sptr<IRemoteObject>& object)
{
sptr<IRemoteObject> remote = Remote();
if (remote == nullptr) {
COMM_LOGE(COMM_SDK, "remote is nullptr!");
return SOFTBUS_IPC_ERR;
}
sptr<IRemoteObject> clientStub = SoftBusServerProxyFrame::GetRemoteInstance();
if (clientStub == nullptr) {
COMM_LOGE(COMM_SDK, "client stub is nullptr!");
return SOFTBUS_IPC_ERR;
}
MessageParcel data;
if (!data.WriteInterfaceToken(GetDescriptor())) {
COMM_LOGE(COMM_SDK, "SoftbusRegisterService write InterfaceToken failed!");
return SOFTBUS_TRANS_PROXY_WRITETOKEN_FAILED;
}
if (!data.WriteRemoteObject(clientStub)) {
COMM_LOGE(COMM_SDK, "SoftbusRegisterService write remote object failed!");
return SOFTBUS_TRANS_PROXY_WRITEOBJECT_FAILED;
}
if (!data.WriteCString(clientPkgName)) {
COMM_LOGE(COMM_SDK, "SoftbusRegisterService write clientPkgName failed!");
return SOFTBUS_TRANS_PROXY_WRITECSTRING_FAILED;
}
MessageParcel reply;
MessageOption option;
int32_t err = remote->SendRequest(MANAGE_REGISTER_SERVICE, data, reply, option);
if (err != 0) {
COMM_LOGE(COMM_SDK, "SoftbusRegisterService send request failed!");
return SOFTBUS_IPC_ERR;
}
int32_t serverRet = 0;
if (!reply.ReadInt32(serverRet)) {
COMM_LOGE(COMM_SDK, "SoftbusRegisterService read serverRet failed!");
return SOFTBUS_TRANS_PROXY_READINT_FAILED;
}
return serverRet;
}
1、获取远端代理对象
通过Remote()获取与软总线服务端通信的IPC代理对象,如果获取失败,则返回SOFTBUS_IPC_ERR。remote()作用是获取通向soft_bus_server的IPC代理。相当于获取远端总线的大门,如果remote == nullptr,就是系统挂掉了,连门都找不到,直接返回失败。
2.获取唯一的单例
sptr<IRemoteObject> clientStub = SoftBusServerProxyFrame::GetRemoteInstance();
这个clientstub应该是客户端与服务端通信的唯一实例,是softbus服务端依据客户端包名来唯一索引的回调通道,clientstub与remote组成了双向IPC。
3.打包注册协议
MessageParcel data
向服务端发送注册申请单要准备接口令牌(WriteInterfaceToken)、单例stub(WriteRemoteObject)、应用包名(WriteCString)
4.同步递交申请并等待批准
int32_t err = remote->SendRequest(MANAGE_REGISTER_SERVICE, data, reply, option);
|
MANAGE_REGISTER_SERVICE |
接口命令符,softbus根据这个调用底层对应业务逻辑 |
|
data |
上面提到的申请单 |
|
reply |
容器,存放服务端回调过来的结果 |
|
option |
MessageOption控制本次ipc的行为模式 |
返回值 err 与 reply 中的 serverRet 区别
-
err(函数返回值):代表 IPC 通信层是否成功。例如,0表示发送成功、服务端正常响应;非0表示远端进程死亡、驱动错误或超时(与业务逻辑无关)。 -
serverRet(从 reply 读取):代表 服务端业务逻辑层的处理结果。例如,0表示注册成功,-1表示包名无权限(与业务功能相关)。
拉起发布服务
上面客户端发布服务以后,下层服务端根据传参会路由到对应的业务代码,OnRemoteRequest()就是负责这个功能
int32_t SoftBusServerStub::OnRemoteRequest(
uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
SoftbusRecordCalledApiCnt(code);
if (data.ReadInterfaceToken() != GetDescriptor()) {
COMM_LOGE(COMM_SVC, "SOFTBUS_SERVER_NOT_INIT ReadInterfaceToken failed!");
return SOFTBUS_IPC_ERR;
}
if (!GetServerIsInit()) {
COMM_LOGE(COMM_SVC, "server not init");
if (!reply.WriteInt32(SOFTBUS_SERVER_NOT_INIT)) {
COMM_LOGE(COMM_SVC, "SOFTBUS_SERVER_NOT_INIT write reply failed!");
}
return SOFTBUS_IPC_ERR;
}
auto itPerm = memberPermissionMap_.find(code);
if (itPerm != memberPermissionMap_.end()) {
const char *permission = itPerm->second;
uint32_t callingTokenId = IPCSkeleton::GetCallingTokenID();
if ((permission != nullptr) &&
(!SoftBusCheckIsAccessAndRecordAccessToken(callingTokenId, permission))) {
SoftbusReportPermissionFaultEvt(code);
COMM_LOGE(COMM_SVC, "access token permission denied! permission=%{public}s, tokenId=%{public}d",
permission, callingTokenId);
pid_t callingPid = OHOS::IPCSkeleton::GetCallingPid();
TransAlarmExtra extra = {
.callerPid = (int32_t)callingPid,
.methodId = (int32_t)code,
.conflictName = NULL,
.conflictedName = NULL,
.occupyedName = NULL,
.permissionName = permission,
.sessionName = NULL,
};
TRANS_ALARM(NO_PERMISSION_ALARM, CONTROL_ALARM_TYPE, extra);
return SOFTBUS_ACCESS_TOKEN_DENIED;
}
}
const auto &itFunc = memberFuncMap_.find(code);
if (itFunc != memberFuncMap_.end()) {
auto memberFunc = itFunc->second;
if (memberFunc != nullptr) {
return (this->*memberFunc)(data, reply);
}
}
COMM_LOGI(COMM_SVC, "default case, need check.");
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
流程
SoftbusRecordCalledApiCnt(code);
这个code就是对应上面的指令码
核对接口令牌
if (data.ReadInterfaceToken() != GetDescriptor())
检查服务端初始化
GetServerIsInit()
AccessToken权限校验
itPerm是从 memberPermissionMap_ 中查找该 code 对应的权限名称(如 "ohos.permission.DISTRIBUTED_DATASYNC")
memberPermissionMap_ 是一个map容器,用来做指令键值比对。
callingTokenId,获取调用方的tokenID.
权限验证SoftBusCheckIsAccessAndRecordAccessToken(callingTokenId, permission)
权限被拒绝时:SoftbusReportPermissionFaultEvt(code)记录权限故障事件 + TRANS_ALARM触发 NO_PERMISSION_ALARM 告警 + 返回 SOFTBUS_ACCESS_TOKEN_DENIED
请求分发
return (this->*memberFunc)(data, reply);
这一句写的好,对象内部都有一个this指针,这个项目自定义map容器是键是指令,值是具体的函数指针,他这个是直接在map中索引调用函数。
比如这里的发布服务会索引
memberFuncMap_[SERVER_PUBLISH_LNN] = &SoftBusServerStub::PublishLNNInner;
前面的申请表传到服务端是字节流, SoftBusServerStub::PublishLNNInner()会进行反序列化,
客户端进程 服务端进程
┌──────────────────┐ ┌──────────────────┐
│ PublishInfo 对象 │ │ │
│ ┌──────────────┐ │ 序列化 │ MessageParcel │
│ │ publishId=1 │ │ ──────────→ │ (一串字节流) │
│ │ mode=ACTIVE │ │ (扁平化) │ "1|1|0|2|..." │
│ │ medium=WIFI │ │ │ │
│ │ freq=HIGH │ │ 反序列化 │ ┌──────────────┐ │
│ │ capability=..│ │ ←────────── │ │ publishId=1 │ │
│ └──────────────┘ │ (重组) │ │ mode=ACTIVE │ │
│ │ │ │ medium=WIFI │ │
│ │ │ │ freq=HIGH │ │
│ │ │ └──────────────┘ │
└──────────────────┘ └──────────────────┘
每次读取一个数据都会通过COMM_CHECK_AND_RETURN_RET_LOGE进行校验和边界检查。
当校验组装成功后才会调用实际发布业务
这个位置有个坑,看到下面以为调用的是下面的这个函数对吧
int32_t retReply = PublishLNN(clientName, &info);
再跳转会发现
int32_t ISoftBusServer::PublishLNN(const char *pkgName, const PublishInfo *info)
{
(void)pkgName;
(void)info;
COMM_LOGI(COMM_SVC, "ipc default impl");
return SOFTBUS_IPC_ERR;
}
他是个默认实现,直接返回错误了,这是个虚函数,光看实现看不出来,在类声明里面,这个调用会根据根据this指针到虚表里面去查,实际调用对象是softbusserver,默认实现一般不走,这里才是真实业务
int32_t SoftBusServer::PublishLNN(const char *pkgName, const PublishInfo *info)
{
pid_t callingPid = OHOS::IPCSkeleton::GetCallingPid();
return LnnIpcPublishLNN(pkgName, (int32_t)callingPid, info);
}
服务端获取对端客户端的callingPid,并将之前的参数都传进去
int32_t LnnIpcPublishLNN(const char *pkgName, int32_t callingPid, const PublishInfo *info)
{
int32_t ret = IsOverThreshold(pkgName, SERVER_PUBLISH_LNN);
if (ret >= SOFTBUS_DDOS_ID_AND_USER_SAME_COUNT_LIMIT && ret <= SOFTBUS_DDOS_USER_ID_ALL_COUNT_LIMIT) {
LNN_LOGE(LNN_EVENT, "here's the statistics, no need return");
}
return LnnPublishService(pkgName, info, false, callingPid);
}
ddos防护,检查包名对这个发布接口的访问频率,超出阈值加入日志但不停止
调用流程图
LnnIpcPublishLNN() ← 你在这里
└── LnnPublishService()
└── DiscPublishService()
├── 5 道参数/状态检查
├── CreateDiscInfoForPublish() → 创建内部节点
└── InnerPublishService() → 加入列表 + 按介质分发
└── CallInterfaceByMedium()
└── CoapPublish() / BlePublish() / ...
int32_t LnnPublishService(const char *pkgName, const PublishInfo *info, bool isInnerRequest, int32_t callingPid)
{
LNN_CHECK_AND_RETURN_RET_LOGE(
!SoftBusIsRamTest(), SOFTBUS_RAM_TEST_ABORT, LNN_BUILDER, "LnnPublishService: ram test abort");
int32_t ret;
if (!isInnerRequest) {
if ((ret = DiscPublishService(pkgName, info, callingPid)) != SOFTBUS_OK) {
DfxRecordLnnDiscServiceEnd(DISC_SERVER_PUBLISH, pkgName, ret);
LNN_LOGE(LNN_BUILDER, "DiscPublishService failed\n");
return ret;
}
return SOFTBUS_OK;
}
if ((ret = DiscStartScan(MODULE_LNN, info, callingPid)) != SOFTBUS_OK) {
DfxRecordLnnDiscServiceEnd(DISC_SERVER_PUBLISH, LNN_DEFAULT_PKG_NAME, ret);
LNN_LOGE(LNN_BUILDER, "DiscStartScan failed\n");
return ret;
}
return SOFTBUS_OK;
}
int32_t DiscPublishService(const char *packageName, const PublishInfo *info, int32_t callingPid)
{
// ① 参数非空检查
DISC_CHECK_AND_RETURN_RET_LOGE(packageName != NULL && info != NULL, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
"invalid parameters");
// ② 包名长度检查
DISC_CHECK_AND_RETURN_RET_LOGW(strlen(packageName) < PKG_NAME_SIZE_MAX,
SOFTBUS_INVALID_PARAM, DISC_CONTROL, "package name too long");
// ③ 禁止内部保留包名
DISC_CHECK_AND_RETURN_RET_LOGE(!IsInnerPackageName(packageName), SOFTBUS_INVALID_PARAM,
DISC_CONTROL, "package name is reserved, not allowed");
// ④ 发布信息合法性检查
DISC_CHECK_AND_RETURN_RET_LOGW(CheckPublishInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
"invalid info");
// ⑤ 模块初始化状态检查
DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
"manager is not inited");
// ⑥ 创建发布信息节点
DiscInfo *infoNode = CreateDiscInfoForPublish(info, callingPid);
DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
"create info failed");
// ⑦ 执行内部发布
int32_t ret = InnerPublishService(packageName, infoNode, PUBLISH_SERVICE);
if (ret != SOFTBUS_OK) {
FreeDiscInfo(infoNode, PUBLISH_SERVICE); // 失败时释放节点
}
return ret;
}
DiscPublishService进行5项安全检查
| 步骤 | 检查项 | 失败返回值 | 含义 |
|---|---|---|---|
| ① | packageName 和 info 非空 |
SOFTBUS_INVALID_PARAM |
基本空指针防护 |
| ② | 包名长度 < PKG_NAME_SIZE_MAX |
SOFTBUS_INVALID_PARAM |
防止缓冲区溢出 |
| ③ | 包名不是内部保留名 | SOFTBUS_INVALID_PARAM |
外部 App 不能用系统保留包名 |
| ④ | PublishInfo 内容合法 |
SOFTBUS_INVALID_PARAM |
检查 publishId、mode、medium、freq 等字段 |
| ⑤ | 发现管理器已初始化 | SOFTBUS_DISCOVER_MANAGER_NOT_INIT |
防止未初始化就调用 |
| ⑥ | 创建 DiscInfo 节点 |
SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE |
分配内存、填充信息 |
| ⑦ | 调用 InnerPublishService |
其返回值 | 加入发布列表 + 按介质分发 |
static int32_t InnerPublishService(const char *packageName, DiscInfo *info, const ServiceType type)
{
int32_t ret = SoftBusMutexLock(&g_publishInfoList->lock);
DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, DISC_CONTROL, "lock failed");
do {
ret = AddDiscInfoToPublishList(packageName, NULL, info, type);
if (ret != SOFTBUS_OK) {
DISC_LOGE(DISC_CONTROL, "add info to list failed");
break;
}
DFX_RECORD_DISC_CALL_START(info, packageName, PUBLISH_FUNC);
ret = CallInterfaceByMedium(info, packageName, PUBLISH_FUNC);
if (ret != SOFTBUS_OK) {
DISC_LOGE(DISC_CONTROL, "call interface by medium failed");
ListDelete(&(info->node));
info->item->infoNum--;
}
} while (false);
SoftBusMutexUnlock(&g_publishInfoList->lock);
return ret;
}
| 步骤 | 操作 | 说明 |
|---|---|---|
| ① | SoftBusMutexLock |
对全局发布列表 g_publishInfoList 加互斥锁,保证线程安全 |
| ② | AddDiscInfoToPublishList |
将发布信息节点挂到全局链表上,用于后续管理和去重 |
| ③ | DFX_RECORD_DISC_CALL_START |
记录诊断打点(开始时间、调用方、函数类型),用于性能分析 |
| ④ | CallInterfaceByMedium |
核心:根据 info->medium(COAP/BLE/USB/AUTO)调用对应底层发布接口 |
| ⑤ | 失败回滚 | 如果底层发布失败,从链表中删除刚加入的节点,恢复计数 |
| ⑥ | SoftBusMutexUnlock |
解锁 |
DiscPublishService()
├── 5 道参数校验
├── CreateDiscInfoForPublish() → 创建节点
└── InnerPublishService() ← 你在这里
├── AddDiscInfoToPublishList() → 登记
└── CallInterfaceByMedium() → 执行
├── COAP → CoapPublish()
├── BLE → BlePublish()
├── AUTO → CoAP + BLE
└── USB → UsbPublish()
这里面链表节点的挂载和以前接触的传统链表不一样,采用的是(内核链表)侵入式链表,不过多赘述,后面慢慢了解。函数指针路由器:
static int32_t CallInterfaceByMedium(const DiscInfo *info, const char *packageName, const InterfaceFuncType type)
{
int32_t ret = SOFTBUS_OK;
switch (info->medium) {
case COAP:
ret = CallSpecificInterfaceFunc(&(info->option), g_discCoapInterface, info->mode, type);
DfxCallInterfaceByMedium(info, packageName, type, ret);
return ret;
case BLE:
ret = CallSpecificInterfaceFunc(&(info->option), g_discBleInterface, info->mode, type);
DfxCallInterfaceByMedium(info, packageName, type, ret);
return ret;
case AUTO: {
int32_t coapRet = CallSpecificInterfaceFunc(&(info->option), g_discCoapInterface, info->mode, type);
DfxCallInterfaceByMedium(info, packageName, type, coapRet);
int32_t bleRet = CallSpecificInterfaceFunc(&(info->option), g_discBleInterface, info->mode, type);
DfxCallInterfaceByMedium(info, packageName, type, bleRet);
DISC_CHECK_AND_RETURN_RET_LOGE(coapRet == SOFTBUS_OK || bleRet == SOFTBUS_OK,
SOFTBUS_DISCOVER_MANAGER_INNERFUNCTION_FAIL, DISC_CONTROL, "all medium failed");
return SOFTBUS_OK;
}
case USB:
ret = CallSpecificInterfaceFunc(&(info->option), g_discUsbInterface, info->mode, type);
DfxCallInterfaceByMedium(info, packageName, type, ret);
return ret;
default:
return SOFTBUS_DISCOVER_MANAGER_INNERFUNCTION_FAIL;
}
}
根据传入类型调用相应处理。
将执行返回值写入给IPC的reply返回给客户端
回退机制
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
未识别的code交给父类处理
发现服务
流程上和发布服务类似
┌─────── PublishLNN 流程 ───────┐ ┌─────── RefreshLNN 流程 ───────┐
│ │ │ │
客户端 App 调用 │ PublishLNN() │ │ RefreshLNN() │
│ ↓ │ │ ↓ │
SDK Proxy 层 │ SendRequest(PUBLISH_LNN) │ │ SendRequest(REFRESH_LNN) │
│ ↓ │ │ ↓ │
═══════════════════╪═══════ IPC 边界 ═══════════════╪════╪═══════ IPC 边界 ═══════════════
│ ↓ │ │ ↓ │
服务端 Stub 层 │ PublishLNNInner() │ │ RefreshLNNInner() │
反序列化 │ ↓ │ │ ↓ │
服务端业务层 │ SoftBusServer::PublishLNN() │ │ SoftBusServer::RefreshLNN() │
│ ↓ │ │ ↓ │
IPC 逻辑层 │ LnnIpcPublishLNN() │ │ LnnIpcRefreshLNN() │
│ ↓ │ │ ↓ │
发现服务接口层 │ LnnPublishService() │ │ LnnStartDiscDevice() │
│ ↓ │ │ ↓ │
发现管理器 │ DiscPublishService() │ │ DiscStartDiscovery() │
│ ↓ │ │ ↓ │
内部发布/发现 │ InnerPublishService() │ │ InnerStartDiscovery() │
│ ↓ │ │ ↓ │
按介质分发 │ CallInterfaceByMedium() │ │ CallInterfaceByMedium() │
type= │ PUBLISH_FUNC │ │ STARTDISCOVERTY_FUNC │
│ ↓ │ │ ↓ │
函数指针路由 │ CallSpecificInterfaceFunc() │ │ CallSpecificInterfaceFunc() │
│ ↓ │ │ ↓ │
底层协议 │ CoapPublish() │ │ CoapStartAdvertise() │
└────────────────────────────────┘ └────────────────────────────────┘
更多推荐

所有评论(0)