📄 tcpstream.cpp
字号:
/************************************************************ * Copyright(C) 1998-2004,CongXing Tech. Co. Ltd. * FileName: TCPStream.cpp * Author: Jay * Version: V01.00.000 * Date: 2004.01.13 * Description: 实现TCP流类 ************************************************************/#include <TCPStream.h>#include <TCPPacket.h>#include <memory.h>#include <stdlib.h>#include<Timeutil.h>#include <stdio.h>#include <string.h>#include <Mem.h>#include <Log.h>#include <arpa/inet.h>//全局变量,不使用局部变量,减少申请内存次数,减少碎片和加快速度///////////////////////////////////long G_TIME_NOW = 0;//当前时间//long g_tcpstream_ltmp;const long *cl = (long *)(C_HTTP_KEYWORD);/////////////////////////////////////************************************************************ * function: CTCPStream * Author: Jay * Version: V01.00.000 * Date: 2004.01.13 * Description: 构造函数 * ************************************************************/CTCPStream::CTCPStream(){ m_len = 0; m_size = 0; m_head = NULL; m_iMultiGene = 2; m_bFinish = false; m_bAbort = false; m_count = 0; //printf("%p constructor ok\n",this);}/************************************************************ * function: CTCPStream * Author: Jay * Version: V01.00.000 * Date: 2004.04.06 * Description: copy constructor * ************************************************************/CTCPStream::CTCPStream(const CTCPStream &_s){ m_len = _s.m_len; m_size = _s.m_size; m_head = _s.m_head; m_iMultiGene = _s.m_iMultiGene; m_bFinish = _s.m_bFinish; m_bAbort = _s.m_bAbort; m_count = _s.m_count;}/************************************************************ * function: ~CTCPStream * Author: Jay * Version: V01.00.000 * Date: 2004.01.13 * Description: 析构函数 * ************************************************************/CTCPStream::~CTCPStream(){ clear();}/************************************************************ * function: clear * Author: Jay * Version: V01.00.000 * Date: 2004.04.08 * Description: 释放空间 * ************************************************************/int CTCPStream::clear(){ if(m_head != NULL) { if(!m_memAdm->free( (char*)m_head)) { writelog("free stream space fail!"); m_head = NULL; return -1; } m_head = NULL; } return 0;}/************************************************************ * function: 重新初始化 * Author: Jay * Version: V01.00.000 * Date: 2004.03.15 * Description: 有新的syn包,所以重新初始化 * param: * _baseSize(in): TCP流初始化大小 * _ip:(in) 第一个包 * return: * 0:成功 * -1:失败 * ************************************************************/int CTCPStream::reinit( IP_PACKET *_ip){ TCP_PACKET *ts_tcp; m_len = 0; m_bFinish = false; m_bAbort = false; m_count = 0; ts_tcp = (TCP_PACKET*)((char*)_ip+get_ip_headlen(_ip)); //收集第一个包信息 m_src_ip = get_ip_src_ip(_ip); m_dst_ip = get_ip_dst_ip(_ip); m_src_port = get_tcp_src_port(ts_tcp); m_dst_port = get_tcp_dst_port(ts_tcp);// m_protocol = get_ip_protocol(_ip); m_lLastPacketTime = (unsigned long)time(NULL); //debug if(get_tcp_seqno(ts_tcp) == 0) {#ifdef _DEBUG writelog("seqno = 0,init new stream fail!!\n"); //print_TCP_Packet(_ip,true);#endif return -1; } m_latestSeqNum = m_firstSeqNum = get_tcp_seqno(ts_tcp); return 0;}/************************************************************ * function: init * Author: Jay * Version: V01.00.000 * Date: 2004.01.13 * Description: 初始化函数 * param: * _baseSize: * _ip:(in) 第一个包 * _pmemAdm: 内存管理器 * return: * 0:成功 * -1:失败 * ************************************************************/int CTCPStream::init(unsigned int _baseSize,IP_PACKET *_ip,CMem *_pmemAdm){ TCP_PACKET *ts_tcp; m_memAdm = _pmemAdm; ts_tcp = (TCP_PACKET*)((char*)_ip+get_ip_headlen(_ip)); if( tcp_checksum(_ip)!=0) { writelog("tcp checksum fail!"); return -1; } m_baseSize = _baseSize; m_size = 0;/* m_size = _baseSize*sizeof(char); m_head = (unsigned char*) m_memAdm->maloc(m_size); if (m_head == NULL) { writelog("CTCPStream::init-->申请内存size(%d)失败",m_size); return -1;//申请内存失败 } */ //收集第一个包信息 m_src_ip = get_ip_src_ip(_ip); m_dst_ip = get_ip_dst_ip(_ip); m_src_port = get_tcp_src_port(ts_tcp); m_dst_port = get_tcp_dst_port(ts_tcp); //m_protocol = get_ip_protocol(_ip); m_lLastPacketTime = (unsigned long)time(NULL); //debug#ifdef _DEBUG if(get_tcp_seqno(ts_tcp) == 0) { writelog("seqno = 0!!"); //print_TCP_Packet(_ip,true); return -1; }#endif m_latestSeqNum = m_firstSeqNum = get_tcp_seqno(ts_tcp); return 0;}/************************************************************ * function: getStream * Author: Jay * Version: V01.00.000 * Date: 2004.01.13 * Description: 提取流的内容 * param: * *_pbuff:(in) 缓冲区指针 * _bufsize:(in) 缓冲区大小 * return: * >=0:流长度 * -1:失败 * -2:缓冲区太小 * ************************************************************/int CTCPStream::getStream(unsigned char *_pbuff,unsigned int _bufsize){ if(_bufsize < m_len ) return -2; memcpy(_pbuff,m_head + 1,m_len*sizeof(unsigned char) - 1); return m_len - 1;}/************************************************************ * function: addPacket * Author: Jay * Version: V01.00.000 * Date: 2004.01.14 * Description: 增加一个IP包到TCP流中 * 由于TCP协议保证了TCP包不会在传输过程中被 * 路由器分片,所以不考虑IP分片可能 * 对于错包处理如下: * 判断错包:如果TCP包的序列号超过窗口大小, * 则认为TCP包是错包,丢弃 * 如果是SYN或者FIN或者RST,则判断checksum * 是否正确 * param: * *_p:(in) 指向IP包的指针 * return: * 0:成功 * -1:失败 * -2:内存不足 * ************************************************************/int CTCPStream::addPacket(IP_PACKET *_p){ TCP_PACKET *ts_tcp; ulong seqNo ;//序列号 long offset;//离包头第一个字节的偏移量 int contentLen;//TCP包内容长度 const unsigned char *content ; //判断是否包尾 bool isFinish ; //判断有否中断流 bool isReset ; content = get_ip_content(contentLen,_p); ts_tcp=(TCP_PACKET*)(((char*)_p) + get_ip_headlen(_p)); seqNo = get_tcp_seqno(ts_tcp);//序列号 offset = seqNo - m_firstSeqNum; contentLen = contentLen - get_tcp_headlen(ts_tcp); //判断是否包尾 isFinish = get_tcp_fin(ts_tcp); //判断有否中断流 isReset = get_tcp_rst(ts_tcp); if(isFinish || isReset) { if( tcp_checksum(_p)!=0 ) {#ifdef _DEBUG printf("but checksum fail!\n");#endif return -1; } } //debug //#ifdef _DEBUG if(seqNo == 0) { if( tcp_checksum(_p)!=0) { writelog("seq = 0,checksum fail!"); } else {#ifdef _DEBUG printIP(_p); print_TCP_Packet(_p,true);#endif writelog("seq = 0,but checksum ok"); } return -1; } //#endif //end debug if (m_size == 0)//第一个包 { m_size = m_baseSize*sizeof(char); m_head = (unsigned char*) m_memAdm->maloc(m_size); if (m_head == NULL) { writelog("CTCPStream::init-->申请内存size(%d)失败",m_size); m_size = 0; return -1;//申请内存失败 } } if(offset + contentLen > C_MAX_TCP_STREAM_LEN) { if(tcp_checksum(_p)==0) {#ifdef _DEBUG printf("Stream too long:%ld,lastseq[%u],seq[%u]\n", offset+contentLen,m_latestSeqNum,seqNo);#endif writelog("Stream too long:%ld,lastseq[%u],seq[%u]", offset+contentLen,m_latestSeqNum,seqNo); return -3; } else { printf("好像包过长,实际checksum 错误"); writelog("好像包过长,实际checksum 错误"); } //是错包,则返回-1,以免遭删除之厄运 return -1; } while(offset + contentLen + 1 >= m_size ) { if(seqNo - m_latestSeqNum > (ulong)C_MAX_WINDOW_SIZE*2)//乘以2是为了防止有漏包 { //与最近一个包的间隔大于窗口理论最大值,判定为错包,返回 //debug#ifdef _DEBUG writelog("大于窗口理论最大值,错包,this seq:(%u) - last seq(%u)=%u",seqNo,m_latestSeqNum, seqNo - m_latestSeqNum);#endif return -1; } if(resize() != 0) {#ifdef _DEBUG printf("resize fail!\n");#endif return -2; } } if(contentLen<0 && !isFinish && !isReset) {#ifdef _DEBUG printf("contentLen(%d) <0 \n",contentLen);#endif if( tcp_checksum(_p)!=0) writelog("TCP content len%d <=0 ,check sum fail!",contentLen); else writelog("TCP content len:%d<0,but checksum ok!"); return -1; } memcpy(m_head+offset,content+get_tcp_headlen(ts_tcp),contentLen*sizeof(unsigned char)); m_count += contentLen; m_bFinish = isFinish; m_bAbort = isReset; if(m_len < offset+contentLen) m_len = offset+contentLen; m_lLastPacketTime = (long)time(NULL) ; m_latestSeqNum = seqNo;#ifdef _DEBUG if(m_latestSeqNum == 0) printf("m_latestSeqNum is zero\n");#endif return 0;}/************************************************************ * function: resize * Author: Jay * Version: V01.00.000 * Date: 2004.01.14 * Description: 扩充流大小 * param: * return: * 0:成功 * -1:失败 * ************************************************************/int CTCPStream::resize(){ int newLen; unsigned char *newHead;#ifdef _DEBUG struct in_addr inaddr;#endif if(m_iMultiGene > NETMON_MAX_MULTIGENE) return -1; newLen = m_baseSize*(m_iMultiGene); m_iMultiGene = m_iMultiGene * 2; newHead = (unsigned char*)m_memAdm->maloc(newLen); if(newHead == NULL) { writelog("stream resize: maloc memory(size:%d) fail!",newLen); return -1; }#ifdef _DEBUG /* printf("申请了一块(%d)大小的内存,地址:%p ",newLen,newHead); inaddr.s_addr = get_src_ip(); printf("SIP:%s SPORT:%hu ",inet_ntoa(inaddr),ntohs(get_src_port())); inaddr.s_addr =get_dst_ip(); printf("DIP:%s DPORT:%hu length:%d,receive:%d%%\n",inet_ntoa(inaddr),ntohs(get_dst_port()) ,m_len - 1,getReceivedRate());*/#endif memcpy(newHead,m_head,m_size*sizeof(unsigned char)); if(!m_memAdm->free((char*)m_head) ) { m_memAdm->free((char*)newHead); writelog("free memory fail!"); return -1; }#ifdef _DEBUG // printf("释放了一块内存,地址:%p\n",m_head);#endif m_head = newHead; m_size = newLen; return 0;} /************************************************************ * function: isTextHTTPStream * Author: Jay * Version: V01.00.000 * Date: 2004.02.23 * Description: 根据HTTP协议判断这个流是不是一个TEXT内容 * 调用前要确定: * 1.是HTTP协议 * 2.是第一个内容包,否则会影响速度 * param: * return: * true:成功 * false:失败 * ************************************************************/bool CTCPStream::isTextHTTPStream(){ unsigned char *lineHead,*lineTail;//从stream中,截取所有子串(以0x00,CRLF为子串结束符) int checkLen; if(!isHTTPStream())//确定是否HTTP流 return false; // printf("isTextHTTPStream?mlen:%d,\n",m_len); // char buff[1024]; lineHead = m_head+1; //找出第一个非空字符 while(*lineHead == 0x00 && lineHead - m_head < m_len) lineHead++; if(lineHead - m_head == m_len) return false;//空流 lineTail = lineHead; // printf("lineTail - m_head:%d,m_len - size:%d\n",lineTail - m_head,m_len - sizeof(C_HTTP_CONTENT_TYPE_TEXT)); while(lineTail - m_head < m_len-sizeof(C_HTTP_CONTENT_TYPE_TEXT) && *(lineTail) != 0x00 && !(*(lineTail) == C_CRLF[0] &&*(lineTail+1) == C_CRLF[1])) lineTail++; if( lineTail - m_head== m_len - sizeof(C_HTTP_CONTENT_TYPE_TEXT)) return false;//查完也没找到特征串,非文本类型 /* //debug // memset( buff,0x00,sizeof(buff)); // snprintf(buff,sizeof(buff),"%s",lineHead); // printf("substr:#%s#\n",buff); // memset( buff,0x00,sizeof(buff)); memcpy(buff,lineHead,lineTail - lineHead); printf("line:#%s#\n",buff); //end debug */ checkLen = m_len - sizeof(C_HTTP_CONTENT_TYPE_TEXT); while (lineHead - m_head < checkLen) { if(strncasecmp((char*)lineHead,C_HTTP_CONTENT_TYPE_TEXT,sizeof(C_HTTP_CONTENT_TYPE_TEXT)-1)==0) return true; if(*lineTail == 0x00) lineHead = lineTail+1;//字符串结束符,一个字符位置 else lineHead = lineTail +2;//CRLF,两个字符位置 lineTail = lineHead; while(lineTail - m_head < m_len-sizeof(C_HTTP_CONTENT_TYPE_TEXT) && *(lineTail) != 0x00 && !(*(lineTail) == C_CRLF[0] &&*(lineTail+1) == C_CRLF[1])) lineTail++; // memset( buff,0x00,sizeof(buff)); // memncpy(buff,lineHead,lineTail - lineHead); // printf("line:#%s#\n",buff); } return false;}/************************************************************ * function: isHTTPStream * Author: Jay * Version: V01.00.000 * Date: 2004.02.23 * Description: 根据HTTP协议判断这个流是不是一个HTTP流 * 判断流的开始4个字节是否为:"HTTP" * 不包括第一个空字节 * param: * return: * true:是 * false:不是 * ************************************************************/bool CTCPStream::isHTTPStream(){ //pl = (long *)(m_head+1);//流的前4个字节,m_head[0]是一个空字节,跳过 if (*(long *)(m_head+1)==*cl) return true; return false;}bool CTCPStream::isStreamTimeOut(){ //g_tcpstream_ltmp = G_TIME_NOW - m_lLastPacketTime; if( G_TIME_NOW - m_lLastPacketTime > C_TIMEOUT_SECONDS)// || (g_tcpstream_ltmp > C_TIMEOUT_FOR_ZERO_TCP_STREAM && m_size == 0)) { return true; } return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -