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

📄 tcp.c

📁 Pic Nic 16f877/18f452控制 rtl8019as 原代码
💻 C
字号:
/*
 * tcp.c
 *
 * TCP Specific functions
 *
 */

//TCP Packet contents (PAYLOAD only!)
int8 TCP_DATA[30];



//TCP Header definition
_TCP_HEADER TCP_HEADER;

//Send TCP Header to the NIC
void load_TCP_header(int16 data_flags, int16 tcp_chksum, int16 tcp_length) {

  chksum = tcp_chksum;

  // calculate checksum of pseudo header
  calc_chksum( make16(my_ip[0],my_ip[1]));
  calc_chksum( make16(my_ip[2],my_ip[3]));
  calc_chksum( make16(IP_HEADER.SourceAddress.ip0,IP_HEADER.SourceAddress.ip1));
  calc_chksum( make16(IP_HEADER.SourceAddress.ip2,IP_HEADER.SourceAddress.ip3));
  calc_chksum(TCP);
  calc_chksum(tcp_length);

  // source port
  outportw(NIC_DATA, TCP_HEADER.DestPort);

  // destination port
  outportw(NIC_DATA, TCP_HEADER.SourcePort);

  // sequence number
  outportw(NIC_DATA, xm_seq >>16);
  outportw(NIC_DATA, xm_seq);

  // acknowledment number
  outportw(NIC_DATA, xm_ack>>16);
  outportw(NIC_DATA, xm_ack);

  // data offset and flags
  outportw(NIC_DATA, data_flags);

  // window
  outportw(NIC_DATA, 1460);

  // checksum
  outportw(NIC_DATA, ~chksum);

  // urgent pointer
  outportw(NIC_DATA, 0);
}

//Invert bytes positions
static void swapTCPHeader(_TCP_HEADER*  header) {
    header->SourcePort      = swap16(header->SourcePort);
    header->DestPort        = swap16(header->DestPort);
    header->SeqNumber       = swap32(header->SeqNumber);
    header->AckNumber       = swap32(header->AckNumber);
    header->Window          = swap16(header->Window);
    header->Checksum        = swap16(header->Checksum);
    header->UrgentPointer   = swap16(header->UrgentPointer);
}


void tcp_response(void) {
  int i;

  switch(html_socket)
  {
    case LISTEN:
    {
      #ifdef DEBUG
        puts("LISTEN");
      #endif
      // *** We are expecting a SYN without an ACK
      // *** Could get a RST, FIN, PSH or URG but we'll ignore the PSH or URG
      if (TCP_HEADER.Flags.flagSYN)

      {
        #ifdef DEBUG
        puts("flagSYN");
      #endif
      // SYN set
        // We should check to be sure an ACK wasn't also sent
        if (TCP_HEADER.Flags.flagACK) break;
          // Ignore it for now. We'll add code to handle later
        // We shouldn't have a RST or FIN with a SYN
        if (TCP_HEADER.Flags.flagRST || TCP_HEADER.Flags.flagFIN) break;
          // Ignore it for now. We'll add code to hanlde later
        // Everything looks okay so handle the SYN request
        // Save the senders sequence number
        tcp_listen();
      }
      }
      break;
    case SYN_RCVD:
    {
      #ifdef DEBUG
        puts(" Syn Rcvd ");
      #endif
      // Check if addressed for this socket
    if (port!=TCP_HEADER.SourcePort || iphh.ip0!=IP_HEADER.SourceAddress.ip0 ||
     iphh.ip1!=IP_HEADER.SourceAddress.ip1 || iphh.ip2!=IP_HEADER.SourceAddress.ip2
      || iphh.ip3!= IP_HEADER.SourceAddress.ip3)
        break;
          printf("flags %x \n\r",*(&TCP_HEADER.Flags));
       // We are expecting an ACK without a SYN
   if (TCP_HEADER.Flags.flagACK)
      {
       #ifdef DEBUG
        puts("flagACK\n\r");
      #endif
        // ACK set
        // We should check to be sure an SYN wasn't also sent
        if (TCP_HEADER.Flags.flagSYN)
        {
         #ifdef DEBUG
        puts("flagSYN\n\r");
      #endif
          break;  // Ignore it for now. We'll add code to handle later
        }
        // We shouldn't have a RST or FIN with an ACK
        if (TCP_HEADER.Flags.flagRST || TCP_HEADER.Flags.flagFIN)
        {
         #ifdef DEBUG
        puts("flagRST o flagFIN\n\r");
      #endif
        	//html_socket = LISTEN;
          break;  // Ignore it for now. We'll add code to hanlde later
        }
        // Everything looks okay so handle the ACK response
        tcp_syn_rcvd();
      }
      else
      {
      #ifdef DEBUG
        puts(" none ");
      #endif
      html_socket = LISTEN;
      }
    }
      break;

    case ESTAB:
    {
      #ifdef DEBUG
        puts(" Estab ");
      #endif
      // We are expecting an ACK without or SYN
      // We could receive a FIN
      if (TCP_HEADER.Flags.flagACK) {
        // ACK set
        // We should check to be sure an SYN wasn't also sent
          if (TCP_HEADER.Flags.flagSYN) {
          break;          // Ignore it for now. We'll add code to handle later
          }
        // We shouldn't have a RST with an ACK
        if (TCP_HEADER.Flags.flagRST ) {
          break;          // Ignore it for now. We'll add code to hanlde later
          }
        // ************************************************************
        // *** - check received sequence number to be sure it's     ***
        // ***   what we expected                                   ***
        // *** - check acknowledgement number to be sure it's what  ***
        // ***   we are going to send                               ***
        // *** - check source ip address and source port to be sure ***
        // ***   they are correct                                   ***
        // ************************************************************
       // if (seq[0] != xm_ack[0] || seq[1] != xm_ack[1] ||ack[0] != xm_seq[0] || ack[1] != xm_seq[1])
         if(TCP_HEADER.SeqNumber!=xm_ack)
            break;
        if (port!=TCP_HEADER.SourcePort || iphh.ip0!=IP_HEADER.SourceAddress.ip0 ||
     iphh.ip1!=IP_HEADER.SourceAddress.ip1 || iphh.ip2!=IP_HEADER.SourceAddress.ip2 ||
     iphh.ip3!= IP_HEADER.SourceAddress.ip3)
break;
        // Everything looks okay so handle the ACK response
      tcp_estab();
        }
    }
    }

}


void tcp_listen(void)
{
	int i;
	int16 optionlen;

	xm_ack=TCP_HEADER.SeqNumber;
	//xm_seq=TCP_HEADER.AckNumber;

	port = TCP_HEADER.SourcePort;

	// Save the source IP address
	iphh = IP_HEADER.SourceAddress;

	// Calculate data length
	optionlen = (TCP_HEADER.dataoffset.val << 2)-sizeof(TCP_HEADER);
	tcp_data_len= IP_HEADER.TotalLength - (40 + optionlen);

	// Increment sequence to account for SYN and add data
	xm_ack = xm_ack + tcp_data_len + 1;
	xm_seq+=1;

	#ifdef DEBUG
		printf("hdr_:%u\n\r",hdr_len);
		printf("option_:%lu\n\r",optionlen);
		printf("TotalLength:%lu\n\r",IP_HEADER.TotalLength);
		printf("tcplen_:%lu\n\r",tcp_data_len);
		printf("xm_ack:%lx\n\r",xm_ack);
		printf("xm_seq:%lx\n\r",xm_seq);
	#endif

	load_ethernet_header();   // 12 bytes (2 bytes for protocol included in load_IP..)
	load_IP_header(48,TCP);   // Number of bytes included in call (add 2 for protocol)
          // 20 for IP header
          // 20 for TCP header
          // 8 for Options

	load_TCP_header( 0x7000 | TCP_SYN | TCP_ACK, 0x07B8, 28);

	// Number of bytes include in load_IP_header call 07B8
	// Send options
	outport(NIC_DATA,0x02);
	outport(NIC_DATA,0x04);
	outport(NIC_DATA,0x05);
	outport(NIC_DATA,0xB4);
	outport(NIC_DATA,0x00);
	outport(NIC_DATA,0x00);
	outport(NIC_DATA,0x00);
	outport(NIC_DATA,0x00);
	sendPacket(62);

	// Calculate the next sequence number to send
	// In this case we add 1 since we only sent a SYN
	xm_seq+=1;

	html_socket = SYN_RCVD;
}

void tcp_syn_rcvd(void) {

	int16 optionlen;

	printf("tcp_syn_rcvd\n\r");

	// Calculate data length
	optionlen = (TCP_HEADER.dataoffset.val << 2)-sizeof(TCP_HEADER);
	tcp_data_len= IP_HEADER.TotalLength - (40 + optionlen);
	printf("tcplen_:%lu\n\r",tcp_data_len);

	//tcp_data_len = IP_HEADER.TotalLength - (hdr_len + (int8)TCP_HEADER.dataoffset);
	// Increment sequence to account for data
	xm_ack+= tcp_data_len;

	// *** Need to handle data if any here.
	// We'll assume there isn't any for now so no response is needed
	html_socket = ESTAB;
}

/////////////////////////////////////////////////////////////////////////////
void tcp_estab(void) {

   int16 optionlen;
   int16 cks;
   int8 dat,dat1, i;
   int8 html_request[19];
   #ifdef DEBUG
      printf("TCP Data: ");
      for (i=0; i < 30; i++) {
         printf("%c", TCP_DATA[i]);
      }
      printf("\n\r");
   #endif

   //Check if the request starts with 'GET' that means its an authentic HTTP request
   //This should be done somewhere else, because here we are already sending the answer to the request
   /*if (!TCP_DATA[0] == 'G'
       || !TCP_DATA[1] == 'E'
       || !TCP_DATA[2] == 'T'
       || !TCP_DATA[3] == ' '
       || !TCP_DATA[4] == '/') {
      printf("Not an HTTP request\n\r");
      //fin_rx();
      return;
   }
   printf("Got HTTP Request\r\n");*/

   //Get Page Name the user asked
   for (i=0; i<=19; i++) {
      if (TCP_DATA[i+5] == ' ') {
            html_request[i] = 0;
            break;
      }
      html_request[i] = TCP_DATA[i+5];
   }
   html_request[18] = 0;

   //Show page name - up to now the entire page name is okay
   #ifdef DEBUG
      printf("Asked Page: %s", html_request);
   #endif

   //tcp_data_len = IP_HEADER.TotalLength  - (hdr_len + (int8)TCP_HEADER.dataoffset);
   optionlen = (TCP_HEADER.dataoffset.val << 2)-sizeof(TCP_HEADER);
   tcp_data_len= IP_HEADER.TotalLength - (40 + optionlen);

   // This is the next sequence number we expect
   xm_ack+= tcp_data_len;

   //Start preparing our answer
   load_ethernet_header();		// 12 bytes (2 bytes for protocol included in load_IP..)

   //Increase access counter
   accessCount++;

   //Prepares page - Look! Only first char! I want to pass the entire page name to the function!
   preparar_pagina(html_request[0], html_request);

   //Now IP and TCP Stuff
   load_IP_header(htmlSize + 40,TCP);		// Number of bytes included in call (add 2 for protocol)
								// 20 for IP header
								// 20 for TCP header
								// 148 for Data
   load_TCP_header( 0x5000 | TCP_ACK | TCP_FIN, htmlChecksum, htmlSize);

   //Finish sending the page to NIC and the packet with the page to the client
   sendHttpPage();
   xm_ack+=htmlSize;

   sendPacket(htmlSize + 54);

   html_socket = LISTEN;

   #ifdef DEBUG
      puts("Webpage sent\n\r");
   #endif
}

//Ok, we have a TCP Packet
//Read its header and Payload storing in the correct places
void processTCP() {

	int8 i,kind;

	#ifdef DEBUG
        	puts(" TCP ");
        #endif

	//Reads TCP Header and stores in the correct var
	getNicData(&TCP_HEADER,sizeof(TCP_HEADER));
	swapTCPHeader(&TCP_HEADER);

	#ifdef DEBUG
		printf("src port: = %Lx\n\r", TCP_HEADER.SourcePort);
                printf("dst port: = %Lx\n\r", TCP_HEADER.DestPort);
                printf("SeqNum: = %Lx\n\r", TCP_HEADER.SeqNumber);
                printf("AckNum: = %Lx\n\r", TCP_HEADER.AckNumber);
                printf("offset: = %x\n\r", (int8)TCP_HEADER.dataoffset);
	#endif

	//Reads TCP Payload and stores in TCP_DATA
	//So anything the browser will send such as a "GET / HTTP/1.0", a POST, a page requested name, or whatever will be in this var
	//Later we check for the type of request and the pagename, redirecting to the correct page we have stored in flash memory as printfs
	getNicData(TCP_DATA,30);

	// We only respond to port 80 (HTML requests)
	/* Answering on all TCP Ports!
	if (TCP_HEADER.DestPort != 80) {
        	fin_rx();
                break;
        }
	*/

	fin_rx();
	tcp_response();
}

⌨️ 快捷键说明

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