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

📄 tcp.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
		break;
	case SR_CANCEL_READ:
assert (tcp_fd->tf_flags & TFF_READ_IP);
		tcp_fd->tf_flags &= ~TFF_READ_IP;
		if (tcp_conn->tc_readuser == tcp_fd)
		{
			tcp_conn->tc_readuser= 0;
			tcp_restart_fd_read (tcp_conn);
		}
		if (tcp_fd->tf_read_count)
			reply_thr_put (tcp_fd, tcp_fd->tf_read_count, FALSE);
		else
			reply_thr_put (tcp_fd, EINTR, FALSE);
		break;
	case SR_CANCEL_IOCTL:
assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;

		type= tcp_fd->tf_ioreq & IOCTYPE_MASK;
		switch (type)
		{
		case NWIOGTCPCONF & IOCTYPE_MASK:
			reply_thr_put (tcp_fd, EINTR, TRUE);
			break;
		case NWIOSTCPCONF & IOCTYPE_MASK:
		case NWIOTCPSHUTDOWN & IOCTYPE_MASK:
		case NWIOTCPATTACH & IOCTYPE_MASK:
			reply_thr_get (tcp_fd, EINTR, TRUE);
			break;
		case NWIOTCPCONN & IOCTYPE_MASK:
		case NWIOTCPLISTEN & IOCTYPE_MASK:
assert (tcp_conn->tc_connuser == tcp_fd);
			tcp_conn->tc_connuser= 0;
			tcp_conn->tc_mainuser= 0;
			tcp_close_connection(tcp_conn, ENOCONN);
			reply_thr_get (tcp_fd, EINTR, TRUE);
			break;
		default:
			ip_warning(( "unknown ioctl inprogress: 0x%x",
				tcp_fd->tf_ioreq ));
			reply_thr_get (tcp_fd, EINTR, TRUE);
			break;
		}
		break;
	default:
		ip_panic(( "unknown cancel request" ));
		break;
	}
	return NW_OK;
}

/*
tcp_connect
*/

PRIVATE int tcp_connect(tcp_fd)
tcp_fd_t *tcp_fd;
{
	tcp_conn_t *tcp_conn;
	int state;

	if (!(tcp_fd->tf_flags & TFF_OPTSET))
	{
#if DEBUG
 { where(); }
#endif
		tcp_reply_ioctl(tcp_fd, EBADMODE);
		return NW_OK;
	}
	if (tcp_fd->tf_flags & TFF_CONNECT)
	{
		tcp_reply_ioctl(tcp_fd, EISCONN);
		return NW_OK;
	}
	if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
		!= (NWTC_SET_RA|NWTC_SET_RP))
	{
#if DEBUG
 { where(); printf("tcp_fd_table[%d].tf_tcpconf.nwtc_flags= 0x%x\n",
	tcp_fd-tcp_fd_table, tcp_fd->tf_tcpconf.nwtc_flags); }
#endif
		tcp_reply_ioctl(tcp_fd, EBADMODE);
		return NW_OK;
	}

assert(!tcp_fd->tf_conn);
	tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
		tcp_fd->tf_port->tp_ipaddr,
		tcp_fd->tf_tcpconf.nwtc_remport,
		tcp_fd->tf_tcpconf.nwtc_remaddr);
	if (tcp_conn)
	{
		if (tcp_conn->tc_mainuser)
		{
			tcp_reply_ioctl(tcp_fd, EADDRINUSE);
			return NW_OK;
		}
	}
	else
	{
		tcp_conn= find_empty_conn();
		if (!tcp_conn)
		{
			tcp_reply_ioctl(tcp_fd, EAGAIN);
			return NW_OK;
		}
	}
	tcp_fd->tf_conn= tcp_conn;
	return tcp_su4connect(tcp_fd);
}

/*
tcp_su4connect
*/

PRIVATE int tcp_su4connect(tcp_fd)
tcp_fd_t *tcp_fd;
{
	tcp_conn_t *tcp_conn;
	acc_t *tmp_acc;

	tcp_conn= tcp_fd->tf_conn;

	tcp_conn->tc_locport= tcp_fd->tf_tcpconf.nwtc_locport;
	tcp_conn->tc_locaddr= tcp_fd->tf_port->tp_ipaddr;

assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP);
assert (tcp_fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA);

	tcp_conn->tc_remport= tcp_fd->tf_tcpconf.nwtc_remport;
	tcp_conn->tc_remaddr= tcp_fd->tf_tcpconf.nwtc_remaddr;
	tcp_conn->tc_mainuser= tcp_fd;

	tcp_setup_conn(tcp_conn);
	tcp_conn->tc_port= tcp_fd->tf_port;
	tcp_conn->tc_connuser= tcp_fd;
#if DEBUG & 256
 { where(); printf("tcp_conn_table[%d].tc_connuser= 0x%x\n", tcp_conn-
	tcp_conn_table, tcp_conn->tc_connuser); }
#endif
	tcp_conn->tc_orglisten= FALSE;
	tcp_conn->tc_state= TCS_SYN_SENT;
#if DEBUG & 16
 { where(); tcp_write_state(tcp_conn); }
#endif
	tcp_restart_write (tcp_conn);

	if (tcp_conn->tc_connuser)
		return NW_SUSPEND;
	else
		return NW_OK;
}

PRIVATE void close_mainuser(tcp_conn, tcp_fd)
tcp_conn_t *tcp_conn;
tcp_fd_t *tcp_fd;
{
	int i;

	if (tcp_conn->tc_mainuser != tcp_fd)
		return;

	tcp_conn->tc_mainuser= 0;
	assert (tcp_conn->tc_writeuser != tcp_fd);
	assert (tcp_conn->tc_readuser != tcp_fd);
	assert (tcp_conn->tc_connuser != tcp_fd);

	for (i= 0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)
	{
		if (!(tcp_fd->tf_flags & TFF_INUSE))
			continue;
		if (tcp_fd->tf_conn != tcp_conn)
			continue;
		tcp_conn->tc_mainuser= tcp_fd;
		return;
	}
}


PRIVATE int conn_right4fd(tcp_conn, tcp_fd)
tcp_fd_t *tcp_fd;
tcp_conn_t *tcp_conn;
{
	unsigned long flags;

	flags= tcp_fd->tf_tcpconf.nwtc_flags;

	if (tcp_fd->tf_tcpconf.nwtc_locport != tcp_conn->tc_locport)
		return FALSE;

	if ((flags & NWTC_SET_RA) && tcp_fd->tf_tcpconf.nwtc_remaddr !=
		tcp_conn->tc_remaddr)
		return FALSE;

	if ((flags & NWTC_SET_RP) && tcp_fd->tf_tcpconf.nwtc_remport !=
		tcp_conn->tc_remport)
		return FALSE;

	if (tcp_fd->tf_port != tcp_conn->tc_port)
		return FALSE;

	return TRUE;
}

PRIVATE int tcp_attache(tcp_fd)
tcp_fd_t *tcp_fd;
{
	tcp_conn_t *tcp_conn;
	int state;

	if (!(tcp_fd->tf_flags & TFF_OPTSET))
	{
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get(tcp_fd, EBADMODE, TRUE);
		return NW_OK;
	}
	if (tcp_fd->tf_flags & TFF_CONNECT)
	{
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get(tcp_fd, EISCONN, TRUE);
		return NW_OK;
	}
	if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
		!= (NWTC_SET_RA|NWTC_SET_RP))
	{
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get(tcp_fd, EBADMODE, TRUE);
		return NW_OK;
	}

	tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport,
		tcp_fd->tf_port->tp_ipaddr,
		tcp_fd->tf_tcpconf.nwtc_remport,
		tcp_fd->tf_tcpconf.nwtc_remaddr);
	if (!tcp_conn)
	{
#if DEBUG
 { where(); printf("conn_entry not found\n"); }
#endif
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get (tcp_fd, ENOCONN, TRUE);
		return NW_OK;
	}
	assert (tcp_conn->tc_flags & TCF_INUSE);
	state= tcp_conn->tc_state;
	if (state == TCS_CLOSED || state == TCS_LISTEN || state ==
		TCS_SYN_SENT || state == TCS_SYN_RECEIVED)
	{
#if DEBUG
 { where(); printf("conn_entry in wrong state: ");
	tcp_write_state(tcp_conn); printf("\n"); }
#endif
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get (tcp_fd, ENOCONN, TRUE);
		return NW_OK;
	}
	tcp_fd->tf_conn= tcp_conn;
	tcp_fd->tf_flags |= TFF_CONNECTED;
	tcp_fd->tf_flags |= TFF_PUSH_DATA;	/* XXX */
	return NW_OK;
}

/*
tcp_listen
*/

PRIVATE int tcp_listen(tcp_fd)
tcp_fd_t *tcp_fd;
{
	tcp_conn_t *tcp_conn;
	int state;

#if DEBUG & 256
 { where(); printf("tcp_listen(&tcp_fd_table[%d]) called\n", tcp_fd-
	tcp_fd_table); }
#endif
	if (!(tcp_fd->tf_flags & TFF_OPTSET))
	{
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get(tcp_fd, EBADMODE, TRUE);
		return NW_OK;
	}
	if (tcp_fd->tf_flags & TFF_CONNECT)
	{
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get(tcp_fd, EISCONN, TRUE);
		return NW_OK;
	}
	tcp_conn= tcp_fd->tf_conn;
assert(!tcp_conn);
	if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP))
		== (NWTC_SET_RA|NWTC_SET_RP))
	{
		tcp_conn= find_conn_entry(
			tcp_fd->tf_tcpconf.nwtc_locport,
			tcp_fd->tf_port->tp_ipaddr,
			tcp_fd->tf_tcpconf.nwtc_remport,
			tcp_fd->tf_tcpconf.nwtc_remaddr);
		if (tcp_conn)
		{
			if (tcp_conn->tc_mainuser)
			{
				tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
				reply_thr_get (tcp_fd, EADDRINUSE, TRUE);
				return NW_OK;
			}
			tcp_fd->tf_conn= tcp_conn;
			return tcp_su4listen(tcp_fd);
		}
	}
	tcp_conn= find_empty_conn();
	if (!tcp_conn)
	{
		tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
		reply_thr_get (tcp_fd, EAGAIN, TRUE);
		return NW_OK;
	}
	tcp_fd->tf_conn= tcp_conn;
#if DEBUG & 256
 { where(); printf("tcp_conn_table[%d].tc_connuser= 0x%x\n", tcp_conn-
	tcp_conn_table, tcp_conn->tc_connuser); }
#endif
	return tcp_su4listen(tcp_fd);
}

PRIVATE void tcp_buffree (priority, reqsize)
int priority;
size_t reqsize;
{
	int i;
	tcp_conn_t *tcp_conn;

	if (priority <TCP_PRI_FRAG2SEND)
		return;

#if DEBUG & 256
 { where(); printf("tcp_buffree called\n"); }
#endif

	for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
		tcp_conn++)
	{
		if (!(tcp_conn->tc_flags & TCF_INUSE))
			continue;
		if (!tcp_conn->tc_frag2send)
			continue;
		bf_afree(tcp_conn->tc_frag2send);
		tcp_conn->tc_frag2send= 0;
		if (bf_free_buffsize >= reqsize)
			return;
	}

	if (priority <TCP_PRI_CONNwoUSER)
		return;

	for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
		tcp_conn++)
	{
		if (!(tcp_conn->tc_flags & TCF_INUSE))
			continue;
		if (tcp_conn->tc_mainuser)
			continue;
		if (tcp_conn->tc_state == TCS_CLOSED)
			continue;
#if DEBUG
 { where(); printf("calling tcp_close_connection (out of memory)\n"); }
#endif
		tcp_close_connection (tcp_conn, EOUTOFBUFS);
		if (bf_free_buffsize >= reqsize)
			return;
	}

	if (priority <TCP_PRI_CONN_INUSE)
		return;

	for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,
		tcp_conn++)
	{
		if (!(tcp_conn->tc_flags & TCF_INUSE))
			continue;
		if (tcp_conn->tc_state == TCS_CLOSED)
			continue;
#if DEBUG
 { where(); printf("calling tcp_close_connection (out of memory)\n"); }
#endif
		tcp_close_connection (tcp_conn, EOUTOFBUFS);
		if (bf_free_buffsize >= reqsize)
			return;
	}
}

PRIVATE void tcp_notreach(pack)
acc_t *pack;
{
	acc_t *tcp_pack;
	ip_hdr_t *ip_hdr;
	tcp_hdr_t *tcp_hdr;
	tcp_conn_t *tcp_conn;
	int ip_hdr_size;
	int new_ttl;

	pack->acc_linkC++;
	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
	ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;

	tcp_pack= bf_cut(pack, ip_hdr_size, TCP_MIN_HDR_SIZE);
	tcp_pack= bf_packIffLess(tcp_pack, TCP_MIN_HDR_SIZE);
	tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);

	tcp_conn= find_conn_entry( tcp_hdr->th_srcport, ip_hdr->ih_src,
		tcp_hdr->th_dstport, ip_hdr->ih_dst);
	if (tcp_conn)
	{
		new_ttl= tcp_conn->tc_ttl;
		if (new_ttl == IP_MAX_TTL)
		{
#if DEBUG
 { where(); printf("calling tcp_close_connection\n"); }
#endif
			tcp_close_connection(tcp_conn, EDSTNOTRCH);
			bf_afree(pack);
			bf_afree(tcp_pack);
			return;
		}
		new_ttl *= 2;
		if (new_ttl> IP_MAX_TTL)
			new_ttl= IP_MAX_TTL;
		tcp_conn->tc_ttl= new_ttl;
		tcp_conn->tc_no_retrans= 0;
	}
	else
	{
#if DEBUG
 { where(); printf("got a EDSTNOTRCH for non existing connection\n"); }
#endif
	}
	bf_afree(pack);
	bf_afree(tcp_pack);
}

/*
tcp_setup_conn
*/

PRIVATE void tcp_setup_conn(tcp_conn)
tcp_conn_t *tcp_conn;
{
assert(!tcp_conn->tc_readuser);
assert(!tcp_conn->tc_writeuser);
assert(!tcp_conn->tc_connuser);
	if (tcp_conn->tc_flags & TCF_INUSE)
	{
assert (tcp_conn->tc_state == TCS_CLOSED || 
	tcp_conn->tc_state == TCS_TIME_WAIT);
assert (!tcp_conn->tc_send_data);
		if (tcp_conn->tc_senddis < get_time())
			tcp_conn->tc_ISS= 0;
	}
	else
	{
		tcp_conn->tc_senddis= 0;
		tcp_conn->tc_ISS= 0;
		tcp_conn->tc_tos= TCP_DEF_TOS;
		tcp_conn->tc_ttl= TCP_DEF_TTL;
		tcp_conn->tc_rcv_wnd= TCP_MAX_WND_SIZE;
		tcp_conn->tc_urg_wnd= TCP_DEF_URG_WND;
	}
	if (!tcp_conn->tc_ISS)
	{
		tcp_conn->tc_ISS= (get_time()/HZ)*ISS_INC_FREQ;
	}
	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;
	tcp_conn->tc_SND_PSH= tcp_conn->tc_ISS;
	tcp_conn->tc_SND_WL2= tcp_conn->tc_ISS;
	tcp_conn->tc_IRS= 0;
	tcp_conn->tc_SND_WL1= tcp_conn->tc_IRS;
	tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS;
	tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS;
	tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS;
	tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS;
	tcp_conn->tc_rcvd_data= 0;
	tcp_conn->tc_rcv_queue= 0;
	tcp_conn->tc_send_data= 0;
	tcp_conn->tc_remipopt= 0;
	tcp_conn->tc_remtcpopt= 0;
	tcp_conn->tc_frag2send= 0;
	tcp_conn->tc_no_retrans= 0;
	tcp_conn->tc_max_no_retrans= TCP_DEF_MAX_NO_RETRANS;
	tcp_conn->tc_0wnd_to= 0;
	tcp_conn->tc_rtt= TCP_DEF_RTT;
	tcp_conn->tc_ett= 0;
	tcp_conn->tc_mss= TCP_DEF_MSS;
	tcp_conn->tc_error= NW_OK;
	tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + tcp_conn->tc_mss;
	tcp_conn->tc_snd_cthresh= TCP_MAX_WND_SIZE;
	tcp_conn->tc_snd_cinc= 0;
	tcp_conn->tc_snd_wnd= TCP_MAX_WND_SIZE;
	tcp_conn->tc_flags= TCF_INUSE;
#if DEBUG & 256
 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 
	tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }
#endif
}

⌨️ 快捷键说明

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