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