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

📄 tcp.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*tcp.cCopyright 1995 Philip Homburg*/#include "inet.h"#include "buf.h"#include "clock.h"#include "event.h"#include "type.h"#include "io.h"#include "ip.h"#include "sr.h"#include "assert.h"#include "rand256.h"#include "tcp.h"#include "tcp_int.h"THIS_FILE#define NOT_IMPLEMENTED 0PUBLIC tcp_port_t *tcp_port_table;PUBLIC tcp_fd_t tcp_fd_table[TCP_FD_NR];PUBLIC tcp_conn_t tcp_conn_table[TCP_CONN_NR];PUBLIC sr_cancel_t tcp_cancel_f;FORWARD void tcp_main ARGS(( tcp_port_t *port ));FORWARD int tcp_select ARGS(( int fd, unsigned operations ));FORWARD acc_t *tcp_get_data ARGS(( int fd, size_t offset,	size_t count, int for_ioctl ));FORWARD int tcp_put_data ARGS(( int fd, size_t offset,	acc_t *data, int for_ioctl ));FORWARD void tcp_put_pkt ARGS(( int fd, acc_t *data, size_t datalen ));FORWARD void read_ip_packets ARGS(( tcp_port_t *port ));FORWARD int tcp_setconf ARGS(( tcp_fd_t *tcp_fd ));FORWARD int tcp_setopt ARGS(( tcp_fd_t *tcp_fd ));FORWARD int tcp_connect ARGS(( tcp_fd_t *tcp_fd ));FORWARD int tcp_listen ARGS(( tcp_fd_t *tcp_fd, int do_listenq ));FORWARD int tcp_acceptto ARGS(( tcp_fd_t *tcp_fd ));FORWARD tcpport_t find_unused_port ARGS(( int fd ));FORWARD int is_unused_port ARGS(( Tcpport_t port ));FORWARD int reply_thr_put ARGS(( tcp_fd_t *tcp_fd, int reply,	int for_ioctl ));FORWARD void reply_thr_get ARGS(( tcp_fd_t *tcp_fd, int reply,	int for_ioctl ));FORWARD tcp_conn_t *find_conn_entry ARGS(( Tcpport_t locport,	ipaddr_t locaddr, Tcpport_t remport, ipaddr_t readaddr ));FORWARD tcp_conn_t *find_empty_conn ARGS(( void ));FORWARD tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr, 	tcp_hdr_t *tcp_hdr ));FORWARD tcp_conn_t *new_conn_for_queue ARGS(( tcp_fd_t *tcp_fd ));FORWARD int maybe_listen ARGS(( ipaddr_t locaddr, Tcpport_t locport,				ipaddr_t remaddr, Tcpport_t remport ));FORWARD int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));FORWARD void tcp_buffree ARGS(( int priority ));#ifdef BUF_CONSISTENCY_CHECKFORWARD void tcp_bufcheck ARGS(( void ));#endifFORWARD void tcp_setup_conn ARGS(( tcp_port_t *tcp_port,					tcp_conn_t *tcp_conn ));FORWARD u32_t tcp_rand32 ARGS(( void ));PUBLIC void tcp_prep(){	tcp_port_table= alloc(tcp_conf_nr * sizeof(tcp_port_table[0]));}PUBLIC void tcp_init(){	int i, j, k, ifno;	tcp_fd_t *tcp_fd;	tcp_port_t *tcp_port;	tcp_conn_t *tcp_conn;	assert (BUF_S >= sizeof(struct nwio_ipopt));	assert (BUF_S >= sizeof(struct nwio_ipconf));	assert (BUF_S >= sizeof(struct nwio_tcpconf));	assert (BUF_S >= IP_MAX_HDR_SIZE + TCP_MAX_HDR_SIZE);	for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++)	{		tcp_fd->tf_flags= TFF_EMPTY;	}	for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++,		tcp_fd++)	{		tcp_conn->tc_flags= TCF_EMPTY;		tcp_conn->tc_busy= 0;	}#ifndef BUF_CONSISTENCY_CHECK	bf_logon(tcp_buffree);#else	bf_logon(tcp_buffree, tcp_bufcheck);#endif	for (i=0, tcp_port= tcp_port_table; i<tcp_conf_nr; i++, tcp_port++)	{		tcp_port->tp_ipdev= tcp_conf[i].tc_port;		tcp_port->tp_flags= TPF_EMPTY;		tcp_port->tp_state= TPS_EMPTY;		tcp_port->tp_snd_head= NULL;		tcp_port->tp_snd_tail= NULL;		ev_init(&tcp_port->tp_snd_event);		for (j= 0; j<TCP_CONN_HASH_NR; j++)		{			for (k= 0; k<4; k++)			{				tcp_port->tp_conn_hash[j][k]=					&tcp_conn_table[0];			}		}		ifno= ip_conf[tcp_port->tp_ipdev].ic_ifno;		sr_add_minor(if2minor(ifno, TCP_DEV_OFF),			i, tcp_open, tcp_close, tcp_read,			tcp_write, tcp_ioctl, tcp_cancel, tcp_select);		tcp_main(tcp_port);	}	tcp_cancel_f= tcp_cancel;}PRIVATE void tcp_main(tcp_port)tcp_port_t *tcp_port;{	int result, i;	tcp_conn_t *tcp_conn;	tcp_fd_t *tcp_fd;	switch (tcp_port->tp_state)	{	case TPS_EMPTY:		tcp_port->tp_state= TPS_SETPROTO;		tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev,			tcp_port->tp_ipdev, tcp_get_data,			tcp_put_data, tcp_put_pkt, 0 /* no select_res */);		if (tcp_port->tp_ipfd < 0)		{			tcp_port->tp_state= TPS_ERROR;			DBLOCK(1, printf("%s, %d: unable to open ip port\n",				__FILE__, __LINE__));			return;		}		result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT);		if (result == NW_SUSPEND)			tcp_port->tp_flags |= TPF_SUSPEND;		if (result < 0)		{			return;		}		if (tcp_port->tp_state != TPS_GETCONF)			return;		/* drops through */	case TPS_GETCONF:		tcp_port->tp_flags &= ~TPF_SUSPEND;		result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF);		if (result == NW_SUSPEND)			tcp_port->tp_flags |= TPF_SUSPEND;		if (result < 0)		{			return;		}		if (tcp_port->tp_state != TPS_MAIN)			return;		/* drops through */	case TPS_MAIN:		tcp_port->tp_flags &= ~TPF_SUSPEND;		tcp_port->tp_pack= 0;		tcp_conn= &tcp_conn_table[tcp_port->tp_ipdev];		tcp_conn->tc_flags= TCF_INUSE;		assert(!tcp_conn->tc_busy);		tcp_conn->tc_locport= 0;		tcp_conn->tc_locaddr= tcp_port->tp_ipaddr;		tcp_conn->tc_remport= 0;		tcp_conn->tc_remaddr= 0;		tcp_conn->tc_state= TCS_CLOSED;		tcp_conn->tc_fd= 0;		tcp_conn->tc_connInprogress= 0;		tcp_conn->tc_orglisten= FALSE;		tcp_conn->tc_senddis= 0;		tcp_conn->tc_ISS= 0;		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;		tcp_conn->tc_SND_UP= tcp_conn->tc_ISS;		tcp_conn->tc_IRS= 0;		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_port= tcp_port;		tcp_conn->tc_rcvd_data= NULL;		tcp_conn->tc_adv_data= NULL;		tcp_conn->tc_send_data= 0;		tcp_conn->tc_remipopt= NULL;		tcp_conn->tc_tcpopt= NULL;		tcp_conn->tc_frag2send= 0;		tcp_conn->tc_tos= TCP_DEF_TOS;		tcp_conn->tc_ttl= IP_MAX_TTL;		tcp_conn->tc_rcv_wnd= TCP_MAX_RCV_WND_SIZE;		tcp_conn->tc_rt_dead= TCP_DEF_RT_DEAD;		tcp_conn->tc_stt= 0;		tcp_conn->tc_0wnd_to= 0;		tcp_conn->tc_artt= TCP_DEF_RTT*TCP_RTT_SCALE;		tcp_conn->tc_drtt= 0;		tcp_conn->tc_rtt= TCP_DEF_RTT;		tcp_conn->tc_max_mtu= tcp_port->tp_mtu;		tcp_conn->tc_mtu= tcp_conn->tc_max_mtu;		tcp_conn->tc_mtutim= 0;		tcp_conn->tc_error= NW_OK;		tcp_conn->tc_snd_wnd= TCP_MAX_SND_WND_SIZE;		tcp_conn->tc_snd_cinc=			(long)TCP_DEF_MSS*TCP_DEF_MSS/TCP_MAX_SND_WND_SIZE+1;		tcp_conn->tc_rt_time= 0;		tcp_conn->tc_rt_seq= 0;		tcp_conn->tc_rt_threshold= tcp_conn->tc_ISS;		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_port != tcp_port)				continue;			if (tcp_fd->tf_flags & TFF_IOC_INIT_SP)			{				tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;				tcp_ioctl(i, tcp_fd->tf_ioreq);			}		}		read_ip_packets(tcp_port);		return;	default:		ip_panic(( "unknown state" ));		break;	}}PRIVATE int tcp_select(fd, operations)int fd;unsigned operations;{	int i;	unsigned resops;	tcp_fd_t *tcp_fd;	tcp_conn_t *tcp_conn;	tcp_fd= &tcp_fd_table[fd];	assert (tcp_fd->tf_flags & TFF_INUSE);	resops= 0;	if (tcp_fd->tf_flags & TFF_LISTENQ)	{		/* Special case for LISTENQ */		if (operations & SR_SELECT_READ)		{			for (i= 0; i<TFL_LISTEN_MAX; i++)			{				if (tcp_fd->tf_listenq[i] == NULL)					continue;				if (tcp_fd->tf_listenq[i]->tc_connInprogress					== 0)				{					break;				}			}			if (i >= TFL_LISTEN_MAX)				tcp_fd->tf_flags |= TFF_SEL_READ;			else				resops |= SR_SELECT_READ;		}		if (operations & SR_SELECT_WRITE)			return ENOTCONN;	/* Is this right? */		return resops;	}	if (tcp_fd->tf_flags & TFF_CONNECTING)	{		/* Special case for CONNECTING */		if (operations & SR_SELECT_WRITE)			tcp_fd->tf_flags |= TFF_SEL_WRITE;		return 0;	}	if (operations & SR_SELECT_READ)	{		if (!(tcp_fd->tf_flags & TFF_CONNECTEDx))			return ENOTCONN;	/* Is this right? */		tcp_conn= tcp_fd->tf_conn;		if (tcp_conn->tc_state == TCS_CLOSED || tcp_sel_read(tcp_conn))			resops |= SR_SELECT_READ;		else if (!(operations & SR_SELECT_POLL))			tcp_fd->tf_flags |= TFF_SEL_READ;	}	if (operations & SR_SELECT_WRITE)	{		if (!(tcp_fd->tf_flags & TFF_CONNECTEDx))			return ENOTCONN;	/* Is this right? */		tcp_conn= tcp_fd->tf_conn;		if (tcp_conn->tc_state == TCS_CLOSED ||			tcp_conn->tc_flags & TCF_FIN_SENT ||			tcp_sel_write(tcp_conn))		{			resops |= SR_SELECT_WRITE;		}		else if (!(operations & SR_SELECT_POLL))			tcp_fd->tf_flags |= TFF_SEL_WRITE;	}	if (operations & SR_SELECT_EXCEPTION)	{		printf("tcp_select: not implemented for exceptions\n");	}	return resops;}PRIVATE acc_t *tcp_get_data (port, offset, count, for_ioctl)int port;size_t offset;size_t count;int for_ioctl;{	tcp_port_t *tcp_port;	int result;	tcp_port= &tcp_port_table[port];	switch (tcp_port->tp_state)	{	case TPS_SETPROTO:		if (!count)		{			result= (int)offset;			if (result<0)			{				tcp_port->tp_state= TPS_ERROR;				break;			}			tcp_port->tp_state= TPS_GETCONF;			if (tcp_port->tp_flags & TPF_SUSPEND)				tcp_main(tcp_port);			return NW_OK;		}assert (!offset);assert (count == sizeof(struct nwio_ipopt));		{			struct nwio_ipopt *ipopt;			acc_t *acc;			acc= bf_memreq(sizeof(*ipopt));			ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);			ipopt->nwio_flags= NWIO_COPY |				NWIO_EN_LOC | NWIO_DI_BROAD |				NWIO_REMANY | NWIO_PROTOSPEC |				NWIO_HDR_O_ANY | NWIO_RWDATALL;			ipopt->nwio_proto= IPPROTO_TCP;			return acc;		}	case TPS_MAIN:		assert(tcp_port->tp_flags & TPF_WRITE_IP);		if (!count)		{			result= (int)offset;			if (result<0)			{				if (result == EDSTNOTRCH)				{					if (tcp_port->tp_snd_head)					{						tcp_notreach(tcp_port->							tp_snd_head);					}				}				else				{					ip_warning((					"ip_write failed with error: %d\n", 								result ));				}			}			assert (tcp_port->tp_pack);			bf_afree (tcp_port->tp_pack);			tcp_port->tp_pack= 0;			if (tcp_port->tp_flags & TPF_WRITE_SP)			{				tcp_port->tp_flags &= ~(TPF_WRITE_SP|					TPF_WRITE_IP);				if (tcp_port->tp_snd_head)					tcp_port_write(tcp_port);			}			else				tcp_port->tp_flags &= ~TPF_WRITE_IP;		}		else		{			return bf_cut (tcp_port->tp_pack, offset,				count);		}		break;	default:		printf("tcp_get_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n",			port, offset, count, tcp_port->tp_state);		break;	}	return NW_OK;}PRIVATE int tcp_put_data (fd, offset, data, for_ioctl)int fd;size_t offset;acc_t *data;int for_ioctl;{	tcp_port_t *tcp_port;	int result;	tcp_port= &tcp_port_table[fd];	switch (tcp_port->tp_state)	{	case TPS_GETCONF:		if (!data)		{			result= (int)offset;			if (result<0)			{				tcp_port->tp_state= TPS_ERROR;				return NW_OK;			}			tcp_port->tp_state= TPS_MAIN;			if (tcp_port->tp_flags & TPF_SUSPEND)				tcp_main(tcp_port);		}		else		{			struct nwio_ipconf *ipconf;			data= bf_packIffLess(data, sizeof(*ipconf));			ipconf= (struct nwio_ipconf *)ptr2acc_data(data);assert (ipconf->nwic_flags & NWIC_IPADDR_SET);			tcp_port->tp_ipaddr= ipconf->nwic_ipaddr;			tcp_port->tp_subnetmask= ipconf->nwic_netmask;			tcp_port->tp_mtu= ipconf->nwic_mtu;			bf_afree(data);		}		break;	case TPS_MAIN:		assert(tcp_port->tp_flags & TPF_READ_IP);		if (!data)		{			result= (int)offset;			if (result<0)				ip_panic(( "ip_read() failed" ));			if (tcp_port->tp_flags & TPF_READ_SP)			{				tcp_port->tp_flags &= ~(TPF_READ_SP|					TPF_READ_IP);				read_ip_packets(tcp_port);			}			else				tcp_port->tp_flags &= ~TPF_READ_IP;		}		else		{			assert(!offset);				/* this is an invalid assertion but ip sends			  * only whole datagrams up */			tcp_put_pkt(fd, data, bf_bufsize(data));		}		break;	default:		printf(		"tcp_put_data(%d, 0x%x, %p) called but tp_state= 0x%x\n",			fd, offset, data, tcp_port->tp_state);		break;	}	return NW_OK;}/*tcp_put_pkt*/PRIVATE void tcp_put_pkt(fd, data, datalen)int fd;acc_t *data;size_t datalen;{	tcp_port_t *tcp_port;	tcp_conn_t *tcp_conn, **conn_p;	ip_hdr_t *ip_hdr;	tcp_hdr_t *tcp_hdr;	acc_t *ip_pack, *tcp_pack;	size_t ip_datalen, tcp_datalen, ip_hdr_len, tcp_hdr_len;	u16_t sum, mtu;	u32_t bits;	int i, hash;	ipaddr_t srcaddr, dstaddr, ipaddr, mask;	tcpport_t srcport, dstport;	tcp_port= &tcp_port_table[fd];	/* Extract the IP header. */	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	ip_datalen= datalen - ip_hdr_len;	if (ip_datalen == 0)	{		if (ip_hdr->ih_proto == 0)		{			/* IP layer reports new IP address */			ipaddr= ip_hdr->ih_src;			mask= ip_hdr->ih_dst;			mtu= ntohs(ip_hdr->ih_length);			tcp_port->tp_ipaddr= ipaddr;			tcp_port->tp_subnetmask= mask;			tcp_port->tp_mtu= mtu;			DBLOCK(1, printf("tcp_put_pkt: using address ");				writeIpAddr(ipaddr);				printf(", netmask ");				writeIpAddr(mask);				printf(", mtu %u\n", mtu));			for (i= 0, tcp_conn= tcp_conn_table+i;

⌨️ 快捷键说明

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