当前位置:   article > 正文

软总线源码分析4: 接口解析之组网_软总线 自组网原理

软总线 自组网原理

当A端通过PublishService发布服务,B端通过调用StartDiscovery查找对应的服务后,A端或者B端根据对端设备的MAC地址,便可以发布组网请求。

组网请求的函数为JoinLNN,其源码如下所示:

  1. int32_t JoinLNN(const char *pkgName, ConnectionAddr *target, OnJoinLNNResult cb)
  2. {
  3. int32_t rc;
  4. SoftBusList *list = NULL;
  5. if (pkgName == NULL || target == NULL || cb == NULL) {
  6. LOG_ERR("fail : params are NULL!");
  7. return SOFTBUS_INVALID_PARAM;
  8. }
  9. if (InitSoftBus(pkgName) != SOFTBUS_OK) {
  10. LOG_ERR("fail: init softbus");
  11. return SOFTBUS_ERR;
  12. }
  13. list = g_busCenterClient.joinLNNCbList;
  14. if (list == NULL) {
  15. LOG_ERR("fail : join lnn cb list = NULL!");
  16. return SOFTBUS_ERR;
  17. }
  18. if (pthread_mutex_lock(&g_busCenterClient.lock) != 0) {
  19. LOG_ERR("fail: lock join lnn cb list in join");
  20. }
  21. rc = SOFTBUS_ERR;
  22. do {
  23. if (FindJoinLNNCbItem(target, cb) != NULL) {
  24. LOG_ERR("fail : join request already exist");
  25. break;
  26. }
  27. rc = GetServerProvideInterface()->joinLNN(target, sizeof(*target));
  28. if (rc != SOFTBUS_OK) {
  29. LOG_ERR("fail : request join lnn");
  30. } else {
  31. rc = AddJoinLNNCbItem(target, cb);
  32. }
  33. } while (false);
  34. if (pthread_mutex_unlock(&g_busCenterClient.lock) != 0) {
  35. LOG_ERR("fail: unlock join lnn cb list in join");
  36. }
  37. return rc;
  38. }

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源码如下:

  1. int32_t LnnIpcServerJoin(const char *pkgName, void *addr, uint32_t addrTypeLen)
  2. {
  3. if (CheckBusCenterPermission(pkgName) != true) {
  4. LOG_ERR("ServerJoinLNN no permission!");
  5. return SOFTBUS_PERMISSION_DENIED;
  6. }
  7. ConnectionAddr *connAddr = (ConnectionAddr *)addr;
  8. (void)addrTypeLen;
  9. if (pkgName == nullptr || connAddr == nullptr) {
  10. LOG_ERR("parameters are nullptr!\n");
  11. return SOFTBUS_ERR;
  12. }
  13. std::lock_guard<std::mutex> autoLock(g_lock);
  14. if (IsRepeatJoinLNNRequest(pkgName, connAddr)) {
  15. LOG_ERR("repeat join lnn request from: %s", pkgName);
  16. return SOFTBUS_ERR;
  17. }
  18. int32_t ret = LnnServerJoin(connAddr);
  19. if (ret == SOFTBUS_OK) {
  20. ret = AddJoinLNNInfo(pkgName, connAddr);
  21. }
  22. return ret;
  23. }

其逻辑也比较简单,即调用LnnServerJoin发起组网请求,请求成功后调用AddJoinLNNInfo将组网信息添加到本地。

LnnServerJoin的源码如下所示:

  1. int32_t LnnServerJoin(ConnectionAddr *addr)
  2. {
  3. LOG_INFO("LnnServerJoin enter!");
  4. if (addr == NULL || addr->type < CONNECTION_ADDR_WLAN || addr->type > CONNECTION_ADDR_ETH) {
  5. LOG_ERR("para error!");
  6. return SOFTBUS_ERR;
  7. }
  8. if (g_netBuilder.isInit == false) {
  9. LOG_ERR("no init");
  10. return SOFTBUS_ERR;
  11. }
  12. uint32_t cap = 0;
  13. if (ConvertTypeToNetCap(addr->type, &cap) != SOFTBUS_OK) {
  14. LOG_ERR("ConvertTypeToNetCap error!");
  15. return SOFTBUS_ERR;
  16. }
  17. if (LnnSetLocalNumInfo(NUM_KEY_NET_CAP, (int32_t)cap) != SOFTBUS_OK) {
  18. LOG_ERR("LnnSetLocalNumInfo error!");
  19. return SOFTBUS_ERR;
  20. }
  21. if (g_netBuilder.hook[addr->type] != NULL) {
  22. LOG_INFO("LnnServerJoin enter hook");
  23. return g_netBuilder.hook[addr->type]->preprocess(addr, &g_netBuilder.fsm, NETWORK_TYPE_ACTIVE);
  24. }
  25. return ConnTypeDefaultHook(addr);
  26. }

其将组网请求的连接类型转换为cap描述的Bitmap并保存后,调用g_netBuilder对应的preprocess钩子函数,最后调用函数ConnTypeDefaultHook完成相应的处理。

一、IpPreprocess

g_netBuilder.hook[addr->type]->preprocess在组网服务初始化中注册,其源码如下:

  1. static ConnTypeHook g_hook = {
  2. .preprocess = IpPreprocess,
  3. .shutdown = IpShutdown,
  4. };
  5. void LnnInitIpHook(void)
  6. {
  7. LnnRegisterConnTypeHook(CONNECTION_ADDR_WLAN, &g_hook);
  8. LnnRegisterConnTypeHook(CONNECTION_ADDR_ETH, &g_hook);
  9. if (UpdateLocalIp(CONNECTION_ADDR_ETH) == SOFTBUS_OK) {
  10. LOG_INFO("update eth ip success");
  11. return;
  12. }
  13. if (UpdateLocalIp(CONNECTION_ADDR_WLAN) == SOFTBUS_OK) {
  14. LOG_INFO("update wlan ip success");
  15. }
  16. }

所以可知g_netBuilder.hook[addr->type]->preprocess指向的函数指针即为IpPreprocess,其源码如下所示:

  1. static int32_t IpPreprocess(const ConnectionAddr *addr, FsmStateMachine *fsm, NetworkType networkType)
  2. {
  3. if (addr == NULL || fsm == NULL) {
  4. LOG_ERR("para error!");
  5. return SOFTBUS_ERR;
  6. }
  7. ConnectionAddrType type = addr->type;
  8. if (UpdateLocalIp(type) != SOFTBUS_OK) {
  9. LOG_ERR("UpdateLocalIp fail!");
  10. return SOFTBUS_ERR;
  11. }
  12. if (OpenIpLink() != SOFTBUS_OK) {
  13. LOG_ERR("OpenIpLink fail!");
  14. return SOFTBUS_ERR;
  15. }
  16. if (networkType == NETWORK_TYPE_ACTIVE) {
  17. ConnectionAddrType *para = (ConnectionAddrType *)SoftBusCalloc(sizeof(ConnectionAddrType));
  18. if (para == NULL) {
  19. LOG_ERR("malloc init message fail");
  20. return SOFTBUS_ERR;
  21. }
  22. *para = type;
  23. if (LnnFsmPostMessageDelay(fsm, FSM_MSG_TYPE_DISCOVERY_TIMEOUT, para, JOIN_DISCOVERY_TIMEOUT_LEN)
  24. != SOFTBUS_OK) {
  25. SoftBusFree(para);
  26. return SOFTBUS_ERR;
  27. }
  28. }
  29. if (EnableCoapDisc() != SOFTBUS_OK) {
  30. LOG_ERR("EnableCoapDisc fail!");
  31. return SOFTBUS_ERR;
  32. }
  33. LOG_INFO("IpPreprocess ok!");
  34. g_status.fsm = fsm;
  35. g_status.type = type;
  36. return SOFTBUS_OK;
  37. }

IpPreprocess主要分为四部分:1.更新本地IP地址;2.打开IP连接;3.如果是主动组网,则延迟1分钟后向状态机发送超时消息;4.打开COAP发现服务。

1.更新本地IP

UpdateLocalIp的源码如下所示:

  1. static int32_t UpdateLocalIp(ConnectionAddrType type)
  2. {
  3. char ipAddr[IP_MAX_LEN] = {0};
  4. char ifName[NET_IF_NAME_LEN] = {0};
  5. IfInfo info = {
  6. .ifName = ifName,
  7. .ifNameLen = NET_IF_NAME_LEN,
  8. };
  9. int32_t r
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/339863?site
推荐阅读
相关标签
  

闽ICP备14008679号