往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- 【OpenHarmony】鸿蒙南向开发保姆级知识点汇总~
- OpenHarmony源码分析之分布式软总线:trans_service模块(1)/认证通道管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(2)/会话管理之新会话
- OpenHarmony源码分析之分布式软总线:trans_service模块(3)/线程同步锁管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(4)/TCP会话管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(5)/TCP会话管理
- OpenHarmony源码分析之分布式软总线:trans_service模块(6)/TCP会话管理
- 持续更新中……
一、概述
trans_service模块基于系统内核提供的socket通信,向authmanager模块提供设备认证通道管理和设备认证数据的传输;向业务模块提供session管理和基于session的数据收发功能,并且通过GCM模块的加密功能提供收发报文的加解密保护。 本文是分布式软总线的会话管理机制的结尾部分,在前文中介绍了新会话中客户端请求数据的处理过程,本文重点介绍普通会话中的新数据处理。衔接OpenHarmony源码分析之分布式软总线:trans_service模块(5)/TCP会话管理 。
二、源码分析
- 在函数OnProcessDataAvailable()中,先根据会话名称进行判断,该设备是否属于未知设备,如果不是,将进行常规处理。首先根据会话名字在会话管理器的会话监听器表中查找相应会话监听器,若会话监听器已存在,则表明该会话已创建,然后在TcpSessionRecv()中接收会话新数据并进行解密,返回明文数据。TcpSessionRecv()函数的具体分析如下:
/*
函数功能:接收TCP会话新数据,并进行解密
函数参数:
session:tcp通信会话
buf:用于存储接收到并解密成功的明文数据
size:除去OVERHEAD_LEN部分的数据长度
timeout:超时时间
函数返回值:
成功:返回实际接收到的明文数据长度
失败:返回TRANS_FAILED(-1)
详细:
*/
static int32_t TcpSessionRecv(TcpSession *session, const char* buf, uint32_t size, int timeout)
{
if (buf == NULL || session == NULL || session->fd < 0 || size <= 0 || timeout < 0) {
return TRANS_FAILED;
}
char *recvDataBuf = calloc(1, size + OVERHEAD_LEN);
if (recvDataBuf == NULL) {
return TRANS_FAILED;
}
int recvSize = TcpRecvData(session->fd, recvDataBuf, size + OVERHEAD_LEN, 0);//接收TCP数据保存在recvDataBuf中,预读取size + OVERHEAD_LEN的数据量,返回实际读到的数据量
if (recvSize < TRANS_PACKET_HEAD_SIZE) {
FreeSessionRecvMem(recvDataBuf, session);
return TRANS_FAILED;
}
long long seq = 0;
AesGcmCipherKey cipherKey = {0};
cipherKey.keybits = GCM_KEY_BITS_LEN_256;//采用256位的密钥加解密
int ret = memcpy_s(&seq, SIZE_OF_LONG_LONG, recvDataBuf + TRANS_SEQ_NUM_OFFSET, SIZE_OF_LONG_LONG);//获取数据包的序列号
ret += memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, session->sessionKey, SESSION_KEY_LENGTH);//赋予会话密钥
ret += memcpy_s(cipherKey.iv, IV_LEN, recvDataBuf + TRANS_PACKET_HEAD_SIZE, IV_LEN);//赋予会话iv值
if (ret != 0) {
FreeSessionRecvMem(recvDataBuf, session);
return TRANS_FAILED;
}
SessionSeqNumNode* node = calloc(1, sizeof(SessionSeqNumNode));
if (node == NULL) {
FreeSessionRecvMem(recvDataBuf, session);
return TRANS_FAILED;
}
node->seqNum = seq;//赋予数据包序列号
ListInsertTail(session->seqNumList, &(node->head));//将该数据包序列号节点插入seqNumList链表尾部
int plainLen = DecryptTransData(&cipherKey, (unsigned char*)(recvDataBuf + TRANS_PACKET_HEAD_SIZE),
recvSize - TRANS_PACKET_HEAD_SIZE, (unsigned char*)buf, size);//解密传输数据,解密后的明文保存在buf中
free(recvDataBuf);
if (plainLen <= 0) {
return TRANS_FAILED;
}
return plainLen;
}
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: