From a8ac37f419b7f8d451605d56b19b904e88d25bf2 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Sat, 9 Sep 2017 21:41:06 +0200 Subject: [PATCH] refactor tcp_input a bit in preparation of a fix for bug #51937 --- src/core/tcp_in.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 747a0181..48d95c12 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -91,6 +91,8 @@ static void tcp_parseopt(struct tcp_pcb *pcb); static void tcp_listen_input(struct tcp_pcb_listen *pcb); static void tcp_timewait_input(struct tcp_pcb *pcb); +static int tcp_input_delayed_close(struct tcp_pcb *pcb); + #if LWIP_TCP_SACK_OUT static void tcp_add_sack(struct tcp_pcb *pcb, u32_t left, u32_t right); static void tcp_remove_sacks_lt(struct tcp_pcb *pcb, u32_t seq); @@ -445,17 +447,7 @@ tcp_input(struct pbuf *p, struct netif *inp) } recv_acked = 0; } - if (recv_flags & TF_CLOSED) { - /* The connection has been closed and we will deallocate the - PCB. */ - if (!(pcb->flags & TF_RXCLOSED)) { - /* Connection closed although the application has only shut down the - tx side: call the PCB's err callback and indicate the closure to - ensure the application doesn't continue using the PCB. */ - TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); - } - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); + if (tcp_input_delayed_close(pcb)) { goto aborted; } #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE @@ -572,6 +564,30 @@ dropped: pbuf_free(p); } +/** Called from tcp_input to check for TF_CLOSED flag. This results in closing + * and deallocating a pcb at the correct place to ensure noone references it + * any more. + * @returns 1 if the pcb has been closed and deallocated, 0 otherwise + */ +static int +tcp_input_delayed_close(struct tcp_pcb *pcb) +{ + if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + return 1; + } + return 0; +} + /** * Called by tcp_input() when a segment arrives for a listening * connection (from tcp_input()).