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

📄 tcp.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*tcp.c*/#include "inet.h"#include "buf.h"#include "clock.h"#include "type.h"#include "io.h"#include "ip.h"#include "sr.h"#include "assert.h"#include "tcp.h"#include "tcp_int.h"INIT_PANIC();PUBLIC tcp_port_t tcp_port_table[TCP_PORT_NR];PUBLIC tcp_fd_t tcp_fd_table[TCP_FD_NR];PUBLIC tcp_conn_t tcp_conn_table[TCP_CONN_NR];FORWARD void tcp_main ARGS(( tcp_port_t *port ));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 read_ip_packets ARGS(( tcp_port_t *port ));FORWARD int tcp_setconf 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 ));FORWARD int tcp_attache 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 void process_inc_fragm ARGS(( tcp_port_t *tcp_port,	acc_t *data ));FORWARD tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr, 	tcp_hdr_t *tcp_hdr ));FORWARD void close_mainuser ARGS(( tcp_conn_t *tcp_conn,	tcp_fd_t *tcp_fd ));FORWARD int conn_right4fd ARGS(( tcp_conn_t *tcp_conn, tcp_fd_t *tcp_fd ));FORWARD int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));FORWARD void tcp_buffree ARGS(( int priority, size_t reqsize ));FORWARD void tcp_notreach ARGS(( acc_t *pack ));FORWARD void tcp_setup_conn ARGS(( tcp_conn_t *tcp_conn ));PUBLIC void tcp_init(){	int i, result;	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);	assert (BUF_S >= TCP_MAX_HDR_SIZE);	tcp_port_table[0].tp_minor= TCP_DEV0;	tcp_port_table[0].tp_ipdev= IP0;	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;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 	tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif	}	bf_logon(tcp_buffree);	for (i=0, tcp_port= tcp_port_table; i<TCP_PORT_NR; i++,		tcp_port++)	{		tcp_port->tp_flags= TPF_EMPTY;		tcp_port->tp_state= TPS_EMPTY;		result= sr_add_minor (tcp_port->tp_minor,			tcp_port-tcp_port_table, tcp_open, tcp_close,			tcp_read, tcp_write, tcp_ioctl, tcp_cancel);		assert (result>=0);		tcp_main(tcp_port);	}}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;#if DEBUG & 256 { where(); printf("doing ip_open\n"); }#endif		tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev,			tcp_port-tcp_port_table, tcp_get_data,			tcp_put_data);		if (tcp_port->tp_ipfd < 0)		{			tcp_port->tp_state= TPS_ERROR;			printf("%s, %d: unable to open ip port\n",				__FILE__, __LINE__);			return;		}#if DEBUG & 256 { where(); printf("doing ip_ioctl(.., NWIOSIPOPT)\n"); }#endif		result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT);		if (result == NW_SUSPEND)			tcp_port->tp_flags |= TPF_SUSPEND;		if (result < 0)		{#if DEBUG { where(); printf("ip_ioctl(..,%lx)=%d\n", NWIOSIPOPT, result); }#endif			return;		}		if (tcp_port->tp_state != TPS_GETCONF)			return;		/* drops through */	case TPS_GETCONF:		tcp_port->tp_flags &= ~TPF_SUSPEND;#if DEBUG & 256 { where(); printf("doing ip_ioctl(.., NWIOGIPCONF)\n"); }#endif		result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF);		if (result == NW_SUSPEND)			tcp_port->tp_flags |= TPF_SUSPEND;		if (result < 0)		{#if DEBUG & 256 { where(); printf("ip_ioctl(..,%lx)=%d\n", NWIOGIPCONF, result); }#endif			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-tcp_port_table];		tcp_conn->tc_flags= TCF_INUSE;#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_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;#if DEBUG & 2 { where(); tcp_write_state(tcp_conn); }#endif		tcp_conn->tc_mainuser= 0;		tcp_conn->tc_readuser= 0;		tcp_conn->tc_writeuser= 0;		tcp_conn->tc_connuser= 0;#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_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_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_port= tcp_port;		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_tos= TCP_DEF_TOS;		tcp_conn->tc_ttl= IP_MAX_TTL;		tcp_conn->tc_rcv_wnd= TCP_MAX_WND_SIZE;		tcp_conn->tc_urg_wnd= TCP_DEF_URG_WND;		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_wnd= TCP_MAX_WND_SIZE;		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;#if DEBUG & 256 { where(); printf("restarting tcp_ioctl\n"); }#endif				tcp_ioctl(i, tcp_fd->tf_ioreq);			}		}		read_ip_packets(tcp_port);		return;	default:		ip_panic(( "unknown state" ));		break;	}}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 DEBUG & 256 { where(); printf("tcp_get_data: got reply: %d\n", result); }#endif			if (result<0)			{				if (result == EDSTNOTRCH)				{					tcp_notreach(tcp_port->tp_pack);				}				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_flags & TPF_MORE2WRITE)				{#if DEBUG & 256 { where(); printf("calling tcp_restart_write_port(&tcp_port_table[%d])\n",	tcp_port - tcp_port_table); }#endif					tcp_restart_write_port(						tcp_port);				}			}			else				tcp_port->tp_flags &= ~TPF_WRITE_IP;		}		else		{#if DEBUG & 256 { where(); printf("suplying data, count= %d, offset= %d, bufsize= %d\n",	count, offset, bf_bufsize(tcp_port->tp_pack)); }#endif			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 DEBUG & 256 { where(); printf("get GETCONF reply\n"); }#endif			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;			bf_afree(data);		}		break;	case TPS_MAIN:		assert(tcp_port->tp_flags & TPF_READ_IP);		if (!data)		{			result= (int)offset;			if (result<0)#if DEBUG { where(); printf("tcp_put_data got error %d (ignored)\n", result); }#elseip_panic(( "ip_read() failed" ));#endif			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 isn't a valid assertion but ip sends			  * only whole datagrams up */#if DEBUG & 256 { where(); printf("got data from ip\n"); }#endif			process_inc_fragm(tcp_port, data);		}		break;	default:		printf("tcp_put_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n",	fd, offset, data, tcp_port->tp_state);		break;	}	return NW_OK;}PUBLIC int tcp_open (port, srfd, get_userdata, put_userdata)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;{	int i;	tcp_fd_t *tcp_fd;	for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE);		i++);	if (i>=TCP_FD_NR)	{#if DEBUG { where(); printf("out of fds\n"); }#endif		return EOUTOFBUFS;	}	tcp_fd= &tcp_fd_table[i];	tcp_fd->tf_flags= TFF_INUSE;	tcp_fd->tf_flags |= TFF_PUSH_DATA;	/* XXX */	tcp_fd->tf_port= &tcp_port_table[port];	tcp_fd->tf_srfd= srfd;	tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_OPT;	tcp_fd->tf_tcpconf.nwtc_remaddr= 0;	tcp_fd->tf_tcpconf.nwtc_remport= 0;	tcp_fd->tf_get_userdata= get_userdata;	tcp_fd->tf_put_userdata= put_userdata;	tcp_fd->tf_conn= 0;	return i;}PUBLIC int tcp_ioctl (fd, req)int fd;int req;{	tcp_fd_t *tcp_fd;	tcp_port_t *tcp_port;	tcp_conn_t *tcp_conn;	nwio_tcpconf_t *tcp_conf;	acc_t *conf_acc;	int type;	int result;#if DEBUG & 256 { where(); printf("tcp_ioctl called\n"); }#endif	tcp_fd= &tcp_fd_table[fd];	type= req & IOCTYPE_MASK;assert (tcp_fd->tf_flags & TFF_INUSE);	tcp_port= tcp_fd->tf_port;	tcp_fd->tf_flags |= TFF_IOCTL_IP;	tcp_fd->tf_ioreq= req;	if (tcp_port->tp_state != TPS_MAIN)	{		tcp_fd->tf_flags |= TFF_IOC_INIT_SP;		return NW_SUSPEND;	}	switch (type)	{	case NWIOSTCPCONF & IOCTYPE_MASK:		if (req != NWIOSTCPCONF)		{#if DEBUG { where(); printf("0x%x: bad ioctl\n", req); }#endif			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		if (tcp_fd->tf_flags & TFF_CONNECTED)		{			tcp_fd->tf_flags &= ~TFF_IOCTL_IP;			reply_thr_get (tcp_fd, EISCONN, TRUE);			result= NW_OK;

⌨️ 快捷键说明

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