struct ast_format *slin_format;
int setup_fail;
+ /* The callers have already ensured that sc is never NULL. */
+ ast_assert(sc != NULL);
+
slin_format = ast_format_cache_get_slin_by_rate(rate);
ast_mutex_lock(&sc->lock);
{
int res = 0;
- if (!bridge->tech_pvt || (bridge_channel && !bridge_channel->tech_pvt)) {
+ if (!bridge->tech_pvt || !bridge_channel || !bridge_channel->tech_pvt) {
/* "Accept" the frame and discard it. */
return 0;
}
AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
struct softmix_channel *sc = bridge_channel->tech_pvt;
+ if (!sc) {
+ /* This channel failed to join successfully. */
+ continue;
+ }
+
/* Update the sample rate to match the bridge's native sample rate if necessary. */
if (update_all_rates) {
set_softmix_bridge_data(softmix_data->internal_rate, softmix_data->internal_mixing_interval, bridge_channel, 1);
AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
struct softmix_channel *sc = bridge_channel->tech_pvt;
- if (bridge_channel->suspended) {
+ if (!sc || bridge_channel->suspended) {
+ /* This channel failed to join successfully or is suspended. */
continue;
}
* \retval -1 on failure
*
* \note On entry, bridge is already locked.
+ *
+ * \note The bridge technology must tollerate a failed to join channel
+ * until it can be kicked from the bridge.
*/
int (*join)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
/*!
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",
+ /* We cannot leave the channel partially in the bridge so we must kick it out */
+ ast_debug(1, "Bridge %s: %p(%s) failed to join %s technology (Kicking it out)\n",
bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan),
bridge->technology->name);
bridge_channel->just_joined = 1;
+ ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END, 0);
return;
}
#include "asterisk/bridge.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/features.h"
+#include "asterisk/format_cache.h"
#define TEST_CATEGORY "/channels/features/"
#define TEST_BACKEND_NAME "Features Test Logging"
+#define TEST_CHANNEL_FORMAT ast_format_slin
+
/*! \brief A channel technology used for the unit tests */
static struct ast_channel_tech test_features_chan_tech = {
.type = CHANNEL_TECH_NAME,
#define START_CHANNEL(channel, name, number) do { \
channel = ast_channel_alloc(0, AST_STATE_UP, number, name, number, number, \
"default", NULL, NULL, 0, CHANNEL_TECH_NAME "/" name); \
+ ast_channel_nativeformats_set(channel, test_features_chan_tech.capabilities); \
+ ast_channel_set_rawwriteformat(channel, TEST_CHANNEL_FORMAT); \
+ ast_channel_set_rawreadformat(channel, TEST_CHANNEL_FORMAT); \
+ ast_channel_set_writeformat(channel, TEST_CHANNEL_FORMAT); \
+ ast_channel_set_readformat(channel, TEST_CHANNEL_FORMAT); \
ast_channel_unlock(channel); \
} while (0)
AST_TEST_UNREGISTER(test_features_channel_interval);
ast_channel_unregister(&test_features_chan_tech);
+ ao2_cleanup(test_features_chan_tech.capabilities);
+ test_features_chan_tech.capabilities = NULL;
return 0;
}
static int load_module(void)
{
+ test_features_chan_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!test_features_chan_tech.capabilities) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+ ast_format_cap_append(test_features_chan_tech.capabilities, TEST_CHANNEL_FORMAT, 0);
ast_channel_register(&test_features_chan_tech);
AST_TEST_REGISTER(test_features_channel_dtmf);