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

📄 tcp_input.c.svn-base

📁 realtek的8186芯片ADSL路由AP源代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2001, Swedish Institute of Computer Science. * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * 3. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  * * This file is part of the lwIP TCP/IP stack. *  * Author: Adam Dunkels <adam@sics.se> * * $Id: tcp_input.c,v 1.1.1.1 2006/06/07 05:27:50 kaohj Exp $ *//*-----------------------------------------------------------------------------------*//* tcp_input.c * * The input processing functions of TCP. * * These functions are generally called in the order (ip_input() ->) tcp_input() -> * tcp_process() -> tcp_receive() (-> application). * *//*-----------------------------------------------------------------------------------*/#include "debug.h"#include "def.h"#include "opt.h"//#include "lwip/netif.h"#include "mem.h"#include "memp.h"//#include "lwip/inet.h"
#ifndef __LWIP_INET_H__
#define __LWIP_INET_H__

#include "arch.h"

#include "opt.h"
#include "pbuf.h"
//#include "lwip/ip_addr.h"

//u16_t inet_chksum(void *dataptr, u16_t len);
//u16_t inet_chksum_pbuf(struct pbuf *p);
//u16_t inet_chksum_pseudo(struct pbuf *p,
//			 struct ip_addr *src, struct ip_addr *dest,
//			 u8_t proto, u16_t proto_len);
u16_t inet_chksum_pseudo(struct pbuf *p,
		   u32_t *src, u32_t *dest,
		   u8_t proto, u32_t proto_len);

#ifdef HTONS
#undef HTONS
#endif /* HTONS */
#ifdef NTOHS
#undef NTOHS
#endif /* NTOHS */
#ifdef HTONL
#undef HTONL
#endif /* HTONL */
#ifdef NTOHL
#undef NTOHL
#endif /* NTOHL */

#ifndef HTONS
#   if BYTE_ORDER == BIG_ENDIAN
#      define HTONS(n) (n)
#      define htons(n) HTONS(n)
#   else /* BYTE_ORDER == BIG_ENDIAN */
#      define HTONS(n) (((((u16_t)(n) & 0xff)) << 8) | (((u16_t)(n) & 0xff00) >> 8))
#   endif /* BYTE_ORDER == BIG_ENDIAN */
#endif /* HTONS */

#ifdef NTOHS
#undef NTOHS
#endif /* NTOHS */

#ifdef ntohs
#undef ntohs
#endif /* ntohs */

#define NTOHS HTONS
#define ntohs htons


#ifndef HTONL
#   if BYTE_ORDER == BIG_ENDIAN
#      define HTONL(n) (n)
#      define htonl(n) HTONL(n)
#   else /* BYTE_ORDER == BIG_ENDIAN */
#      define HTONL(n) (((((u32_t)(n) & 0xff)) << 24) | \
                        ((((u32_t)(n) & 0xff00)) << 8) | \
                        ((((u32_t)(n) & 0xff0000)) >> 8) | \
                        ((((u32_t)(n) & 0xff000000)) >> 24))
#   endif /* BYTE_ORDER == BIG_ENDIAN */
#endif /* HTONL */

#ifdef ntohl
#undef ntohl
#endif /* ntohl */

#ifdef NTOHL
#undef NTOHL
#endif /* NTOHL */

#define NTOHL HTONL
#define ntohl htonl

#ifndef _MACHINE_ENDIAN_H_
#ifndef _NETINET_IN_H
#ifndef _LINUX_BYTEORDER_GENERIC_H

#if BYTE_ORDER == LITTLE_ENDIAN
u16_t htons(u16_t n);
u32_t htonl(u32_t n);
#else
#endif /* BYTE_ORDER == LITTLE_ENDIAN */

#endif /* _LINUX_BYTEORDER_GENERIC_H */
#endif /* _NETINET_IN_H */
#endif /* _MACHINE_ENDIAN_H_ */

#endif /* __LWIP_INET_H__ */


#include "tcp.h"#include "stats.h"//#include "arch/perf.h"
#ifndef __PERF_H__
#define __PERF_H__

#define PERF_START    /* null definition */
#define PERF_STOP(x)  /* null definition */

#endif /* __PERF_H__ */
static struct tcp_seg inseg;/* Forward declarations. */static err_t tcp_process(struct tcp_pcb *pcb);static void tcp_receive(struct tcp_pcb *pcb);static void tcp_parseopt(struct tcp_pcb *pcb);/*-----------------------------------------------------------------------------------*//* tcp_input: * * The initial input processing of TCP. It verifies the TCP header, demultiplexes * the segment between the PCBs and passes it on to tcp_process(), which implements * the TCP finite state machine. This function is called by the IP layer (in * ip_input()). *//*-----------------------------------------------------------------------------------*/void//tcp_input(struct pbuf *p, struct netif *inp)
tcp_input(struct pbuf *p){  struct tcp_hdr *tcphdr;  struct tcp_pcb *pcb, *prev;  struct ip_hdr *iphdr;  u8_t offset;  err_t err;
//  printf("Here into the tcp_input.\n");
//  if (p!=NULL) {
//	  printf("pbuf size is %d.\n", p->tot_len);
//  } else {
//	  printf("pbuf is null.\n");
//  }  PERF_START;  #ifdef TCP_STATS  ++stats.tcp.recv;#endif /* TCP_STATS */  iphdr = p->payload;  tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4/sizeof(u8_t));
//  printf("IP: %d.%d.%d.%d.\n", (iphdr->dest>>24)&0xff, (iphdr->dest>>16)&0xff, (iphdr->dest>>8)&0xff, (iphdr->dest)&0xff);
  pbuf_header(p, -(IPH_HL(iphdr) * 4/sizeof(u8_t)));
    /* Don't even process incoming broadcasts/multicasts. *///  if(ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) ||//     ip_addr_ismulticast(&(iphdr->dest))) {//    pbuf_free(p);//    return;//  }

//  printf("IP: %d.%d.%d.%d.\n", (iphdr->dest>>24)&0xff, (iphdr->dest>>16)&0xff, (iphdr->dest>>8)&0xff, (iphdr->dest)&0xff);
//	  printf("netif IP : %d.%d.%d.%d.\n", (netif.ip>>24)&0xff, (netif.ip>>16)&0xff, (netif.ip>>8)&0xff, (netif.ip)&0xff);

  if (iphdr->dest!=netif.ip) {
//	  printf("IP address error.\n");
	  pbuf_free(p);
	  return;
  }    /* Verify TCP checksum. *///  if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),//			(struct ip_addr *)&(iphdr->dest),//			IP_PROTO_TCP, p->tot_len) != 0) {
//  printf("checksum is %d, 0x%x\n", tcphdr->chksum, tcphdr->chksum);
    if(inet_chksum_pseudo(p, (u32_t*)&(iphdr->src),
			(u32_t*)&(iphdr->dest),
			IP_PROTO_TCP, p->tot_len) != 0) {
		
//		printf("checksum error. checksum is 0x%x.\n", inet_chksum_pseudo(p, (u32_t*)&(iphdr->src),(u32_t*)&(iphdr->dest),IP_PROTO_TCP, p->tot_len));
    DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n", inet_chksum_pseudo(p, (u32_t*)&(iphdr->src),			(u32_t*)&(iphdr->dest),			IP_PROTO_TCP, p->tot_len)));#if TCP_DEBUG    tcp_debug_print(tcphdr);#endif /* TCP_DEBUG */#ifdef TCP_STATS    ++stats.tcp.chkerr;    ++stats.tcp.drop;#endif /* TCP_STATS */    pbuf_free(p);    return;  }
//	printf("checksum passed.\n");  /* Move the payload pointer in the pbuf so that it points to the     TCP data instead of the TCP header. */  offset = TCPH_OFFSET(tcphdr) >> 4;  pbuf_header(p, -(offset * 4));  /* Convert fields in TCP header to host byte order. */  tcphdr->src = ntohs(tcphdr->src);  tcphdr->dest = ntohs(tcphdr->dest);  tcphdr->seqno = ntohl(tcphdr->seqno);  tcphdr->ackno = ntohl(tcphdr->ackno);  tcphdr->wnd = ntohs(tcphdr->wnd);
//  printf("src_port is %d, dst_port is %d, seqno is %d, ackno is %d, wnd is %d.\n",
//	  tcphdr->src, tcphdr->dest, tcphdr->seqno, tcphdr->ackno, tcphdr->wnd);  /* Demultiplex an incoming segment. First, we check if it is destined     for an active connection. */    prev = NULL;  
//  printf("Search the active list.\nThe active list is 0x%x.\n", tcp_active_pcbs);  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->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);    if(pcb->remote_port == tcphdr->src &&       pcb->local_port == tcphdr->dest &&       ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&       ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {            /* 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 = pcb->next;	pcb->next = tcp_active_pcbs;	tcp_active_pcbs = pcb;       }      ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);      break;    }    prev = pcb;  }  /* If it did not go to an active connection, we check the connections     in the TIME-WAIT state. */  if(pcb == NULL) {
//	  printf("Search the timewait list.\nThe timewait list is 0x%x.\n", tcp_tw_pcbs);    for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {      ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);      if(pcb->remote_port == tcphdr->src &&	 pcb->local_port == tcphdr->dest &&	 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {	/* 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(pcb == NULL) {
//		printf("Search the listen list.\nThe listen list is 0x%x.\n", tcp_listen_pcbs);      for(pcb = (struct tcp_pcb *)tcp_listen_pcbs; pcb != NULL; pcb = pcb->next) {	ASSERT("tcp_input: LISTEN pcb->state == LISTEN", pcb->state == LISTEN);
//	printf("pcb ip is 0x%x, dest ip is 0x%x\n", pcb->local_ip, iphdr->dest);	if((ip_addr_isany(&(pcb->local_ip)) ||               ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) &&	   pcb->local_port == tcphdr->dest) {	  	  /* 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 = pcb->next;	    pcb->next = (struct tcp_pcb *)tcp_listen_pcbs;	    tcp_listen_pcbs = (struct tcp_pcb_listen *)pcb; 	  }	  break;	}	prev = pcb;      }    }  }  #if TCP_INPUT_DEBUG  DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));  tcp_debug_print_flags(TCPH_FLAGS(tcphdr));  DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));#endif /* TCP_INPUT_DEBUG */  /*  seg = memp_malloc2(MEMP_TCP_SEG);      if(seg != NULL && pcb != NULL) {*/  if(pcb != NULL) {
//	  printf("pcb is OK.\n");      #if TCP_INPUT_DEBUG#if TCP_DEBUG    tcp_debug_print_state(pcb->state);#endif /* TCP_DEBUG */#endif /* TCP_INPUT_DEBUG */        /* Set up a tcp_seg structure. */    inseg.next = NULL;    inseg.len = p->tot_len;    inseg.dataptr = p->payload;    inseg.p = p;    inseg.tcphdr = tcphdr;        /* The len field in the tcp_seg structure is the segment length       in TCP terms. In TCP, the SYN and FIN segments are treated as       one byte, hence increment the len field. */    /*    if(TCPH_FLAGS(tcphdr) & TCP_FIN || TCPH_FLAGS(tcphdr) & TCP_SYN) {      ++inseg.len;      } */   
//	printf("state is: %d.\n", pcb->state);    if(pcb->state != LISTEN && pcb->state != TIME_WAIT) {
//		printf("pcb->recv_data here.%d\n",__LINE__);      pcb->recv_data = NULL;    }    err = tcp_process(pcb);

//	if( err == ERR_OK) {
//		printf("process OK.\n");
//	} else {
//		printf("process ERROR.\n");
//	}    /* A return value of ERR_ABRT means that tcp_abort() was called       and that the pcb has been freed. */    if(err != ERR_ABRT) {      if(pcb->state != LISTEN) {	if(pcb->flags & TF_RESET) {	  if(pcb->state != LISTEN) {	    if(pcb->errf != NULL) {	      pcb->errf(pcb->callback_arg, ERR_RST);	    }	  }	  if(pcb->state == TIME_WAIT) {	    tcp_pcb_remove(&tcp_tw_pcbs, pcb);	  } else {	    tcp_pcb_remove(&tcp_active_pcbs, pcb);      	  }	  memp_free(MEMP_TCP_PCB, pcb);	} else if(pcb->flags & TF_CLOSED) {	  tcp_pcb_remove(&tcp_active_pcbs, pcb);	  memp_free(MEMP_TCP_PCB, pcb);	} else {	  if(pcb->state < TIME_WAIT) {	    err = ERR_OK;	    /* If the application has registered a "sent" function to be	       called when new send buffer space is avaliable, we call it	       now. */	    if(pcb->acked > 0 && pcb->sent != NULL) {	      err = pcb->sent(pcb->callback_arg, pcb, pcb->acked);	    }
//		printf("pcb->recv is 0x%x, pcb->recv_data is 0x%x, flag is %d.\n", pcb->recv, pcb->recv_data, pcb->flags&TF_GOT_FIN);	    if(pcb->recv != NULL) {
//			printf("Here0.\n");	      if(pcb->recv_data != NULL) {
//			  printf("Here1.\n");
			  err = pcb->recv(pcb->callback_arg, pcb, pcb->recv_data, ERR_OK);
		  }
		  if(pcb->flags & TF_GOT_FIN) {
//			  printf("Here3.\n");
			  err = pcb->recv(pcb->callback_arg, pcb, NULL, ERR_OK);
		  }	    } else {	      err = ERR_OK;
//		  printf("pcb->recv_data here.%d\n",__LINE__);	      pbuf_free(pcb->recv_data);	      if(pcb->flags & TF_GOT_FIN) {		tcp_close(pcb);

⌨️ 快捷键说明

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