diff options
author | dvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-29 15:35:38 +0000 |
---|---|---|
committer | dvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-29 15:35:38 +0000 |
commit | 0efc39c832fe8eeb15fd417e20ae849356a84202 (patch) | |
tree | 3a4e066b59fa4c20ed015116babeec18bc2bf974 /main/audiohook.c | |
parent | 8eec384ac2ca9d660b7491cf05bc6aa153e0121a (diff) |
Merged revisions 260050 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
................
r260050 | dvossel | 2010-04-29 10:33:27 -0500 (Thu, 29 Apr 2010) | 21 lines
Merged revisions 260049 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r260049 | dvossel | 2010-04-29 10:31:02 -0500 (Thu, 29 Apr 2010) | 14 lines
Fixes crash in audiohook_write_list
The middle_frame in the audiohook_write_list function was
being freed if a audiohook manipulator returned a failure.
This is incorrect logic. This patch resolves this and
adds detailed descriptions of how this function should work
and why manipulator failures must be ignored.
(closes issue #17052)
Reported by: dvossel
Tested by: dvossel
(closes issue #16196)
Reported by: atis
Review: https://reviewboard.asterisk.org/r/623/
........
................
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@260051 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/audiohook.c')
-rw-r--r-- | main/audiohook.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/main/audiohook.c b/main/audiohook.c index b0fb48ad6..2dd2bea35 100644 --- a/main/audiohook.c +++ b/main/audiohook.c @@ -572,7 +572,29 @@ static struct ast_frame *dtmf_audiohook_write_list(struct ast_channel *chan, str return frame; } -/*! \brief Pass an AUDIO frame off to be handled by the audiohook core +/*! + * \brief Pass an AUDIO frame off to be handled by the audiohook core + * + * \details + * This function has 3 ast_frames and 3 parts to handle each. At the beginning of this + * function all 3 frames, start_frame, middle_frame, and end_frame point to the initial + * input frame. + * + * Part_1: Translate the start_frame into SLINEAR audio if it is not already in that + * format. The result of this part is middle_frame is guaranteed to be in + * SLINEAR format for Part_2. + * Part_2: Send middle_frame off to spies and manipulators. At this point middle_frame is + * either a new frame as result of the translation, or points directly to the start_frame + * because no translation to SLINEAR audio was required. The result of this part + * is end_frame will be updated to point to middle_frame if any audiohook manipulation + * took place. + * Part_3: Translate end_frame's audio back into the format of start frame if necessary. + * At this point if middle_frame != end_frame, we are guaranteed that no manipulation + * took place and middle_frame can be freed as it was translated... If middle_frame was + * not translated and still pointed to start_frame, it would be equal to end_frame as well + * regardless if manipulation took place which would not result in this free. The result + * of this part is end_frame is guaranteed to be the format of start_frame for the return. + * * \param chan Channel that the list is coming off of * \param audiohook_list List of audiohooks * \param direction Direction frame is coming in from @@ -587,6 +609,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st struct ast_audiohook *audiohook = NULL; int samples = frame->samples; + /* ---Part_1. translate start_frame to SLINEAR if necessary. */ /* If the frame coming in is not signed linear we have to send it through the in_translate path */ if (frame->subclass != AST_FORMAT_SLINEAR) { if (in_translate->format != frame->subclass) { @@ -601,6 +624,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st samples = middle_frame->samples; } + /* ---Part_2: Send middle_frame to spy and manipulator lists. middle_frame is guaranteed to be SLINEAR here.*/ /* Queue up signed linear frame to each spy */ AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) { ast_audiohook_lock(audiohook); @@ -654,20 +678,21 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st audiohook->manipulate_callback(audiohook, chan, NULL, direction); continue; } - /* Feed in frame to manipulation */ + /* Feed in frame to manipulation. */ if (audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) { - ast_frfree(middle_frame); - middle_frame = NULL; + /* XXX IGNORE FAILURE */ + + /* If the manipulation fails then the frame will be returned in its original state. + * Since there are potentially more manipulator callbacks in the list, no action should + * be taken here to exit early. */ } ast_audiohook_unlock(audiohook); } AST_LIST_TRAVERSE_SAFE_END; - if (middle_frame) { - end_frame = middle_frame; - } + end_frame = middle_frame; } - /* Now we figure out what to do with our end frame (whether to transcode or not) */ + /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */ if (middle_frame == end_frame) { /* Middle frame was modified and became the end frame... let's see if we need to transcode */ if (end_frame->subclass != start_frame->subclass) { @@ -692,9 +717,7 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st } } else { /* No frame was modified, we can just drop our middle frame and pass the frame we got in out */ - if (middle_frame) { - ast_frfree(middle_frame); - } + ast_frfree(middle_frame); } return end_frame; |