a41f8a5483f3eab0582985a16c6f078efe4d5a4a
[asterisk/asterisk.git] / main / bridge_after.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007 - 2009, 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 After Bridge Execution API
22  *
23  * \author Richard Mudgett <rmudgett@digium.com>
24  *
25  * See Also:
26  * \arg \ref AstCREDITS
27  */
28
29 /*** MODULEINFO
30         <support_level>core</support_level>
31  ***/
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include "asterisk/logger.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/bridge_after.h"
41
42 struct after_bridge_cb_node {
43         /*! Next list node. */
44         AST_LIST_ENTRY(after_bridge_cb_node) list;
45         /*! Desired callback function. */
46         ast_bridge_after_cb callback;
47         /*! After bridge callback will not be called and destroy any resources data may contain. */
48         ast_bridge_after_cb_failed failed;
49         /*! Extra data to pass to the callback. */
50         void *data;
51         /*! Reason the after bridge callback failed. */
52         enum ast_bridge_after_cb_reason reason;
53 };
54
55 struct after_bridge_cb_ds {
56         /*! After bridge callbacks container. */
57         AST_LIST_HEAD(, after_bridge_cb_node) callbacks;
58 };
59
60 /*!
61  * \internal
62  * \brief Indicate after bridge callback failed.
63  * \since 12.0.0
64  *
65  * \param node After bridge callback node.
66  *
67  * \return Nothing
68  */
69 static void after_bridge_cb_failed(struct after_bridge_cb_node *node)
70 {
71         if (node->failed) {
72                 node->failed(node->reason, node->data);
73                 node->failed = NULL;
74         }
75 }
76
77 /*!
78  * \internal
79  * \brief Run discarding any after bridge callbacks.
80  * \since 12.0.0
81  *
82  * \param after_bridge After bridge callback container process.
83  * \param reason Why are we doing this.
84  *
85  * \return Nothing
86  */
87 static void after_bridge_cb_run_discard(struct after_bridge_cb_ds *after_bridge, enum ast_bridge_after_cb_reason reason)
88 {
89         struct after_bridge_cb_node *node;
90
91         for (;;) {
92                 AST_LIST_LOCK(&after_bridge->callbacks);
93                 node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
94                 AST_LIST_UNLOCK(&after_bridge->callbacks);
95                 if (!node) {
96                         break;
97                 }
98                 if (!node->reason) {
99                         node->reason = reason;
100                 }
101                 after_bridge_cb_failed(node);
102                 ast_free(node);
103         }
104 }
105
106 /*!
107  * \internal
108  * \brief Destroy the after bridge callback datastore.
109  * \since 12.0.0
110  *
111  * \param data After bridge callback data to destroy.
112  *
113  * \return Nothing
114  */
115 static void after_bridge_cb_destroy(void *data)
116 {
117         struct after_bridge_cb_ds *after_bridge = data;
118
119         after_bridge_cb_run_discard(after_bridge, AST_BRIDGE_AFTER_CB_REASON_DESTROY);
120
121         AST_LIST_HEAD_DESTROY(&after_bridge->callbacks);
122         ast_free(after_bridge);
123 }
124
125 static struct after_bridge_cb_ds *after_bridge_cb_find(struct ast_channel *chan);
126
127 /*!
128  * \internal
129  * \brief Fixup the after bridge callback datastore.
130  * \since 12.0.0
131  *
132  * \param data After bridge callback data to fixup.
133  * \param old_chan The datastore is moving from this channel.
134  * \param new_chan The datastore is moving to this channel.
135  *
136  * \return Nothing
137  */
138 static void after_bridge_cb_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
139 {
140         struct after_bridge_cb_ds *after_bridge;
141         struct after_bridge_cb_node *node;
142
143         after_bridge = after_bridge_cb_find(new_chan);
144         if (!after_bridge) {
145                 return;
146         }
147
148         AST_LIST_LOCK(&after_bridge->callbacks);
149         node = AST_LIST_LAST(&after_bridge->callbacks);
150         if (node && !node->reason) {
151                 node->reason = AST_BRIDGE_AFTER_CB_REASON_MASQUERADE;
152         }
153         AST_LIST_UNLOCK(&after_bridge->callbacks);
154 }
155
156 static const struct ast_datastore_info after_bridge_cb_info = {
157         .type = "after-bridge-cb",
158         .destroy = after_bridge_cb_destroy,
159         .chan_fixup = after_bridge_cb_fixup,
160 };
161
162 /*!
163  * \internal
164  * \brief Find an after bridge callback datastore container.
165  * \since 12.0.0
166  *
167  * \param chan Channel to find the after bridge callback container on.
168  *
169  * \retval after_bridge datastore container on success.
170  * \retval NULL on error.
171  */
172 static struct after_bridge_cb_ds *after_bridge_cb_find(struct ast_channel *chan)
173 {
174         struct ast_datastore *datastore;
175         SCOPED_CHANNELLOCK(lock, chan);
176
177         datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
178         if (!datastore) {
179                 return NULL;
180         }
181         return datastore->data;
182 }
183
184 /*!
185  * \internal
186  * \brief Setup/create an after bridge callback datastore container.
187  * \since 12.0.0
188  *
189  * \param chan Channel to setup/create the after bridge callback container on.
190  *
191  * \retval after_bridge datastore container on success.
192  * \retval NULL on error.
193  */
194 static struct after_bridge_cb_ds *after_bridge_cb_setup(struct ast_channel *chan)
195 {
196         struct ast_datastore *datastore;
197         struct after_bridge_cb_ds *after_bridge;
198         SCOPED_CHANNELLOCK(lock, chan);
199
200         datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
201         if (datastore) {
202                 return datastore->data;
203         }
204
205         /* Create a new datastore. */
206         datastore = ast_datastore_alloc(&after_bridge_cb_info, NULL);
207         if (!datastore) {
208                 return NULL;
209         }
210         after_bridge = ast_calloc(1, sizeof(*after_bridge));
211         if (!after_bridge) {
212                 ast_datastore_free(datastore);
213                 return NULL;
214         }
215         AST_LIST_HEAD_INIT(&after_bridge->callbacks);
216         datastore->data = after_bridge;
217         ast_channel_datastore_add(chan, datastore);
218
219         return datastore->data;
220 }
221
222 void ast_bridge_run_after_callback(struct ast_channel *chan)
223 {
224         struct after_bridge_cb_ds *after_bridge;
225         struct after_bridge_cb_node *node;
226
227         after_bridge = after_bridge_cb_find(chan);
228         if (!after_bridge) {
229                 return;
230         }
231
232         for (;;) {
233                 AST_LIST_LOCK(&after_bridge->callbacks);
234                 node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
235                 AST_LIST_UNLOCK(&after_bridge->callbacks);
236                 if (!node) {
237                         break;
238                 }
239                 if (node->reason) {
240                         after_bridge_cb_failed(node);
241                 } else {
242                         node->failed = NULL;
243                         node->callback(chan, node->data);
244                 }
245                 ast_free(node);
246         }
247 }
248
249 void ast_bridge_discard_after_callback(struct ast_channel *chan, enum ast_bridge_after_cb_reason reason)
250 {
251         struct after_bridge_cb_ds *after_bridge;
252
253         after_bridge = after_bridge_cb_find(chan);
254         if (!after_bridge) {
255                 return;
256         }
257
258         after_bridge_cb_run_discard(after_bridge, reason);
259 }
260
261 int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
262 {
263         struct after_bridge_cb_ds *after_bridge;
264         struct after_bridge_cb_node *new_node;
265         struct after_bridge_cb_node *last_node;
266
267         /* Sanity checks. */
268         ast_assert(chan != NULL);
269         if (!chan || !callback) {
270                 return -1;
271         }
272
273         after_bridge = after_bridge_cb_setup(chan);
274         if (!after_bridge) {
275                 return -1;
276         }
277
278         /* Create a new callback node. */
279         new_node = ast_calloc(1, sizeof(*new_node));
280         if (!new_node) {
281                 return -1;
282         }
283         new_node->callback = callback;
284         new_node->failed = failed;
285         new_node->data = data;
286
287         /* Put it in the container disabling any previously active one. */
288         AST_LIST_LOCK(&after_bridge->callbacks);
289         last_node = AST_LIST_LAST(&after_bridge->callbacks);
290         if (last_node && !last_node->reason) {
291                 last_node->reason = AST_BRIDGE_AFTER_CB_REASON_REPLACED;
292         }
293         AST_LIST_INSERT_TAIL(&after_bridge->callbacks, new_node, list);
294         AST_LIST_UNLOCK(&after_bridge->callbacks);
295         return 0;
296 }
297
298 const char *reason_strings[] = {
299         [AST_BRIDGE_AFTER_CB_REASON_DESTROY] = "Channel destroyed (hungup)",
300         [AST_BRIDGE_AFTER_CB_REASON_REPLACED] = "Callback was replaced",
301         [AST_BRIDGE_AFTER_CB_REASON_MASQUERADE] = "Channel masqueraded",
302         [AST_BRIDGE_AFTER_CB_REASON_DEPART] = "Channel was departed from bridge",
303         [AST_BRIDGE_AFTER_CB_REASON_REMOVED] = "Callback was removed",
304 };
305
306 const char *ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
307 {
308         if (reason < AST_BRIDGE_AFTER_CB_REASON_DESTROY
309                 || AST_BRIDGE_AFTER_CB_REASON_REMOVED < reason
310                 || !reason_strings[reason]) {
311                 return "Unknown";
312         }
313
314         return reason_strings[reason];
315 }
316
317 struct after_bridge_goto_ds {
318         /*! Goto string that can be parsed by ast_parseable_goto(). */
319         const char *parseable_goto;
320         /*! Specific goto context or default context for parseable_goto. */
321         const char *context;
322         /*! Specific goto exten or default exten for parseable_goto. */
323         const char *exten;
324         /*! Specific goto priority or default priority for parseable_goto. */
325         int priority;
326         /*! TRUE if the peer should run the h exten. */
327         unsigned int run_h_exten:1;
328         /*! Specific goto location */
329         unsigned int specific:1;
330 };
331
332 /*!
333  * \internal
334  * \brief Destroy the after bridge goto datastore.
335  * \since 12.0.0
336  *
337  * \param data After bridge goto data to destroy.
338  *
339  * \return Nothing
340  */
341 static void after_bridge_goto_destroy(void *data)
342 {
343         struct after_bridge_goto_ds *after_bridge = data;
344
345         ast_free((char *) after_bridge->parseable_goto);
346         ast_free((char *) after_bridge->context);
347         ast_free((char *) after_bridge->exten);
348         ast_free((char *) after_bridge);
349 }
350
351 /*!
352  * \internal
353  * \brief Fixup the after bridge goto datastore.
354  * \since 12.0.0
355  *
356  * \param data After bridge goto data to fixup.
357  * \param old_chan The datastore is moving from this channel.
358  * \param new_chan The datastore is moving to this channel.
359  *
360  * \return Nothing
361  */
362 static void after_bridge_goto_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
363 {
364         /* There can be only one.  Discard any already on the new channel. */
365         ast_bridge_discard_after_goto(new_chan);
366 }
367
368 static const struct ast_datastore_info after_bridge_goto_info = {
369         .type = "after-bridge-goto",
370         .destroy = after_bridge_goto_destroy,
371         .chan_fixup = after_bridge_goto_fixup,
372 };
373
374 /*!
375  * \internal
376  * \brief Remove channel goto location after the bridge and return it.
377  * \since 12.0.0
378  *
379  * \param chan Channel to remove after bridge goto location.
380  *
381  * \retval datastore on success.
382  * \retval NULL on error or not found.
383  */
384 static struct ast_datastore *after_bridge_goto_remove(struct ast_channel *chan)
385 {
386         struct ast_datastore *datastore;
387
388         ast_channel_lock(chan);
389         datastore = ast_channel_datastore_find(chan, &after_bridge_goto_info, NULL);
390         if (datastore && ast_channel_datastore_remove(chan, datastore)) {
391                 datastore = NULL;
392         }
393         ast_channel_unlock(chan);
394
395         return datastore;
396 }
397
398 void ast_bridge_discard_after_goto(struct ast_channel *chan)
399 {
400         struct ast_datastore *datastore;
401
402         datastore = after_bridge_goto_remove(chan);
403         if (datastore) {
404                 ast_datastore_free(datastore);
405         }
406 }
407
408 void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
409 {
410         struct ast_datastore *datastore;
411         struct after_bridge_goto_ds *after_bridge;
412         char *current_pos = buffer;
413         size_t remaining_size = buf_size;
414
415         SCOPED_CHANNELLOCK(lock, chan);
416
417         datastore = ast_channel_datastore_find(chan, &after_bridge_goto_info, NULL);
418         if (!datastore) {
419                 buffer[0] = '\0';
420                 return;
421         }
422
423         after_bridge = datastore->data;
424
425         if (after_bridge->parseable_goto) {
426                 snprintf(buffer, buf_size, "%s", after_bridge->parseable_goto);
427                 return;
428         }
429
430         if (!ast_strlen_zero(after_bridge->context)) {
431                 snprintf(current_pos, remaining_size, "%s,", after_bridge->context);
432                 remaining_size = remaining_size - strlen(current_pos);
433                 current_pos += strlen(current_pos);
434         }
435
436         if (after_bridge->run_h_exten) {
437                 snprintf(current_pos, remaining_size, "h,");
438                 remaining_size = remaining_size - strlen(current_pos);
439                 current_pos += strlen(current_pos);
440         } else if (!ast_strlen_zero(after_bridge->exten)) {
441                 snprintf(current_pos, remaining_size, "%s,", after_bridge->exten);
442                 remaining_size = remaining_size - strlen(current_pos);
443                 current_pos += strlen(current_pos);
444         }
445
446         snprintf(current_pos, remaining_size, "%d", after_bridge->priority);
447 }
448
449 int ast_bridge_setup_after_goto(struct ast_channel *chan)
450 {
451         struct ast_datastore *datastore;
452         struct after_bridge_goto_ds *after_bridge;
453         int goto_failed = -1;
454
455         /* We are going to be leaving the bridging system now;
456          * clear any pending unbridge flags
457          */
458         ast_channel_set_unbridged(chan, 0);
459
460         /* Determine if we are going to setup a dialplan location and where. */
461         if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
462                 /* An async goto has already setup a location. */
463                 ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ASYNCGOTO);
464                 if (!ast_check_hangup(chan)) {
465                         goto_failed = 0;
466                 }
467                 return goto_failed;
468         }
469
470         /* Get after bridge goto datastore. */
471         datastore = after_bridge_goto_remove(chan);
472         if (!datastore) {
473                 return goto_failed;
474         }
475
476         after_bridge = datastore->data;
477         if (after_bridge->run_h_exten) {
478                 if (ast_exists_extension(chan, after_bridge->context, "h", 1,
479                         S_COR(ast_channel_caller(chan)->id.number.valid,
480                                 ast_channel_caller(chan)->id.number.str, NULL))) {
481                         ast_debug(1, "Running after bridge goto h exten %s,h,1\n",
482                                 ast_channel_context(chan));
483                         ast_pbx_h_exten_run(chan, after_bridge->context);
484                 }
485         } else if (!ast_check_hangup(chan)) {
486                 /* Clear the outgoing flag */
487                 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
488
489                 if (after_bridge->specific) {
490                         goto_failed = ast_explicit_goto(chan, after_bridge->context,
491                                 after_bridge->exten, after_bridge->priority);
492                 } else if (!ast_strlen_zero(after_bridge->parseable_goto)) {
493                         char *context;
494                         char *exten;
495                         int priority;
496
497                         /* Option F(x) for Bridge(), Dial(), and Queue() */
498
499                         /* Save current dialplan location in case of failure. */
500                         context = ast_strdupa(ast_channel_context(chan));
501                         exten = ast_strdupa(ast_channel_exten(chan));
502                         priority = ast_channel_priority(chan);
503
504                         /* Set current dialplan position to default dialplan position */
505                         ast_explicit_goto(chan, after_bridge->context, after_bridge->exten,
506                                 after_bridge->priority);
507
508                         /* Then perform the goto */
509                         goto_failed = ast_parseable_goto(chan, after_bridge->parseable_goto);
510                         if (goto_failed) {
511                                 /* Restore original dialplan location. */
512                                 ast_channel_context_set(chan, context);
513                                 ast_channel_exten_set(chan, exten);
514                                 ast_channel_priority_set(chan, priority);
515                         }
516                 } else {
517                         /* Option F() for Bridge(), Dial(), and Queue() */
518                         goto_failed = ast_goto_if_exists(chan, after_bridge->context,
519                                 after_bridge->exten, after_bridge->priority + 1);
520                 }
521                 if (!goto_failed) {
522                         if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
523                                 ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
524                         }
525
526                         ast_debug(1, "Setup after bridge goto location to %s,%s,%d.\n",
527                                 ast_channel_context(chan),
528                                 ast_channel_exten(chan),
529                                 ast_channel_priority(chan));
530                 }
531         }
532
533         /* Discard after bridge goto datastore. */
534         ast_datastore_free(datastore);
535
536         return goto_failed;
537 }
538
539 void ast_bridge_run_after_goto(struct ast_channel *chan)
540 {
541         int goto_failed;
542
543         goto_failed = ast_bridge_setup_after_goto(chan);
544         if (goto_failed || ast_pbx_run(chan)) {
545                 ast_hangup(chan);
546         }
547 }
548
549 /*!
550  * \internal
551  * \brief Set after bridge goto location of channel.
552  * \since 12.0.0
553  *
554  * \param chan Channel to setup after bridge goto location.
555  * \param run_h_exten TRUE if the h exten should be run.
556  * \param specific TRUE if the context/exten/priority is exactly specified.
557  * \param context Context to goto after bridge.
558  * \param exten Exten to goto after bridge. (Could be NULL if run_h_exten)
559  * \param priority Priority to goto after bridge.
560  * \param parseable_goto User specified goto string. (Could be NULL)
561  *
562  * \details Add a channel datastore to setup the goto location
563  * when the channel leaves the bridge and run a PBX from there.
564  *
565  * If run_h_exten then execute the h exten found in the given context.
566  * Else if specific then goto the given context/exten/priority.
567  * Else if parseable_goto then use the given context/exten/priority
568  *   as the relative position for the parseable_goto.
569  * Else goto the given context/exten/priority+1.
570  *
571  * \return Nothing
572  */
573 static void __after_bridge_set_goto(struct ast_channel *chan, int run_h_exten, int specific, const char *context, const char *exten, int priority, const char *parseable_goto)
574 {
575         struct ast_datastore *datastore;
576         struct after_bridge_goto_ds *after_bridge;
577
578         /* Sanity checks. */
579         ast_assert(chan != NULL);
580         if (!chan) {
581                 return;
582         }
583         if (run_h_exten) {
584                 ast_assert(run_h_exten && context);
585                 if (!context) {
586                         return;
587                 }
588         } else {
589                 ast_assert(context && exten && 0 < priority);
590                 if (!context || !exten || priority < 1) {
591                         return;
592                 }
593         }
594
595         /* Create a new datastore. */
596         datastore = ast_datastore_alloc(&after_bridge_goto_info, NULL);
597         if (!datastore) {
598                 return;
599         }
600         after_bridge = ast_calloc(1, sizeof(*after_bridge));
601         if (!after_bridge) {
602                 ast_datastore_free(datastore);
603                 return;
604         }
605
606         /* Initialize it. */
607         after_bridge->parseable_goto = ast_strdup(parseable_goto);
608         after_bridge->context = ast_strdup(context);
609         after_bridge->exten = ast_strdup(exten);
610         after_bridge->priority = priority;
611         after_bridge->run_h_exten = run_h_exten ? 1 : 0;
612         after_bridge->specific = specific ? 1 : 0;
613         datastore->data = after_bridge;
614         if ((parseable_goto && !after_bridge->parseable_goto)
615                 || (context && !after_bridge->context)
616                 || (exten && !after_bridge->exten)) {
617                 ast_datastore_free(datastore);
618                 return;
619         }
620
621         /* Put it on the channel replacing any existing one. */
622         ast_channel_lock(chan);
623         ast_bridge_discard_after_goto(chan);
624         ast_channel_datastore_add(chan, datastore);
625         ast_channel_unlock(chan);
626 }
627
628 void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
629 {
630         __after_bridge_set_goto(chan, 0, 1, context, exten, priority, NULL);
631 }
632
633 void ast_bridge_set_after_h(struct ast_channel *chan, const char *context)
634 {
635         __after_bridge_set_goto(chan, 1, 0, context, NULL, 1, NULL);
636 }
637
638 void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
639 {
640         char *p_goto;
641
642         if (!ast_strlen_zero(parseable_goto)) {
643                 p_goto = ast_strdupa(parseable_goto);
644                 ast_replace_subargument_delimiter(p_goto);
645         } else {
646                 p_goto = NULL;
647         }
648         __after_bridge_set_goto(chan, 0, 0, context, exten, priority, p_goto);
649 }