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

📄 tcp_recv.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
 { where(); printf("calling tcp_close_connection\n"); }
#endif
				tcp_close_connection(tcp_conn,
					ECONNRESET);
				if (connuser)
					(void)tcp_su4listen(connuser);
				break;
			}
#if DEBUG
 { where(); printf("calling tcp_close_connection\n"); }
#endif
			tcp_close_connection(tcp_conn, ECONNRESET);
			break;
		}
/*
	!ACK ?
		discard packet
		exit
*/
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
		if (!(tcp_hdr_flags & THF_ACK))
			break;
/*
	state == SYN-RECEIVED ?
		SND.UNA <= SEG.ACK <= SND.NXT ?
			state= ESTABLISHED
		:
			<SEG=SEG.ACK><CTL=RST>
			exit
*/
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
	if (tcp_conn->tc_state == TCS_SYN_RECEIVED)
	{
		if (tcp_LEmod4G(tcp_conn->tc_SND_UNA, seg_ack) &&
			tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT))
		{
			tcp_conn->tc_state= TCS_ESTABLISHED;
assert (tcp_check_conn(tcp_conn));
#if DEBUG & 2
 { where(); tcp_write_state(tcp_conn); }
#endif
assert(tcp_conn->tc_connuser);
			tcp_restart_connect(tcp_conn->tc_connuser);
			if (tcp_conn->tc_state == TCS_CLOSED)
			{
#if DEBUG
 { where(); printf("connection closed while inuse\n"); }
#endif
				break;
			}
		}
		else
		{
			create_RST (tcp_conn, ip_hdr, tcp_hdr);
			tcp_restart_write(tcp_conn);
			break;
		}
	}
/*
	state == ESTABLISHED || state == FIN-WAIT-1 ||
		state == FIN-WAIT-2 || state == CLOSE-WAIT ||
		state == LAST-ACK || state == TIME_WAIT || state == CLOSING ?
		SND.UNA < SEG.ACK <= SND.NXT ?
			SND.UNA= SEG.ACK
			reply "send ok"
			SND.WL1 < SEG.SEQ || (SND.WL1 == SEG.SEQ &&
				SND.WL2 <= SEG.ACK ?
				SND.WND= SEG.WND
				SND.Wl1= SEG.SEQ
				SND.WL2= SEG.ACK
		SEG.ACK <= SND.UNA ?
			ignore ACK
		SEG.ACK > SND.NXT ?
			<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
			discard packet
			exit
*/
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
		if (tcp_conn->tc_state == TCS_ESTABLISHED ||
			tcp_conn->tc_state == TCS_FIN_WAIT_1 ||
			tcp_conn->tc_state == TCS_FIN_WAIT_2 ||
			tcp_conn->tc_state == TCS_CLOSE_WAIT ||
			tcp_conn->tc_state == TCS_LAST_ACK ||
			tcp_conn->tc_state == TCS_TIME_WAIT ||
			tcp_conn->tc_state == TCS_CLOSING)
		{
			if (tcp_LEmod4G(tcp_conn->tc_SND_UNA, seg_ack)
				&& tcp_LEmod4G(seg_ack, tcp_conn->
				tc_SND_NXT))
			{
				if (tcp_Lmod4G(tcp_conn->tc_SND_WL1,
					seg_seq) || (tcp_conn->
					tc_SND_WL1==seg_seq &&
					tcp_LEmod4G(tcp_conn->
					tc_SND_WL2, seg_ack)))
				{
					if (seg_wnd > TCP_MAX_WND_SIZE)
						seg_wnd= TCP_MAX_WND_SIZE;
					if (!seg_wnd)
						seg_wnd++;
					tcp_conn->tc_SND_WL1= seg_seq;
					tcp_conn->tc_SND_WL2= seg_ack;
#if SUN_0WND_BUG
					if (seg_wnd && seg_ack == tcp_conn->
						tc_SND_UNA && tcp_LEmod4G(
						seg_ack + seg_wnd,
						tcp_conn->tc_SND_NXT) &&
						tcp_LEmod4G(seg_ack + seg_wnd,
						tcp_conn->tc_snd_cwnd))
						seg_wnd= 0;
#endif
				}
				else
				{
					seg_wnd= tcp_conn->tc_mss;
					/* assume 1 segment if not a valid
					 * window */
				}
				tcp_release_retrans(tcp_conn, seg_ack, seg_wnd);
				if (tcp_conn->tc_state == TCS_CLOSED)
				{
#if DEBUG
 { where(); printf("connection closed while inuse\n"); }
#endif
					break;
				}
			}
			else if (tcp_Gmod4G(seg_ack,
				tcp_conn->tc_SND_NXT))
			{
				tcp_set_ack_timer(tcp_conn);
#if DEBUG
 { where(); printf("got an ack of something I haven't send\n");
   printf("seg_ack= %lu, SND_NXT= %lu\n", seg_ack, tcp_conn->tc_SND_NXT); }
#endif
				break;
			}
#if DEBUG & 256
 if (!seg_wnd) { where(); printf("SND_UNA= %lu, SND_NXT= %lu\n",
	tcp_conn->tc_SND_UNA, tcp_conn->tc_SND_NXT); }
#endif
			if (!seg_wnd &&
			/* tcp_GEmod4G(seg_wnd, tcp_conn->tc_SND_UNA) &&
			*/
				tcp_Lmod4G(tcp_conn->tc_SND_UNA,
				tcp_conn->tc_SND_NXT))
			{	/* zero window */
#if DEBUG & 256
 { where(); printf("setting 0wnd_to\n"); }
#endif
				clck_untimer(&tcp_conn->tc_minor_timer);
				if (!tcp_conn->tc_0wnd_to)
				{
assert (tcp_conn->tc_rtt);
					tcp_conn->tc_0wnd_to=
						tcp_conn->tc_rtt;
				}
				clck_timer(&tcp_conn->tc_major_timer,
					get_time()+tcp_conn->tc_0wnd_to,
					tcp_zero_wnd_to, tcp_conn-
					tcp_conn_table);
			}
			else
			{
#if DEBUG & 256
 { where(); printf("not setting 0wnd_to\n"); }
#endif
				if (tcp_conn->tc_0wnd_to)
				{
#if DEBUG & 256
 { where(); printf("resetting 0wnd_to\n"); }
#endif
					tcp_conn->tc_0wnd_to= 0;
					tcp_conn->tc_SND_TRM=
						tcp_conn->tc_SND_UNA;
					clck_untimer(&tcp_conn->
						tc_major_timer);
					tcp_restart_write (tcp_conn);
				}
			}
		}
/*
	state == FIN-WAIT-1 && FIN acknowledged ?
		state= FIN-WAIT-2

	state == CLOSING && FIN acknowledged ?
		state= TIME-WAIT

	state == LAST-ACK && FIN acknowledged ?
		state= CLOSED

	state == TIME-WAIT ?
		<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
		restart 2 MSL timeout
*/
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
		{
			switch (tcp_conn->tc_state)
			{
			case TCS_FIN_WAIT_1:

				tcp_conn->tc_state= TCS_FIN_WAIT_2;
assert (tcp_check_conn(tcp_conn));
#if DEBUG
 { where(); tcp_write_state(tcp_conn); }
#endif
				break;
			case TCS_CLOSING:
				tcp_conn->tc_state= TCS_TIME_WAIT;
assert (tcp_check_conn(tcp_conn));
#if DEBUG
 { where(); tcp_write_state(tcp_conn); }
#endif
				tcp_set_time_wait_timer(tcp_conn);
				break;
			case TCS_LAST_ACK:
#if DEBUG & 256
 { where(); printf("calling tcp_close_connection\n"); }
#endif
				tcp_close_connection(tcp_conn, ENOCONN);
				break;
			}
			if (!tcp_conn->tc_mainuser)
			{
				tcp_close_connection(tcp_conn, ENOCONN);
				break;
			}
		}
		if (tcp_conn->tc_state == TCS_TIME_WAIT)
		{
			tcp_set_ack_timer(tcp_conn);
			tcp_set_time_wait_timer(tcp_conn);
		}

/*
	process data...
*/
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
		tcp_extract_ipopt(tcp_conn, ip_hdr);
		tcp_extract_tcpopt(tcp_conn, tcp_hdr);

		if (data_length)
		{
			if (tcp_LEmod4G(seg_seq, tcp_conn->tc_RCV_NXT))
				process_data (tcp_conn, tcp_hdr,
					tcp_hdr_len, tcp_pack,
					data_length);
			else
				process_advanced_data (tcp_conn,
					tcp_hdr, tcp_hdr_len, tcp_pack,
					data_length);
			if (tcp_conn->tc_state == TCS_CLOSED)
				break;
			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);
			if (tcp_conn->tc_state == TCS_CLOSED)
				break;
		}
/*
	FIN ?
		reply pending receives
		advace RCV.NXT over the FIN
		<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

		state == SYN-RECEIVED || state == ESTABLISHED ?
			state= CLOSE-WAIT
		state == FIN-WAIT-1 ?
			state= CLOSING
		state == FIN-WAIT-2 ?
			state= TIME-WAIT
		state == TIME-WAIT ?
			restart the TIME-WAIT timer
	exit
*/
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
		if ((tcp_hdr_flags & THF_FIN) && tcp_LEmod4G(seg_seq,
			tcp_conn->tc_RCV_NXT))
		{
			switch (tcp_conn->tc_state)
			{
			case TCS_SYN_RECEIVED:
				break;
			case TCS_ESTABLISHED:
				tcp_conn->tc_state= TCS_CLOSE_WAIT;
assert (tcp_check_conn(tcp_conn));
#if DEBUG
 { where(); tcp_write_state(tcp_conn); }
#endif
				break;
			case TCS_FIN_WAIT_1:
				tcp_conn->tc_state= TCS_CLOSING;
assert (tcp_check_conn(tcp_conn));
#if DEBUG
 { where(); tcp_write_state(tcp_conn); }
#endif
				break;
			case TCS_FIN_WAIT_2:
				tcp_conn->tc_state= TCS_TIME_WAIT;
assert (tcp_check_conn(tcp_conn));
#if DEBUG
 { where(); tcp_write_state(tcp_conn); }
#endif
				/* drops through */
			case TCS_TIME_WAIT:
				tcp_set_time_wait_timer(tcp_conn);
				break;
			}
			if (!(tcp_conn->tc_flags & TCF_FIN_RECV))
			{
				tcp_conn->tc_RCV_NXT++;
				tcp_conn->tc_flags |= TCF_FIN_RECV;
#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_set_ack_timer(tcp_conn);
			if (tcp_conn->tc_readuser)
				tcp_restart_fd_read(tcp_conn);
		}
		break;
	default:
		printf("unknown state: tcp_conn->tc_state== %d\n",
			tcp_conn->tc_state);
		break;
	}
	bf_afree(ip_pack);
	bf_afree(tcp_pack);
}


PRIVATE void process_data(tcp_conn, tcp_hdr, tcp_hdr_len, tcp_data,
	data_len)
tcp_conn_t *tcp_conn;
tcp_hdr_t *tcp_hdr;
int tcp_hdr_len;
acc_t *tcp_data;
int data_len;
{
	u32_t lo_seq, hi_seq, urg_seq, seq_nr;
	u16_t urgptr;
	int tcp_hdr_flags;
	unsigned int offset;
	acc_t *all_data, *tmp_data, *rcvd_data;

#if DEBUG & 256
 { where(); printf("in process data\n"); }
#endif
	seq_nr= ntohl(tcp_hdr->th_seq_nr);
	urgptr= ntohs(tcp_hdr->th_urgptr);
	while (tcp_data)
	{
assert (tcp_check_conn(tcp_conn));
		all_data= bf_cut(tcp_data, tcp_hdr_len, data_len);
		tcp_data= 0;

		lo_seq= seq_nr;
		tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK;

		if (tcp_hdr_flags & THF_URG)
		{
			urg_seq= lo_seq+ urgptr;
			tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+
				tcp_conn->tc_rcv_wnd+tcp_conn->
				tc_urg_wnd;
			if (tcp_GEmod4G(urg_seq, tcp_conn->tc_RCV_HI))
				urg_seq= tcp_conn->tc_RCV_HI;
			if (tcp_Gmod4G(urg_seq, tcp_conn->tc_RCV_UP))
				tcp_conn->tc_RCV_UP= urg_seq;
		}
		if (tcp_hdr_flags & THF_SYN)
			lo_seq++;

		if (tcp_hdr_flags & THF_PSH)
		{
			tcp_conn->tc_flags |= TCF_RCV_PUSH;
#if DEBUG & 256
 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 
	tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }
#endif
		}

		if (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
		{
			offset= tcp_conn->tc_RCV_NXT-lo_seq;
			tmp_data= bf_cut(all_data, offset, data_len-
				offset);
			bf_afree(all_data);
			lo_seq += offset;
			data_len -= offset;
			all_data= tmp_data;
			tmp_data= 0;
		}
		assert (lo_seq == tcp_conn->tc_RCV_NXT);

		hi_seq= lo_seq+data_len;
		if (tcp_Gmod4G(hi_seq, tcp_conn->tc_RCV_HI))
		{
			data_len= tcp_conn->tc_RCV_HI-lo_seq;
			tmp_data= bf_cut(all_data, 0, data_len);
			bf_afree(all_data);
			all_data= tmp_data;
			hi_seq= lo_seq+data_len;
			tcp_hdr_flags &= ~THF_FIN;
		}
		assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));

#if DEBUG & 256
 { where(); printf("in process data: lo_seq= %lu, hi_seq= %lu\n",
	lo_seq, hi_seq); }
#endif
		rcvd_data= tcp_conn->tc_rcvd_data;
		tcp_conn->tc_rcvd_data= 0;
		tmp_data= bf_append(rcvd_data, all_data);
		if (tcp_conn->tc_state == TCS_CLOSED)
		{
#if DEBUG
 { where(); printf("connection closed while inuse\n"); }
#endif
			bf_afree(tmp_data);
			return;
		}
		tcp_conn->tc_rcvd_data= tmp_data;
		tcp_conn->tc_RCV_NXT= hi_seq;

		assert (tcp_conn->tc_RCV_LO + bf_bufsize(tcp_conn->
			tc_rcvd_data) == tcp_conn->tc_RCV_NXT);
		
		if (tcp_hdr_flags & THF_FIN)
		{
#if DEBUG
 { where(); printf("got a FIN\n"); }
#endif
			tcp_conn->tc_RCV_NXT++;
			tcp_conn->tc_flags |= TCF_FIN_RECV;
#if DEBUG & 16
 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 
	tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }
#endif
		}
		tcp_set_ack_timer(tcp_conn);
		while (tcp_conn->tc_rcv_queue)
		{
			tmp_data= tcp_conn->tc_rcv_queue;
			assert (tmp_data->acc_length >= TCP_MIN_HDR_SIZE);
			tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tmp_data);
			lo_seq= tcp_hdr->th_seq_nr;
			/* th_seq_nr is changed to host byte order */
			if (tcp_Gmod4G(lo_seq, tcp_conn->tc_RCV_NXT))
				break;
			tcp_hdr_len= (tcp_hdr->th_data_off &
				TH_DO_MASK) >> 2;
			data_len= tcp_hdr->th_chksum-tcp_hdr_len;
			if (tcp_LEmod4G(lo_seq+data_len, tcp_conn->
				tc_RCV_NXT))
			{
				tcp_conn->tc_rcv_queue= tmp_data->
					acc_ext_link;
				bf_afree(tmp_data);
				continue;
			}
			tcp_data= tmp_data;
			seq_nr= tcp_hdr->th_seq_nr;
			urgptr= tcp_hdr->th_urgptr;
			break;
		}
	}
assert (tcp_check_conn(tcp_conn));
	if (tcp_conn->tc_readuser)
		tcp_restart_fd_read(tcp_conn);
	else if (!tcp_conn->tc_mainuser)
	{
#if DEBUG
 { where(); printf("calling tcp_close_connection\n"); }
#endif
		tcp_close_connection (tcp_conn, ENOCONN);
	}
assert (tcp_check_conn(tcp_conn));
}

PRIVATE void process_advanced_data(tcp_conn, tcp_hdr, tcp_hdr_len,
	tcp_data, data_len)
tcp_conn_t *tcp_conn;
tcp_hdr_t *tcp_hdr;
int tcp_hdr_len;
acc_t *tcp_data;
int data_len;
{
	u32_t seg_seq, seg_hi;
	u16_t seg_up;
	acc_t *hdr_acc, *next_acc, **tail_acc_ptr, *head_acc, *data_acc,
		*tmp_acc;
	tcp_hdr_t *tmp_hdr;
	int tmp_hdr_len;

#if DEBUG & 256
 { where(); printf ("processing advanced data\n"); }
#endif

⌨️ 快捷键说明

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