pjsip show channelstats: Prevent possible segfault when faxing
Under rare circumstances, it's possible for the original audio
session in the active_media_state default_session to be corrupted
instead of removed when switching to the t38/image media session
during fax negotiation. This can cause a segfault when a "pjsip
show channelstats" attempts to print that audio media session's
rtp statistics. In these cases, the active_media_state
topology is correctly showing only a single t38/image stream
so we now check that there's an audio stream in the topology
before attempting to use the audio media session to get the rtp
statistics.
Resolves: #592
(cherry picked from commit cb057a6381
)
This commit is contained in:
parent
6df5fbee65
commit
f770c9c92c
|
@ -343,6 +343,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
|
||||||
struct ast_sip_session *session;
|
struct ast_sip_session *session;
|
||||||
struct ast_sip_session_media *media;
|
struct ast_sip_session_media *media;
|
||||||
struct ast_rtp_instance_stats stats;
|
struct ast_rtp_instance_stats stats;
|
||||||
|
struct ast_stream *stream;
|
||||||
char *print_name = NULL;
|
char *print_name = NULL;
|
||||||
char *print_time = alloca(32);
|
char *print_time = alloca(32);
|
||||||
char codec_in_use[7];
|
char codec_in_use[7];
|
||||||
|
@ -359,16 +360,29 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
|
||||||
|
|
||||||
cpvt = ast_channel_tech_pvt(channel);
|
cpvt = ast_channel_tech_pvt(channel);
|
||||||
session = cpvt ? cpvt->session : NULL;
|
session = cpvt ? cpvt->session : NULL;
|
||||||
if (!session) {
|
|
||||||
|
if (!session
|
||||||
|
|| !session->active_media_state
|
||||||
|
|| !session->active_media_state->topology) {
|
||||||
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
|
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
|
||||||
ast_channel_unlock(channel);
|
ast_channel_unlock(channel);
|
||||||
ao2_cleanup(channel);
|
ao2_cleanup(channel);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream = ast_stream_topology_get_first_stream_by_type(
|
||||||
|
session->active_media_state->topology, AST_MEDIA_TYPE_AUDIO);
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
ast_str_append(&context->output_buffer, 0, " %s no audio streams\n", snapshot->base->name);
|
||||||
|
ast_channel_unlock(channel);
|
||||||
|
ao2_cleanup(channel);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
|
media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
|
||||||
if (!media || !media->rtp) {
|
if (!media || media->type != AST_MEDIA_TYPE_AUDIO || !media->rtp) {
|
||||||
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
|
ast_str_append(&context->output_buffer, 0, " %s corrupted default audio session\n", snapshot->base->name);
|
||||||
ast_channel_unlock(channel);
|
ast_channel_unlock(channel);
|
||||||
ao2_cleanup(channel);
|
ao2_cleanup(channel);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2460,6 +2460,10 @@ int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (!instance || !instance->engine || !stats) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (instance->engine->get_stat) {
|
if (instance->engine->get_stat) {
|
||||||
ao2_lock(instance);
|
ao2_lock(instance);
|
||||||
res = instance->engine->get_stat(instance, stats, stat);
|
res = instance->engine->get_stat(instance, stats, stat);
|
||||||
|
|
Loading…
Reference in New Issue