From 10c3ce08af9a1af1f85a5b79082f462793a6c602 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Tue, 10 Feb 2009 20:29:38 +0000 Subject: [PATCH] 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. --- CHANGELOG | 5 +++++ src/core/tcp.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) 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);