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

📄 tcp_out.c

📁 一个基于ucos-ii和lwip的简单telent服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* 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_SET_FLAG(seg->tcphdr, TCP_PSH);  }  return ERR_OK;  memerr:  TCP_STATS_INC(tcp.memerr);  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);  }  LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("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 = 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, 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) {      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 %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_HDRLEN_SET(tcphdr, 5);    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), 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", pcb->unsent));  }#endif /* TCP_OUTPUT_DEBUG */#if TCP_CWND_DEBUG  if (seg == NULL) {    LWIP_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 {    LWIP_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    LWIP_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_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;      if (pcb->unacked == NULL) {        pcb->unacked = seg;        useg = seg;      } else {        useg->next = seg;        useg = useg->next;      }    } 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);    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));  }  LWIP_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);  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;  tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,              IP_PROTO_TCP, p->tot_len);  TCP_STATS_INC(tcp.xmit);   /* 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 %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);}voidtcp_keepalive(struct tcp_pcb *pcb){   struct pbuf *p;   struct tcp_hdr *tcphdr;   LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\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 %ld   pcb->tmr %ld  pcb->keep_cnt %ld\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;   tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);  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 %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));}#endif /* LWIP_TCP */

⌨️ 快捷键说明

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