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

📄 ztcp_input.c

📁 uCOSII上实现的tcpip协议实现代码(gcc编译)
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "include/zeth.h"#include "include/zarp.h"#include "include/ztcp.h"#include "include/ztask.h"#include "include/zstats.h"/****used in tcp_process and tcp_input reduse paramer's number*****/static tcp_header_t *ptcpheader;static ip_header_t *pipheader;static tcp_seg_t	inseg;static void tcp_parseopt(tcp_pcb_t *ptcp, tcp_header_t *ptcpheader){	u8_t c;	u8_t *opts, opt;	u16_t mss;	opts = (u8_t *)ptcpheader + TCP_HEAD_LEN;	/* Parse the TCP MSS option, if present. */	if((TCPH_OFFSET(ptcpheader) & 0xf0) > 0x50)	{		for(c = 0; c < ((TCPH_OFFSET(ptcpheader) >> 4) - 5) << 2 ;)		{			opt = opts[c];			if(opt == 0x00)			{				/* End of options. */				break;			}			else if(opt == 0x01)			{				++c;				/* NOP option. */			}			else if(opt == 0x02 && opts[c + 1] == 0x04)			{				/* An MSS option with the right option length. */				mss = (opts[c + 2] << 8) | opts[c + 3];				ptcp->mss = mss > TCP_MSS? TCP_MSS: mss;				/* And we are done processing options. */				break;			}			else			{				if(opts[c + 1] == 0)				{					/* If the length field is zero, the options are malformed					   and we don't process them further. */					break;				}				/* All other options have a length field, so that we easily				   can skip past them. */				c += opts[c + 1];			}		}	}}static void tcp_process(znetif_t *pnetif, zbuffer_t *pbuffer, tcp_pcb_t *ptcp);static void tcp_receive(tcp_pcb_t *ptcp, zbuffer_t *pbuffer);void tcp_input(znetif_t *pnetif, zbuffer_t *pbuffer){	eth_header_t	*pethheader;	u16_t			offset;	s16_t			h_off;	tcp_pcb_t		*prev, *ptcp;	zsocket_t		*psocket;	/*setup information pointer*/	pethheader = (eth_header_t *)( (u8_t *)pbuffer->pdata);	pipheader = (ip_header_t *)( (u8_t *)pbuffer->pdata + ETH_HEAD_LEN);	offset =  IPH_HL(pipheader) * 4 + ETH_HEAD_LEN;	ptcpheader = (tcp_header_t *)((u8_t *)pbuffer->pdata + offset);	inseg.next = NULL;	inseg.len = IPH_LEN(pipheader) - (TCPH_OFFSET(ptcpheader) >> 2) - (IPH_HL(pipheader) << 2);	inseg._ori_pbuffer = pbuffer;	inseg.pbuffer = pbuffer;	inseg.pdata = (void *)((u8_t *)ptcpheader + (TCPH_OFFSET(ptcpheader) >> 2));	inseg.ptcpheader = ptcpheader;	if ( !((pipheader->dest_ipaddr == pnetif->ipaddr) ||				(ip_addr_isbroadcast(pipheader->dest_ipaddr,pnetif->netmask) &&				 ip_addr_maskcmp(pipheader->dest_ipaddr,pnetif->ipaddr,pnetif->netmask) )))	{		zbuffer_delete(pbuffer);		return ;	}	/*we check checksum*/	h_off = (s16_t)(0 -offset);	if ( zbuffer_head_adjust(pbuffer, h_off) != 0)		return;	if ( inet_chksum_pseudo(pbuffer,&pipheader->src_ipaddr,				&pipheader->dest_ipaddr,IP_PROTO_TCP,pbuffer->tot_len) != 0)	{		zbuffer_delete(pbuffer);		return;	}	h_off *= -1;	if ( zbuffer_head_adjust(pbuffer, h_off) != 0)		return;	/*add to arp table*/	add_arp_item( &pipheader->src_ipaddr,&pethheader->src_hwaddr);	/* Demultiplex an incoming segment. First, we check if it is destined	   for an active connection. */  	prev = NULL;  	for(ptcp = ptcp_active_chain; ptcp != NULL; ptcp = ptcp->next) 	{		/*		   ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);		   ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);		   ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);		   */		psocket = ptcp->_psocket;		if ( psocket->_lport == ptcpheader->dest &&				psocket->_rport == ptcpheader->src &&				psocket->_lipaddr == pipheader->dest_ipaddr &&				psocket->_ripaddr == pipheader->src_ipaddr)		{			/* Move this PCB to the front of the list so that subsequent			   lookups will be faster (we exploit locality in TCP segment			   arrivals). */			/*			   ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);			   */			if(prev != NULL) 			{				prev->next = ptcp->next;				ptcp->next = ptcp_active_chain;				ptcp_active_chain = ptcp; 			}			/*			   ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);			   */			break;		}		prev = ptcp;	}	/* If it did not go to an active connection, we check the connections	   in the TIME-WAIT state. */	if(ptcp == NULL) 	{		for(ptcp = ptcp_tw_chain; ptcp != NULL; ptcp = ptcp->next) 		{			/*ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);*/			psocket = ptcp->_psocket;			if ( psocket->_lport == ptcpheader->dest &&					psocket->_rport == ptcpheader->src &&					psocket->_lipaddr == pipheader->dest_ipaddr &&					psocket->_ripaddr == pipheader->src_ipaddr)			{				/* We don't really care enough to move this PCB to the front				   of the list since we are not very likely to receive that				   many segments for connections in TIME-WAIT. */				break;			}		}  		/* Finally, if we still did not get a match, we check all PCBs that		   are LISTENing for incomming connections. */		prev = NULL;  		if(ptcp == NULL) 		{			for(ptcp = ptcp_listen_chain; ptcp != NULL; ptcp = ptcp->next) 			{				/*ASSERT("tcp_input: LISTEN pcb->state == LISTEN", pcb->state == LISTEN);*/				psocket = ptcp->_psocket;				if ( psocket->_lport == ptcpheader->dest &&						psocket->_lipaddr == pipheader->dest_ipaddr)				{	  					/* Move this PCB to the front of the list so that subsequent					   lookups will be faster (we exploit locality in TCP segment					   arrivals). */					if(prev != NULL) {						prev->next = ptcp->next;						ptcp->next = ptcp_listen_chain;						ptcp_listen_chain = ptcp; 					}					break;				}				prev = ptcp;			}		}	}	if ( ptcp == NULL)	{		tcp_reset(pnetif, pipheader, ptcpheader);		zbuffer_delete(pbuffer);		return;	}	tcp_process(pnetif, pbuffer, ptcp);	zbuffer_delete(pbuffer);		if (ptcp->flags & TF_CLOSED) 	{					if(ptcp->state == TIME_WAIT) 			{				tcp_pcb_remove(&ptcp_tw_chain, ptcp);			}			else 			{				tcp_pcb_remove(&ptcp_active_chain, ptcp); 			}			sys_signal_sem(ptcp->user_sem);	/*just as a EVENT*/			tcp_pcb_delete(ptcp);			return;	}	if (ptcp->state != LISTEN && ptcp->state != CLOSED)	{		tcp_output(ptcp);	}	if (ptcp->flags & TF_GOT_FIN)	{		tcp_pcb_close(ptcp);		}}void tcp_process(znetif_t *pnetif, zbuffer_t *pbuffer, tcp_pcb_t *ptcp){	tcp_pcb_t *nptcp, *tcp_tmp_pcb;	u32_t seqno, ackno;	u8_t flags;	u32_t optdata;	tcp_seg_t *rseg;	u8_t acceptable = 0;	s8_t nsocket, err;	flags = TCPH_FLAGS(ptcpheader);	seqno = ptcpheader->seqno;	ackno = ptcpheader->ackno;	/* Process incoming RST segments. */	if(flags & TCP_RST) 	{		/* First, determine if the reset is acceptable. */		if(ptcp->state != LISTEN) 		{			if(ptcp->state == SYN_SENT) 			{				if(ackno == ptcp->snd_nxt) 				{					acceptable = 1;				}			} 			else 			{				if(TCP_SEQ_GEQ(seqno, ptcp->rcv_nxt) &&						TCP_SEQ_LEQ(seqno, ptcp->rcv_nxt + ptcp->rcv_wnd)) 				{					acceptable = 1;				}			}		}		if(acceptable) 		{			/*			   DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));			   ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);			   */			ptcp->flags |= TF_RESET;			ptcp->flags &= ~TF_ACK_DELAY;			if(ptcp->state == TIME_WAIT) 			{				tcp_pcb_remove(&ptcp_tw_chain, ptcp);			}			else 			{				tcp_pcb_remove(&ptcp_active_chain, ptcp); 			}			sys_signal_sem(ptcp->user_sem);	/*just as a EVENT*/			tcp_pcb_delete(ptcp);		} 		else 		{			/*			   DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",			   seqno, pcb->rcv_nxt));			   DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",			   seqno, pcb->rcv_nxt));			   */		}		return;						/*XXX return point*/	}/*end of process reset TCP falgs*/	/*Ok,there is no RESET flags set in incoming tcp packet for a PCB*/	/* Update the PCB timer unless we are in the LISTEN state, in	   which case we don't even have memory allocated for the timer,	   much less use it. */	ptcp->tmr = tcp_ticks;	/*first we update the PCB's timer*/	/* Do different things depending on the TCP state. */	switch(ptcp->state) 	{		case CLOSED:			/* Do nothing in the CLOSED state. In fact, this case should never occur			   since PCBs in the CLOSED state are never found in the list of			   active PCBs. */			break;		case LISTEN:			/* In the LISTEN state, we check for incoming SYN segments,			   creates a new PCB, and responds with a SYN|ACK. */						if(flags & TCP_ACK) 			{				/* For incoming segments with the ACK flag set, respond with a				   RST. */				/*DEBUGF(TCP_RST_DEBUG, ("tcp_process: ACK in LISTEN, sending reset\n"));*/				tcp_reset(pnetif, pipheader, ptcpheader);				return;						/*XXX return point*/			}			else if(flags & TCP_SYN)			{				if ( ptcp->accept != 0)	/*if there is a connected remote client*/				{					tcp_reset(pnetif, pipheader, ptcpheader);					return;					/*XXX return point*/				}				nsocket = zsocket(data_stream);								if ( nsocket < 0)			/*because there are too many sockets in system*/				{					tcp_reset(pnetif, pipheader, ptcpheader);					return;					/*XXX return point*/				}							zbind(nsocket, &ptcp->_psocket->_lipaddr, &ptcp->_psocket->_lport);				nptcp = tcp_pcb_query(nsocket);				/*identify this is a listen's client,				 * when ESTABLISH send a EVENT*/								nptcp->server = ptcp;				/* Set up the new PCB. */				nptcp->_psocket->_ripaddr = pipheader->src_ipaddr;				nptcp->_psocket->_rport = ptcpheader->src;				nptcp->state = SYN_RCVD;				nptcp->rcv_nxt = seqno + 1;				nptcp->snd_wnd = ptcpheader->wnd;				nptcp->ssthresh = nptcp->snd_wnd;				nptcp->snd_wl1 = ptcpheader->seqno;				TCP_REG(&ptcp_active_chain, nptcp);				/* Parse any options in the SYN. */				tcp_parseopt(nptcp, ptcpheader);				/* Build an MSS option. */				optdata = (((u32_t)2 << 24) | ((u32_t)4 << 16) |						(((u32_t)nptcp->mss / 256) << 8) |						(nptcp->mss & 255));				/* Send a SYN|ACK together with the MSS option. */				err = tcp_insert_queue(nptcp, NULL, 0,						TCP_SYN | TCP_ACK,						(u8_t *)&optdata, 4);								if ( err != ERR_OK)				{					tcp_pcb_remove(&ptcp_active_chain, nptcp);					tcp_pcb_delete(nptcp);					tcp_reset(pnetif, pipheader, ptcpheader);					return;					/*XXX return point*/				}								tcp_output(nptcp);			}			else			{				tcp_reset(pnetif, pipheader, ptcpheader);			}			break;		case SYN_SENT:			/*DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,			  pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));*/					if(flags & TCP_ACK &&					flags & TCP_SYN &&					ackno == (ptcp->unacked->ptcpheader->seqno) + 1)			{				ptcp->rcv_nxt = seqno + 1;				ptcp->lastack = ackno;				ptcp->rcv_wnd = ptcpheader->wnd;				ptcp->state = ESTABLISHED;				sys_signal_sem(ptcp->user_sem);		/*as a EVENT */				ptcp->cwnd = ptcp->mss;				--ptcp->snd_queuelen;				/*				   DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %d\n", pcb->snd_queuelen));*/				rseg = ptcp->unacked;				ptcp->unacked = rseg->next;				rseg->next = NULL;				tcp_seg_delete(rseg);				/* Parse any options in the SYNACK. */				tcp_parseopt(ptcp, ptcpheader);				tcp_ack(ptcp);	/*ack later*/			}			break;		case SYN_RCVD:					if(flags & TCP_ACK &&					!(flags & TCP_RST)) 			{				if(TCP_SEQ_LT(ptcp->lastack, ackno) &&						TCP_SEQ_LEQ(ackno, ptcp->snd_nxt)) 				{					ptcp->state = ESTABLISHED;					/*					   DEBUGF(DEMO_DEBUG, ("TCP connection established %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));					   */					/* Call the accept function. */					if ( ptcp->server != NULL)					{						ptcp->server->accept = ptcp->_psocket->_id;						sys_signal_sem( ptcp->server->user_sem);					}					else	/*FIXME we don't operate SYN_SENT t0 SYN_RECV*/					{						tcp_abort(ptcp, pbuffer);						return;					}					/* If there was any data contained within this ACK,					   we'd better pass it on to the application as well. */					tcp_receive(ptcp, pbuffer);					ptcp->cwnd = ptcp->mss;				}				}			break;		case CLOSE_WAIT:		case ESTABLISHED:			tcp_receive(ptcp, pbuffer);	  			if(flags & TCP_FIN) 			{				tcp_ack_now(ptcp);				ptcp->state = CLOSE_WAIT;			}			break;

⌨️ 快捷键说明

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