系统开机

分布式软总线在开机的时候,系统会直接调用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()          │
                    └────────────────────────────────┘    └────────────────────────────────┘

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐