From 2fe6b6a5331e41b351774da0b66de40aa2f77ae7 Mon Sep 17 00:00:00 2001 From: Richard Mudgett <rmudgett@digium.com> Date: Sat, 8 Jun 2013 06:31:50 +0000 Subject: [PATCH] Add more support for native bridging. * Added a start technology callback that technologies can use to start bridging operations. It is expected that native bridges will find this useful. * Factored out bridge_channel_complete_join(). git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390991 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk/bridging_technology.h | 13 ++++ main/bridging.c | 104 +++++++++++++++---------- 2 files changed, 75 insertions(+), 42 deletions(-) diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h index 6405545dd9..3c808b1598 100644 --- a/include/asterisk/bridging_technology.h +++ b/include/asterisk/bridging_technology.h @@ -62,6 +62,16 @@ struct ast_bridge_technology { * However, it can be accessed as if it were locked. */ int (*create)(struct ast_bridge *bridge); + /*! + * \brief Request a bridge technology instance start operations. + * + * \retval 0 on success + * \retval -1 on failure + * + * \note On entry, bridge may or may not already be locked. + * However, it can be accessed as if it were locked. + */ + int (*start)(struct ast_bridge *bridge); /*! * \brief Request a bridge technology instance stop in preparation for being destroyed. * @@ -106,6 +116,9 @@ struct ast_bridge_technology { * * \retval 0 if not compatible * \retval non-zero if compatible + * + * \note On entry, bridge may or may not already be locked. + * However, it can be accessed as if it were locked. */ int (*compatible)(struct ast_bridge *bridge); /*! diff --git a/main/bridging.c b/main/bridging.c index 51f52c00ea..0045a2f5eb 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -1093,6 +1093,39 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel) ast_frfree(frame); } +/*! + * \internal + * \brief Complete joining a channel to the bridge. + * \since 12.0.0 + * + * \param bridge What to operate upon. + * \param bridge_channel What is joining the bridge technology. + * + * \note On entry, bridge is already locked. + * + * \return Nothing + */ +static void bridge_channel_complete_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) +{ + /* Make the channel compatible with the bridge */ + bridge_make_compatible(bridge, bridge_channel); + + /* Tell the bridge technology we are joining so they set us up */ + ast_debug(1, "Bridge %s: %p(%s) is joining %s technology\n", + bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), + bridge->technology->name); + if (bridge->technology->join + && bridge->technology->join(bridge, bridge_channel)) { + ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology\n", + bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), + bridge->technology->name); + bridge_channel->just_joined = 1; + return; + } + + bridge_channel->just_joined = 0; +} + /*! * \internal * \brief Complete joining new channels to the bridge. @@ -1123,22 +1156,7 @@ static void bridge_complete_join(struct ast_bridge *bridge) if (!bridge_channel->just_joined) { continue; } - - /* Make the channel compatible with the bridge */ - bridge_make_compatible(bridge, bridge_channel); - - /* Tell the bridge technology we are joining so they set us up */ - ast_debug(1, "Bridge %s: %p(%s) is joining %s technology\n", - bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), - bridge->technology->name); - if (bridge->technology->join - && bridge->technology->join(bridge, bridge_channel)) { - ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology\n", - bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), - bridge->technology->name); - } - - bridge_channel->just_joined = 0; + bridge_channel_complete_join(bridge, bridge_channel); } } @@ -1414,6 +1432,14 @@ struct ast_bridge *ast_bridge_base_init(struct ast_bridge *self, uint32_t capabi ao2_ref(self, -1); return NULL; } + ast_debug(1, "Bridge %s: calling %s technology start\n", + self->uniqueid, self->technology->name); + if (self->technology->start && self->technology->start(self)) { + ast_debug(1, "Bridge %s: failed to start %s technology\n", + self->uniqueid, self->technology->name); + ao2_ref(self, -1); + return NULL; + } if (!ast_bridge_topic(self)) { ao2_ref(self, -1); @@ -1756,36 +1782,30 @@ static int smart_bridge_operation(struct ast_bridge *bridge) old_technology->stop(&dummy_bridge); } - /* Move existing channels over to the new technology. */ + /* + * Move existing channels over to the new technology and + * complete joining any new channels to the bridge. + */ AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { - if (bridge_channel->just_joined) { - /* - * This channel has not completed joining the bridge so it is - * not in the old bridge technology. - */ - continue; - } - - /* First we part them from the old technology */ - ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology (dummy)\n", - dummy_bridge.uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), - old_technology->name); - if (old_technology->leave) { - old_technology->leave(&dummy_bridge, bridge_channel); + if (!bridge_channel->just_joined) { + /* Take existing channel from the old technology. */ + ast_debug(1, "Bridge %s: %p(%s) is leaving %s technology (dummy)\n", + dummy_bridge.uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), + old_technology->name); + if (old_technology->leave) { + old_technology->leave(&dummy_bridge, bridge_channel); + } } - /* Second we make them compatible again with the bridge */ - bridge_make_compatible(bridge, bridge_channel); + /* Add any new channels or re-add an existing channel to the bridge. */ + bridge_channel_complete_join(bridge, bridge_channel); + } - /* Third we join them to the new technology */ - ast_debug(1, "Bridge %s: %p(%s) is joining %s technology\n", - bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), - new_technology->name); - if (new_technology->join && new_technology->join(bridge, bridge_channel)) { - ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology\n", - bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan), - new_technology->name); - } + ast_debug(1, "Bridge %s: calling %s technology start\n", + bridge->uniqueid, new_technology->name); + if (new_technology->start && new_technology->start(bridge)) { + ast_log(LOG_WARNING, "Bridge %s: failed to start bridge technology %s\n", + bridge->uniqueid, new_technology->name); } /* -- GitLab