Merge "res_calendar: Specialized calendars depend on symbols of general calendar."
[asterisk/asterisk.git] / main / bridge.c
index b732d5f..4f79852 100644 (file)
@@ -234,8 +234,21 @@ int __ast_bridge_technology_register(struct ast_bridge_technology *technology, s
        /* Copy module pointer so reference counting can keep the module from unloading */
        technology->mod = module;
 
-       /* Insert our new bridge technology into the list and print out a pretty message */
-       AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
+       /* Find the correct position to insert the technology. */
+       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) {
+               /* Put the highest preference tech's first in the list. */
+               if (technology->preference >= current->preference) {
+                       AST_RWLIST_INSERT_BEFORE_CURRENT(technology, entry);
+
+                       break;
+               }
+       }
+       AST_RWLIST_TRAVERSE_SAFE_END;
+
+       if (!current) {
+               /* Insert our new bridge technology to the end of the list. */
+               AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
+       }
 
        AST_RWLIST_UNLOCK(&bridge_technologies);
 
@@ -517,12 +530,17 @@ static struct ast_bridge_technology *find_best_technology(uint32_t capabilities,
                                current->name);
                        continue;
                }
+               if (!ast_module_running_ref(current->mod)) {
+                       ast_debug(1, "Bridge technology %s is not running, skipping.\n", current->name);
+                       continue;
+               }
+               if (best) {
+                       ast_module_unref(best->mod);
+               }
                best = current;
        }
 
        if (best) {
-               /* Increment it's module reference count if present so it does not get unloaded while in use */
-               ast_module_ref(best->mod);
                ast_debug(1, "Chose bridge technology %s\n", best->name);
        }
 
@@ -1741,7 +1759,7 @@ int ast_bridge_join(struct ast_bridge *bridge,
 
        ao2_ref(bridge_channel, -1);
 
-join_exit:;
+join_exit:
        ast_bridge_run_after_callback(chan);
        bridge_channel_impart_signal(chan);
        if (!(ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO)
@@ -1758,12 +1776,13 @@ join_exit:;
 static void *bridge_channel_depart_thread(void *data)
 {
        struct ast_bridge_channel *bridge_channel = data;
+       int res = 0;
 
        if (bridge_channel->callid) {
                ast_callid_threadassoc_add(bridge_channel->callid);
        }
 
-       bridge_channel_internal_join(bridge_channel);
+       res = bridge_channel_internal_join(bridge_channel);
 
        /*
         * cleanup
@@ -1775,7 +1794,8 @@ static void *bridge_channel_depart_thread(void *data)
        ast_bridge_features_destroy(bridge_channel->features);
        bridge_channel->features = NULL;
 
-       ast_bridge_discard_after_callback(bridge_channel->chan, AST_BRIDGE_AFTER_CB_REASON_DEPART);
+       ast_bridge_discard_after_callback(bridge_channel->chan,
+               res ? AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED : AST_BRIDGE_AFTER_CB_REASON_DEPART);
        /* If join failed there will be impart threads waiting. */
        bridge_channel_impart_signal(bridge_channel->chan);
        ast_bridge_discard_after_goto(bridge_channel->chan);
@@ -2509,6 +2529,8 @@ int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan,
        RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
        RAII_VAR(struct ast_channel *, yanked_chan, NULL, ao2_cleanup);
 
+       ast_moh_stop(chan);
+
        ast_channel_lock(chan);
        chan_bridge = ast_channel_get_bridge(chan);
        ast_channel_unlock(chan);
@@ -3844,7 +3866,7 @@ void ast_bridge_update_talker_src_video_mode(struct ast_bridge *bridge, struct a
                data->average_talking_energy = talker_energy;
        } else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
                if (data->chan_old_vsrc) {
-                       ast_channel_unref(data->chan_old_vsrc);
+                       data->chan_old_vsrc = ast_channel_unref(data->chan_old_vsrc);
                }
                if (data->chan_vsrc) {
                        data->chan_old_vsrc = data->chan_vsrc;