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

📄 uip.c

📁 AVR单片机使用U-IP库的例子
💻 C
📖 第 1 页 / 共 3 页
字号:
	    /* In all these states we should retransmit a FINACK. */
	    goto tcp_send_finack;
	    
	  }
	}
      } else if((uip_conn->tcpstateflags & TS_MASK) == ESTABLISHED) {
	/* If there was no need for a retransmission, we poll the
           application for new data. */
	uip_len = 0;
	uip_flags = UIP_POLL;
	UIP_APPCALL();
	goto appsend;
      }
    }   
    goto drop;
  }

  /* This is where the input processing starts. */
  UIP_STAT(++uip_stat.ip.recv);
  
  /* Check validity of the IP header. */  
  if(BUF->vhl != 0x45)  { /* IP version and header length. */
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.vhlerr);
    UIP_LOG("ip:vhl");
    goto drop;
  }
  
  /* Check the size of the packet. If the size reported to us in
     uip_len doesn't match the size reported in the IP header, there
     has been a transmission error and we drop the packet. */
  
#if UIP_BUFSIZE > 255
  if(BUF->len[0] != (uip_len >> 8)) {
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.hblenerr);
    UIP_LOG("ip:len");
                               /* IP length, high byte. */
    goto drop;
  }
  if(BUF->len[1] != (uip_len & 0xff)) {
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.lblenerr);
    UIP_LOG("ip:len");
                               /* IP length, low byte. */
    goto drop;
  }
#else
  if(BUF->len[0] != 0) {        /* IP length, high byte. */
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.hblenerr);
    UIP_LOG("ip:len");
    goto drop;
  }
  if(BUF->len[1] != uip_len) {  /* IP length, low byte. */
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.lblenerr);
    UIP_LOG("ip:len");
    goto drop;
  }
#endif /* UIP_BUFSIZE > 255 */  

  if(BUF->ipoffset[0] & 0x3f) { /* We don't allow IP fragments. */
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.fragerr);
    UIP_LOG("ip:frag");    
    goto drop;
  }

  /* Check if the packet is destined for our IP address. */
  if(BUF->destipaddr[0] != htons(((u16_t)UIP_IPADDR0 << 8) | UIP_IPADDR1)) {
    UIP_STAT(++uip_stat.ip.drop);
    UIP_LOG("ip:wrnip");        
    goto drop;
  }
  if(BUF->destipaddr[1] != htons(((u16_t)UIP_IPADDR2 << 8) | UIP_IPADDR3)) {
    UIP_STAT(++uip_stat.ip.drop);
    UIP_LOG("ip:wrnip");        
    goto drop;
  }

  if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
				    checksum. */
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.chkerr);
    UIP_LOG("ip:ck");    
    goto drop;
  }

  if(BUF->proto == IP_PROTO_TCP)  /* Check for TCP packet. If so, jump
                                     to the tcp_input label. */
    goto tcp_input;

  if(BUF->proto != IP_PROTO_ICMP) { /* We only allow ICMP packets from
				       here. */
    UIP_STAT(++uip_stat.ip.drop);
    UIP_STAT(++uip_stat.ip.protoerr);
    UIP_LOG("ip:prot");        
    goto drop;
  }

  UIP_STAT(++uip_stat.icmp.recv);
  
  /* ICMP echo (i.e., ping) processing. This is simple, we only change
     the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
     checksum before we return the packet. */
  if(ICMPBUF->type != ICMP_ECHO) {
    UIP_STAT(++uip_stat.icmp.drop);
    UIP_STAT(++uip_stat.icmp.typeerr);
    UIP_LOG("icmp:");
    goto drop;
  }

  ICMPBUF->type = ICMP_ECHO_REPLY;
  
  if(ICMPBUF->icmpchksum >= htons(0xffff - (ICMP_ECHO << 8))) {
    ICMPBUF->icmpchksum += htons(ICMP_ECHO << 8) + 1;
  } else {
    ICMPBUF->icmpchksum += htons(ICMP_ECHO << 8);
  }
  
  /* Swap IP addresses. */
  tmpport = BUF->destipaddr[0];
  BUF->destipaddr[0] = BUF->srcipaddr[0];
  BUF->srcipaddr[0] = tmpport;
  tmpport = BUF->destipaddr[1];
  BUF->destipaddr[1] = BUF->srcipaddr[1];
  BUF->srcipaddr[1] = tmpport;

  UIP_STAT(++uip_stat.icmp.sent);
  goto send;

  /* TCP input processing. */  
 tcp_input:
  UIP_STAT(++uip_stat.tcp.recv);
    
  if(uip_tcpchksum() != 0xffff) {   /* Compute and check the TCP
				       checksum. */
    UIP_STAT(++uip_stat.tcp.drop);
    UIP_STAT(++uip_stat.tcp.chkerr);
    UIP_LOG("tcp:csum");    
    goto drop;
  }
  
  /* Demultiplex this segment. */
  /* First check any active connections. */
  for(uip_conn = &uip_conns[0]; uip_conn < &uip_conns[UIP_CONNS]; ++uip_conn) {
    if(uip_conn->tcpstateflags != CLOSED &&
       BUF->srcipaddr[0] == uip_conn->ripaddr[0] &&
       BUF->srcipaddr[1] == uip_conn->ripaddr[1] &&
       BUF->destport == uip_conn->lport &&
       BUF->srcport == uip_conn->rport)
      goto found;    
  }

  /* If we didn't find and active connection that expected the packet,
     either this packet is an old duplicate, or this is a SYN packet
     destined for a connection in LISTEN. If the SYN flag isn't set,
     it is an old packet and we send a RST. */
  if(BUF->flags != TCP_SYN)
    goto reset;
  
  tmpport = BUF->destport;
  /* Next, check listening connections. */  
  for(c = 0; c < UIP_LISTENPORTS && uip_listenports[c] != 0; ++c) {
    if(tmpport == uip_listenports[c])
      goto found_listen;
  }
  
  /* No matching connection found, so we send a RST packet. */
  UIP_STAT(++uip_stat.tcp.synrst);
 reset:

  /* We do not send resets in response to resets. */
  if(BUF->flags & TCP_RST) 
    goto drop;

  UIP_STAT(++uip_stat.tcp.rst);
  
  BUF->flags = TCP_RST | TCP_ACK;
  uip_len = 40;
  BUF->tcpoffset = 5 << 4;

  /* Flip the seqno and ackno fields in the TCP header. */
  c = BUF->seqno[3];
  BUF->seqno[3] = BUF->ackno[3];  
  BUF->ackno[3] = c;
  
  c = BUF->seqno[2];
  BUF->seqno[2] = BUF->ackno[2];  
  BUF->ackno[2] = c;
  
  c = BUF->seqno[1];
  BUF->seqno[1] = BUF->ackno[1];
  BUF->ackno[1] = c;
  
  c = BUF->seqno[0];
  BUF->seqno[0] = BUF->ackno[0];  
  BUF->ackno[0] = c;

  /* We also have to increase the sequence number we are
     acknowledging. If the least significant byte overflowed, we need
     to propagate the carry to the other bytes as well. */
  if(++BUF->ackno[3] == 0) {
    if(++BUF->ackno[2] == 0) {
      if(++BUF->ackno[1] == 0) {
	++BUF->ackno[0];
      }
    }
  }
 
  /* Swap port numbers. */
  tmpport = BUF->srcport;
  BUF->srcport = BUF->destport;
  BUF->destport = tmpport;
  
  /* Swap IP addresses. */
  tmpport = BUF->destipaddr[0];
  BUF->destipaddr[0] = BUF->srcipaddr[0];
  BUF->srcipaddr[0] = tmpport;
  tmpport = BUF->destipaddr[1];
  BUF->destipaddr[1] = BUF->srcipaddr[1];
  BUF->srcipaddr[1] = tmpport;

  /* And send out the RST packet! */
  goto tcp_send_noconn;

  /* This label will be jumped to if we matched the incoming packet
     with a connection in LISTEN. In that case, we should create a new
     connection and send a SYNACK in return. */
 found_listen:
  /* First we check if there are any connections avaliable. Unused
     connections are kept in the same table as used connections, but
     unused ones have the tcpstate set to CLOSED. */
  for(c = 0; c < UIP_CONNS; ++c) {
    if(uip_conns[c].tcpstateflags == CLOSED) 
      goto found_unused_connection;
  }
  for(c = 0; c < UIP_CONNS; ++c) {
    if(uip_conns[c].tcpstateflags == TIME_WAIT) 
      goto found_unused_connection;
  }
  /* All connections are used already, we drop packet and hope that
     the remote end will retransmit the packet at a time when we have
     more spare connections. */
  UIP_STAT(++uip_stat.tcp.syndrop);
  UIP_LOG("tcp:con");
  goto drop;

  /* This label will be jumped to if we have found an unused
     connection that we can use. */
 found_unused_connection:
  uip_conn = &uip_conns[c];

  /* Fill in the necessary fields for the new connection. */
  uip_conn->timer = UIP_RTO;
  uip_conn->nrtx = 0;
  uip_conn->lport = BUF->destport;
  uip_conn->rport = BUF->srcport;
  uip_conn->ripaddr[0] = BUF->srcipaddr[0];
  uip_conn->ripaddr[1] = BUF->srcipaddr[1];
  uip_conn->tcpstateflags = SYN_RCVD | UIP_OUTSTANDING;

  uip_conn->snd_nxt[0] = uip_conn->ack_nxt[0] = iss[0];
  uip_conn->snd_nxt[1] = uip_conn->ack_nxt[1] = iss[1];
  uip_conn->snd_nxt[2] = uip_conn->ack_nxt[2] = iss[2];
  uip_conn->snd_nxt[3] = uip_conn->ack_nxt[3] = iss[3];
  uip_add_ack_nxt(1);

  /* rcv_nxt should be the seqno from the incoming packet + 1. */
  uip_conn->rcv_nxt[3] = BUF->seqno[3];
  uip_conn->rcv_nxt[2] = BUF->seqno[2];
  uip_conn->rcv_nxt[1] = BUF->seqno[1];
  uip_conn->rcv_nxt[0] = BUF->seqno[0];
  uip_add_rcv_nxt(1);


  /* Parse the TCP MSS option, if present. */
  if((BUF->tcpoffset & 0xf0) > 0x50) {
    for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
      opt = uip_buf[40 + UIP_LLH_LEN + c];
      if(opt == 0x00) {
	/* End of options. */	
	break;
      } else if(opt == 0x01) {
	++c;
	/* NOP option. */
      } else if(opt == 0x02 &&
		uip_buf[40 + UIP_LLH_LEN + c + 1] == 0x04) {
	/* An MSS option with the right option length. */	
	tmpport = (uip_buf[40 + UIP_LLH_LEN + c + 2] << 8) |
	  uip_buf[40 + UIP_LLH_LEN + c + 3];
	uip_conn->mss = tmpport > UIP_TCP_MSS? UIP_TCP_MSS: tmpport;
	
	/* And we are done processing options. */
	break;
      } else {
	/* All other options have a length field, so that we easily
	   can skip past them. */
	c += uip_buf[40 + UIP_LLH_LEN + c + 1];
      }      
    }
  }
  
  /* Our response will be a SYNACK. */
#if UIP_ACTIVE_OPEN
 tcp_send_synack:
  BUF->flags = TCP_ACK;    
  
 tcp_send_syn:
  BUF->flags |= TCP_SYN;    
#else /* UIP_ACTIVE_OPEN */
 tcp_send_synack:
  BUF->flags = TCP_SYN | TCP_ACK;    
#endif /* UIP_ACTIVE_OPEN */
  
  /* We send out the TCP Maximum Segment Size option with our
     SYNACK. */
  BUF->optdata[0] = 2;
  BUF->optdata[1] = 4;
  BUF->optdata[2] = (UIP_TCP_MSS) / 256;
  BUF->optdata[3] = (UIP_TCP_MSS) & 255;
  uip_len = 44;
  BUF->tcpoffset = 6 << 4;
  goto tcp_send;

  /* This label will be jumped to if we found an active connection. */
 found:
  uip_flags = 0;

  /* We do a very naive form of TCP reset processing; we just accept
     any RST and kill our connection. We should in fact check if the
     sequence number of this reset is wihtin our advertised window
     before we accept the reset. */
  if(BUF->flags & TCP_RST) {
    uip_conn->tcpstateflags = CLOSED;
    UIP_LOG("tcp:r");
    uip_flags = UIP_ABORT;
    UIP_APPCALL();
    goto drop;
  }
  /* All segments that are come thus far should have the ACK flag set,
     otherwise we drop the packet. */
  if(!(BUF->flags & TCP_ACK)) {
    UIP_STAT(++uip_stat.tcp.drop);
    UIP_STAT(++uip_stat.tcp.ackerr);
    UIP_LOG("tcp:na");
    goto drop;
  }
      
  /* Calculated the length of the data, if the application has sent
     any data to us. */

⌨️ 快捷键说明

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