Merge "Bridge system: Fix memory leaks and double frees on impart failure."
[asterisk/asterisk.git] / res / stasis / stasis_bridge.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, 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 Stasis bridge subclass.
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_REGISTER_FILE()
33
34 #include "asterisk/bridge.h"
35 #include "asterisk/bridge_after.h"
36 #include "asterisk/bridge_internal.h"
37 #include "asterisk/bridge_features.h"
38 #include "asterisk/stasis_app.h"
39 #include "asterisk/stasis_channels.h"
40 #include "stasis_bridge.h"
41 #include "control.h"
42 #include "command.h"
43 #include "app.h"
44 #include "asterisk/stasis_app.h"
45 #include "asterisk/pbx.h"
46
47 /* ------------------------------------------------------------------- */
48
49 static struct ast_bridge_methods bridge_stasis_v_table;
50
51 static void bridge_stasis_run_cb(struct ast_channel *chan, void *data)
52 {
53         RAII_VAR(char *, app_name, NULL, ast_free);
54         struct ast_app *app_stasis;
55
56         /* Take ownership of the swap_app memory from the datastore */
57         app_name = app_get_replace_channel_app(chan);
58         if (!app_name) {
59                 ast_log(LOG_ERROR, "Failed to get app name for %s (%p)\n", ast_channel_name(chan), chan);
60                 return;
61         }
62
63         /* find Stasis() */
64         app_stasis = pbx_findapp("Stasis");
65         if (!app_stasis) {
66                 ast_log(LOG_WARNING, "Could not find application (Stasis)\n");
67                 return;
68         }
69
70         if (ast_check_hangup_locked(chan)) {
71                 /* channel hungup, don't run Stasis() */
72                 return;
73         }
74
75         /* run Stasis() */
76         pbx_exec(chan, app_stasis, app_name);
77 }
78
79 struct defer_bridge_add_obj {
80         /*! Bridge to join (has ref) */
81         struct ast_bridge *bridge;
82         /*!
83          * \brief Channel to swap with in the bridge. (has ref)
84          *
85          * \note NULL if not swapping with a channel.
86          */
87         struct ast_channel *swap;
88 };
89
90 static void defer_bridge_add_dtor(void *obj)
91 {
92         struct defer_bridge_add_obj *defer = obj;
93
94         ao2_cleanup(defer->bridge);
95         ast_channel_cleanup(defer->swap);
96 }
97
98 static int defer_bridge_add(
99         struct stasis_app_control *control,
100         struct ast_channel *chan, void *obj)
101 {
102         struct defer_bridge_add_obj *defer = obj;
103
104         return control_swap_channel_in_bridge(control, defer->bridge, chan, defer->swap);
105 }
106
107 static void bridge_stasis_queue_join_action(struct ast_bridge *self,
108         struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
109 {
110         struct defer_bridge_add_obj *defer;
111
112         defer = ao2_alloc_options(sizeof(*defer), defer_bridge_add_dtor,
113                 AO2_ALLOC_OPT_LOCK_NOLOCK);
114         if (!defer) {
115                 return;
116         }
117         ao2_ref(self, +1);
118         defer->bridge = self;
119         if (swap) {
120                 ast_channel_ref(swap->chan);
121                 defer->swap = swap->chan;
122         }
123
124         ast_channel_lock(bridge_channel->chan);
125         command_prestart_queue_command(bridge_channel->chan, defer_bridge_add,
126                 defer, __ao2_cleanup);
127         ast_channel_unlock(bridge_channel->chan);
128 }
129
130 /*!
131  * \internal
132  * \brief Peek at channel before it is pushed into bridge
133  * \since 13.2.0
134  *
135  * \param self Bridge to operate upon.
136  * \param bridge_channel Bridge channel to push.
137  * \param swap Bridge channel to swap places with if not NULL.
138  *
139  * \note On entry, self is already locked.
140  *
141  * \retval 0 on success.
142  * \retval -1 on failure.  The channel should not be pushed.
143  */
144 static int bridge_stasis_push_peek(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
145 {
146         struct stasis_app_control *swap_control;
147         struct ast_channel_snapshot *to_be_replaced;
148
149         if (!swap) {
150                 goto done;
151         }
152
153         swap_control = stasis_app_control_find_by_channel(swap->chan);
154         if (!swap_control) {
155                 ast_log(LOG_ERROR,"Failed to find stasis app control for swapped channel %s\n", ast_channel_name(swap->chan));
156                 return -1;
157         }
158         to_be_replaced = ast_channel_snapshot_get_latest(ast_channel_uniqueid(swap->chan));
159
160         ast_debug(3, "Copying stasis app name %s from %s to %s\n", app_name(control_app(swap_control)),
161                 ast_channel_name(swap->chan), ast_channel_name(bridge_channel->chan));
162
163         ast_channel_lock(bridge_channel->chan);
164
165         /* copy the app name from the swap channel */
166         app_set_replace_channel_app(bridge_channel->chan, app_name(control_app(swap_control)));
167
168         /* set the replace channel snapshot */
169         app_set_replace_channel_snapshot(bridge_channel->chan, to_be_replaced);
170
171         ast_channel_unlock(bridge_channel->chan);
172
173         ao2_ref(swap_control, -1);
174         ao2_cleanup(to_be_replaced);
175
176 done:
177         return ast_bridge_base_v_table.push_peek(self, bridge_channel, swap);
178 }
179
180 /*!
181  * \internal
182  * \brief Push this channel into the Stasis bridge.
183  * \since 12.5.0
184  *
185  * \param self Bridge to operate upon.
186  * \param bridge_channel Bridge channel to push.
187  * \param swap Bridge channel to swap places with if not NULL.
188  *
189  * \note On entry, self is already locked.
190  *
191  * \retval 0 on success.
192  * \retval -1 on failure.  The channel did not get pushed.
193  */
194 static int bridge_stasis_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
195 {
196         struct stasis_app_control *control = stasis_app_control_find_by_channel(bridge_channel->chan);
197
198         if (!control && !stasis_app_channel_is_internal(bridge_channel->chan)) {
199                 /* channel not in Stasis(), get it there */
200                 ast_debug(1, "Bridge %s: pushing non-stasis %p(%s) setup to come back in under stasis\n",
201                         self->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
202
203                 /* Attach after-bridge callback and pass ownership of swap_app to it */
204                 if (ast_bridge_set_after_callback(bridge_channel->chan,
205                         bridge_stasis_run_cb, NULL, NULL)) {
206                         ast_log(LOG_ERROR,
207                                 "Failed to set after bridge callback for bridge %s non-stasis push of %s\n",
208                                 self->uniqueid, ast_channel_name(bridge_channel->chan));
209                         return -1;
210                 }
211
212                 bridge_stasis_queue_join_action(self, bridge_channel, swap);
213
214                 /* Return -1 so the push fails and the after-bridge callback gets called
215                  * This keeps the bridging framework from putting the channel into the bridge
216                  * until the Stasis thread gets started, and then the channel is put into the bridge.
217                  */
218                 return -1;
219         }
220
221         /*
222          * If going into a holding bridge, default the role to participant, if
223          * it has no compatible role currently
224          */
225         if ((self->technology->capabilities & AST_BRIDGE_CAPABILITY_HOLDING)
226             && !ast_channel_has_role(bridge_channel->chan, "announcer")
227             && !ast_channel_has_role(bridge_channel->chan, "holding_participant")) {
228                 if (ast_channel_add_bridge_role(bridge_channel->chan, "holding_participant")) {
229                         ast_log(LOG_ERROR, "Failed to set holding participant on %s\n", ast_channel_name(bridge_channel->chan));
230                         return -1;
231                 }
232
233                 if (ast_channel_set_bridge_role_option(bridge_channel->chan, "holding_participant", "idle_mode", "none")) {
234                         ast_log(LOG_ERROR, "Failed to set holding participant mode on %s\n", ast_channel_name(bridge_channel->chan));
235                         return -1;
236                 }
237         }
238
239         ao2_cleanup(control);
240         if (self->allowed_capabilities & STASIS_BRIDGE_MIXING_CAPABILITIES) {
241                 ast_bridge_channel_update_linkedids(bridge_channel, swap);
242                 if (ast_test_flag(&self->feature_flags, AST_BRIDGE_FLAG_SMART)) {
243                         ast_bridge_channel_update_accountcodes(bridge_channel, swap);
244                 }
245         }
246
247         return ast_bridge_base_v_table.push(self, bridge_channel, swap);
248 }
249
250 static int bridge_stasis_moving(struct ast_bridge_channel *bridge_channel, void *hook_pvt,
251                 struct ast_bridge *src, struct ast_bridge *dst)
252 {
253         if (src->v_table == &bridge_stasis_v_table &&
254                         dst->v_table != &bridge_stasis_v_table) {
255                 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
256                 struct ast_channel *chan;
257
258                 chan = bridge_channel->chan;
259                 ast_assert(chan != NULL);
260
261                 control = stasis_app_control_find_by_channel(chan);
262                 if (!control) {
263                         return -1;
264                 }
265
266                 stasis_app_channel_set_stasis_end_published(chan);
267                 app_send_end_msg(control_app(control), chan);
268         }
269
270         return -1;
271 }
272
273 /*!
274  * \internal
275  * \brief Pull this channel from the Stasis bridge.
276  * \since 12.5.0
277  *
278  * \param self Bridge to operate upon.
279  * \param bridge_channel Bridge channel to pull.
280  *
281  * \note On entry, self is already locked.
282  *
283  * \return Nothing
284  */
285 static void bridge_stasis_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
286 {
287         if ((self->allowed_capabilities & STASIS_BRIDGE_MIXING_CAPABILITIES)
288                 && ast_test_flag(&self->feature_flags, AST_BRIDGE_FLAG_SMART)) {
289                 ast_bridge_channel_update_accountcodes(NULL, bridge_channel);
290         }
291
292         if (self->technology->capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
293                 ast_channel_clear_bridge_roles(bridge_channel->chan);
294         }
295
296         ast_bridge_move_hook(bridge_channel->features, bridge_stasis_moving, NULL, NULL, 0);
297
298         ast_bridge_base_v_table.pull(self, bridge_channel);
299 }
300
301 struct ast_bridge *bridge_stasis_new(uint32_t capabilities, unsigned int flags, const char *name, const char *id)
302 {
303         void *bridge;
304
305         bridge = bridge_alloc(sizeof(struct ast_bridge), &bridge_stasis_v_table);
306         bridge = bridge_base_init(bridge, capabilities, flags, "Stasis", name, id);
307         bridge = bridge_register(bridge);
308
309         return bridge;
310 }
311
312 void bridge_stasis_init(void)
313 {
314         /* Setup the Stasis bridge subclass v_table. */
315         bridge_stasis_v_table = ast_bridge_base_v_table;
316         bridge_stasis_v_table.name = "stasis";
317         bridge_stasis_v_table.push = bridge_stasis_push;
318         bridge_stasis_v_table.pull = bridge_stasis_pull;
319         bridge_stasis_v_table.push_peek = bridge_stasis_push_peek;
320 }