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

📄 tcpout.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
          */
         flags &= ~TH_FIN; /* don't FIN on segment prior to last */
      }

      /* limit send to this packet's data */
      if(len > (int)sendp->m_len)
         len = (int)sendp->m_len;
   }
   else  /* no data to send, get an empty packet */
   {
sentall:
      /* big enough for headers and options */
      sendp = tcp_pktalloc(MaxLnh + TCPIPHDR_SIZE + optlen);
      if(sendp == NULL)
         return ENOBUFS;
   }
   EXIT_CRIT_SECTION(tp);

   /* set pointers to TCP and IP headers */
   pip = (struct ip *)(sendp->nb_buff + MaxLnh);
   ptcp = (struct tcphdr *)(pip + 1);

   /* Don't send partial packets. tcp_send() should have made sure
    * that the packets all fit into the other guy's TCP_MSS. If
    * his window is smaller than both our send size and his MSS, treat it
    * as a silly window and send no data.
    */
   if(len < (int)sendp->m_len)
   {
      if(!tp->t_force)
         len = (int)sendp->m_len; /* send whole packet as window probe */
      else
         len = 0;    /* else don't send any data */
   }

#ifdef NPDEBUG
   if (len) 
   {
      if (tp->t_force)
      {
         TCP_STAT_INC(tcps_sndprobe);
      }
      else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) 
      {
         TCP_STAT_INC(tcps_sndrexmitpack);
         TCP_STAT_ADD(tcps_sndrexmitbyte, len);
      } 
      else 
      {
         TCP_STAT_INC(tcps_sndpack);
         TCP_STAT_ADD(tcps_sndbyte, len);
      }
   }
   else if (tp->t_flags & TF_ACKNOW)
      TCP_STAT_INC(tcps_sndacks);
   else if (flags & (TH_SYN|TH_FIN|TH_RST))
      TCP_STAT_INC(tcps_sndctrl);
   else if (SEQ_GT(tp->snd_up, tp->snd_una))
      TCP_STAT_INC(tcps_sndurg);
   else
      TCP_STAT_INC(tcps_sndwinup);
#endif /* NET_STATS */

   /* prepend TCP/IP header in the space provided. */
   MEMCPY((char*)pip, (char*)tp->t_template, TCPIPHDR_SIZE);

   /*
    * Fill in fields, remembering maximum advertised
    * window for use in delaying messages about window sizes.
    * If resending a FIN, be sure not to use a new sequence number.
    */
   if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 
       tp->snd_nxt == tp->snd_max)
   {
      tp->snd_nxt--;
   }

   /* send tcp packets seq & ack fields */
   if((tp->t_flags & TF_SENDKEEP) && (len == 0))
   {
      /* set seq for a BSD-ish keepalive */
      ptcp->th_seq = htonl(tp->snd_nxt);
   }
   else  /* not a keepalive */
   {
      ptcp->th_seq = htonl(tp->snd_nxt);
   }
   ptcp->th_ack = htonl(tp->rcv_nxt);

   /*
    * If we're sending a SYN, check the IP address of the interface
    * that we will (likely) use to send the IP datagram -- if it's
    * changed from what is in the template (as it might if this is
    * a retransmission, and the original SYN caused PPP to start
    * bringing the interface up, and PPP has got a new IP address
    * via IPCP), update the template and the inpcb with the new 
    * address.
    */
   if (flags & TH_SYN)
   {
      ip_addr src = ip_mymach(pip->ip_src);

      if (src != pip->ip_src)
      {
         pip->ip_src = src;
         tp->t_template->ti_i.ip_src = src;
         so->lhost = src;
      }
   }

   /* fill in any required options. Since we only use the MSS option 
    * we never have to send a packet with both options and data. We
    * take advantage of this and put the options in the tcp data area
    * pointed to by datap. 
    */
   if (opt) 
   {
      if(len)
      {
         dtrap("tcpout 3\n");
      }
      MEMCPY(sendp->m_data, opt, optlen);   /* copy in options */
      sendp->m_data += optlen;

      /* use portable macro to set tcp data offset bits */
      SET_TH_OFF((*ptcp), ((sizeof (struct tcphdr) + optlen) >> 2));
   }

   ptcp->th_flags = (u_char)flags;
   /*
    * Calculate receive window.  Don't shrink window,
    * but avoid silly window syndrome.
    */
   if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
      win = (int)(tp->rcv_adv - tp->rcv_nxt);
   if (win > IP_MAXPACKET)
      win = IP_MAXPACKET;

   /* do check for Iniche buffer limits -JB- */
   if (bigfreeq.q_len == 0)   /* If queue length is 0, set window to 0 */
   {
      win = 0;
   }
   else if(win > (((long)bigfreeq.q_len - 1) * (long)bigbufsiz))
   {
      win = ((int)bigfreeq.q_len - 1) * bigbufsiz;
   }

   ptcp->th_win = htons((u_short)win);
   if (SEQ_GT(tp->snd_up, tp->snd_nxt)) 
   {
      ptcp->th_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
      ptcp->th_flags |= TH_URG;
   }
   else
   {
      /*
       * If no urgent pointer to send, then we pull
       * the urgent pointer to the left edge of the send window
       * so that it doesn't drift into the send window on sequence
       * number wraparound.
       */
      tp->snd_up = tp->snd_una;        /* drag it along */
   }

   /*
    * If anything to send and we can send it all, set PUSH.
    * (This will keep happy those implementations which only
    * give data to the user when a buffer fills or a PUSH comes in.)
    */
   if (len && ((off + len) == (int)so->sendq.sb_cc))
      ptcp->th_flags |= TH_PUSH;

   /*
    * In transmit state, time the transmission and arrange for
    * the retransmit.  In persist state, just set snd_max.
    */
   if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) 
   {
      tcp_seq startseq = tp->snd_nxt;

      /*
       * Advance snd_nxt over sequence space of this segment.
       */
      if (flags & TH_SYN)
         tp->snd_nxt++;

      if (flags & TH_FIN)
      {
         tp->snd_nxt++;
         tp->t_flags |= TF_SENTFIN;
      }
      tp->snd_nxt += len;
      if (SEQ_GT(tp->snd_nxt, tp->snd_max)) 
      {
         tp->snd_max = tp->snd_nxt;
         /*
          * Time this transmission if not a retransmission and
          * not currently timing anything.
          */
         if (tp->t_rtt == 0) 
         {
            tp->t_rtt = 1;
            tp->t_rtseq = startseq;
            TCP_STAT_INC(tcps_segstimed);
         }
      }

      /*
       * Set retransmit timer if not currently set,
       * and not doing an ack or a keep-alive probe.
       * Initial value for retransmit timer is smoothed
       * round-trip time + 2 * round-trip time variance.
       * Initialize shift counter which is used for backoff
       * of retransmit time.
       */
      if (tp->t_timer[TCPT_REXMT] == 0 &&
          tp->snd_nxt != tp->snd_una) 
      {
         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
         if (tp->t_timer[TCPT_PERSIST]) 
         {
            tp->t_timer[TCPT_PERSIST] = 0;
            tp->t_rxtshift = 0;
         }
      }
   }
   else if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
         tp->snd_max = tp->snd_nxt + len;

#ifdef DO_TCPTRACE
   tcp_trace("tcp_output: sending, state %d, tcpcb: %x",
    tp->t_state, tp );
#endif

   /* If packet has data then increment the use counter so that
    * the ip_write does not put the packet in the free queue. Don't
    * bump this if the packet is a resend.
    */
   if((len > 0) && (sendp->inuse < 2))
      sendp->inuse++;

   /* Set pkt pointers & lengths and send to IP level. */
   sendp->nb_prot = (char*)ptcp;
   sendp->nb_plen = (len + optlen + sizeof(struct tcphdr));

   /* fill in TCP checksum - first fixup IP header fields which 
    * figure into checksum. IP addrs are already done.
    */
   pip->ip_ver_ihl = 0x45;
   len = sendp->nb_plen + sizeof(struct ip); /* IP length */
   pip->ip_len = htons((unshort)len);
   pip->ip_prot = TCPTP;
   ptcp->th_sum = tcp_cksum(pip);      /* fill in checksum */

   /* send the packet */
   sendp->fhost = pip->ip_dest;        /* pass fhost to IP layer */
   error = ip_write(TCPTP, sendp);     /* send to IP */

   if (error)
      return (error);

   TCP_MIB_INC(tcpOutSegs);   /* keep MIB stats */
   TCP_STAT_INC(tcps_sndtotal);

   /*
    * Data sent (as far as we can tell).
    * If this advertises a larger window than any other segment,
    * then remember the size of the advertised window.
    * Any pending ACK has now been sent.
    */
   if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
      tp->rcv_adv = tp->rcv_nxt + (unsigned)win;
   tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
   if (sendalot)
      goto again;
   return (0);
}


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

void
tcp_setpersist(struct tcpcb * tp)
{
   int   t;

   t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;

   if (tp->t_timer[TCPT_REXMT])
      panic("tcp_output REXMT");

   /* Start/restart persistance timer. */
   TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], (short)(t * tcp_backoff[tp->t_rxtshift]),
      TCPTV_PERSMIN, TCPTV_PERSMAX);

   if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
      tp->t_rxtshift++;

}

/* end of file tcp_out.c */



⌨️ 快捷键说明

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