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

📄 tcp.c

📁 lwip在ucos上的移植
💻 C
📖 第 1 页 / 共 3 页
字号:

  DEBUGF(TCP_DEBUG, ("tcp_connect to port %d\n", port));
  if(ipaddr != NULL) {
    pcb->remote_ip = *ipaddr;
  } else {
    return ERR_VAL;
  }
  pcb->remote_port = port;
  if(pcb->local_port == 0) {
    pcb->local_port = tcp_new_port();
  }
  iss = tcp_next_iss();
  pcb->rcv_nxt = 0;
  pcb->snd_nxt = iss;
  pcb->lastack = iss - 1;
  pcb->snd_lbb = iss - 1;
  pcb->rcv_wnd = TCP_WND;
  pcb->snd_wnd = TCP_WND;
  pcb->mss = TCP_MSS;
  pcb->cwnd = 1;
  pcb->ssthresh = pcb->mss * 10;
  pcb->state = SYN_SENT;
  pcb->connected = connected;
  TCP_REG(&tcp_active_pcbs, pcb);
  
  /* Build an MSS option */
  optdata = HTONL(((u32_t)2 << 24) | 
		  ((u32_t)4 << 16) | 
		  (((u32_t)pcb->mss / 256) << 8) |
		  (pcb->mss & 255));

  ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
  if(ret == ERR_OK) { 
    tcp_output(pcb);
  }
  return ret;
} 
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_slowtmr():
 *
 * Called every 500 ms and implements the retransmission timer and the timer that
 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
 * various timers such as the inactivity timer in each PCB.
 */
/*-----------------------------------------------------------------------------------*/
void
tcp_slowtmr(void)
{
  static struct tcp_pcb *pcb, *pcb2, *prev;
  static struct tcp_seg *seg, *useg;
  static u32_t eff_wnd;
  static u8_t pcb_remove;      /* flag if a PCB should be removed */

  ++tcp_ticks;
  
  /* Steps through all of the active PCBs. */
  prev = NULL;
  pcb = tcp_active_pcbs;
  while(pcb != NULL) {
    ASSERT("tcp_timer_coarse: active pcb->state != CLOSED", pcb->state != CLOSED);
    ASSERT("tcp_timer_coarse: active pcb->state != LISTEN", pcb->state != LISTEN);
    ASSERT("tcp_timer_coarse: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);

    pcb_remove = 0;

    if(pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
      ++pcb_remove;
    } else if(pcb->nrtx == TCP_MAXRTX) {
      ++pcb_remove;
    } else {
      ++pcb->rtime;
      seg = pcb->unacked;
      if(seg != NULL && pcb->rtime >= pcb->rto) {
        
        DEBUGF(TCP_RTO_DEBUG, ("tcp_timer_coarse: rtime %ld pcb->rto %d\n",
                               tcp_ticks - pcb->rtime, pcb->rto));

	/* Double retransmission time-out unless we are trying to
           connect to somebody (i.e., we are in SYN_SENT). */
	if(pcb->state != SYN_SENT) {
	  pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
	}

        /* Move all other unacked segments to the unsent queue. */
        if(seg->next != NULL) {
          for(useg = seg->next; useg->next != NULL; useg = useg->next);
          /* useg now points to the last segment on the unacked queue. */
          useg->next = pcb->unsent;
          pcb->unsent = seg->next;
          seg->next = NULL;
          pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
        }

	/* Do the actual retransmission. */
        tcp_rexmit_seg(pcb, seg);

        /* Reduce congestion window and ssthresh. */
        eff_wnd = MIN(pcb->cwnd, pcb->snd_wnd);
        pcb->ssthresh = eff_wnd >> 1;
        if(pcb->ssthresh < pcb->mss) {
          pcb->ssthresh = pcb->mss * 2;
        }
        pcb->cwnd = pcb->mss;

        DEBUGF(TCP_CWND_DEBUG, ("tcp_rexmit_seg: cwnd %u ssthresh %u\n",
                                pcb->cwnd, pcb->ssthresh));
      }
    }
	  
    /* Check if this PCB has stayed too long in FIN-WAIT-2 */
    if(pcb->state == FIN_WAIT_2) {
      if((u32_t)(tcp_ticks - pcb->tmr) >
	 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
        ++pcb_remove;
      }
    }

    /* If this PCB has queued out of sequence data, but has been
       inactive for too long, will drop the data (it will eventually
       be retransmitted). */
#if TCP_QUEUE_OOSEQ    
    if(pcb->ooseq != NULL &&
       (u32_t)tcp_ticks - pcb->tmr >=
       pcb->rto * TCP_OOSEQ_TIMEOUT) {
      tcp_segs_free(pcb->ooseq);
      pcb->ooseq = NULL;
    }
#endif /* TCP_QUEUE_OOSEQ */

    /* Check if this PCB has stayed too long in SYN-RCVD */
    if(pcb->state == SYN_RCVD) {
      if((u32_t)(tcp_ticks - pcb->tmr) >
	 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
        ++pcb_remove;
      }
    }


    /* If the PCB should be removed, do it. */
    if(pcb_remove) {
      tcp_pcb_purge(pcb);      
      /* Remove PCB from tcp_active_pcbs list. */
      if(prev != NULL) {
	ASSERT("tcp_timer_coarse: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
        prev->next = pcb->next;
      } else {
        /* This PCB was the first. */
        ASSERT("tcp_timer_coarse: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
        tcp_active_pcbs = pcb->next;
      }

      if(pcb->errf != NULL) {
	pcb->errf(pcb->callback_arg, ERR_ABRT);
      }

      pcb2 = pcb->next;
      memp_free(MEMP_TCP_PCB, pcb);
      pcb = pcb2;
    } else {

      /* We check if we should poll the connection. */
      ++pcb->polltmr;
      if(pcb->polltmr >= pcb->pollinterval &&
	 pcb->poll != NULL) {
	pcb->polltmr = 0;
	pcb->poll(pcb->callback_arg, pcb);
	tcp_output(pcb);
      }
      
      prev = pcb;
      pcb = pcb->next;
    }
  }

  
  /* Steps through all of the TIME-WAIT PCBs. */
  prev = NULL;    
  pcb = tcp_tw_pcbs;
  while(pcb != NULL) {
    ASSERT("tcp_timer_coarse: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
    pcb_remove = 0;

    /* Check if this PCB has stayed long enough in TIME-WAIT */
    if((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
      ++pcb_remove;
    }
    


    /* If the PCB should be removed, do it. */
    if(pcb_remove) {
      tcp_pcb_purge(pcb);      
      /* Remove PCB from tcp_tw_pcbs list. */
      if(prev != NULL) {
	ASSERT("tcp_timer_coarse: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
        prev->next = pcb->next;
      } else {
        /* This PCB was the first. */
        ASSERT("tcp_timer_coarse: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
        tcp_tw_pcbs = pcb->next;
      }
      pcb2 = pcb->next;
      memp_free(MEMP_TCP_PCB, pcb);
      pcb = pcb2;
    } else {
      prev = pcb;
      pcb = pcb->next;
    }
  }
}
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_fasttmr():
 *
 * Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
 */
/*-----------------------------------------------------------------------------------*/
void
tcp_fasttmr(void)
{
  struct tcp_pcb *pcb;

  /* send delayed ACKs */  
  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
    if(pcb->flags & TF_ACK_DELAY) {
      DEBUGF(TCP_DEBUG, ("tcp_timer_fine: delayed ACK\n"));
      tcp_ack_now(pcb);
      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
    }
  }
}
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_segs_free():
 *
 * Deallocates a list of TCP segments (tcp_seg structures).
 *
 */
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_segs_free(struct tcp_seg *seg)
{
  u8_t count = 0;
  struct tcp_seg *next;
 again:  
  if(seg != NULL) {
    next = seg->next;
    count += tcp_seg_free(seg);
    seg = next;
    goto again;
  }
  return count;
}
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_seg_free():
 *
 * Frees a TCP segment.
 *
 */
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_seg_free(struct tcp_seg *seg)
{
  u8_t count = 0;
  
  if(seg != NULL) {
    if(seg->p == NULL) {
      memp_free(MEMP_TCP_SEG, seg);
    } else {
      count = pbuf_free(seg->p);
#if TCP_DEBUG
      seg->p = NULL;
#endif /* TCP_DEBUG */
      memp_free(MEMP_TCP_SEG, seg);
    }
  }
  return count;
}
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_seg_copy():
 *
 * Returns a copy of the given TCP segment.
 *
 */ 
/*-----------------------------------------------------------------------------------*/
struct tcp_seg *
tcp_seg_copy(struct tcp_seg *seg)
{
  struct tcp_seg *cseg;

  cseg = memp_malloc(MEMP_TCP_SEG);
  if(cseg == NULL) {
    return NULL;
  }
  bcopy(seg, cseg, sizeof(struct tcp_seg));
  pbuf_ref(cseg->p);
  return cseg;
}
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_new():
 *
 * Creates a new TCP protocol control block but doesn't place it on
 * any of the TCP PCB lists.
 *
 */
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_new(void)
{
  struct tcp_pcb *pcb;
  u32_t iss;
  
  pcb = memp_malloc2(MEMP_TCP_PCB);
  if(pcb != NULL) {
    bzero(pcb, sizeof(struct tcp_pcb));
    pcb->snd_buf = TCP_SND_BUF;
    pcb->snd_queuelen = 0;
    pcb->rcv_wnd = TCP_WND;
    pcb->mss = TCP_MSS;
    pcb->rto = 3000 / TCP_SLOW_INTERVAL;
    pcb->sa = 0;
    pcb->sv = 3000 / TCP_SLOW_INTERVAL;
    pcb->rtime = 0;
    pcb->cwnd = 1;
    iss = tcp_next_iss();
    pcb->snd_wl2 = iss;
    pcb->snd_nxt = iss;
    pcb->snd_max = iss;
    pcb->lastack = iss;
    pcb->snd_lbb = iss;   
    pcb->tmr = tcp_ticks;

    pcb->polltmr = 0;

    return pcb;
  }
  return NULL;
}
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_mem_reclaim():
 *
 * Tries to free up TCP memory. This function is called from the memory manager
 * when memory is scarce.
 *
 */
/*-----------------------------------------------------------------------------------*/
#if MEM_RECLAIM
static mem_size_t
tcp_mem_reclaim(void *arg, mem_size_t size)
{
  static struct tcp_pcb *pcb, *inactive;
  static u32_t inactivity;
  static mem_size_t reclaimed;

  reclaimed = 0;

  /* Kill the oldest active connection, hoping that there may be
     memory associated with it. */
  inactivity = 0;
  inactive = NULL;
  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
    if((u32_t)(tcp_ticks - pcb->tmr) > inactivity) {
      inactivity = tcp_ticks - pcb->tmr;
      inactive = pcb;
    }
  }
  if(inactive != NULL) {
    DEBUGF(TCP_DEBUG, ("tcp_mem_reclaim: killing oldest PCB 0x%p (%ld)\n",
		       inactive, inactivity));
    tcp_abort(inactive);
  }
  return reclaimed;
}
#endif /* MEM_RECLAIM */
/*-----------------------------------------------------------------------------------*/
/*
 * tcp_memp_reclaim():
 *
 * Tries to free up TCP memory. This function is called from the
 * memory pool manager when memory is scarce.
 *
 */

⌨️ 快捷键说明

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