OpenHarmony分布式软总线流程分析v1.0丨2.开启软总线,建立连接

开发 前端 分布式
StartListener()函数的底层存在对应不同版本平台的适配函数,这印证了鸿蒙OS各部分解耦的模块化设计思想,针对不同的硬件设备,组合成最适合该设备的OS。

[[408696]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

二、当接入网络,触发WifiEventTrigger(),开启软总线

  1. Z:\harmony110\foundation\communication\softbus_lite\discovery\discovery_service\source\discovery_service.c 
  2. void WifiEventTrigger(unsigned int para) 
  3.     DeviceInfo *localDev = GetCommonDeviceInfo(); 
  4.     if (localDev == NULL) { 
  5.         return
  6.     } 
  7.  
  8.     int ret; 
  9.     if (para) { 
  10.         char wifiIp[MAX_DEV_IP_LEN] = {0}; 
  11.         CoapGetIp(wifiIp, MAX_DEV_IP_LEN, 0); //参考1.获取本设备ip 
  12.         if (strcmp(wifiIp, "0.0.0.0") == 0) { 
  13.             SOFTBUS_PRINT("[DISCOVERY] WifiEventTrigger new event interupt.\n"); 
  14.             return
  15.         } 
  16.         ret = memcpy_s(localDev->deviceIp, sizeof(localDev->deviceIp), wifiIp, sizeof(wifiIp)); 
  17.     } else { 
  18.         ret = memset_s(localDev->deviceIp, sizeof(localDev->deviceIp), 0, sizeof(localDev->deviceIp)); 
  19.     } 
  20.  
  21.     if (ret != ERROR_SUCCESS) { 
  22.         return
  23.     } 
  24.  
  25.     if (BusManager(para) != ERROR_SUCCESS) { //参考2.BusManager()启动软总线 
  26.         SOFTBUS_PRINT("[DISCOVERY] WifiEventTrigger StartBusManager(%d) fail\n", para); 
  27.         return
  28.     } 
  29.  
  30.     if (CoapRegisterDeviceInfo() != ERROR_SUCCESS) { 
  31.         SOFTBUS_PRINT("[DISCOVERY] WifiEventTrigger CoapRegisterDeviceInfo fail\n"); 
  32.         return
  33.     } 
  34.  
  35.     if (DoRegistService(COAP) != ERROR_SUCCESS) { 
  36.         SOFTBUS_PRINT("[DISCOVERY] WifiEventTrigger DoRegistService fail\n"); 
  37.         return
  38.     } 

1.获取本设备ip

  1. Z:\harmony110\foundation\communication\softbus_lite\discovery\coap\source\coap_discover.c 
  2. //通过CoapGetIp()循环获取本地设备wifi连接后的IP地址,并放入到deviceInfo->deviceIp中。后续会使用。 
  3. void CoapGetIp(char *ip, int length, int finite) 
  4.     if (ip == NULL || length != NSTACKX_MAX_IP_STRING_LEN) { 
  5.         return
  6.     } 
  7.  
  8.     g_queryIpFlag = 1; 
  9.     int count = finite ? GET_IP_TIMES : GET_IP_INFINITE; 
  10.     while (g_queryIpFlag) { 
  11.         CoapGetWifiIp(ip, length);//获取ip方式根据内核不同,会有多个方式 
  12.         if (CheckIpIsValid(ip, strlen(ip)) == 0) { 
  13.             break; 
  14.         } 
  15.  
  16.         if (count == 0) { 
  17.             break; 
  18.         } 
  19.         count--; 
  20.         usleep(TEN_MS); //#define TEN_MS  (10 * 1000)//usleep 10ms,每次获取IP间隔10ms 
  21.     } 
  22.     return

2.BusManager()启动软总线

  1. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\bus_manager.c 
  2. int BusManager(unsigned int startFlag) 
  3.     if (startFlag == 1) { 
  4.         return StartBus(); 
  5.     } else { 
  6.         return StopBus(); 
  7.     } 
  8. ============================================================================== 
  9. int StartBus(void) 
  10.     if (g_busStartFlag == 1) { 
  11.         return 0; 
  12.     } 
  13.     DeviceInfo *info = GetCommonDeviceInfo(); 
  14.     if (info == NULL) { 
  15.         return ERROR_FAIL; 
  16.     } 
  17.  
  18.     g_baseLister.onConnectEvent = OnConnectEvent;   //当存在新连接时调用此函数 
  19.     g_baseLister.onDataEvent = OnDataEvent;         //当存在新数据时调用此函数 
  20.     //StartListener()函数负责为认证模块提供通道完成初始化 
  21.     int authPort = StartListener(&g_baseLister, info->deviceIp);  //参考:2.1.启动侦听 
  22.     if (authPort < 0) { 
  23.         SOFTBUS_PRINT("[AUTH] StartBus StartListener fail\n"); 
  24.         return ERROR_FAIL; 
  25.     } 
  26.     info->devicePort = authPort; 
  27.     //StartSession()函数负责初始化业务的session管理 
  28.     int sessionPort = StartSession(info->deviceIp); //参考:2.2.启动会话 
  29.     if (sessionPort < 0) { 
  30.         SOFTBUS_PRINT("[AUTH] StartBus StartSession fail\n"); 
  31.         StopListener(); 
  32.         return ERROR_FAIL; 
  33.     } 
  34.  
  35.     AuthMngInit(authPort, sessionPort); 
  36.     g_busStartFlag = 1; 
  37.  
  38.     SOFTBUS_PRINT("[AUTH] StartBus ok\n"); 
  39.     return 0; 
  40. ============================================================================== 
  41. //回调函数的处理 
  42. //trans_service模块的使用者设置的回调函数将在存在新连接、和新数据时被调用 
  43. //比如认证模块通过以下函数完成认证动作:OnConnectEvent()函数中完成对新连接的处理, OnDataEvent()函数中完成对新数据的处理。 
  44.  
  45. int OnConnectEvent(int fd, const char *ip) 
  46.     ProcessConnectEvent(fd, ip); 
  47.     return 0; 
  48.  
  49. int OnDataEvent(int fd) 
  50.     ProcessDataEvent(fd); 
  51.     return 0; 

2.1.启动监听,StartListener(),监听与发现端建立连接

StartListener()函数的底层存在对应不同版本平台的适配函数,这印证了鸿蒙OS各部分解耦的模块化设计思想,针对不同的硬件设备,组合成最适合该设备的OS。比如创建线程时采用了统一的static void WaitProcess(void)函数,而其内部封装了不同底层API的适配代码。

  1. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\libdistbus\auth_conn_manager.c 
  2. //StartListener()函数负责为认证模块提供通道完成初始化 
  3. //该函数主要是创建了一个WaitProcess 的线程,该线程用于对g_maxFd 所代表的文件描述符利用select 函数进行监控,若返回值大于0,则调用ProcessAuthData 函数。该函数完成对建立的链接的数据进行收发,并对收到的数据进行处理的工作,两个处理事件的函数分别是onConnectEvent和onDataEvent,即前面注册的两个回调函数。其中onConnectEvent 函数主要是为新建立连接的设备创建AuthConnNode 类型的节点,并将其加入链表中;onDataEvent 函数是对AuthConnNode节点中的数据成员进行内存分配及对数据进行处理。 
  4. #if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__) 
  5. int StartListener(BaseListener *callback, const char *ip)   // *callback,回调函数 
  6.     if (callback == NULL || ip == NULL) { 
  7.         return -DBE_BAD_PARAM; 
  8.     } 
  9.  
  10.     g_callback = callback; 
  11.     //InitListenFd()函数完成监听TCP socket的创建和监听,其中IP地址和端口号由上层调用者指定。 
  12.     int rc = InitListenFd(ip, SESSIONPORT); // 
  13.     if (rc != DBE_SUCCESS) { 
  14.         return -DBE_BAD_PARAM; 
  15.     } 
  16.  
  17.     osThreadAttr_t attr; 
  18.     attr.name = "trans_auth_task"
  19.     attr.attr_bits = 0U; 
  20.     attr.cb_mem = NULL
  21.     attr.cb_size = 0U; 
  22.     attr.stack_mem = NULL
  23.     attr.stack_size = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 
  24.     attr.priority = osPriorityNormal5; // LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO -> cmsis prio 
  25.     //osThreadNew()在不同平台上会有不同的实现,在LITEOS_A和Linux平台上, osThreadNew()会调用兼容POSIX的pthread_create()完成线程的创建 
  26.     g_uwTskLoID = osThreadNew((osThreadFunc_t)WaitProcess, NULL, &attr);//监听新连接和数据WaitProcess(void) 
  27.     if (NULL == g_uwTskLoID) { 
  28.         SOFTBUS_PRINT("[TRANS] StartListener task create fail\n"); 
  29.         return -1; 
  30.     } 
  31.  
  32.     SOFTBUS_PRINT("[TRANS] StartListener ok\n"); 
  33.     return GetSockPort(g_listenFd); 
  34. ============================================================================== 
  35. static void WaitProcess(void)//监听新连接和数据WaitProcess(void) 
  36.     SOFTBUS_PRINT("[TRANS] WaitProcess begin\n"); 
  37.     fd_set readSet; 
  38.     fd_set exceptfds; 
  39.  
  40.     while (1) {//WaitProcess()使用忙等方式,调用select()来监听listenFd和数据g_dataFd的信息,如果监听到有数据可读,则进入ProcessAuthData来处理。 
  41.         FD_ZERO(&readSet); 
  42.         FD_ZERO(&exceptfds); 
  43.         FD_SET(g_listenFd, &readSet); 
  44.         if (g_dataFd >= 0) { 
  45.             FD_SET(g_dataFd, &readSet); 
  46.             FD_SET(g_dataFd, &exceptfds); 
  47.         } 
  48.         int ret = select(g_maxFd + 1, &readSet, NULL, &exceptfds, NULL);//监听g_listenFd和数据g_dataFd的信息 
  49.         if (ret > 0) {//如果监听到有数据可读,则进入ProcessAuthData来处理。 
  50.             if (!ProcessAuthData(g_listenFd, &readSet)) {//【重要的监听】参考: 
  51.                 SOFTBUS_PRINT("[TRANS] WaitProcess ProcessAuthData fail\n"); 
  52.                 StopListener(); 
  53.                 break; 
  54.             } 
  55.         } else if (ret < 0) {//如果发现g_dataFd有异常信息,则将其关闭。其中g_dataFd是由listenFd监听到连接时创建的socket。 
  56.             if (errno == EINTR || (g_dataFd > 0 && FD_ISSET(g_dataFd, &exceptfds))) { 
  57.                 SOFTBUS_PRINT("[TRANS] errno == EINTR or g_dataFd is in exceptfds set.\n"); 
  58.                 CloseAuthSessionFd(g_dataFd); 
  59.                 continue
  60.             } 
  61.             SOFTBUS_PRINT("[TRANS] WaitProcess select fail, stop listener\n"); 
  62.             StopListener(); 
  63.             break; 
  64.         } 
  65.     } 

2.2.启动会话,StartSession()

  1. //StartSession()函数负责初始化业务的session管理 
  2. //StartSession 该函数只有一个参数,即const char *ip,也就是一个IP,和StartListener函数中的IP 是一样的。该函数是为全局变量g_sessionMgr 申请空间及初始化,然后根据所给的参数创建socket 文件描述符并监听,之后通过调用StartSelectLoop 函数创建SelectSessionLoop 的线程,该线程将socket 文件描述符加入集合,并调用select 函数进行监控,若函数的返回值大于0,则调用ProcessData 函数,该函数有两个分支,若socket 未创建session则为其创建session;若已创建session,则处理其数据部分 
  3. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\bus_manager.c 
  4. int StartSession(const char *ip) 
  5.     int port = CreateTcpSessionMgr(true, ip); 
  6.     return port; 
  7. ============================================================================== 
  8. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\libdistbus\tcp_session_manager.c 
  9. int CreateTcpSessionMgr(bool asServer, const char* localIp) 
  10.     if (localIp == NULL) { 
  11.         return TRANS_FAILED; 
  12.     } 
  13.  
  14.     if (InitTcpMgrLock() != 0 || GetTcpMgrLock() != 0) { 
  15.         return TRANS_FAILED; 
  16.     } 
  17.  
  18.     int ret = InitGSessionMgr(); 
  19.     if (ReleaseTcpMgrLock() != 0 || ret != 0) { 
  20.         FreeSessionMgr(); 
  21.         return TRANS_FAILED; 
  22.     } 
  23.     g_sessionMgr->asServer = asServer;//该函数是为全局变量g_sessionMgr 申请空间及初始化 
  24.     int listenFd = OpenTcpServer(localIp, DEFAULT_TRANS_PORT); 
  25.     if (listenFd < 0) { 
  26.         SOFTBUS_PRINT("[TRANS] CreateTcpSessionMgr OpenTcpServer fail\n"); 
  27.         FreeSessionMgr(); 
  28.         return TRANS_FAILED; 
  29.     } 
  30.     int rc = listen(listenFd, LISTEN_BACKLOG);//然后根据所给的参数创建socket 文件描述符并监听 
  31.     if (rc != 0) { 
  32.         SOFTBUS_PRINT("[TRANS] CreateTcpSessionMgr listen fail\n"); 
  33.         CloseSession(listenFd); 
  34.         FreeSessionMgr(); 
  35.         return TRANS_FAILED; 
  36.     } 
  37.     g_sessionMgr->listenFd = listenFd; 
  38.  
  39.     signal(SIGPIPE, SIG_IGN); 
  40.     if (StartSelectLoop(g_sessionMgr) != 0) {//之后通过调用StartSelectLoop 函数创建SelectSessionLoop 的线程 
  41.         SOFTBUS_PRINT("[TRANS] CreateTcpSessionMgr StartSelectLoop fail\n"); 
  42.         CloseSession(listenFd); 
  43.         FreeSessionMgr(); 
  44.         return TRANS_FAILED; 
  45.     } 
  46.     return GetSockPort(listenFd); 
  47. ============================================================================== 
  48. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\libdistbus\tcp_session_manager.c 
  49. #if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__) 
  50. int StartSelectLoop(TcpSessionMgr *tsm) 
  51.     if (tsm == NULL) { 
  52.         return TRANS_FAILED; 
  53.     } 
  54.  
  55.     if (tsm->isSelectLoopRunning) { 
  56.         return 0; 
  57.     } 
  58.  
  59.     osThreadId_t sessionLoopTaskId; 
  60.  
  61.     osThreadAttr_t attr; 
  62.     attr.name = "trans_session_task"
  63.     attr.attr_bits = 0U; 
  64.     attr.cb_mem = NULL
  65.     attr.cb_size = 0U; 
  66.     attr.stack_mem = NULL
  67.     attr.stack_size = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 
  68.     attr.priority = osPriorityNormal5; // LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO -> cmsis prio 
  69.     //该线程将socket 文件描述符加入集合,并调用select 函数进行监控, 
  70.     sessionLoopTaskId = osThreadNew((osThreadFunc_t)SelectSessionLoop, (void *)tsm, &attr); 
  71.     if (NULL == sessionLoopTaskId) { 
  72.         SOFTBUS_PRINT("[TRANS] StartSelectLoop TaskCreate fail\n"); 
  73.         return TRANS_FAILED; 
  74.     } 
  75.  
  76.     return 0; 
  77. ============================================================================== 
  78. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\libdistbus\tcp_session_manager.c 
  79. static void SelectSessionLoop(TcpSessionMgr *tsm) 
  80.     if (tsm == NULL) { 
  81.         return
  82.     } 
  83.     SOFTBUS_PRINT("[TRANS] SelectSessionLoop begin\n"); 
  84.     tsm->isSelectLoopRunning = true
  85.     while (true) { 
  86.         fd_set readfds; 
  87.         fd_set exceptfds; 
  88.         int maxFd = InitSelectList(tsm, &readfds, &exceptfds); 
  89.         if (maxFd < 0) { 
  90.             break; 
  91.         } 
  92.          
  93.         errno = 0; 
  94.         int ret = select(maxFd + 1, &readfds, NULL, &exceptfds, NULL); 
  95.         if (ret < 0) { 
  96.             SOFTBUS_PRINT("RemoveExceptSessionFd\r\n"); 
  97.             if (errno == EINTR || RemoveExceptSessionFd(tsm, &exceptfds) == 0) { 
  98.                 continue
  99.             } 
  100.             SOFTBUS_PRINT("[TRANS] SelectSessionLoop close all Session\n"); 
  101.             CloseAllSession(tsm); 
  102.             break; 
  103.         } else if (ret == 0) { 
  104.             continue
  105.         } else {//若函数的返回值大于0,则调用ProcessData 函数, 
  106.             ProcessData(tsm, &readfds); 
  107.         } 
  108.     } 
  109.     tsm->isSelectLoopRunning = false
  110. ============================================================================== 
  111. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\libdistbus\tcp_session_manager.c 
  112. static void ProcessData(TcpSessionMgr *tsm, fd_set *rfds) 
  113.     if (tsm == NULL || tsm->listenFd == -1) { 
  114.         return
  115.     } 
  116.     //该函数有两个分支,若socket 未创建session则为其创建session;若已创建session,则处理其数据部分 
  117.     if (FD_ISSET(tsm->listenFd, rfds)) { 
  118.         ProcessConnection(tsm); 
  119.         return
  120.     } 
  121.  
  122.     ProcessSesssionData(tsm, rfds); 

总结:

当软总线启动后,就会开始监听新连接,OnConnectEvent()函数中完成对新连接的处理, OnDataEvent()函数中完成对新数据的处理。

三、当发现端(比如手机)发送广播

当鸿蒙手机开启锁屏后,会在局域网内发送UDP广播,当开发板(服务端)检测到广播会调用下面的函数。

1.当检测到局域网内UDP广播包,HandleReadEvent()

  1. Z:\harmony110\foundation\communication\softbus_lite\discovery\coap\source\coap_discover.c 
  2. static void HandleReadEvent(int fd) 
  3.     int socketFd = fd; 
  4.     unsigned char *recvBuffer = calloc(1, COAP_MAX_PDU_SIZE + 1); 
  5.     if (recvBuffer == NULL) { 
  6.         return
  7.     } 
  8.     ssize_t nRead; 
  9.     nRead = CoapSocketRecv(socketFd, recvBuffer, COAP_MAX_PDU_SIZE);//这个函数读取socket的内容 
  10.     if ((nRead == 0) || (nRead < 0 && errno != EAGAIN && 
  11.         errno != EWOULDBLOCK && errno != EINTR)) { 
  12.         free(recvBuffer); 
  13.         return
  14.     } 
  15.  
  16.     COAP_Packet decodePacket; 
  17.     (void)memset_s(&decodePacket, sizeof(COAP_Packet), 0, sizeof(COAP_Packet)); 
  18.     decodePacket.protocol = COAP_UDP; 
  19.     COAP_SoftBusDecode(&decodePacket, recvBuffer, nRead);//然后调用COAP_SoftBusDecode来解码 
  20.     PostServiceDiscover(&decodePacket);//解码后的报文由PostServiceDiscover来处理,参考下面解析 
  21.     free(recvBuffer); 
  22. ============================================================================== 
  23. void PostServiceDiscover(const COAP_Packet *pkt) 
  24.     char *remoteUrl = NULL
  25.     DeviceInfo deviceInfo; 
  26.  
  27.     if (pkt == NULL) { 
  28.         return
  29.     } 
  30.  
  31.     (void)memset_s(&deviceInfo, sizeof(deviceInfo), 0, sizeof(deviceInfo)); 
  32.     //关于GetServiceDiscoverInfo()这个解包函数暂时不深挖了,TODO 
  33.     if (GetServiceDiscoverInfo(pkt->payload.buffer, pkt->payload.len, &deviceInfo, &remoteUrl) != NSTACKX_EOK) { 
  34.         return
  35.     } 
  36.  
  37.     char wifiIpAddr[NSTACKX_MAX_IP_STRING_LEN]; 
  38.     (void)memset_s(wifiIpAddr, sizeof(wifiIpAddr), 0, sizeof(wifiIpAddr)); 
  39.     (void)inet_ntop(AF_INET, &deviceInfo.netChannelInfo.wifiApInfo.ip, wifiIpAddr, sizeof(wifiIpAddr)); 
  40. printf(">>>>>%s:%d\nremoteUrl:%s\nwifiIpAddr:%s\n",__FILE__,__LINE__,remoteUrl,wifiIpAddr);//添加打印调试 
  41.     if (remoteUrl != NULL) { 
  42.         CoapResponseService(pkt, remoteUrl, wifiIpAddr);//通过解析到的手机(发现端)的地址,应答服务 
  43.         free(remoteUrl); 
  44.     } 
  45. ============================================================================== 
  46. static int CoapResponseService(const COAP_Packet *pkt, const char* remoteUrl, const char* remoteIp) 
  47.     int ret; 
  48.     CoapRequest coapRequest; 
  49.     (void)memset_s(&coapRequest, sizeof(coapRequest), 0, sizeof(coapRequest)); 
  50.     coapRequest.remoteUrl = remoteUrl; 
  51.     coapRequest.remoteIp = remoteIp; 
  52.     char *payload = PrepareServiceDiscover(); 
  53.     if (payload == NULL) { 
  54.         return NSTACKX_EFAILED; 
  55.     } 
  56. printf(">>>>>%s:%d\npayload:%s\n",__FILE__,__LINE__,payload);//添加打印调试 
  57.     COAP_ReadWriteBuffer sndPktBuff = {0}; 
  58.     sndPktBuff.readWriteBuf = calloc(1, COAP_MAX_PDU_SIZE); 
  59.     if (sndPktBuff.readWriteBuf == NULL) { 
  60.         free(payload); 
  61.         return NSTACKX_EFAILED; 
  62.     } 
  63.     sndPktBuff.size = COAP_MAX_PDU_SIZE; 
  64.     sndPktBuff.len = 0; 
  65.  
  66.     ret = BuildSendPkt(pkt, remoteIp, payload, &sndPktBuff);//构建要发回的包 
  67.     free(payload); 
  68.     if (ret != DISCOVERY_ERR_SUCCESS) { 
  69.         free(sndPktBuff.readWriteBuf); 
  70.         sndPktBuff.readWriteBuf = NULL
  71.         return ret; 
  72.     } 
  73.     coapRequest.data = sndPktBuff.readWriteBuf; 
  74.     coapRequest.dataLength = sndPktBuff.len; 
  75.     ret = CoapSendRequest(&coapRequest);    //发送 
  76.     free(sndPktBuff.readWriteBuf); 
  77.     sndPktBuff.readWriteBuf = NULL
  78.  
  79.     return ret; 

2.当检测到新连接,ProcessAuthData()

  1. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\libdistbus\auth_conn_manager.c:85 
  2. //无论是新连接请求,还是已有连接中有数据到来,均会进入本函数。 
  3. static bool ProcessAuthData(int listenFd, const fd_set *readSet) 
  4.     if (readSet == NULL || g_callback == NULL || g_callback->onConnectEvent == NULL || 
  5.         g_callback->onDataEvent == NULL) { 
  6.         return false
  7.     } 
  8.  
  9.     if (FD_ISSET(listenFd, readSet)) {//判断是否是listenFd上存在消息 
  10.         struct sockaddr_in addrClient = {0}; 
  11.         socklen_t addrLen = sizeof(addrClient); 
  12.         //如果是,则说明当前存在新的连接,这时调用accept()完成链接创建,新创建的socket的fd被存储在g_dataFd中, 
  13.         g_dataFd = accept(listenFd, (struct sockaddr *)(&addrClient), &addrLen); 
  14.         if (g_dataFd < 0) { 
  15.             CloseAuthSessionFd(listenFd); 
  16.             return false
  17.         } 
  18.         RefreshMaxFd(g_dataFd); 
  19.         //同时调用g_callback->onConnectEvent通知认证模块有新的连接事件发生,并将新创建的fd和client的IP地址告知认证模块。 
  20.         //与此同时,创建g_dataFd时候需要刷新g_maxFd,以保证在WaitProcess()中的下一次select()操作时中,会监听到g_dataFd上的事件。 
  21.         if (g_callback->onConnectEvent(g_dataFd, inet_ntoa(addrClient.sin_addr)) != 0) {    //参考下面解析OnConnectEvent() 
  22.             CloseAuthSessionFd(g_dataFd); 
  23.         } 
  24.     } 
  25.     //如果FD_ISSET()判断出g_dataFd上存在消息,则说明已完成握手的连接向本节点发送了数据, 
  26.     if (g_dataFd > 0 && FD_ISSET(g_dataFd, readSet)) {  //参考下面解析OnDataEvent() 
  27.         g_callback->onDataEvent(g_dataFd);//这时函数回调g_callback->onDataEvent(),把控制权返回给调用者,以处理接收到的数据。 
  28.     } 
  29.  
  30.     return true
  31. ============================================================================== 
  32. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\bus_manager.c 
  33. int OnConnectEvent(int fd, const char *ip) 
  34.     ProcessConnectEvent(fd, ip);    //2.1当建立新连接 
  35.     return 0; 
  36. int OnDataEvent(int fd) 
  37.     ProcessDataEvent(fd);           //2.2当接收到新数据 
  38.     return 0; 

2.1当建立新连接,OnConnectEvent()

  1. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\wifi_auth_manager.c:192行 
  2. void ProcessConnectEvent(int fd, const char *ip) 
  3.     SOFTBUS_PRINT("[AUTH] ProcessConnectEvent fd = %d\n", fd); 
  4.     AuthConn *aconn = FindAuthConnByFd(fd); //通过fd查找验证连接 
  5.  
  6.     aconn = calloc(1, sizeof(AuthConn));  //? 系统声明吗? 
  7.  
  8.     int ret = strcpy_s(aconn->deviceIp, sizeof(aconn->deviceIp), ip);//字符串复制函数 
  9.  
  10.     aconn->fd = fd; 
  11.  
  12.     ret = AddAuthConnToList(aconn);//添加认证连接到列表 
  1. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\wifi_auth_manager.c:554 
  2. 这个函数被调用3次?? 
  3. 数据事件进程 
  4. void ProcessDataEvent(int fd) 
  5.     SOFTBUS_PRINT("[AUTH] ProcessDataEvent fd = %d\n", fd); 
  6.     AuthConn *conn = FindAuthConnByFd(fd); //通过fd查找验证连接 
  7.  
  8.     if (conn->db.buf == NULL) { 
  9.         conn->db.buf = (char *)malloc(DEFAULT_BUF_SIZE); 
  10.         if (conn->db.buf == NULL) { 
  11.             return
  12.         } 
  13.         (void)memset_s(conn->db.buf, DEFAULT_BUF_SIZE, 0, DEFAULT_BUF_SIZE); 
  14.         conn->db.size = DEFAULT_BUF_SIZE; 
  15.         conn->db.used = 0; 
  16.     } 
  17.  
  18.     DataBuffer *db = &conn->db; 
  19.     char *buf = db->buf; 
  20.     int used = db->used; 
  21.     int size = db->size
  22.  
  23.     int rc = AuthConnRecv(fd, buf, used, size - used, 0); 
  24.     if (rc == 0) { 
  25.         return
  26.     } else if (rc < 0) { 
  27.         CloseConn(conn); 
  28.         return
  29.     } 
  30.  
  31.     used += rc; 
  32.     int processed = ProcessPackets(conn, buf, size, used); //参考下面解析1 
  33.     if (processed > 0) { 
  34.         used -= processed; 
  35.         if (used != 0) { 
  36.             if (memmove_s(buf, processed, buf, used) != EOK) { 
  37.                 CloseConn(conn); 
  38.                 return
  39.             } 
  40.         } 
  41.     } else if (processed < 0) { 
  42.         CloseConn(conn); 
  43.         return
  44.     } 
  45.  
  46.     db->used = used; 
  47.     SOFTBUS_PRINT("[AUTH] ProcessDataEvent ok\n"); 

1.\Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\wifi_auth_manager.c:527行

  1. static int ProcessPackets(AuthConn *conn, const char *buf, int sizeint used) 
  2.     int processed = 0; 
  3.     while (processed + PACKET_HEAD_SIZE < used) { 
  4.         Packet *pkt = ParsePacketHead(buf, processed, used - processed, size);//参考下面解析1 
  5.  
  6.         int len = pkt->dataLen;//将解析完包的大小,赋值给len 
  7.         processed += PACKET_HEAD_SIZE;//+24 
  8.         OnDataReceived(conn, pkt, buf + processed);//参考下面解析2 
  9.         processed += len; 
  10.         free(pkt); 
  11.         pkt = NULL
  12.     } 
  13.     return processed; 

1.\Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\wifi_auth_manager.c:485行

  1. //解析包头,这个函数返回一个packet的结构体 
  2. static Packet *ParsePacketHead(const char *buf, int offset, int len, int size
  3.     unsigned int identifier = GetIntFromBuf(buf, offset); //1.从buf获取识别码 
  4.      
  5.     offset += DEFAULT_INT_LEN; //将偏移量+4 
  6.     int module = GetIntFromBuf(buf, offset);//2.从buf获取module 
  7.      
  8.     offset += DEFAULT_INT_LEN;//将偏移量+4 
  9.     long long seq = 0; 
  10.     if (GetLongFromBuf(buf, offset, &seq) != 0) {//3.从buf获取序列号 
  11.         return NULL
  12.     } 
  13.      
  14.     offset += DEFAULT_LONG_LEN;//将偏移量+4 
  15.     int flags = GetIntFromBuf(buf, offset);//4.从buf获取标志位 
  16.      
  17.     offset += DEFAULT_INT_LEN;//将偏移量+4 
  18.     int dataLen = GetIntFromBuf(buf, offset);//5.从buf获取数据长度 
  19.  
  20.     SOFTBUS_PRINT("[AUTH] ParsePacketHead module=%d, seq=%lld, flags=%d, datalen=%d\n", module, seq, flags, dataLen); 
  21.  
  22.     Packet *packet = (Packet *)malloc(sizeof(Packet)); 
  23.     packet->module = module; 
  24.     packet->seq = seq; 
  25.     packet->flags = flags; 
  26.     packet->dataLen = dataLen; 
  27.  
  28.     return packet; 

 2.\Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\wifi_auth_manager.c:446行

  1. static void OnDataReceived(AuthConn *conn, const Packet *pkt, const char *data) 
  2.     SOFTBUS_PRINT("[AUTH] OnDataReceived\n"); //数据接收 
  3.     if ((pkt->module > MODULE_HICHAIN) && (pkt->module <= MODULE_AUTH_SDK)) { 
  4.         //接收数据的认证接口函数,参考解析1 
  5.         AuthInterfaceOnDataReceived(conn, pkt->module, pkt->seq, data, pkt->dataLen); 
  6.         return
  7.     } 
  8.  
  9.     cJSON *msg = DecryptMessage(pkt->module, data, pkt->dataLen); 
  10.     if (msg == NULL) { 
  11.         SOFTBUS_PRINT("[AUTH] OnDataReceived DecryptMessage fail\n"); 
  12.         return
  13.     } 
  14.  
  15.     OnModuleMessageReceived(conn, pkt->module, pkt->flags, pkt->seq, msg); 
  16.     cJSON_Delete(msg); 
  17.     msg = NULL
  1. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\auth_interface.c 
  2. void AuthInterfaceOnDataReceived(const AuthConn *conn, int module, long long seqId, const char *data, int dataLen) 
  3.     SOFTBUS_PRINT("[AUTH] AuthInterfaceOnDataReceived begin\n"); 
  4.  
  5.     if (AuthSessionMapInit() != 0) { //认证会话初始化 
  6.         return
  7.     } 
  8.     AuthSession *auth = AuthGetAuthSessionBySeqId(seqId);//身份验证-通过序列ID获取验证会话 
  9.     if (auth == NULL) { 
  10.         auth = AuthGetNewAuthSession(conn, seqId, g_authSessionId);//身份验证-获取新的验证会话 
  11.         if (auth == NULL) { 
  12.             return
  13.         } 
  14.         ++g_authSessionId; 
  15.     } 
  16.  
  17.     switch (module) { 
  18.         case MODULE_AUTH_SDK: 
  19.             AuthProcessReceivedData(auth->sessionId, data, dataLen);//身份验证线程接收数据 
  20.             break; 
  21.         default
  22.             break; 
  23.     } 
  24.     return

2.2当接收到新数据,OnDataEvent()

  1. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\wifi_auth_manager.c 
  2. void ProcessDataEvent(int fd) 
  3.     SOFTBUS_PRINT("[AUTH] ProcessDataEvent fd = %d\n", fd); 
  4.     AuthConn *conn = FindAuthConnByFd(fd); 
  5.     if (conn == NULL) { 
  6.         SOFTBUS_PRINT("ProcessDataEvent get authConn fail\n"); 
  7.         return
  8.     } 
  9.  
  10.     if (conn->db.buf == NULL) { 
  11.         conn->db.buf = (char *)malloc(DEFAULT_BUF_SIZE); 
  12.         if (conn->db.buf == NULL) { 
  13.             return
  14.         } 
  15.         (void)memset_s(conn->db.buf, DEFAULT_BUF_SIZE, 0, DEFAULT_BUF_SIZE); 
  16.         conn->db.size = DEFAULT_BUF_SIZE; 
  17.         conn->db.used = 0; 
  18.     } 
  19.  
  20.     DataBuffer *db = &conn->db; 
  21.     char *buf = db->buf; 
  22.     int used = db->used; 
  23.     int size = db->size
  24.     printf(">>>>>%s:%d\nbuf:%s\n",__FILE__,__LINE__,buf); 
  25.     int rc = AuthConnRecv(fd, buf, used, size - used, 0);//认证连接的返回信息 
  26.     if (rc == 0) { 
  27.         return
  28.     } else if (rc < 0) { 
  29.         CloseConn(conn); 
  30.         return
  31.     } 
  32.     used += rc; 
  33.     int processed = ProcessPackets(conn, buf, size, used);//对收到的包处理 
  34.     if (processed > 0) { 
  35.         used -= processed; 
  36.         if (used != 0) { 
  37.             if (memmove_s(buf, processed, buf, used) != EOK) { 
  38.                 CloseConn(conn); 
  39.                 return
  40.             } 
  41.         } 
  42.     } else if (processed < 0) { 
  43.         CloseConn(conn); 
  44.         return
  45.     } 
  46.     db->used = used; 
  47.     SOFTBUS_PRINT("[AUTH] ProcessDataEvent ok\n"); 
  48. ============================================================================== 
  49. Z:\harmony110\foundation\communication\softbus_lite\authmanager\source\auth_conn.c 
  50. int AuthConnRecv(int fd, char *buf, int offset, int countint timeout) 
  51.     if ((buf == NULL) || (offset < 0) || (count <= 0) || (offset + count <= 0)) { 
  52.         return -1; 
  53.     } 
  54.  
  55.     return TcpRecvData(fd, buf + offset, count, timeout); 
  56. ============================================================================== 
  57. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\utils\tcp_socket.c 
  58. int TcpRecvData(int fd, char *buf, int len, int timeout) 
  59.     return TcpRecvMessages(fd, buf, len, timeout, 0); 
  60. ============================================================================== 
  61. Z:\harmony110\foundation\communication\softbus_lite\trans_service\source\utils\tcp_socket.c 
  62. static int32_t TcpRecvMessages(int fd, char *buf, uint32_t len, int timeout, int flags) 
  63. {printf(">>>>>%s:%d:%s()\n",__FILE__,__LINE__,__FUNCTION__); 
  64.     if (fd < 0 || buf == NULL || len == 0 || timeout < 0) { 
  65.         return -1; 
  66.     } 
  67. printf(">>>>>%s:%d\nfd:%d,len:%d,flags:%d\nTcpRecvMessages:buf:%s\n",__FILE__,__LINE__,fd,len,flags,buf); 
  68.     errno = 0; 
  69.     int32_t rc = recv(fd, buf, len, flags); 
  70. printf(">>>>>%s:%d\nfd:%d,len:%d,flags:%d,rc:%d\nTcpRecvMessages:buf:%s\n",__FILE__,__LINE__,fd,len,flags,rc,buf); 
  71.     if ((rc == -1) && (errno == EAGAIN)) { 
  72.         rc = 0; 
  73.     } else if (rc <= 0) { 
  74.         rc = -1;//rc = -1; //这里rc = -1,程序在这里跳出了,但是却找不到int32_t rc = recv(fd, buf, len, flags);的来源 
  75.     } 
  76.     return rc; 
  77. //通过添加2条打印信息发现,经过recv(fd, buf, len, flags)之后,buf有了数据,这数据来自手机端,并加密了。关于recv()打开下面文件 
  78. //Z:\harmony110\device\hisilicon\hispark_pegasus\sdk_liteos\third_party\lwip_sack\include\lwip\sockets.h:1589 
  79. //在函数的描述里可以看做,这里的recv()是作为API提供的,所以只能挖到这里了。 

auth.设备认证机制

authmanager【提供设备认证机制和设备知识库管理】

  1. 当发现有请求时,调用ProcessDataEvent函数,收包,检验包头,根据数据包的类型确定不同的处理方式。类型主要包括以下三种: 
  2. MODULE_AUTH_SDK     加密数据类型 
  3. MODULE_TRUST_ENGINE 可信类型,直接进行数据传输 
  4. MODULE_CONNECTION  进行ip及设备认证 
  5.  
  6. ├── BUILD.gn 
  7. ├── include 
  8. │   ├── auth_conn.h 
  9. │   ├── auth_interface.h 
  10. │   ├── bus_manager.h 
  11. │   ├── msg_get_deviceid.h 
  12. │   └── wifi_auth_manager.h 
  13. └── source 
  14.     ├── auth_conn.c【提供发送、接收、认证、获取秘钥功能】 
  15.     ├── auth_interface.c【管理各个会话节点、各个链接节点、各个秘钥节点,提供包括增删改查等功能】 
  16.     ├── bus_manager.c【主要通过deviceIp创建两个不同的listen,主要用来监听系统上有哪些device及新的device节点的创建;其中有两个回调函数OnConnectEvent和OnDataEvent,分别是用来处理设备节点的基本操作及节点数据的处理】 
  17.     ├── msg_get_deviceid.c【提供以cJSON格式获取各个设备的信息,包括设备id、链接信息、设备名、设备类型等】 
  18.     └── wifi_auth_manager.c【主要实现了连接管理和数据接收功能。连接管理包括连接的建立、断开及连接的查找。数据接收包括数据获取、包头及包长等的校验,并且为了简化包头数据读取,单独实现了对一个int型和一个long型数据的接收函数 

reference:

communication_dsoftbus: DSoftBus capabilities, including discovery, networking, and transmission | 软总线发现、组网、传输功能实现 (gitee.com)

文章相关附件可以点击下面的原文链接前往下载

原文链接:https://harmonyos.51cto.com/posts/4776

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-07-01 14:21:58

鸿蒙HarmonyOS应用

2022-01-12 14:45:26

鸿蒙HarmonyOS应用

2022-03-18 15:29:02

Harmony鸿蒙架构

2022-12-04 22:41:15

IPC分布式机制

2022-03-28 15:28:42

分布式软总线通讯Harmony

2021-10-26 07:59:22

鸿蒙HarmonyOS应用

2022-03-30 14:43:00

Harmony分布式软总线通讯

2020-11-16 11:29:40

HarmonyOS

2016-07-28 14:36:10

神州信息信息化IT

2023-02-20 15:38:38

2023-02-21 16:41:41

分布式相机鸿蒙

2023-02-20 15:29:14

分布式相机鸿蒙

2021-08-20 14:27:50

鸿蒙HarmonyOS应用

2009-08-26 16:37:04

ibmdwRational

2010-06-09 11:05:28

SPI总线协议

2022-11-28 15:42:39

分布式软总线鸿蒙

2015-04-15 09:23:03

AFormChange

2022-07-27 14:30:15

分布式数据鸿蒙

2012-07-10 11:08:52

asyncoro

2021-02-22 15:20:48

存储
点赞
收藏

51CTO技术栈公众号