Remove stub comment on function that is not a stub.
[asterisk/asterisk.git] / main / bridging_basic.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013 Digium, Inc.
5  *
6  * Richard Mudgett <rmudgett@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Basic bridge class.  It is a subclass of struct ast_bridge.
22  *
23  * \author Richard Mudgett <rmudgett@digium.com>
24  *
25  * See Also:
26  * \arg \ref AstCREDITS
27  */
28
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/channel.h"
35 #include "asterisk/utils.h"
36 #include "asterisk/linkedlists.h"
37 #include "asterisk/bridging.h"
38 #include "asterisk/bridging_basic.h"
39 #include "asterisk/astobj2.h"
40
41 /* ------------------------------------------------------------------- */
42
43 static const struct ast_datastore_info dtmf_features_info = {
44         .type = "bridge-dtmf-features",
45         .destroy = ast_free_ptr,
46 };
47
48 int ast_bridge_features_ds_set(struct ast_channel *chan, struct ast_flags *flags)
49 {
50         struct ast_datastore *datastore;
51         struct ast_flags *ds_flags;
52
53         datastore = ast_channel_datastore_find(chan, &dtmf_features_info, NULL);
54         if (datastore) {
55                 ds_flags = datastore->data;
56                 *ds_flags = *flags;
57                 return 0;
58         }
59
60         datastore = ast_datastore_alloc(&dtmf_features_info, NULL);
61         if (!datastore) {
62                 return -1;
63         }
64
65         ds_flags = ast_malloc(sizeof(*ds_flags));
66         if (!ds_flags) {
67                 ast_datastore_free(datastore);
68                 return -1;
69         }
70
71         *ds_flags = *flags;
72         datastore->data = ds_flags;
73         ast_channel_datastore_add(chan, datastore);
74         return 0;
75 }
76
77 struct ast_flags *ast_bridge_features_ds_get(struct ast_channel *chan)
78 {
79         struct ast_datastore *datastore;
80
81         datastore = ast_channel_datastore_find(chan, &dtmf_features_info, NULL);
82         if (!datastore) {
83                 return NULL;
84         }
85         return datastore->data;
86 }
87
88 /*!
89  * \internal
90  * \brief Determine if we should dissolve the bridge from a hangup.
91  * \since 12.0.0
92  *
93  * \param bridge The bridge that the channel is part of
94  * \param bridge_channel Channel executing the feature
95  * \param hook_pvt Private data passed in when the hook was created
96  *
97  * \retval 0 Keep the callback hook.
98  * \retval -1 Remove the callback hook.
99  */
100 static int basic_hangup_hook(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
101 {
102 /* BUGBUG Race condition.  If all parties but one hangup at the same time, the bridge may not be dissolved on the remaining party. */
103         ast_bridge_channel_lock_bridge(bridge_channel);
104         if (2 < bridge_channel->bridge->num_channels) {
105                 /* Just allow this channel to leave the multi-party bridge. */
106                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
107         }
108         ast_bridge_unlock(bridge_channel->bridge);
109         return 0;
110 }
111
112 /*!
113  * \internal
114  * \brief ast_bridge basic push method.
115  * \since 12.0.0
116  *
117  * \param self Bridge to operate upon.
118  * \param bridge_channel Bridge channel to push.
119  * \param swap Bridge channel to swap places with if not NULL.
120  *
121  * \note On entry, self is already locked.
122  *
123  * \retval 0 on success
124  * \retval -1 on failure
125  */
126 static int bridge_basic_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
127 {
128         if (ast_bridge_hangup_hook(bridge_channel->features, basic_hangup_hook, NULL, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)
129                 || ast_bridge_channel_setup_features(bridge_channel)) {
130                 return -1;
131         }
132
133         ast_bridge_update_accountcodes(self, bridge_channel, swap);
134         ast_bridge_update_linkedids(self, bridge_channel, swap);
135
136         return ast_bridge_base_v_table.push(self, bridge_channel, swap);
137 }
138
139 struct ast_bridge_methods ast_bridge_basic_v_table;
140
141 struct ast_bridge *ast_bridge_basic_new(void)
142 {
143         void *bridge;
144
145         bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
146         bridge = ast_bridge_base_init(bridge,
147                 AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
148                         | AST_BRIDGE_CAPABILITY_MULTIMIX,
149                 AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY
150                         | AST_BRIDGE_FLAG_SMART);
151         bridge = ast_bridge_register(bridge);
152         return bridge;
153 }
154
155 void ast_bridging_init_basic(void)
156 {
157         /* Setup bridge basic subclass v_table. */
158         ast_bridge_basic_v_table = ast_bridge_base_v_table;
159         ast_bridge_basic_v_table.name = "basic";
160         ast_bridge_basic_v_table.push = bridge_basic_push;
161 }