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

📄 tcp_out.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
  else {          if(useg == NULL) {      pcb->unsent = queue;    }    else {      useg->next = queue;    }  }  if((flags & TCP_SYN) || (flags & TCP_FIN)) {    ++len;  }  pcb->snd_lbb += len;  pcb->snd_buf -= len;  pcb->snd_queuelen = queuelen;  DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));  if(pcb->snd_queuelen != 0) {    LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||      pcb->unsent != NULL);  }  /* Set the PSH flag in the last segment that we enqueued, but only  if the segment has data (indicated by seglen > 0). */  if(seg != NULL && seglen > 0 && seg->tcphdr != NULL) {    TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);  }  return ERR_OK;  memerr:#ifdef TCP_STATS  ++lwip_stats.tcp.memerr;#endif /* TCP_STATS */  if(queue != NULL) {    tcp_segs_free(queue);  }  if(pcb->snd_queuelen != 0) {    LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||      pcb->unsent != NULL);  }  DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (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  int 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 = MIN(pcb->snd_wnd, pcb->cwnd);    seg = pcb->unsent;  /* If the TF_ACK_NOW flag is set, we check if there is data that is     to be sent. If data is to be sent out, we'll just piggyback our     acknowledgement with the outgoing segment. If no data will be     sent (either because the ->unsent queue is empty or because the     window doesn't allow it) we'll have to construct an empty ACK     segment and send it. */  if(pcb->flags & TF_ACK_NOW &&     (seg == NULL ||      ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {    pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);    p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);    if(p == NULL) {      DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));      return ERR_BUF;    }    DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));            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_OFFSET_SET(tcphdr, 5 << 4);        tcphdr->chksum = 0;    tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),					IP_PROTO_TCP, p->tot_len);    ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,	      IP_PROTO_TCP);    pbuf_free(p);    return ERR_OK;  }   #if TCP_OUTPUT_DEBUG  if(seg == NULL) {    DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));  }#endif /* TCP_OUTPUT_DEBUG */#if TCP_CWND_DEBUG  if(seg == NULL) {    DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",                            pcb->snd_wnd, pcb->cwnd, wnd,                            pcb->lastack));  } else {    DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\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 */    while(seg != NULL &&	ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {#if TCP_CWND_DEBUG    DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\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_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(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;      if(pcb->unacked == NULL) {        pcb->unacked = seg;		      } else {        for(useg = pcb->unacked; useg->next != NULL; useg = useg->next);        useg->next = seg;      }    } else {      tcp_seg_free(seg);    }    seg = pcb->unsent;  }    return ERR_OK;}/*-----------------------------------------------------------------------------------*/static voidtcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb){  u16_t len;  struct netif *netif;  /* 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);    DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));  }  DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\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;  seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,					   &(pcb->local_ip),					   &(pcb->remote_ip),					   IP_PROTO_TCP, seg->p->tot_len);#ifdef TCP_STATS  ++lwip_stats.tcp.xmit;#endif /* TCP_STATS */  ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,	    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) {      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_OFFSET_SET(tcphdr, 5 << 4);    tcphdr->chksum = 0;  tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,				      IP_PROTO_TCP, p->tot_len);#ifdef TCP_STATS  ++lwip_stats.tcp.xmit;#endif /* TCP_STATS */  ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);  pbuf_free(p);  DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));}/*-----------------------------------------------------------------------------------*/voidtcp_rexmit(struct tcp_pcb *pcb){  struct tcp_seg *seg;  if(pcb->unacked == NULL) {    return;  }    /* Move all unacked segments to the unsent queue. */  for(seg = pcb->unacked; seg->next != NULL; seg = seg->next);    seg->next = pcb->unsent;  pcb->unsent = pcb->unacked;    pcb->unacked = NULL;      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. */  tcp_output(pcb);}#endif /* LWIP_TCP */

⌨️ 快捷键说明

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