📄 tcp_out.c
字号:
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);#if LWIP_NETIF_HWADDRHINT { struct netif *netif; netif = ip_route(&pcb->remote_ip); if(netif != NULL){ netif->addr_hint = &(pcb->addr_hint); ip_output_if(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); netif->addr_hint = NULL; } }#else /* LWIP_NETIF_HWADDRHINT*/ ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, IP_PROTO_TCP);#endif /* LWIP_NETIF_HWADDRHINT*/}/** * Send a TCP RESET packet (empty segment with RST flag set) either to * abort a connection or to show that there is no matching local connection * for a received segment. * * Called by tcp_abort() (to abort a local connection), tcp_input() (if no * matching local pcb was found), tcp_listen_input() (if incoming segment * has ACK flag set) and tcp_process() (received segment in the wrong state) * * Since a RST segment is in most cases not sent for an active connection, * tcp_rst() has a number of arguments that are taken from a tcp_pcb for * most other segment output functions. * * @param seqno the sequence number to use for the outgoing segment * @param ackno the acknowledge number to use for the outgoing segment * @param local_ip the local IP address to send the segment from * @param remote_ip the remote IP address to send the segment to * @param local_port the local TCP port to send the segment from * @param remote_port the remote TCP port to send the segment to */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; } LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", (p->len >= sizeof(struct tcp_hdr))); 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 * * Called by tcp_slowtmr() for slow retransmission. * * @param pcb the tcp_pcb for which to re-enqueue all unacked segments */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);}/** * Requeue the first unacked segment for retransmission * * Called by tcp_receive() for fast retramsmit. * * @param pcb the tcp_pcb for which to retransmit the first unacked segment */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);}/** * Send keepalive packets to keep a connection active although * no data is sent over it. * * Called by tcp_slowtmr() * * @param pcb the tcp_pcb for which to send a keepalive packet */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_sent %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); 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; } LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", (p->len >= sizeof(struct tcp_hdr))); 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); TCPH_FLAGS_SET(tcphdr, 0); tcphdr->wnd = htons(pcb->rcv_ann_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 */#if LWIP_NETIF_HWADDRHINT { struct netif *netif; netif = ip_route(&pcb->remote_ip); if(netif != NULL){ netif->addr_hint = &(pcb->addr_hint); ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, 0, IP_PROTO_TCP, netif); netif->addr_hint = NULL; } }#else /* LWIP_NETIF_HWADDRHINT*/ ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);#endif /* LWIP_NETIF_HWADDRHINT*/ pbuf_free(p); LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));}/** * Send persist timer zero-window probes to keep a connection active * when a window update is lost. * * Called by tcp_slowtmr() * * @param pcb the tcp_pcb for which to send a zero-window probe packet */voidtcp_zero_window_probe(struct tcp_pcb *pcb){ struct pbuf *p; struct tcp_hdr *tcphdr; struct tcp_seg *seg; LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW 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_zero_window_probe: tcp_ticks %"U32_F " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); seg = pcb->unacked; if(seg == NULL) seg = pcb->unsent; if(seg == NULL) return; p = pbuf_alloc(PBUF_IP, TCP_HLEN + 1, PBUF_RAM); if(p == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); return; } LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", (p->len >= sizeof(struct tcp_hdr))); tcphdr = p->payload; tcphdr->src = htons(pcb->local_port); tcphdr->dest = htons(pcb->remote_port); tcphdr->seqno = seg->tcphdr->seqno; tcphdr->ackno = htonl(pcb->rcv_nxt); TCPH_FLAGS_SET(tcphdr, 0); tcphdr->wnd = htons(pcb->rcv_ann_wnd); tcphdr->urgp = 0; TCPH_HDRLEN_SET(tcphdr, 5); /* Copy in one byte from the head of the unacked queue */ *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr; 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 */#if LWIP_NETIF_HWADDRHINT { struct netif *netif; netif = ip_route(&pcb->remote_ip); if(netif != NULL){ netif->addr_hint = &(pcb->addr_hint); ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, 0, IP_PROTO_TCP, netif); netif->addr_hint = NULL; } }#else /* LWIP_NETIF_HWADDRHINT*/ ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);#endif /* LWIP_NETIF_HWADDRHINT*/ pbuf_free(p); LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: 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 + -