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

📄 tcp.c

📁 opentcp_mcf5282原代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				if( ReceivedTCPPacket.ackno != soc->send_next )
				{
					DEBUGOUT("ACK received but wrong Ack\n\r");
					return(-1);
				}

				DEBUGOUT("Last ACK received, next LISTENING or CLOSED\r\n");

				/* We have no unacked data	*/

				soc->send_unacked = soc->send_next;

				if(soc->type & TCP_TYPE_SERVER)
					tcp_newstate(soc, TCP_STATE_LISTENING);
				else
					tcp_newstate(soc, TCP_STATE_CLOSED);

				return(0);

			}

			/* Is it repeated FIN?	*/

			if( ReceivedTCPPacket.hlen_flags & TCP_FLAG_FIN	)
			{

				DEBUGOUT("Repeated FIN, repeat ACK\n\r");

				/* ACK FIN and all data	*/

				soc->receive_next = ReceivedTCPPacket.seqno;
				soc->receive_next++;
				soc->receive_next += dlen;

				soc->myflags = TCP_FLAG_FIN | TCP_FLAG_ACK;
				tcp_sendcontrol(sochandle);

				return(0);

			}

			tcp_sendreset(&ReceivedTCPPacket, frame->sip);

			return(-1);

			break;

		case TCP_STATE_TIMED_WAIT:

			DEBUGOUT("TIMED_WAIT State...\r\n");

			/* Check for RESET	*/

			if(ReceivedTCPPacket.hlen_flags & TCP_FLAG_RESET)
			{
				DEBUGOUT("ERROR:Reset received\r\n");

				/* Inform application	*/

				soc->event_listener(sochandle, TCP_EVENT_ABORT, soc->rem_ip, soc->remport);

				if(soc->type & TCP_TYPE_SERVER)
					tcp_newstate(soc, TCP_STATE_LISTENING);
				else
					tcp_newstate(soc, TCP_STATE_CLOSED);

				return(-1);
			}

			/* Is it repeated FIN?	*/

			if( ReceivedTCPPacket.hlen_flags & TCP_FLAG_FIN	)
			{

				DEBUGOUT("Repeated FIN, repeat ACK\n\r");

				/* ACK FIN and all data	*/

				soc->receive_next = ReceivedTCPPacket.seqno;
				soc->receive_next++;
				soc->receive_next += dlen;

				soc->myflags = TCP_FLAG_ACK;
				tcp_sendcontrol(sochandle);

				return(0);

			}

			tcp_sendreset(&ReceivedTCPPacket, frame->sip);

			return(-1);


			break;


		default:

			DEBUGOUT("ERROR:TCP State machine in unknown state!!\r\n");

			tcp_sendreset(&ReceivedTCPPacket, frame->sip);

			RESET_SYSTEM();

	}

	DEBUGOUT("Should not be there!\r\n");

	return(-1);

}

/********************************************************************************
Function:		ProcessTCPOut

Parameters:		INT8 sockethandle - handle to processed socket
				UINT8* buf - data buffer
				UINT16 blen - buffer length in bytes
				UINT16 dlen - legth of data in bytes

Return val:		INT16 - (-1) Not OK
						>0 Packet OK


Date:			16.7.2002

Desc:			Calculate checksum for TCP packet and send it to IP.
				Buffer must contain 20 bytes free on start of it for TCP
				header assembly.
*********************************************************************************/

INT16 ProcessTCPOut (INT8 sockethandle, UINT8* buf, UINT16 blen, UINT16 dlen)
{
	struct tcb* soc;
	UINT16 cs;
	UINT8 cs_cnt;
	UINT8* buf_start;

	DEBUGOUT("Entering to send TCP packet\r\n");

	if( sockethandle < 0 )
	{
		DEBUGOUT("ERROR:Socket Handle not valid (<0)\r\n");
		return(-1);
	}

	if( sockethandle > NO_OF_TCPSOCKETS )
	{
		DEBUGOUT("ERROR:Socket Handle not valid (>NO_OF_TCPSOCKETS)\r\n");
		return(-1);
	}

	if( (dlen + MIN_TCP_HLEN) > blen )
	{
		DEBUGOUT("ERROR:Transmit buffer too small for TCP header\r\n");
		return(-1);
	}

	soc = &TCPSocket[sockethandle];				/* Get socket	*/

	buf_start = buf;

	if( (dlen + MIN_TCP_HLEN) > soc->send_mtu )
	{
		DEBUGOUT("ERROR:Send MTU exceeded\r\n");
		return(-1);
	}

	/* Assemble TCP header to buffer	*/

	*buf++ = (UINT8)(soc->locport >> 8);
	*buf++ = (UINT8)soc->locport;
	*buf++ = (UINT8)(soc->remport >> 8);
	*buf++ = (UINT8)soc->remport;
	*buf++ = (UINT8)(soc->send_unacked >>24);
	*buf++ = (UINT8)(soc->send_unacked >>16);
	*buf++ = (UINT8)(soc->send_unacked >>8);
	*buf++ = (UINT8)(soc->send_unacked);
	*buf++ = (UINT8)(soc->receive_next >>24);
	*buf++ = (UINT8)(soc->receive_next >>16);
	*buf++ = (UINT8)(soc->receive_next >>8);
	*buf++ = (UINT8)(soc->receive_next);
	*buf =	MIN_TCP_HLEN >> 2;
	*buf <<= 4;
	buf++;
	*buf++ = soc->myflags;
	*buf++ = (UINT8)((TCP_DEF_MTU) >> 8);
	*buf++ = (UINT8)TCP_DEF_MTU;
	*buf++ = 0;								/* Checksum	*/
	*buf++ = 0;
	*buf++ = 0;								/* Urgent	*/
	*buf++ = 0;


	/* Calculate checksum	*/

	cs = 0;
	cs_cnt = 0;

	/* Do it firstly to IP pseudo header	*/

	cs = IpCheckSum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)localmachine.localip, cs_cnt++);

	cs = IpCheckSum(cs, (UINT8)(soc->rem_ip >> 24), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(soc->rem_ip >> 16), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(soc->rem_ip >> 8), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)soc->rem_ip, cs_cnt++);

	cs = IpCheckSum(cs, 0, cs_cnt++);

	cs = IpCheckSum(cs, (UINT8)IP_TCP, cs_cnt++);

	cs = IpCheckSum(cs, (UINT8)((dlen + MIN_TCP_HLEN) >> 8), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(dlen + MIN_TCP_HLEN), cs_cnt++);

	/* Go to TCP header + data	*/

	buf = buf_start;

	cs = IpCheckSumBuf(cs, buf, dlen + MIN_TCP_HLEN);

	cs = ~ cs;

#if 0
	/* Is the padding required?	*/

	if(dlen & 0x01)
	{
		DEBUGOUT("Padding required\r\n");
		*buf = 0;
		dlen++;
	}
#endif

	/* Save checksum in correct place	*/

	buf = buf_start + 16;
	*buf++ = (UINT8)(cs >> 8);
	*buf = (UINT8)cs;

	/* Send it to IP	*/

	DEBUGOUT("Sending TCP...\r\n");

	ProcessIPOut(soc->rem_ip, IP_TCP, soc->tos, 100, buf_start, dlen + MIN_TCP_HLEN);

	DEBUGOUT("TCP packet sent\r\n");

	return(0);


}

/********************************************************************************
Function:		tcp_sendcontrol

Parameters:		INT8 sochandle - handle to socket


Return val:		void

Date:			17.7.2002

Desc:			Send a control packet with predefined flags
*********************************************************************************/

void tcp_sendcontrol (INT8 sockethandle)
{
	//struct tcb* soc;


	DEBUGOUT("Entering to send TCP control packet\r\n");



	if( sockethandle < 0 )
	{
		DEBUGOUT("ERROR:Socket Handle not valid (<0)\r\n");
		return;
	}

	if( sockethandle > NO_OF_TCPSOCKETS )
	{
		DEBUGOUT("ERROR:Socket Handle not valid (>NO_OF_TCPSOCKETS)\r\n");
		return;
	}

	//soc = &TCPSocket[sockethandle];				/* Get socket	*/

	ProcessTCPOut(sockethandle, &tcp_tempbuf[0], MIN_TCP_HLEN + 1, 0);

	return;


}


/********************************************************************************
Function:		tcp_sendreset

Parameters:		struct TCPFrame* frame - received TCP packet
				UINT32 remip - remote IP address of packet


Return val:		void

Date:			20.8.2002

Desc:			Uses socket NO_OF_TCPSOCKETS to send a RESET packet to peer.
				This function is used when we are establishing connection but
				we receive something else than SYN or SYN+ACK when it's
				possible that the peer has still old connection on which
				needs to be resetted without canceling the connection establishment
				on process.
*********************************************************************************/

void tcp_sendreset (struct TCPFrame *frame, UINT32 remip)
{
	struct tcb* soc;

	soc = &TCPSocket[NO_OF_TCPSOCKETS];				/* Get socket	*/


	/* Is this itself a reset packet?	*/

	if( frame->hlen_flags & TCP_FLAG_RESET )
		return;

	/* Set temporary tcb variables	*/

	soc->rem_ip = remip;
	soc->remport = frame->sport;
	soc->locport = frame->dport;
	soc->tos = 0;
	soc->send_unacked = frame->ackno;
	soc->myflags = TCP_FLAG_RESET | TCP_FLAG_ACK;
	soc->receive_next = frame->seqno;


	/* Is there SYN or FIN?	*/

	if( (frame->hlen_flags & TCP_FLAG_SYN) || ( frame->hlen_flags & TCP_FLAG_FIN) )
		soc->receive_next++;


	soc->send_mtu = TCP_DEF_MTU;

	tcp_sendcontrol(NO_OF_TCPSOCKETS);

}


/********************************************************************************
Function:		tcp_initseq

Parameters:		-

Return val:		UINT32 initial sequence number

Date:			17.7.2002

Desc:			Get and return initial sequence number
*********************************************************************************/

UINT32 tcp_initseq (void)
{

	DEBUGOUT("Calculating initial sequence number\r\n");

	return( ( (UINT32)BaseTimer << 24) | 0x00FFFFFF );

}

/********************************************************************************
Function:		tcp_mapsocket

Parameters:		struct IPFrame* ipframe - pointer to received IP frame
				struct TCPFrame* tcpframe - pointer to frame to be mapped


Return val:		INT8 - (-1) = Error (No resources)
					 -  >0 = Handle to mapped socket

Date:			12.7.2002

Desc:			Try to find a socket for received TCP packet or allocate
				listening one
*********************************************************************************/

INT8 tcp_mapsocket (struct IPFrame* ipframe, struct TCPFrame* tcpframe)
{
	struct tcb* soc;
	UINT8 i;


	/* Check if there is already connection on	*/

	for( i=0; i < NO_OF_TCPSOCKETS; i++)
	{
		soc = &TCPSocket[i];					/* Get socket	*/

		if(soc->state == TCP_STATE_LISTENING)
			continue;							/* No match		*/
		if(soc->remport != tcpframe->sport)
			continue;
		if(soc->locport != tcpframe->dport)
			continue;
		if(soc->rem_ip != ipframe->sip)
			continue;

		/* There is connection on already	*/

		DEBUGOUT("Active connection socket found\r\n");

		return(i);
	}

	/* Allocate listening one if SYN packet (Connection Request)	*/

	DEBUGOUT("No active connection, checking if SYN packet\r\n");

	/* Is it SYN?	*/

	if( (tcpframe->hlen_flags & TCP_FLAG_SYN) == 0 )
		return(-1);
	if( tcpframe->hlen_flags & TCP_FLAG_ACK )
		return(-1);
	if( tcpframe->hlen_flags & TCP_FLAG_RESET )
		return(-1);
	if( tcpframe->hlen_flags & TCP_FLAG_FIN )
		return(-1);

	DEBUGOUT("Trying to allocate listening one for SYN packet\r\n");

	/* Search listening sockets	*/

	for( i=0; i < NO_OF_TCPSOCKETS; i++)
	{
		soc = &TCPSocket[i];				/* Get socket	*/

		if(soc->state != TCP_STATE_LISTENING)
			continue;

		if(soc->locport != tcpframe->dport)
			continue;

		/* Bind it	*/

		soc->rem_ip = ipframe->sip;
		soc->remport = tcpframe->sport;

		DEBUGOUT("Allocated new socket\r\n");

		return(i);

	}

	/* No success	*/

	DEBUGOUT("ERROR:No socket found or allocated for TCP packet\r\n");

	return(-1);

}



/********************************************************************************
Function:		tcp_newstate

Parameters:		struct tcb* soc - socket structure operated
				UINT8 nstate - new state

Return val:		void

Date:			18.7.2002

Desc:			Change state of socket and reload timers.
				Call this function periodically on connected state to keep
				connection on.
*********************************************************************************/

void tcp_newstate (struct tcb* soc, UINT8 nstate)
{
	soc->state = nstate;
	soc->retries_left = TCP_DEF_RETRIES;

	/* Retransmit timer */

	init_timer(soc->retransmit_timerh, TCP_DEF_RETRY_TOUT);

	/* In some states we don't want to wait for many retries (e.g. TIMED_WAIT)	*/

	switch(soc->state)
	{
		case TCP_STATE_TIMED_WAIT:
			soc->retries_left = 0;
			break;

		case TCP_STATE_SYN_SENT:

			/* When we are sending SYN it's propably that ARP is not valid 	*/
			/* Do retransmit faster on first time							*/
			init_timer(soc->retransmit_timerh, TCP_INIT_RETRY_TOUT);
			soc->retries_left = TCP_CON_ATTEMPTS;
			break;

		case TCP_STATE_LAST_ACK:
		case TCP_STATE_FINW1:
		case TCP_STATE_FINW2:
		case TCP_STATE_CLOSING:
			soc->retries_left = 1;
			break;

		default:
			break;

	}


	/* KeepAlive timer	*/

	if(soc->state == TCP_STATE_CONNECTED)
		init_timer(soc->persist_timerh, soc->tout);



	return;


}


/********************************************************************************
Function:		tcp_getfreeport

Parameters:		void


Return val:		UINT16 - 0 = no free ports
						 >0 = Free local TCP port

Date:			19.8.2002

Desc:			Gets next free (not used) local port
*********************************************************************************/

UINT16 tcp_getfreeport (void)
{
	struct tcb* soc;
	static UINT16 lastport = 1;
	UINT16 start;
	UINT16 i;


	/* Try with every port to every socket untill free found	*/

	for( start = lastport++; start != lastport; lastport++)
	{
		if(lastport == TCP_PORTS_END)
			lastport = 1;

		for(i = 0; i < NO_OF_TCPSOCKETS; i++)
		{
			soc = &TCPSocket[i];					/* Get socket	*/

			if( (soc->state > TCP_STATE_CLOSED) && (soc->locport == lastport) )
			{
				/* Blaah, this socket has reserved the port, go to next one	*/
				break;
			}

		}

		/* Did we found it?	*/

		if( i == NO_OF_TCPSOCKETS)
			break;

	}

	if(lastport == start)
	{
		DEBUGOUT("Out of TCP ports!!\n\r");
		return(0);
	}

	return(lastport);

}


/********************************************************************************
Function:		TCP_CheckCS

Parameters:		struct IPFrame* ipframe - pointer to IP frame that carried TCP
				UINT16 len - length of TCP portion


Return val:		UINT8 0 - Checksum corrupted
				UINT8 1 - Checksum OK

Date:			16.7.2002

Desc:			Calculate is the TCP frame uncorrupted. May be
				made more intelligent/faster by using carry method.
*********************************************************************************/

UINT8 TCP_CheckCS (struct IPFrame* ipframe, UINT16 len)
{
	UINT16 cs;
	UINT8 cs_cnt;

	cs = 0;
	cs_cnt = 0;

	/* Do it firstly to IP pseudo header	*/

	cs = IpCheckSum(cs, (UINT8)(ipframe->sip >> 24), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(ipframe->sip >> 16), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(ipframe->sip >> 8), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)ipframe->sip, cs_cnt++);

	cs = IpCheckSum(cs, (UINT8)(ipframe->dip >> 24), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(ipframe->dip >> 16), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)(ipframe->dip >> 8), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)ipframe->dip, cs_cnt++);

	cs = IpCheckSum(cs, 0, cs_cnt++);

	cs = IpCheckSum(cs, (UINT8)ipframe->protocol, cs_cnt++);

	cs = IpCheckSum(cs, (UINT8)(len >> 8), cs_cnt++);
	cs = IpCheckSum(cs, (UINT8)len, cs_cnt++);

	/* Go to TCP data	*/

	while(len>15)
	{
		RECEIVE_NETWORK_BUF(tcp_tempbuf,16);

		cs = IpCheckSumBuf(cs, tcp_tempbuf,16);
		len -= 16;
		cs_cnt += 16;
	}

	while(len--)
	{
		cs = IpCheckSum(cs, RECEIVE_NETWORK_B(), (UINT8)cs_cnt++);
	}


	cs = ~ cs;

	if(cs != IP_GOOD_CS)
	{
		return (0);
	}

	/* It's OK	*/

	return(1);


}

⌨️ 快捷键说明

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