⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpstream.cpp

📁 linux 上http email 协议分析程序 主要能够处理大数据量的主干网的应用
💻 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 + -