diff --git a/src/core/tcp.c b/src/core/tcp.c index 1dfe62c1..ee841e00 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -1014,7 +1014,6 @@ tcp_alloc(u8_t prio) iss = tcp_next_iss(); pcb->snd_wl2 = iss; pcb->snd_nxt = iss; - pcb->snd_max = iss; pcb->lastack = iss; pcb->snd_lbb = iss; pcb->tmr = tcp_ticks; diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index dad16bc6..b0420e90 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -506,7 +506,6 @@ tcp_process(struct tcp_pcb *pcb) struct tcp_seg *rseg; u8_t acceptable = 0; err_t err; - u8_t accepted_inseq; err = ERR_OK; @@ -527,7 +526,7 @@ tcp_process(struct tcp_pcb *pcb) if (acceptable) { LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); - recv_flags = TF_RESET; + recv_flags |= TF_RESET; pcb->flags &= ~TF_ACK_DELAY; return ERR_RST; } else { @@ -626,11 +625,11 @@ tcp_process(struct tcp_pcb *pcb) old_cwnd = pcb->cwnd; /* If there was any data contained within this ACK, * we'd better pass it on to the application as well. */ - accepted_inseq = tcp_receive(pcb); + tcp_receive(pcb); pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); - if ((flags & TCP_FIN) && accepted_inseq) { + if (recv_flags & TF_GOT_FIN) { tcp_ack_now(pcb); pcb->state = CLOSE_WAIT; } @@ -649,16 +648,16 @@ tcp_process(struct tcp_pcb *pcb) case CLOSE_WAIT: /* FALLTHROUGH */ case ESTABLISHED: - accepted_inseq = tcp_receive(pcb); - if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */ + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ tcp_ack_now(pcb); pcb->state = CLOSE_WAIT; } break; case FIN_WAIT_1: tcp_receive(pcb); - if (flags & TCP_FIN) { - if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); tcp_ack_now(pcb); @@ -670,13 +669,13 @@ tcp_process(struct tcp_pcb *pcb) tcp_ack_now(pcb); pcb->state = CLOSING; } - } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { pcb->state = FIN_WAIT_2; } break; case FIN_WAIT_2: tcp_receive(pcb); - if (flags & TCP_FIN) { + if (recv_flags & TF_GOT_FIN) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); tcp_ack_now(pcb); tcp_pcb_purge(pcb); @@ -689,7 +688,6 @@ tcp_process(struct tcp_pcb *pcb) tcp_receive(pcb); if (flags & TCP_ACK && ackno == pcb->snd_nxt) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); tcp_pcb_purge(pcb); TCP_RMV(&tcp_active_pcbs, pcb); pcb->state = TIME_WAIT; @@ -701,7 +699,7 @@ tcp_process(struct tcp_pcb *pcb) if (flags & TCP_ACK && ackno == pcb->snd_nxt) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ - recv_flags = TF_CLOSED; + recv_flags |= TF_CLOSED; } break; default: @@ -755,8 +753,10 @@ tcp_receive(struct tcp_pcb *pcb) #if TCP_WND_DEBUG } else { if (pcb->snd_wnd != tcphdr->wnd) { - LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %"U32_F" snd_max %"U32_F" ackno %"U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", - pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); } #endif /* TCP_WND_DEBUG */ } @@ -803,7 +803,7 @@ tcp_receive(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n", pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge)); } - } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){ + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ /* We come here when the ACK acknowledges new data. */ /* Reset the "IN Fast Retransmit" flag, since we are no longer @@ -897,10 +897,8 @@ tcp_receive(struct tcp_pcb *pcb) ->unsent list after a retransmission, so these segments may in fact have been sent once. */ while (pcb->unsent != NULL && - /*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) && - TCP_SEQ_LEQ(ackno, pcb->snd_max)*/ - TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max) - ) { + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent))); @@ -916,10 +914,6 @@ tcp_receive(struct tcp_pcb *pcb) LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || pcb->unsent != NULL); } - - if (pcb->unsent != NULL) { - pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno); - } } /* End of ACK for new data processing. */ @@ -1081,13 +1075,7 @@ tcp_receive(struct tcp_pcb *pcb) #endif /* TCP_QUEUE_OOSEQ */ tcplen = TCP_TCPLEN(&inseg); - - /* First received FIN will be ACKed +1, on any successive (duplicate) - * FINs we are already in CLOSE_WAIT and have already done +1. - */ - if (pcb->state != CLOSE_WAIT) { - pcb->rcv_nxt += tcplen; - } + pcb->rcv_nxt = seqno + tcplen; /* Update the receiver's (our) window. */ if (pcb->rcv_wnd < tcplen) { @@ -1116,7 +1104,7 @@ tcp_receive(struct tcp_pcb *pcb) } if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); - recv_flags = TF_GOT_FIN; + recv_flags |= TF_GOT_FIN; } #if TCP_QUEUE_OOSEQ @@ -1149,7 +1137,7 @@ tcp_receive(struct tcp_pcb *pcb) } if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); - recv_flags = TF_GOT_FIN; + recv_flags |= TF_GOT_FIN; if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ pcb->state = CLOSE_WAIT; } diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 5ecfe2fd..ca72d9dc 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -60,12 +60,13 @@ static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); static struct tcp_hdr * -tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen) +tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen, + u32_t seqno_be /* already in network byte order */) { struct tcp_hdr *tcphdr = p->payload; tcphdr->src = htons(pcb->local_port); tcphdr->dest = htons(pcb->remote_port); - tcphdr->seqno = htonl(pcb->snd_nxt); + tcphdr->seqno = seqno_be; tcphdr->ackno = htonl(pcb->rcv_nxt); TCPH_FLAGS_SET(tcphdr, TCP_ACK); tcphdr->wnd = htons(pcb->rcv_ann_wnd); @@ -456,7 +457,7 @@ tcp_output(struct tcp_pcb *pcb) struct pbuf *p; struct tcp_hdr *tcphdr; struct tcp_seg *seg, *useg; - u32_t wnd; + u32_t wnd, snd_nxt; #if TCP_CWND_DEBUG s16_t i = 0; #endif /* TCP_CWND_DEBUG */ @@ -503,7 +504,7 @@ tcp_output(struct tcp_pcb *pcb) /* remove ACK flags from the PCB, as we send an empty ACK now */ pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - tcphdr = tcp_output_set_header(pcb, p, optlen); + tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt)); /* NB. MSS option is only sent on SYNs, so ignore it here */ #if LWIP_TCP_TIMESTAMPS @@ -583,9 +584,9 @@ tcp_output(struct tcp_pcb *pcb) } 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; + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; } /* put segment on unacknowledged list if length > 0 */ if (TCP_TCPLEN(seg) > 0) { @@ -805,7 +806,6 @@ tcp_rexmit_rto(struct tcp_pcb *pcb) /* unacked queue is now empty */ pcb->unacked = NULL; - pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); /* increment number of retransmissions */ ++pcb->nrtx; @@ -846,8 +846,6 @@ tcp_rexmit(struct tcp_pcb *pcb) seg->next = *cur_seg; *cur_seg = seg; - pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); - ++pcb->nrtx; /* Don't take any rtt measurements after retransmitting. */ @@ -889,9 +887,7 @@ tcp_keepalive(struct tcp_pcb *pcb) LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", (p->len >= sizeof(struct tcp_hdr))); - tcphdr = tcp_output_set_header(pcb, p, 0); - - tcphdr->seqno = htonl(pcb->snd_nxt - 1); + tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1)); #if CHECKSUM_GEN_TCP tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, @@ -957,9 +953,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", (p->len >= sizeof(struct tcp_hdr))); - tcphdr = tcp_output_set_header(pcb, p, 0); - - tcphdr->seqno = seg->tcphdr->seqno; + tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno); /* Copy in one byte from the head of the unacked queue */ *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr; diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index c3894918..40025753 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -338,12 +338,11 @@ struct tcp_pcb { u16_t ssthresh; /* sender variables */ - u32_t snd_nxt, /* next seqno to be sent */ - snd_max; /* Highest seqno sent. */ + u32_t snd_nxt; /* next new seqno to be sent */ u16_t snd_wnd; /* sender window */ - u32_t snd_wl1, snd_wl2, /* Sequence and acknowledgement numbers of last + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last window update. */ - snd_lbb; /* Sequence number of next byte to be buffered. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ u16_t acked;