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

📄 tcp.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 4 页
字号:
          if (pcb->ssthresh < (pcb->mss << 1)) {            pcb->ssthresh = (pcb->mss << 1);          }          pcb->cwnd = pcb->mss;          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F                                       " ssthresh %"U16_F"\n",                                       pcb->cwnd, pcb->ssthresh));           /* The following needs to be called AFTER cwnd is set to one             mss - STJ */          tcp_rexmit_rto(pcb);        }      }    }    /* 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;        LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));      }    }    /* Check if KEEPALIVE should be sent */    if((pcb->so_options & SOF_KEEPALIVE) &&       ((pcb->state == ESTABLISHED) ||        (pcb->state == CLOSE_WAIT))) {#if LWIP_TCP_KEEPALIVE      if((u32_t)(tcp_ticks - pcb->tmr) >         (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl))         / TCP_SLOW_INTERVAL)#else            if((u32_t)(tcp_ticks - pcb->tmr) >         (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)#endif /* LWIP_TCP_KEEPALIVE */      {        LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",                                ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),                                ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));                ++pcb_remove;        ++pcb_reset;      }#if LWIP_TCP_KEEPALIVE      else if((u32_t)(tcp_ticks - pcb->tmr) >               (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl)              / TCP_SLOW_INTERVAL)#else      else if((u32_t)(tcp_ticks - pcb->tmr) >               (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT)               / TCP_SLOW_INTERVAL)#endif /* LWIP_TCP_KEEPALIVE */      {        tcp_keepalive(pcb);        pcb->keep_cnt_sent++;      }    }    /* 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;      LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));    }#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;        LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));      }    }    /* Check if this PCB has stayed too long in LAST-ACK */    if (pcb->state == LAST_ACK) {      if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {        ++pcb_remove;        LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));      }    }    /* If the PCB should be removed, do it. */    if (pcb_remove) {      struct tcp_pcb *pcb2;      tcp_pcb_purge(pcb);      /* Remove PCB from tcp_active_pcbs list. */      if (prev != NULL) {        LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);        prev->next = pcb->next;      } else {        /* This PCB was the first. */        LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);        tcp_active_pcbs = pcb->next;      }      TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);      if (pcb_reset) {        tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,          pcb->local_port, pcb->remote_port);      }      pcb2 = pcb;      pcb = pcb->next;      memp_free(MEMP_TCP_PCB, pcb2);    } else {      /* get the 'next' element now and work with 'prev' below (in case of abort) */      prev = pcb;      pcb = pcb->next;      /* We check if we should poll the connection. */      ++prev->polltmr;      if (prev->polltmr >= prev->pollinterval) {        prev->polltmr = 0;        LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));        TCP_EVENT_POLL(prev, err);        /* if err == ERR_ABRT, 'prev' is already deallocated */        if (err == ERR_OK) {          tcp_output(prev);        }      }    }  }    /* Steps through all of the TIME-WAIT PCBs. */  prev = NULL;  pcb = tcp_tw_pcbs;  while (pcb != NULL) {    LWIP_ASSERT("tcp_slowtmr: 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) {      struct tcp_pcb *pcb2;      tcp_pcb_purge(pcb);      /* Remove PCB from tcp_tw_pcbs list. */      if (prev != NULL) {        LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);        prev->next = pcb->next;      } else {        /* This PCB was the first. */        LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);        tcp_tw_pcbs = pcb->next;      }      pcb2 = pcb;      pcb = pcb->next;      memp_free(MEMP_TCP_PCB, pcb2);    } else {      prev = pcb;      pcb = pcb->next;    }  }}/** * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously * "refused" by upper layer (application) and sends delayed ACKs. * * Automatically called from tcp_tmr(). */voidtcp_fasttmr(void){  struct tcp_pcb *pcb = tcp_active_pcbs;  while(pcb != NULL) {    struct tcp_pcb *next = pcb->next;    /* If there is data which was previously "refused" by upper layer */    if (pcb->refused_data != NULL) {      /* Notify again application with data previously received. */      err_t err;      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n"));      TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);      if (err == ERR_OK) {        pcb->refused_data = NULL;      } else if (err == ERR_ABRT) {        /* if err == ERR_ABRT, 'pcb' is already deallocated */        pcb = NULL;      }    }    /* send delayed ACKs */    if (pcb && (pcb->flags & TF_ACK_DELAY)) {      LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));      tcp_ack_now(pcb);      tcp_output(pcb);      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);    }    pcb = next;  }}/** * Deallocates a list of TCP segments (tcp_seg structures). * * @param seg tcp_seg list of TCP segments to free */voidtcp_segs_free(struct tcp_seg *seg){  while (seg != NULL) {    struct tcp_seg *next = seg->next;    tcp_seg_free(seg);    seg = next;  }}/** * Frees a TCP segment (tcp_seg structure). * * @param seg single tcp_seg to free */voidtcp_seg_free(struct tcp_seg *seg){  if (seg != NULL) {    if (seg->p != NULL) {      pbuf_free(seg->p);#if TCP_DEBUG      seg->p = NULL;#endif /* TCP_DEBUG */    }    memp_free(MEMP_TCP_SEG, seg);  }}/** * Sets the priority of a connection. * * @param pcb the tcp_pcb to manipulate * @param prio new priority */voidtcp_setprio(struct tcp_pcb *pcb, u8_t prio){  pcb->prio = prio;}#if TCP_QUEUE_OOSEQ/** * Returns a copy of the given TCP segment. * The pbuf and data are not copied, only the pointers * * @param seg the old tcp_seg * @return a copy of seg */ struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg){  struct tcp_seg *cseg;  cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG);  if (cseg == NULL) {    return NULL;  }  SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));   pbuf_ref(cseg->p);  return cseg;}#endif /* TCP_QUEUE_OOSEQ */#if LWIP_CALLBACK_API/** * Default receive callback that is called if the user didn't register * a recv callback for the pcb. */err_ttcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err){  LWIP_UNUSED_ARG(arg);  if (p != NULL) {    tcp_recved(pcb, p->tot_len);    pbuf_free(p);  } else if (err == ERR_OK) {    return tcp_close(pcb);  }  return ERR_OK;}#endif /* LWIP_CALLBACK_API *//** * Kills the oldest active connection that has lower priority than prio. * * @param prio minimum priority */static voidtcp_kill_prio(u8_t prio){  struct tcp_pcb *pcb, *inactive;  u32_t inactivity;  u8_t mprio;  mprio = TCP_PRIO_MAX;    /* We kill the oldest active connection that has lower priority than prio. */  inactivity = 0;  inactive = NULL;  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {    if (pcb->prio <= prio &&       pcb->prio <= mprio &&       (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {      inactivity = tcp_ticks - pcb->tmr;      inactive = pcb;      mprio = pcb->prio;    }  }  if (inactive != NULL) {    LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",           (void *)inactive, inactivity));    tcp_abort(inactive);  }}/** * Kills the oldest connection that is in TIME_WAIT state. * Called from tcp_alloc() if no more connections are available. */static voidtcp_kill_timewait(void){  struct tcp_pcb *pcb, *inactive;  u32_t inactivity;  inactivity = 0;  inactive = NULL;  /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */  for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {    if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {      inactivity = tcp_ticks - pcb->tmr;      inactive = pcb;    }  }  if (inactive != NULL) {    LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",           (void *)inactive, inactivity));    tcp_abort(inactive);  }}/** * Allocate a new tcp_pcb structure. * * @param prio priority for the new pcb * @return a new tcp_pcb that initially is in state CLOSED */struct tcp_pcb *tcp_alloc(u8_t prio){  struct tcp_pcb *pcb;  u32_t iss;    pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);  if (pcb == NULL) {    /* Try killing oldest connection in TIME-WAIT. */    LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));    tcp_kill_timewait();    /* Try to allocate a tcp_pcb again. */    pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);    if (pcb == NULL) {      /* Try killing active connections with lower priority than the new one. */      LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio));      tcp_kill_prio(prio);      /* Try to allocate a tcp_pcb again. */      pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);      if (pcb != NULL) {        /* adjust err stats: memp_malloc failed twice before */        MEMP_STATS_DEC(err, MEMP_TCP_PCB);      }    }    if (pcb != NULL) {      /* adjust err stats: timewait PCB was freed above */      MEMP_STATS_DEC(err, MEMP_TCP_PCB);    }  }  if (pcb != NULL) {    memset(pcb, 0, sizeof(struct tcp_pcb));    pcb->prio = prio;    pcb->snd_buf = TCP_SND_BUF;    pcb->snd_queuelen = 0;    pcb->rcv_wnd = TCP_WND;    pcb->rcv_ann_wnd = TCP_WND;    pcb->tos = 0;    pcb->ttl = TCP_TTL;    /* As initial send MSS, we use TCP_MSS but limit it to 536.       The send MSS is updated when an MSS option is received. */    pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;    pcb->rto = 3000 / TCP_SLOW_INTERVAL;    pcb->sa = 0;    pcb->sv = 3000 / TCP_SLOW_INTERVAL;    pcb->rtime = -1;    pcb->cwnd = 1;    iss = tcp_next_iss();    pcb->snd_wl2 = iss;    pcb->snd_nxt = iss;

⌨️ 快捷键说明

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