> 文档中心 > OpenHarmony源码分析之分布式软总线:authmanager模块(1)/设备认证连接管理

OpenHarmony源码分析之分布式软总线:authmanager模块(1)/设备认证连接管理


一、 概述

authmanager模块是鸿蒙为设备提供认证机制的模块。模块内的主要处理过程包括报文的接收、解密、再次封装、加密、发送的步骤。本文重点介绍当有设备发起身份认证连接请求时,系统是如何管理的。处理过程主要集中在wifi_auth_manager.c文件中。

二、 源码分析

  1. 当有设备发起连接请求时,首先在trans_service模块建立socket连接,主要在函数 ProcessAuthData() 中实现:
/*函数功能: 处理listenFd的事件调用accept建立连接生成通信描述符g_dataFd,或者处理g_dataFd的通信事件函数参数:监听描述符listenFd,可读描述符集合函数返回值:成功返回true,失败返回false详细:*/static bool ProcessAuthData(int listenFd, const fd_set *readSet){    if (readSet == NULL || g_callback == NULL || g_callback->onConnectEvent == NULL || g_callback->onDataEvent == NULL) { return false;    }//如果有设备发起连接,响应listenFd事件,accept建立socket连接,然后调用回调函数onConnectEvent处理连接事件    if (FD_ISSET(listenFd, readSet)) { struct sockaddr_in addrClient = {0}; socklen_t addrLen = sizeof(addrClient);//建立socket连接 g_dataFd = accept(listenFd, (struct sockaddr *)(&addrClient), &addrLen); if (g_dataFd < 0) {//accept函数执行出错     CloseAuthSessionFd(listenFd);     return false; } //更新最大描述符值,因为后续需要为select函数提供最大描述符值,select函数需要获得监听集合中所有文件描述符的范围 RefreshMaxFd(g_dataFd); //响应新连接事件 if (g_callback->onConnectEvent(g_dataFd, inet_ntoa(addrClient.sin_addr)) != 0) {     CloseAuthSessionFd(g_dataFd); }    }//如果接收到设备发送的可读数据,响应g_dataFd的事件,调用回调函数onDataEvent处理数据传输事件    if (g_dataFd > 0 && FD_ISSET(g_dataFd, readSet)) { g_callback->onDataEvent(g_dataFd);//响应通信新数据事件    }    return true;}
  1. 为处理新连接,调用 onConnectEvent() 函数,在该函数中又调用了 ProcessConnectEvent() 函数,此函数才是真正的处理连接函数:
/*函数功能:处理设备建立新socket连接事件函数参数:    fd:通信fd    ip:请求连接的设备IP地址字符串函数返回值:0详细:*/int OnConnectEvent(int fd, const char *ip){    ProcessConnectEvent(fd, ip);//处理建立新socket连接事件    return 0;}/*函数功能:处理设备建立新socket连接事件函数参数:    fd:用于通信的套接字fd    ip:请求连接的设备IP地址字符串函数返回值:无详细:*/void ProcessConnectEvent(int fd, const char *ip){    SOFTBUS_PRINT("[AUTH] ProcessConnectEvent fd = %d\n", fd);    if (fd < 0 || ip == NULL) { return;    }    AuthConn *aconn = FindAuthConnByFd(fd);//通过fd查找认证连接链表中是否已存在该设备    if (aconn != NULL) { CloseConn(aconn); return;    }    //若不存在,则添加到设备认证连接链表中    aconn = calloc(1, sizeof(AuthConn));//新建一个待认证设备连接信息体    if (aconn == NULL) { return;    }    int ret = strcpy_s(aconn->deviceIp, sizeof(aconn->deviceIp), ip);//赋值设备IP    if (ret != EOK) { free(aconn); aconn = NULL; return;    }    aconn->fd = fd;//赋值与该设备通信的套接字描述符    ret = AddAuthConnToList(aconn);//将aconn连接添加到已建立socket连接设备链表中    if (ret != 0) { AuthConnClose(aconn); free(aconn); aconn = NULL; return;    }    SOFTBUS_PRINT("[AUTH] ProcessConnectEvent ok\n");}
  1. 在函数 ProcessConnectEvent() 中,首先判断在全局认证设备链表中是否已存在该设备:
/*函数功能:查找该连接的套接字fd是否已在设备链表中函数参数:    fd:建立连接的套接字fd函数返回值:    若该设备已存在则返回设备连接信息,若不存在则返回NULL详细:*/static AuthConn* FindAuthConnByFd(int fd){    if (g_fdMap == NULL) { return NULL;    }    AuthConnNode *node = NULL;    List *pos = NULL;    List *tmp = NULL;//遍历g_fdMap链表,该链表只存储认证连接设备节点地址    LIST_FOR_EACH_SAFE(pos, tmp, g_fdMap) { node = (AuthConnNode*)pos; if (node->aconn == NULL) {     continue; } if (node->aconn->fd == fd) {//若该设备已存在,则返回该设备的连接信息     return node->aconn; }    }    return NULL;}
  1. 若该设备不存在,则将其添加到设备认证连接链表中:
/*函数功能:将当前已建立连接设备信息添加到已建立连接设备链表中函数参数:    aconn:当前连接的设备连接信息结构体地址函数返回值:    成功:返回0    失败:返回-1详细:*/static int AddAuthConnToList(AuthConn *aconn){    if (aconn == NULL) { return -1;    }    if (g_fdMap == NULL) {//如果认证连接链表未初始化,就申请空间并初始化 g_fdMap = calloc(1, sizeof(List)); if (g_fdMap == NULL) {     return -1; } ListInitHead(g_fdMap);//初始化已建立连接设备的双向链表头指针    }    if (ListLength(g_fdMap) >= AUTH_CONN_MAX_NUM) {//不允许超过最大连接设备数量32 return -1;    }    AuthConnNode *node = calloc(1, sizeof(AuthConnNode));//申请设备节点内存    if (node == NULL) { return -1;    }    node->aconn = aconn;    ListInsertTail(g_fdMap, &node->head);//将新节点插入到链表末尾    SOFTBUS_PRINT("[AUTH] AddAuthConnToList add new node(%d) ok\n", aconn->fd);    return 0;}void ListInitHead(List *head)//初始化头指针{    head->next = head;    head->prev = head;}/*函数功能:将新增节点插入双向链表末尾函数参数:head      链表头指针;node    新增节点指针函数返回值:无详细:*/void ListInsertTail(List *head, List *node)//将新增节点插入双向链表末尾{    node->prev = head->prev;    node->prev->next = node;    node->next = head;    head->prev = node;}
  1. 本模块涉及的关键数据结构:
/*用于管理连接设备的双向链表结构*/typedef struct List {//双向链表    struct List *prev;    struct List *next;} List;static List *g_fdMap = NULL;//全局已建立连接设备双向链表头指针/*AuthConn结构体用于保存已建立socket连接的身份认证设备的基本信息以及状态信息*/typedef struct AuthConn {    int fd;//通信套接字描述符    char authId[MAX_AUTH_ID_LEN];//身份认证id    char deviceId[MAX_DEV_ID_LEN];//设备id    char deviceIp[MAX_DEV_IP_LEN];//设备IP    int busVersion;//总线版本    int authPort;//认证通道端口    int sessionPort;//会话通道端口    int authState;//认证状态    int onlineState;//设备在线状态    DataBuffer db;//数据缓冲区} AuthConn;/*设备身份认证连接节点*/typedef struct AuthConnNode {    List head;//头指针    AuthConn *aconn;//设备连接信息} AuthConnNode;

至此,设备发起新连接的处理结束。