From 723a84dbd98a63951bccdea6b71a0d6c1243ecbe Mon Sep 17 00:00:00 2001 From: Jonathan Rose <jrose@digium.com> Date: Tue, 11 Jun 2013 22:21:36 +0000 Subject: [PATCH] bridge_native_rtp: Fix native bridge tech being incompatible when it should be. When checking compatability for the native RTP bridge technology there is a race condition between clearing framehooks that are destroyed when leaving certain bridges with certain technologies (such as bridge_native_rtp) and joining bridges with the bridge_native_rtp technology. Yes, that means a channel in a native RTP bridge could move to another native RTP bridge and be considered incompatible with the new native RTP bridge causing it to revert to a simple bridge technology0. This fixes that bug by ignoring framehooks that have been marked for destruction when checking for compatibility with the bridge_native_rtp technology. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391453 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- bridges/bridge_native_rtp.c | 2 +- include/asterisk/framehook.h | 27 +++++++++++++++++++++------ main/framehook.c | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c index ce050c89e5..3c8e57c935 100644 --- a/bridges/bridge_native_rtp.c +++ b/bridges/bridge_native_rtp.c @@ -87,7 +87,7 @@ static int native_rtp_bridge_capable(struct ast_channel *chan) { if (ast_channel_monitor(chan) || (ast_channel_audiohooks(chan) && !ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))) || - !ast_framehook_list_is_empty(ast_channel_framehooks(chan))) { + !ast_framehook_list_contains_no_active(ast_channel_framehooks(chan))) { return 0; } else { return 1; diff --git a/include/asterisk/framehook.h b/include/asterisk/framehook.h index 10d525ca73..1b3a83ea5e 100644 --- a/include/asterisk/framehook.h +++ b/include/asterisk/framehook.h @@ -222,7 +222,7 @@ struct ast_framehook_interface { * \param chan ast_channel The channel to attach the hook on to. * \param i framehook interface, The framehook's callback functions and stored data. * - * \pre XXX The Channel must be locked during this function all. + * \pre The Channel must be locked during this function all. * * \note The data pointer is never touched by the framehook API except to * provide it during the event and destruction callbacks. It is entirely up to the @@ -237,7 +237,7 @@ int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interfac * \brief Detach an framehook from a channel. * \since 1.8 * - * \pre XXX The Channel must be locked during this function all. + * \pre The Channel must be locked during this function all. * If this function is never called after attaching an framehook, * the framehook will be detached and destroyed during channel * destruction. @@ -256,7 +256,7 @@ int ast_framehook_detach(struct ast_channel *chan, int framehook_id); * framehooks on a channel during channel destruction. * \since 1.8 * - * \pre XXX The Channel must be locked during this function all. + * \pre The Channel must be locked during this function all. * * \param chan channel containing the framehook list to destroy. * \retval 0 success @@ -272,7 +272,7 @@ int ast_framehook_list_destroy(struct ast_channel *chan); * even NULL. There is nothing to keep up with after this function. If the frame is modified, the * framehook callback is in charge of any memory management associated with that modification. * - * \pre XXX The Channel must be locked during this function all. + * \pre The Channel must be locked during this function all. * * \param framehooks list to push event to. * \param frame being pushed to the framehook list. @@ -289,7 +289,7 @@ struct ast_frame *ast_framehook_list_read_event(struct ast_framehook_list *frame * even NULL. There is nothing to keep up with after this function. If the frame is modified, the * framehook callback is in charge of any memory management associated with that modification. * - * \pre XXX The Channel must be locked during this function all. + * \pre The Channel must be locked during this function all. * * \param framehooks list to push event to. * \param frame being pushed to the framehook list. @@ -301,11 +301,26 @@ struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *fram /*! * \brief Determine if an framehook list is empty or not * \since 1.8 - * \pre XXX The Channel must be locked during this function all. + * \pre The Channel must be locked during this function all. * * \param framehooks the framehook list * \retval 0, not empty * \retval 1, is empty */ int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks); + +/*! + * \brief Determine if a framehook list is free of active framehooks or not + * \since 12.0.0 + * \pre The channel must be locked during this function all. + * + * \param framehooks the framehook list + * \retval 0, not empty + * \retval 1, is empty (aside from dying framehooks) + * + * \note This function is very similar to ast_framehook_list_is_empty, but it checks individual + * framehooks to see if they have been marked for destruction and doesn't count them if they are. + */ +int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks); + #endif /* _AST_FRAMEHOOK_H */ diff --git a/main/framehook.c b/main/framehook.c index 830a4593a2..f85a4c2989 100644 --- a/main/framehook.c +++ b/main/framehook.c @@ -181,6 +181,28 @@ int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks) return AST_LIST_EMPTY(&framehooks->list) ? 1 : 0; } +int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks) +{ + struct ast_framehook *cur; + + if (!framehooks) { + return 1; + } + + if (AST_LIST_EMPTY(&framehooks->list)) { + return 1; + } + + AST_LIST_TRAVERSE(&framehooks->list, cur, list) { + if (cur->detach_and_destroy_me) { + continue; + } + return 0; + } + + return 1; +} + struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *framehooks, struct ast_frame *frame) { return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_WRITE); -- GitLab