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

📄 tcp.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 3 页
字号:
  for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {    if (pcb->local_port == port) {      goto again;    }  }  for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {    if (pcb->local_port == port) {      goto again;    }  }  for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {    if (pcb->local_port == port) {      goto again;    }  }  return port;}/** * Connects to another host. The function given as the "connected" * argument will be called when the connection has been established. * */err_ttcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,      err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)){  u32_t optdata;  err_t ret;  u32_t iss;  LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\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;#if LWIP_CALLBACK_API    pcb->connected = connected;#endif /* LWIP_CALLBACK_API */    TCP_REG(&tcp_active_pcbs, pcb);  snmp_inc_tcpactiveopens();    /* 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;} /** * 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. */voidtcp_slowtmr(void){  struct tcp_pcb *pcb, *pcb2, *prev;  u32_t eff_wnd;  u8_t pcb_remove;      /* flag if a PCB should be removed */  err_t err;  err = ERR_OK;  ++tcp_ticks;  /* Steps through all of the active PCBs. */  prev = NULL;  pcb = tcp_active_pcbs;  if (pcb == NULL) {    LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));  }  while (pcb != NULL) {    LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));    LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);    LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);    LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);    pcb_remove = 0;    if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {      ++pcb_remove;      LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));    }    else if (pcb->nrtx == TCP_MAXRTX) {      ++pcb_remove;      LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));    } else {      ++pcb->rtime;      if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {        /* Time for a retransmission. */        LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"U16_F" pcb->rto %"U16_F"\n",          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];        }        /* Reduce congestion window and ssthresh. */        eff_wnd = LWIP_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;        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((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)  {         LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",                                 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),                                 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));         tcp_abort(pcb);      }      else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {         tcp_keepalive(pcb);         pcb->keep_cnt++;      }   }    /* 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) {      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);      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->polltmr = 0;        LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));        TCP_EVENT_POLL(pcb, err);        if (err == ERR_OK) {          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) {    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) {      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->next;      memp_free(MEMP_TCP_PCB, pcb);      pcb = pcb2;    } else {      prev = pcb;      pcb = pcb->next;    }  }}/** * Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs. */voidtcp_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) {      LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));      tcp_ack_now(pcb);      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);    }  }}/** * Deallocates a list of TCP segments (tcp_seg structures). * */u8_ttcp_segs_free(struct tcp_seg *seg){  u8_t count = 0;  struct tcp_seg *next;  while (seg != NULL) {    next = seg->next;    count += tcp_seg_free(seg);    seg = next;  }  return count;}/** * Frees a TCP segment. * */u8_ttcp_seg_free(struct tcp_seg *seg){  u8_t count = 0;    if (seg != NULL) {    if (seg->p != NULL) {      count = pbuf_free(seg->p);#if TCP_DEBUG      seg->p = NULL;#endif /* TCP_DEBUG */    }    memp_free(MEMP_TCP_SEG, seg);  }  return count;}/** * Sets the priority of a connection. * */voidtcp_setprio(struct tcp_pcb *pcb, u8_t prio){  pcb->prio = prio;}#if TCP_QUEUE_OOSEQ/** * 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;  }  memcpy((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));   pbuf_ref(cseg->p);  return cseg;}#endif#if LWIP_CALLBACK_APIstatic err_ttcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err){  arg = arg;  if (p != NULL) {    pbuf_free(p);  } else if (err == ERR_OK) {    return tcp_close(pcb);  }  return ERR_OK;}#endif /* LWIP_CALLBACK_API */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);  }      }static void

⌨️ 快捷键说明

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