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

📄 tcp_recv.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 ||		(tcp_print_conn(tcp_conn), printf("\n"), 0));	if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_READ_IP))		tcp_fd_read(tcp_conn, 1);	if (tcp_conn->tc_fd && (tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))		tcp_rsel_read(tcp_conn);	adv_data= tcp_conn->tc_adv_data;	if (adv_data != NULL)	{		/* Try to use advanced data. */		adv_seq= tcp_conn->tc_adv_seq;		nxt= tcp_conn->tc_RCV_NXT;		if (tcp_Gmod4G(adv_seq, nxt))			return;		/* not yet */		tcp_conn->tc_adv_data= NULL;		data_len= bf_bufsize(adv_data);		if (tcp_Lmod4G(adv_seq, nxt))		{			if (tcp_LEmod4G(adv_seq+data_len, nxt))			{				/* Data is not needed anymore. */				bf_afree(adv_data);				return;			}			len_diff= nxt-adv_seq;			adv_data= bf_delhead(adv_data, len_diff);			data_len -= len_diff;		}		DBLOCK(1, printf("using advanced data\n"));		/* Append data to the input buffer */		if (tcp_conn->tc_rcvd_data == NULL)		{			tcp_conn->tc_rcvd_data= adv_data;		}		else		{			tcp_conn->tc_rcvd_data=				bf_append(tcp_conn->tc_rcvd_data, adv_data);		}		tcp_conn->tc_SND_NXT += data_len;		assert(tcp_check_conn(tcp_conn));		if (tcp_conn->tc_fd &&			(tcp_conn->tc_fd->tf_flags & TFF_READ_IP))		{			tcp_fd_read(tcp_conn, 1);		}		if (tcp_conn->tc_fd &&			(tcp_conn->tc_fd->tf_flags & TFF_SEL_READ))		{			tcp_rsel_read(tcp_conn);		}	}}PRIVATE void process_advanced_data(tcp_conn, tcp_hdr, tcp_data, data_len)tcp_conn_t *tcp_conn;tcp_hdr_t *tcp_hdr;acc_t *tcp_data;int data_len;{	u32_t seq, adv_seq;	acc_t *adv_data;	assert(tcp_conn->tc_busy);	/* Note, tcp_data will be freed by the caller. */	/* Always send an ACK, this allows the sender to do a fast	 * retransmit.	 */	tcp_conn->tc_flags |= TCF_SEND_ACK;	tcp_conn_write(tcp_conn, 1);	if (tcp_hdr->th_flags & THF_URG)		return;	/* Urgent data is to complicated */	if (tcp_hdr->th_flags & THF_PSH)		tcp_conn->tc_flags |= TCF_RCV_PUSH;	seq= ntohl(tcp_hdr->th_seq_nr);	/* Make sure that the packet doesn't fall outside of the window	 * we offered.	 */	if (tcp_Gmod4G(seq+data_len, tcp_conn->tc_RCV_HI))		return;	adv_data= tcp_conn->tc_adv_data;	adv_seq= tcp_conn->tc_adv_seq;	tcp_conn->tc_adv_data= NULL;	tcp_data->acc_linkC++;	if (adv_data == NULL)	{		adv_seq= seq;		adv_data= tcp_data;	}	else if (seq + data_len == adv_seq)	{		/* New data fits right before exiting data. */		adv_data= bf_append(tcp_data, adv_data);		adv_seq= seq;	}	else if (adv_seq + bf_bufsize(adv_data) == seq)	{		/* New data fits right after exiting data. */		adv_data= bf_append(adv_data, tcp_data);	}	else	{		/* New data doesn't fit. */		bf_afree(tcp_data);	}	tcp_conn->tc_adv_data= adv_data;	tcp_conn->tc_adv_seq= adv_seq;}				PRIVATE void create_RST(tcp_conn, ip_hdr, tcp_hdr, data_len)tcp_conn_t *tcp_conn;ip_hdr_t *ip_hdr;tcp_hdr_t *tcp_hdr;int data_len;{	acc_t *tmp_ipopt, *tmp_tcpopt, *tcp_pack;	acc_t *RST_acc;	ip_hdr_t *RST_ip_hdr;	tcp_hdr_t *RST_tcp_hdr;	size_t pack_size, ip_hdr_len, mss;	DBLOCK(0x10, printf("in create_RST, bad pack is:\n"); 		tcp_print_pack(ip_hdr, tcp_hdr); tcp_print_state(tcp_conn);		printf("\n"));	assert(tcp_conn->tc_busy);	/* Only send RST packets in reponse to actual data (or SYN, FIN)	 * this solves a problem during connection shutdown. The problem	 * is the follow senario: a senders closes the connection instead	 * of doing a shutdown and waiting for the receiver to shutdown.	 * The receiver is slow in processing the last data. After the	 * sender has completely closed the connection, the receiver	 * sends a window update which triggers the sender to send a	 * RST. The receiver closes the connection in reponse to the RST.	 */	if ((tcp_hdr->th_flags & (THF_FIN|THF_SYN)) == 0 &&		data_len == 0)	{#if DEBUG { printf("tcp_recv`create_RST: no data, no RST\n"); }#endif		return;	}	tmp_ipopt= tcp_conn->tc_remipopt;	if (tmp_ipopt)		tmp_ipopt->acc_linkC++;	tmp_tcpopt= tcp_conn->tc_tcpopt;	if (tmp_tcpopt)		tmp_tcpopt->acc_linkC++;	tcp_extract_ipopt (tcp_conn, ip_hdr);	tcp_extract_tcpopt (tcp_conn, tcp_hdr, &mss);	RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr,		(acc_t *)0);	if (tcp_conn->tc_remipopt)		bf_afree(tcp_conn->tc_remipopt);	tcp_conn->tc_remipopt= tmp_ipopt;	if (tcp_conn->tc_tcpopt)		bf_afree(tcp_conn->tc_tcpopt);	tcp_conn->tc_tcpopt= tmp_tcpopt;	RST_ip_hdr->ih_src= ip_hdr->ih_dst;	RST_ip_hdr->ih_dst= ip_hdr->ih_src;	RST_tcp_hdr->th_srcport= tcp_hdr->th_dstport;	RST_tcp_hdr->th_dstport= tcp_hdr->th_srcport;	if (tcp_hdr->th_flags & THF_ACK)	{		RST_tcp_hdr->th_seq_nr= tcp_hdr->th_ack_nr;		RST_tcp_hdr->th_flags= THF_RST;	}	else	{		RST_tcp_hdr->th_seq_nr= 0;		RST_tcp_hdr->th_ack_nr=			htonl(				ntohl(tcp_hdr->th_seq_nr)+				data_len +				(tcp_hdr->th_flags & THF_SYN ? 1 : 0) +				(tcp_hdr->th_flags & THF_FIN ? 1 : 0));		RST_tcp_hdr->th_flags= THF_RST|THF_ACK;	}	pack_size= bf_bufsize(RST_acc);	RST_ip_hdr->ih_length= htons(pack_size);	RST_tcp_hdr->th_window= htons(tcp_conn->tc_rcv_wnd);	RST_tcp_hdr->th_chksum= 0;	RST_acc->acc_linkC++;	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	tcp_pack= bf_delhead(RST_acc, ip_hdr_len);	RST_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_ip_hdr, tcp_pack);	bf_afree(tcp_pack);		DBLOCK(2, tcp_print_pack(ip_hdr, tcp_hdr); printf("\n");		tcp_print_pack(RST_ip_hdr, RST_tcp_hdr); printf("\n"));	if (tcp_conn->tc_frag2send)		bf_afree(tcp_conn->tc_frag2send);	tcp_conn->tc_frag2send= RST_acc;	tcp_conn_write(tcp_conn, 1);}PUBLIC voidtcp_fd_read(tcp_conn, enq)tcp_conn_t *tcp_conn;int enq;					/* Enqueue writes. */{	tcp_fd_t *tcp_fd;	size_t data_size, read_size;	acc_t *data;	int fin_recv, urg, push, result;	i32_t old_window, new_window;	u16_t mss;	assert(tcp_conn->tc_busy);	tcp_fd= tcp_conn->tc_fd;	assert (tcp_fd->tf_flags & TFF_READ_IP);	if (tcp_conn->tc_state == TCS_CLOSED)	{		if (tcp_fd->tf_read_offset)			tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);		else			tcp_reply_read (tcp_fd, tcp_conn->tc_error);		return;	}	urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);	push= (tcp_conn->tc_flags & TCF_RCV_PUSH);	fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;	if (fin_recv)		data_size--;	if (urg)	{#if DEBUG		printf("tcp_fd_read: RCV_UP = 0x%x, RCV_LO = 0x%x\n",			tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);#endif		read_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;	}	else		read_size= data_size;	if (read_size >= tcp_fd->tf_read_count)		read_size= tcp_fd->tf_read_count;	else if (!push && !fin_recv && !urg &&		data_size < TCP_MIN_RCV_WND_SIZE)	{		/* Defer the copy out until later. */		return;	}	else if (data_size == 0 && !fin_recv)	{		/* No data, and no end of file. */		return;	}	if (read_size)	{		if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))		{			if (tcp_fd->tf_read_offset)			{				tcp_reply_read (tcp_fd,					tcp_fd->tf_read_offset);			}			else			{				tcp_reply_read (tcp_fd, EURG);			}			return;		}		else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))		{			if (tcp_fd->tf_read_offset)			{				tcp_reply_read (tcp_fd,					tcp_fd->tf_read_offset);			}			else			{				tcp_reply_read(tcp_fd, ENOURG);			}			return;		}		if (read_size == data_size)		{			data= tcp_conn->tc_rcvd_data;			data->acc_linkC++;		}		else		{			data= bf_cut(tcp_conn->tc_rcvd_data, 0, read_size);		}		result= (*tcp_fd->tf_put_userdata) (tcp_fd->tf_srfd,			tcp_fd->tf_read_offset, data, FALSE);		if (result<0)		{			if (tcp_fd->tf_read_offset)				tcp_reply_read(tcp_fd, tcp_fd->					tf_read_offset);			else				tcp_reply_read(tcp_fd, result);			return;		}		tcp_fd->tf_read_offset += read_size;		tcp_fd->tf_read_count -= read_size;		if (data_size == read_size)		{			bf_afree(tcp_conn->tc_rcvd_data);			tcp_conn->tc_rcvd_data= 0;		}		else		{			tcp_conn->tc_rcvd_data=				bf_delhead(tcp_conn->tc_rcvd_data,				read_size);		}		tcp_conn->tc_RCV_LO += read_size;		data_size -= read_size;	}	/* Update IRS and often RCV_UP every 0.5GB */	if (tcp_conn->tc_RCV_LO - tcp_conn->tc_IRS > 0x40000000)	{		tcp_conn->tc_IRS += 0x20000000;		DBLOCK(1, printf("tcp_fd_read: updating IRS to 0x%lx\n",			(unsigned long)tcp_conn->tc_IRS););		if (tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_IRS))		{			tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;			DBLOCK(1, printf(				"tcp_fd_read: updating RCV_UP to 0x%lx\n",				(unsigned long)tcp_conn->tc_RCV_UP););		}		DBLOCK(1, printf("tcp_fd_read: RCP_LO = 0x%lx\n",			(unsigned long)tcp_conn->tc_RCV_LO););	}	mss= tcp_conn->tc_mtu-IP_TCP_MIN_HDR_SIZE;	if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO <=		tcp_conn->tc_rcv_wnd-mss)	{		old_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;		tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO + 			tcp_conn->tc_rcv_wnd;		new_window= tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_NXT;		assert(old_window >=0 && new_window >= old_window);		if (old_window < mss && new_window >= mss)		{			tcp_conn->tc_flags |= TCF_SEND_ACK;			DBLOCK(2, printf("opening window\n"));			tcp_conn_write(tcp_conn, 1);		}	}	if (tcp_conn->tc_rcvd_data == NULL &&		tcp_conn->tc_adv_data == NULL)	{		/* Out of data, clear PUSH flag and reply to a read. */		tcp_conn->tc_flags &= ~TCF_RCV_PUSH;	}	if (fin_recv || urg || tcp_fd->tf_read_offset ||		!tcp_fd->tf_read_count)	{		tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);		return;	}}PUBLIC unsignedtcp_sel_read(tcp_conn)tcp_conn_t *tcp_conn;{	tcp_fd_t *tcp_fd;	size_t data_size;	int fin_recv, urg, push;	tcp_fd= tcp_conn->tc_fd;	if (tcp_conn->tc_state == TCS_CLOSED)		return 1;	fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);	if (fin_recv)		return 1;	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;	if (data_size == 0)	{		/* No data, and no end of file. */		return 0;	}	urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);	push= (tcp_conn->tc_flags & TCF_RCV_PUSH);	if (!push && !urg && data_size < TCP_MIN_RCV_WND_SIZE)	{		/* Defer until later. */		return 0;	}	return 1;}PUBLIC voidtcp_rsel_read(tcp_conn)tcp_conn_t *tcp_conn;{	tcp_fd_t *tcp_fd;	if (tcp_sel_read(tcp_conn) == 0)		return;	tcp_fd= tcp_conn->tc_fd;	tcp_fd->tf_flags &= ~TFF_SEL_READ;	if (tcp_fd->tf_select_res)		tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_READ);	else		printf("tcp_rsel_read: no select_res\n");}PUBLIC void tcp_bytesavailable(tcp_fd, bytesp)tcp_fd_t *tcp_fd;int *bytesp;{	tcp_conn_t *tcp_conn;	size_t data_size, read_size;	acc_t *data;	int fin_recv, urg, push, result;	i32_t old_window, new_window;	u16_t mss;	*bytesp= 0;	/* The default is that nothing is available */	if (!(tcp_fd->tf_flags & TFF_CONNECTEDx))		return;	tcp_conn= tcp_fd->tf_conn;	if (tcp_conn->tc_state == TCS_CLOSED)		return;	urg= tcp_Gmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO);	push= (tcp_conn->tc_flags & TCF_RCV_PUSH);	fin_recv= (tcp_conn->tc_flags & TCF_FIN_RECV);	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;	if (fin_recv)		data_size--;	if (urg)		data_size= tcp_conn->tc_RCV_UP-tcp_conn->tc_RCV_LO;	if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))		return;	else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))		return;	*bytesp= data_size;}/* * $PchId: tcp_recv.c,v 1.30 2005/06/28 14:21:35 philip Exp $ */

⌨️ 快捷键说明

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