diff --git a/CHANGELOG b/CHANGELOG index 4f2804fc..ea0ec9c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -60,6 +60,11 @@ HISTORY ++ Bugfixes: + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + 2009-01-28 Jonathan Larmour * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run out of pool pbufs. diff --git a/src/core/tcp.c b/src/core/tcp.c index 9d4f215c..ab51fd90 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -1150,6 +1150,27 @@ tcp_pcb_purge(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + (ip_addr_isany(&lpcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + if (pcb->refused_data != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); pbuf_free(pcb->refused_data);