diff --git a/daemon/call.c b/daemon/call.c index e8657b410..a68716090 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2526,6 +2526,7 @@ static void __call_free(void *p) { g_queue_clear(&m->medias); g_hash_table_destroy(m->other_tags); + g_hash_table_destroy(m->branches); g_hash_table_destroy(m->media_ids); g_slice_free1(sizeof(*m), m); } @@ -2673,6 +2674,7 @@ struct call_monologue *__monologue_create(struct call *call) { ret->call = call; ret->created = rtpe_now.tv_sec; ret->other_tags = g_hash_table_new(str_hash, str_equal); + ret->branches = g_hash_table_new(str_hash, str_equal); ret->media_ids = g_hash_table_new(str_hash, str_equal); g_queue_init(&ret->medias); @@ -2693,15 +2695,21 @@ void __monologue_tag(struct call_monologue *ml, const str *tag) { } void __monologue_viabranch(struct call_monologue *ml, const str *viabranch) { struct call *call = ml->call; + struct call_monologue *other = ml->active_dialogue; - if (!viabranch) + if (!viabranch || !viabranch->len) return; __C_DBG("tagging monologue with viabranch '"STR_FORMAT"'", STR_FMT(viabranch)); - if (ml->viabranch.s) + if (ml->viabranch.s) { g_hash_table_remove(call->viabranches, &ml->viabranch); + if (other) + g_hash_table_remove(other->branches, &ml->viabranch); + } call_str_cpy(call, &ml->viabranch, viabranch); g_hash_table_insert(call->viabranches, &ml->viabranch, ml); + if (other) + g_hash_table_insert(other->branches, &ml->viabranch, ml); } /* must be called with call->master_lock held in W */ @@ -2750,6 +2758,10 @@ static void __monologue_destroy(struct call_monologue *monologue, int recurse) { call = monologue->call; + ilog(LOG_DEBUG, "Destroying monologue '" STR_FORMAT "' (" STR_FORMAT ")", + STR_FMT(&monologue->tag), + STR_FMT0(&monologue->viabranch)); + g_hash_table_remove(call->tags, &monologue->tag); if (monologue->viabranch.s) g_hash_table_remove(call->viabranches, &monologue->viabranch); @@ -2759,12 +2771,16 @@ static void __monologue_destroy(struct call_monologue *monologue, int recurse) { if (dialogue == monologue) continue; - if (dialogue->active_dialogue != monologue + if (monologue->tag.len && !g_hash_table_lookup(dialogue->other_tags, &monologue->tag)) continue; + if (monologue->viabranch.len + && !g_hash_table_lookup(dialogue->branches, &monologue->viabranch)) + continue; g_hash_table_remove(dialogue->other_tags, &monologue->tag); - if (recurse && !g_hash_table_size(dialogue->other_tags)) + g_hash_table_remove(dialogue->branches, &monologue->viabranch); + if (recurse && !g_hash_table_size(dialogue->other_tags) && !g_hash_table_size(dialogue->branches)) __monologue_destroy(dialogue, 0); } diff --git a/daemon/redis.c b/daemon/redis.c index ce857d8a7..f0e35f414 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1403,6 +1403,16 @@ static int json_link_tags(struct call *c, struct redis_list *tags, struct redis_ } g_queue_clear(&q); + if (json_build_list(&q, c, "branches", &c->callid, i, tags, root_reader)) + return -1; + for (l = q.head; l; l = l->next) { + other_ml = l->data; + if (!other_ml) + return -1; + g_hash_table_insert(ml->branches, &other_ml->viabranch, other_ml); + } + g_queue_clear(&q); + if (json_build_list(&ml->medias, c, "medias", &c->callid, i, medias, root_reader)) return -1; } @@ -2026,6 +2036,18 @@ char* redis_encode_json(struct call *c) { g_list_free(k); + k = g_hash_table_get_values(ml->branches); + snprintf(tmp, sizeof(tmp), "branches-%u", ml->unique_id); + json_builder_set_member_name(builder, tmp); + json_builder_begin_array (builder); + for (m = k; m; m = m->next) { + ml2 = m->data; + JSON_ADD_STRING("%u",ml2->unique_id); + } + json_builder_end_array (builder); + + g_list_free(k); + snprintf(tmp, sizeof(tmp), "medias-%u", ml->unique_id); json_builder_set_member_name(builder, tmp); json_builder_begin_array (builder); diff --git a/include/call.h b/include/call.h index ebe12f9ad..fde0cccf5 100644 --- a/include/call.h +++ b/include/call.h @@ -357,6 +357,7 @@ struct call_monologue { struct timeval terminated; /* for CDR */ enum termination_reason term_reason; GHashTable *other_tags; + GHashTable *branches; struct call_monologue *active_dialogue; GQueue medias; GHashTable *media_ids; diff --git a/perl/NGCP/Rtpengine/AutoTest.pm b/perl/NGCP/Rtpengine/AutoTest.pm index c135311cb..d3871e8ef 100644 --- a/perl/NGCP/Rtpengine/AutoTest.pm +++ b/perl/NGCP/Rtpengine/AutoTest.pm @@ -120,6 +120,7 @@ sub offer_answer { $regexp =~ s/CRYPTO192/([0-9a-zA-Z\/+]{51})/gs; $regexp =~ s/CRYPTO256/([0-9a-zA-Z\/+]{62})/gs; $regexp =~ s/LOOPER/([0-9a-f]{12})/gs; + $regexp =~ s/FINGERPRINT/([0-9a-fA-F:]{59})/gs; my $crlf = crlf($resp->{sdp}); like $crlf, qr/$regexp/s, "$name - output '$cmd' SDP"; my @matches = $crlf =~ qr/$regexp/s; diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index c8f0d1c0f..1de891403 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -112,6 +112,244 @@ rcv($sock_d, -1, qr/^\x16\xfe\xff\x00\x00\x00\x00\x00\x00\x00/); +# GH 1037 + +new_call; + +offer('rtcp-mux branched w delete-delay', { + ICE => 'remove', + SDES => 'off', + 'via-branch' => 'foo.0', + 'transport-protocol' => 'RTP/SAVPF', + 'rtcp-mux' => ['offer'], + }, < 'remove', + SDES => 'off', + 'via-branch' => 'foo.1', + 'transport-protocol' => 'RTP/AVP', + 'rtcp-mux' => ['demux'], + }, < ft(), 'via-branch' => 'foo.1' }); + +answer('rtcp-mux branched w delete-delay', { + ICE => 'remove', + SDES => 'off', + 'via-branch' => 'foo.0', + 'transport-protocol' => 'RTP/AVPF', + 'rtcp-mux' => ['demux'], + }, < 'remove', + SDES => 'off', + 'via-branch' => 'foo.0', + 'transport-protocol' => 'RTP/SAVPF', + 'rtcp-mux' => ['offer'], + }, < 'remove', + SDES => 'off', + 'via-branch' => 'foo.1', + 'transport-protocol' => 'RTP/AVP', + 'rtcp-mux' => ['demux'], + }, < ft(), 'via-branch' => 'foo.1', + 'delete-delay' => 0, + }); + +answer('rtcp-mux branched delete-delay=0', { + ICE => 'remove', + SDES => 'off', + 'via-branch' => 'foo.0', + 'transport-protocol' => 'RTP/AVPF', + 'rtcp-mux' => ['demux'], + }, <