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

📄 tcpin.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
#pragma  O0      // yaxon add
/*
 * FILENAME: tcp_in.c
 *
 * Copyright 1997- 2000 By InterNiche Technologies Inc. All rights reserved
 * Version Note: modify by zealea_kuethy   yaxon 2004.04
 *
 * MODULE: INET
 *
 * ROUTINES: m_tcpreass(), tcp_input(), tcp_dooptions(), tcp_xmit_timer(),
 *
 * PORTABLE: yes
 */

/* Additional Copyrights: */
/*
 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */


#include "ipport.h"
#include "mtcp.h"
#include "icmp.h" /* for icmp_destun() declaration */

#include "minip.h"      /* (yaxon add) */
#define DebugTcpin	0xff
#if DebugTcpin <= 0x03
#include "uartdrv.h"
#endif
#include "ZPrint.h"
void tcp_wakeup(void *);/* (yaxon add) */


#define DEBUG_DROP 1
#ifdef DEBUG_DROP  /* trace logic for dropped packets */
int      dropline;
#define  GOTO_DROP   {  dropline=__LINE__;   goto  drop; }
#define  GOTO_DROPWITHRESET   {  dropline=__LINE__;   goto  dropwithreset; }
#else /* the production flavor: */
#define  GOTO_DROP   {  goto  drop; }
#define  GOTO_DROPWITHRESET   {  goto  dropwithreset; }
#endif

char     tcpprintfs  =  0;
char     tcprexmtthresh =  3;
struct   tcpiphdr tcp_saveti;

#ifdef DO_DELAY_ACKS
char     _tcp_delay_ack =  1;
#else
char     _tcp_delay_ack =  0;
#endif   /* DO_DELAY_ACKS */

void  tcp_xmit_timer(struct tcpcb * tp);


/* FUNCTION: m_tcpoptions()
 *
 * Handle TCP options. Only one we do is MSS.
 *
 * PARAM1: struct tcpcb * tp
 * PARAM2: pointer to option string
 * PARAM3: length of option string
 *
 * RETURNS: nothing
 */

void
m_tcpoptions(struct tcpcb * tp, char * opt, int optlen)
{
   /* see if it's mss option and length is valid */
   while(optlen >= 4)
   {
      /* we currently only support max seg size */
      if(*opt == TCPOPT_MAXSEG)
      {
         /* set tcpcb mss to the lesser of passed MSS and our own local MSS */
         tp->t_maxseg = *(u_short *)(opt + 2);
         tp->t_maxseg = ntohs(tp->t_maxseg);
         tp->t_maxseg = (u_short)MIN(tp->t_maxseg, TCP_MSS);
      }
      opt += 4;
      optlen -= 4;
   }
}



/* FUNCTION: m_tcpreass()
 *
 * Mini version of tcp_reass(). Puts passed packets in tcpcb's recevied
 * packet queue. Any packets not in sequence are kept in the tp->oosq,
 * out of sequence queue.
 *
 *
 * PARAM1: struct tcpcb * tp
 *
 * RETURNS: void
 */


void
m_tcpreass(struct tcpcb * tp, struct tcphdr * ptcp, PACKET pkt)
{
   int      offset;     /* offset of this pkt into rcv seq space */
   PACKET   tmp;        /* scratch */
   M_SOCK   so;         /* scratch */
   struct tcpiphdr * ti;/* scratch */
   int      overlap;    /* data overlap with next packet */
   PACKET  pktptr;
   offset = (int)(ptcp->th_seq - tp->rcv_nxt);
   so = (M_SOCK)(tp->t_inpcb);
#if DebugTcpin <= 0x03
   Printu("m_tcpreass pkt->m_len:%d\toffset:%d\r\n",pkt->m_len,offset);
#endif
   /* set flag to ACK received data */
   if (_tcp_delay_ack)
      tp->t_flags |= TF_DELACK;
   else
      tp->t_flags |= TF_ACKNOW;
#if DebugTcpin <= 0x03
   Printu("2\t");
#endif
   if((offset + (int)pkt->m_len) < 0)  /* packet is a duplicate */
   {
      TCP_STAT_INC(tcps_rcvduppack);
      TCP_STAT_ADD(tcps_rcvdupbyte, pkt->m_len );
#if DebugTcpin <= 0x03
      Printu("2return\r\n");
#endif
      return;

   }
#if DebugTcpin <= 0x03
   Printu("3\t");
#endif
   if(offset > 0)     /* packet is ahead of seq space */
   {
      ENTER_CRIT_SECTION(&so->oosq);
/*    dtrap("tcpin 0\n");*/ /* (yaxon del) */
      /* put packet in order in the oos queue */
      tmp = so->oosq.p_head;        /* start at head of queue */
      if(tmp == NULL)      /* no queued OOS packets yet, start que */
      {
#if DebugTcpin <= 0x03
         Printu("Empty list to insert\r\n");
#endif
         so->oosq.p_head = so->oosq.p_tail = pkt;
         so->oosq.sb_cc = pkt->m_len;
         pkt->m_next = NULL;
      }
      else  /* add to existing OOS queue */
      {
         while(offset > (int)tmp->m_len)    /* loop to packet before new one */
         {
            //Printu("offset:%d\tm_len:%d\ttmp->m_next:%x\r\n",offset,tmp->m_len,tmp->m_next);
            offset -= tmp->m_len;
	    if((tmp->m_next) == NULL) {			 //modify by zealea 2004.04
	       //Printu("(tmp->m_next) == NULL\r\n");
	       break;
	    }
	    tmp = tmp->m_next;

         }
         /* tmp is now packet in data space prior to new one */
         pkt->m_next = tmp->m_next;    /* insert pkt into oosq */
         tmp->m_next = pkt;
         so->oosq.sb_cc += pkt->m_len;
      }

      EXIT_CRIT_SECTION(&so->oosq);

      TCP_STAT_INC(tcps_rcvoopack);
      TCP_STAT_ADD(tcps_rcvoobyte, pkt->m_len);
#if DebugTcpin <= 0x03
      Printu("3 return\r\n");
#endif
      return;
   }

   /* fall to here if he packet contains the next data in the seq space.
    * The packet may also contain previously received data at the front.
    */
#if DebugTcpin <= 0x03
   Printu("4\t");
#endif
   if(offset < 0) /* packet contains some new data at end, trim it */
   {
#if DebugTcpin <= 0x03
      Printu("pkt->m_len:%d\toffset:%d\r\n",pkt->m_len,offset);
#endif
      pkt->m_data += offset;
      pkt->m_len -= offset;
      TCP_STAT_ADD(tcps_rcvdupbyte, -((long)offset));
   }

   put_soq(&so->rcvdq, pkt);
   tp->rcv_nxt += pkt->m_len;

   /* see if we can process any Out of Order packets */
   if(so->oosq.sb_cc)
   {
      ENTER_CRIT_SECTION(&so->oosq);
      while(so->oosq.sb_cc)
      {
/*       dtrap("tcpin 1\n");*/ /* (yaxon del) */
#if DebugTcpin <= 0x03
         Printu("so->oosq.sb_cc:%d\r\n",so->oosq.sb_cc);
#endif
         tmp = (PACKET)(so->oosq.p_head);
         ti = (struct tcpiphdr *)(tmp->m_next->nb_buff + MaxLnh);
         overlap = (int)((ptcp->th_seq + pkt->m_len) - ti->ti_seq);
#if DebugTcpin <= 0x03
         Printu("overlap:%d\tpkt->m_len:%d\tptcp->th_seq:%d\r\n",overlap,pkt->m_len,ptcp->th_seq);
#endif
         if(overlap >= 0)
         {
            /* see if next packet is completely covered by new one */
            if(overlap > (int)tmp->m_len)
            {
               pktptr = get_soq(&so->oosq);
#if DebugTcpin <= 0x03
	       Printu("get_soq sb_cc:%d\r\n",so->oosq.sb_cc);
#endif
               if(pktptr==NULL){	      //modify by zealea 2004.04
#if DebugTcpin <= 0x03
	          Printu("non error\r\n");
#endif
		  break;
	       }
               tcp_pktfree(pktptr);  /* dump next oosq pkt */

               continue;
            }
            /* see if next packet is parially covered by new one */
            if(overlap > 0)
            {
               /* adjust data and move tmp from oosq to rcvdq. The data adjustment
                * makes tmp's tcp header seq ovsolete, but that;s OK since we
                * don't need it anymore once it's in rcvdq.
                */
               tmp->m_data += overlap;
               tmp->m_len -= overlap;
#if DebugTcpin <= 0x03
	       Printu("overlaptmp->m_len:%d\r\n",tmp->m_len);
#endif
            }
            /* get here if data in tmp comes exactly after data in pkt */
            pktptr = get_soq(&so->oosq);	  //modify by zealea 2004.04
	    if(pktptr) put_soq(&so->rcvdq, pktptr);  /* move tmp to rvcdq */
#if DebugTcpin <= 0x03
	    Printu("put_soq sb_cc:%d\r\n",so->oosq.sb_cc);
#endif
         }
         else  /* next packet in oosq still in future seq numbers */
            break;
      }
      EXIT_CRIT_SECTION(&so->oosq);
   }
#if DebugTcpin <= 0x03
   Printu("5\r\n");
#endif
   tcp_wakeup(&so->rcvdq);   /* wake any sockets waiting for recv */

   return;
}


/* FUNCTION: tcp_rcv()
 *
 * TCP input routine, follows pages 65-76 of the
 * protocol specification dated September, 1981 very closely.
 *
 *
 * PARAM1: struct mbuf *m0
 * PARAM2: unsigned ifindex
 *
 * RETURNS: int; always SUCCESS (0)
 */

int
tcp_rcv(PACKET pkt)
{
   struct tcphdr * ptcp;
   struct ip *    pip;
   struct tcpcb * tp =  0;
   M_SOCK   so =  NULL;
   ip_addr mask;
   long     iss =  0;
   char *   opts;
   int      optlen = 0;
   int      len,  tlen, off;
   int      tiflags;
   int      todrop,  acked,   ourfinisacked, needoutput  =  0;
   int      dropsocket  =  0;

#ifdef DO_TCPTRACE
   int   ostate;
#endif
#if DebugTcpin <= 0x03
   Printu("tcp0\t");
#endif
   TCP_STAT_INC(tcps_rcvtotal);
   TCP_MIB_INC(tcpInSegs);    /* keep MIB stats */

   pip = (struct ip *)pkt->nb_prot;

   if (pkt->nb_plen < ((sizeof (struct ip) + sizeof (struct tcphdr))))
   {
      TCP_STAT_INC(tcps_rcvshort);
      GOTO_DROP;
   }
   ptcp = (struct tcphdr *)ip_data(pip);

   if (tcp_cksum(pip) != ptcp->th_sum)
   {
      TCP_MIB_INC(tcpInErrs);    /* keep MIB stats */
      TCP_STAT_INC(tcps_rcvbadsum);  /* keep BSD stats */
      GOTO_DROP;
   }

   tlen = htons(pip->ip_len);     /* this was fudged by IP layer */

   /* Check that TCP offset makes sense, */
   off = GET_TH_OFF((*ptcp)) << 2;
   if (off < sizeof (struct tcphdr) || off > tlen)
   {
#ifdef DO_TCPTRACE
      tcp_trace("tcp off: src %x off %d\n", ti->ti_src, off);
#endif
      TCP_STAT_INC(tcps_rcvbadoff);
      TCP_MIB_INC(tcpInErrs);   /* keep MIB stats */
      GOTO_DROP;
   }
   tlen -= (int)off;
   pip->ip_len = (u_short)tlen;  /* ip_len is now length of tcp data */

   /* set options pointer and length */
   if (off > sizeof (struct tcphdr))
   {
      opts = (char *)(ptcp + 1);
      optlen = off - sizeof (struct tcphdr);
      if (pkt->nb_plen < sizeof(struct ip) + off)
      {
         TCP_STAT_INC(tcps_rcvshort);
         GOTO_DROP;
      }
   }
   else     /* no options in packet */
   {
      opts = NULL;      /* use opts as flag for option presence */
      optlen = 0;
   }

   tiflags = ptcp->th_flags;

   /* Drop TCP and IP headers; and any TCP options. */
  // Printu("recv:nb_plen:%d\t",pkt->nb_plen);
   pkt->nb_prot += (TCPIPHDRSZ + optlen);
   pkt->nb_plen -= (TCPIPHDRSZ + optlen);

   /* Set up packet's TCP members. Future reference to TCP data should
    * be done via these:
    */
   pkt->m_data = pkt->nb_prot;
   pkt->m_len = pkt->nb_plen;
  // Printu("recv:m_len:%d\r\n",pkt->m_len);
   /* Convert TCP protocol specific fields to host format. */
#if(BYTE_ORDER == LITTLE_ENDIAN)
   ptcp->th_seq = ntohl(ptcp->th_seq);
   ptcp->th_ack = ntohl(ptcp->th_ack);
   ptcp->th_win = ntohs(ptcp->th_win);
   ptcp->th_urp = ntohs(ptcp->th_urp);
#endif

#ifdef DO_TCPTRACE
   tcp_trace("TCPIN: S:%08lx A:%08lx", ptcp->th_seq, ptcp->th_ack);
   tcp_trace("     : W:%04x  U:%04x F:%02x", ptcp->th_win, ptcp->th_urp, tiflags);
#endif
#if DebugTcpin <= 0x03
  Printu("tcp1\t");
#endif
   /* find the socket for the segment */
findpcb:
   so = so_lookup(pip, ptcp);
   if(so == NULL)
   {
      /* no socket, send ICMP "desination unreachable" packet */
#if DebugTcpin <= 0x03
      Printu("====icmp_destun====\r\n");
#endif
      icmp_destun(pip->ip_src, pip, DSTPORT, pkt->net);
      GOTO_DROPWITHRESET;
   }

   /*
    * If the state is CLOSED (i.e., TCB does not exist) then
    * all data in the incoming segment is discarded.
    * If the TCB exists but is in CLOSED state, it is embryonic,
    * but should either do a listen or a connect soon.
    */
   tp = so->tp;
   if (tp == NULL)
      GOTO_DROPWITHRESET;
   if (tp->t_state == TCPS_CLOSED)
      GOTO_DROP;

#ifdef DO_TCPTRACE
   if (so->so_options & SO_DEBUG)
   {
      ostate = tp->t_state;
      tcp_saveti = *ti;
   }
#endif

   /* see if the matched socket is listening for a new connection */
   if (tp->t_state == TCPS_LISTEN)
   {
      M_SOCK so_new;
      M_SOCK so_tmp;
      struct tcpcb * tp_new;

      /* clone the socket and the tcpcb for new connection. We DONT
       * call m_socket() for this since the NET_RESID is already locked
       * If it's being used in this build.
       */

      so_new = (M_SOCK)SOC_ALLOC(sizeof(struct msocket));
      if (so_new == NULL)
         GOTO_DROP;
      putq(&msoq, so_new);       /* put new socket in queue */

      /* copy listen socket data into new socket. */
      so_tmp = so_new->next;     /* save the link first */
      MEMCPY(so_new, so, sizeof(struct msocket));
      so_new->next = so_tmp;     /* restore the link */
      so = so_new;               /* make the socket the one to use */

      tp_new = m_newtcpcb(so);
      if(tp_new == NULL)
      {
         m_delsocket(so);
         GOTO_DROP;
      }
      tp = tp_new;
      tp->t_state = TCPS_LISTEN;

      /*
       * Mark socket as temporary until we're
       * committed to keeping it.  The code at
       * ``drop'' and ``dropwithreset'' check the
       * flag dropsocket to see if the temporary
       * socket created here should be discarded.
       * We mark the socket as discardable until
       * we're committed to it below in TCPS_LISTEN.
       */
      dropsocket++;
   }

⌨️ 快捷键说明

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