详解C语言开发unixLinux下安全套接字(SSL)的TCP服务端程序

    技术2022-05-20  49

    本文详细说明了用C语言开发UNIX/Linux下安全套接字(TCP SSL)

    的服务端程序,采用IO多路复用,单进程单线程,自定义并实现

    缓存,链表等数据结构,代码由本人亲自编写,在IBM AIX,

    Solaris,Linux多个版本下都能够稳定运行,下面详解程序

    软件要求:

         OpenSSL

          编译器  GCC

          编译命令  GCC 文件名.c -o SSLServer.o -lpthread -lssl -lcrypto

     

     

     //系统头文件

     #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <signal.h> #include <sys/socket.h>  #include <sys/select.h>  #include <sys/time.h>  //SSL 头文件  #include <openssl/rsa.h>       /* SSLeay stuff */  #include <openssl/crypto.h>  #include <openssl/x509.h>  #include <openssl/pem.h>  #include <openssl/ssl.h>  #include <openssl/err.h>

     //下面3个文件都存在于执行程序的路径下

     //如何制作请参阅OpenSSL说明文档,这里就不细说了

     #define USE_SSL_CERTF  "server.crt"  //服务器证书文件名 #define USE_SSL_KEYF  "server.key"   //密钥文件文件名 #define USE_SSL_CACERT "ca.crt"       //CA 的证书文件名      //监听的端口号  #define   TCP_LISTENPORT         9001  //最大接收发送的消息长度(字节)  #define   MAX_RCVSNDMSG_SIZE     1024*16

      //同是最多可连接的客户端数量  #define   MAX_CLIENT_COUNT      512  //心跳消息内容,这里使用txt,如果是二进制的则需要从新构造和计算长度(字节)  #define   HEARTBEAT_MESSAGE     "HEARTBEAT/n"  #define   HEARTBEAT_MSGLEN      10    //strlen("HEARTBEAT/n")  //心跳检测周期(秒)  #define   HEARTBEAT_TIMEOUT     20  //SSL_accept的超时(秒),由于SSL_accept不影响select的结果,所以只能

      //循环调用SSL_accept检查成功或失败  #define  SSLACCEPT_TIMEOUT      20

     

    //首先,初始化SSL库,下面定义的结构体

        typedef struct _tagAgent_ssl   {        bool         t_enable;        SSL_CTX     *t_ssl_ctx;        SSL_METHOD  *t_ssl_meth;    }AG_SSL,*LPAG_SSL;

       

        bool InitSSL(struct AG_SSL *pAgSSL)   {        char strCWD[512],strName[512];        memset(strCWD,0,sizeof(strCWD));        memset(strName,0,sizeof(strName));        //获取当前路径        getcwd(strCWD,sizeof(strCWD)-1);        //进行SSL信息的初始化        SSL_load_error_strings();        SSLeay_add_ssl_algorithms();        //        pAgSSL->t_ssl_meth = SSLv23_server_method();        pAgSSL->t_ssl_ctx = SSL_CTX_new (pAgSSL->t_ssl_meth);           if (!pAgSSL->t_ssl_ctx)        {           printf("SSL_CTX_new  failed!/n");           return false;        }        snprintf(strName,sizeof(strName)-1,"%s/%s",strCWD,USE_SSL_CERTF);        if (SSL_CTX_use_certificate_file(pAgSSL->t_ssl_ctx, strName, SSL_FILETYPE_PEM) <= 0)        {           printf("SSL_CTX_use_certificate_file  failed!/n");           return false;       }       EVP_PKEY *pkey;       snprintf(strName,sizeof(strName)-1,"%s/%s",strCWD,USE_SSL_KEYF);       if (SSL_CTX_use_PrivateKey_file(pAgSSL->t_ssl_ctx, strName, SSL_FILETYPE_PEM) <= 0)       {           printf("SSL_CTX_use_PrivateKey_file  failed!/n");           return false;       }       if (!SSL_CTX_check_private_key(pAgSSL->t_ssl_ctx))      {          printf("Private key does not match the certificate public key/n");          return false;      }      pAgSSL->t_enable = true;      return true;   }

    //监听端口

      //以下是需要使用的数据结构和处理函数  //我们需要一个缓存结构,处理socket数据的发送和接收 typedef struct _tagAgent_DynticBuffer {  unsigned int m_buf_length;  //缓冲区长度  unsigned int m_buf_datalen; //缓冲区内数据长度  char          *m_buf_ptr;    //缓冲区首地址 }AG_BUFFER,*LPAG_BUFFER;

     //控制函数:

     //初始化 void AgBufferReady(LPAG_BUFFER pBuf); //清空缓存数据 void AgBufferResetMem(LPAG_BUFFER pBuf); //释放缓存空间 void AgBufferFreeMem(LPAG_BUFFER pBuf); //创建缓存 LPAG_BUFFER AgBufferCreate(int iSize,bool IsZeroMem);  //从头移除数据块,剩余数据移动 void AgBufferDecLenFromHead(LPAG_BUFFER pBuf,int iOffset); //从尾部添加数据块 void AgBufferAppendData(LPAG_BUFFER pBuf,char *pData,int iSize,bool bRemoveLastZero); //从尾移除数据块,剩余数据不移动 void AgBufferDecLenFromTail(LPAG_BUFFER pBuf,int iOffset); 

    //以上函数代码在后面给出

     //我们也需要一个结构体,存储socket连接信息 typedef enum _euSockStatus {  sock_down = 1,         //断开  sock_listen = 4,         //监听  sock_accept = 5,       //SSL_accept成功的client }euSockStatus; typedef enum _euSSLacceptChk {  chk_success = 0,      //检查通过  chk_fail = 2,              //SSL_accept失败  chk_continue = 3      //SSL_accept 未决,继续检查 }euSSLacceptChk; //存储活动套接字信息 typedef struct _tagAgent_Net {  SOCKET t_sock;         //套接字描述符  int    t_flags;              //套接字初始option(阻塞)  SOCKADDR_IN t_sa;  //目标网络地址  SSL *t_ssl;                 //ssl结构指针  time_t t_sslaccp_begintime;      //第一次调用SSL_accept时间  time_t t_connected_time;          //连接上来的时间  enum _euSockStatus t_status;  //当前状态  bool t_begin_stream;                 //是否通过了ssl_accept连接检查  AG_BUFFER *t_rcvbuf;                //接收数据缓存指针  AG_BUFFER *t_sndbuf;               //发送数据缓存指针 }AG_NET,*LPAG_NET;

     //控制函数

     //初始化

     void AgNetItemReset(LPAG_NET pNetItem){

      AgNetItemClear(pNetItem);

      t_ssl = 0;

      t_rcvbuf = 0;

      t_sndbuf = 0;

      //注意 t_ssl,t_rcvbuf,t_sndbuf 三个指针类型成员初始为空

    }

    //复位,除t_ssl,t_rcvbuf,t_sndbuf 这3个指针外,其余

    //成员复位。 void AgNetItemClear(LPAG_NET pNetItem) {  pNetItem->t_sock = -1;  memset(&pNetItem->t_sa,0,sizeof(SOCKADDR_IN));  memset(pNetItem->t_ansi_addr,0,sizeof(pNetItem->t_ansi_addr));  pNetItem->t_status = sock_down;  pNetItem->t_begin_stream = false;  pNetItem->t_sslaccp_begintime = 0; } //我们需要一个链表来存储活动套接字数据结构及控制函数定义如下 //函数实现后面给出 typedef struct _tagPosition {} TPOSITION,*LPTPOS; //链表数据区结构 typedef struct _tagAgent_Data {  int  t_type;         //数据类别,用户私有定义  char *t_data;     //数据指针  int  t_buf_len;    //当前存储区总长度(字节)  int  t_data_len;  //当前数据长度(字节) }AG_DATA,*LPAG_DATA; //链表节点结构 typedef struct _tagAgent_ListNode {  bool t_status;                                          //是否分配的标志  struct _tagAgent_Data t_data;               //数据区  struct _tagAgent_ListNode *t_list_next; //当前节点的next指针  struct _tagAgent_ListNode *t_list_pre;   //当前节点的pre指针  struct _tagAgent_ListNode *t_pool_next; //当前节点的的节点池的next指针  struct _tagAgent_ListNode *t_pool_pre;  //当前节点的的节点池的pre指针 }AG_NODE,*LPAG_NODE; //链表容器结构 typedef struct _tagAgent_ListContainer {  struct _tagAgent_ListNode *t_pool_head;   //节点池的头指针  struct _tagAgent_ListNode *t_pool_tail;      //节点池的尾指针  struct _tagAgent_ListNode *t_list_head;     //链表头指针  struct _tagAgent_ListNode *t_list_tail;        //链表尾指针  int t_pool_count;  int t_list_count; }AG_LISTCONT,*LPAG_LISTCONT; //控制函数: //初始化链表节点 void ListNodeReset(AG_NODE *pListNode); //初始化链表容器 void ListContainerReset(AG_LISTCONT *pListContainer); //从头部添加节点 void ListContainerAddHead(AG_LISTCONT *pListContainer,AG_DATA nData,bool keepOldVal); //从尾部添加节点 void ListContainerAddTail(AG_LISTCONT *pListContainer,AG_DATA nData,bool keepOldVal); //Get头部节点存储的数据指针 AG_DATA *ListContainerGetHead(AG_LISTCONT *pListContainer); //Get尾部节点存储的数据指针 AG_DATA *ListContainerGetTail(AG_LISTCONT *pListContainer); //从头部移除节点 void ListContainerRemoveHead(AG_LISTCONT *pListContainer); //从尾部移除节点 void ListContainerRemoveTail(AG_LISTCONT *pListContainer); //移除指定节点 void ListContainerRemoveNode(LPAG_NODE pNode,AG_LISTCONT *pListContainer); //移除所有节点 void ListContainerRemoveListAll(AG_LISTCONT *pListContainer); //移除节点池所有节点,并释放所有存储 void ListContainerRemovePoolAll(AG_LISTCONT *pListContainer); //从节点池中分配一个空闲节点 AG_NODE *_List_AllocFromPool(AG_LISTCONT *pListContainer);  //下面俩函数是验证链表长度和节点池长度的函数 int  ListContainerPurListCount(AG_LISTCONT *pListContainer,bool *bValidate); int  ListContainerPurPoolCount(AG_LISTCONT *pListContainer,bool *bValidate); //开始监听,参数 pNetList 是链表容器指针,listenport 监听的端口 bool start_tcplisten(AG_LISTCONT *pNetList,int listenport){  AG_NET listener;  AG_DATA agData,*pData;  agData.t_data = (void*)&listener;  agData.t_data_len = sizeof(listener);  agData.t_type = 10;  //监听的socket  ListContainerAddTail(pNetList,agData,false);  pData = ListContainerGetTail(pNetList);  AG_NET *tail = (LPAG_NET)pData->t_data;  AgNetItemReset(tail);  tail->t_sock = socket(AF_INET, SOCK_STREAM, 0);  if (tail->t_sock < 0)   {        ListContainerRemoveTail(pNetList);        return false;  }  tail->t_rcvbuf = 0;  tail->t_sa.sin_family = AF_INET;  tail->t_sa.sin_port = htons(listenport);  tail->t_sa.sin_addr.s_addr = INADDR_ANY;    //设置SO_REUSEADDR标志  setsockopt(tail->t_sock,SOL_SOCKET,SO_REUSEADDR,                   (void *)&tail->t_sa.sin_addr,sizeof(tail->t_sa.sin_addr));  //绑定端口  if(bind(tail->t_sock, (struct sockaddr *)&(tail->t_sa), sizeof(tail->t_sa)) < 0 )  {        ShutTCPSocket(tail);        ListContainerRemoveTail(pNetList);        return false;  }  //监听  if(listen(tail->t_sock, SOMAXCONN) < 0)  {        ShutTCPSocket(tail);        ListContainerRemoveTail(pNetList);        return false;  }  tail->t_status = sock_listen;  return true; }  //监听建立起来之后,要开始接收客户端的连接,使用IO多路复用 //select 方式 //调用select之前,收集当前所有活动socket,并进行检查每个套接字的心跳周期 void net_beforeselects(AG_LISTCONT *pNetList,SOCKET *ptrSockMax,fd_set *ptrRD,                                      fd_set *ptrWD,bool *ptrWDFlg,time_t *ptrTmHeartbeatBegin); //检查SSL_Accept结果,如果失败,则从链表中删除 euSSLacceptChk net_chk_SSLAcceptResult(LPAG_NODE pNetNode,AG_LISTCONT *pNetList); //处理accept成功的client void net_Accept(AG_NET *pListener,LPAG_SSL pSSL,AG_LISTCONT *pNetList);

      //接收数据

     bool read_Stream(LPAG_NODE pNetNode,AG_LISTCONT *pNetList)

     //发送数据 bool send_Stream(LPAG_NODE pNetNode,AG_LISTCONT *pNetList) //关闭socket连接 void ShutTCPSocket(AG_NET *pBroken);

     //select 循环主函数 void net_Loop(LPAG_SSL pSSL,AG_LISTCONT *pNetList) {  time_t _tm_begin = 0;  time_t _tm_cur;  bool bDoNext = false;  struct timeval tmsk;  tmsk.tv_sec=0;  tmsk.tv_usec=200000; //200 毫秒  int iSelect;  bool bwd_flg = false;  fd_set rd,wd;  SOCKET sockMax = -1;  LPAG_NET pItem = 0;  SOCKADDR_IN l_sa;  socklen_t   l_nsca;  LPAG_NODE pNode = 0;  LPAG_NODE _pNode_tmp = 0;    while(1)  {        bDoNext = false;        pItem = 0;        sockMax = -1;        FD_ZERO(&rd);        FD_ZERO(&wd);           //收集活动套接字,并进行检查每个套接字的心跳周期        net_beforeselects(pNetList,&sockMax,&rd,&wd,&bwd_flg,&_tm_begin);         pItem = 0;        tmsk.tv_sec=0;

            //timeout 200 毫秒        tmsk.tv_usec=200000;         iSelect = select(sockMax,&rd,bwd_flg?&wd:0,0,&tmsk);        switch(iSelect)        {              case -1:                   //通讯失败                   printf("select failed/n");                   exit(0);                   break;              case 0:                   //超时,循环检查链表上每一个未决的ssl_accept的结果。                   pNode = pNetList->t_list_head;                   while(pNode)                  {                        _pNode_tmp = pNode;                        pItem = (LPAG_NET)pNode->t_data.t_data;                        pNode = pNode->t_list_next;                        switch(pItem->t_status)                       {                             case sock_accept:                                  net_chk_SSLAcceptResult(_pNode_tmp,pNetList);                                  break;                        }                   }                   break;             default:                   //循环检查链表上每一个活动socket                   pNode = pNetList->t_list_head;                   while(pNode)                 {                        _pNode_tmp = pNode;                        pItem = (LPAG_NET)pNode->t_data.t_data;                        pNode = pNode->t_list_next;                        switch(pItem->t_status)                       {                             case sock_listen:                                  if(FD_ISSET(pItem->t_sock,&rd))                                 {                                        //有连接请求                                        net_Accept(pItem,pSSL,pNetList);                                 }                                 break;                             case sock_accept:                                  switch(net_chk_SSLAcceptResult(_pNode_tmp,pNetList))                                 {                                       case chk_success:                                            bDoNext = true;                                            if(FD_ISSET(pItem->t_sock,&rd))                                           {                                                 //有数据可读                                                 bDoNext = read_Stream(_pNode_tmp,pNetList);                                           }                                            if(bDoNext)                                           {                                                 if(FD_ISSET(pItem->t_sock,&wd))                                                {                                                     //有数据要发送                                                     send_Stream(_pNode_tmp,pNetList);                                                }                                 }                                 break;                         }                         break;                   }                  }               break;        }     } }

     /*net_beforeselects*/ void net_beforeselects(AG_LISTCONT *pNetList,SOCKET *ptrSockMax,fd_set *ptrRD,              fd_set *ptrWD,bool *ptrWDFlg,time_t *ptrTmHeartbeatBegin) {  SOCKET sockMax = -1;  LPAG_NET pItem = 0;  time_t _tm_cur;  bool _b_heartbeat = false;  if((*ptrTmHeartbeatBegin) == 0)  {   //设置检查HEARTBEAT(心跳)开始时间   time(ptrTmHeartbeatBegin);  }  else  {    time(&_tm_cur);    if(difftime(_tm_cur,*ptrTmHeartbeatBegin) >= (double)HEARTBEAT_TIMEOUT)    {     //当前应该发送心跳检测了     _b_heartbeat = true;     *ptrTmHeartbeatBegin = _tm_cur;    }  }    //遍历链表头节  LPAG_NODE pNode = pNetList->t_list_head;  while(pNode)  {   pItem = (LPAG_NET)pNode->t_data.t_data;   if(pItem->t_sock > sockMax)   {    sockMax = pItem->t_sock;   }   FD_SET(pItem->t_sock,ptrRD);      //判断是否通过SSL_Accept检查成功   if(pItem->t_status == sock_accept && pItem->t_begin_stream)   {    if(_b_heartbeat)    {

          //将心跳信息数据追加写入发送缓存      AgBufferAppendData(pItem->t_sndbuf,HEARTBEAT_MESSAGE,HEARTBEAT_MSGLEN,false);    }    //判断发送缓存是否有数据要发送    if(pItem->t_sndbuf->m_buf_datalen > 0)    {       FD_SET(pItem->t_sock,ptrWD);       *ptrWDFlg = true;    }   }   pNode = pNode->t_list_next;  }  sockMax ++;  *ptrSockMax = sockMax; } /*net_chk_SSLAcceptResult*/ euSSLacceptChk net_chk_SSLAcceptResult(LPAG_NODE pNetNode,AG_LISTCONT *pNetList) {   LPAG_NET pLink = (LPAG_NET)pNetNode->t_data.t_data;   if(pLink->t_begin_stream)   {     return chk_success;   }   //调用SSL_accept,由于pLink->t_sock被置成异步,所以该函数不会阻塞。   int ssl_accp = SSL_accept (pLink->t_ssl);   //取得错误码   int iErr = errno;   if(ssl_accp==-1 && iErr == 0)   {    //此种情况不会出现,因此不用处理   }   if( ssl_accp != -1)    {    //SSL_accept 成功    time(&pLink->t_connected_time);    //恢复pLink->t_sock的阻塞标志     fcntl(pLink->t_sock,F_SETFL,pLink->t_flags);     pLink->t_sslaccp_begintime = 0;     //获取连接者的证书信息     X509*    client_cert = SSL_get_peer_certificate (pLink->t_ssl);    if (client_cert != NULL)    {       //连接者有证书,这里没做证书的验证,仅仅释放证书信息      X509_free (client_cert);    }    pLink->t_begin_stream = true;     return chk_success;    }   if(iErr != EINPROGRESS && iErr != EAGAIN )   {     //SSL_accept 失败     pLink->t_begin_stream = false;     ShutTCPSocket(pLink);     AgNetItemClear(pLink);     //从链表中移除(貌似删除了,但却存在于链表的节点池中,     //状态空闲,可以被分配)     ListContainerRemoveNode(pNetNode,pNetList);     return chk_fail;   }   time_t tCur;   time(&tCur);   double dOff = difftime(tCur,pLink->t_sslaccp_begintime);   if(dOff > (double)SSLACCEPT_TIMEOUT)   {     //从调用ssl_accept到目前为止,超过了SSLACCEPT_TIMEOUT秒,则认为     //ssl_accept失败。     pLink->t_begin_stream = false;     ShutTCPSocket(pLink);     AgNetItemClear(pLink);     //从链表中移除(貌似删除了,但却存在于链表的节点池中,     //状态空闲,可以被分配)     ListContainerRemoveNode(pNetNode,pNetList);     return chk_fail;   }   //还需要继续检查。   return chk_continue;  }  /*net_Accept*/  void net_Accept(AG_NET *pListener,LPAG_SSL pSSL,AG_LISTCONT *pNetList)  {   SOCKADDR_IN l_sa;   memset(&l_sa,0,sizeof(l_sa));   int l_sock,l_keepalive;   socklen_t l_nsca = sizeof(SOCKADDR_IN);      AG_NET accp;   AgNetItemReset(&accp);

          AG_DATA agData,*pData;   agData.t_data = (void*)&accp;   agData.t_data_len = sizeof(accp);   agData.t_type = 11;        l_sock = accept(pListener->t_sock,(struct sockaddr *)&(l_sa),&l_nsca);   int iCurClients = ListContainerPurListCount(pNetList,0);      //当前连接者的client数量是否超过上限   if(iCurClients >= MAX_CLIENT_COUNT)   {     close(l_sock);     return;   }   //添加到链表尾部,注意,添加过程中是在

       //链表的节点池中分配空闲节点,则

       //成员 ssl,t_rcvbuf,t_sndbuf很有可能

       //不为空,是有效的指针,所以下面有判断   ListContainerAddTail(pNetList,agData,true);   pData = ListContainerGetTail(pNetList);   AG_NET *tail = (LPAG_NET)pData->t_data;   tail->t_sock = l_sock;   memcpy(&tail->t_sa,&l_sa,sizeof(tail->t_sa));         tail->t_status = sock_accept;   if(!tail->t_rcvbuf)   {    //创建接收缓存    tail->t_rcvbuf = AgBufferCreate(MAX_RCVSNDMSG_SIZE,true);   }   if(!tail->t_sndbuf)   {    //创建发送缓存    tail->t_sndbuf = AgBufferCreate(MAX_RCVSNDMSG_SIZE,true);   }   AgBufferResetMem(tail->t_rcvbuf);   AgBufferResetMem(tail->t_sndbuf);   if(!tail->t_ssl)   {    tail->t_ssl = SSL_new (pSSL->t_ssl_ctx);    //判断 SSL_new 是否成功    if(!tail->t_ssl)    {      ShutTCPSocket(pLink);      AgNetItemClear(pLink);      ListContainerRemoveNode(pNetNode,pNetList);      return;    }   }

       //设置SSL的套接字描述符   SSL_set_fd (tail->t_ssl, tail->t_sock);

       //保存套接字初始flag

       tail->t_flags = fcntl(tail->t_sock,F_GETFL,0);   //设置套接字为非阻塞模式,等SSL_accept成功后再恢复初始flag   fcntl(tail->t_sock,F_SETFL,tail->t_flags|O_NONBLOCK);   //调用 SSL_accept   int ssl_accp = SSL_accept (tail->t_ssl);   int iErr = errno;   if( ssl_accp != -1)   {      //立即就成功了,虽然有些不可思议      //但实际上该情况还真有(这个可以有,呵呵)      tail->t_begin_stream = true;      //恢复tail->t_sock的阻塞标志      fcntl(tail->t_sock,F_SETFL,tail->t_flags);      return;    }    if(iErr != EINPROGRESS && iErr != EAGAIN )   {      //失败     ShutTCPSocket(tail);     AgNetItemClear(tail);     ListContainerRemoveTail(pNetList);     return;   }   //设置第一次调用 SSL_accept 的时间    time(&tail->t_sslaccp_begintime);  }  /*关闭套接字描述符*/  void ShutTCPSocket(AG_NET *pBroken)  {    if(pBroken->t_ssl)    {       //调用 SSL_clear 清空ssl缓存数据,

           //不调用SSL_free释放      SSL_clear(pBroken->t_ssl);    }    close(pBroken->t_sock);  }  /*read_Stream*/  bool read_Stream(LPAG_NODE pNetNode,AG_LISTCONT *pNetList)  {   time_t tmCur;   LPAG_NET pLink = (LPAG_NET)pNetNode->t_data.t_data;   LPAG_BUFFER pBuf = pLink->t_rcvbuf;   int iRet = 0;

       //计算接收缓存的指针偏移量,就是从什么位置读   char *pRead = pBuf->m_buf_ptr + pBuf->m_buf_datalen;

       //计算接收缓存剩余空间长度,就是还能读多少字节   int iReadLen = pBuf->m_buf_length - pBuf->m_buf_datalen-1;   if(iReadLen <= 0)   {    //当前接收缓存数据溢出。    goto LASTERR;   }

       //SSL读数据   iRet = SSL_read(pLink->t_ssl, pRead, iReadLen);   if(iRet <= 0)   {    //连接中断了    goto LASTERR;   }   //数据解析   pBuf->m_buf_datalen += iRet;   {    //这里做数据解析,暂时来个最简单的,原封不动的反射回去

        //将接收缓存里所有数据追加到发送缓存里

        AgBufferAppendData(pLink->t_sndbuf,pBuf->m_buf_ptr ,pBuf->m_buf_datalen,false);

        //将接收缓存里剩余数据往头部移动pBuf->m_buf_datalen长度(原封不动的反射的情况下,没有剩余数据了

        AgBufferDecLenFromHead(pLink->t_rcvdbuf,pBuf->m_buf_datalen);   }   return true;  LASTERR:   ShutTCPSocket(pLink);   AgNetItemClear(pLink);   ListContainerRemoveNode(pNetNode,pNetList);   return false;  }

      /*send_Stream*/   bool send_Stream(LPAG_NODE pNetNode,AG_LISTCONT *pNetList)  {   int iRet = 0;   LPAG_NET pLink = (LPAG_NET)pNetNode->t_data.t_data;   LPAG_TuxAsynCallNode pTuxNode = 0;   SSL *ssl = pLink->t_ssl;   SOCKET sock = pLink->t_sock;

       //从头开始   char *pSend = pLink->t_otherbuf->m_buf_ptr;

       //尽量发送所有数据   int iSendLen = pLink->t_otherbuf->m_buf_datalen;   if(iSendLen > 0)   {

        //SSL发送数据    iRet = SSL_write(ssl, pSend, iSendLen);    if(iRet <= 0)    {       //连接中断。      goto LASTERR;    }    //把剩余数据左移,因为发送成功的返回值(复制到系统发送缓存字节数)

        //很有可能小于期望值    AgBufferDecLenFromHead(pLink->t_otherbuf,iRet);   }   return true;  LASTERR:   ShutTCPSocket(pLink);   AgNetItemClear(pLink);   ListContainerRemoveNode(pNetNode,pNetList);   return false;  }              //下面是全局变量  AG_LISTCONT g_net_List;  AG_SSL g_net_SSL;            //安全退出函数  void _safe_exit()  {   LPAG_NODE pNode = g_net_List.t_list_head;   while(pNode)   {    LPAG_NET pItem = (LPAG_NET)pNode->t_data.t_data;    ShutTCPSocket(pItem);    pNode = pNode->t_list_next;   }  }  //信号捕获函数  void _catchsignal(int sig)  {   switch(sig)   {   case SIGINT:   case SIGTERM:    _safe_exit();    break;   case SIGILL:    _safe_exit();    break;   }  }  

      //主程序入口  int main(int argc,char *argv[])  {    if(!InitSSL(&g_net_SSL))    {      printf("InitSSL failed/n");      exit(0)    }    signal(SIGPIPE,SIG_IGN);  //忽略socket中断连接的信号    signal(SIGINT,_catchsignal);    signal(SIGTERM,_catchsignal);    signal(SIGILL,_catchsignal);    signal(SIGTRAP,SIG_IGN);  //忽略陷阱信号        ListContainerReset(&g_net_List);    if(start_tcplisten(&g_net_List,TCP_LISTENPORT))           net_Loop(&g_net_SSL,&g_net_List);

        else

               printf("start_tcplisten failed/n");  }

     

    //检查pData有效性

    void _chk_data_validate(void *pData,void *pChk,const char *pErrdesc){ if(pData == pChk) {  FILE *fp = fopen("./AgentC_Core","a");  if(fp)  {   AG_DATETIME dt;   _date_time(&dt);   fprintf(fp,"<_chk_data_validate>%s!<d-d-d d:d:d>/n",    pErrdesc,dt.year,dt.mon,dt.day,dt.hour,dt.min,dt.sec);   fflush(fp);   fclose(fp);  }  sleep(2);  exit(0); }}

      /*下面是缓存控制函数*/

     //初始化

     void AgBufferReady(LPAG_BUFFER pBuf){ pBuf->m_buf_ptr = 0; pBuf->m_buf_length = 0; pBuf->m_buf_datalen = 0;};

    //清空缓存数据void AgBufferResetMem(LPAG_BUFFER pBuf){ if(pBuf->m_buf_ptr) {  memset(pBuf->m_buf_ptr,0,pBuf->m_buf_length);  pBuf->m_buf_datalen = 0; }}

    //释放缓存空间void AgBufferFreeMem(LPAG_BUFFER pBuf){ if(pBuf->m_buf_ptr) {  free(pBuf->m_buf_ptr);  free(pBuf); }}

    //创建缓存LPAG_BUFFER AgBufferCreate(int iSize,bool IsZeroMem){ LPAG_BUFFER retBuf = (LPAG_BUFFER)malloc(sizeof(AG_BUFFER)); _chk_data_validate(retBuf,NULL,"AgBufferCreate()->malloc(AG_BUFFER) failed!"); AgBufferReady(retBuf); retBuf->m_buf_ptr = (char*)malloc(iSize); _chk_data_validate(retBuf->m_buf_ptr,NULL,"AgBufferCreate()->malloc(size) failed!"); if(IsZeroMem)  memset(retBuf->m_buf_ptr,0,iSize); retBuf->m_buf_length = iSize; return retBuf;}

    //往缓存追加数据块void AgBufferAppendData(LPAG_BUFFER pBuf,char *pData,int iSize,bool bRemoveLastZero){ int iDataLen = pBuf->m_buf_datalen; int iPreBufLen = pBuf->m_buf_length; int iNewLen = 0; char *pTR = pBuf->m_buf_ptr; if(bRemoveLastZero) {  if(pData[iSize-1] == '/0')  {   iSize --;  } } iDataLen += iSize; pTR += pBuf->m_buf_datalen; if(iPreBufLen-iDataLen > 0) {  memcpy(pTR,pData,iSize);  pBuf->m_buf_datalen = iDataLen;  return; } iNewLen = iDataLen+1; pTR = (char*)malloc(iNewLen); _chk_data_validate(pTR,NULL,g_log.t_buf);  if(pBuf->m_buf_datalen > 0)  memcpy(pTR,pBuf->m_buf_ptr,pBuf->m_buf_datalen);

     memcpy(pTR+pBuf->m_buf_datalen,pData,iSize); free(pBuf->m_buf_ptr); pTR[iDataLen] = '/0'; pBuf->m_buf_ptr = pTR; pBuf->m_buf_length = iNewLen; pBuf->m_buf_datalen = iDataLen; }

    //从头移除数据块,剩余数据移动void AgBufferDecLenFromHead(LPAG_BUFFER pBuf,int iOffset){ char *pOffset = 0; int iOffLen = 0; if(pBuf->m_buf_datalen >= iOffset) {  iOffLen = pBuf->m_buf_datalen - iOffset;  if(iOffLen > 0)  {   pOffset = pBuf->m_buf_ptr + iOffset;   memmove(pBuf->m_buf_ptr,pOffset,iOffLen);   pBuf->m_buf_ptr[iOffLen] = '/0';  }  pBuf->m_buf_datalen = iOffLen;  return; }}

    //从尾移除数据块,剩余数据不移动void AgBufferDecLenFromTail(LPAG_BUFFER pBuf,int iOffset){ pBuf->m_buf_datalen = pBuf->m_buf_datalen - iOffset; if(pBuf->m_buf_datalen < 0) {  pBuf->m_buf_datalen = 0; }}

     

    /*下面给出链表控制函数*/

    //初始化链表节点

    void ListNodeReset(AG_NODE *pListNode){ pListNode->t_data.t_buf_len = 0; pListNode->t_data.t_data = 0; pListNode->t_data.t_data_len = 0; pListNode->t_data.t_type = 0; pListNode->t_list_next = 0; pListNode->t_list_pre = 0; pListNode->t_pool_next = 0; pListNode->t_pool_pre = 0; pListNode->t_status = false;}

    //初始化链表容器void ListContainerReset(AG_LISTCONT *pListContainer){ pListContainer->t_pool_head = 0; pListContainer->t_pool_tail = 0; pListContainer->t_list_head = 0; pListContainer->t_list_tail = 0; pListContainer->t_list_count = 0; pListContainer->t_pool_count = 0;}

    //从节点池中分配一个空闲节点AG_NODE *_List_AllocFromPool(AG_LISTCONT *pListContainer){ if(pListContainer->t_pool_head == 0 || pListContainer->t_pool_tail == 0) {  pListContainer->t_pool_head = (AG_NODE *)malloc(sizeof(AG_NODE));  if(!pListContainer->t_pool_head)  {   _chk_data_validate(NULL,NULL,"List malloc(...) failed!");  }  ListNodeReset(pListContainer->t_pool_head);  pListContainer->t_pool_tail = pListContainer->t_pool_head;  pListContainer->t_pool_count = 1;  pListContainer->t_pool_head->t_status = true;  return pListContainer->t_pool_head; } AG_NODE *pRight = pListContainer->t_pool_head,  *pLeft = pListContainer->t_pool_tail,*pReturn = 0; while(1) {  if(!pLeft && !pRight)   break;  if(pLeft)  {   if(!pLeft->t_status)   {    pReturn = pLeft;    break;   }   pLeft = pLeft->t_pool_pre;  }  if(pRight)  {   if(!pRight->t_status)   {    pReturn = pRight;    break;   }   pRight = pRight->t_pool_next;  } } if(!pReturn) {  pReturn = (AG_NODE *)malloc(sizeof(AG_NODE));  if(!pReturn)  {   _chk_data_validate(NULL,NULL,"List malloc(...) failed!");  }  ListNodeReset(pReturn);  pReturn->t_pool_pre = pListContainer->t_pool_tail;  pReturn->t_pool_next = 0;  pListContainer->t_pool_tail->t_pool_next = pReturn;  

      pListContainer->t_pool_tail = pReturn;  pListContainer->t_pool_count ++; } pReturn->t_status = true; return pReturn;}

    //从头部添加节点void ListContainerAddHead(AG_LISTCONT *pListContainer,AG_DATA nData,bool keepOldVal){ AG_NODE *pNode = _List_AllocFromPool(pListContainer); if(pNode->t_data.t_buf_len >= nData.t_data_len) {

      if(!keepOldVal)

      { 

      //如果不保持原有数据的话就将节点的数据区清零  memset(pNode->t_data.t_data,0,pNode->t_data.t_buf_len);  memcpy(pNode->t_data.t_data,nData.t_data,nData.t_data_len);  pNode->t_data.t_type = nData.t_type;

      } } else {  if(pNode->t_data.t_data)   free(pNode->t_data.t_data);  pNode->t_data.t_data = (char*)malloc(nData.t_data_len);  if(!pNode->t_data.t_data)  {   _chk_data_validate(NULL,NULL,"List malloc(...) failed!");  }  memcpy(pNode->t_data.t_data,nData.t_data,nData.t_data_len);  pNode->t_data.t_buf_len = nData.t_data_len;  pNode->t_data.t_data_len = nData.t_data_len;  pNode->t_data.t_type = nData.t_type; } if(pListContainer->t_list_head == 0 || pListContainer->t_list_tail == 0) {  pListContainer->t_list_head = pNode;  pListContainer->t_list_tail = pNode;  pNode->t_list_pre = 0;  pNode->t_list_next = 0;  pListContainer->t_list_count = 1; } else {  pListContainer->t_list_head->t_list_pre = pNode;  pNode->t_list_pre = 0;  pNode->t_list_next = pListContainer->t_list_head;  pListContainer->t_list_head = pNode;  pListContainer->t_list_count ++; }}

    //从尾部添加节点void ListContainerAddTail(AG_LISTCONT *pListContainer,AG_DATA nData,bool keepOldVal){ AG_NODE *pNode = _List_AllocFromPool(pListContainer); if(pNode->t_data.t_buf_len >= nData.t_data_len) {  if(!keepOldVal)  {

       //如果不保持原有数据的话就将节点的数据区清零   memset(pNode->t_data.t_data,0,pNode->t_data.t_buf_len);   memcpy(pNode->t_data.t_data,nData.t_data,nData.t_data_len);   pNode->t_data.t_type = nData.t_type;  } } else {  if(pNode->t_data.t_data)   free(pNode->t_data.t_data);  pNode->t_data.t_data = (char*)malloc(nData.t_data_len);  if(!pNode->t_data.t_data)  {   _chk_data_validate(NULL,NULL,"List malloc(...) failed!");  }  memcpy(pNode->t_data.t_data,nData.t_data,nData.t_data_len);  pNode->t_data.t_buf_len = nData.t_data_len;  pNode->t_data.t_data_len = nData.t_data_len;  pNode->t_data.t_type = nData.t_type; } if(pListContainer->t_list_head == 0 || pListContainer->t_list_tail == 0) {  pListContainer->t_list_head = pNode;  pListContainer->t_list_tail = pNode;  pNode->t_list_pre = 0;  pNode->t_list_next = 0;  pListContainer->t_list_count = 1; } else {  pListContainer->t_list_tail->t_list_next = pNode;  pNode->t_list_next = 0;  pNode->t_list_pre = pListContainer->t_list_tail;  pListContainer->t_list_tail = pNode;  pListContainer->t_list_count ++; }}

     

    //Get头部节点存储的数据指针LPAG_DATA ListContainerGetHead(AG_LISTCONT *pListContainer){ return (pListContainer->t_list_head!=0)?&pListContainer->t_list_head->t_data:0;}

     

    //Get尾部节点存储的数据指针LPAG_DATA ListContainerGetTail(AG_LISTCONT *pListContainer){ return (pListContainer->t_list_tail!=0)?&pListContainer->t_list_tail->t_data:0;}

     

    //从头部移除节点

     

    void ListContainerRemoveHead(AG_LISTCONT *pListContainer){ LPAG_NODE pNode = pListContainer->t_list_head; if(pNode) {  if(pNode == pListContainer->t_list_tail)  {   //只有一个节点   pListContainer->t_list_head = 0;   pListContainer->t_list_tail = 0;  }  else  {   pListContainer->t_list_head = pNode->t_list_next;   pListContainer->t_list_head->t_list_pre = 0;  }  pNode->t_status = false;  pListContainer->t_list_count --; }}

    //从尾部移除节点void ListContainerRemoveTail(AG_LISTCONT *pListContainer){ LPAG_NODE pNode = pListContainer->t_list_tail; if(pNode) {  if(pNode == pListContainer->t_list_head)  {   //只有一个节点   pListContainer->t_list_head = 0;   pListContainer->t_list_tail = 0;  }  else  {   pListContainer->t_list_tail = pNode->t_list_pre;   pListContainer->t_list_tail->t_list_next = 0;  }  pNode->t_status = false;  pListContainer->t_list_count --; }}

    //移除指定节点void ListContainerRemoveNode(LPAG_NODE pNode,AG_LISTCONT *pListContainer){ if(pNode == pListContainer->t_list_head) {  ListContainerRemoveHead(pListContainer);  return; } if(pNode == pListContainer->t_list_tail) {  ListContainerRemoveTail(pListContainer);  return; } LPAG_NODE pPre = pNode->t_list_pre,pNext = pNode->t_list_next; pPre->t_list_next = pNext; pNext->t_list_pre = pPre; pNode->t_status = false; pListContainer->t_list_count --;}

    //移除所有节点void ListContainerRemoveListAll(AG_LISTCONT *pListContainer){ LPAG_NODE pNode = pListContainer->t_list_head; if(pNode && pNode == pListContainer->t_list_tail) {  pListContainer->t_list_head = 0;  pListContainer->t_list_tail = 0;  pNode->t_status = false;  pListContainer->t_list_count --;  return; } while(pNode) {  pNode->t_status = false;  pListContainer->t_list_count --;  pNode = pNode->t_list_next; } pListContainer->t_list_head = 0; pListContainer->t_list_tail = 0;}

    //移除节点池所有节点,并释放所有存储void ListContainerRemovePoolAll(AG_LISTCONT *pListContainer){ LPAG_NODE pNode = pListContainer->t_pool_head; while(pNode) {  LPAG_NODE pTmp = pNode->t_pool_next;  if(pNode->t_data.t_data)  {   free(pNode->t_data.t_data);  }  free(pNode);  pListContainer->t_pool_count --;  pNode = pTmp; } pListContainer->t_pool_head = 0; pListContainer->t_pool_tail = 0;}

    //验证链表长度int  ListContainerPurListCount(AG_LISTCONT *pListContainer){ int i = 0; LPAG_NODE pNode = pListContainer->t_list_head; while(pNode) {  i ++;  pNode = pNode->t_list_next; } if(i != pListContainer->t_list_count) {  _chk_data_validate(NULL,NULL,"ListContainerPurListCount() != "/

                                  "pListContainer->t_list_count"); } return i;}

    //验证节点池长度int  ListContainerPurPoolCount(AG_LISTCONT *pListContainer){ int i = 0; LPAG_NODE pNode = pListContainer->t_pool_head; while(pNode) {  i ++;  pNode = pNode->t_pool_next; } if(i != pListContainer->t_pool_count) {  _chk_data_validate(NULL,NULL,"ListContainerPurPoolCount() != "/

                                 "pListContainer->t_pool_count"); } return i;}

     

     

     

      //一旦指针有效的话,就永远也不释放了,因为  //pNetItem会存在于链表容器的节点池中。


    最新回复(0)