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

📄 tcpin.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
   /*
    * Segment received on connection.
    * Reset idle time and keep-alive timer.
    */
   tp->t_idle = 0;
   tp->t_timer[TCPT_KEEP] = tcp_keepidle;

   /*
    * Process options if not in LISTEN state,
    * else do it below (after getting remote address).
    */
   if (opts && (tp->t_state != TCPS_LISTEN) )
   {
      m_tcpoptions(tp, opts, optlen);
      opts = NULL;
   }

   /*
    * Calculate amount of space in receive window,
    * and then do TCP input processing.
    * Receive window is amount of space in rcv queue,
    * but not less than advertised window.
    */
   { int win;

      win = mt_defrxwin - so->rcvdq.sb_cc;
      if (win < 0)
         win = 0;
      tp->rcv_wnd = (u_short)MAX(win, (int)(tp->rcv_adv - tp->rcv_nxt));
   }
#if DebugTcpin <= 0x03
    Printu("tcp2\t");
#endif
   switch (tp->t_state)
   {

   /*
    * If the state is LISTEN then ignore segment if it contains an RST.
    * If the segment contains an ACK then it is bad and send a RST.
    * If it does not contain a SYN then it is not interesting; drop it.
    * Don't bother responding if the destination was a broadcast.
    * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
    * tp->iss, and send a segment:
    *     <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
    * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
    * Fill in remote peer address fields if not previously specified.
    * Enter SYN_RECEIVED state, and process any other fields of this
    * segment in this state.
    */
   case TCPS_LISTEN:
      {
         //Printu("TCPS_LISTEN\r\n");
         if (tiflags & TH_RST)
            GOTO_DROP;
         if (tiflags & TH_ACK)
            GOTO_DROPWITHRESET;
         if ((tiflags & TH_SYN) == 0)
            GOTO_DROP;

         mask = ~pkt->net->snmask;   /* mask for broadcast detection */
         if((pip->ip_dest & mask) == mask)
            GOTO_DROP;


         /* fill in IP connection info */
         so->fhost = pip->ip_src;
         so->fport = ptcp->th_sport;
         so->lhost = pkt->net->n_ipaddr;  /* our local address */

         so->ifp = pkt->net;     /* set interface for conn.*/
         m_template(tp);         /* set up header template for tcp sends */
         if(opts)
            m_tcpoptions(tp, opts, optlen);

         if (iss)
            tp->iss = iss;
         else
            tp->iss = tcp_iss;
         tcp_iss += (unsigned)(TCP_ISSINCR/2);
         tp->irs = ptcp->th_seq;
         tcp_sendseqinit(tp);
         tcp_rcvseqinit(tp);
         tp->t_flags |= TF_ACKNOW;
         tp->t_state = TCPS_SYN_RECEIVED;
         tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
         dropsocket = 0;      /* committed to socket */
         TCP_STAT_INC(tcps_accepts);
         goto trimthenstep6;
      }

   /*
    * If the state is SYN_SENT:
    *   if seg contains an ACK, but not for our SYN, drop the input.
    *   if seg contains a RST, then drop the connection.
    *   if seg does not contain SYN, then drop it.
    * Otherwise this is an acceptable SYN segment
    *   initialize tp->rcv_nxt and tp->irs
    *   if seg contais ack then advance tp->snd_una
    *   if SYN has been acked change to ESTABLISHED else SYN_RCVD state
    *   arrange for segment to be acked (eventually)
    *   continue processing rest of data/controls, beginning with URG
    */
   case TCPS_SYN_SENT:
#if DebugTcpin <= 0x03
      Printu("TCPS_SYN_SENT\r\n");
#endif
      so->ifp = pkt->net;     /* set interface for conn.*/
      if ((tiflags & TH_ACK) &&
          (SEQ_LEQ(ptcp->th_ack, tp->iss) ||
          SEQ_GT(ptcp->th_ack, tp->snd_max)))
      {
         GOTO_DROPWITHRESET;
      }
      if (tiflags & TH_RST)
      {
         if (tiflags & TH_ACK)
            m_tcpdrop(tp, ECONNREFUSED);
         GOTO_DROP;
      }
      if ((tiflags & TH_SYN) == 0)
         GOTO_DROP;
      if (tiflags & TH_ACK)
      {
         tp->snd_una = ptcp->th_ack;
         if (SEQ_LT(tp->snd_nxt, tp->snd_una))
            tp->snd_nxt = tp->snd_una;
      }
      tp->t_timer[TCPT_REXMT] = 0;
      tp->irs = ptcp->th_seq;
      tcp_rcvseqinit(tp);
      if (so->lhost != pip->ip_dest)
      {
         /*
          * the IP interface may have changed address since we sent our SYN
          * (e.g. PPP brings link up as a result of said SYN and gets new
          * address via IPCP); if so we need to update the inpcb and the
          * TCP header template with the new address.
          */
         if (pkt->net->n_ipaddr == pip->ip_dest)
         {
            so->lhost = pip->ip_dest;
            tp->t_template->ti_i.ip_src = pip->ip_dest;
         }
      }
      tp->t_flags |= TF_ACKNOW;
      if ((tiflags & TH_ACK) && SEQ_GT(tp->snd_una, tp->iss))
      {
         TCP_MIB_INC(tcpActiveOpens);     /* keep MIB stats */
         TCP_STAT_INC(tcps_connects);
         tp->t_state = TCPS_ESTABLISHED;
         m_connected (so);
         tp->t_maxseg = MIN(tp->t_maxseg, TCP_MSS);

         /*
          * if we didn't have to retransmit the SYN,
          * use its rtt as our initial srtt & rtt var.
          */
         if (tp->t_rtt)
         {
            tp->t_srtt = tp->t_rtt << 3;
            tp->t_rttvar = tp->t_rtt << 1;
            TCPT_RANGESET(tp->t_rxtcur,
             (short)(((tp->t_srtt >> 2) + tp->t_rttvar) >> 1),
             TCPTV_MIN, TCPTV_REXMTMAX);
            tp->t_rtt = 0;
         }
      } else
         tp->t_state = TCPS_SYN_RECEIVED;

trimthenstep6:
      /* Advance ptcp->th_seq to correspond to first data byte. */
      ptcp->th_seq++;

      tp->snd_wl1 = ptcp->th_seq - 1;
      tp->rcv_up = ptcp->th_seq;
      goto step6;
   }

   /*
    * States other than LISTEN or SYN_SENT.
    * First check that at least some bytes of segment are within
    * receive window.  If segment begins before rcv_nxt,
    * drop leading data (and SYN); if nothing left, just ack.
    */
   todrop = (int)(tp->rcv_nxt - ptcp->th_seq);
   if (todrop > 0)
   {
      if (tiflags & TH_SYN)
      {
         tiflags &= ~TH_SYN;
         ptcp->th_seq++;
         if (ptcp->th_urp > 1)
            ptcp->th_urp--;
         else
            tiflags &= ~TH_URG;
         todrop--;
      }

      if ((todrop > (int)pkt->m_len) ||
          ((todrop == (int)pkt->m_len) && ( tiflags&TH_FIN) == 0))
      {
         TCP_STAT_INC(tcps_rcvduppack);
         TCP_STAT_ADD(tcps_rcvdupbyte, pip->ip_len);
         /*
          * If segment is just one to the left of the window,
          * check two special cases:
          * 1. Don't toss RST in response to 4.2-style keepalive.
          * 2. If the only thing to drop is a FIN, we can drop
          *    it, but check the ACK or we will get into FIN
          *    wars if our FINs crossed (both CLOSING).
          * In either case, send ACK to resynchronize,
          * but keep on processing for RST or ACK.
          */
         if ((tiflags & TH_FIN && todrop == (int)pip->ip_len + 1) ||
            (tiflags & TH_RST && ptcp->th_seq == tp->rcv_nxt - 1))
         {
            todrop = pip->ip_len;
            tiflags &= ~TH_FIN;
            tp->t_flags |= TF_ACKNOW;
         }
         else
            goto dropafterack;
      }
      else
      {
         TCP_STAT_INC(tcps_rcvpartduppack);
         TCP_STAT_ADD(tcps_rcvpartdupbyte, todrop);
      }
#ifdef NPDEBUG
      if(todrop > (int)pkt->m_len)  /* sanity test */
      {
/*       dtrap("tcpin 2\n");*/ /* (yaxon del) */
         todrop = pkt->m_len;
      }
#endif
      if(todrop)
      {
#if DebugTcpin <= 0x03
         Printu("todrop:%d\r\n",todrop);
#endif
         pkt->m_len -= todrop;    /* trim received packet data */
         pkt->m_data += todrop;
         ptcp->th_seq += todrop;
         pip->ip_len -= (u_short)todrop;
      }
      if (ptcp->th_urp > (u_short)todrop)
         ptcp->th_urp -= (u_short)todrop;
      else
      {
         tiflags &= ~TH_URG;
         ptcp->th_urp = 0;
      }
   }

#ifdef NOTDEF  /* this test looks broken in the BSD code too -JB- */
   /*
    * If new data are received on a connection after the
    * user processes are gone, then RST the other end.
    */
   if ((tp->t_state > TCPS_CLOSE_WAIT) && pip->ip_len)
   {
      m_tcpclose(tp);
      TCP_STAT_INC(tcps_rcvafterclose);
      GOTO_DROPWITHRESET;
   }
#endif   /* NOTDEF */

   /*
    * If segment ends after window, drop trailing data
    * (and PUSH and FIN); if nothing left, just ACK.
    */
   todrop = (int)((ptcp->th_seq + (short)pip->ip_len) - (tp->rcv_nxt + tp->rcv_wnd));
   if (todrop > 0)
   {
      TCP_STAT_INC(tcps_rcvpackafterwin);
      if (todrop >= (int)pip->ip_len)
      {
         TCP_STAT_ADD(tcps_rcvbyteafterwin, pip->ip_len);
         /*
          * If a new connection request is received
          * while in TIME_WAIT, drop the old connection
          * and start over if the sequence numbers
          * are above the previous ones.
          */
         if (tiflags & TH_SYN &&
             tp->t_state == TCPS_TIME_WAIT &&
             SEQ_GT(ptcp->th_seq, tp->rcv_nxt))
         {
            iss = (tcp_seq)(tp->rcv_nxt + (TCP_ISSINCR));
            if (iss & 0xff000000)
            {
/*             dtrap("tcpin 3\n");     tmp, remove later???? -JB */ /* (yaxon del) */
               iss = 0L;
            }
            m_tcpclose(tp);
            goto findpcb;
         }
         /*
          * If window is closed can only take segments at
          * window edge, and have to drop data and PUSH from
          * incoming segments.  Continue processing, but
          * remember to ack.  Otherwise, drop segment
          * and ack.
          */
         if (tp->rcv_wnd == 0 && ptcp->th_seq == tp->rcv_nxt)
         {
            tp->t_flags |= TF_ACKNOW;
            TCP_STAT_INC(tcps_rcvwinprobe);
         } else
            goto dropafterack;
      } else
         TCP_STAT_ADD(tcps_rcvbyteafterwin, todrop);

      pip->ip_len -= (u_short)todrop;  /* trim data from end of packet */
      tiflags &= ~(TH_PUSH|TH_FIN);
   }

   /*
    * If the RST bit is set examine the state:
    *    SYN_RECEIVED STATE:
    *   If passive open, return to LISTEN state.
    *   If active open, inform user that connection was refused.
    *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
    *   Inform user that connection was reset, and close tcb.
    *    CLOSING, LAST_ACK, TIME_WAIT STATES
    *   Close the tcb.
    */
#if DebugTcpin <= 0x03
   Printu("tcp TH_RSHCHECK\r\n");
#endif
   if (tiflags & TH_RST)
      switch (tp->t_state)
   {

   case TCPS_SYN_RECEIVED:
      so->error = ECONNREFUSED;
      goto close;

   case TCPS_ESTABLISHED:
      TCP_MIB_INC(tcpEstabResets);     /* keep MIB stats */
   case TCPS_FIN_WAIT_1:
   case TCPS_FIN_WAIT_2:
   case TCPS_CLOSE_WAIT:
      so->error = ECONNRESET;
      close:
      tp->t_state = TCPS_CLOSED;
      TCP_STAT_INC(tcps_drops);
      m_tcpclose(tp);
      if (so->callback)
         so->callback(M_CLOSED, so, NULL);
      GOTO_DROP;

   case TCPS_CLOSING:
   case TCPS_LAST_ACK:
   case TCPS_TIME_WAIT:
      m_tcpclose(tp);
      GOTO_DROP;
   }

   /*
    * If a SYN is in the window, then this is an
    * error and we send an RST and drop the connection.
    */
   if (tiflags & TH_SYN)
   {
      m_tcpdrop(tp, ECONNRESET);
      GOTO_DROPWITHRESET;
   }

   /*
    * If the ACK bit is off we drop the segment and return.
    */
   if ((tiflags & TH_ACK) == 0)
      GOTO_DROP;

   /*
    * Ack processing.
    */
#if DebugTcpin <= 0x03
   Printu("tcp ack\r\n");
#endif
   switch (tp->t_state)
   {

   /*
    * In SYN_RECEIVED state if the ack ACKs our SYN then enter
    * ESTABLISHED state and continue processing, otherwise
    * send an RST.
    */
   case TCPS_SYN_RECEIVED:
      if (SEQ_GT(tp->snd_una, ptcp->th_ack) ||
          SEQ_GT(ptcp->th_ack, tp->snd_max))
      {
         TCP_MIB_INC(tcpEstabResets);     /* keep MIB stats */
         GOTO_DROPWITHRESET;
      }
      TCP_STAT_INC(tcps_connects);
      TCP_MIB_INC(tcpPassiveOpens);     /* keep MIB stats */
      tp->t_state = TCPS_ESTABLISHED;
      m_connected(so);
      tp->t_maxseg = MIN(tp->t_maxseg, TCP_MSS);
      tp->snd_wl1 = ptcp->th_seq - 1;
      /* fall into ... */

   /*
    * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
    * ACKs.  If the ack is in the range
    *   tp->snd_una < ptcp->th_ack <= tp->snd_max
    * then advance tp->snd_una to ptcp->th_ack and drop
    * data from the retransmission queue.  If this ACK reflects
    * more up to date window information we update our window information.
    */
   case TCPS_ESTABLISHED:
   case TCPS_FIN_WAIT_1:
   case TCPS_FIN_WAIT_2:
   case TCPS_CLOSE_WAIT:
   case TCPS_CLOSING:
   case TCPS_LAST_ACK:
   case TCPS_TIME_WAIT:

      if (SEQ_LEQ(ptcp->th_ack, tp->snd_una))
      {
         if (pip->ip_len == 0 && ptcp->th_win == tp->snd_wnd)
         {
            TCP_STAT_INC(tcps_rcvdupack);
            /*
             * If we have outstanding data (not a
             * window probe), this is a completely
             * duplicate ack (ie, window info didn't
             * change), the ack is the biggest we've
             * seen and we've seen exactly our rexmt
             * threshhold of them, assume a packet
             * has been dropped and retransmit it.
             * Kludge snd_nxt & the congestion
             * window so we send only this one
             * packet.  If this packet fills the
             * only hole in the receiver's seq.
             * space, the next real ack will fully
             * open our window.  This means we
             * have to do the usual slow-start to
             * not overwhelm an intermediate gateway
             * with a burst of packets.  Leave
             * here with the congestion window set
             * to allow 2 packets on the next real
             * ack and the exp-to-linear thresh
             * set for half the current window
             * size (since we know we're losing at
             * the current window size).
             */
            if (tp->t_timer[TCPT_REXMT] == 0 ||
                ptcp->th_ack != tp->snd_una)
            {
               tp->t_dupacks = 0;
            }
            else if (++tp->t_dupacks == tcprexmtthresh)
            {
               tcp_seq onxt = tp->snd_nxt;
               u_short  win   =
               MIN(tp->snd_wnd, tp->snd_cwnd) / 2 /
               tp->t_maxseg;

               if (win < 2)
                  win = 2;
               tp->snd_ssthresh = (u_short)(win * tp->t_maxseg);

               tp->t_timer[TCPT_REXMT] = 0;
               tp->t_rtt = 0;
               tp->snd_nxt = ptcp->th_ack;
               tp->snd_cwnd = tp->t_maxseg;
               (void) tcp_output(tp);

               if (SEQ_GT(onxt, tp->snd_nxt))
                  tp->snd_nxt = onxt;

⌨️ 快捷键说明

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