authmanager模块是鸿蒙为设备提供认证机制的模块。模块内的主要处理过程包括报文的接收、解密、再次封装、加密、发送的步骤。本文重点介绍当有设备发起身份认证连接请求时,系统是如何管理的。处理过程主要集中在wifi_auth_manager.c文件中。
/*
函数功能: 处理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;
}
/*
函数功能:处理设备建立新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");
}
/*
函数功能:查找该连接的套接字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;
}
/*
函数功能:将当前已建立连接设备信息添加到已建立连接设备链表中
函数参数:
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;
}
/*用于管理连接设备的双向链表结构*/
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;
至此,设备发起新连接的处理结束。