diff --git a/src/etcp.c b/src/etcp.c index 5c2e859..9ab1885 100644 --- a/src/etcp.c +++ b/src/etcp.c @@ -115,33 +115,82 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance) { void etcp_connection_close(struct ETCP_CONN* etcp) { if (!etcp) return; - // Free queues only if they exist, then nullify to prevent double free + // Drain and free input_queue (contains ETCP_FRAGMENT with pkt_data from data_pool) if (etcp->input_queue) { + struct ETCP_FRAGMENT* pkt; + while ((pkt = queue_data_get(etcp->input_queue)) != NULL) { + if (pkt->pkt_data) { + memory_pool_free(etcp->instance->data_pool, pkt->pkt_data); + } + memory_pool_free(etcp->rx_pool, pkt); + } queue_free(etcp->input_queue); etcp->input_queue = NULL; } + + // Drain and free output_queue (contains ETCP_FRAGMENT with pkt_data from data_pool) if (etcp->output_queue) { + struct ETCP_FRAGMENT* pkt; + while ((pkt = queue_data_get(etcp->output_queue)) != NULL) { + if (pkt->pkt_data) { + memory_pool_free(etcp->instance->data_pool, pkt->pkt_data); + } + memory_pool_free(etcp->rx_pool, pkt); + } queue_free(etcp->output_queue); etcp->output_queue = NULL; } + + // Drain and free input_send_q (contains INFLIGHT_PACKET with pkt_data from data_pool) if (etcp->input_send_q) { + struct INFLIGHT_PACKET* pkt; + while ((pkt = queue_data_get(etcp->input_send_q)) != NULL) { + if (pkt->pkt_data) { + memory_pool_free(etcp->instance->data_pool, pkt->pkt_data); + } + memory_pool_free(etcp->inflight_pool, pkt); + } queue_free(etcp->input_send_q); etcp->input_send_q = NULL; } + + // Drain and free input_wait_ack (contains INFLIGHT_PACKET with pkt_data from data_pool) if (etcp->input_wait_ack) { + struct INFLIGHT_PACKET* pkt; + while ((pkt = queue_data_get(etcp->input_wait_ack)) != NULL) { + if (pkt->pkt_data) { + memory_pool_free(etcp->instance->data_pool, pkt->pkt_data); + } + memory_pool_free(etcp->inflight_pool, pkt); + } queue_free(etcp->input_wait_ack); etcp->input_wait_ack = NULL; } + + // Drain and free ack_q (contains ACK_PACKET from ack_pool) if (etcp->ack_q) { + struct ACK_PACKET* pkt; + while ((pkt = queue_data_get(etcp->ack_q)) != NULL) { + queue_data_free(pkt); + } queue_free(etcp->ack_q); etcp->ack_q = NULL; } + + // Drain and free recv_q (contains ETCP_FRAGMENT with pkt_data from data_pool) if (etcp->recv_q) { + struct ETCP_FRAGMENT* pkt; + while ((pkt = queue_data_get(etcp->recv_q)) != NULL) { + if (pkt->pkt_data) { + memory_pool_free(etcp->instance->data_pool, pkt->pkt_data); + } + memory_pool_free(etcp->rx_pool, pkt); + } queue_free(etcp->recv_q); etcp->recv_q = NULL; } - // Free memory pool only if it exists + // Free memory pools after all elements are returned if (etcp->inflight_pool) { memory_pool_destroy(etcp->inflight_pool); etcp->inflight_pool = NULL; diff --git a/tests/test_etcp_100_packets b/tests/test_etcp_100_packets index e0f2d80..4b557ed 100755 Binary files a/tests/test_etcp_100_packets and b/tests/test_etcp_100_packets differ