diff --git a/CHANGELOG b/CHANGELOG index a7321b25..e6b1fe40 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -46,6 +46,9 @@ HISTORY ++ Bugfixes: + 2009-11-22: Simon Goldschmidt + * tcp_in.c: Fixed bug #27905: FIN isn't combined with data on unsent + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when reusing time-wait pcb diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 5559d768..7d06f1cd 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -346,7 +346,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, if (useg != NULL && TCP_TCPLEN(useg) != 0 && !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) && - !(flags & (TCP_SYN | TCP_FIN)) && + (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) && /* fit within max seg size */ (useg->len + queue->len <= pcb->mss) && /* only concatenate segments with the same options */ @@ -368,10 +368,16 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, queuelen--; pbuf_free(old_q); } - LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0)); - pbuf_cat(useg->p, queue->p); - useg->len += queue->len; - useg->next = queue->next; + if (flags & TCP_FIN) { + /* the new segment contains only FIN, no data -> put the FIN into the last segment */ + LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0); + TCPH_SET_FLAG(useg->tcphdr, TCP_FIN); + } else { + LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0)); + pbuf_cat(useg->p, queue->p); + useg->len += queue->len; + useg->next = queue->next; + } LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len)); if (seg == queue) {