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

📄 tcpin.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
               GOTO_DROP;
            }
         } else
            tp->t_dupacks = 0;
         break;
      }
      tp->t_dupacks = 0;
      if (SEQ_GT(ptcp->th_ack, tp->snd_max))
      {
         TCP_STAT_INC(tcps_rcvacktoomuch);
         goto dropafterack;
      }
      acked = (int)(ptcp->th_ack - tp->snd_una);
      TCP_STAT_INC(tcps_rcvackpack);
      TCP_STAT_ADD(tcps_rcvackbyte, acked);

      /*
       * If transmit timer is running and timed sequence
       * number was acked, update smoothed round trip time.
       * Since we now have an rtt measurement, cancel the
       * timer backoff (cf., Phil Karn's retransmit alg.).
       * Recompute the initial retransmit timer.
       */
      if (tp->t_rtt && SEQ_GT(ptcp->th_ack, tp->t_rtseq))
         tcp_xmit_timer(tp);

      /*
       * If all outstanding data is acked, stop retransmit
       * timer and remember to restart (more output or persist).
       * If there is more data to be acked, restart retransmit
       * timer, using current (possibly backed-off) value.
       */
      if (ptcp->th_ack == tp->snd_max)
      {
         tp->t_timer[TCPT_REXMT] = 0;
         needoutput = 1;
      } else if (tp->t_timer[TCPT_PERSIST] == 0)
         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
      /*
       * When new data is acked, open the congestion window.
       * If the window gives us less than ssthresh packets
       * in flight, open exponentially (maxseg per packet).
       * Otherwise open linearly (maxseg per window,
       * or maxseg^2 / cwnd per packet).
       */
      {
         u_short  cw =  tp->snd_cwnd;
         u_short  incr  =  tp->t_maxseg;

         if (cw > tp->snd_ssthresh)
            incr = MAX( (incr * incr / cw), (ALIGN_TYPE << 2) );

         tp->snd_cwnd = MIN(cw + (u_short)incr, (IP_MAXPACKET));
      }

      /* If he acked more than we have sent assume he's acking a FIN.
       * Note that we can also get into this when receiving ack of syn/ack
       * packet, but that should be harmless.
       */
      if (acked > (int)so->sendq.sb_cc)
      {
         tp->snd_wnd -= (u_short)so->sendq.sb_cc;
         m_sbdrop(&so->sendq, so->sendq.sb_cc);    /* drop everything */
         ourfinisacked = 1;                  /* set local flag */
      }
      else  /* acked some data */
      {
         m_sbdrop(&so->sendq, acked);        /* drop amount he acked */
         tp->snd_wnd -= (u_short)acked;
         ourfinisacked = 0;
         /* callback app in case it's sleeping on send */
        //Printu("call tcp tx back proc\r\n");
         if(so->callback)
            so->callback(M_TXDATA, so, NULL);
      }
    
      /* wake up anybody sleeping on a send */
      if((tp->t_state == TCPS_ESTABLISHED) &&
         (acked > 0))
      {
        //Printu("tcp wakeup\r\n");
         tcp_wakeup(&so->sendq);
      }

      /* update variable for our next seq number from rcvd ack */
      tp->snd_una = ptcp->th_ack;
      if (SEQ_LT(tp->snd_nxt, tp->snd_una))
         tp->snd_nxt = tp->snd_una;

      switch (tp->t_state)
      {

      /*
       * In FIN_WAIT_1 STATE in addition to the processing
       * for the ESTABLISHED state if our FIN is now acknowledged
       * then enter FIN_WAIT_2.
       */
      case TCPS_FIN_WAIT_1:
         if (ourfinisacked)
         {
            /*
             * If we can't receive any more
             * data, then closing user can proceed.
             * Starting the timer is contrary to the
             * specification, but if we don't get a FIN
             * we'll hang forever.
             */
            if (so->state & SS_CANTRCVMORE)
            {
               m_disconnected(so);
               tp->t_timer[TCPT_2MSL] = tcp_maxidle;
            }
            tp->t_state = TCPS_FIN_WAIT_2;
         }
         break;

       /*
       * In CLOSING STATE in addition to the processing for
       * the ESTABLISHED state if the ACK acknowledges our FIN
       * then enter the TIME-WAIT state, otherwise ignore
       * the segment.
       */
      case TCPS_CLOSING:
         if (ourfinisacked)
         {
            tp->t_state = TCPS_TIME_WAIT;
            tcp_canceltimers(tp);
            tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
            m_disconnected(so);
         }
         break;

      /*
       * In LAST_ACK, we may still be waiting for data to drain
       * and/or to be acked, as well as for the ack of our FIN.
       * If our FIN is now acknowledged, delete the TCB,
       * enter the closed state and return.
       */
      case TCPS_LAST_ACK:
         if (ourfinisacked)
         {
            m_tcpclose(tp);
            GOTO_DROP;
         }
         break;

      /*
       * In TIME_WAIT state the only thing that should arrive
       * is a retransmission of the remote FIN.  Acknowledge
       * it and restart the finack timer.
       */
      case TCPS_TIME_WAIT:
         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
         goto dropafterack;
      }
   }

step6:
   /*
    * Update window information.
    * Don't look at window if no ACK: TAC's send garbage on first SYN.
    */
#if DebugTcpin <= 0x03
   Printu("step6\r\n");
#endif
   if ((tiflags & TH_ACK) &&
       (SEQ_LT(tp->snd_wl1, ptcp->th_seq) || tp->snd_wl1 == ptcp->th_seq &&
       (SEQ_LT(tp->snd_wl2, ptcp->th_ack) ||
       tp->snd_wl2 == ptcp->th_ack && ptcp->th_win > tp->snd_wnd)))
   {
      /* keep track of pure window updates */
      if (pip->ip_len == 0 &&
          tp->snd_wl2 == ptcp->th_ack && ptcp->th_win > tp->snd_wnd)
      {
         TCP_STAT_INC(tcps_rcvwinupd);
      }
      tp->snd_wnd = ptcp->th_win;
      tp->snd_wl1 = ptcp->th_seq;
      tp->snd_wl2 = ptcp->th_ack;
      if (tp->snd_wnd > tp->max_sndwnd)
         tp->max_sndwnd = tp->snd_wnd;
      needoutput = 1;
   }

   /*
    * pull receive urgent pointer along
    * with the receive window.
    */
   if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
      tp->rcv_up = tp->rcv_nxt;

   /*
    * Process the segment text, merging it into the TCP sequencing queue,
    * and arranging for acknowledgment of receipt if necessary. If a FIN
    * has already been received on this connection then we just ignore
    * the data.
    *
    * NOTE: this step also involes moving the received packet to a socket
    * queue or back intto the free queue, so the pkt should not be
    * referenced after this.
    */
   if ((pkt->m_len || (tiflags & TH_FIN)) &&
      (TCPS_HAVERCVDFIN(tp->t_state) == 0))
   {
      /* put data packets in the received pkt que */
#if DebugTcpin <= 0x03
      Printu("tcp5 \t");
#endif
      if(pkt->m_len){
#if DebugTcpin <= 0x03
         Printu("11\r\n");
#endif
         m_tcpreass(tp, ptcp, pkt);

      }else{
#if DebugTcpin <= 0x03
         Printu("12\r\n");
#endif
         tcp_pktfree(pkt);

      }
#if DebugTcpin <= 0x03
       Printu("tcp9999\r\n");
#endif
         /*
       * Note the amount of data that peer has sent into
       * our window, in order to estimate the sender's
       * buffer size.
       */
      len = (int)(mt_defrxwin - (tp->rcv_adv - tp->rcv_nxt));
      if (len > (int)tp->max_rcvd)
         tp->max_rcvd = (u_short)len;
      if (so->callback)
      {
#if DebugTcpin <= 0x03
         Printu("ready to call\r\n");
#endif
         m_data_upcall(so);
         /* if we have FIN and app has all data, do shutdown */
         if ((tiflags & TH_FIN) &&
            (so->sendq.sb_cc == 0))
         {
            so->error = ESHUTDOWN;
            /* if sock has callback, do close notify */
            if(so->callback)
               so->callback(M_CLOSED, so, NULL);
            so->state |= SS_UPCFIN;    /* flag that upcall was FINed */
         }
      }

   }
   else
   {
#if DebugTcpin <= 0x03
      Printu("tcp52\r\n");
#endif
      tcp_pktfree(pkt);
      tiflags &= ~TH_FIN;
   }

   /*
    * If FIN is received ACK the FIN and let the user know
    * that the connection is closing.
    */
   if (tiflags & TH_FIN)
   {
#if DebugTcpin <= 0x03
      Printu("tcp fin\r\n");
#endif
      if (TCPS_HAVERCVDFIN(tp->t_state) == 0)
      {
         so->state |= SS_CANTRCVMORE;
         tp->t_flags |= TF_ACKNOW;
         tp->rcv_nxt++;
      }
      switch (tp->t_state)
      {
      /*
       * In SYN_RECEIVED and ESTABLISHED STATES
       * enter the CLOSE_WAIT state.
       */
      case TCPS_SYN_RECEIVED:
      case TCPS_ESTABLISHED:
         tp->t_state = TCPS_CLOSE_WAIT;
         break;

       /*
       * If still in FIN_WAIT_1 STATE FIN has not been acked so
       * enter the CLOSING state.
       */
      case TCPS_FIN_WAIT_1:
         tp->t_state = TCPS_CLOSING;
         break;

       /*
       * In FIN_WAIT_2 state enter the TIME_WAIT state,
       * starting the time-wait timer, turning off the other
       * standard timers.
       */
      case TCPS_FIN_WAIT_2:
         tp->t_state = TCPS_TIME_WAIT;
         tcp_canceltimers(tp);
         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
         so->state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
         so->state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
         tcp_wakeup ((char *)so);
         break;

      /*
       * In TIME_WAIT state restart the 2 MSL time_wait timer.
       */
      case TCPS_TIME_WAIT:
         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
         break;
      }
   }
#ifdef DO_TCPTRACE
   if (so->so_options & SO_DEBUG)
      tcp_trace("TCP_IN: state: %d, tcpcb: %x saveti: %x",
    ostate, tp, &tcp_saveti);
#endif

   /* see if we need to do a connect upcall */
   if((tp->t_flags & TF_OPENUP) &&       /* flag is set */
      (so->callback != NULL))             /* callback exists */
   {
      tp->t_flags &= ~TF_OPENUP;          /* clear flag */
#if DebugTcpin <= 0x03
      PrintFromUART(DebugTcpin,"TF_OPENUP!\n");
#endif
      so->callback(M_OPENOK, so, NULL);   /* notify application */
      /* wake any task which is blocked on connect */
      tcp_wakeup(so);
   }
#if DebugTcpin <= 0x03
   Printu("tcp4\t");
#endif
   /* Return any desired output. */
   if (needoutput || (tp->t_flags & TF_ACKNOW))
      (void) tcp_output(tp);
   return SUCCESS;

dropafterack:
   /*
    * Generate an ACK dropping incoming segment if it occupies
    * sequence space, where the ACK reflects our state.
    */
#if DebugTcpin <= 0x03
   Printu("tcp dropafterack\r\n");
#endif
   if (tiflags & TH_RST)
      GOTO_DROP;
   tcp_pktfree(pkt);
   tp->t_flags |= TF_ACKNOW;
   (void) tcp_output (tp);
   return SUCCESS;

dropwithreset:
#if DebugTcpin <= 0x03
   Printu("tcp dropwithreset\r\n");
#endif
   TCP_MIB_INC(tcpInErrs);    /* keep MIB stats */

   /*
    * Generate a RST, dropping incoming segment.
    * Make ACK acceptable to originator of segment.
    * Don't bother to respond if destination was broadcast.
    */
   if (tiflags & TH_RST)
      GOTO_DROP;

   mask = ~pkt->net->snmask;           /* set mask for broadcast detection */
   if((pip->ip_dest & mask) == mask)   /* don't reset broadcasts */
      GOTO_DROP;

   if(tp == NULL || so == NULL)
   {
/*    dtrap("tcpin 4\n");*/ /* (yaxon del) */
      GOTO_DROP;
   }
   /* If socket is in LISTEN state template is not set */
   if(tp->t_template == NULL)
      GOTO_DROP;

   if (tiflags & TH_SYN)
      tp->snd_nxt++;

   tp->t_flags |= TF_SENDRST; /* force a reset */
   tcp_output(tp);
   TCP_MIB_INC(tcpOutRsts);

drop:
#if DebugTcpin <= 0x03
   Printu("tcp drop\r\n");
#endif
   tcp_pktfree(pkt);

   /* destroy temporarily created socket */
   if (dropsocket)
      m_delsocket(so);
   return SUCCESS;
}



/* FUNCTION: tcp_xmit_timer()
 *
 * PARAM1: struct tcpcb * tp
 *
 * RETURNS:
 */

void
tcp_xmit_timer(struct tcpcb * tp)
{
   short delta;

   TCP_STAT_INC(tcps_rttupdated);
   if (tp->t_srtt != 0)
   {

      /*
       * srtt is stored as fixed point with 3 bits
       * after the binary point (i.e., scaled by 8).
       * The following magic is equivalent
       * to the smoothing algorithm in rfc793
       * with an alpha of .875
       * (srtt = rtt/8 + srtt*7/8 in fixed point).
       * Adjust t_rtt to origin 0.
       */
      delta = (short)(tp->t_rtt - 1 - (tp->t_srtt >> 3));
      if ((tp->t_srtt += delta) <= 0)
         tp->t_srtt = 1;
      /*
       * We accumulate a smoothed rtt variance
       * (actually, a smoothed mean difference),
       * then set the retransmit timer to smoothed
       * rtt + 2 times the smoothed variance.
       * rttvar is stored as fixed point
       * with 2 bits after the binary point
       * (scaled by 4).  The following is equivalent
       * to rfc793 smoothing with an alpha of .75
       * (rttvar = rttvar*3/4 + |delta| / 4).
       * This replaces rfc793's wired-in beta.
       */
      if (delta < 0)
         delta = -delta;
      delta -= (short)(tp->t_rttvar >> 2);
      if ((tp->t_rttvar += delta) <= 0)
         tp->t_rttvar = 1;
   }
   else
   {
      /*
       * No rtt measurement yet - use the
       * unsmoothed rtt.  Set the variance
       * to half the rtt (so our first
       * retransmit happens at 2*rtt)
       */
      tp->t_srtt = tp->t_rtt << 3;
      tp->t_rttvar = tp->t_rtt << 1;
   }
   tp->t_rtt = 0;
   tp->t_rxtshift = 0;
   TCPT_RANGESET(tp->t_rxtcur,
    (short)(((tp->t_srtt >> 2) + tp->t_rttvar) >> 1),
    TCPTV_MIN, TCPTV_REXMTMAX);
}

/* end of file tcp_in.c */


⌨️ 快捷键说明

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