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

📄 tcp_recv.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	hdr_acc= bf_memreq(tcp_hdr_len);	/* make fresh header */
	if (tcp_conn->tc_state == TCS_CLOSED)
	{
#if DEBUG
 { where(); printf("connection closed while inuse\n"); }
#endif
		bf_afree(hdr_acc);
		return;
	}
	assert (hdr_acc->acc_length == tcp_hdr_len);
	tmp_hdr= (tcp_hdr_t *)ptr2acc_data(hdr_acc);
#if DEBUG & 256
 { where(); printf("doing memcpy\n"); }
#endif
	memcpy ((char *)tmp_hdr, (char *)tcp_hdr, tcp_hdr_len);
	tcp_hdr= tmp_hdr;

	data_acc= bf_cut (tcp_data, tcp_hdr_len, data_len);

	seg_seq= ntohl(tcp_hdr->th_seq_nr);
	tcp_hdr->th_seq_nr= seg_seq;	/* seq_nr in host format */

	if (tcp_hdr->th_flags & THF_URG)
	{
		seg_up= ntohs(tcp_hdr->th_urgptr);
		tcp_hdr->th_urgptr= seg_up;
					/* urgptr in host format */
		tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+
			tcp_conn->tc_rcv_wnd+tcp_conn->tc_urg_wnd;
	}

	assert (!(tcp_hdr->th_flags & THF_SYN));
	assert (tcp_Gmod4G(seg_seq, tcp_conn->tc_RCV_NXT));

	tcp_hdr->th_flags &= ~THF_FIN;	/* it is too difficult to
		preserve a FIN */

	seg_hi= seg_seq + data_len;

	if (tcp_Gmod4G(seg_hi, tcp_conn->tc_RCV_HI))
	{
		seg_hi= tcp_conn->tc_RCV_HI;
		data_len= seg_hi-seg_seq;
		if (!data_len)
		{
			bf_afree(hdr_acc);
			bf_afree(data_acc);
			return;
		}
#if DEBUG
 { where(); printf("Cutting packet\n"); }
#endif
		tmp_acc= bf_cut(data_acc, 0, data_len);
		bf_afree(data_acc);
		data_acc= tmp_acc;
	}
	hdr_acc->acc_next= data_acc;
	hdr_acc->acc_ext_link= 0;

	head_acc= tcp_conn->tc_rcv_queue;
	tcp_conn->tc_rcv_queue= 0;
	tail_acc_ptr= 0;
	next_acc= head_acc;

	while (next_acc)
	{
		assert (next_acc->acc_length >= TCP_MIN_HDR_SIZE);
		tmp_hdr= (tcp_hdr_t *)ptr2acc_data(next_acc);
		if (tcp_Lmod4G(seg_seq, tmp_hdr->th_seq_nr))
		{
#if DEBUG & 256
 { where(); printf("calling merge_packs\n"); } 
#endif
			next_acc= merge_packs(hdr_acc, next_acc);
			hdr_acc= 0;
			if (tail_acc_ptr)
			{
assert (*tail_acc_ptr);
				(*tail_acc_ptr)->acc_ext_link= 0;
#if DEBUG & 256
 { where(); printf("calling merge_packs\n"); } 
#endif
				*tail_acc_ptr= merge_packs(
					*tail_acc_ptr, next_acc);
			}
			else
				head_acc= next_acc;
			break;
		}
		if (!tail_acc_ptr)
			tail_acc_ptr=  &head_acc;
		else
			tail_acc_ptr= &(*tail_acc_ptr)->acc_ext_link;
		next_acc= next_acc->acc_ext_link;
	}
	if (hdr_acc)
	{
		next_acc= hdr_acc;
		hdr_acc= 0;
		if (tail_acc_ptr)
		{
			if (*tail_acc_ptr)
			{
				(*tail_acc_ptr)->acc_ext_link= 0;
#if DEBUG & 256
 { where(); printf("calling merge_packs\n"); } 
#endif
				*tail_acc_ptr= merge_packs(
					*tail_acc_ptr, next_acc);
			}
			else
				*tail_acc_ptr= next_acc;
		}
		else
			head_acc= next_acc;
	}
	if (tcp_conn->tc_state == TCS_CLOSED)
	{
		while (head_acc)
		{
			next_acc= head_acc->acc_ext_link;
			bf_afree(head_acc);
			head_acc= next_acc;
		}
		return;
	}
	tcp_conn->tc_rcv_queue= head_acc;
}
				
PRIVATE acc_t *merge_packs(first, next)
acc_t *first;
acc_t *next;
{
	tcp_hdr_t *first_hdr, *next_hdr;
	int first_hdr_len, next_hdr_len, first_data_len, next_data_len;
	acc_t *next_acc, *tmp_acc;

	assert (first->acc_length >= TCP_MIN_HDR_SIZE);
	assert (next->acc_length >= TCP_MIN_HDR_SIZE);

	first_hdr= (tcp_hdr_t *)ptr2acc_data(first);
	next_hdr= (tcp_hdr_t *)ptr2acc_data(next);

	first_hdr_len= (first_hdr->th_data_off & TH_DO_MASK) >>2;
	next_hdr_len= (next_hdr->th_data_off & TH_DO_MASK) >> 2;

	first_data_len= first_hdr->th_chksum-first_hdr_len;
	next_data_len= next_hdr->th_chksum-next_hdr_len;

assert (tcp_LEmod4G(first_hdr->th_seq_nr, next_hdr->th_seq_nr));
assert (first_hdr_len + first_data_len == bf_bufsize(first));
#if DEBUG
 if (next_hdr_len + next_data_len != bf_bufsize(next))
 { ip_panic(( "fatal error: %d + %d != %d\n", next_hdr_len, next_data_len,
    bf_bufsize(next) )); }
#endif
assert (next_hdr_len + next_data_len == bf_bufsize(next));

	if (tcp_Lmod4G(first_hdr->th_seq_nr+first_data_len,
		next_hdr->th_seq_nr))
	{
		first->acc_ext_link= next;
		return first;
	}
	if (first_hdr->th_seq_nr == next_hdr->th_seq_nr)
		if (first_data_len <= next_data_len)
		{
			bf_afree(first);
			return next;
		}
		else
		{
			first->acc_ext_link= next->acc_ext_link;
			bf_afree(next);
			return first;
		}
	if (tcp_GEmod4G(first_hdr->th_seq_nr+first_data_len,
		next_hdr->th_seq_nr+next_data_len))
	{
		first->acc_ext_link= next->acc_ext_link;
		bf_afree(next);
		return first;
	}
	first_data_len= next_hdr->th_seq_nr-first_hdr->th_seq_nr;
	first_hdr->th_chksum= first_data_len+first_hdr_len+
		next_data_len;
	tmp_acc= bf_cut(first, 0, first_hdr_len + first_data_len);
	bf_afree(first);
	first= tmp_acc;

	if (next_hdr->th_flags & THF_PSH)
		first_hdr->th_flags |= THF_PSH;
	if (next_hdr->th_flags & THF_URG)
	{
		if (!(first_hdr->th_flags & THF_URG))
		{
			first_hdr->th_flags |= THF_URG;
			first_hdr->th_urgptr= next_hdr->th_seq_nr+
				next_hdr->th_urgptr-
				first_hdr->th_seq_nr;
		}
		else if (next_hdr->th_seq_nr+next_hdr->th_urgptr-
			first_hdr->th_seq_nr > first_hdr->th_urgptr)
			first_hdr->th_urgptr= next_hdr->th_seq_nr+
				next_hdr->th_urgptr-
				first_hdr->th_seq_nr;
	}

	next_acc= next->acc_ext_link;
	tmp_acc= bf_cut(next, next_hdr_len ,next_data_len);
	bf_afree(next);
	next= tmp_acc;
	tmp_acc= bf_append (first, next);
	tmp_acc->acc_ext_link= next_acc;
	return tmp_acc;
}

PRIVATE void create_RST(tcp_conn, ip_hdr, tcp_hdr)
tcp_conn_t *tcp_conn;
ip_hdr_t *ip_hdr;
tcp_hdr_t *tcp_hdr;
{
	acc_t *tmp_ipopt, *tmp_tcpopt;
	ip_hdropt_t ip_hdropt;
	tcp_hdropt_t tcp_hdropt;
	acc_t *RST_acc;
	ip_hdr_t *RST_ip_hdr;
	tcp_hdr_t *RST_tcp_hdr;
	char *ptr2RSThdr;
	size_t pack_size;

	tmp_ipopt= tcp_conn->tc_remipopt;
	if (tmp_ipopt)
		tmp_ipopt->acc_linkC++;
	tmp_tcpopt= tcp_conn->tc_remtcpopt;
	if (tmp_tcpopt)
		tmp_tcpopt->acc_linkC++;

	tcp_extract_ipopt (tcp_conn, ip_hdr);
	tcp_extract_tcpopt (tcp_conn, tcp_hdr);

	RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr,
		(acc_t *)0);
	if (!RST_acc)
	{
#if DEBUG
 { where(); printf("connection closed while inuse\n"); }
#endif
		return;
	}

	if (tcp_conn->tc_remipopt)
		bf_afree(tcp_conn->tc_remipopt);
	tcp_conn->tc_remipopt= tmp_ipopt;
	if (tcp_conn->tc_remtcpopt)
		bf_afree(tcp_conn->tc_remtcpopt);
	tcp_conn->tc_remtcpopt= 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)+
			tcp_hdr->th_chksum-((tcp_hdr->th_data_off &
			TH_DO_MASK) >> 2)+ (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_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_acc, pack_size);
	
	if (tcp_conn->tc_frag2send)
		bf_afree(tcp_conn->tc_frag2send);
	tcp_conn->tc_frag2send= RST_acc;
}

PUBLIC void tcp_restart_fd_read (tcp_conn)
tcp_conn_t *tcp_conn;
{
	tcp_fd_t *new_fd, *hi_fd, *urgent_fd, *normal_fd, *tcp_fd;

#if DEBUG & 256
 { where(); printf("tcp_restart_fd_read called\n"); }
#endif
	do
	{
		tcp_fd= tcp_conn->tc_readuser;

		if (tcp_fd)
			fd_read (tcp_fd);
		else
			tcp_fd= &tcp_fd_table[TCP_FD_NR-1];

		if (!tcp_conn->tc_readuser)
		{
			urgent_fd= 0;
			normal_fd= 0;
			for (new_fd= tcp_fd+1, hi_fd=
				&tcp_fd_table[TCP_FD_NR]; new_fd<hi_fd;
				new_fd++)
				switch_read_fd(tcp_conn, new_fd,
					&urgent_fd, &normal_fd);
			for (new_fd= tcp_fd_table, hi_fd= tcp_fd+1;
				new_fd < hi_fd; new_fd++)
				switch_read_fd(tcp_conn, new_fd,
					&urgent_fd, &normal_fd);
			if (urgent_fd)
				tcp_fd= urgent_fd;
			else
				tcp_fd= normal_fd;
			tcp_conn->tc_readuser= tcp_fd;
		}
		else
			return;
	} while (tcp_conn->tc_readuser);
}

PRIVATE void switch_read_fd (tcp_conn, new_fd, ref_urg_fd,
	ref_norm_fd)
tcp_conn_t *tcp_conn;
tcp_fd_t *new_fd, **ref_urg_fd, **ref_norm_fd;
{
	if (!(new_fd->tf_flags & TFF_INUSE))
		return;
	if (new_fd->tf_conn != tcp_conn)
		return;
	if (!(new_fd->tf_flags & TFF_READ_IP))
		return;
	if (new_fd->tf_flags & TFF_RECV_URG)
	{
		if (!*ref_urg_fd)
			*ref_urg_fd= new_fd;
	}
	else
	{
		if (!*ref_norm_fd)
			*ref_norm_fd= new_fd;
	}
}

PRIVATE void fd_read(tcp_fd)
tcp_fd_t *tcp_fd;
{
	tcp_conn_t *tcp_conn;
	size_t data_size, read_size;
	acc_t * data;
	int urg, result;
	int more2write;

	more2write= FALSE;
	tcp_conn= tcp_fd->tf_conn;

	assert (tcp_fd->tf_flags & TFF_READ_IP);
	if (tcp_conn->tc_state == TCS_CLOSED)
	{
		tcp_conn->tc_readuser= 0;
#if DEBUG
 { where(); printf("calling tcp_reply_read\n"); }
#endif
		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;
	}

#if URG_PROPERLY_IMPLEMENTED
	urg= (tcp_GEmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO) &&
		tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_NXT));
#else
#define urg 0
#endif
	if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
	{
		tcp_conn->tc_readuser= 0;
#if DEBUG
 { where(); printf("calling tcp_reply_read\n"); }
#endif
		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))
	{
		tcp_conn->tc_readuser= 0;
#if DEBUG
 { where(); printf("calling tcp_reply_read\n"); }
#endif
		if (tcp_fd->tf_read_offset)
			tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
		else
			tcp_reply_read(tcp_fd, ENOURG);
		return;
	}
	data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
	if (tcp_conn->tc_flags & TCF_FIN_RECV)
		data_size--;
	if (urg)
		read_size= tcp_conn->tc_RCV_UP+1-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;

	if (read_size)
	{
		if (read_size == data_size)
			data= bf_dupacc(tcp_conn->tc_rcvd_data);
		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 (tcp_conn->tc_state == TCS_CLOSED)
		{
#if DEBUG
 { where(); printf("connection closed while inuse\n"); }
#endif
			return;
		}
		if (result<0)
		{
			tcp_conn->tc_readuser= 0;
#if DEBUG
 { where(); printf("calling tcp_reply_read\n"); }
#endif
			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
		{
			data= tcp_conn->tc_rcvd_data;
			tcp_conn->tc_rcvd_data= bf_cut(data,
				read_size, data_size-read_size);
			bf_afree(data);
		}
		tcp_conn->tc_RCV_LO += read_size;
		data_size -= read_size;
	}
	if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO < (tcp_conn->
		tc_rcv_wnd >> 2))
	{
		tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO + 
			tcp_conn->tc_rcv_wnd;
		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
		more2write= TRUE;
	}
	if (!data_size && (tcp_conn->tc_flags & TCF_RCV_PUSH))
	{
		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_fd->tf_read_offset)
		{
			tcp_conn->tc_readuser= 0;
#if DEBUG & 256
 { where(); printf("calling tcp_reply_read\n"); }
#endif
			tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
			if (more2write)
				tcp_restart_write(tcp_conn);
			return;
		}
	}
	if ((tcp_conn->tc_flags & TCF_FIN_RECV) ||
		!tcp_fd->tf_read_count)
	{
		tcp_conn->tc_readuser= 0;
#if DEBUG & 256
 { where(); printf("calling tcp_reply_read\n"); }
#endif
		tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
		if (more2write)
			tcp_restart_write(tcp_conn);
		return;
	}
	if (more2write)
		tcp_restart_write(tcp_conn);
}

⌨️ 快捷键说明

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