From 5203d0dd5daba4ba06352a4e65661b5b484765f8 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 25 Feb 2020 09:46:19 -0500 Subject: [PATCH] TT#76206 fix call teardown for half established dialogues In case of an offer with a via-branch followed by a delete without a via-branch (cancelled call), the call erroneously remains open after deleting one half of the call. The reason is that un-answered branches do not appear in the `other_tags` list and so are left out from being checked. Change-Id: Ib008f32ef5ee06a7ca997c900c9a3adc85b0f10d --- daemon/call.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index b79a7dd58..55953d02b 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -127,7 +127,7 @@ GHashTable *rtpe_callhash; /* ********** */ -static void __monologue_destroy(struct call_monologue *monologue); +static void __monologue_destroy(struct call_monologue *monologue, int recurse); static int monologue_destroy(struct call_monologue *ml); static struct timeval add_ongoing_calls_dur_in_interval(struct timeval *interval_start, struct timeval *interval_duration); @@ -2452,23 +2452,26 @@ void call_media_unkernelize(struct call_media *media) { } /* must be called with call->master_lock held in W */ -static void __monologue_destroy(struct call_monologue *monologue) { +static void __monologue_destroy(struct call_monologue *monologue, int recurse) { struct call *call; struct call_monologue *dialogue; - GList *l; call = monologue->call; g_hash_table_remove(call->tags, &monologue->tag); - l = g_hash_table_get_values(monologue->other_tags); - - while (l) { + for (GList *l = call->monologues.head; l; l = l->next) { dialogue = l->data; - l = g_list_delete_link(l, l); + + if (dialogue == monologue) + continue; + if (dialogue->active_dialogue != monologue + && !g_hash_table_lookup(dialogue->other_tags, &monologue->tag)) + continue; + g_hash_table_remove(dialogue->other_tags, &monologue->tag); - if (!g_hash_table_size(dialogue->other_tags)) - __monologue_destroy(dialogue); + if (recurse && !g_hash_table_size(dialogue->other_tags)) + __monologue_destroy(dialogue, 0); } monologue->deleted = 0; @@ -2478,7 +2481,7 @@ static void __monologue_destroy(struct call_monologue *monologue) { static int monologue_destroy(struct call_monologue *ml) { struct call *c = ml->call; - __monologue_destroy(ml); + __monologue_destroy(ml, 1); if (!g_hash_table_size(c->tags)) { ilog(LOG_INFO, "Call branch '"STR_FORMAT"' (%s"STR_FORMAT"%svia-branch '"STR_FORMAT"') "