Asterisk - The Open Source Telephony Project  GIT-master-1b41629
bridge_after.c
Go to the documentation of this file.
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 
41  /*! Next list node. */
43  /*! Desired callback function. */
45  /*! After bridge callback will not be called and destroy any resources data may contain. */
47  /*! Extra data to pass to the callback. */
48  void *data;
49  /*! Reason the after bridge callback failed. */
51 };
52 
54  /*! After bridge callbacks container. */
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  */
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  */
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  }
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 
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) {
150  }
151  AST_LIST_UNLOCK(&after_bridge->callbacks);
152 }
153 
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  */
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  */
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 
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) {
239  } else {
240  node->failed = NULL;
241  node->callback(chan, node->data);
242  }
243  ast_free(node);
244  }
245 }
246 
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 
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) {
290  }
291  AST_LIST_INSERT_TAIL(&after_bridge->callbacks, new_node, list);
292  AST_LIST_UNLOCK(&after_bridge->callbacks);
293  return 0;
294 }
295 
297 {
298  switch (reason) {
300  return "Channel destroyed (hungup)";
302  return "Callback was replaced";
304  return "Channel masqueraded";
306  return "Channel was departed from bridge";
308  return "Callback was removed";
310  return "Channel failed joining the bridge";
311  }
312  return "Unknown";
313 }
314 
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. */
364 }
365 
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  */
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 
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 
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. */
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 */
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) {
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 
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);
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);
643  } else {
644  p_goto = NULL;
645  }
646  __after_bridge_set_goto(chan, 0, 0, context, exten, priority, p_goto);
647 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * type
Definition: datastore.h:32
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition: pbx.c:4209
#define ast_channel_lock(chan)
Definition: channel.h:2902
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
Definition: test_heap.c:38
void ast_bridge_run_after_callback(struct ast_channel *chan)
Run any after bridge callback.
Definition: bridge_after.c:220
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define ast_test_flag(p, flag)
Definition: utils.h:63
const char * parseable_goto
Definition: bridge_after.c:317
static void after_bridge_cb_run_discard(struct after_bridge_cb_ds *after_bridge, enum ast_bridge_after_cb_reason reason)
Definition: bridge_after.c:85
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
ast_bridge_after_cb callback
Definition: bridge_after.c:44
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
Definition: bridge_after.c:447
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Definition: channel.c:11128
static const struct ast_datastore_info after_bridge_goto_info
Definition: bridge_after.c:366
void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
Read after bridge goto if it exists.
Definition: bridge_after.c:406
Structure for a data store type.
Definition: datastore.h:31
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6987
#define ast_assert(a)
Definition: utils.h:710
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2390
#define NULL
Definition: resample.c:96
enum ast_bridge_after_cb_reason reason
Definition: bridge_after.c:50
static void after_bridge_cb_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: bridge_after.c:136
void ast_bridge_run_after_goto(struct ast_channel *chan)
Run a PBX on any after bridge goto location.
Definition: bridge_after.c:537
static int priority
int ast_channel_priority(const struct ast_channel *chan)
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:259
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
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)
Definition: bridge_after.c:571
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:652
ast_bridge_after_cb_reason
Definition: bridge_after.h:37
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
void ast_replace_subargument_delimiter(char *s)
Replace &#39;^&#39; in a string with &#39;,&#39;.
Definition: main/utils.c:2095
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
General Asterisk PBX channel definitions.
const char * ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
Get a string representation of an after bridge callback reason.
Definition: bridge_after.c:296
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2423
ast_mutex_t lock
Definition: app_meetme.c:1091
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8859
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct ast_datastore * after_bridge_goto_remove(struct ast_channel *chan)
Definition: bridge_after.c:382
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
Definition: bridge_after.c:396
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
const char * ast_channel_exten(const struct ast_channel *chan)
Core PBX routines and definitions.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:441
ast_bridge_after_cb_failed failed
Definition: bridge_after.c:46
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
unsigned int specific
Definition: bridge_after.c:327
static struct after_bridge_cb_ds * after_bridge_cb_setup(struct ast_channel *chan)
Definition: bridge_after.c:192
struct after_bridge_cb_ds::@345 callbacks
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
Definition: bridge_after.c:636
static struct after_bridge_cb_ds * after_bridge_cb_find(struct ast_channel *chan)
Definition: bridge_after.c:170
const char * context
Definition: bridge_after.c:319
const char * exten
Definition: bridge_after.c:321
static const struct ast_datastore_info after_bridge_cb_info
Definition: bridge_after.c:154
void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set channel to goto specific location after the bridge.
Definition: bridge_after.c:626
static void after_bridge_goto_destroy(void *data)
Definition: bridge_after.c:339
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8793
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2903
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2534
static void after_bridge_goto_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition: bridge_after.c:360
Support for logging to various files, console and syslog Configuration in file logger.conf.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
void * data
Definition: datastore.h:70
After Bridge Execution API.
void ast_channel_context_set(struct ast_channel *chan, const char *value)
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4759
static void after_bridge_cb_destroy(void *data)
Definition: bridge_after.c:113
void ast_bridge_discard_after_callback(struct ast_channel *chan, enum ast_bridge_after_cb_reason reason)
Run discarding any after bridge callbacks.
Definition: bridge_after.c:247
const char * ast_channel_context(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
void(* ast_bridge_after_cb)(struct ast_channel *chan, void *data)
After bridge callback function.
Definition: bridge_after.h:211
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
static void after_bridge_cb_failed(struct after_bridge_cb_node *node)
Definition: bridge_after.c:67
void ast_channel_priority_set(struct ast_channel *chan, int value)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2376
unsigned int run_h_exten
Definition: bridge_after.c:325
struct after_bridge_cb_node::@344 list
void(* ast_bridge_after_cb_failed)(enum ast_bridge_after_cb_reason reason, void *data)
After bridge callback failed.
Definition: bridge_after.h:200
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2385
void ast_channel_set_unbridged(struct ast_channel *chan, int value)
Sets the unbridged flag and queues a NULL frame on the channel to trigger a check by bridge_channel_w...
void ast_bridge_set_after_h(struct ast_channel *chan, const char *context)
Set channel to run the h exten after the bridge.
Definition: bridge_after.c:631