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

📄 tcp_recv.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*tcp_recv.c*/#include "inet.h"#include "buf.h"#include "clock.h"#include "type.h"#include "tcp_int.h"#include "tcp.h"#include "assert.h"INIT_PANIC();FORWARD void create_RST ARGS(( tcp_conn_t *tcp_conn,	ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr ));FORWARD void process_data ARGS(( tcp_conn_t *tcp_conn,	tcp_hdr_t *tcp_hdr, int tcp_hdr_len, acc_t *tcp_data,	int data_len ));FORWARD void process_advanced_data ARGS(( tcp_conn_t *tcp_conn,	tcp_hdr_t *tcp_hdr, int tcp_hdr_len, acc_t *tcp_data,	int data_len ));FORWARD acc_t *merge_packs ARGS(( acc_t *first, acc_t *next ));FORWARD void fd_read ARGS(( tcp_fd_t *tcp_fd ));FORWARD void switch_read_fd ARGS(( tcp_conn_t *tcp_conn,	tcp_fd_t *tcp_fd, tcp_fd_t **ref_urg_fd,	tcp_fd_t **ref_norm_fd ));PUBLIC void tcp_frag2conn(tcp_conn, ip_pack, tcp_pack)tcp_conn_t *tcp_conn;acc_t *ip_pack;acc_t *tcp_pack;{	tcp_fd_t *connuser;	int tcp_hdr_flags;	ip_hdr_t *ip_hdr;	tcp_hdr_t *tcp_hdr;	int ip_hdr_len, tcp_hdr_len;	u32_t seg_ack, seg_seq, rcv_hi;	u16_t data_length, seg_wnd;	int acceptable_ACK, segm_acceptable;#if DEBUG & 256 { where(); printf("tcp_frag2conn(&tcp_conn_table[%d],..) called\n",	tcp_conn-tcp_conn_table); }#endif#if DEBUG & 256 { where(); printf("tc_connuser= 0x%x\n", tcp_conn->tc_connuser); }#endif	ip_pack= bf_packIffLess(ip_pack, IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	if (ip_hdr_len>IP_MIN_HDR_SIZE)	{		ip_pack= bf_packIffLess(ip_pack, ip_hdr_len);		ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);	}	tcp_pack= bf_packIffLess(tcp_pack, TCP_MIN_HDR_SIZE);	tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);	tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2;		/* actualy (>> 4) << 2 */	if (tcp_hdr_len>TCP_MIN_HDR_SIZE)	{		tcp_pack= bf_packIffLess(tcp_pack, tcp_hdr_len);		tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);	}	data_length= tcp_hdr->th_chksum-tcp_hdr_len;		/* th_chksum is used for packet size internally */	tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;	seg_ack= ntohl(tcp_hdr->th_ack_nr);	seg_seq= ntohl(tcp_hdr->th_seq_nr);	seg_wnd= ntohs(tcp_hdr->th_window);	switch (tcp_conn->tc_state)	{	case TCS_CLOSED:/*CLOSED:	discard all data.	!RST ?		ACK ?			<SEQ=SEG.ACK><CTL=RST>			exit		:			<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>			exit	:		discard packet		exit*/		if (!(tcp_hdr_flags & THF_RST))		{			create_RST (tcp_conn, ip_hdr, tcp_hdr);			tcp_restart_write(tcp_conn);		}		break;	case TCS_LISTEN:/*LISTEN:	RST ?		discard packet		exit	ACK ?		<SEQ=SEG.ACK><CTL=RST>		exit	SYN ?		BUG: no security check		RCV.NXT= SEG.SEQ+1		IRS= SEG.SEQ		ISS should already be selected		<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>		SND.NXT=ISS+1		SND.UNA=ISS		state= SYN-RECEIVED		exit	:		shouldnot occur		discard packet		exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif		if (tcp_hdr_flags & THF_RST)			break;		if (tcp_hdr_flags & THF_ACK)		{			create_RST (tcp_conn, ip_hdr, tcp_hdr);			tcp_restart_write(tcp_conn);			break;		}		if (tcp_hdr_flags & THF_SYN)		{			tcp_extract_ipopt(tcp_conn, ip_hdr);			tcp_extract_tcpopt(tcp_conn, tcp_hdr);			tcp_conn->tc_RCV_LO= seg_seq+1;			tcp_conn->tc_RCV_NXT= seg_seq+1;			tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+				tcp_conn->tc_rcv_wnd;			tcp_conn->tc_RCV_UP= seg_seq;			tcp_conn->tc_IRS= seg_seq;			tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS;			tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;			tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS+1;			tcp_conn->tc_SND_UP= tcp_conn->tc_ISS-1;			tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS-1;			tcp_conn->tc_SND_WL1= seg_seq;			tcp_conn->tc_state= TCS_SYN_RECEIVED;			tcp_conn->tc_no_retrans= 0;assert (tcp_check_conn(tcp_conn));#if DEBUG & 2 { where(); tcp_write_state(tcp_conn); }#endif			tcp_conn->tc_locaddr= ip_hdr->ih_dst;			tcp_conn->tc_locport= tcp_hdr->th_dstport;			tcp_conn->tc_remaddr= ip_hdr->ih_src;			tcp_conn->tc_remport= tcp_hdr->th_srcport;#if DEBUG & 256 { where(); printf("calling tcp_restart_write(&tcp_conn_table[%d])\n",	tcp_conn-tcp_conn_table); }#endif			tcp_restart_write(tcp_conn);			break;		}#if DEBUG { where(); printf("this shouldn't happen\n"); }#endif		break;	case TCS_SYN_SENT:/*SYN-SENT:	ACK ?		SEG.ACK <= ISS || SEG.ACK > SND.NXT ?			RST ?				discard packet				exit			:				<SEQ=SEG.ACK><CTL=RST>				exit		SND.UNA <= SEG.ACK && SEG.ACK <= SND.NXT ?			ACK is acceptable		:			ACK is !acceptable	:		ACK is !acceptable	RST ?		ACK acceptable ?			discard segment			state= CLOSED			error "connection refused"			exit		:			discard packet			exit	BUG: no security check	SYN ?		IRS= SEG.SEQ		RCV.NXT= IRS+1		ACK ?			SND.UNA= SEG.ACK		SND.UNA > ISS ?			state= ESTABLISHED			<SEQ=SND.NXT><ACK= RCV.NXT><CTL=ACK>			process ev. URG and text			exit		:			state= SYN-RECEIVED			SND.WND= SEG.WND			SND.WL1= SEG.SEQ			SND.WL2= SEG.ACK			<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>			exit	:		discard segment		exit*/		if (tcp_hdr_flags & THF_ACK)		{			if (tcp_LEmod4G(seg_ack, tcp_conn->tc_ISS) ||				tcp_Gmod4G(seg_ack, tcp_conn->tc_SND_NXT))				if (tcp_hdr_flags & THF_RST)					break;				else				{					create_RST (tcp_conn, ip_hdr,						tcp_hdr);					tcp_restart_write(tcp_conn);					break;				}			acceptable_ACK= (tcp_LEmod4G(tcp_conn->tc_SND_UNA,				seg_ack) && tcp_LEmod4G(seg_ack,				tcp_conn->tc_SND_NXT));		}		else			acceptable_ACK= FALSE;		if (tcp_hdr_flags & THF_RST)		{			if (acceptable_ACK)			{#if DEBUG & 256 { where(); printf("calling tcp_close_connection\n"); }#endif				tcp_close_connection(tcp_conn,					ECONNREFUSED);			}			break;		}		if (tcp_hdr_flags & THF_SYN)		{			tcp_conn->tc_RCV_LO= seg_seq+1;			tcp_conn->tc_RCV_NXT= seg_seq+1;			tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +				tcp_conn->tc_rcv_wnd;			tcp_conn->tc_RCV_UP= seg_seq;			tcp_conn->tc_IRS= seg_seq;			if (tcp_hdr_flags & THF_ACK)				tcp_conn->tc_SND_UNA= seg_ack;			if (tcp_Gmod4G(tcp_conn->tc_SND_UNA,				tcp_conn->tc_ISS))			{				tcp_conn->tc_state= TCS_ESTABLISHED;assert (tcp_check_conn(tcp_conn));#if DEBUG & 2 { where(); tcp_write_state(tcp_conn); }#endif#if DEBUG & 256 { where(); printf("ISS= 0x%lx\n", tcp_conn->tc_ISS); }#endifassert(tcp_conn->tc_connuser);				tcp_restart_connect(tcp_conn-> tc_connuser);				if (tcp_conn->tc_state == TCS_CLOSED)				{ { where(); printf("connection closed while inuse\n"); }					break;				}				tcp_conn->tc_flags &= ~TCF_ACK_TIMER_SET;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 	tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif				tcp_conn->tc_flags |= TCF_SEND_ACK;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 	tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif				tcp_restart_write (tcp_conn);				tcp_frag2conn(tcp_conn, ip_pack, tcp_pack);				return;				/* ip_pack and tcp_pack are already					freed */			}			tcp_conn->tc_state= TCS_SYN_RECEIVED;assert (tcp_check_conn(tcp_conn));#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif			tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS;			tcp_restart_write(tcp_conn);		}		break;	case TCS_SYN_RECEIVED:	case TCS_ESTABLISHED:	case TCS_FIN_WAIT_1:	case TCS_FIN_WAIT_2:	case TCS_CLOSE_WAIT:	case TCS_CLOSING:	case TCS_LAST_ACK:	case TCS_TIME_WAIT:/*SYN-RECEIVED:ESTABLISHED:FIN-WAIT-1:FIN-WAIT-2:CLOSE-WAIT:CLOSING:LAST-ACK:TIME-WAIT:	test if segment is acceptable:	Segment	Receive	Test	Length	Window	0	0	SEG.SEQ == RCV.NXT	0	>0	RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND	>0	0	not acceptable	>0	>0	(RCV.NXT <= SEG.SEQ && SEG.SEQ < RCV.NXT+RCV.WND)			|| (RCV.NXT <= SEG.SEQ+SEG.LEN-1 &&			SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND)	for urgent data: use RCV.WND+URG.WND for RCV.WND*/#if DEBUG & 256 { where(); printf("\n"); }#endif		rcv_hi= tcp_conn->tc_RCV_HI;		if (tcp_hdr_flags & THF_URG)			rcv_hi= tcp_conn->tc_RCV_LO + tcp_conn->tc_rcv_wnd +				tcp_conn->tc_urg_wnd;		if (!data_length)		{			if (rcv_hi == tcp_conn->tc_RCV_NXT)			{#if DEBUG & 256 { where(); printf("\n"); }#endif				segm_acceptable= (seg_seq == rcv_hi);#if DEBUG if (!segm_acceptable) { where(); printf("!segm_acceptable\n"); }#endif			}			else			{#if DEBUG & 256 { where(); printf("\n"); }#endifassert (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT));				segm_acceptable= (tcp_LEmod4G(tcp_conn->					tc_RCV_NXT, seg_seq) &&					tcp_Lmod4G(seg_seq, rcv_hi));#if DEBUG & 256 if (!segm_acceptable) { where(); printf("RCV_NXT= 0x%lx, seg_seq= 0x%lx, rcv_hi= 0x%lx\n",	tcp_conn->tc_RCV_NXT, seg_seq, rcv_hi); }#endif			}		}		else		{			if (tcp_Gmod4G(rcv_hi, tcp_conn->tc_RCV_NXT))			{#if DEBUG & 256 { where(); printf("RCV_NXT= %lu, rcv_hi= %lu, seg_seq= %lu, data_length= %u\n",	tcp_conn->tc_RCV_NXT, rcv_hi, seg_seq, data_length); }#endif				segm_acceptable= (tcp_LEmod4G(tcp_conn->					tc_RCV_NXT, seg_seq) &&					tcp_Lmod4G(seg_seq, rcv_hi)) ||					(tcp_LEmod4G(tcp_conn->tc_RCV_NXT,					seg_seq+data_length-1) &&					tcp_Lmod4G(seg_seq+data_length-1,					rcv_hi));#if DEBUG & 256 if (!segm_acceptable) { where(); printf("!segm_acceptable\n"); }#endif			}			else			{#if DEBUG { where(); printf("\n"); }#endif				segm_acceptable= FALSE;#if DEBUG if (!segm_acceptable) { where(); printf("!segm_acceptable\n"); }#endif			}		}/*	!segment acceptable ?		RST ?			discard packet			exit		:			<SEG=SND.NXT><ACK=RCV.NXT><CTL=ACK>			exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif		if (!segm_acceptable)		{#if DEBUG & 256 { where(); printf("segment is not acceptable\n"); }#endif			if (!(tcp_hdr_flags & THF_RST))			{#if DEBUG & 256 { where(); printf("segment is not acceptable setting ack timer\n"); }#endif				tcp_set_ack_timer(tcp_conn);			}			break;		}/*	RST ?		state == SYN-SECEIVED ?			initiated by a LISTEN ?				state= LISTEN				exit			:				state= CLOSED				error "connection refused"				exit		state == CLOSING || state == LAST-ACK ||			state == TIME-WAIT ?			state= CLOSED			exit		:			state= CLOSED			error "connection reset"			exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif		if (tcp_hdr_flags & THF_RST)		{			if (tcp_conn->tc_state == TCS_SYN_RECEIVED)			{				if (tcp_conn->tc_orglisten)				{					connuser= tcp_conn->tc_connuser;					tcp_conn->tc_connuser= 0;#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif					tcp_close_connection (tcp_conn,						ECONNREFUSED);					if (connuser)						(void)tcp_su4listen(							connuser);					break;				}				else				{#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif					tcp_close_connection(tcp_conn,						ECONNREFUSED);					break;				}			}			if (tcp_conn->tc_state == TCS_CLOSING ||				tcp_conn->tc_state == TCS_LAST_ACK ||				tcp_conn->tc_state == TCS_TIME_WAIT)			{#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif				tcp_close_connection (tcp_conn,					ENOCONN);				break;			}#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif			tcp_close_connection(tcp_conn, ECONNRESET);			break;		}/*	SYN in window ?		state == SYN-RECEIVED && initiated by a LISTEN ?			state= LISTEN			exit		:			state= CLOSED			error "connection reset"			exit*/#if DEBUG  & 256 { where(); printf("\n"); }#endif		if ((tcp_hdr_flags & THF_SYN) && tcp_GEmod4G(seg_seq,			tcp_conn->tc_RCV_NXT))		{			if (tcp_conn->tc_state == TCS_SYN_RECEIVED &&				tcp_conn->tc_orglisten)			{				connuser= tcp_conn->tc_connuser;				tcp_conn->tc_connuser= 0;#if DEBUG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -