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

📄 tcp.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
字号:
//-----------------------------------------------------------------------------
// TCP
//-----------------------------------------------------------------------------

#include <string.h>
#include "tcpip_stack.h"
#include "ip.h"
#include "tcp.h"
#include "http.h"

//-----------------------------------------------------------------------------
// TCP stack part internal variables
//-----------------------------------------------------------------------------
static TCB tcp_table[TCP_MAX_CONNECTIONS]; //TCP control block array
static u8 TCB_used;     //number of TCBs in use
static u8 TCB_current;  //TCB in use
static u16 num_received = 0;

//-----------------------------------------------------------------------------
//Name:Tcp_Sum()
//Funcionality: Calculates the TCP header checksum
//-----------------------------------------------------------------------------
u16 Tcp_Sum(u16 len_tcp, u8 src_addr[],u8 dest_addr[], u8 buff[])
{
u16 prot_tcp=6;
u16 padd=0;
u16 word16;
u32 sum;	
int i;

	if (len_tcp%2){
		padd=1;
		buff[len_tcp]=0;
	}
	
	sum=0;
	
	for (i=0;i<len_tcp+padd;i=i+2){
		word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
		if (i!=16) sum = sum + (u32)word16;
	}	

	for (i=0;i<4;i=i+2){
		word16 =((src_addr[i]<<8)&0xFF00)+(src_addr[i+1]&0xFF);
		sum= sum + (u32)word16;	
	}

	for (i=0;i<4;i=i+2){
		word16 =((dest_addr[i]<<8)&0xFF00)+(dest_addr[i+1]&0xFF);
		sum=sum+ (u32) word16; 	
	}

	sum = sum + prot_tcp + len_tcp;

    	while (sum>>16)
		sum = (sum & 0xFFFF)+(sum >> 16);
		
	sum = ~sum;
        sum = ((sum >> 8) & 0x00FF) + ((sum << 8) & 0xFF00);

return ((u16) sum);
}

//-----------------------------------------------------------------------------
//Name:Tcp_Ip_Init()
//Funcionality: Initialization of the TCB array, performaed at the application start-up
//for proper structure content definition
//-----------------------------------------------------------------------------
void Tcp_Ip_Init()
{
       int i;	

       TCB_used = 0;  //number of TCBs in use

       for (i = 0; i < TCP_MAX_CONNECTIONS; i++)
       {
       	tcp_table[i].src_port = 0;
       	tcp_table[i].dest_port = 0;
       	tcp_table[i].dest_ip[0] = 0;
       	tcp_table[i].dest_ip[1] = 0;
       	tcp_table[i].dest_ip[2] = 0;
       	tcp_table[i].dest_ip[3] = 0;
       	tcp_table[i].state = LISTEN;
       	tcp_table[i].src_seq = 0;
       	tcp_table[i].dest_seq = 0;
       }
}
//-----------------------------------------------------------------------------
//Name:ClearTCB()
//Funcionality: used to free the TCB when a tcp connection was closed
//-----------------------------------------------------------------------------
void ClearTCB(u8 num_TCB)
{
       	tcp_table[num_TCB].src_port = 0;
       	tcp_table[num_TCB].dest_port = 0;
       	tcp_table[num_TCB].dest_ip[0] = 0;
       	tcp_table[num_TCB].dest_ip[1] = 0;
       	tcp_table[num_TCB].dest_ip[2] = 0;
       	tcp_table[num_TCB].dest_ip[3] = 0;
       	tcp_table[num_TCB].state = LISTEN;
       	tcp_table[num_TCB].src_seq = 0;
       	tcp_table[num_TCB].dest_seq = 0;
}


//-----------------------------------------------------------------------------
//Name:Rx_TCP_Frame()
//Funcionality: Analyses the received frame, checks whether a TCB exists. If yes
// then keeps the control settings of the TCB. If no, creates new TCB if possible.
// Returns the TCB array index.
//-----------------------------------------------------------------------------

u8 Rx_TCP_Frame(EthernetFrame *frame)
{
  tcp_hdr *rx_tcp_hdr = (tcp_hdr *)((u8 *)frame + ETHER_HEADER_LENGTH + IP_HEADER_LENGTH);
  ip_hdr *rx_ip_hdr = (ip_hdr *)((u8 *)frame + ETHER_HEADER_LENGTH);

  TCB_current = TCP_MAX_CONNECTIONS; //default, means no TCB array member is free
  u8 i;

  //check the ports to find the right TCB
  for(i=0; i < TCP_MAX_CONNECTIONS; i++){
	      if ((tcp_table[i].dest_ip[0] == rx_ip_hdr->srcIP[0]) &&
                  (tcp_table[i].dest_ip[1] == rx_ip_hdr->srcIP[1]) &&
                  (tcp_table[i].dest_ip[2] == rx_ip_hdr->srcIP[2]) &&
                  (tcp_table[i].dest_ip[3] == rx_ip_hdr->srcIP[3]) &&
	      tcp_table[i].dest_port == rx_tcp_hdr->src_port &&
              tcp_table[i].src_port == rx_tcp_hdr->dst_port) {

                num_received = 0;
                num_received = rx_ip_hdr->length;
                ChangeEndianess_16(num_received);
                num_received -= ((4*((rx_tcp_hdr->data_off)>>4)) + sizeof(ip_hdr));
                TCB_current = i;

              }
  }

  if ((TCB_current == TCP_MAX_CONNECTIONS) && (TCB_used < TCP_MAX_CONNECTIONS)){ //not yet in the table and there is free space -> new one
        for(i=0; i < TCP_MAX_CONNECTIONS; i++){
          if (tcp_table[i].state == LISTEN){ //-> make new record
            TCB_current = i;
	    tcp_table[TCB_current].src_port = rx_tcp_hdr->dst_port;
	    tcp_table[TCB_current].dest_port = rx_tcp_hdr->src_port;
	    memcpy(tcp_table[TCB_current].dest_ip, rx_ip_hdr->srcIP,IP_ADDR_LEN);
	    tcp_table[TCB_current].src_seq = TCP_START_SEQ;
	    memcpy(&(tcp_table[TCB_current].dest_seq), &(rx_tcp_hdr->seq),4);
            ChangeEndianess_32(tcp_table[TCB_current].dest_seq);

            TCB_used++;

            break;
          }
        }
  }
  else if (TCB_used == TCP_MAX_CONNECTIONS) { //no free space, we have to RST connection
          return TCP_MAX_CONNECTIONS;
  }

  return TCB_current;
}

//-----------------------------------------------------------------------------
//Name:Tx_TCP_Frame()
//Funcionality: enters a valid TCP header values, calculates a checksum and
// calls the IP stack part.
//-----------------------------------------------------------------------------

void Tx_TCP_Frame(EthernetFrame *frame, u8 control_bits, u8 *szData, u16 nLength)
{
	tcp_hdr *tx_tcp_hdr = (tcp_hdr*)((u8 *)frame + IP_HEADER_LENGTH + ETHER_HEADER_LENGTH);
	u8 *tcp_data = (u8 *)((u8*)frame + ETHER_HEADER_LENGTH + IP_HEADER_LENGTH + TCP_HEADER_LENGTH);
	u8 *chksum_hdr = (u8*)tx_tcp_hdr;
	
        u32 temp_seq;
        u32 temp_ack;

        //fill the data to be sent
	memcpy(tcp_data, szData, nLength);

        //fill the TCP header
        tx_tcp_hdr->src_port = tcp_table[TCB_current].src_port;
        tx_tcp_hdr->dst_port = tcp_table[TCB_current].dest_port;

	tx_tcp_hdr->control = control_bits;

        temp_ack = tcp_table[TCB_current].src_seq;
        temp_seq = tcp_table[TCB_current].dest_seq + num_received;
        ChangeEndianess_32(temp_ack);
        ChangeEndianess_32(temp_seq);
        memcpy(&(tx_tcp_hdr->seq),&temp_ack,4);
        memcpy(&(tx_tcp_hdr->ack),&temp_seq,4);

        tx_tcp_hdr->data_off = 0x70; //no fragmentation

        tx_tcp_hdr->window = 0xf460; //should be counted, here const value

	//compute the checksum
        tx_tcp_hdr->checksum = Tcp_Sum(TCP_HEADER_LENGTH + nLength, srcIP, destIP, chksum_hdr);

      	Tx_Ip_Frame(frame,  nLength + TCP_HEADER_LENGTH, IP_TCP);

        //update the seq and ack fields
        tcp_table[TCB_current].dest_seq += num_received;
        tcp_table[TCB_current].src_seq += nLength;
}

//-----------------------------------------------------------------------------
//Name:Receive_TCP()
//Funcionality: Used as an entry point to the TCP stack part. Analyses TCP header
//and includes the TCP state machine (limited version, not all features involved)
//-----------------------------------------------------------------------------
void Receive_TCP(EthernetFrame *frame){

	tcp_hdr *rx_tcp_hdr = (tcp_hdr *)((u8 *)frame + ETHER_HEADER_LENGTH + IP_HEADER_LENGTH);

        u32 temp_seq;
        u32 temp_ack;

        TCB_current = Rx_TCP_Frame(frame); //if ok -> returns index of the communication channel

        if (TCB_current == TCP_MAX_CONNECTIONS) return; //no free TCB

        //Store the seq and ack numbers of the current frame for comparing with TCB values
        memcpy(&temp_seq, &rx_tcp_hdr->seq, 4);
        memcpy(&temp_ack, &rx_tcp_hdr->ack, 4);
        ChangeEndianess_32(temp_seq);
        ChangeEndianess_32(temp_ack);

	switch (tcp_table[TCB_current].state)
	{
        	case LISTEN:
                        //Passive Open
			if (rx_tcp_hdr->control & TCP_SYN)
			{
			tcp_table[TCB_current].state = SYN_RECVD;
                        tcp_table[TCB_current].dest_seq += 0x1;

                        Tx_TCP_Frame(frame, TCP_ACK | TCP_SYN, 0, 0);
			}
			break;
		case SYN_SENT:
                        { //Active Open			
                        }
                        break;
                case SYN_RECVD:
                        {
                          if (rx_tcp_hdr->control & TCP_ACK)
                          {
                            // received ACK, enter ESTABLISHED
                            if ((temp_seq) == (tcp_table[TCB_current].dest_seq) &&
                                (temp_ack) == (tcp_table[TCB_current].src_seq+1)){ //check seq and ack numbers

                              tcp_table[TCB_current].src_seq++;
                              tcp_table[TCB_current].state = ESTABLISHED;
                            }
                          }
                        }
                        break;
		case ESTABLISHED:
                        {
                          if (!(~(rx_tcp_hdr->control ^ (~(TCP_ACK | TCP_PSH)))))
                              switch (rx_tcp_hdr->dst_port) {
                                 case 0x5000:{  //http port
                                    Receive_HTTP(frame);
                                 }
                                 break;
                              }

                          if (!(~(rx_tcp_hdr->control ^ (~TCP_ACK)))){  //dostanu acknowledge, ze paket s http byl hostem prijat v poradku
                              Tx_TCP_Frame(frame, TCP_ACK | TCP_FIN , 0, 0);
                              tcp_table[TCB_current].state = CLOSE_WAIT;
                          }
                        }
   			break;
                case CLOSE_WAIT:{
                          if (!(~(rx_tcp_hdr->control ^ (~TCP_ACK)))){
                          }

                          if (!(~(rx_tcp_hdr->control ^ (~(TCP_ACK | TCP_FIN))))){
                          }
                              memcpy(&(tcp_table[TCB_current].src_seq),&(rx_tcp_hdr->ack),4);
                              ChangeEndianess_32(tcp_table[TCB_current].src_seq);
                              tcp_table[TCB_current].dest_seq++;
                              Tx_TCP_Frame(frame, TCP_ACK, 0, 0);
                              ClearTCB(TCB_current); // free the used TCB
                              TCB_used --;
                          }
			  break;
		case FIN_WAIT_1:
			break;
		case FIN_WAIT_2:
			break;
		case CLOSING:
			break;
		case LAST_ACK:
                        break;
		case CLOSED:
                        break;
		case TIME_WAIT:
                        break;
	}

}

//-----------------------------------------------------------------------------

⌨️ 快捷键说明

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