diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-05-21 18:00:22 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-05-21 18:00:22 +0000 |
commit | 3d63833bd6c869b7efa383e8dea14be1a6eff998 (patch) | |
tree | 34957dd051b8f67c7cc58a510e24ee3873a61ad4 /main/bridging_basic.c | |
parent | e1e1cc2deefb92f8b43825f1f34e619354737842 (diff) |
Merge in the bridge_construction branch to make the system use the Bridging API.
Breaks many things until they can be reworked. A partial list:
chan_agent
chan_dahdi, chan_misdn, chan_iax2 native bridging
app_queue
COLP updates
DTMF attended transfers
Protocol attended transfers
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@389378 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/bridging_basic.c')
-rw-r--r-- | main/bridging_basic.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/main/bridging_basic.c b/main/bridging_basic.c new file mode 100644 index 000000000..00daf7710 --- /dev/null +++ b/main/bridging_basic.c @@ -0,0 +1,159 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013 Digium, Inc. + * + * Richard Mudgett <rmudgett@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! + * \file + * \brief Basic bridge class. It is a subclass of struct ast_bridge. + * + * \author Richard Mudgett <rmudgett@digium.com> + * + * See Also: + * \arg \ref AstCREDITS + */ + + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/channel.h" +#include "asterisk/utils.h" +#include "asterisk/linkedlists.h" +#include "asterisk/bridging.h" +#include "asterisk/bridging_basic.h" +#include "asterisk/astobj2.h" + +/* ------------------------------------------------------------------- */ + +static const struct ast_datastore_info dtmf_features_info = { + .type = "bridge-dtmf-features", + .destroy = ast_free_ptr, +}; + +int ast_bridge_features_ds_set(struct ast_channel *chan, struct ast_flags *flags) +{ + struct ast_datastore *datastore; + struct ast_flags *ds_flags; + + datastore = ast_channel_datastore_find(chan, &dtmf_features_info, NULL); + if (datastore) { + ds_flags = datastore->data; + *ds_flags = *flags; + return 0; + } + + datastore = ast_datastore_alloc(&dtmf_features_info, NULL); + if (!datastore) { + return -1; + } + + ds_flags = ast_malloc(sizeof(*ds_flags)); + if (!ds_flags) { + ast_datastore_free(datastore); + return -1; + } + + *ds_flags = *flags; + datastore->data = ds_flags; + ast_channel_datastore_add(chan, datastore); + return 0; +} + +struct ast_flags *ast_bridge_features_ds_get(struct ast_channel *chan) +{ + struct ast_datastore *datastore; + + datastore = ast_channel_datastore_find(chan, &dtmf_features_info, NULL); + if (!datastore) { + return NULL; + } + return datastore->data; +} + +/*! + * \internal + * \brief Determine if we should dissolve the bridge from a hangup. + * \since 12.0.0 + * + * \param bridge The bridge that the channel is part of + * \param bridge_channel Channel executing the feature + * \param hook_pvt Private data passed in when the hook was created + * + * \retval 0 Keep the callback hook. + * \retval -1 Remove the callback hook. + */ +static int basic_hangup_hook(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt) +{ +/* BUGBUG Race condition. If all parties but one hangup at the same time, the bridge may not be dissolved on the remaining party. */ + ast_bridge_channel_lock_bridge(bridge_channel); + if (2 < bridge_channel->bridge->num_channels) { + /* Just allow this channel to leave the multi-party bridge. */ + ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP); + } + ast_bridge_unlock(bridge_channel->bridge); + return 0; +} + +/*! + * \internal + * \brief ast_bridge basic push method. + * \since 12.0.0 + * + * \param self Bridge to operate upon. + * \param bridge_channel Bridge channel to push. + * \param swap Bridge channel to swap places with if not NULL. + * + * \note On entry, self is already locked. + * \note Stub because of nothing to do. + * + * \retval 0 on success + * \retval -1 on failure + */ +static int bridge_basic_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap) +{ + if (ast_bridge_hangup_hook(bridge_channel->features, basic_hangup_hook, NULL, NULL, 1) + || ast_bridge_channel_setup_features(bridge_channel)) { + return -1; + } + + return ast_bridge_base_v_table.push(self, bridge_channel, swap); +} + +struct ast_bridge_methods ast_bridge_basic_v_table; + +struct ast_bridge *ast_bridge_basic_new(void) +{ + void *bridge; + + bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table); + bridge = ast_bridge_base_init(bridge, + AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX + | AST_BRIDGE_CAPABILITY_MULTIMIX, + AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY + | AST_BRIDGE_FLAG_SMART); + bridge = ast_bridge_register(bridge); + return bridge; +} + +void ast_bridging_init_basic(void) +{ + /* Setup bridge basic subclass v_table. */ + ast_bridge_basic_v_table = ast_bridge_base_v_table; + ast_bridge_basic_v_table.name = "basic"; + ast_bridge_basic_v_table.push = bridge_basic_push; +} |