diff --git a/daemon/call.c b/daemon/call.c index 86f4c8133..9a9881f1b 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -3737,6 +3737,7 @@ static void __call_free(void *p) { g_queue_clear(&m->medias); g_hash_table_destroy(m->other_tags); + g_hash_table_destroy(m->associated_tags); g_hash_table_destroy(m->branches); g_hash_table_destroy(m->media_ids); free_ssrc_hash(&m->ssrc_hash); @@ -3932,6 +3933,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->associated_tags = g_hash_table_new(g_direct_hash, g_direct_equal); ret->branches = g_hash_table_new(str_hash, str_equal); ret->media_ids = g_hash_table_new(str_hash, str_equal); ret->ssrc_hash = create_ssrc_hash_call(); @@ -4037,6 +4039,16 @@ void call_media_unkernelize(struct call_media *media) { } } +/* must be called with call->master_lock held in W */ +static void __tags_unassociate_all(struct call_monologue *a) { + GHashTableIter iter; + g_hash_table_iter_init(&iter, a->associated_tags); + struct call_monologue *b; + while (g_hash_table_iter_next(&iter, (void **) &b, NULL)) + g_hash_table_remove(b->associated_tags, a); + g_hash_table_remove_all(a->associated_tags); +} + /* must be called with call->master_lock held in W */ static void __monologue_destroy(struct call_monologue *monologue, bool recurse) { struct call *call; @@ -4049,6 +4061,7 @@ static void __monologue_destroy(struct call_monologue *monologue, bool recurse) STR_FMT0(&monologue->viabranch)); __monologue_unkernelize(monologue); + __tags_unassociate_all(monologue); g_hash_table_remove(call->tags, &monologue->tag); if (monologue->viabranch.s) @@ -4096,6 +4109,12 @@ static void __monologue_destroy(struct call_monologue *monologue, bool recurse) monologue->deleted = 0; } +/* must be called with call->master_lock held in W */ +static void __tags_unassociate(struct call_monologue *a, struct call_monologue *b) { + g_hash_table_remove(a->associated_tags, b); + g_hash_table_remove(b->associated_tags, a); +} + /* must be called with call->master_lock held in W */ int monologue_destroy(struct call_monologue *ml) { struct call *c = ml->call; @@ -4149,6 +4168,12 @@ struct call_monologue *call_get_or_create_monologue(struct call *call, const str return ret; } +/* must be called with call->master_lock held in W */ +static void __tags_associate(struct call_monologue *a, struct call_monologue *b) { + g_hash_table_insert(a->associated_tags, b, b); + g_hash_table_insert(b->associated_tags, a, a); +} + /* must be called with call->master_lock held in W */ static int call_get_monologue_new(struct call_monologue *dialogue[2], struct call *call, const str *fromtag, const str *totag, @@ -4242,6 +4267,7 @@ ok_check_tag: break; // there should only be one // XXX check if there's more than a one-to-one mapping here? } + __tags_associate(ret, os); dialogue[0] = ret; dialogue[1] = os; return 0; @@ -4320,6 +4346,7 @@ tag_setup: done: __monologue_unkernelize(ft); dialogue_unkernelize(ft); + __tags_associate(ft, tt); dialogue[0] = ft; dialogue[1] = tt; return 0; diff --git a/daemon/redis.c b/daemon/redis.c index e1b6acb95..2fb2ca7b4 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1721,6 +1721,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, "associated_tags", 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->associated_tags, other_ml, other_ml); + } + g_queue_clear(&q); + if (json_build_list(&q, c, "branches", i, tags, root_reader)) return -1; for (l = q.head; l; l = l->next) { @@ -2509,6 +2519,18 @@ char* redis_encode_json(struct call *c) { g_list_free(k); + k = g_hash_table_get_values(ml->associated_tags); + snprintf(tmp, sizeof(tmp), "associated_tags-%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); + k = g_hash_table_get_values(ml->branches); snprintf(tmp, sizeof(tmp), "branches-%u", ml->unique_id); json_builder_set_member_name(builder, tmp); diff --git a/include/call.h b/include/call.h index 63f621633..6f82606f6 100644 --- a/include/call.h +++ b/include/call.h @@ -487,6 +487,7 @@ struct call_monologue { struct timeval terminated; /* for CDR */ enum termination_reason term_reason; const struct logical_intf *logical_intf; + GHashTable *associated_tags; GHashTable *other_tags; GHashTable *branches; GQueue subscriptions; /* who am I subscribed to (sources) */