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

📄 tcp_out.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 2 页
字号:
  if (pcb->snd_queuelen != 0) {    LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||      pcb->unsent != NULL);  }  LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));  return ERR_MEM;}/* find out what we can send and send it */err_ttcp_output(struct tcp_pcb *pcb){  struct pbuf *p;  struct tcp_hdr *tcphdr;  struct tcp_seg *seg, *useg;  u32_t wnd;#if TCP_CWND_DEBUG  s16_t i = 0;#endif /* TCP_CWND_DEBUG */  /* First, check if we are invoked by the TCP input processing     code. If so, we do not output anything. Instead, we rely on the     input processing code to call us when input processing is done     with. */  if (tcp_input_pcb == pcb) {    return ERR_OK;  }  wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);  seg = pcb->unsent;  /* useg should point to last segment on unacked queue */  useg = pcb->unacked;  if (useg != NULL) {    for (; useg->next != NULL; useg = useg->next);  }                                                                                  /* If the TF_ACK_NOW flag is set and no data will be sent (either   * because the ->unsent queue is empty or because the window does   * not allow it), construct an empty ACK segment and send it.   *   * If data is to be sent, we will just piggyback the ACK (see below).   */  if (pcb->flags & TF_ACK_NOW &&     (seg == NULL ||      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {    p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);    if (p == NULL) {      LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));      return ERR_BUF;    }    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));    /* remove ACK flags from the PCB, as we send an empty ACK now */    pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);    tcphdr = p->payload;    tcphdr->src = htons(pcb->local_port);    tcphdr->dest = htons(pcb->remote_port);    tcphdr->seqno = htonl(pcb->snd_nxt);    tcphdr->ackno = htonl(pcb->rcv_nxt);    TCPH_FLAGS_SET(tcphdr, TCP_ACK);    tcphdr->wnd = htons(pcb->rcv_wnd);    tcphdr->urgp = 0;    TCPH_HDRLEN_SET(tcphdr, 5);    tcphdr->chksum = 0;#if CHECKSUM_GEN_TCP    tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),          IP_PROTO_TCP, p->tot_len);#endif    ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,        IP_PROTO_TCP);    pbuf_free(p);    return ERR_OK;  }#if TCP_OUTPUT_DEBUG  if (seg == NULL) {    LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));  }#endif /* TCP_OUTPUT_DEBUG */#if TCP_CWND_DEBUG  if (seg == NULL) {    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",                            pcb->snd_wnd, pcb->cwnd, wnd,                            pcb->lastack));  } else {    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",                            pcb->snd_wnd, pcb->cwnd, wnd,                            ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,                            ntohl(seg->tcphdr->seqno), pcb->lastack));  }#endif /* TCP_CWND_DEBUG */  /* data available and window allows it to be sent? */  while (seg != NULL &&  ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {#if TCP_CWND_DEBUG    LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",                            pcb->snd_wnd, pcb->cwnd, wnd,                            ntohl(seg->tcphdr->seqno) + seg->len -                            pcb->lastack,                            ntohl(seg->tcphdr->seqno), pcb->lastack, i));    ++i;#endif /* TCP_CWND_DEBUG */    pcb->unsent = seg->next;    if (pcb->state != SYN_SENT) {      TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);      pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);    }    tcp_output_segment(seg, pcb);    pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);    if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {      pcb->snd_max = pcb->snd_nxt;    }    /* put segment on unacknowledged list if length > 0 */    if (TCP_TCPLEN(seg) > 0) {      seg->next = NULL;      /* unacked list is empty? */      if (pcb->unacked == NULL) {        pcb->unacked = seg;        useg = seg;      /* unacked list is not empty? */      } else {        /* In the case of fast retransmit, the packet should not go to the tail         * of the unacked queue, but rather at the head. We need to check for         * this case. -STJ Jul 27, 2004 */        if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){          /* add segment to head of unacked list */          seg->next = pcb->unacked;          pcb->unacked = seg;        } else {          /* add segment to tail of unacked list */          useg->next = seg;          useg = useg->next;        }      }    /* do not queue empty segments on the unacked list */    } else {      tcp_seg_free(seg);    }    seg = pcb->unsent;  }  return ERR_OK;}/** * Actually send a TCP segment over IP */static voidtcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb){  u16_t len;  struct netif *netif;  /** @bug Exclude retransmitted segments from this count. */  snmp_inc_tcpoutsegs();  /* The TCP header has already been constructed, but the ackno and   wnd fields remain. */  seg->tcphdr->ackno = htonl(pcb->rcv_nxt);  /* silly window avoidance */  if (pcb->rcv_wnd < pcb->mss) {    seg->tcphdr->wnd = 0;  } else {    /* advertise our receive window size in this TCP segment */    seg->tcphdr->wnd = htons(pcb->rcv_wnd);  }  /* If we don't have a local IP address, we get one by     calling ip_route(). */  if (ip_addr_isany(&(pcb->local_ip))) {    netif = ip_route(&(pcb->remote_ip));    if (netif == NULL) {      return;    }    ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));  }  pcb->rtime = 0;  if (pcb->rttest == 0) {    pcb->rttest = tcp_ticks;    pcb->rtseq = ntohl(seg->tcphdr->seqno);    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));  }  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",          htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +          seg->len));  len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);  seg->p->len -= len;  seg->p->tot_len -= len;  seg->p->payload = seg->tcphdr;  seg->tcphdr->chksum = 0;#if CHECKSUM_GEN_TCP  seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,             &(pcb->local_ip),             &(pcb->remote_ip),             IP_PROTO_TCP, seg->p->tot_len);#endif  TCP_STATS_INC(tcp.xmit);  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,      IP_PROTO_TCP);}voidtcp_rst(u32_t seqno, u32_t ackno,  struct ip_addr *local_ip, struct ip_addr *remote_ip,  u16_t local_port, u16_t remote_port){  struct pbuf *p;  struct tcp_hdr *tcphdr;  p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);  if (p == NULL) {      LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));      return;  }  tcphdr = p->payload;  tcphdr->src = htons(local_port);  tcphdr->dest = htons(remote_port);  tcphdr->seqno = htonl(seqno);  tcphdr->ackno = htonl(ackno);  TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);  tcphdr->wnd = htons(TCP_WND);  tcphdr->urgp = 0;  TCPH_HDRLEN_SET(tcphdr, 5);  tcphdr->chksum = 0;#if CHECKSUM_GEN_TCP  tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,              IP_PROTO_TCP, p->tot_len);#endif  TCP_STATS_INC(tcp.xmit);  snmp_inc_tcpoutrsts();   /* Send output with hardcoded TTL since we have no access to the pcb */  ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);  pbuf_free(p);  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));}/* requeue all unacked segments for retransmission */voidtcp_rexmit_rto(struct tcp_pcb *pcb){  struct tcp_seg *seg;  if (pcb->unacked == NULL) {    return;  }  /* Move all unacked segments to the head of the unsent queue */  for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);  /* concatenate unsent queue after unacked queue */  seg->next = pcb->unsent;  /* unsent queue is the concatenated queue (of unacked, unsent) */  pcb->unsent = pcb->unacked;  /* unacked queue is now empty */  pcb->unacked = NULL;  pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);  /* increment number of retransmissions */  ++pcb->nrtx;  /* Don't take any RTT measurements after retransmitting. */  pcb->rttest = 0;  /* Do the actual retransmission */  tcp_output(pcb);}voidtcp_rexmit(struct tcp_pcb *pcb){  struct tcp_seg *seg;  if (pcb->unacked == NULL) {    return;  }  /* Move the first unacked segment to the unsent queue */  seg = pcb->unacked->next;  pcb->unacked->next = pcb->unsent;  pcb->unsent = pcb->unacked;  pcb->unacked = seg;  pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);  ++pcb->nrtx;  /* Don't take any rtt measurements after retransmitting. */  pcb->rttest = 0;  /* Do the actual retransmission. */  snmp_inc_tcpretranssegs();  tcp_output(pcb);}voidtcp_keepalive(struct tcp_pcb *pcb){   struct pbuf *p;   struct tcp_hdr *tcphdr;   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe 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)));   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F"   pcb->tmr %"U32_F"  pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));      p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);   if(p == NULL) {      LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));      return;   }   tcphdr = p->payload;   tcphdr->src = htons(pcb->local_port);   tcphdr->dest = htons(pcb->remote_port);   tcphdr->seqno = htonl(pcb->snd_nxt - 1);   tcphdr->ackno = htonl(pcb->rcv_nxt);   tcphdr->wnd = htons(pcb->rcv_wnd);   tcphdr->urgp = 0;   TCPH_HDRLEN_SET(tcphdr, 5);      tcphdr->chksum = 0;#if CHECKSUM_GEN_TCP   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);#endif  TCP_STATS_INC(tcp.xmit);   /* Send output to IP */  ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);  pbuf_free(p);  LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));}#endif /* LWIP_TCP */

⌨️ 快捷键说明

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