本文详细说明了用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会存在于链表容器的节点池中。