赞
踩
当A端通过PublishService发布服务,B端通过调用StartDiscovery查找对应的服务后,A端或者B端根据对端设备的MAC地址,便可以发布组网请求。
组网请求的函数为JoinLNN,其源码如下所示:
- int32_t JoinLNN(const char *pkgName, ConnectionAddr *target, OnJoinLNNResult cb)
- {
- int32_t rc;
- SoftBusList *list = NULL;
-
- if (pkgName == NULL || target == NULL || cb == NULL) {
- LOG_ERR("fail : params are NULL!");
- return SOFTBUS_INVALID_PARAM;
- }
- if (InitSoftBus(pkgName) != SOFTBUS_OK) {
- LOG_ERR("fail: init softbus");
- return SOFTBUS_ERR;
- }
- list = g_busCenterClient.joinLNNCbList;
- if (list == NULL) {
- LOG_ERR("fail : join lnn cb list = NULL!");
- return SOFTBUS_ERR;
- }
- if (pthread_mutex_lock(&g_busCenterClient.lock) != 0) {
- LOG_ERR("fail: lock join lnn cb list in join");
- }
- rc = SOFTBUS_ERR;
- do {
- if (FindJoinLNNCbItem(target, cb) != NULL) {
- LOG_ERR("fail : join request already exist");
- break;
- }
- rc = GetServerProvideInterface()->joinLNN(target, sizeof(*target));
- if (rc != SOFTBUS_OK) {
- LOG_ERR("fail : request join lnn");
- } else {
- rc = AddJoinLNNCbItem(target, cb);
- }
- } while (false);
- if (pthread_mutex_unlock(&g_busCenterClient.lock) != 0) {
- LOG_ERR("fail: unlock join lnn cb list in join");
- }
- return rc;
- }
JoinLNN源码主要做了两件事:1. 调用本地的joinLNN接口发起组网请求;2.成功后调用函数AddJoinLNNCbItem将组网结果添加到本地维护的列表中。
其中AddJoinLNNCbItem的源码比较简单,即将组网成功后的target信息和cb回调保存在本地g_busCenterClient的joinLNNCbList列表中,因此不展开。我们主要分析joinLNN接口。
与PublishService和StartDiscovery的IPC通信过程一致:1. joinLNN获取SoftBusServerProxy对象,调用其JoinLNN方法,该方法填写参数请求发送到服务端进程。2. 服务端解析参数后调用SoftBusServer的JoinLNN方法。3. JoinLNN调用LnnIpcServerJoin完成相应的处理。
LnnIpcServerJoin源码如下:
- int32_t LnnIpcServerJoin(const char *pkgName, void *addr, uint32_t addrTypeLen)
- {
- if (CheckBusCenterPermission(pkgName) != true) {
- LOG_ERR("ServerJoinLNN no permission!");
- return SOFTBUS_PERMISSION_DENIED;
- }
- ConnectionAddr *connAddr = (ConnectionAddr *)addr;
-
- (void)addrTypeLen;
- if (pkgName == nullptr || connAddr == nullptr) {
- LOG_ERR("parameters are nullptr!\n");
- return SOFTBUS_ERR;
- }
- std::lock_guard<std::mutex> autoLock(g_lock);
- if (IsRepeatJoinLNNRequest(pkgName, connAddr)) {
- LOG_ERR("repeat join lnn request from: %s", pkgName);
- return SOFTBUS_ERR;
- }
- int32_t ret = LnnServerJoin(connAddr);
- if (ret == SOFTBUS_OK) {
- ret = AddJoinLNNInfo(pkgName, connAddr);
- }
- return ret;
- }
其逻辑也比较简单,即调用LnnServerJoin发起组网请求,请求成功后调用AddJoinLNNInfo将组网信息添加到本地。
LnnServerJoin的源码如下所示:
- int32_t LnnServerJoin(ConnectionAddr *addr)
- {
- LOG_INFO("LnnServerJoin enter!");
- if (addr == NULL || addr->type < CONNECTION_ADDR_WLAN || addr->type > CONNECTION_ADDR_ETH) {
- LOG_ERR("para error!");
- return SOFTBUS_ERR;
- }
- if (g_netBuilder.isInit == false) {
- LOG_ERR("no init");
- return SOFTBUS_ERR;
- }
-
- uint32_t cap = 0;
- if (ConvertTypeToNetCap(addr->type, &cap) != SOFTBUS_OK) {
- LOG_ERR("ConvertTypeToNetCap error!");
- return SOFTBUS_ERR;
- }
- if (LnnSetLocalNumInfo(NUM_KEY_NET_CAP, (int32_t)cap) != SOFTBUS_OK) {
- LOG_ERR("LnnSetLocalNumInfo error!");
- return SOFTBUS_ERR;
- }
-
- if (g_netBuilder.hook[addr->type] != NULL) {
- LOG_INFO("LnnServerJoin enter hook");
- return g_netBuilder.hook[addr->type]->preprocess(addr, &g_netBuilder.fsm, NETWORK_TYPE_ACTIVE);
- }
- return ConnTypeDefaultHook(addr);
- }
其将组网请求的连接类型转换为cap描述的Bitmap并保存后,调用g_netBuilder对应的preprocess钩子函数,最后调用函数ConnTypeDefaultHook完成相应的处理。
g_netBuilder.hook[addr->type]->preprocess在组网服务初始化中注册,其源码如下:
- static ConnTypeHook g_hook = {
- .preprocess = IpPreprocess,
- .shutdown = IpShutdown,
- };
-
- void LnnInitIpHook(void)
- {
- LnnRegisterConnTypeHook(CONNECTION_ADDR_WLAN, &g_hook);
- LnnRegisterConnTypeHook(CONNECTION_ADDR_ETH, &g_hook);
- if (UpdateLocalIp(CONNECTION_ADDR_ETH) == SOFTBUS_OK) {
- LOG_INFO("update eth ip success");
- return;
- }
- if (UpdateLocalIp(CONNECTION_ADDR_WLAN) == SOFTBUS_OK) {
- LOG_INFO("update wlan ip success");
- }
- }
所以可知g_netBuilder.hook[addr->type]->preprocess指向的函数指针即为IpPreprocess,其源码如下所示:
- static int32_t IpPreprocess(const ConnectionAddr *addr, FsmStateMachine *fsm, NetworkType networkType)
- {
- if (addr == NULL || fsm == NULL) {
- LOG_ERR("para error!");
- return SOFTBUS_ERR;
- }
- ConnectionAddrType type = addr->type;
-
- if (UpdateLocalIp(type) != SOFTBUS_OK) {
- LOG_ERR("UpdateLocalIp fail!");
- return SOFTBUS_ERR;
- }
- if (OpenIpLink() != SOFTBUS_OK) {
- LOG_ERR("OpenIpLink fail!");
- return SOFTBUS_ERR;
- }
- if (networkType == NETWORK_TYPE_ACTIVE) {
- ConnectionAddrType *para = (ConnectionAddrType *)SoftBusCalloc(sizeof(ConnectionAddrType));
- if (para == NULL) {
- LOG_ERR("malloc init message fail");
- return SOFTBUS_ERR;
- }
- *para = type;
- if (LnnFsmPostMessageDelay(fsm, FSM_MSG_TYPE_DISCOVERY_TIMEOUT, para, JOIN_DISCOVERY_TIMEOUT_LEN)
- != SOFTBUS_OK) {
- SoftBusFree(para);
- return SOFTBUS_ERR;
- }
- }
- if (EnableCoapDisc() != SOFTBUS_OK) {
- LOG_ERR("EnableCoapDisc fail!");
- return SOFTBUS_ERR;
- }
-
- LOG_INFO("IpPreprocess ok!");
- g_status.fsm = fsm;
- g_status.type = type;
- return SOFTBUS_OK;
- }
IpPreprocess主要分为四部分:1.更新本地IP地址;2.打开IP连接;3.如果是主动组网,则延迟1分钟后向状态机发送超时消息;4.打开COAP发现服务。
UpdateLocalIp的源码如下所示:
- static int32_t UpdateLocalIp(ConnectionAddrType type)
- {
- char ipAddr[IP_MAX_LEN] = {0};
- char ifName[NET_IF_NAME_LEN] = {0};
- IfInfo info = {
- .ifName = ifName,
- .ifNameLen = NET_IF_NAME_LEN,
- };
- int32_t r
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。