tcp_session_manager.c代码分析中篇
本篇主要分析tcp_session_manager.c中出现的函数
和本篇代码相关的一些背景知识和该文件的上一部分代码详解:
tcp_socket机制详解
互斥锁和消息队列详解
tcp_session详解
tcp_session_manager.c代码分析上篇
二、代码分析
static bool AssignValue2Session(TcpSession *session, cJSON *receiveObj)
//标记值转换到session
{
if (receiveObj == NULL) {
return false;
//检查参数
}
char *recvBus = GetJsonString(receiveObj, "BUS_NAME");
//通过参数获取jsonstring
if (recvBus == NULL) {
return false;
//检查上一步是否成功获取
}
if (strncpy_s(session->sessionName, NAME_LENGTH, recvBus, strlen(recvBus)) != 0) {
return false;
}
char *sessionKeyEncoded = GetJsonString(receiveObj, "SESSION_KEY");
//获取sessionkey的json.string值
if (sessionKeyEncoded == NULL) {
return false;//检查是否获取成功
}
size_t olen = 0;
int ret = mbedtls_base64_decode((unsigned char *)session->sessionKey, SESSION_KEY_LENGTH,
&olen, (unsigned char *)sessionKeyEncoded, strlen(sessionKeyEncoded));
//基于base64进行编码
if (ret != 0) {
SOFTBUS_PRINT("[TRANS] AssignValue2Session mbedtls_base64_decode error: %d\n", ret);
return false;
//用来检查是否编码成功
}
SOFTBUS_PRINT("[TRANS] AssignValue2Session busname=%s, fd=%d\n", session->sessionName, session->fd);
return true;
}
static bool ResponseToClient(TcpSession *session)//客户端响应函数
{
cJSON *jsonObj = cJSON_CreateObject();
if (jsonObj == NULL) {
return false;
}
GetReplyMsg(jsonObj, session);//接受回复的消息
char *msg = cJSON_PrintUnformatted(jsonObj);
//将jsonObj转换为字符串数据
if (msg == NULL) {
cJSON_Delete(jsonObj);
return false;、
//检查是否转换成功
}
int bufLen = 0;
unsigned char *buf = PackBytes(msg, &bufLen);
//打包数据
if (buf == NULL) {
SOFTBUS_PRINT("[TRANS] ResponseToClient PackBytes fail\n");
free(msg);
cJSON_Delete(jsonObj);
return false;
}
int dataLen = TcpSendData(session->fd, (char*)buf, bufLen, 0);
//发送数据到tcp连接的另一端,datalen的值为发送的数据大小
free(msg);
cJSON_Delete(jsonObj);
free(buf);
if (dataLen <= 0) {
SOFTBUS_PRINT("[TRANS] ResponseToClient TcpSendData fail\n");
return false;
//检查数据是否发送到tcp另一端
}
return true;
}
static bool HandleRequestMsg(TcpSession *session)
//用来处理用户请求消息
{
char data[RECIVED_BUFF_SIZE] = { 0 };//初始化数组
int size = TcpRecvData(session->fd, data, AUTH_PACKET_HEAD_SIZE, 0);
//size为接收信息的数据大小
if (size != AUTH_PACKET_HEAD_SIZE) {
return false;
//检查接受的数据大小是否和用户数据包大小相同
}
int identifier = GetIntFromBuf(data, 0); 用来将data中内容以offset=0的偏置进行复制信息
if ((unsigned int)identifier != PKG_HEADER_IDENTIFIER) {
return false;
//检查是否复制成功
}
int dataLen = GetIntFromBuf(data, AUTH_PACKET_HEAD_SIZE - sizeof(int));
if (dataLen + AUTH_PACKET_HEAD_SIZE >= RECIVED_BUFF_SIZE) {
return false;
}
int total = size;
int remain = dataLen;
while (remain > 0) {
size = TcpRecvData(session->fd, data + total, remain, 0);
remain -= size;
total += size;
}
//如果有接收到数据,就将用户发送的信息不断接收到data当中(位置为data首地址+total)
cJSON *receiveObj = TransFirstPkg2Json(data, dataLen + AUTH_PACKET_HEAD_SIZE);
if (receiveObj == NULL) {
return false;
}
int ret = AssignValue2Session(session, receiveObj);
cJSON_Delete(receiveObj);
if (ret != true) {
return false;
}
//以上为两种数据的类型转换
SessionListenerMap *sessionListener = GetSessionListenerByName(session->sessionName, strlen(session->sessionName));
//通过name来启动监听
if (sessionListener == NULL) {
return false;
}
if (!ResponseToClient(session)) {
SOFTBUS_PRINT("[TRANS] HandleRequestMsg ResponseToClient fail\n");
return false;
//响应到客户端
}
if (sessionListener->listener == NULL) {
return false;
}
if (sessionListener->listener->onSessionOpened == NULL) {
return false;
}
if (sessionListener->listener->onSessionOpened(session->fd) != 0) {
return false;
}
//检测会话监听和相关session是否打开
return true;
}
static void FreeSessionRecvMem(char* recvDataBuf, TcpSession* session)//释放会话接收成员
{
if (recvDataBuf != NULL) {
free(recvDataBuf);
//检查如果传入的数组recvDataBuf不为空,就释放空间。
}
if (session == NULL) {
return;
}
CloseSession(session->fd);//根据传入的session,获取套接字关闭相应文件设备
}
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);
//calloc函数申请一个size+OVERHEAD_LEN大小的
if (recvDataBuf == NULL) {
return TRANS_FAILED;
//接收数据的缓冲区为空的话函数返回
}
int recvSize = TcpRecvData(session->fd, recvDataBuf, size + OVERHEAD_LEN, 0);
//从tcp的另一端接收数据,返回接受数据的大小
if (recvSize < TRANS_PACKET_HEAD_SIZE) {
FreeSessionRecvMem(recvDataBuf, session);
return TRANS_FAILED;
//接受的数据小于传输数据,就释放session会话成员
}
long long seq = 0;
AesGcmCipherKey cipherKey = {0};
cipherKey.keybits = GCM_KEY_BITS_LEN_256;
int ret = memcpy_s(&seq, SIZE_OF_LONG_LONG, recvDataBuf + TRANS_SEQ_NUM_OFFSET, SIZE_OF_LONG_LONG);//复制recvDataBuf + TRANS_SEQ_NUM_OFFSET开始的内容到seq
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);
//将接受的数据赋值进seq和cipherKey.iv,将对应session的键值复制进cipherKey.key
if (ret != 0) {
FreeSessionRecvMem(recvDataBuf, session);
return TRANS_FAILED;
//同来检查前面的复制是否存在失败,只要存在失败便ret<0
}
SessionSeqNumNode* node = calloc(1, sizeof(SessionSeqNumNode));//申请一个sizeof(SessionSeqNumNode)大小的数组
if (node == NULL) {
FreeSessionRecvMem(recvDataBuf, session);
return TRANS_FAILED;
}
node->seqNum = seq;
ListInsertTail(session->seqNumList, &(node->head));//将&(node->head)插入链表session->seqNumList
int plainLen = DecryptTransData(&cipherKey, (unsigned char*)(recvDataBuf + TRANS_PACKET_HEAD_SIZE),
recvSize - TRANS_PACKET_HEAD_SIZE, (unsigned char*)buf, size);
//对cipherKey密钥进行加密
free(recvDataBuf);//释放数据缓冲
if (plainLen <= 0) {
return TRANS_FAILED;
}
return plainLen;
}
static bool OnProcessDataAvailable(TcpSession *session)
{
if (session == NULL) {
return false;
}
if (strcmp(session->sessionName, "softbus_Lite_unknown") == 0) {
//比较会话名和softbus_Lite_unknown是否相同
bool isSuccess = HandleRequestMsg(session);
if (!isSuccess) {
//如果处理请求信息不成功就关闭session—>fd套接字对应设备
CloseSession(session->fd);
}
return isSuccess;
} else {//如果
unsigned char* buf = calloc(1, RECIVED_BUFF_SIZE);
if (buf == NULL) {
return false;
}
SOFTBUS_PRINT("[TRANS] OnProcessDataAvailable sessionName: %s, fd: %d\n", session->sessionName, session->fd);
SessionListenerMap *sessionListener = GetSessionListenerByName(session->sessionName,
strlen(session->sessionName));
if (sessionListener != NULL && sessionListener->listener != NULL) {
int recvLen = TcpSessionRecv(session, (char *)buf, RECIVED_BUFF_SIZE, 0);
if (recvLen < 0) {
free(buf);
return false;
}
sessionListener->listener->onBytesReceived(session->fd, buf, recvLen);
free(buf);
return true;
}
free(buf);
}
return false;
}
static void ProcessSesssionData(const TcpSessionMgr *tsm, const fd_set *rfds)
{
for (int i = 0; i < MAX_SESSION_SUM_NUM; i++) {
if (tsm->sessionMap_[i] != NULL && tsm->sessionMap_[i]->fd != -1 &&
FD_ISSET(tsm->sessionMap_[i]->fd, rfds) > 0) {
if (!OnProcessDataAvailable(tsm->sessionMap_[i])) {
return;
}
}
}
}
static void ProcessData(TcpSessionMgr *tsm, fd_set *rfds)//来检查tsm变量的监听套接字是否在集合rfds中,在的话根据套接字连接监听的进程
{
if (tsm == NULL || tsm->listenFd == -1) {
return;
}
if (FD_ISSET(tsm->listenFd, rfds)) {
ProcessConnection(tsm);
return;
}
ProcessSesssionData(tsm, rfds);
}
static void FreeSessionMgr(void)//释放会话管理
{
free(g_sessionMgr);
g_sessionMgr = NULL;
}