diff --git a/main/channel.c b/main/channel.c index 76e7c3c787..ff2e38a343 100644 --- a/main/channel.c +++ b/main/channel.c @@ -75,6 +75,7 @@ #include "asterisk/max_forwards.h" #include "asterisk/stream.h" #include "asterisk/message.h" +#include "asterisk/rtp_engine.h" #include "channelstorage.h" @@ -2463,8 +2464,21 @@ int ast_softhangup(struct ast_channel *chan, int cause) RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); int res; int tech_cause = 0; + struct ast_rtp_glue *glue; + RAII_VAR(struct ast_rtp_instance *, rtp, NULL, ao2_cleanup); + const struct ast_channel_tech *tech; ast_channel_lock(chan); + + tech = ast_channel_tech(chan); + glue = ast_rtp_instance_get_glue(tech->type); + if (glue) { + glue->get_rtp_info(chan, &rtp); + if (rtp) { + ast_rtp_instance_set_stats_vars(chan, rtp); + } + } + res = ast_softhangup_nolock(chan, cause); blob = ast_json_pack("{s: i, s: b}", "cause", cause, diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 90198e089d..b0c1bc2c42 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -2704,14 +2704,36 @@ char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_r return buf; } +#define SET_STATS_VAR_HELPER(var_prefix, field) \ +({ \ + value = ast_rtp_instance_get_quality(instance, field, quality_buf, sizeof(quality_buf)); \ + if (value) { \ + if (!chanvars || ast_strlen_zero(ast_var_find(chanvars, var_prefix))) { \ + pbx_builtin_setvar_helper(chan, var_prefix, value); \ + chanchanges++; \ + } \ + if (bridge) { \ + if (!bridgevars || ast_strlen_zero(ast_var_find(bridgevars, var_prefix "BRIDGED"))) { \ + pbx_builtin_setvar_helper(bridge, var_prefix "BRIDGED", value); \ + bridgechanges++; \ + } \ + } \ + } \ +}) + void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance) { char quality_buf[AST_MAX_USER_FIELD]; - char *quality; + char *value; struct ast_channel *bridge; + struct varshead *chanvars = ast_channel_varshead(chan); + struct varshead *bridgevars = NULL; + int chanchanges = 0; + int bridgechanges = 0; bridge = ast_channel_bridge_peer(chan); if (bridge) { + bridgevars = ast_channel_varshead(bridge); ast_channel_lock_both(chan, bridge); ast_channel_stage_snapshot(bridge); } else { @@ -2719,55 +2741,28 @@ void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_in } ast_channel_stage_snapshot(chan); - quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, - quality_buf, sizeof(quality_buf)); - if (quality) { - pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality); - if (bridge) { - pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality); - } - } + SET_STATS_VAR_HELPER("RTPAUDIOQOS", AST_RTP_INSTANCE_STAT_FIELD_QUALITY); - quality = ast_rtp_instance_get_quality(instance, - AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)); - if (quality) { - pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality); - if (bridge) { - pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality); - } - } + SET_STATS_VAR_HELPER("RTPAUDIOQOSJITTER", AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER); - quality = ast_rtp_instance_get_quality(instance, - AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)); - if (quality) { - pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality); - if (bridge) { - pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality); - } - } + SET_STATS_VAR_HELPER("RTPAUDIOQOSLOSS", AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS); - quality = ast_rtp_instance_get_quality(instance, - AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)); - if (quality) { - pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality); - if (bridge) { - pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality); - } - } + SET_STATS_VAR_HELPER("RTPAUDIOQOSRTT", AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT); - quality = ast_rtp_instance_get_quality(instance, - AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES, quality_buf, sizeof(quality_buf)); - if (quality) { - pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSMES", quality); - if (bridge) { - pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSMESBRIDGED", quality); - } - } + SET_STATS_VAR_HELPER("RTPAUDIOQOSMES", AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES); - ast_channel_stage_snapshot_done(chan); + if (chanchanges) { + ast_channel_stage_snapshot_done(chan); + } else { + ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE); + } ast_channel_unlock(chan); if (bridge) { - ast_channel_stage_snapshot_done(bridge); + if (bridgechanges) { + ast_channel_stage_snapshot_done(bridge); + } else { + ast_clear_flag(ast_channel_flags(bridge), AST_FLAG_SNAPSHOT_STAGE); + } ast_channel_unlock(bridge); ast_channel_unref(bridge); }