您当前的位置: 首页 > 

小生叫安辰

暂无认证

  • 5浏览

    0关注

    105博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

鸿蒙源码分析(十二)

小生叫安辰 发布时间:2021-08-04 13:34:32 ,浏览量:5

tcp_session_manager.c代码分析下篇

本篇主要分析tcp_session_manager.c中出现的函数

一、相关链接

和本篇代码相关的一些背景知识和该文件的上一部分代码详解:

  1. tcp_socket机制详解
  2. 互斥锁和消息队列详解
  3. tcp_session详解
  4. tcp_session_manager.c代码分析上篇
  5. tcp_session_manager.c代码分析中篇
二、代码分析

SelectSessionLoop函数用来处理会话线程数据

static void SelectSessionLoop(TcpSessionMgr *tsm)
{
    if (tsm == NULL) {
        return;
    }
    SOFTBUS_PRINT("[TRANS] SelectSessionLoop begin\n");
    tsm->isSelectLoopRunning = true;
    while (true) {
        fd_set readfds;
        fd_set exceptfds;
        int maxFd = InitSelectList(tsm, &readfds, &exceptfds);
        //将tsm中非空元素的套接字写进readfds集合和exceptfds集合
        if (maxFd = NAME_LENGTH) {
        SOFTBUS_PRINT("[TRANS] CreateSessionServerInner name length is too big\n");
        return TRANS_FAILED;
        //检查会话名和模块名字的标准是否合格
    }
    int findIndex = -1;
    for (int i = 0; i serverListenerMap[i] == NULL) {
            findIndex = i;
            break;
            //遍历所有会话服务器,找出空值对应下标
        }
    }
    if (findIndex == -1) {
        return TRANS_FAILED;
    }
    if (findIndex >= 0 && findIndex serverListenerMap[findIndex] = calloc(1, sizeof(SessionListenerMap));
        if (g_sessionMgr->serverListenerMap[findIndex] == NULL) {
            return TRANS_FAILED;
            //对上次找出空值,将空值对应位置申请空间内存
        }
        SessionListenerMap *listenerMap = g_sessionMgr->serverListenerMap[findIndex];
        if (strncpy_s(listenerMap->sessionName, NAME_LENGTH, sessionName, strlen(sessionName)) ||
            strncpy_s(listenerMap->moduleName, NAME_LENGTH, moduleName, strlen(moduleName))) {
                //将会话名二号模块名字复制到指定位置
            free(listenerMap);
            listenerMap = NULL;
            return TRANS_FAILED;
        }
        listenerMap->listener = listener;//监听变量赋值
    }
    return 0;
}

RemoveSessionServerInner通过模块名和会话名实现服务器的删除

static int RemoveSessionServerInner(const char* moduleName, const char *sessionName)//删除内部服务器
{
    if (g_sessionMgr == NULL) {
        return TRANS_FAILED;
    }//检查参数
    int removeFd = -1;
    for (int i = 0; i sessionMap_[i] != NULL &&
            strcmp(g_sessionMgr->sessionMap_[i]->sessionName, sessionName) == 0) {
            removeFd = g_sessionMgr->sessionMap_[i]->fd;
            //检查非空值释放会话空间并且关闭数据传输会话
            CloseTransSession(removeFd);
            free(g_sessionMgr->sessionMap_[i]);
            g_sessionMgr->sessionMap_[i] = NULL;
        }
    }
    for (int i = 0; i serverListenerMap[i];
        if (serverListener != NULL && (strcmp(serverListener->sessionName, sessionName) == 0) &&
        //检查服务器监听是否开启,以及监听会话名和传入的会话名是否相同,监听的模块名和传入的模块名是否相同
            (strcmp(serverListener->moduleName, moduleName) == 0)) {
            if (serverListener->listener != NULL && serverListener->listener->onSessionClosed != NULL) {
                serverListener->listener->onSessionClosed(removeFd);//关闭会话
            }
            free(serverListener);//关闭服务器的监听
            serverListener = NULL;
            break;
        }
    }
    return 0;
}

该条件编译中第一部分函数已在前面出现过,主要用来处理线程数据

#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__)
int StartSelectLoop(TcpSessionMgr *tsm)
{
    if (tsm == NULL) {
        return TRANS_FAILED;
    }

    if (tsm->isSelectLoopRunning) {
        return 0;
    }

    osThreadId_t sessionLoopTaskId;

    osThreadAttr_t attr;
    attr.name = "trans_session_task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = (LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE * 2);
    attr.priority = osPriorityNormal5; // LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO -> cmsis prio

    sessionLoopTaskId = osThreadNew((osThreadFunc_t)SelectSessionLoop, (void *)tsm, &attr);
    if (NULL == sessionLoopTaskId) {
        SOFTBUS_PRINT("[TRANS] StartSelectLoop TaskCreate fail\n");
        return TRANS_FAILED;
    }

    return 0;
}

该代码块主要用来创建线程,实现线程中数据处理

#else
#define MIN_STACK_SIZE 0x8000
static pthread_key_t g_localKey = 0;
typedef void *(*Runnable)(void *argv);
typedef struct ThreadAttr ThreadAttr;
struct ThreadAttr {
    const char *name;   // 线程
    uint32_t stackSize;   // 堆栈大小
    uint8_t priority;     // 优先级
    uint8_t reserved1;    // reserved1 (must be 0)//可以看作是端口
    uint16_t reserved2;   // reserved2 (must be 0)
};
typedef void *ThreadId;

ThreadId TcpCreate(Runnable run, void *argv, const ThreadAttr *attr)//用来创建一个tcp相关的线程
{
    if (attr == NULL) {
        return NULL;
    }
    int ret;
    pthread_attr_t threadAttr;

    ret = pthread_attr_init(&threadAttr);//对线程进行初始化
    if (ret != 0) {//初始化是否成功
        SOFTBUS_PRINT("[TRANS] TcpCreate pthread attr init fail\n");
    }
    ret = pthread_attr_setstacksize(&threadAttr, (attr->stackSize | MIN_STACK_SIZE));
    //指定线程堆栈区的大小
    if (ret != 0) {
        SOFTBUS_PRINT("[TRANS] TcpCreate pthread attr setstacksize fail\n");//分配大小是否成功
    }
    struct sched_param sched = {attr->priority};
    ret = pthread_attr_setschedparam(&threadAttr, &sched);//用于设置线程的调用策略和优先级,第一个参数为线程ID,第二个参数优先级
    if (ret != 0) {
        SOFTBUS_PRINT("[TRANS] TcpCreate pthread attr setschedparam fail\n");
        //检查是否优先级设置失败
    }
    ret = pthread_key_create(&g_localKey, NULL);//对线程池中找到数据分配至g_localKey,第二个参数为清理函数。NULL表示选择默认的数据清理函数
    if (ret != 0) {
        SOFTBUS_PRINT("[TRANS] TcpCreate pthread key create fail\n");
    }

    pthread_t threadId = 0;
    ret = pthread_create(&threadId, &threadAttr, run, argv);//创建一个线程
    /*第一个参数为指向线程 标识符的指针。
    第二个参数用来设置线程属性。
    第三个参数是线程运行函数的起始地址。
    最后一个参数是运行函数的参数。*/
    if (ret != 0) {
        return NULL;
    }
    return (ThreadId)threadId;//最后返回线程的ID
}

int StartSelectLoop(TcpSessionMgr *tsm)//线程处理所有的会话数据接收
{
    if (tsm == NULL) {
        return TRANS_FAILED;
        //检查参数
    }
    if (tsm->isSelectLoopRunning) {
        return 0;
        //检查tsm的SelectLoop状态是否运行
    }
    ThreadAttr attr = {"tcp", 0x800, 20, 0, 0};
    register ThreadId threadId = (ThreadId)TcpCreate((Runnable)SelectSessionLoop, tsm, &attr);
    //创建并定义了一个寄存器线程变量
    if (threadId == NULL) {
        return TRANS_FAILED;
    }
    tsm->isSelectLoopRunning = true;//线程处理中
}
#endif

CreateTcpSessionMgr函数和RemoveTcpSessionMgr实现TcpSessionMgr的创建和删除,参数为服务器和本地ip

int CreateTcpSessionMgr(bool asServer, const char* localIp)//传入一个服务器和本地ip来创建一个tcp会话管理器
{
    if (localIp == NULL) {//检查传入的ip参数是否为空
        return TRANS_FAILED;
    }

    if (InitTcpMgrLock() != 0 || GetTcpMgrLock() != 0) {
        return TRANS_FAILED;
        //初始化mutex相关锁和互斥体。申请互斥锁
    }
    int ret = InitGSessionMgr();
    if (ReleaseTcpMgrLock() != 0 || ret != 0) {
        FreeSessionMgr();
        //初始化GSessionMgr失败iu释放互斥锁,函数退出
        return TRANS_FAILED;
    }
    g_sessionMgr->asServer = asServer;
    int listenFd = OpenTcpServer(localIp, DEFAULT_TRANS_PORT);//根据端口和ip打开服务器,并将套接字写进listenfd
    if (listenFd listenFd = listenFd;//将服务器的套接字写进g_sessionMgr->listenFd
    signal(SIGPIPE, SIG_IGN);//使用函数来处理信号SIGPIPE,SIG_IGN为忽视信号函数
    if (StartSelectLoop(g_sessionMgr) != 0) {//使用线程处理g_sessionMgr中数据
        SOFTBUS_PRINT("[TRANS] CreateTcpSessionMgr StartSelectLoop fail\n");
        CloseSession(listenFd);
        FreeSessionMgr();
        return TRANS_FAILED;
    }
    return GetSockPort(listenFd);
    //返回listenFd对应套接字的socket端口
}

int RemoveTcpSessionMgr(void)//删除TcpSessionMgr
{
    if (g_sessionMgr == NULL) {
        return TRANS_FAILED;//检查g_sessionMgr
    }

    CloseAllSession(g_sessionMgr);
    //关闭g_sessionMgr相关所有session
    if (GetTcpMgrLock() != 0) {//申请互斥锁
        return TRANS_FAILED;
    }

    CloseFd(g_sessionMgr->listenFd);//关闭g_sessionMgr->listenFd对应文件设备
    g_sessionMgr->listenFd = -1;//将listenfd改为-1,相当于没有所连接的listenfd

    if (ReleaseTcpMgrLock() != 0) {
        return TRANS_FAILED;
        //释放互斥锁。
    }
    return 0;
}

CreateSessionServer函数和RemoveSessionServer为创建和删除会话服务器的函数 通过会话名,模块名,监听名

int CreateSessionServer(const char* moduleName, const char* sessionName, struct ISessionListener *listener)//创建会话服务器
{
    if (moduleName == NULL || sessionName == NULL || listener == NULL) {
        return TRANS_FAILED;//检查参数
    }

    if (SoftBusCheckPermission(SOFTBUS_PERMISSION_NAME) != 0) {
        return TRANS_FAILED;//检查权限
    }

    if (GetTcpMgrLock() != 0) {
        return TRANS_FAILED;//申请互斥锁,一边操作数据文件设备
    }

    int ret = CreateSessionServerInner(moduleName, sessionName, listener);//根据moduleName, sessionName, listener创建一个内部的会话服务器

    if (ReleaseTcpMgrLock() != 0) {
        return TRANS_FAILED;
        //释放互斥锁
    }
    return ret;
}
int RemoveSessionServer(const char* moduleName, const char *sessionName)//删除会话服务器
{
    if (moduleName == NULL || sessionName == NULL) {
        SOFTBUS_PRINT("[TRANS] moduleName == NULL || sessionName == NULL\n");
        return TRANS_FAILED;//检查参数
    }

    if (SoftBusCheckPermission(SOFTBUS_PERMISSION_NAME) != 0) {
        return TRANS_FAILED;//检查用户的权限
    }

    if (GetTcpMgrLock() != 0) {
        return TRANS_FAILED;//申请加互斥锁
    }

    int ret = RemoveSessionServerInner(moduleName, sessionName);//删除内部的会话服务器

    if (ReleaseTcpMgrLock() != 0) {
        return TRANS_FAILED;//释放锁
    }

    return ret;
}

SendBytes和TransPackBytes两个函数实现数据传输并加密。将session会话中sendData中数据发送带连接另一端的socket,大小为sendDataLen。传输依赖于ace_gcm.c文件中EncryptTransData函数,实现数据的传输和加密。

static unsigned char *TransPackBytes(TcpSession *session, const unsigned char *sendData, unsigned int sendDataLen,
    int *bufLen)
{
    if (session == NULL || sendData == NULL || bufLen == NULL || sendDataLen > SEND_BUFF_MAX_SIZE || sendDataLen == 0) {
        return NULL;//检查传入参数
    }

    int allLen = sendDataLen + TRANS_PACKET_HEAD_SIZE + OVERHEAD_LEN;
    if (allLen > RECIVED_BUFF_SIZE || allLen seqNum++;
    unsigned char *buf = (unsigned char *)malloc(allLen);//申请一个buf数组
    if (buf == NULL) {
        return NULL;
    }

    memset_s(buf, allLen, 0, allLen);//初始化buf数组
    unsigned int magicnum = PKG_HEADER_IDENTIFIER;

    AesGcmCipherKey cipherKey = {0};
    unsigned char* randomIv = GenerateRandomIv();
    if (randomIv == NULL) {
        free(buf);
        return NULL;
    }

    int offset = 0;
    int ret = memcpy_s(buf + offset, allLen - offset, &magicnum, SIZE_OF_INT);
    offset += SIZE_OF_INT;
    ret += memcpy_s(buf + offset, allLen - offset, &seqNum, SIZE_OF_INT);
    offset += SIZE_OF_INT;
    ret += memcpy_s(buf + offset, allLen - offset, &flags, SIZE_OF_INT);
    offset += SIZE_OF_INT;
    int dataLen = sendDataLen + OVERHEAD_LEN;
    ret += memcpy_s(buf + offset, allLen - offset, &dataLen, SIZE_OF_INT);
    offset += SIZE_OF_INT;
    //不断将magicnum,seqNum,flags,dataLen中内容复制到指定数组buf的指定位置

    cipherKey.keybits = GCM_KEY_BITS_LEN_256;
    ret += memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, session->sessionKey, SESSION_KEY_LENGTH);
    ret += memcpy_s(cipherKey.iv, IV_LEN, randomIv, IV_LEN);
    //将session->sessionKey写进cipherKey.key,将随机向量randomIv写进cipherKey.iv,同时释放randomIv
    free(randomIv);
    ret += memcpy_s(cipherKey.iv, SIZE_OF_INT, &seqNum, SIZE_OF_INT);
    if (ret != 0) {
        free(buf);
        return NULL;
    }
    int cipherLen = EncryptTransData(&cipherKey, sendData, sendDataLen, buf + offset, sendDataLen + OVERHEAD_LEN);//对数据发送并进行加密,写进buf
    if (cipherLen  len) {
        SOFTBUS_PRINT("[TRANS] len is too small.\n");
        return TRANS_FAILED;
        //检查len和id长度
    }

    if (strncpy_s(devId, len, id, strlen(id)) != 0) {
        SOFTBUS_PRINT("[TRANS] devId copy failed.\n");
        return TRANS_FAILED;
        //将id中内容复制到devid中指定位置
    }
    return 0;
}

CloseSession函数实现会话的关闭

void CloseSession(int sessionId)//关闭会话
{
    if (SoftBusCheckPermission(SOFTBUS_PERMISSION_NAME) != 0) {
        return;
        //检查权限后退出
    }

    if (GetTcpMgrLock() != 0) {
        return;
        //获取tcp管理互斥锁后退出
    }
    CloseTransSession(sessionId);
    if (ReleaseTcpMgrLock() != 0) {
        return;
        //释放tcp互斥锁后退出
    }
    return;
}
关注
打赏
1635606302
查看更多评论
立即登录/注册

微信扫码登录

0.3659s